Project import generated by Copybara.

GitOrigin-RevId: c415cd6adaf576dac916f3adff080fcd4ac23400
diff --git a/bt_sd8897/Makefile b/bt_sd8897/Makefile
new file mode 100644
index 0000000..444c953
--- /dev/null
+++ b/bt_sd8897/Makefile
@@ -0,0 +1,169 @@
+# File: Makefile
+# Copyright (C) 2007-2018, Marvell International Ltd.
+#
+
+CC=		$(CROSS_COMPILE)gcc
+LD=		$(CROSS_COMPILE)ld
+
+BACKUP=		/root/backup
+YMD=		`date +%Y%m%d%H%M`
+
+#############################################################################
+# Configuration Options
+#############################################################################
+
+# Debug Option
+# DEBUG LEVEL n/1/2:
+# n: NO DEBUG
+# 1: PRINTM(MSG,...), PRINTM(FATAL,...), PRINTM(WARN,...) and PRINTM(INFO,...)
+# 2: All PRINTM()
+CONFIG_DEBUG=1
+
+
+# SDIO suspend/resume
+CONFIG_SDIO_SUSPEND_RESUME=y
+
+
+CONFIG_BLE_WAKEUP=y
+
+#############################################################################
+# Select Platform Tools
+#############################################################################
+
+MODEXT = ko
+
+ifeq ($(CONFIG_64BIT), y)
+	EXTRA_CFLAGS += -DMBT_64BIT
+endif
+
+ifeq ($(CONFIG_T50), y)
+        EXTRA_CFLAGS += -DT50
+        EXTRA_CFLAGS += -DT40
+        EXTRA_CFLAGS += -DT3T
+endif
+
+ifeq ($(CONFIG_BLE_WAKEUP), y)
+        EXTRA_CFLAGS += -DBLE_WAKEUP
+endif
+
+
+
+
+
+
+ARCH ?= arm
+KERNELDIR ?= /usr/src/arm/linux-4.9.70-bg4ct
+CROSS_COMPILE ?= /usr/local/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
+
+EXTRA_CFLAGS += -I$(KERNELDIR)/include
+
+EXTRA_CFLAGS += -I$(M)/../mbtchar_src
+EXTRA_CFLAGS += -I$(M)/bt
+LD += -S
+
+#ifdef SD8xxx
+BINDIR = ../bin_sd8xxx_btchar
+#endif
+
+
+#############################################################################
+# Compiler Flags
+#############################################################################
+	EXTRA_CFLAGS += -DFPNUM='"28"'
+
+ifeq ($(CONFIG_DEBUG),1)
+	EXTRA_CFLAGS += -DDEBUG_LEVEL1
+endif
+
+ifeq ($(CONFIG_DEBUG),2)
+	EXTRA_CFLAGS += -DDEBUG_LEVEL1
+	EXTRA_CFLAGS += -DDEBUG_LEVEL2
+	DBG=	-dbg
+endif
+
+ifeq ($(CONFIG_SDIO_SUSPEND_RESUME),y)
+	EXTRA_CFLAGS += -DSDIO_SUSPEND_RESUME
+endif
+
+#############################################################################
+# Make Targets
+#############################################################################
+
+ifneq ($(KERNELRELEASE),)
+
+BTOBJS = bt/bt_main.o bt/bt_sdiommc.o bt/bt_proc.o bt/mbt_char.o
+
+BTOBJS += bt/bt_init.o
+
+obj-m := mbt8897.o
+mbt8897-objs := $(BTOBJS)
+
+
+
+# Otherwise we were called directly from the command line; invoke the kernel build system.
+else
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) modules
+endif
+
+###############################################################
+
+export		CC LD EXTRA_CFLAGS KERNELDIR
+
+.PHONY: app/fm_app clean distclean
+
+app/fm_app:
+	$(MAKE) -C  $@
+
+echo:
+
+build:		echo default
+
+	@if [ ! -d $(BINDIR) ]; then \
+		mkdir $(BINDIR); \
+	fi
+
+	cp -f mbt8xxx.$(MODEXT) $(BINDIR)/mbt8xxx$(DBG).$(MODEXT)
+	cp -r config $(BINDIR)
+
+
+
+
+
+	cp -f README $(BINDIR)
+
+	$(MAKE) -C app/fm_app $@ INSTALLDIR=$(BINDIR);
+	cp -f app/fm_app/fmapp $(BINDIR);
+
+clean:
+	-find . -name "*.o" -exec rm {} \;
+	-find . -name "*.ko" -exec rm {} \;
+	-find . -name ".*.cmd" -exec rm {} \;
+	-find . -name "*.mod.c" -exec rm {} \;
+	-find . -name "*.symvers" -exec rm {} \;
+	-find . -name "modules.order" -exec rm {} \;
+	-find . -name ".*.dwo" -exec rm {} \;
+	-find . -name "*dwo" -exec rm {} \;
+	-rm -rf .tmp_versions
+	$(MAKE) -C app/fm_app $@
+
+install: default
+
+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
+	$(MAKE) -C app/fm_app $@
+# End of file;
diff --git a/bt_sd8897/README b/bt_sd8897/README
new file mode 100644
index 0000000..ed48a72
--- /dev/null
+++ b/bt_sd8897/README
@@ -0,0 +1,224 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2003-2016, Marvell International Ltd.
+
+ This software file (the "File") is distributed by Marvell International
+ Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ (the "License").  You may use, redistribute and/or modify this File in
+ accordance with the terms and conditions of the License, a copy of which
+ is available along with the File in the gpl.txt file or by writing to
+ the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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.
+
+===============================================================================
+
+1) FOR DRIVER BUILD
+
+	Goto source code directory mbtc_src/.
+		make [clean] build
+	The driver binary can be found in ../bin_xxxx_btchar directory.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy sd8787.bin | ... to /lib/firmware/mrvl/ directory,
+	   create the directory if it doesn't exist.
+	b) Install bluetooth driver,
+		insmod bt8787.ko | mbt8787.ko | ... [fw_name=mrvl/sd8xxx.bin]
+	c) Uninstall bluetooth driver,
+		rmmod bt8xxx | mbt8xxx
+
+	There are some other parameters for debugging purpose etc. Use modinfo to check details.
+	  The bit settings of drv_mode are,
+		Bit 0: BT/AMP/BLE
+		Bit 1: FM
+		Bit 2: NFC
+	  mbt_drvdbg=<bit mask of driver debug message control>
+	  psmode=1|0 <enable PS mode (default) | disable PS mode>
+	  dts_enable=1|0 <Disable DTS | Enable DTS (default)>
+	  bt_name=<BT interface name>
+	  fm_name=<FM interface name>
+	  nfc_name=<NFC interface name>
+	  debug_intf=1|0 <Enable debug interface (default) | Disable debug interface>
+	  debug_name=<Debug interface name>
+	  mbt_pm_keep_power=1|0 <PM keep power in suspend (default) | PM no power in suspend>
+	  fw=0|other <Skip firmware download | Download firmware (default)>
+	  bt_req_fw_nowait=0|1 <use request_firmware API (default) | use request_firmware_nowait API>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy bt_init_cfg.conf to firmware directory, init_cfg=mrvl/bt_init_cfg.conf
+      bt_mac=xx:xx:xx:xx:xx:xx <override the MAC address (in hex)>
+      cal_cfg=<BT CAL data config file name>
+		e.g. copy bt_cal_data.conf to firmware directory, cal_cfg=mrvl/bt_cal_data.conf
+      cal_cfg_ext=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_cfg_ext=mrvl/cal_data.conf
+	  mbt_gpio_pin=<GPIO pin to interrupt host. 0xFFFF: disable GPIO interrupt mode; Others: GPIO pin assigned to generate pulse to host.>
+
+	btindrst = Independent reset configuration; high byte:GPIOpin;low byte:MODE
+
+	<MODE> :
+		0x00 : disable independent reset
+		0x01 : enable out-band gpio independent reset.
+		0x02 : enable in-band independent reset
+	<GPIOpin> :
+		0xFF : default GPIO pins will be used. Currently for BT it is GPIO[15].
+		0xXX : specified GPIO pin number will be used for out-band reset.
+
+	Example:
+		btindrst=0x0e01        : outband-reset, gpio pin 14
+		btindrst=0xff01        : outband-reset, use firmware default GPIO pin
+
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod mbt8xxx.ko "<para1> <para2> ..."
+
+3) cat /proc/mbt/mbtcharx/status
+	This command is used to get driver status.
+
+4) cat /proc/mbt/mbtcharx/config
+	This command is used to get the current driver settings.
+
+5) proc commands to config bluetooth parameters
+
+mbt_drvdbg=[n]
+	This command is used to set the bit mask of driver debug message control.
+
+	bit 0:  MSG  		PRINTM(MSG,...)
+	bit 1:  FATAL		PRINTM(FATAL,...)
+	bit 2:  ERROR		PRINTM(ERROR,...)
+	bit 3:  DATA 		PRINTM(DATA,...)
+	bit 4:  CMD  		PRINTM(CMD,...)
+	bit 5:  EVENT		PRINTM(EVENT,...)
+	bit 6:  INTR		PRINTM(INTR,...)
+	...
+	bit 16: DAT_D		PRINTM(DAT_D,...), DBG_HEXDUMP(DAT_D,...)
+	bit 17: CMD_D		PRINTM(CMD_D,...), DBG_HEXDUMP(CMD_D,...)
+	...
+	bit 28: ENTRY		PRINTM(ENTRY,...), ENTER(), LEAVE()
+	bit 29: WARN 		PRINTM(WARN,...)
+	bit 30: INFO 		PRINTM(INFO,...)
+
+	Usage:
+		echo "drvdbg=0x7" > /proc/mbt/mbtcharx/config		#enable MSG,FATAL,ERROR messages
+
+gpio_gap=[n]
+	This command is used to configure the host sleep parameters.
+
+	bit 8:0  -- Gap
+	bit 16:8 -- GPIO
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+		GPIO pin# (e.g. 0-7) or 0xff (Interface, e.g. SDIO will be used instead).
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event
+		or 0xff for special setting when GPIO is used to wakeup host.
+
+	Usage:
+		echo "gpio_gap=0xff80" > /proc/mbt/mbtcharx/config   	# use Interface (e.g. SDIO)
+		echo "hscfgcmd=1" > /proc/mbt/mbtcharx/config		# gap = 0x80
+
+		echo "gpio_gap=0x03ff" > /proc/mbt/mbtcharx/config   	# use gpio 3
+		echo "hscfgcmd=1" > /proc/mbt/mbtcharx/config		# and special host sleep mode
+
+psmode=[n]
+	This command is used to enable/disable auto sleep mode
+
+	where the option is:
+			1 	-- Enable auto sleep mode
+			0 	-- Disable auto sleep mode
+
+	Usage:
+		echo "psmode=1" > /proc/mbt/mbtcharx/config			#enable power save mode
+		echo "idle_timeout=0x0100" > /proc/mbt/mbtcharx/config		#configure idle, timeout value in ms
+		echo "pscmd=1" > /proc/mbt/mbtcharx/config
+
+		echo "psmode=0" > /proc/mbt/mbtcharx/config			#disable power save mode
+		echo "pscmd=1" > /proc/mbt/mbtcharx/config
+
+sdio_pull_cfg=[n]
+	This command is used to configure the delay values for pull up and pull down the SDIO lines.
+
+   	where value is:
+	        bit 15:0  -- Pull up delay in microsecond
+	        bit 31:16 -- Pull down delay in microsecond
+	        0xffff disables PullUp and PullDown in BT controller
+
+	Usage:
+		echo "sdio_pull_cfg=0x00020002" > /proc/mbt/mbtcharx/config   	# Enable sdio pull control
+		echo "sdio_pull_ctrl=1" > /proc/mbt/mbtcharx/config             # configure sdio pull up delay to 2 microseconds
+                                                                        # configure sdio pull down delay to 2 microseconds
+
+		echo "sdio_pull_cfg=0xffffffff" > /proc/mbt/mbtcharx/config   	# Disable sdio pull control
+		echo "sdio_pull_ctrl=1" > /proc/mbt/mbtcharx/config
+
+6) cat /proc/mbt/mbtcharx/debug
+	This command is used to get driver debug parameters.
+
+7) proc command to config debug parameters
+
+sdcmd52rw=<func> <reg> [data]
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	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 BT function (2/3) access is allowed.
+	And there is a limitation for function 0 write, only vendor specific CCCR
+	registers (0xf0 -0xff) are permiited.
+
+	Usage:
+		echo "sdcmd52rw= 2 3 0xf" > /proc/mbt/mbtcharx/debug	# write 0xf to func 2 address 3
+		echo "sdcmd52rw= 0 4" > /proc/mbt/mbtcharx/debug    	# read func 0 address 4
+
+Issue debug_dump command through proc.
+	Usage:
+		echo "debug_dump" > /proc/mbt/mbtcharx/debug		# dump driver internal debug status.
+	Use dmesg or cat /var/log/debug to check driver debug messages.
+
+proc command to enable BT test mode
+    Usage:
+        echo "test_mode=1" > /proc/mbt/mbtcharx/config   #enable BT test mode
+
+FOR FW RELOAD
+    a) Enable parallel firmware download in driver parameter
+       insmod bt8xxx.ko fw_serail=0
+
+    b) default fw name for parallel firmware download
+       sd8887_bt_a2.bin
+
+    c) Trigger FW reload
+	echo "fw_reload=1" > /proc/mbt/hcix/debug    		    # start inband reset and fw reload.
+	echo "fw_reload=2" > proc/mbt/hcix/debug       		    # start fw reload
+
+    (Note: This feature should works on SD8977/SD8997 board,
+           For CAC-A2 board, only works on the board which supports parallel fw download)
+
+
+==============================================================================
+			U S E R  M A N U A L  F O R  F M A P P
+
+1) FOR TOOL BUILD
+
+	a) Enter directory
+	b) make
+	c) After building, the executable binary "fmapp" is in the directory
+
+2) FOR TOOL RUN
+
+	a) chmod 777 fmapp (optional)
+	b) Run fmapp utility based on usage below
+		Usage: fmapp <Options> devicename ogf ocf [command content]
+		devicename example: mfmchar0 /mnfccahr0
+		FM ogf/ocf example: 0x3f 0x280
+		NFC ogf/ocf example: 0x3f 0x281
+	Options:
+		-h: Display help
+		-v: Verbose
+
+3) TEST EXAMPLES
+    ./fmapp mfmchar0 0x3f 0x280 0x01 0x01
+    ./fmapp mnfcchar0 0x3f 0x281 0x20 0x00 0x01 0x01
diff --git a/bt_sd8897/bt/bt_drv.h b/bt_sd8897/bt/bt_drv.h
new file mode 100644
index 0000000..69b801f
--- /dev/null
+++ b/bt_sd8897/bt/bt_drv.h
@@ -0,0 +1,901 @@
+/** @file bt_drv.h
+ *  @brief This header file contains global constant/enum definitions,
+ *  global variable declaration.
+ *
+ *  Copyright (C) 2007-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_DRV_H_
+#define _BT_DRV_H_
+
+#include <linux/version.h>
+#include <linux/kthread.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+
+#include "hci_wrapper.h"
+
+/** MAX adapter BT driver supported */
+#define MAX_BT_ADAPTER    3
+
+#ifndef BIT
+/** BIT definition */
+#define BIT(x) (1UL << (x))
+#endif
+
+#ifdef MBT_64BIT
+typedef u64 t_ptr;
+#else
+typedef u32 t_ptr;
+#endif
+
+/** max number of adapter supported */
+#define MAX_BT_ADAPTER      3
+/** Define drv_mode bit */
+#define DRV_MODE_BT         BIT(0)
+#define DRV_MODE_NFC       BIT(2)
+
+/** Define devFeature bit */
+#define DEV_FEATURE_BT     BIT(0)
+#define DEV_FEATURE_BTAMP     BIT(1)
+#define DEV_FEATURE_BLE     BIT(2)
+#define DEV_FEATURE_NFC     BIT(4)
+
+/** Define maximum number of radio func supported */
+#define MAX_RADIO_FUNC     4
+
+/** MAC address print format */
+#ifndef MACSTR
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+
+/** MAC address print arguments */
+#ifndef MAC2STR
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#endif
+
+/** Debug level : Message */
+#define	DBG_MSG			BIT(0)
+/** Debug level : Fatal */
+#define DBG_FATAL		BIT(1)
+/** Debug level : Error */
+#define DBG_ERROR		BIT(2)
+/** Debug level : Data */
+#define DBG_DATA		BIT(3)
+/** Debug level : Command */
+#define DBG_CMD			BIT(4)
+/** Debug level : Event */
+#define DBG_EVENT		BIT(5)
+/** Debug level : Interrupt */
+#define DBG_INTR		BIT(6)
+
+/** Debug entry : Data dump */
+#define DBG_DAT_D		BIT(16)
+/** Debug entry : Data dump */
+#define DBG_CMD_D		BIT(17)
+
+/** Debug level : Entry */
+#define DBG_ENTRY		BIT(28)
+/** Debug level : Warning */
+#define DBG_WARN		BIT(29)
+/** Debug level : Informative */
+#define DBG_INFO		BIT(30)
+
+#ifdef	DEBUG_LEVEL1
+extern u32 mbt_drvdbg;
+
+#ifdef	DEBUG_LEVEL2
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  \
+	do {if (mbt_drvdbg & DBG_INFO)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...) \
+	do {if (mbt_drvdbg & DBG_WARN)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) \
+	do {if (mbt_drvdbg & DBG_ENTRY) \
+		printk(KERN_DEBUG msg); } while (0)
+#else
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  do {} while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...)  do {} while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) do {} while (0)
+#endif /* DEBUG_LEVEL2 */
+
+/** Print interrupt message */
+#define	PRINTM_INTR(msg...)  \
+	do {if (mbt_drvdbg & DBG_INTR)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print event message */
+#define	PRINTM_EVENT(msg...) \
+	do {if (mbt_drvdbg & DBG_EVENT) \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print command message */
+#define	PRINTM_CMD(msg...)   \
+	do {if (mbt_drvdbg & DBG_CMD)   \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data message */
+#define	PRINTM_DATA(msg...)  \
+	do {if (mbt_drvdbg & DBG_DATA)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print error message */
+#define	PRINTM_ERROR(msg...) \
+	do {if (mbt_drvdbg & DBG_ERROR) \
+		printk(KERN_ERR msg); } while (0)
+/** Print fatal message */
+#define	PRINTM_FATAL(msg...) \
+	do {if (mbt_drvdbg & DBG_FATAL) \
+		printk(KERN_ERR msg); } while (0)
+/** Print message */
+#define	PRINTM_MSG(msg...)   \
+	do {if (mbt_drvdbg & DBG_MSG)   \
+		printk(KERN_ALERT msg); } while (0)
+
+/** Print data dump message */
+#define	PRINTM_DAT_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_DAT_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data dump message */
+#define	PRINTM_CMD_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_CMD_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+
+/** Print message with required level */
+#define	PRINTM(level, msg...) PRINTM_##level(msg)
+
+/** Debug dump buffer length */
+#define DBG_DUMP_BUF_LEN	64
+/** Maximum number of dump per line */
+#define MAX_DUMP_PER_LINE	16
+/** Maximum data dump length */
+#define MAX_DATA_DUMP_LEN	48
+
+/**
+ * @brief Prints buffer data upto provided length
+ *
+ * @param prompt          Char pointer
+ * @param buf			  Buffer
+ * @param len    		  Length
+ *
+ * @return                N/A
+ */
+static inline void
+hexdump(char *prompt, u8 *buf, int len)
+{
+	int i;
+	char dbgdumpbuf[DBG_DUMP_BUF_LEN];
+	char *ptr = dbgdumpbuf;
+
+	printk(KERN_DEBUG "%s: len=%d\n", prompt, len);
+	for (i = 1; i <= len; i++) {
+		ptr += snprintf(ptr, 4, "%02x ", *buf);
+		buf++;
+		if (i % MAX_DUMP_PER_LINE == 0) {
+			*ptr = 0;
+			printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+			ptr = dbgdumpbuf;
+		}
+	}
+	if (len % MAX_DUMP_PER_LINE) {
+		*ptr = 0;
+		printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+	}
+}
+
+/** Debug hexdump of debug data */
+#define DBG_HEXDUMP_DAT_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_DAT_D) \
+		hexdump(x, y, z); } while (0)
+/** Debug hexdump of debug command */
+#define DBG_HEXDUMP_CMD_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_CMD_D) \
+		hexdump(x, y, z); } while (0)
+
+/** Debug hexdump */
+#define	DBG_HEXDUMP(level, x, y, z)    DBG_HEXDUMP_##level(x, y, z)
+
+/** Mark entry point */
+#define	ENTER()			PRINTM(ENTRY, "Enter: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+/** Mark exit point */
+#define	LEAVE()			PRINTM(ENTRY, "Leave: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+#else
+/** Do nothing */
+#define	PRINTM(level, msg...) do {} while (0)
+/** Do nothing */
+#define DBG_HEXDUMP(level, x, y, z)    do {} while (0)
+/** Do nothing */
+#define	ENTER()  do {} while (0)
+/** Do nothing */
+#define	LEAVE()  do {} while (0)
+#endif /* DEBUG_LEVEL1 */
+
+/** Bluetooth upload size */
+#define	BT_UPLD_SIZE				2312
+/** Bluetooth status success */
+#define BT_STATUS_SUCCESS			(0)
+/** Bluetooth status pending */
+#define BT_STATUS_PENDING           (1)
+/** Bluetooth status failure */
+#define BT_STATUS_FAILURE			(-1)
+
+#ifndef	TRUE
+/** True value */
+#define TRUE			1
+#endif
+#ifndef	FALSE
+/** False value */
+#define	FALSE			0
+#endif
+
+/** Set thread state */
+#define OS_SET_THREAD_STATE(x)		set_current_state(x)
+/** Time to wait until Host Sleep state change in millisecond */
+#define WAIT_UNTIL_HS_STATE_CHANGED 2000
+/** Time to wait cmd resp in millisecond */
+#define WAIT_UNTIL_CMD_RESP	    5000
+
+/** Sleep until a condition gets true or a timeout elapses */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	interruptible_sleep_on_timeout(&waitq, ((timeout) * HZ / 1000))
+#else
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
+#endif
+
+/** bt thread structure */
+typedef struct {
+	/** Task */
+	struct task_struct *task;
+	/** Queue */
+	wait_queue_head_t waitQ;
+	/** PID */
+	pid_t pid;
+	/** Private structure */
+	void *priv;
+} bt_thread;
+
+/**
+ * @brief Activates bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline void
+bt_activate_thread(bt_thread *thr)
+{
+	/** Initialize the wait queue */
+	init_waitqueue_head(&thr->waitQ);
+
+	/** Record the thread pid */
+	thr->pid = current->pid;
+}
+
+/**
+ * @brief De-activates bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline void
+bt_deactivate_thread(bt_thread *thr)
+{
+	thr->pid = 0;
+	return;
+}
+
+/**
+ * @brief Creates bt thread
+ *
+ * @param btfunc          Function pointer
+ * @param thr			  A pointer to bt_thread structure
+ * @param name    		  Char pointer
+ *
+ * @return                N/A
+ */
+static inline void
+bt_create_thread(int (*btfunc) (void *), bt_thread *thr, char *name)
+{
+	thr->task = kthread_run(btfunc, thr, "%s", name);
+}
+
+/**
+ * @brief Delete bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline int
+bt_terminate_thread(bt_thread *thr)
+{
+	/* Check if the thread is active or not */
+	if (!thr->pid)
+		return -1;
+
+	kthread_stop(thr->task);
+	return 0;
+}
+
+/**
+ * @brief  Set scheduled timeout
+ *
+ * @param millisec		 Time unit in ms
+ *
+ * @return                N/A
+ */
+static inline void
+os_sched_timeout(u32 millisec)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	schedule_timeout((millisec * HZ) / 1000);
+}
+
+#ifndef __ATTRIB_ALIGN__
+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
+#endif
+
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__ __attribute__((packed))
+#endif
+
+/** Data structure for the Marvell Bluetooth device */
+typedef struct _bt_dev {
+	/** device name */
+	char name[DEV_NAME_LEN];
+	/** card pointer */
+	void *card;
+	/** IO port */
+	u32 ioport;
+	/** m_dev structure */
+	struct m_dev m_dev[MAX_RADIO_FUNC];
+
+	/** Tx download ready flag */
+	u8 tx_dnld_rdy;
+	/** Function */
+	u8 fn;
+	/** Rx unit */
+	u8 rx_unit;
+	/** Power Save mode : Timeout configuration */
+	u16 idle_timeout;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save command */
+	u8 pscmd;
+	/** Host Sleep mode */
+	u8 hsmode;
+	/** Host Sleep command */
+	u8 hscmd;
+	/** Low byte is gap, high byte is GPIO */
+	u16 gpio_gap;
+	/** Host Sleep configuration command */
+	u8 hscfgcmd;
+	/** Host Send Cmd Flag		 */
+	u8 sendcmdflag;
+	/** opcode for Send Cmd */
+	u16 send_cmd_opcode;
+	/** Device Type			*/
+	u8 devType;
+	/** Device Features    */
+	u8 devFeature;
+	/** cmd52 function */
+	u8 cmd52_func;
+	/** cmd52 register */
+	u8 cmd52_reg;
+	/** cmd52 value */
+	u8 cmd52_val;
+	/** SDIO pull control command */
+	u8 sdio_pull_ctrl;
+	/** Low 2 bytes is pullUp, high 2 bytes for pull-down */
+	u32 sdio_pull_cfg;
+	/** Test mode command */
+	u8 test_mode;
+} bt_dev_t, *pbt_dev_t;
+
+/** Marvell bt adapter structure */
+typedef struct _bt_adapter {
+	/** Chip revision ID */
+	u8 chip_rev;
+    /** magic val */
+	u8 magic_val;
+	/** Surprise removed flag */
+	u8 SurpriseRemoved;
+	/** IRQ number */
+	int irq;
+	/** Interrupt counter */
+	u32 IntCounter;
+	/** Tx packet queue */
+	struct sk_buff_head tx_queue;
+
+	/** Pointer of fw dump file name */
+	char *fwdump_fname;
+	/** Fw dump queue */
+	struct sk_buff_head fwdump_queue;
+	/** Pending Tx packet queue */
+	struct sk_buff_head pending_queue;
+	/** tx lock flag */
+	u8 tx_lock;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save state */
+	u8 ps_state;
+	/** Host Sleep state */
+	u8 hs_state;
+	/** hs skip count */
+	u32 hs_skip;
+	/** suspend_fail flag */
+	u8 suspend_fail;
+	/** suspended flag */
+	u8 is_suspended;
+	/** Number of wakeup tries */
+	u8 WakeupTries;
+	/** Host Sleep wait queue */
+	wait_queue_head_t cmd_wait_q __ATTRIB_ALIGN__;
+	/** Host Cmd complet state */
+	u8 cmd_complete;
+	/** last irq recv */
+	u8 irq_recv;
+	/** last irq processed */
+	u8 irq_done;
+	/** sdio int status */
+	u8 sd_ireg;
+     /** buf allocated for transmit */
+	u8 *tx_buffer;
+    /** buf for transmit */
+	u8 *tx_buf;
+    /** buf allocated for read interrupt status */
+	u8 *hw_regs_buf;
+    /** buf for read interrupt status */
+	u8 *hw_regs;
+	/** tx pending */
+	u32 skb_pending;
+/** Version string buffer length */
+#define MAX_VER_STR_LEN         128
+	/** Driver version */
+	u8 drv_ver[MAX_VER_STR_LEN];
+	/** Number of command timeout */
+	u32 num_cmd_timeout;
+} bt_adapter, *pbt_adapter;
+
+/** Length of prov name */
+#define PROC_NAME_LEN				32
+
+/** Item data structure */
+struct item_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** Size */
+	u32 size;
+	/** Address */
+	t_ptr addr;
+	/** Offset */
+	u32 offset;
+	/** Flag */
+	u32 flag;
+};
+
+/** Proc private data structure */
+struct proc_private_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** File flag */
+	u32 fileflag;
+	/** Buffer size */
+	u32 bufsize;
+	/** Number of items */
+	u32 num_items;
+	/** Item data */
+	struct item_data *pdata;
+	/** Private structure */
+	struct _bt_private *pbt;
+	/** File operations */
+	const struct file_operations *fops;
+};
+
+/** Device proc structure */
+struct device_proc {
+	/** Proc directory entry */
+	struct proc_dir_entry *proc_entry;
+	/** num of proc files */
+	u8 num_proc_files;
+	/** pointer to proc_private_data */
+	struct proc_private_data *pfiles;
+};
+
+/** Private structure for the MV device */
+typedef struct _bt_private {
+	/** Bluetooth device */
+	bt_dev_t bt_dev;
+	/** Adapter */
+	bt_adapter *adapter;
+	/** Firmware helper */
+	const struct firmware *fw_helper;
+	/** Firmware */
+	const struct firmware *firmware;
+	/** Init user configure file */
+	const struct firmware *init_user_cfg;
+	/** Init user configure wait queue token */
+	u16 init_user_conf_wait_flag;
+	/** Init user configure file wait queue */
+	wait_queue_head_t init_user_conf_wait_q __ATTRIB_ALIGN__;
+	/** Firmware request start time */
+	struct timeval req_fw_time;
+	/** Hotplug device */
+	struct device *hotplug_device;
+	/** thread to service interrupts */
+	bt_thread MainThread;
+	 /** proc data */
+	struct device_proc dev_proc[MAX_RADIO_FUNC];
+	/** Driver lock */
+	spinlock_t driver_lock;
+	/** Driver lock flags */
+	ulong driver_flags;
+	/** Driver reference flags */
+	struct kobject kobj;
+	/** CRC check flag */
+	u16 fw_crc_check;
+	/** Card type */
+	u16 card_type;
+	/** sdio device */
+	const struct sdio_device *psdio_device;
+	int debug_device_pending;
+	int debug_ocf_ogf[2];
+	u8 fw_reload;
+#ifdef BLE_WAKEUP
+	u8 ble_wakeup_buf_size;
+	u8 *ble_wakeup_buf;
+#endif
+} bt_private, *pbt_private;
+
+/** Disable interrupt */
+#define OS_INT_DISABLE	spin_lock_irqsave(&priv->driver_lock, \
+						priv->driver_flags)
+/** Enable interrupt */
+#define	OS_INT_RESTORE	spin_unlock_irqrestore(&priv->driver_lock, \
+						priv->driver_flags)
+
+#ifndef HCI_BT_AMP
+/** BT_AMP flag for device type */
+#define  HCI_BT_AMP		0x80
+#endif
+
+/** Device type of BT */
+#define DEV_TYPE_BT		0x00
+/** Device type of AMP */
+#define DEV_TYPE_AMP		0x01
+/** Device type of NFC */
+#define DEV_TYPE_NFC		0x04
+
+/** Marvell vendor packet */
+#define MRVL_VENDOR_PKT			0xFE
+
+/** Bluetooth command : Get FW Version */
+#define BT_CMD_GET_FW_VERSION       0x0F
+/** Bluetooth command : Sleep mode */
+#define BT_CMD_AUTO_SLEEP_MODE		0x23
+/** Bluetooth command : Host Sleep configuration */
+#define BT_CMD_HOST_SLEEP_CONFIG	0x59
+/** Bluetooth command : Host Sleep enable */
+#define BT_CMD_HOST_SLEEP_ENABLE	0x5A
+/** Bluetooth command : Module Configuration request */
+#define BT_CMD_MODULE_CFG_REQ		0x5B
+
+/** Bluetooth command : PMIC Configure */
+#define BT_CMD_PMIC_CONFIGURE           0x7D
+
+/** Bluetooth command : SDIO pull up down configuration request */
+#define BT_CMD_SDIO_PULL_CFG_REQ	0x69
+/** Bluetooth command : Set Evt Filter Command */
+#define BT_CMD_SET_EVT_FILTER		0x05
+/** Bluetooth command : Enable Write Scan Command */
+#define BT_CMD_ENABLE_WRITE_SCAN	0x1A
+/** Bluetooth command : Enable Device under test mode */
+#define BT_CMD_ENABLE_DEVICE_TESTMODE	0x03
+/** Sub Command: Module Bring Up Request */
+#define MODULE_BRINGUP_REQ		0xF1
+/** Sub Command: Module Shut Down Request */
+#define MODULE_SHUTDOWN_REQ		0xF2
+/** Module already up */
+#define MODULE_CFG_RESP_ALREADY_UP      0x0c
+/** Sub Command: Host Interface Control Request */
+#define MODULE_INTERFACE_CTRL_REQ	0xF5
+
+/** Bluetooth event : Power State */
+#define BT_EVENT_POWER_STATE		0x20
+
+/** Bluetooth Power State : Enable */
+#define BT_PS_ENABLE			0x02
+/** Bluetooth Power State : Disable */
+#define BT_PS_DISABLE			0x03
+/** Bluetooth Power State : Sleep */
+#define BT_PS_SLEEP			0x01
+/** Bluetooth Power State : Awake */
+#define BT_PS_AWAKE			0x02
+
+/** Vendor OGF */
+#define VENDOR_OGF				0x3F
+/** OGF for reset */
+#define RESET_OGF		0x03
+/** Bluetooth command : Reset */
+#define BT_CMD_RESET	0x03
+
+/** Host Sleep activated */
+#define HS_ACTIVATED			0x01
+/** Host Sleep deactivated */
+#define HS_DEACTIVATED			0x00
+
+/** Power Save sleep */
+#define PS_SLEEP			0x01
+/** Power Save awake */
+#define PS_AWAKE			0x00
+
+/** bt header length */
+#define BT_HEADER_LEN			4
+
+#ifndef MAX
+/** Return maximum of two */
+#define MAX(a, b)		((a) > (b) ? (a) : (b))
+#endif
+
+/** This is for firmware specific length */
+#define EXTRA_LEN	36
+
+/** Command buffer size for Marvell driver */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+
+/** Bluetooth Rx packet buffer size for Marvell driver */
+#define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \
+	(HCI_MAX_FRAME_SIZE + EXTRA_LEN)
+
+/** Buffer size to allocate */
+#define ALLOC_BUF_SIZE	(((MAX(MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \
+			MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \
+			+ SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
+
+/** Request FW timeout in second */
+#define REQUEST_FW_TIMEOUT		30
+
+/** 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
+
+/** default idle time */
+#define DEFAULT_IDLE_TIME           1000
+
+#define BT_CMD_HEADER_SIZE    3
+
+/** BT command structure */
+typedef struct _BT_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[128];
+} __ATTRIB_PACK__ BT_CMD;
+
+/** BT event structure */
+typedef struct _BT_EVENT {
+	/** Event Counter */
+	u8 EC;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[8];
+} BT_EVENT;
+
+#if defined(SDIO_SUSPEND_RESUME)
+#define DEF_GPIO_GAP        0xffff
+#endif
+
+#ifdef BLE_WAKEUP
+#define BD_ADDR_SIZE 6
+/** Vendor specific event */
+#define VENDOR_SPECIFIC_EVENT     0xff
+/** system suspend event */
+#define HCI_SYSTEM_SUSPEND_EVT    0x80
+/** system suspend */
+#define HCI_SYSTEM_SUSPEND        0x00
+/** system resume */
+#define HCI_SYSTEM_RESUME         0x01
+/** This function enables ble wake up pattern */
+int bt_config_ble_wakeup(bt_private *priv);
+int bt_send_system_event(bt_private *priv, u8 flag);
+#endif
+
+/** This function verify the received event pkt */
+int check_evtpkt(bt_private *priv, struct sk_buff *skb);
+
+/* Prototype of global function */
+/** This function gets the priv reference */
+struct kobject *bt_priv_get(bt_private *priv);
+/** This function release the priv reference */
+void bt_priv_put(bt_private *priv);
+/** This function adds the card */
+bt_private *bt_add_card(void *card);
+/** This function removes the card */
+int bt_remove_card(void *card);
+/** This function handles the interrupt */
+void bt_interrupt(struct m_dev *m_dev);
+
+/** This function creates proc interface directory structure */
+int bt_root_proc_init(void);
+/** This function removes proc interface directory structure */
+int bt_root_proc_remove(void);
+/** This function initializes proc entry */
+int bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq);
+/** This function removes proc interface */
+void bt_proc_remove(bt_private *priv);
+
+/** This function process the received event */
+int bt_process_event(bt_private *priv, struct sk_buff *skb);
+/** This function enables host sleep */
+int bt_enable_hs(bt_private *priv);
+/** This function used to send command to firmware */
+int bt_prepare_command(bt_private *priv);
+/** This function frees the structure of adapter */
+void bt_free_adapter(bt_private *priv);
+/** This function handle the receive packet */
+void bt_recv_frame(bt_private *priv, struct sk_buff *skb);
+
+/** clean up m_devs */
+void clean_up_m_devs(bt_private *priv);
+/** bt driver call this function to register to bus driver */
+int *sbi_register(void);
+/** bt driver call this function to unregister to bus driver */
+void sbi_unregister(void);
+/** bt driver calls this function to register the device  */
+int sbi_register_dev(bt_private *priv);
+/** bt driver calls this function to unregister the device */
+int sbi_unregister_dev(bt_private *priv);
+/** This function initializes firmware */
+int sbi_download_fw(bt_private *priv);
+/** Configures hardware to quit deep sleep state */
+int sbi_wakeup_firmware(bt_private *priv);
+/** Module configuration and register device */
+int sbi_register_conf_dpc(bt_private *priv);
+
+/** This function is used to send the data/cmd to hardware */
+int sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb);
+/** This function reads the current interrupt status register */
+int sbi_get_int_status(bt_private *priv);
+/** This function enables the host interrupts */
+int sbi_enable_host_int(bt_private *priv);
+/** This function disables the host interrupts */
+int sbi_disable_host_int(bt_private *priv);
+
+/** bt fw reload flag */
+extern int bt_fw_reload;
+/** 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
+/** This function reload firmware */
+void bt_request_fw_reload(bt_private *priv, int mode);
+#define MAX_TX_BUF_SIZE     2312
+/** This function downloads firmware image to the card */
+int sd_download_firmware_w_helper(bt_private *priv);
+void bt_dump_sdio_regs(bt_private *priv);
+/* dumps the firmware to /var/ or /data/ */
+void bt_dump_firmware_info_v2(bt_private *priv);
+
+/** 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
+
+/** Bluetooth command : Mac address configuration */
+#define BT_CMD_CONFIG_MAC_ADDR		0x22
+/** Bluetooth command : Write CSU register */
+#define BT_CMD_CSU_WRITE_REG		0x66
+/** Bluetooth command : Load calibrate data */
+#define BT_CMD_LOAD_CONFIG_DATA     0x61
+/** Bluetooth command : Load calibrate ext data */
+#define BT_CMD_LOAD_CONFIG_DATA_EXT     0x60
+
+/** Bluetooth command : BLE deepsleep */
+#define BT_CMD_BLE_DEEP_SLEEP       0x8b
+
+/** BT_BLE command structure */
+typedef struct _BT_BLE_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** deepsleep flag */
+	u8 deepsleep;
+} __ATTRIB_PACK__ BT_BLE_CMD;
+
+/** BT_CSU command structure */
+typedef struct _BT_CSU_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** reg type */
+	u8 type;
+	/** address */
+	u8 offset[4];
+	/** Data */
+	u8 value[2];
+} __ATTRIB_PACK__ BT_CSU_CMD;
+
+/** This function sets mac address */
+int bt_set_mac_address(bt_private *priv, u8 *mac);
+/** This function writes value to CSU registers */
+int bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value);
+/** BT set user defined init data and param */
+int bt_init_config(bt_private *priv, char *cfg_file);
+/** BT PMIC Configure command */
+int bt_pmic_configure(bt_private *priv);
+/** This function load the calibrate data */
+int bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac);
+/** This function load the calibrate ext data */
+int bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len);
+/** BT set user defined calibration data */
+int bt_cal_config(bt_private *priv, char *cfg_file, char *mac);
+/** BT set user defined calibration ext data */
+int bt_cal_config_ext(bt_private *priv, char *cfg_file);
+int bt_init_mac_address(bt_private *priv, char *mac);
+int bt_set_gpio_pin(bt_private *priv);
+/** Bluetooth command : Set gpio pin */
+#define BT_CMD_SET_GPIO_PIN     0xEC
+/** Interrupt Raising Edge**/
+#define INT_RASING_EDGE  0
+/** Interrupt Falling Edge**/
+#define INT_FALLING_EDGE 1
+#define DELAY_50_US      50
+
+int bt_set_independent_reset(bt_private *priv);
+/** Bluetooth command : Independent reset */
+#define BT_CMD_INDEPENDENT_RESET     0x0D
+
+/** BT HCI command structure */
+typedef struct _BT_HCI_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** cmd type */
+	u8 cmd_type;
+	/** cmd len */
+	u8 cmd_len;
+	/** Data */
+	u8 data[6];
+} __ATTRIB_PACK__ BT_HCI_CMD;
+
+#endif /* _BT_DRV_H_ */
diff --git a/bt_sd8897/bt/bt_init.c b/bt_sd8897/bt/bt_init.c
new file mode 100644
index 0000000..9d18912
--- /dev/null
+++ b/bt_sd8897/bt/bt_init.c
@@ -0,0 +1,751 @@
+/** @file bt_init.c
+  *
+  * @brief This file contains the init functions for BlueTooth
+  * driver.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/string.h>
+#include <linux/firmware.h>
+
+#include "bt_drv.h"
+
+extern int bt_req_fw_nowait;
+
+#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
+			 || ('a' <= (c) && (c) <= 'f') \
+			 || ('A' <= (c) && (c) <= 'F'))
+
+#define isdigit(c)	(('0' <= (c) && (c) <= '9'))
+#define isspace(c)  (c <= ' ' && (c == ' ' || (c <= 13 && c >= 9)))
+/**
+ *  @brief Returns hex value of a give character
+ *
+ *  @param chr	Character to be converted
+ *
+ *  @return	The converted character if chr is a valid hex, else 0
+ */
+static int
+bt_hexval(char chr)
+{
+	ENTER();
+
+	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;
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @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
+ */
+static char *
+bt_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 Returns hex value of a given ascii string
+ *
+ *  @param a	String to be converted
+ *
+ *  @return	hex value
+ */
+static int
+bt_atox(const char *a)
+{
+	int i = 0;
+	ENTER();
+	while (isxdigit(*a))
+		i = i * 16 + bt_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief Converts 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
+ */
+static void
+bt_mac2u8(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;
+	}
+	memcpy(mac_buff, buf, strlen(buf));
+
+	begin = mac_buff;
+	for (i = 0; i < ETH_ALEN; ++i) {
+		end = bt_strsep(&begin, ':', '/');
+		if (end)
+			mac_addr[i] = bt_atox(end);
+	}
+
+	kfree(mac_buff);
+	LEAVE();
+}
+
+/**
+ *  @brief Returns integer value of a given ascii string
+ *
+ *  @param data    Converted data to be returned
+ *  @param a       String to be converted
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_atoi(int *data, char *a)
+{
+	int i, val = 0, len;
+
+	ENTER();
+
+	len = strlen(a);
+	if (!strncmp(a, "0x", 2)) {
+		a = a + 2;
+		len -= 2;
+		*data = bt_atox(a);
+		return BT_STATUS_SUCCESS;
+	}
+	for (i = 0; i < len; i++) {
+		if (isdigit(a[i])) {
+			val = val * 10 + (a[i] - '0');
+		} else {
+			PRINTM(ERROR, "Invalid char %c in string %s\n", a[i],
+			       a);
+			return BT_STATUS_FAILURE;
+		}
+	}
+	*data = val;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief parse cal-data
+ *
+ *  @param src      a pointer to cal-data string
+ *  @param len      len of cal-data
+ *  @param dst      a pointer to return cal-data
+ *  @param dst_size size of dest buffer
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 *dst_size)
+{
+	const u8 *ptr;
+	u8 *dptr;
+	u32 count = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	ptr = src;
+	dptr = dst;
+
+	while ((ptr - src) < len) {
+		if (*ptr && isspace(*ptr)) {
+			ptr++;
+			continue;
+		}
+
+		if (isxdigit(*ptr)) {
+			if ((dptr - dst) >= *dst_size) {
+				PRINTM(ERROR, "cal_file size too big!!!\n");
+				goto done;
+			}
+			*dptr++ = bt_atox((const char *)ptr);
+			ptr += 2;
+			count++;
+		} else {
+			ptr++;
+		}
+	}
+	if (dptr == dst) {
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	*dst_size = count;
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT get one line data from ASCII format data
+ *
+ *    @param data         Source data
+ *    @param size         Source data length
+ *    @param line_pos     Destination data
+ *    @return             -1 or length of the line
+ */
+int
+parse_cfg_get_line(u8 *data, u32 size, u8 *line_pos)
+{
+	static s32 pos;
+	u8 *src, *dest;
+
+	if (pos >= size) {	/* reach the end */
+		pos = 0;	/* Reset position for rfkill */
+		return -1;
+	}
+	memset(line_pos, 0, MAX_LINE_LEN);
+	src = data + pos;
+	dest = line_pos;
+
+	while (pos < size && *src != '\x0A' && *src != '\0') {
+		if (*src != ' ' && *src != '\t')	/* parse space */
+			*dest++ = *src++;
+		else
+			src++;
+		pos++;
+	}
+	*dest = '\0';
+	/* parse new line */
+	pos++;
+	return strlen((const char *)line_pos);
+}
+
+/**
+ *    @brief BT parse ASCII format data to MAC address
+ *
+ *    @param priv          BT private handle
+ *    @param data          Source data
+ *    @param size          data length
+ *    @return              BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_init_cfg(bt_private *priv, u8 *data, u32 size)
+{
+	u8 *pos;
+	u8 *intf_s, *intf_e;
+	u8 s[MAX_LINE_LEN];	/* 1 line data */
+	u32 line_len;
+	char dev_name[MAX_PARAM_LEN];
+	u8 buf[MAX_PARAM_LEN];
+	u8 bt_addr[MAX_MAC_ADDR_LEN];
+	u8 bt_mac[ETH_ALEN];
+	int setting = 0;
+	u8 type = 0;
+	u16 value = 0;
+	u32 offset = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	memset(dev_name, 0, sizeof(dev_name));
+	memset(bt_addr, 0, sizeof(bt_addr));
+	memset(bt_mac, 0, sizeof(bt_mac));
+
+	while ((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;	/* Need n't process this line */
+
+		/* Process MAC addr */
+		if (strncmp((char *)pos, "mac_addr", 8) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ':');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				if ((intf_e - intf_s) > MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Too long interface name %d\n",
+					       __LINE__);
+					goto done;
+				}
+				strncpy(dev_name, (const char *)intf_s + 1,
+					intf_e - intf_s - 1);
+				dev_name[intf_e - intf_s - 1] = '\0';
+				strncpy((char *)bt_addr,
+					(const char *)intf_e + 1,
+					MAX_MAC_ADDR_LEN - 1);
+				bt_addr[MAX_MAC_ADDR_LEN - 1] = '\0';
+				/* Convert MAC format */
+				bt_mac2u8(bt_mac, (char *)bt_addr);
+				PRINTM(CMD,
+				       "HCI: %s new BT Address " MACSTR "\n",
+				       dev_name, MAC2STR(bt_mac));
+				if (BT_STATUS_SUCCESS !=
+				    bt_set_mac_address(priv, bt_mac)) {
+					PRINTM(FATAL,
+					       "BT: Fail to set mac address\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+		}
+		/* Process REG value */
+		else if (strncmp((char *)pos, "bt_reg", 6) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ',');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				/* Copy type */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s + 1,
+					1);
+				buf[1] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					type = (u8)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg type\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			intf_e = (u8 *)strchr((const char *)intf_s, ',');
+			if (intf_e != NULL) {
+				if ((intf_e - intf_s) >= MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Regsier offset is too long %d\n",
+					       __LINE__);
+					goto done;
+				}
+				/* Copy offset */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s,
+					intf_e - intf_s);
+				buf[intf_e - intf_s] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					offset = (u32)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg offset\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			if ((strlen((const char *)intf_s) >= MAX_PARAM_LEN)) {
+				PRINTM(ERROR,
+				       "BT: Regsier value is too long %d\n",
+				       __LINE__);
+				goto done;
+			}
+			/* Copy value */
+			memset(buf, 0, sizeof(buf));
+			strncpy((char *)buf, (const char *)intf_s, sizeof(buf));
+			if (0 == bt_atoi(&setting, (char *)buf))
+				value = (u16) setting;
+			else {
+				PRINTM(ERROR, "BT: Fail to parse reg value\n");
+				goto done;
+			}
+
+			PRINTM(CMD,
+			       "BT: Write reg type: %d offset: 0x%x value: 0x%x\n",
+			       type, offset, value);
+			if (BT_STATUS_SUCCESS !=
+			    bt_write_reg(priv, type, offset, value)) {
+				PRINTM(FATAL,
+				       "BT: Write reg failed. type: %d offset: 0x%x value: 0x%x\n",
+				       type, offset, value);
+				goto done;
+			}
+		}
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief BT 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 bt_private structure
+ *
+ * @return          N/A
+ */
+static void
+bt_request_init_user_conf_callback(const struct firmware *firmware,
+				   void *context)
+{
+	bt_private *priv = (bt_private *)context;
+
+	ENTER();
+
+	if (!firmware)
+		PRINTM(ERROR, "BT user init config request firmware failed\n");
+
+	priv->init_user_cfg = firmware;
+	priv->init_user_conf_wait_flag = TRUE;
+	wake_up_interruptible(&priv->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *    @brief BT set user defined init data and param
+ *
+ *    @param priv     BT private handle
+ *    @param cfg_file user cofig file
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_config(bt_private *priv, char *cfg_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if ((request_firmware(&cfg, cfg_file, priv->hotplug_device)) < 0) {
+		PRINTM(FATAL, "BT: request_firmware() %s failed\n", cfg_file);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (cfg)
+		ret = bt_process_init_cfg(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg(bt_private *priv, u8 *data, u32 size, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	u8 cal_data[32];
+	u8 *mac_data = NULL;
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+	u8 *pcal_data = cal_data;
+
+	memset(bt_mac, 0, sizeof(bt_mac));
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (mac != NULL) {
+		/* Convert MAC format */
+		bt_mac2u8(bt_mac, mac);
+		PRINTM(CMD, "HCI: new BT Address " MACSTR "\n",
+		       MAC2STR(bt_mac));
+		mac_data = bt_mac;
+	}
+	if (BT_STATUS_SUCCESS != bt_load_cal_data(priv, pcal_data, mac_data)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg_ext(bt_private *priv, u8 *data, u32 size)
+{
+	u8 cal_data[128];
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (BT_STATUS_SUCCESS !=
+	    bt_load_cal_data_ext(priv, cal_data, cal_data_len)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config(bt_private *priv, char *cal_file, char *mac)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size, mac);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config_ext(bt_private *priv, char *cal_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config_ext() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg_ext(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT init mac address from bt_mac parametre when insmod
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param bt_mac  mac address buf
+ *    @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_mac_address(bt_private *priv, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	memset(bt_mac, 0, sizeof(bt_mac));
+	bt_mac2u8(bt_mac, mac);
+	PRINTM(CMD, "HCI: New BT Address " MACSTR "\n", MAC2STR(bt_mac));
+	ret = bt_set_mac_address(priv, bt_mac);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(FATAL,
+		       "BT: Fail to set mac address from insmod parametre.\n");
+
+	LEAVE();
+	return ret;
+}
diff --git a/bt_sd8897/bt/bt_main.c b/bt_sd8897/bt/bt_main.c
new file mode 100644
index 0000000..744bba3
--- /dev/null
+++ b/bt_sd8897/bt/bt_main.c
@@ -0,0 +1,3958 @@
+/** @file bt_main.c
+  *
+  * @brief This file contains the major functions in BlueTooth
+  * driver. It includes init, exit, open, close and main
+  * thread etc..
+  *
+  * Copyright (C) 2007-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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.
+  *
+  */
+/**
+  * @mainpage M-BT Linux Driver
+  *
+  * @section overview_sec Overview
+  *
+  * The M-BT is a Linux reference driver for Marvell Bluetooth chipset.
+  *
+  * @section copyright_sec Copyright
+  *
+  * Copyright (C) 2007-2018, Marvell International Ltd.
+  *
+  */
+#include <linux/module.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
+
+#include <linux/mmc/sdio_func.h>
+
+#include "bt_drv.h"
+#include "mbt_char.h"
+#include "bt_sdio.h"
+
+/** Version */
+#define VERSION "C3X14113"
+
+/** Driver version */
+static char mbt_driver_version[] = "SD8XXX-%s-" VERSION "-(" "FP" FPNUM ")"
+#ifdef DEBUG_LEVEL2
+	"-dbg"
+#endif
+	" ";
+
+/** SD8787 Card */
+#define CARD_SD8787     "SD8787"
+/** SD8777 Card */
+#define CARD_SD8777     "SD8777"
+/** SD8887 Card */
+#define CARD_SD8887     "SD8887"
+/** SD8897 Card */
+#define CARD_SD8897     "SD8897"
+/** SD8797 Card */
+#define CARD_SD8797     "SD8797"
+/** SD8977 Card */
+#define CARD_SD8977     "SD8977"
+/** SD8997 Card */
+#define CARD_SD8997     "SD8997"
+/** SD8987 Card */
+#define CARD_SD8987     "SD8987"
+
+/** Declare and initialize fw_version */
+static char fw_version[32] = "0.0.0.p0";
+
+#define AID_SYSTEM        1000	/* system server */
+
+#define AID_BLUETOOTH     1002	/* bluetooth subsystem */
+
+#define AID_NET_BT_STACK  3008	/* bluetooth stack */
+
+/** Define module name */
+
+#define MODULE_NAME  "bt_fm_nfc"
+
+/** Declaration of chardev class */
+static struct class *chardev_class;
+
+/** Interface specific variables */
+static int mbtchar_minor;
+static int nfcchar_minor;
+static int debugchar_minor;
+
+/**
+ * The global variable of a pointer to bt_private
+ * structure variable
+ **/
+bt_private *m_priv[MAX_BT_ADAPTER];
+
+/** Default Driver mode */
+static int drv_mode = (DRV_MODE_BT | DRV_MODE_NFC);
+
+/** BT interface name */
+static char *bt_name;
+/** NFC interface name */
+static char *nfc_name;
+/** BT debug interface name */
+static char *debug_name;
+
+/** fw reload flag */
+int bt_fw_reload;
+/** fw serial download flag */
+int bt_fw_serial = 1;
+
+/** Firmware flag */
+static int fw = 1;
+/** default powermode */
+static int psmode = 1;
+/** default BLE deep sleep */
+static int deep_sleep = 1;
+/** Default CRC check control */
+static int fw_crc_check = 1;
+/** Init config file (MAC address, register etc.) */
+static char *init_cfg;
+/** Calibration config file (MAC address, init powe etc.) */
+static char *cal_cfg;
+/** Calibration config file EXT */
+static char *cal_cfg_ext;
+/** Init MAC address */
+static char *bt_mac;
+static int mbt_gpio_pin;
+static int btindrst = -1;
+
+/** Setting mbt_drvdbg value based on DEBUG level */
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define DEFAULT_DEBUG_MASK  (0xffffffff & ~DBG_EVENT)
+#else
+#define DEFAULT_DEBUG_MASK  (DBG_MSG | DBG_FATAL | DBG_ERROR)
+#endif /* DEBUG_LEVEL2 */
+u32 mbt_drvdbg = DEFAULT_DEBUG_MASK;
+#endif
+
+#ifdef CONFIG_OF
+static int dts_enable = 1;
+#endif
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+int mbt_pm_keep_power = 1;
+#endif
+
+static int debug_intf = 1;
+
+static int btpmic = 0;
+
+/** Offset of sequence number in event */
+#define OFFSET_SEQNUM 4
+
+/**
+ *  @brief handle received packet
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *
+ *  @return        N/A
+ */
+void
+bt_recv_frame(bt_private *priv, struct sk_buff *skb)
+{
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		mdev_recv_frame(skb);
+		mdev_bt->stat.byte_rx += skb->len;
+	}
+	return;
+}
+
+/**
+ *  @brief Alloc bt device
+ *
+ *  @return    pointer to structure mbt_dev or NULL
+ */
+struct mbt_dev *
+alloc_mbt_dev(void)
+{
+	struct mbt_dev *mbt_dev;
+	ENTER();
+
+	mbt_dev = kzalloc(sizeof(struct mbt_dev), GFP_KERNEL);
+	if (!mbt_dev) {
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return mbt_dev;
+}
+
+/**
+ *  @brief Alloc nfc device
+ *
+ *  @return    pointer to structure nfc_dev or NULL
+ */
+struct nfc_dev *
+alloc_nfc_dev(void)
+{
+	struct nfc_dev *nfc_dev;
+	ENTER();
+
+	nfc_dev = kzalloc(sizeof(struct nfc_dev), GFP_KERNEL);
+	if (!nfc_dev) {
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return nfc_dev;
+}
+
+/**
+ *  @brief Alloc debug device
+ *
+ *  @return    pointer to structure debug_level or NULL
+ */
+struct debug_dev *
+alloc_debug_dev(void)
+{
+	struct debug_dev *debug_dev;
+	ENTER();
+
+	debug_dev = kzalloc(sizeof(struct debug_dev), GFP_KERNEL);
+	if (!debug_dev) {
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return debug_dev;
+}
+
+/**
+ *  @brief Frees m_dev
+ *
+ *  @return    N/A
+ */
+void
+free_m_dev(struct m_dev *m_dev)
+{
+	ENTER();
+	kfree(m_dev->dev_pointer);
+	m_dev->dev_pointer = NULL;
+	LEAVE();
+}
+
+/**
+ *  @brief clean up m_devs
+ *
+ *  @return    N/A
+ */
+void
+clean_up_m_devs(bt_private *priv)
+{
+	struct m_dev *m_dev = NULL;
+	int i;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+		PRINTM(MSG, "BT: Delete %s\n", m_dev->name);
+		if (m_dev->spec_type == IANYWHERE_SPEC) {
+			if ((drv_mode & DRV_MODE_BT) && (mbtchar_minor > 0))
+				mbtchar_minor--;
+			m_dev->close(m_dev);
+			for (i = 0; i < 3; i++)
+				kfree_skb(((struct mbt_dev *)
+					   (m_dev->dev_pointer))->
+					  reassembly[i]);
+			/**  unregister m_dev to char_dev */
+			if (chardev_class)
+				chardev_cleanup_one(m_dev, chardev_class);
+			free_m_dev(m_dev);
+		}
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = NULL;
+	}
+	if (priv->bt_dev.m_dev[NFC_SEQ].dev_pointer) {
+		m_dev = &(priv->bt_dev.m_dev[NFC_SEQ]);
+		PRINTM(MSG, "BT: Delete %s\n", m_dev->name);
+		if ((drv_mode & DRV_MODE_NFC) && (nfcchar_minor > 0))
+			nfcchar_minor--;
+		m_dev->close(m_dev);
+		/** unregister m_dev to char_dev */
+		if (chardev_class)
+			chardev_cleanup_one(m_dev, chardev_class);
+		free_m_dev(m_dev);
+		priv->bt_dev.m_dev[NFC_SEQ].dev_pointer = NULL;
+	}
+	if (priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer) {
+		m_dev = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
+		PRINTM(MSG, "BT: Delete %s\n", m_dev->name);
+		if ((debug_intf) && (debugchar_minor > 0))
+			debugchar_minor--;
+		/** unregister m_dev to char_dev */
+		if (chardev_class)
+			chardev_cleanup_one(m_dev, chardev_class);
+		free_m_dev(m_dev);
+		priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer = NULL;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function verify the received event pkt
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+--------+
+ *  | Event  | Length |  ncmd  |      Opcode     |
+ *  +--------+--------+--------+--------+--------+
+ *  | 1-byte | 1-byte | 1-byte |      2-byte     |
+ *  +--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+check_evtpkt(bt_private *priv, struct sk_buff *skb)
+{
+	struct hci_event_hdr *hdr = (struct hci_event_hdr *)skb->data;
+	struct hci_ev_cmd_complete *ec;
+	u16 opcode, ocf;
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (!priv->bt_dev.sendcmdflag) {
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	if (hdr->evt == HCI_EV_CMD_COMPLETE) {
+		ec = (struct hci_ev_cmd_complete *)
+			(skb->data + HCI_EVENT_HDR_SIZE);
+		opcode = __le16_to_cpu(ec->opcode);
+		ocf = hci_opcode_ocf(opcode);
+		PRINTM(CMD,
+		       "BT: CMD_COMPLTE opcode=0x%x, ocf=0x%x, send_cmd_opcode=0x%x\n",
+		       opcode, ocf, priv->bt_dev.send_cmd_opcode);
+		if (opcode != priv->bt_dev.send_cmd_opcode) {
+			ret = BT_STATUS_FAILURE;
+			goto exit;
+		}
+		switch (ocf) {
+		case BT_CMD_MODULE_CFG_REQ:
+		case BT_CMD_BLE_DEEP_SLEEP:
+		case BT_CMD_CONFIG_MAC_ADDR:
+		case BT_CMD_CSU_WRITE_REG:
+		case BT_CMD_LOAD_CONFIG_DATA:
+		case BT_CMD_LOAD_CONFIG_DATA_EXT:
+		case BT_CMD_AUTO_SLEEP_MODE:
+		case BT_CMD_HOST_SLEEP_CONFIG:
+		case BT_CMD_SDIO_PULL_CFG_REQ:
+		case BT_CMD_SET_EVT_FILTER:
+		case BT_CMD_ENABLE_WRITE_SCAN:
+			// case BT_CMD_ENABLE_DEVICE_TESTMODE:
+		case BT_CMD_RESET:
+		case BT_CMD_PMIC_CONFIGURE:
+		case BT_CMD_SET_GPIO_PIN:
+		case BT_CMD_INDEPENDENT_RESET:
+			priv->bt_dev.sendcmdflag = FALSE;
+			priv->adapter->cmd_complete = TRUE;
+			wake_up_interruptible(&priv->adapter->cmd_wait_q);
+			break;
+		case BT_CMD_GET_FW_VERSION:
+			{
+				u8 *pos = (skb->data + HCI_EVENT_HDR_SIZE +
+					   sizeof(struct hci_ev_cmd_complete) +
+					   1);
+				snprintf(fw_version, sizeof(fw_version),
+					 "%u.%u.%u.p%u", pos[2], pos[1], pos[0],
+					 pos[3]);
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+				break;
+			}
+		case BT_CMD_HOST_SLEEP_ENABLE:
+			priv->bt_dev.sendcmdflag = FALSE;
+			break;
+		default:
+			/** Ignore command not defined but send by driver */
+			if (opcode == priv->bt_dev.send_cmd_opcode) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			} else {
+				ret = BT_STATUS_FAILURE;
+			}
+			break;
+		}
+	}
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+*  @brief This function stores the FW dumps received from events in a file
+*
+*  @param priv    A pointer to bt_private structure
+*  @param skb     A pointer to rx skb
+*
+*  @return        N/A
+*/
+void
+bt_store_firmware_dump(bt_private *priv, u8 *buf, u32 len)
+{
+	struct file *pfile_fwdump = NULL;
+	loff_t pos = 0;
+	u16 seqnum = 0;
+	struct timeval t;
+	u32 sec;
+
+	ENTER();
+
+	seqnum = __le16_to_cpu(*(u16 *) (buf + OFFSET_SEQNUM));
+
+	if (priv->adapter->fwdump_fname && seqnum != 1) {
+		pfile_fwdump =
+			filp_open((const char *)priv->adapter->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		if (IS_ERR(pfile_fwdump)) {
+			PRINTM(MSG, "Cannot create firmware dump file.\n");
+			LEAVE();
+			return;
+		}
+	} else {
+		if (!priv->adapter->fwdump_fname) {
+			gfp_t flag;
+			flag = (in_atomic() ||
+				irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+			priv->adapter->fwdump_fname = kzalloc(64, flag);
+		} else
+			memset(priv->adapter->fwdump_fname, 0, 64);
+
+		do_gettimeofday(&t);
+		sec = (u32)t.tv_sec;
+		sprintf(priv->adapter->fwdump_fname, "%s%u",
+			"/var/log/bt_fwdump_", sec);
+		pfile_fwdump =
+			filp_open(priv->adapter->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		if (IS_ERR(pfile_fwdump)) {
+			sprintf(priv->adapter->fwdump_fname, "%s%u",
+				"/data/bt_fwdump_", sec);
+			pfile_fwdump =
+				filp_open((const char *)priv->adapter->
+					  fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		}
+	}
+
+	if (IS_ERR(pfile_fwdump)) {
+		PRINTM(MSG, "Cannot create firmware dump file\n");
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile_fwdump, buf, len, &pos);
+#else
+	kernel_write(pfile_fwdump, buf, len, &pos);
+#endif
+	filp_close(pfile_fwdump, NULL);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function process the received event
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+-----+
+ *  |   EC   | Length |           Data        |
+ *  +--------+--------+--------+--------+-----+
+ *  | 1-byte | 1-byte |          n-byte       |
+ *  +--------+--------+--------+--------+-----+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_event(bt_private *priv, struct sk_buff *skb)
+{
+	int ret = BT_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	BT_EVENT *pevent;
+
+	ENTER();
+	if (!m_dev) {
+		PRINTM(CMD, "BT: bt_process_event without m_dev\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pevent = (BT_EVENT *)skb->data;
+	if (pevent->EC != 0xff) {
+		PRINTM(CMD, "BT: Not Marvell Event=0x%x\n", pevent->EC);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	switch (pevent->data[0]) {
+	case BT_CMD_AUTO_SLEEP_MODE:
+		if (pevent->data[2] == BT_STATUS_SUCCESS) {
+			if (pevent->data[1] == BT_PS_ENABLE)
+				priv->adapter->psmode = 1;
+			else
+				priv->adapter->psmode = 0;
+			PRINTM(CMD, "BT: PS Mode %s:%s\n", m_dev->name,
+			       (priv->adapter->psmode) ? "Enable" : "Disable");
+
+		} else {
+			PRINTM(CMD, "BT: PS Mode Command Fail %s\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_CONFIG:
+		if (pevent->data[3] == BT_STATUS_SUCCESS) {
+			PRINTM(CMD, "BT: %s: gpio=0x%x, gap=0x%x\n",
+			       m_dev->name, pevent->data[1], pevent->data[2]);
+		} else {
+			PRINTM(CMD, "BT: %s: HSCFG Command Fail\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_ENABLE:
+		if (pevent->data[1] == BT_STATUS_SUCCESS) {
+			priv->adapter->hs_state = HS_ACTIVATED;
+			if (priv->adapter->suspend_fail == FALSE) {
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+				bt_is_suspended(priv);
+#endif
+#endif
+#endif
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			}
+			if (priv->adapter->psmode)
+				priv->adapter->ps_state = PS_SLEEP;
+			PRINTM(CMD, "BT: EVENT %s: HS ACTIVATED!\n",
+			       m_dev->name);
+
+		} else {
+			PRINTM(CMD, "BT: %s: HS Enable Fail\n", m_dev->name);
+		}
+		break;
+	case BT_CMD_MODULE_CFG_REQ:
+		if ((priv->bt_dev.sendcmdflag == TRUE) &&
+		    ((pevent->data[1] == MODULE_BRINGUP_REQ)
+		     || (pevent->data[1] == MODULE_SHUTDOWN_REQ))) {
+			if (pevent->data[1] == MODULE_BRINGUP_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2] && (pevent->data[2] !=
+							    MODULE_CFG_RESP_ALREADY_UP))
+				       ? "Bring up Fail" : "Bring up success");
+				priv->bt_dev.devType = pevent->data[3];
+				PRINTM(CMD, "devType:%s\n",
+				       (pevent->data[3] ==
+					DEV_TYPE_AMP) ? "AMP controller" :
+				       "BR/EDR controller");
+				priv->bt_dev.devFeature = pevent->data[4];
+				PRINTM(CMD, "devFeature:  %s,    %s,    %s"
+				       ",    %s"
+				       "\n",
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BT) ?
+					"BT Feature" : "No BT Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BTAMP) ?
+					"BTAMP Feature" : "No BTAMP Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BLE) ?
+					"BLE Feature" : "No BLE Feature")
+				       ,
+				       ((pevent->
+					 data[4] & DEV_FEATURE_NFC) ?
+					"NFC Feature" : "No NFC Feature")
+					);
+			}
+			if (pevent->data[1] == MODULE_SHUTDOWN_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2]) ? "Shut down Fail"
+				       : "Shut down success");
+
+			}
+			if (pevent->data[2]) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			}
+		} else {
+			PRINTM(CMD, "BT_CMD_MODULE_CFG_REQ resp for APP\n");
+			ret = BT_STATUS_FAILURE;
+		}
+		break;
+	case BT_EVENT_POWER_STATE:
+		if (pevent->data[1] == BT_PS_SLEEP)
+			priv->adapter->ps_state = PS_SLEEP;
+		if (priv->adapter->ps_state == PS_SLEEP
+		    && (priv->card_type == CARD_TYPE_SD8887)
+			)
+			os_sched_timeout(5);
+		PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+		       (priv->adapter->ps_state) ? "PS_SLEEP" : "PS_AWAKE");
+
+		break;
+	case BT_CMD_SDIO_PULL_CFG_REQ:
+		if (pevent->data[pevent->length - 1] == BT_STATUS_SUCCESS)
+			PRINTM(CMD, "BT: %s: SDIO pull configuration success\n",
+			       m_dev->name);
+
+		else {
+			PRINTM(CMD, "BT: %s: SDIO pull configuration fail\n",
+			       m_dev->name);
+
+		}
+		break;
+	default:
+		PRINTM(CMD, "BT: Unknown Event=%d %s\n", pevent->data[0],
+		       m_dev->name);
+		ret = BT_STATUS_FAILURE;
+		break;
+	}
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function save the dump info to file
+ *
+ *  @param dir_name     directory name
+ *  @param file_name    file_name
+ *  @param buf			buffer
+ *  @param buf_len		buffer length
+ *
+ *  @return   		    0 --success otherwise fail
+ */
+int
+bt_save_dump_info_to_file(char *dir_name, char *file_name, u8 *buf, u32 buf_len)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct file *pfile = NULL;
+	u8 name[64];
+	loff_t pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	if (!dir_name || !file_name || !buf) {
+		PRINTM(ERROR, "Can't save dump info to file\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(name, 0, sizeof(name));
+	sprintf((char *)name, "%s/%s", dir_name, file_name);
+	pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MSG,
+		       "Create file %s error, try to save dump file in /var\n",
+		       name);
+		memset(name, 0, sizeof(name));
+		sprintf((char *)name, "%s/%s", "/var", file_name);
+		pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(ERROR, "Create Dump file for %s error\n", name);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MSG, "Dump data %s saved in %s\n", file_name, name);
+
+	pos = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	vfs_write(pfile, (const char __user *)buf, buf_len, &pos);
+	set_fs(fs);
+#else
+	kernel_write(pfile, (const char __user *)buf, buf_len, &pos);
+#endif
+	filp_close(pfile, NULL);
+
+	PRINTM(MSG, "Dump data %s saved in %s successfully\n", file_name, name);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#define DEBUG_HOST_READY		0xEE
+#define DEBUG_FW_DONE			0xFF
+#define DUMP_MAX_POLL_TRIES			200
+
+#define DEBUG_DUMP_CTRL_REG_8897               0xE2
+#define DEBUG_DUMP_START_REG_8897              0xE3
+#define DEBUG_DUMP_END_REG_8897                0xEA
+#define DEBUG_DUMP_CTRL_REG_8887               0xA2
+#define DEBUG_DUMP_START_REG_8887              0xA3
+#define DEBUG_DUMP_END_REG_8887                0xAA
+#define DEBUG_DUMP_CTRL_REG_8977               0xF0
+#define DEBUG_DUMP_START_REG_8977              0xF1
+#define DEBUG_DUMP_END_REG_8977                0xF8
+#define DEBUG_DUMP_CTRL_REG_8997               0xF0
+#define DEBUG_DUMP_START_REG_8997              0xF1
+#define DEBUG_DUMP_END_REG_8997                0xF8
+#define DEBUG_DUMP_CTRL_REG_8987               0xF0
+#define DEBUG_DUMP_START_REG_8987              0xF1
+#define DEBUG_DUMP_END_REG_8987                0xF8
+
+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
+#define MAX_FULL_NAME_LEN               32
+
+/** Memory type mapping structure */
+typedef struct {
+	/** memory name */
+	u8 mem_name[MAX_NAME_LEN];
+	/** memory pointer */
+	u8 *mem_Ptr;
+	/** file structure */
+	struct file *pfile_mem;
+	/** donbe flag */
+	u8 done_flag;
+} memory_type_mapping;
+
+memory_type_mapping bt_mem_type_mapping_tbl[] = {
+	{"ITCM", NULL, NULL, 0xF0},
+	{"DTCM", NULL, NULL, 0xF1},
+	{"SQRAM", NULL, NULL, 0xF2},
+	{"APU", NULL, NULL, 0xF3},
+	{"CIU", NULL, NULL, 0xF4},
+	{"ICU", NULL, NULL, 0xF5},
+	{"MAC", NULL, NULL, 0xF6},
+	{"EXT7", NULL, NULL, 0xF7},
+	{"EXT8", NULL, NULL, 0xF8},
+	{"EXT9", NULL, NULL, 0xF9},
+	{"EXT10", NULL, NULL, 0xFA},
+	{"EXT11", NULL, NULL, 0xFB},
+	{"EXT12", NULL, NULL, 0xFC},
+	{"EXT13", NULL, NULL, 0xFD},
+	{"EXTLAST", NULL, NULL, 0xFE},
+};
+
+typedef enum {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+} rdwr_status;
+
+/**
+ *  @brief This function read/write firmware via cmd52
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+rdwr_status
+bt_cmd52_rdwr_firmware(bt_private *priv, u8 doneflag)
+{
+	int ret = 0;
+	int tries = 0;
+	u8 ctrl_data = 0;
+	u8 dbg_dump_ctrl_reg = 0;
+
+	if (priv->card_type == CARD_TYPE_SD8887)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8887;
+	else if (priv->card_type == CARD_TYPE_SD8897)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8897;
+	else if (priv->card_type == CARD_TYPE_SD8977)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8977;
+	else if (priv->card_type == CARD_TYPE_SD8997)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8997;
+	else if (priv->card_type == CARD_TYPE_SD8987)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8987;
+
+	sdio_writeb(((struct sdio_mmc_card *)priv->bt_dev.card)->func,
+		    DEBUG_HOST_READY, dbg_dump_ctrl_reg, &ret);
+	if (ret) {
+		PRINTM(ERROR, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	for (tries = 0; tries < DUMP_MAX_POLL_TRIES; tries++) {
+		ctrl_data =
+			sdio_readb(((struct sdio_mmc_card *)priv->bt_dev.card)->
+				   func, dbg_dump_ctrl_reg, &ret);
+		if (ret) {
+			PRINTM(ERROR, "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(INFO,
+			       "The ctrl reg was changed, re-try again!\n");
+			sdio_writeb(((struct sdio_mmc_card *)priv->bt_dev.
+				     card)->func, DEBUG_HOST_READY,
+				    dbg_dump_ctrl_reg, &ret);
+			if (ret) {
+				PRINTM(ERROR, "SDIO Write ERR\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		udelay(100);
+	}
+	if (ctrl_data == DEBUG_HOST_READY) {
+		PRINTM(ERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	return RDWR_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_firmware_info_v2(bt_private *priv)
+{
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	u8 *dbg_ptr = NULL;
+	u8 dump_num = 0;
+	u8 idx = 0;
+	u8 doneflag = 0;
+	rdwr_status stat;
+	u8 i = 0;
+	u8 read_reg = 0;
+	u32 memory_size = 0;
+	u8 path_name[64], file_name[32];
+	u8 *end_ptr = NULL;
+	u8 dbg_dump_start_reg = 0;
+	u8 dbg_dump_end_reg = 0;
+
+	if (!priv) {
+		PRINTM(ERROR, "Could not dump firmwware info\n");
+		return;
+	}
+
+	if ((priv->card_type != CARD_TYPE_SD8887) &&
+	    (priv->card_type != CARD_TYPE_SD8897)
+	    && (priv->card_type != CARD_TYPE_SD8977) &&
+	    (priv->card_type != CARD_TYPE_SD8997)
+	    && (priv->card_type != CARD_TYPE_SD8987)) {
+		PRINTM(MSG, "card_type %d don't support FW dump\n",
+		       priv->card_type);
+		return;
+	}
+
+	memset(path_name, 0, sizeof(path_name));
+	strcpy((char *)path_name, "/data");
+	PRINTM(MSG, "Create DUMP directory success:dir_name=%s\n", path_name);
+
+	if (priv->card_type == CARD_TYPE_SD8887) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8887;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8887;
+	} else if (priv->card_type == CARD_TYPE_SD8897) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8897;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8897;
+	} else if (priv->card_type == CARD_TYPE_SD8977) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8977;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8977;
+	} else if (priv->card_type == CARD_TYPE_SD8997) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8997;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8997;
+	} else if (priv->card_type == CARD_TYPE_SD8987) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8987;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8987;
+	}
+
+	sbi_wakeup_firmware(priv);
+	sdio_claim_host(((struct sdio_mmc_card *)priv->bt_dev.card)->func);
+	/* start dump fw memory */
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT START ====\n");
+	/* read the number of the memories which will dump */
+	if (RDWR_STATUS_FAILURE == bt_cmd52_rdwr_firmware(priv, doneflag))
+		goto done;
+	reg = dbg_dump_start_reg;
+	dump_num =
+		sdio_readb(((struct sdio_mmc_card *)priv->bt_dev.card)->func,
+			   reg, &ret);
+	if (ret) {
+		PRINTM(MSG, "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 ==
+		    bt_cmd52_rdwr_firmware(priv, doneflag))
+			goto done;
+		memory_size = 0;
+		reg = dbg_dump_start_reg;
+		for (i = 0; i < 4; i++) {
+			read_reg =
+				sdio_readb(((struct sdio_mmc_card *)priv->
+					    bt_dev.card)->func, reg, &ret);
+			if (ret) {
+				PRINTM(MSG, "SDIO READ ERR\n");
+				goto done;
+			}
+			memory_size |= (read_reg << i * 8);
+			reg++;
+		}
+		if (memory_size == 0) {
+			PRINTM(MSG, "Firmware Dump Finished!\n");
+			break;
+		} else {
+			PRINTM(MSG, "%s_SIZE=0x%x\n",
+			       bt_mem_type_mapping_tbl[idx].mem_name,
+			       memory_size);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr =
+				vmalloc(memory_size + 1);
+			if ((ret != BT_STATUS_SUCCESS) ||
+			    !bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+				PRINTM(ERROR,
+				       "Error: vmalloc %s buffer failed!!!\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name);
+				goto done;
+			}
+			dbg_ptr = bt_mem_type_mapping_tbl[idx].mem_Ptr;
+			end_ptr = dbg_ptr + memory_size;
+		}
+		doneflag = bt_mem_type_mapping_tbl[idx].done_flag;
+		PRINTM(MSG, "Start %s output, please wait...\n",
+		       bt_mem_type_mapping_tbl[idx].mem_name);
+		do {
+			stat = bt_cmd52_rdwr_firmware(priv, 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++) {
+				*dbg_ptr =
+					sdio_readb(((struct sdio_mmc_card *)
+						    priv->bt_dev.card)->func,
+						   reg, &ret);
+				if (ret) {
+					PRINTM(MSG, "SDIO READ ERR\n");
+					goto done;
+				}
+				if (dbg_ptr < end_ptr)
+					dbg_ptr++;
+				else
+					PRINTM(MSG,
+					       "pre-allocced buf is not enough\n");
+			}
+			if (RDWR_STATUS_DONE == stat) {
+				PRINTM(MSG, "%s done:"
+				       "size = 0x%x\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name,
+				       (unsigned int)(dbg_ptr -
+						      bt_mem_type_mapping_tbl
+						      [idx].mem_Ptr));
+				memset(file_name, 0, sizeof(file_name));
+				sprintf((char *)file_name, "%s%s", "file_bt_",
+					bt_mem_type_mapping_tbl[idx].mem_name);
+				if (BT_STATUS_SUCCESS !=
+				    bt_save_dump_info_to_file((char *)path_name,
+							      (char *)file_name,
+							      bt_mem_type_mapping_tbl
+							      [idx].mem_Ptr,
+							      memory_size))
+					PRINTM(MSG,
+					       "Can't save dump file %s in %s\n",
+					       file_name, path_name);
+				vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+				bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+				break;
+			}
+		} while (1);
+	}
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT END ====\n");
+	/* end dump fw memory */
+done:
+	sdio_release_host(((struct sdio_mmc_card *)priv->bt_dev.card)->func);
+	for (idx = 0; idx < dump_num; idx++) {
+		if (bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+			vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+		}
+	}
+	PRINTM(MSG, "==== DEBUG MODE END ====\n");
+	return;
+}
+
+/**
+ *  @brief This function shows debug info for timeout of command sending.
+ *
+ *  @param adapter  A pointer to bt_private
+ *  @param cmd      Timeout command id
+ *
+ *  @return         N/A
+ */
+static void
+bt_cmd_timeout_func(bt_private *priv, u16 cmd)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+
+	adapter->num_cmd_timeout++;
+
+	PRINTM(ERROR, "Version = %s\n", adapter->drv_ver);
+	PRINTM(ERROR, "Timeout Command id = 0x%x\n", cmd);
+	PRINTM(ERROR, "Number of command timeout = %d\n",
+	       adapter->num_cmd_timeout);
+	PRINTM(ERROR, "Interrupt counter = %d\n", adapter->IntCounter);
+	PRINTM(ERROR, "Power Save mode = %d\n", adapter->psmode);
+	PRINTM(ERROR, "Power Save state = %d\n", adapter->ps_state);
+	PRINTM(ERROR, "Host Sleep state = %d\n", adapter->hs_state);
+	PRINTM(ERROR, "hs skip count = %d\n", adapter->hs_skip);
+	PRINTM(ERROR, "suspend_fail flag = %d\n", adapter->suspend_fail);
+	PRINTM(ERROR, "suspended flag = %d\n", adapter->is_suspended);
+	PRINTM(ERROR, "Number of wakeup tries = %d\n", adapter->WakeupTries);
+	PRINTM(ERROR, "Host Cmd complet state = %d\n", adapter->cmd_complete);
+	PRINTM(ERROR, "Last irq recv = %d\n", adapter->irq_recv);
+	PRINTM(ERROR, "Last irq processed = %d\n", adapter->irq_done);
+	PRINTM(ERROR, "tx pending = %d\n", adapter->skb_pending);
+	PRINTM(ERROR, "sdio int status = %d\n", adapter->sd_ireg);
+	bt_dump_sdio_regs(priv);
+	LEAVE();
+}
+
+/**
+ *  @brief This function queue frame
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    N/A
+ */
+static void
+bt_queue_frame(bt_private *priv, struct sk_buff *skb)
+{
+	skb_queue_tail(&priv->adapter->tx_queue, skb);
+}
+
+/**
+ *  @brief This function send reset cmd to firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return	       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_reset_command(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((RESET_OGF << 10) | BT_CMD_RESET);
+	pcmd->length = 0x00;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, 3);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue Reset Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Reset timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_RESET);
+	} else {
+		PRINTM(CMD, "BT: Reset Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends module cfg cmd to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param subcmd  sub command
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_module_cfg_cmd(bt_private *priv, int subcmd)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_MODULE_CFG_REQ);
+	pcmd->length = 1;
+	pcmd->data[0] = subcmd;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue module cfg Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	/*
+	   On some Android platforms certain delay is needed for HCI daemon to
+	   remove this module and close itself gracefully. Otherwise it hangs.
+	   This 10ms delay is a workaround for such platforms as the root cause
+	   has not been found yet. */
+	mdelay(10);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: module_cfg_cmd(%#x): timeout sendcmdflag=%d\n",
+		       subcmd, priv->bt_dev.sendcmdflag);
+		bt_cmd_timeout_func(priv, BT_CMD_MODULE_CFG_REQ);
+	} else {
+		PRINTM(CMD, "BT: module cfg Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables power save mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_ps(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_AUTO_SLEEP_MODE);
+	if (priv->bt_dev.psmode)
+		pcmd->data[0] = BT_PS_ENABLE;
+	else
+		pcmd->data[0] = BT_PS_DISABLE;
+	if (priv->bt_dev.idle_timeout) {
+		pcmd->length = 3;
+		pcmd->data[1] = (u8)(priv->bt_dev.idle_timeout & 0x00ff);
+		pcmd->data[2] = (priv->bt_dev.idle_timeout & 0xff00) >> 8;
+	} else {
+		pcmd->length = 1;
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PSMODE Command(0x%x):%d\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: psmode timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_AUTO_SLEEP_MODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends hscfg command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_hscfg_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_CONFIG);
+	pcmd->length = 2;
+	pcmd->data[0] = (priv->bt_dev.gpio_gap & 0xff00) >> 8;
+	pcmd->data[1] = (u8)(priv->bt_dev.gpio_gap & 0x00ff);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue HSCFG Command(0x%x),gpio=0x%x,gap=0x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0], pcmd->data[1]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: HSCFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_CONFIG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends sdio pull ctrl command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_sdio_pull_ctrl_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_SDIO_PULL_CFG_REQ);
+	pcmd->length = 4;
+	pcmd->data[0] = (priv->bt_dev.sdio_pull_cfg & 0x000000ff);
+	pcmd->data[1] = (priv->bt_dev.sdio_pull_cfg & 0x0000ff00) >> 8;
+	pcmd->data[2] = (priv->bt_dev.sdio_pull_cfg & 0x00ff0000) >> 16;
+	pcmd->data[3] = (priv->bt_dev.sdio_pull_cfg & 0xff000000) >> 24;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD,
+	       "Queue SDIO PULL CFG Command(0x%x), PullUp=0x%x%x,PullDown=0x%x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[1], pcmd->data[0],
+	       pcmd->data[3], pcmd->data[2]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: SDIO PULL CFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SDIO_PULL_CFG_REQ);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends command to configure PMIC
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_pmic_configure(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_PMIC_CONFIGURE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PMIC Configure Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: PMIC Configure timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_PMIC_CONFIGURE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables host sleep
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_hs(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	priv->adapter->suspend_fail = FALSE;
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_ENABLE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	PRINTM(CMD, "Queue hs enable Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->hs_state,
+	     WAIT_UNTIL_HS_STATE_CHANGED)) {
+		PRINTM(MSG, "BT: Enable host sleep timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_ENABLE);
+	}
+	OS_INT_DISABLE;
+	if ((priv->adapter->hs_state == HS_ACTIVATED) ||
+	    (priv->adapter->is_suspended == TRUE)) {
+		OS_INT_RESTORE;
+		PRINTM(MSG, "BT: suspend success! skip=%d\n",
+		       priv->adapter->hs_skip);
+	} else {
+		priv->adapter->suspend_fail = TRUE;
+		OS_INT_RESTORE;
+		priv->adapter->hs_skip++;
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG,
+		       "BT: suspend skipped! "
+		       "state=%d skip=%d ps_state= %d WakeupTries=%d\n",
+		       priv->adapter->hs_state, priv->adapter->hs_skip,
+		       priv->adapter->ps_state, priv->adapter->WakeupTries);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Set Evt Filter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_evt_filter(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_SET_EVT_FILTER);
+	pcmd->length = 0x03;
+	pcmd->data[0] = 0x02;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Set Evt Filter Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set Evt Filter timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SET_EVT_FILTER);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Write Scan - Page and Inquiry
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_write_scan(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_ENABLE_WRITE_SCAN);
+	pcmd->length = 0x01;
+	pcmd->data[0] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Enable Write Scan Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Write Scan timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_WRITE_SCAN);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Device under test mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_device_under_testmode(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((0x06 << 10) | BT_CMD_ENABLE_DEVICE_TESTMODE);
+	pcmd->length = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue enable device under testmode Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Device under TEST mode timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_DEVICE_TESTMODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables test mode and send cmd
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_test_mode(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	/** Set Evt Filter Command */
+	ret = bt_set_evt_filter(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Set Evt filter fail\n");
+		goto exit;
+	}
+
+	/** Enable Write Scan Command */
+	ret = bt_enable_write_scan(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Enable Write Scan fail\n");
+		goto exit;
+	}
+
+	/** Enable Device under test mode */
+	ret = bt_enable_device_under_testmode(priv);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(ERROR,
+		       "BT test_mode: Enable device under testmode fail\n");
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function set GPIO pin
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_gpio_pin(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	/**Interrupt falling edge **/
+	u8 gpio_int_edge = INT_FALLING_EDGE;
+	/**Delay 50 usec **/
+	u8 gpio_pulse_width = DELAY_50_US;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_SET_GPIO_PIN);
+	pcmd->data[0] = mbt_gpio_pin;
+	pcmd->data[1] = gpio_int_edge;
+	pcmd->data[2] = gpio_pulse_width;
+	pcmd->length = 3;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set GPIO pin: timeout!\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SET_GPIO_PIN);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+#define DISABLE_RESET  0x0
+#define ENABLE_OUTBAND_RESET 0x1
+#define ENABLE_INBAND_RESET  0x02
+#define DEFAULT_GPIO 0xff
+/**
+ *  @brief This function set GPIO pin
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_independent_reset(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	u8 mode, gpio;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_INDEPENDENT_RESET);
+	mode = btindrst & 0xff;
+	gpio = (btindrst & 0xff00) >> 8;
+	if (mode == ENABLE_OUTBAND_RESET) {
+		pcmd->data[0] = ENABLE_OUTBAND_RESET;
+		if (!gpio)
+			pcmd->data[1] = DEFAULT_GPIO;
+		else
+			pcmd->data[1] = gpio;
+	} else if (mode == ENABLE_INBAND_RESET) {
+		pcmd->data[0] = ENABLE_INBAND_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else if (mode == DISABLE_RESET) {
+		pcmd->data[0] = DISABLE_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else {
+		PRINTM(WARN, "Unsupport mode\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	PRINTM(CMD, "BT: independant reset mode=%d gpio=%d\n", mode, gpio);
+	pcmd->length = 2;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Independent reset : timeout!\n");
+		bt_cmd_timeout_func(priv, BT_CMD_INDEPENDENT_RESET);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets ble deepsleep mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mode    TRUE/FALSE
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_ble_deepsleep(bt_private *priv, int mode)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_BLE_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_BLE_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_BLE_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_BLE_DEEP_SLEEP);
+	pcmd->length = 1;
+	pcmd->deepsleep = mode;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_BLE_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set BLE deepsleep = %d (0x%x)\n", mode,
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set BLE deepsleep timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_BLE_DEEP_SLEEP);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets FW version
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_get_fw_version(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_GET_FW_VERSION);
+	pcmd->length = 0x01;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, 4);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Get FW version: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_GET_FW_VERSION);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets mac address
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_mac_address(bt_private *priv, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	int i = 0;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CONFIG_MAC_ADDR);
+	pcmd->length = 8;
+	pcmd->cmd_type = MRVL_VENDOR_PKT;
+	pcmd->cmd_len = 6;
+	for (i = 0; i < 6; i++)
+		pcmd->data[i] = mac[5 - i];
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_HCI_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set mac addr " MACSTR " (0x%x)\n", MAC2STR(mac),
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set mac addr: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CONFIG_MAC_ADDR);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	int i = 0;
+	/* u8 config_data[28] = {0x37 0x01 0x1c 0x00 0xFF 0xFF 0xFF 0xFF 0x01
+	   0x7f 0x04 0x02 0x00 0x00 0xBA 0xCE 0xC0 0xC6 0x2D 0x00 0x00 0x00
+	   0x00 0x00 0x00 0x00 0xF0}; */
+
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA);
+	pcmd->length = 0x20;
+	pcmd->data[0] = 0x00;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x00;
+	pcmd->data[3] = 0x1C;
+	/* swip cal-data byte */
+	for (i = 4; i < 32; i++)
+		pcmd->data[i] = *(config_data + ((i / 4) * 8 - 1 - i));
+	if (mac != NULL) {
+		pcmd->data[2] = 0x01;	/* skip checksum */
+		for (i = 24; i < 30; i++)
+			pcmd->data[i] = mac[29 - i];
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate data: ", pcmd->data, 32);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate EXT data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA_EXT);
+	pcmd->length = cfg_data_len;
+
+	memcpy(pcmd->data, config_data, cfg_data_len);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate ext data", pcmd->data, pcmd->length);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate ext data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA_EXT);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function writes value to CSU registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param type    reg type
+ *  @param offset  register address
+ *  @param value   register value to write
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CSU_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CSU_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CSU_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CSU_WRITE_REG);
+	pcmd->length = 7;
+	pcmd->type = type;
+	pcmd->offset[0] = (offset & 0x000000ff);
+	pcmd->offset[1] = (offset & 0x0000ff00) >> 8;
+	pcmd->offset[2] = (offset & 0x00ff0000) >> 16;
+	pcmd->offset[3] = (offset & 0xff000000) >> 24;
+	pcmd->value[0] = (value & 0x00ff);
+	pcmd->value[1] = (value & 0xff00) >> 8;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_CSU_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set CSU reg type=%d reg=0x%x value=0x%x\n",
+	       type, offset, value);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Set CSU reg timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CSU_WRITE_REG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function used to restore tx_queue
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        N/A
+ */
+void
+bt_restore_tx_queue(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	while (!skb_queue_empty(&priv->adapter->pending_queue)) {
+		skb = skb_dequeue(&priv->adapter->pending_queue);
+		if (skb)
+			bt_queue_frame(priv, skb);
+	}
+	wake_up_interruptible(&priv->MainThread.waitQ);
+}
+
+/**
+ *  @brief This function used to send command to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_prepare_command(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (priv->bt_dev.hscfgcmd) {
+		priv->bt_dev.hscfgcmd = 0;
+		ret = bt_send_hscfg_cmd(priv);
+	}
+	if (priv->bt_dev.pscmd) {
+		priv->bt_dev.pscmd = 0;
+		ret = bt_enable_ps(priv);
+	}
+	if (priv->bt_dev.sdio_pull_ctrl) {
+		priv->bt_dev.sdio_pull_ctrl = 0;
+		ret = bt_send_sdio_pull_ctrl_cmd(priv);
+	}
+	if (priv->bt_dev.hscmd) {
+		priv->bt_dev.hscmd = 0;
+		if (priv->bt_dev.hsmode)
+			ret = bt_enable_hs(priv);
+		else {
+			ret = sbi_wakeup_firmware(priv);
+			priv->adapter->hs_state = HS_DEACTIVATED;
+		}
+	}
+	if (priv->bt_dev.test_mode) {
+		priv->bt_dev.test_mode = 0;
+		ret = bt_enable_test_mode(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function processes a single packet
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to skb which includes TX packet
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+send_single_packet(bt_private *priv, struct sk_buff *skb)
+{
+	int ret;
+	struct sk_buff *new_skb = NULL;
+	ENTER();
+	if (!skb || !skb->data) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	if (!skb->len || ((skb->len + BT_HEADER_LEN) > BT_UPLD_SIZE)) {
+		PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
+		       BT_UPLD_SIZE);
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	if (skb_headroom(skb) < BT_HEADER_LEN) {
+		new_skb = skb_realloc_headroom(skb, BT_HEADER_LEN);
+		if (!new_skb) {
+			PRINTM(ERROR, "TX error: realloc_headroom failed %d\n",
+			       BT_HEADER_LEN);
+			kfree_skb(skb);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		} else {
+			if (new_skb != skb)
+				dev_kfree_skb_any(skb);
+			skb = new_skb;
+		}
+	}
+	/* This is SDIO/PCIE specific header length: byte[3][2][1], * type:
+	   byte[0] (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor)
+	 */
+	skb_push(skb, BT_HEADER_LEN);
+	skb->data[0] = (skb->len & 0x0000ff);
+	skb->data[1] = (skb->len & 0x00ff00) >> 8;
+	skb->data[2] = (skb->len & 0xff0000) >> 16;
+	skb->data[3] = bt_cb(skb)->pkt_type;
+	if (bt_cb(skb)->pkt_type == MRVL_VENDOR_PKT)
+		PRINTM(CMD, "DNLD_CMD: ocf_ogf=0x%x len=%d\n",
+		       __le16_to_cpu(*((u16 *) & skb->data[4])), skb->len);
+	ret = sbi_host_to_card(priv, skb->data, skb->len);
+	if (ret == BT_STATUS_FAILURE)
+		((struct m_dev *)skb->dev)->stat.err_tx++;
+	else
+		((struct m_dev *)skb->dev)->stat.byte_tx += skb->len;
+	if (ret != BT_STATUS_PENDING)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+#ifdef CONFIG_OF
+/**
+ *  @brief This function read the initial parameter from device tress
+ *
+ *
+ *  @return         N/A
+ */
+static void
+bt_init_from_dev_tree(void)
+{
+	struct device_node *dt_node = NULL;
+	struct property *prop;
+	u32 data;
+	const char *string_data;
+
+	ENTER();
+
+	if (!dts_enable) {
+		PRINTM(CMD, "DTS is disabled!");
+		return;
+	}
+
+	dt_node = of_find_node_by_name(NULL, "sd8xxx-bt");
+	if (!dt_node) {
+		LEAVE();
+		return;
+	}
+	for_each_property_of_node(dt_node, prop) {
+#ifdef DEBUG_LEVEL1
+		if (!strncmp(prop->name, "mbt_drvdbg", strlen("mbt_drvdbg"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(CMD, "mbt_drvdbg=0x%x\n", data);
+				mbt_drvdbg = data;
+			}
+		}
+#endif
+		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(CMD, "init_cfg=%s\n", init_cfg);
+			}
+		} else if (!strncmp
+			   (prop->name, "cal_cfg_ext", strlen("cal_cfg_ext"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg_ext = (char *)string_data;
+				PRINTM(CMD, "cal_cfg_ext=%s\n", cal_cfg_ext);
+			}
+		} else if (!strncmp(prop->name, "cal_cfg", strlen("cal_cfg"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg = (char *)string_data;
+				PRINTM(CMD, "cal_cfg=%s\n", cal_cfg);
+			}
+		} else if (!strncmp(prop->name, "bt_mac", strlen("bt_mac"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				bt_mac = (char *)string_data;
+				PRINTM(CMD, "bt_mac=%s\n", bt_mac);
+			}
+		} else if (!strncmp
+			   (prop->name, "mbt_gpio_pin",
+			    strlen("mbt_gpio_pin"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				mbt_gpio_pin = data;
+				PRINTM(CMD, "mbt_gpio_pin=%d\n", mbt_gpio_pin);
+			}
+		} else if (!strncmp(prop->name, "btindrst", strlen("btindrst"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btindrst = data;
+				PRINTM(CMD, "btindrst=%d\n", btindrst);
+			}
+		} else if (!strncmp(prop->name, "btpmic", strlen("btpmic"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btpmic = data;
+				PRINTM(CMD, "btpmic=%d\n", btpmic);
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function initializes the adapter structure
+ *  and set default value to the member of adapter.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+static void
+bt_init_adapter(bt_private *priv)
+{
+	ENTER();
+#ifdef CONFIG_OF
+	bt_init_from_dev_tree();
+#endif
+	skb_queue_head_init(&priv->adapter->tx_queue);
+	skb_queue_head_init(&priv->adapter->fwdump_queue);
+
+	skb_queue_head_init(&priv->adapter->pending_queue);
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+	priv->adapter->fwdump_fname = NULL;
+	init_waitqueue_head(&priv->adapter->cmd_wait_q);
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (fw == 0) {
+		sbi_enable_host_int(priv);
+		goto done;
+	}
+	sbi_disable_host_int(priv);
+	if ((priv->card_type == CARD_TYPE_SD8787) ||
+	    (priv->card_type == CARD_TYPE_SD8777))
+		priv->fw_crc_check = fw_crc_check;
+	if (sbi_download_fw(priv)) {
+		PRINTM(ERROR, " FW failed to be download!\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#define FW_POLL_TRIES 100
+#define SD8897_FW_RESET_REG  0x0E8
+#define SD8887_FW_RESET_REG  0x0B6
+#define SD8977_SD8997_FW_RESET_REG  0x0EE
+#define SD8887_SD8897_FW_RESET_VAL  1
+#define SD8977_SD8997_FW_RESET_VAL  0x99
+
+/**
+ *  @brief This function reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   FW reload mode
+ *
+ *  @return       0--success, otherwise failure
+ */
+static int
+bt_reload_fw(bt_private *priv, int mode)
+{
+	int ret = 0, tries = 0;
+	u8 value = 1;
+	u32 reset_reg = 0;
+	u8 reset_val = 0;
+
+	ENTER();
+	if ((mode != FW_RELOAD_SDIO_INBAND_RESET) &&
+	    (mode != FW_RELOAD_NO_EMULATION)) {
+		PRINTM(ERROR, "Invalid fw reload mode=%d\n", mode);
+		return -EFAULT;
+	}
+
+    /** flush pending tx_queue */
+	skb_queue_purge(&priv->adapter->tx_queue);
+	if (mode == FW_RELOAD_SDIO_INBAND_RESET) {
+		if (priv->card_type == CARD_TYPE_SD8887) {
+			reset_reg = SD8887_FW_RESET_REG;
+			reset_val = SD8887_SD8897_FW_RESET_VAL;
+		} else if (priv->card_type == CARD_TYPE_SD8897) {
+			reset_reg = SD8897_FW_RESET_REG;
+			reset_val = SD8887_SD8897_FW_RESET_VAL;
+		} else if ((priv->card_type == CARD_TYPE_SD8977) ||
+			   (priv->card_type == CARD_TYPE_SD8997) ||
+			   (priv->card_type == CARD_TYPE_SD8987)) {
+			reset_reg = SD8977_SD8997_FW_RESET_REG;
+			reset_val = SD8977_SD8997_FW_RESET_VAL;
+		}
+		sbi_disable_host_int(priv);
+	    /** Wake up firmware firstly */
+		sbi_wakeup_firmware(priv);
+
+	/** wait SOC fully wake up */
+		for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_write_reg(priv, reset_reg, 0xba);
+			if (!ret) {
+				ret = sd_read_reg(priv, reset_reg, &value);
+				if (!ret && (value == 0xba)) {
+					PRINTM(MSG, "Fw wake up\n");
+					break;
+				}
+			}
+			udelay(1000);
+		}
+
+		ret = sd_write_reg(priv, reset_reg, reset_val);
+		if (ret) {
+			PRINTM(ERROR, "Failed to write register.\n");
+			goto done;
+		}
+
+	    /** Poll register around 1 ms */
+		for (; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_read_reg(priv, reset_reg, &value);
+			if (ret) {
+				PRINTM(ERROR, "Failed to read register.\n");
+				goto done;
+			}
+			if (value == 0)
+			    /** FW is ready */
+				break;
+			udelay(1000);
+		}
+		if (value) {
+			PRINTM(ERROR,
+			       "Failed to poll FW reset register %X=0x%x\n",
+			       reset_reg, value);
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	sbi_enable_host_int(priv);
+	/** reload FW */
+	ret = bt_init_fw(priv);
+	if (ret) {
+		PRINTM(ERROR, "Re download firmware failed.\n");
+		ret = -EFAULT;
+	}
+	LEAVE();
+	return ret;
+done:
+	sbi_enable_host_int(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function request to reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   fw reload mode.
+ *
+ *  @return         N/A
+ */
+void
+bt_request_fw_reload(bt_private *priv, int mode)
+{
+	ENTER();
+	if (mode == FW_RELOAD_WITH_EMULATION) {
+		bt_fw_reload = FW_RELOAD_WITH_EMULATION;
+		PRINTM(MSG, "BT: FW reload with re-emulation...\n");
+		LEAVE();
+		return;
+	}
+	/** Reload FW */
+	priv->fw_reload = TRUE;
+	if (bt_reload_fw(priv, mode)) {
+		PRINTM(ERROR, "FW reload fail\n");
+		goto done;
+	}
+	priv->fw_reload = FALSE;
+	/** Other operation here? */
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function frees the structure of adapter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+void
+bt_free_adapter(bt_private *priv)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	skb_queue_purge(&priv->adapter->fwdump_queue);
+	kfree(adapter->tx_buffer);
+	kfree(adapter->hw_regs_buf);
+	/* Free allocated memory for fwdump filename */
+	if (adapter->fwdump_fname) {
+		kfree(adapter->fwdump_fname);
+		adapter->fwdump_fname = NULL;
+	}
+	/* Free the adapter object itself */
+	kfree(adapter);
+	priv->adapter = NULL;
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the wrapper_dev ioctl
+ *
+ *  @param hev     A pointer to wrapper_dev structure
+ *  @cmd            ioctl cmd
+ *  @arg            argument
+ *  @return    -ENOIOCTLCMD
+ */
+static int
+mdev_ioctl(struct m_dev *m_dev, unsigned int cmd, void *arg)
+{
+	bt_private *priv = NULL;
+	int ret = 0;
+#ifdef BLE_WAKEUP
+	u16 len;
+#endif
+
+	ENTER();
+
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Ioctl for unknown device (m_dev=NULL)\n");
+		ret = -ENODEV;
+		goto done;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "HCI_RUNNING not set, flag=0x%lx\n",
+		       m_dev->flags);
+		ret = -EBUSY;
+		goto done;
+	}
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+#ifdef BLE_WAKEUP
+	case MBTCHAR_IOCTL_BLE_WAKEUP_PARAM:
+		PRINTM(MSG, "BT: Set ble wakeup parameters\n");
+		if (copy_from_user(&len, arg, sizeof(u16))) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Fail to copy ble wakeup params length\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		/** Convert little endian length */
+		len = __le16_to_cpu(len);
+		if (len < 2) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Invalid ble wakeup params len %d\n",
+			       len);
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((len + sizeof(u16)) > priv->ble_wakeup_buf_size) {
+			if (priv->ble_wakeup_buf) {
+				kfree(priv->ble_wakeup_buf);
+				priv->ble_wakeup_buf = NULL;
+				priv->ble_wakeup_buf_size = 0;
+			}
+			priv->ble_wakeup_buf =
+				kzalloc(len + sizeof(u16), GFP_KERNEL);
+			if (!priv->ble_wakeup_buf) {
+				PRINTM(ERROR, "BT_IOCTL: Fail to alloc buffer\t"
+				       "for ble wakeup parameters\n");
+				ret = -ENOMEM;
+				goto done;
+			}
+			priv->ble_wakeup_buf_size = len + sizeof(u16);
+		}
+		if (copy_from_user
+		    (priv->ble_wakeup_buf, arg, len + sizeof(u16))) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Fail to copy ble wakeup params\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		DBG_HEXDUMP(DAT_D, "BLE_WAKEUP_PARAM:", priv->ble_wakeup_buf,
+			    len + sizeof(u16));
+		break;
+#endif
+	default:
+		break;
+	}
+
+done:
+#ifdef BLE_WAKEUP
+	if (ret && priv->ble_wakeup_buf) {
+		kfree(priv->ble_wakeup_buf);
+		priv->ble_wakeup_buf = NULL;
+		priv->ble_wakeup_buf_size = 0;
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles wrapper device destruct
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    N/A
+ */
+static void
+mdev_destruct(struct m_dev *m_dev)
+{
+	ENTER();
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handles the wrapper device transmit
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    BT_STATUS_SUCCESS or other error no.
+ */
+static int
+mdev_send_frame(struct m_dev *m_dev, struct sk_buff *skb)
+{
+	bt_private *priv = NULL;
+
+	ENTER();
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Frame for unknown HCI device (m_dev=NULL)\n");
+		LEAVE();
+		return -ENODEV;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "Fail test HCI_RUNNING, flag=0x%lx\n",
+		       m_dev->flags);
+		LEAVE();
+		return -EBUSY;
+	}
+	switch (bt_cb(skb)->pkt_type) {
+	case HCI_COMMAND_PKT:
+		m_dev->stat.cmd_tx++;
+		break;
+	case HCI_ACLDATA_PKT:
+		m_dev->stat.acl_tx++;
+		break;
+	case HCI_SCODATA_PKT:
+		m_dev->stat.sco_tx++;
+		break;
+	}
+
+	if (m_dev->dev_type == DEBUG_TYPE) {
+		/* remember the ogf_ocf */
+		priv->debug_device_pending = 1;
+		priv->debug_ocf_ogf[0] = skb->data[0];
+		priv->debug_ocf_ogf[1] = skb->data[1];
+		PRINTM(CMD, "debug_ocf_ogf[0]=0x%x debug_ocf_ogf[1]=0x%x\n",
+		       priv->debug_ocf_ogf[0], priv->debug_ocf_ogf[1]);
+	}
+
+	if (priv->adapter->tx_lock == TRUE)
+		skb_queue_tail(&priv->adapter->pending_queue, skb);
+	else
+		bt_queue_frame(priv, skb);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function flushes the transmit queue
+ *
+ *  @param m_dev     A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_flush(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	skb_queue_purge(&priv->adapter->pending_queue);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function closes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_close(struct m_dev *m_dev)
+{
+
+	ENTER();
+	mdev_req_lock(m_dev);
+	if (!test_and_clear_bit(HCI_UP, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+
+	if (m_dev->flush)
+		m_dev->flush(m_dev);
+	/* wait up pending read and unregister char dev */
+	wake_up_interruptible(&m_dev->req_wait_q);
+	/* Drop queues */
+	skb_queue_purge(&m_dev->rx_q);
+	if (!test_and_clear_bit(HCI_RUNNING, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+	module_put(THIS_MODULE);
+	m_dev->flags = 0;
+	mdev_req_unlock(m_dev);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function opens the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+static int
+mdev_open(struct m_dev *m_dev)
+{
+	ENTER();
+
+	if (try_module_get(THIS_MODULE) == 0)
+		return BT_STATUS_FAILURE;
+
+	set_bit(HCI_RUNNING, &m_dev->flags);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function queries the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param arg     arguement
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+mdev_query(struct m_dev *m_dev, void *arg)
+{
+	struct mbt_dev *mbt_dev = (struct mbt_dev *)m_dev->dev_pointer;
+
+	ENTER();
+	if (copy_to_user(arg, &mbt_dev->type, sizeof(mbt_dev->type)))
+		PRINTM(ERROR, "IOCTL_QUERY_TYPE: Fail copy to user\n");
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+init_m_dev(struct m_dev *m_dev)
+{
+	m_dev->dev_pointer = NULL;
+	m_dev->driver_data = NULL;
+	m_dev->dev_type = 0;
+	m_dev->spec_type = 0;
+	skb_queue_head_init(&m_dev->rx_q);
+	init_waitqueue_head(&m_dev->req_wait_q);
+	init_waitqueue_head(&m_dev->rx_wait_q);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+	init_MUTEX(&m_dev->req_lock);
+#else
+	sema_init(&m_dev->req_lock, 1);
+#endif
+	spin_lock_init(&m_dev->rxlock);
+	memset(&m_dev->stat, 0, sizeof(struct hci_dev_stats));
+	m_dev->open = mdev_open;
+	m_dev->close = mdev_close;
+	m_dev->flush = mdev_flush;
+	m_dev->send = mdev_send_frame;
+	m_dev->destruct = mdev_destruct;
+	m_dev->ioctl = mdev_ioctl;
+	m_dev->query = mdev_query;
+	m_dev->owner = THIS_MODULE;
+
+}
+
+/**
+ *  @brief This function handles the major job in bluetooth driver.
+ *  it handles the event generated by firmware, rx data received
+ *  from firmware and tx data sent from kernel.
+ *
+ *  @param data    A pointer to bt_thread structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+static int
+bt_service_main_thread(void *data)
+{
+	bt_thread *thread = data;
+	bt_private *priv = thread->priv;
+	bt_adapter *adapter = priv->adapter;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
+	wait_queue_t wait;
+#else
+	wait_queue_entry_t wait;
+#endif
+	struct sk_buff *skb;
+	ENTER();
+	bt_activate_thread(thread);
+	init_waitqueue_entry(&wait, current);
+	current->flags |= PF_NOFREEZE;
+
+	for (;;) {
+		add_wait_queue(&thread->waitQ, &wait);
+		OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE);
+		if (priv->adapter->WakeupTries ||
+		    ((!priv->adapter->IntCounter) &&
+		     (!priv->bt_dev.tx_dnld_rdy ||
+		      skb_queue_empty(&priv->adapter->tx_queue))
+		     && skb_queue_empty(&priv->adapter->fwdump_queue)
+		    )) {
+			PRINTM(INFO, "Main: Thread sleeping...\n");
+			schedule();
+		}
+		OS_SET_THREAD_STATE(TASK_RUNNING);
+		remove_wait_queue(&thread->waitQ, &wait);
+		if (kthread_should_stop() || adapter->SurpriseRemoved) {
+			PRINTM(INFO, "main-thread: break from main thread: "
+			       "SurpriseRemoved=0x%x\n",
+			       adapter->SurpriseRemoved);
+			break;
+		}
+
+		PRINTM(INFO, "Main: Thread waking up...\n");
+
+		if (priv->adapter->IntCounter) {
+			OS_INT_DISABLE;
+			adapter->IntCounter = 0;
+			OS_INT_RESTORE;
+			sbi_get_int_status(priv);
+		} else if ((priv->adapter->ps_state == PS_SLEEP) &&
+			   !skb_queue_empty(&priv->adapter->tx_queue)) {
+			priv->adapter->WakeupTries++;
+			sbi_wakeup_firmware(priv);
+			continue;
+		}
+		if (priv->adapter->ps_state == PS_SLEEP)
+			continue;
+		if (priv->bt_dev.tx_dnld_rdy == TRUE) {
+			if (!skb_queue_empty(&priv->adapter->tx_queue)) {
+				skb = skb_dequeue(&priv->adapter->tx_queue);
+				if (skb)
+					send_single_packet(priv, skb);
+			}
+		}
+		if (!skb_queue_empty(&priv->adapter->fwdump_queue)) {
+			skb = skb_dequeue(&priv->adapter->fwdump_queue);
+			if (skb) {
+				bt_store_firmware_dump(priv, skb->data,
+						       skb->len);
+				dev_kfree_skb_any(skb);
+			}
+		}
+	}
+	bt_deactivate_thread(thread);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the interrupt. it will change PS
+ *  state if applicable. it will wake up main_thread to handle
+ *  the interrupt event as well.
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @return        N/A
+ */
+void
+bt_interrupt(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	if (!priv || !priv->adapter) {
+		LEAVE();
+		return;
+	}
+	PRINTM(INTR, "*\n");
+	priv->adapter->ps_state = PS_AWAKE;
+	if (priv->adapter->hs_state == HS_ACTIVATED) {
+		PRINTM(CMD, "BT: %s: HS DEACTIVATED in ISR!\n", m_dev->name);
+		priv->adapter->hs_state = HS_DEACTIVATED;
+	}
+	priv->adapter->WakeupTries = 0;
+	priv->adapter->IntCounter++;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	LEAVE();
+}
+
+/**
+ * @brief  Dynamic release of char dev
+ *
+ * @param kobj          A pointer to kobject structure
+ *
+ * @return                N/A
+ */
+static void
+char_dev_release_dynamic(struct kobject *kobj)
+{
+	struct char_dev *cdev = container_of(kobj, struct char_dev, kobj);
+	ENTER();
+	PRINTM(INFO, "free char_dev\n");
+	kfree(cdev);
+	LEAVE();
+}
+
+static struct kobj_type ktype_char_dev_dynamic = {
+	.release = char_dev_release_dynamic,
+};
+
+/**
+ * @brief  Allocation of char dev
+ *
+ * @param           	N/A
+ *
+ * @return              char_dev
+ */
+static struct char_dev *
+alloc_char_dev(void)
+{
+	struct char_dev *cdev;
+	ENTER();
+	cdev = kzalloc(sizeof(struct char_dev), GFP_KERNEL);
+	if (cdev) {
+		kobject_init(&cdev->kobj, &ktype_char_dev_dynamic);
+		PRINTM(INFO, "alloc char_dev\n");
+	}
+	return cdev;
+}
+
+/**
+ * @brief  Dynamic release of bt private
+ *
+ * @param kobj          A pointer to kobject structure
+ *
+ * @return                N/A
+ */
+static void
+bt_private_dynamic_release(struct kobject *kobj)
+{
+	bt_private *priv = container_of(kobj, bt_private, kobj);
+	ENTER();
+	PRINTM(INFO, "free bt priv\n");
+	kfree(priv);
+	LEAVE();
+}
+
+static struct kobj_type ktype_bt_private_dynamic = {
+	.release = bt_private_dynamic_release,
+};
+
+/**
+ * @brief  Allocation of bt private
+ *
+ * @param           	N/A
+ *
+ * @return              bt_private
+ */
+static bt_private *
+bt_alloc_priv(void)
+{
+	bt_private *priv;
+	ENTER();
+	priv = kzalloc(sizeof(bt_private), GFP_KERNEL);
+	if (priv) {
+		kobject_init(&priv->kobj, &ktype_bt_private_dynamic);
+		PRINTM(INFO, "alloc bt priv\n");
+	}
+	LEAVE();
+	return priv;
+}
+
+/**
+ * @brief  Get bt private structure
+ *
+ * @param priv          A pointer to bt_private structure
+ *
+ * @return              kobject structure
+ */
+struct kobject *
+bt_priv_get(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv get object");
+	return kobject_get(&priv->kobj);
+}
+
+/**
+ * @brief  Get bt private structure
+ *
+ * @param priv          A pointer to bt_private structure
+ *
+ * @return              N/A
+ */
+void
+bt_priv_put(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv put object");
+	kobject_put(&priv->kobj);
+}
+
+/**
+ *  @brief This function send init commands to firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_init_cmd(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (mbt_gpio_pin) {
+		ret = bt_set_gpio_pin(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "GPIO pin set failed!\n");
+			goto done;
+		}
+	}
+	ret = bt_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+	if (ret < 0) {
+		PRINTM(FATAL, "Module cfg command send failed!\n");
+		goto done;
+	}
+	if (btindrst != -1) {
+		ret = bt_set_independent_reset(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Independent reset failed!\n");
+			goto done;
+		}
+	}
+	if (btpmic
+	    && ((priv->card_type == CARD_TYPE_SD8997) ||
+		(priv->card_type == CARD_TYPE_SD8977))
+		) {
+		if (BT_STATUS_SUCCESS != bt_pmic_configure(priv)) {
+			PRINTM(FATAL, "BT: PMIC Configure failed \n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	ret = bt_set_ble_deepsleep(priv, deep_sleep ? TRUE : FALSE);
+	if (ret < 0) {
+		PRINTM(FATAL, "%s BLE deepsleep failed!\n",
+		       deep_sleep ? "Enable" : "Disable");
+		goto done;
+	}
+	if (psmode) {
+		priv->bt_dev.psmode = TRUE;
+		priv->bt_dev.idle_timeout = DEFAULT_IDLE_TIME;
+		ret = bt_enable_ps(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Enable PS mode failed!\n");
+			goto done;
+		}
+	}
+#if defined(SDIO_SUSPEND_RESUME)
+	priv->bt_dev.gpio_gap = DEF_GPIO_GAP;
+	ret = bt_send_hscfg_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "Send HSCFG failed!\n");
+		goto done;
+	}
+#endif
+	priv->bt_dev.sdio_pull_cfg = 0xffffffff;
+	priv->bt_dev.sdio_pull_ctrl = 0;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reinit firmware after redownload firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_reinit_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+	/* block all the packet from bluez */
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext)
+		priv->adapter->tx_lock = TRUE;
+
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext) {
+		priv->adapter->tx_lock = FALSE;
+		bt_restore_tx_queue(priv);
+	}
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+done:
+	return ret;
+}
+
+/**
+ *  @brief Module configuration and register device
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @return      BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_conf_dpc(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct mbt_dev *mbt_dev = NULL;
+	struct nfc_dev *nfc_dev = NULL;
+	struct debug_dev *debug_dev = NULL;
+	int i = 0;
+	struct char_dev *char_dev = NULL;
+	char dev_file[DEV_NAME_LEN + 5];
+	unsigned char dev_type = 0;
+
+	ENTER();
+
+	priv->bt_dev.tx_dnld_rdy = TRUE;
+	if (priv->fw_reload) {
+		bt_reinit_fw(priv);
+		LEAVE();
+		return ret;
+	}
+
+	if (drv_mode & DRV_MODE_BT) {
+		mbt_dev = alloc_mbt_dev();
+		if (!mbt_dev) {
+			PRINTM(FATAL, "Can not allocate mbt dev\n");
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		init_m_dev(&(priv->bt_dev.m_dev[BT_SEQ]));
+		priv->bt_dev.m_dev[BT_SEQ].dev_type = BT_TYPE;
+		priv->bt_dev.m_dev[BT_SEQ].spec_type = IANYWHERE_SPEC;
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = (void *)mbt_dev;
+		priv->bt_dev.m_dev[BT_SEQ].driver_data = priv;
+		priv->bt_dev.m_dev[BT_SEQ].read_continue_flag = 0;
+	}
+
+	dev_type = HCI_SDIO;
+
+	if (mbt_dev)
+		mbt_dev->type = dev_type;
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+
+	if (mbt_dev && priv->bt_dev.devType == DEV_TYPE_AMP) {
+		mbt_dev->type |= HCI_BT_AMP;
+		priv->bt_dev.m_dev[BT_SEQ].dev_type = BT_AMP_TYPE;
+	}
+	/** Process device tree init parameters before register hci device.
+	 *  Since uplayer device has not yet registered, no need to block tx queue.
+	 * */
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	} else if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Get FW version */
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+
+	if (mbt_dev) {
+		/** init mbt_dev */
+		mbt_dev->flags = 0;
+		mbt_dev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
+		mbt_dev->esco_type = (ESCO_HV1);
+		mbt_dev->link_mode = (HCI_LM_ACCEPT);
+
+		mbt_dev->idle_timeout = 0;
+		mbt_dev->sniff_max_interval = 800;
+		mbt_dev->sniff_min_interval = 80;
+		for (i = 0; i < 3; i++)
+			mbt_dev->reassembly[i] = NULL;
+		atomic_set(&mbt_dev->promisc, 0);
+
+		/** alloc char dev node */
+		char_dev = alloc_char_dev();
+		if (!char_dev) {
+			class_destroy(chardev_class);
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		char_dev->minor = MBTCHAR_MINOR_BASE + mbtchar_minor;
+		if (mbt_dev->type & HCI_BT_AMP)
+			char_dev->dev_type = BT_AMP_TYPE;
+		else
+			char_dev->dev_type = BT_TYPE;
+
+		if (bt_name)
+			snprintf(mbt_dev->name, sizeof(mbt_dev->name), "%s%d",
+				 bt_name, mbtchar_minor);
+		else
+			snprintf(mbt_dev->name, sizeof(mbt_dev->name),
+				 "mbtchar%d", mbtchar_minor);
+		snprintf(dev_file, sizeof(dev_file), "/dev/%s", mbt_dev->name);
+		mbtchar_minor++;
+		PRINTM(MSG, "BT: Create %s\n", dev_file);
+
+		/** register m_dev to BT char device */
+		priv->bt_dev.m_dev[BT_SEQ].index = char_dev->minor;
+		char_dev->m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+
+		/** create BT char device node */
+		register_char_dev(char_dev, chardev_class, MODULE_NAME,
+				  mbt_dev->name);
+
+		/** chmod & chown for BT char device */
+		mbtchar_chown(dev_file, AID_SYSTEM, AID_NET_BT_STACK);
+		mbtchar_chmod(dev_file, 0666);
+
+		/** create proc device */
+		snprintf(priv->bt_dev.m_dev[BT_SEQ].name,
+			 sizeof(priv->bt_dev.m_dev[BT_SEQ].name),
+			 mbt_dev->name);
+		bt_proc_init(priv, &(priv->bt_dev.m_dev[BT_SEQ]), BT_SEQ);
+	}
+
+	if ((drv_mode & DRV_MODE_NFC) &&
+	    (!(priv->bt_dev.devType == DEV_TYPE_AMP)) &&
+	    (priv->bt_dev.devFeature & DEV_FEATURE_NFC)) {
+
+		/** alloc nfc_dev */
+		nfc_dev = alloc_nfc_dev();
+		if (!nfc_dev) {
+			PRINTM(FATAL, "Can not allocate nfc dev\n");
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+
+		/** init m_dev */
+		init_m_dev(&(priv->bt_dev.m_dev[NFC_SEQ]));
+		priv->bt_dev.m_dev[NFC_SEQ].dev_type = NFC_TYPE;
+		priv->bt_dev.m_dev[NFC_SEQ].spec_type = GENERIC_SPEC;
+		priv->bt_dev.m_dev[NFC_SEQ].dev_pointer = (void *)nfc_dev;
+		priv->bt_dev.m_dev[NFC_SEQ].driver_data = priv;
+		priv->bt_dev.m_dev[NFC_SEQ].read_continue_flag = 0;
+
+		/** create char device for NFC */
+		char_dev = alloc_char_dev();
+		if (!char_dev) {
+			class_destroy(chardev_class);
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		char_dev->minor = NFCCHAR_MINOR_BASE + nfcchar_minor;
+		char_dev->dev_type = NFC_TYPE;
+		if (nfc_name)
+			snprintf(nfc_dev->name, sizeof(nfc_dev->name), "%s%d",
+				 nfc_name, nfcchar_minor);
+		else
+			snprintf(nfc_dev->name, sizeof(nfc_dev->name),
+				 "mnfcchar%d", nfcchar_minor);
+		snprintf(dev_file, sizeof(dev_file), "/dev/%s", nfc_dev->name);
+		PRINTM(MSG, "BT: Create %s\n", dev_file);
+		nfcchar_minor++;
+
+		/** register m_dev to NFC char device */
+		priv->bt_dev.m_dev[NFC_SEQ].index = char_dev->minor;
+		char_dev->m_dev = &(priv->bt_dev.m_dev[NFC_SEQ]);
+
+		/** register char dev */
+		register_char_dev(char_dev, chardev_class, MODULE_NAME,
+				  nfc_dev->name);
+
+		/** chmod for NFC char device */
+		mbtchar_chmod(dev_file, 0666);
+
+		/** create proc device */
+		snprintf(priv->bt_dev.m_dev[NFC_SEQ].name,
+			 sizeof(priv->bt_dev.m_dev[NFC_SEQ].name),
+			 nfc_dev->name);
+		bt_proc_init(priv, &(priv->bt_dev.m_dev[NFC_SEQ]), NFC_SEQ);
+	}
+
+	if ((debug_intf) && ((drv_mode & DRV_MODE_BT)
+			     || (drv_mode & DRV_MODE_NFC)
+	    )) {
+		/** alloc debug_dev */
+		debug_dev = alloc_debug_dev();
+		if (!debug_dev) {
+			PRINTM(FATAL, "Can not allocate debug dev\n");
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+
+		/** init m_dev */
+		init_m_dev(&(priv->bt_dev.m_dev[DEBUG_SEQ]));
+		priv->bt_dev.m_dev[DEBUG_SEQ].dev_type = DEBUG_TYPE;
+		priv->bt_dev.m_dev[DEBUG_SEQ].spec_type = GENERIC_SPEC;
+		priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer = (void *)debug_dev;
+		priv->bt_dev.m_dev[DEBUG_SEQ].driver_data = priv;
+
+		/** create char device for Debug */
+		char_dev = alloc_char_dev();
+		if (!char_dev) {
+			class_destroy(chardev_class);
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		char_dev->minor = DEBUGCHAR_MINOR_BASE + debugchar_minor;
+		char_dev->dev_type = DEBUG_TYPE;
+		if (debug_name)
+			snprintf(debug_dev->name, sizeof(debug_dev->name),
+				 "%s%d", debug_name, debugchar_minor);
+		else
+			snprintf(debug_dev->name, sizeof(debug_dev->name),
+				 "mdebugchar%d", debugchar_minor);
+		snprintf(dev_file, sizeof(dev_file), "/dev/%s",
+			 debug_dev->name);
+		PRINTM(MSG, "BT: Create %s\n", dev_file);
+		debugchar_minor++;
+
+		/** register char dev */
+		priv->bt_dev.m_dev[DEBUG_SEQ].index = char_dev->minor;
+		char_dev->m_dev = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
+		register_char_dev(char_dev, chardev_class, MODULE_NAME,
+				  debug_dev->name);
+
+		/** chmod for debug char device */
+		mbtchar_chmod(dev_file, 0666);
+
+		/** create proc device */
+		snprintf(priv->bt_dev.m_dev[DEBUG_SEQ].name,
+			 sizeof(priv->bt_dev.m_dev[DEBUG_SEQ].name),
+			 debug_dev->name);
+		bt_proc_init(priv, &(priv->bt_dev.m_dev[DEBUG_SEQ]), DEBUG_SEQ);
+	}
+
+done:
+	LEAVE();
+	return ret;
+err_kmalloc:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function adds the card. it will probe the
+ *  card, allocate the bt_priv and initialize the device.
+ *
+ *  @param card    A pointer to card
+ *  @return        A pointer to bt_private structure
+ */
+
+bt_private *
+bt_add_card(void *card)
+{
+	bt_private *priv = NULL;
+	int index = 0;
+
+	ENTER();
+
+	priv = bt_alloc_priv();
+	if (!priv) {
+		PRINTM(FATAL, "Can not allocate priv\n");
+		LEAVE();
+		return NULL;
+	}
+	/* Save the handle */
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == NULL)
+			break;
+	}
+	if (index < MAX_BT_ADAPTER) {
+		m_priv[index] = priv;
+	} else {
+		PRINTM(ERROR, "Exceeded maximum cards supported!\n");
+		goto err_kmalloc;
+	}
+	/* allocate buffer for bt_adapter */
+	priv->adapter = kzalloc(sizeof(bt_adapter), GFP_KERNEL);
+	if (!priv->adapter) {
+		PRINTM(FATAL, "Allocate buffer for bt_adapter failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buffer =
+		kzalloc(MAX_TX_BUF_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->tx_buffer) {
+		PRINTM(FATAL, "Allocate buffer for transmit\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buf =
+		(u8 *)ALIGN_ADDR(priv->adapter->tx_buffer, DMA_ALIGNMENT);
+	priv->adapter->hw_regs_buf =
+		kzalloc(SD_BLOCK_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->hw_regs_buf) {
+		PRINTM(FATAL, "Allocate buffer for INT read buf failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->hw_regs =
+		(u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf, DMA_ALIGNMENT);
+	bt_init_adapter(priv);
+
+	PRINTM(INFO, "Starting kthread...\n");
+	priv->MainThread.priv = priv;
+	spin_lock_init(&priv->driver_lock);
+
+	bt_create_thread(bt_service_main_thread, &priv->MainThread,
+			 "bt_main_service");
+
+	/* wait for mainthread to up */
+	while (!priv->MainThread.pid)
+		os_sched_timeout(1);
+
+	sdio_update_card_type(priv, card);
+	/* Update driver version */
+	if (priv->card_type == CARD_TYPE_SD8787)
+		memcpy(mbt_driver_version, CARD_SD8787, strlen(CARD_SD8787));
+	else if (priv->card_type == CARD_TYPE_SD8777)
+		memcpy(mbt_driver_version, CARD_SD8777, strlen(CARD_SD8777));
+	else if (priv->card_type == CARD_TYPE_SD8887)
+		memcpy(mbt_driver_version, CARD_SD8887, strlen(CARD_SD8887));
+	else if (priv->card_type == CARD_TYPE_SD8897)
+		memcpy(mbt_driver_version, CARD_SD8897, strlen(CARD_SD8897));
+	else if (priv->card_type == CARD_TYPE_SD8797)
+		memcpy(mbt_driver_version, CARD_SD8797, strlen(CARD_SD8797));
+	else if (priv->card_type == CARD_TYPE_SD8977)
+		memcpy(mbt_driver_version, CARD_SD8977, strlen(CARD_SD8977));
+	else if (priv->card_type == CARD_TYPE_SD8997)
+		memcpy(mbt_driver_version, CARD_SD8997, strlen(CARD_SD8997));
+	else if (priv->card_type == CARD_TYPE_SD8987)
+		memcpy(mbt_driver_version, CARD_SD8987, strlen(CARD_SD8987));
+
+	if (BT_STATUS_SUCCESS != sdio_get_sdio_device(priv))
+		goto err_kmalloc;
+
+	/** user config file */
+	init_waitqueue_head(&priv->init_user_conf_wait_q);
+
+	priv->bt_dev.card = card;
+
+	((struct sdio_mmc_card *)card)->priv = priv;
+	priv->adapter->sd_ireg = 0;
+	/*
+	 * Register the device. Fillup the private data structure with
+	 * relevant information from the card and request for the required
+	 * IRQ.
+	 */
+	if (sbi_register_dev(priv) < 0) {
+		PRINTM(FATAL, "Failed to register bt device!\n");
+		goto err_registerdev;
+	}
+	if (bt_init_fw(priv)) {
+		PRINTM(FATAL, "BT Firmware Init Failed\n");
+		goto err_init_fw;
+	}
+	LEAVE();
+	return priv;
+
+err_init_fw:
+	clean_up_m_devs(priv);
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+err_registerdev:
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+err_kmalloc:
+	if (priv->adapter)
+		bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function send hardware remove event
+ *
+ *  @param priv    A pointer to bt_private
+ *  @return        N/A
+ */
+void
+bt_send_hw_remove_event(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+	ENTER();
+	if (!priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		LEAVE();
+		return;
+	}
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+#define HCI_HARDWARE_ERROR_EVT  0x10
+#define HCI_HARDWARE_REMOVE     0x24
+	skb = bt_skb_alloc(3, GFP_ATOMIC);
+	skb->data[0] = HCI_HARDWARE_ERROR_EVT;
+	skb->data[1] = 1;
+	skb->data[2] = HCI_HARDWARE_REMOVE;
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb_put(skb, 3);
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		PRINTM(MSG, "Send HW ERROR event\n");
+		if (!mdev_recv_frame(skb)) {
+#define RX_WAIT_TIMEOUT				300
+			mdev_bt->wait_rx_complete = TRUE;
+			mdev_bt->rx_complete_flag = FALSE;
+			if (os_wait_interruptible_timeout
+			    (mdev_bt->rx_wait_q, mdev_bt->rx_complete_flag,
+			     RX_WAIT_TIMEOUT))
+				PRINTM(MSG, "BT stack received the event\n");
+			mdev_bt->stat.byte_rx += 3;
+		}
+	}
+	LEAVE();
+	return;
+}
+
+#ifdef BLE_WAKEUP
+/**
+ *  @brief This function used to config BLE wakeup pattern
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        N/A
+ */
+int
+bt_config_ble_wakeup(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	u16 ocf, left_len;
+	u8 len, more_cmd;
+	u8 *pos;
+
+	ENTER();
+
+	if (!priv->ble_wakeup_buf) {
+		PRINTM(ERROR, "BT: no ble wakeup parameters found\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MSG, "Config ble wakeup pattern\n");
+
+	pos = priv->ble_wakeup_buf;
+	left_len = *(u16 *) pos;
+	left_len = __le16_to_cpu(left_len);
+	pos += sizeof(u16);
+
+	while (left_len >= 2) {
+		more_cmd = *pos;
+		len = *(pos + 1);
+		if (((len + 2) > left_len) ||
+		    (!more_cmd && ((len + 2) < left_len))) {
+			PRINTM(ERROR, "Invalid ble parameters\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		skb = bt_skb_alloc(len, GFP_ATOMIC);
+		if (!skb) {
+			PRINTM(ERROR, "BT BLE WAKEUP: fail to alloc skb\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy(skb_put(skb, len), pos + 2, len);
+		bt_cb(skb)->pkt_type = *(u8 *)skb->data;
+		skb_pull(skb, 1);
+		DBG_HEXDUMP(DAT_D, "BLE_WAKEUP_CMD:", skb->data, skb->len);
+		skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+		skb_queue_head(&priv->adapter->tx_queue, skb);
+		priv->bt_dev.sendcmdflag = TRUE;
+		priv->bt_dev.send_cmd_opcode = *(u16 *) skb->data;
+		ocf = hci_opcode_ocf(priv->bt_dev.send_cmd_opcode);
+		priv->adapter->cmd_complete = FALSE;
+
+		wake_up_interruptible(&priv->MainThread.waitQ);
+		if (!os_wait_interruptible_timeout
+		    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+		     WAIT_UNTIL_CMD_RESP)) {
+			ret = BT_STATUS_FAILURE;
+			PRINTM(ERROR,
+			       "BT: Set  Set ble wakeup cmd 0x%x timeout:\n",
+			       priv->bt_dev.send_cmd_opcode);
+			bt_cmd_timeout_func(priv, ocf);
+			goto done;
+		}
+
+		pos += len + 2;
+		left_len -= len + 2;
+	}
+
+done:
+	if (ret != BT_STATUS_SUCCESS) {
+		if (priv->ble_wakeup_buf) {
+			kfree(priv->ble_wakeup_buf);
+			priv->ble_wakeup_buf = NULL;
+			priv->ble_wakeup_buf_size = 0;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function send system suspend event
+ *
+ *  @param priv    A pointer to bt_private
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_send_system_event(bt_private *priv, u8 flag)
+{
+	struct sk_buff *skb = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+
+	ENTER();
+
+	if (!priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+
+	skb = bt_skb_alloc(4, GFP_ATOMIC);
+	if (!skb) {
+		PRINTM(ERROR, "Fail to allocate sys suspend event skb\n");
+		return BT_STATUS_FAILURE;
+	}
+	skb->data[0] = VENDOR_SPECIFIC_EVENT;
+	skb->data[1] = 2;
+	skb->data[2] = HCI_SYSTEM_SUSPEND_EVT;
+	if (flag)
+		skb->data[3] = HCI_SYSTEM_SUSPEND;
+	else
+		skb->data[3] = HCI_SYSTEM_RESUME;
+
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb_put(skb, 4);
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		PRINTM(MSG, "Send system %s event\n",
+		       flag ? "suspend" : "resume");
+		if (!mdev_recv_frame(skb)) {
+#define RX_WAIT_TIMEOUT                         300
+			mdev_bt->wait_rx_complete = TRUE;
+			mdev_bt->rx_complete_flag = FALSE;
+			if (os_wait_interruptible_timeout(mdev_bt->rx_wait_q,
+							  mdev_bt->
+							  rx_complete_flag,
+							  RX_WAIT_TIMEOUT))
+				PRINTM(MSG, "BT stack received the event\n");
+			mdev_bt->stat.byte_rx += 4;
+		}
+	}
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function removes the card.
+ *
+ *  @param card    A pointer to card
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_remove_card(void *card)
+{
+	bt_private *priv = (bt_private *)card;
+	int index;
+	ENTER();
+	if (!priv) {
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv->adapter->SurpriseRemoved = TRUE;
+
+	bt_send_hw_remove_event(priv);
+#ifdef BLE_WAKEUP
+	if (priv->ble_wakeup_buf) {
+		kfree(priv->ble_wakeup_buf);
+		priv->ble_wakeup_buf = NULL;
+		priv->ble_wakeup_buf_size = 0;
+	}
+#endif
+	wake_up_interruptible(&priv->adapter->cmd_wait_q);
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid) {
+		os_sched_timeout(1);
+		wake_up_interruptible(&priv->MainThread.waitQ);
+	}
+
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+	clean_up_m_devs(priv);
+	PRINTM(INFO, "Free Adapter\n");
+	bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function initializes module.
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_module(void)
+{
+	int ret = BT_STATUS_SUCCESS;
+	int index;
+	ENTER();
+	PRINTM(MSG, "BT: Loading driver\n");
+	/* Init the bt_private pointer array first */
+	for (index = 0; index < MAX_BT_ADAPTER; index++)
+		m_priv[index] = NULL;
+	bt_root_proc_init();
+
+	/** create char device class */
+	chardev_class = class_create(THIS_MODULE, MODULE_NAME);
+	if (IS_ERR(chardev_class)) {
+		PRINTM(ERROR, "Unable to allocate class\n");
+		bt_root_proc_remove();
+		ret = PTR_ERR(chardev_class);
+		goto done;
+	}
+
+	if (sbi_register() == NULL) {
+		bt_root_proc_remove();
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	if (ret)
+		PRINTM(MSG, "BT: Driver loading failed\n");
+	else
+		PRINTM(MSG, "BT: Driver loaded successfully\n");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function cleans module
+ *
+ *  @return        N/A
+ */
+static void
+bt_exit_module(void)
+{
+	bt_private *priv;
+	int index;
+	ENTER();
+	PRINTM(MSG, "BT: Unloading driver\n");
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		priv = m_priv[index];
+		if (!priv)
+			continue;
+		if (priv && !priv->adapter->SurpriseRemoved) {
+			if (BT_STATUS_SUCCESS == bt_send_reset_command(priv))
+				bt_send_module_cfg_cmd(priv,
+						       MODULE_SHUTDOWN_REQ);
+		}
+		sbi_disable_host_int(priv);
+
+	}
+
+	sbi_unregister();
+
+	bt_root_proc_remove();
+	class_destroy(chardev_class);
+	PRINTM(MSG, "BT: Driver unloaded\n");
+	LEAVE();
+}
+
+module_init(bt_init_module);
+module_exit(bt_exit_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell Bluetooth Driver Ver. " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+module_param(fw, int, 0);
+MODULE_PARM_DESC(fw, "0: Skip firmware download; otherwise: Download firmware");
+module_param(fw_crc_check, int, 0);
+MODULE_PARM_DESC(fw_crc_check,
+		 "1: Enable FW download CRC check (default); 0: Disable FW download CRC check");
+module_param(psmode, int, 0);
+MODULE_PARM_DESC(psmode, "1: Enable powermode; 0: Disable powermode");
+module_param(deep_sleep, int, 0);
+MODULE_PARM_DESC(deep_sleep, "1: Enable deep sleep; 0: Disable deep sleep");
+#ifdef CONFIG_OF
+module_param(dts_enable, int, 0);
+MODULE_PARM_DESC(dts_enable, "0: Disable DTS; 1: Enable DTS");
+#endif
+#ifdef	DEBUG_LEVEL1
+module_param(mbt_drvdbg, uint, 0);
+MODULE_PARM_DESC(mbt_drvdbg, "BIT3:DBG_DATA BIT4:DBG_CMD 0xFF:DBG_ALL");
+#endif
+#ifdef SDIO_SUSPEND_RESUME
+module_param(mbt_pm_keep_power, int, 0);
+MODULE_PARM_DESC(mbt_pm_keep_power, "1: PM keep power; 0: PM no power");
+#endif
+module_param(init_cfg, charp, 0);
+MODULE_PARM_DESC(init_cfg, "BT init config file name");
+module_param(cal_cfg, charp, 0);
+MODULE_PARM_DESC(cal_cfg, "BT calibrate file name");
+module_param(cal_cfg_ext, charp, 0);
+MODULE_PARM_DESC(cal_cfg_ext, "BT calibrate ext file name");
+module_param(bt_mac, charp, 0660);
+MODULE_PARM_DESC(bt_mac, "BT init mac address");
+module_param(drv_mode, int, 0);
+MODULE_PARM_DESC(drv_mode, "Bit 0: BT/AMP/BLE;" "Bit 2: NFC");
+module_param(bt_name, charp, 0);
+MODULE_PARM_DESC(bt_name, "BT interface name");
+module_param(nfc_name, charp, 0);
+MODULE_PARM_DESC(nfc_name, "NFC interface name");
+module_param(debug_intf, int, 0);
+MODULE_PARM_DESC(debug_intf,
+		 "1: Enable debug interface; 0: Disable debug interface ");
+module_param(debug_name, charp, 0);
+MODULE_PARM_DESC(debug_name, "Debug interface name");
+module_param(bt_fw_reload, int, 0);
+MODULE_PARM_DESC(bt_fw_reload,
+		 "0: disable fw_reload; 1: enable fw reload feature");
+module_param(mbt_gpio_pin, int, 0);
+MODULE_PARM_DESC(mbt_gpio_pin,
+		 "GPIO pin to interrupt host. 0xFF: disable GPIO interrupt mode; Others: GPIO pin assigned to generate pulse to host.");
+module_param(btindrst, int, 0);
+MODULE_PARM_DESC(btindrst,
+		 "Independent reset configuration; high byte:GPIO pin number;low byte:0x0:disable, 0x1:out-band reset, 0x2:in-band reset.");
+module_param(btpmic, int, 0);
+MODULE_PARM_DESC(btpmic,
+		 "1: Send pmic configure cmd to firmware; 0: No pmic configure cmd sent to firmware (default)");
+module_param(bt_fw_serial, int, 0);
+MODULE_PARM_DESC(bt_fw_serial,
+		 "0: Support parallel download FW; 1: Support serial download FW");
diff --git a/bt_sd8897/bt/bt_proc.c b/bt_sd8897/bt/bt_proc.c
new file mode 100644
index 0000000..04f87b4
--- /dev/null
+++ b/bt_sd8897/bt/bt_proc.c
@@ -0,0 +1,720 @@
+/** @file bt_proc.c
+  *
+  * @brief This file handle the functions for proc files
+  *
+  * Copyright (C) 2007-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/proc_fs.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** proc diretory root */
+#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
+
+/** Proc mbt directory entry */
+static struct proc_dir_entry *proc_mbt;
+
+#define     CMD52_STR_LEN   50
+static char cmd52_string[CMD52_STR_LEN];
+
+/** proc data structure */
+struct proc_data {
+	/** Read length */
+	int rdlen;
+	/** Read buffer */
+	char *rdbuf;
+	/** Write length */
+	int wrlen;
+	/** Maximum write length */
+	int maxwrlen;
+	/** Write buffer */
+	char *wrbuf;
+	/** Private structure */
+	struct _bt_private *pbt;
+	void (*on_close) (struct inode *, struct file *);
+};
+
+/** Default file permission */
+#define DEFAULT_FILE_PERM  0644
+
+/** Bluetooth device offset */
+#define OFFSET_BT_DEV		0x01
+/** Bluetooth adapter offset */
+#define OFFSET_BT_ADAPTER	0x02
+/** Show integer */
+#define SHOW_INT		0x10
+/** Show hex */
+#define SHOW_HEX		0x20
+/** Show string */
+#define SHOW_STRING		0x40
+
+/** Device size */
+#define item_dev_size(n) (sizeof((bt_dev_t *)0)->n)
+/** Device address */
+#define item_dev_addr(n) ((t_ptr) &((bt_dev_t *)0)->n)
+
+/** Adapter size */
+#define item_adapter_size(n) (sizeof((bt_adapter *)0)->n)
+/** Adapter address */
+#define item_adapter_addr(n) ((t_ptr) &((bt_adapter *)0)->n)
+
+static struct item_data config_items[] = {
+#ifdef	DEBUG_LEVEL1
+	{"drvdbg", sizeof(u32), (t_ptr)&mbt_drvdbg, 0, SHOW_HEX}
+	,
+#endif
+	{"idle_timeout", item_dev_size(idle_timeout), 0,
+	 item_dev_addr(idle_timeout), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"psmode", item_dev_size(psmode), 0, item_dev_addr(psmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"pscmd", item_dev_size(pscmd), 0, item_dev_addr(pscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hsmode", item_dev_size(hsmode), 0, item_dev_addr(hsmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hscmd", item_dev_size(hscmd), 0, item_dev_addr(hscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"gpio_gap", item_dev_size(gpio_gap), 0, item_dev_addr(gpio_gap),
+	 OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"hscfgcmd", item_dev_size(hscfgcmd), 0, item_dev_addr(hscfgcmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"sdio_pull_cfg", item_dev_size(sdio_pull_cfg), 0,
+	 item_dev_addr(sdio_pull_cfg), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"sdio_pull_ctrl", item_dev_size(sdio_pull_ctrl), 0,
+	 item_dev_addr(sdio_pull_ctrl), OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"test_mode", item_dev_size(test_mode), 0, item_dev_addr(test_mode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+
+};
+
+static struct item_data status_items[] = {
+	{"version", item_adapter_size(drv_ver), 0, item_adapter_addr(drv_ver),
+	 OFFSET_BT_ADAPTER | SHOW_STRING},
+	{"tx_dnld_rdy", item_dev_size(tx_dnld_rdy), 0,
+	 item_dev_addr(tx_dnld_rdy),
+	 OFFSET_BT_DEV | SHOW_INT},
+	{"psmode", item_adapter_size(psmode), 0, item_adapter_addr(psmode),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_state", item_adapter_size(hs_state), 0,
+	 item_adapter_addr(hs_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_skip", item_adapter_size(hs_skip), 0, item_adapter_addr(hs_skip),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"ps_state", item_adapter_size(ps_state), 0,
+	 item_adapter_addr(ps_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"WakeupTries", item_adapter_size(WakeupTries), 0,
+	 item_adapter_addr(WakeupTries), OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_recv", item_adapter_size(irq_recv), 0,
+	 item_adapter_addr(irq_recv),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_done", item_adapter_size(irq_done), 0,
+	 item_adapter_addr(irq_done),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"skb_pending", item_adapter_size(skb_pending), 0,
+	 item_adapter_addr(skb_pending), OFFSET_BT_ADAPTER | SHOW_INT},
+};
+
+static struct item_data debug_items[] = {
+	{"sdcmd52rw", 0, (t_ptr)cmd52_string, 0, SHOW_STRING},
+};
+
+/**
+ *  @brief convert string to number
+ *
+ *  @param s	pointer to numbered string
+ *  @return	converted number from string s
+ */
+int
+string_to_number(char *s)
+{
+	int r = 0;
+	int base = 0;
+	int pn = 1;
+
+	if (strncmp(s, "-", 1) == 0) {
+		pn = -1;
+		s++;
+	}
+	if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
+		base = 16;
+		s += 2;
+	} else
+		base = 10;
+
+	for (s = s; *s != 0; 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 Create cmd52 string
+ *
+ *  @param priv	A pointer to bt_private structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+form_cmd52_string(bt_private *priv)
+{
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	snprintf(cmd52_string, CMD52_STR_LEN - 1, "BT: %d 0x%0x 0x%02X",
+		 priv->bt_dev.cmd52_func, priv->bt_dev.cmd52_reg,
+		 priv->bt_dev.cmd52_val);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/*
+ *  @brief Parse cmd52 string
+ *
+ *  @param buffer  A pointer user buffer
+ *  @param len     Length of 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 __user * buffer, size_t len,
+		   int *func, int *reg, int *val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	char *string = NULL;
+	char *pos = NULL;
+
+	ENTER();
+
+	string = kzalloc(CMD52_STR_LEN, GFP_KERNEL);
+	if (!string) {
+		PRINTM(ERROR, "BT: Can not alloc mem for cmd52 string\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	memcpy(string, buffer + strlen("sdcmd52rw="),
+	       len - strlen("sdcmd52rw="));
+	string = strstrip(string);
+
+	*func = -1;
+	*reg = -1;
+	*val = -1;
+
+	/* Get func */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*func = string_to_number(pos);
+
+	/* Get reg */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*reg = string_to_number(pos);
+
+	/* Get val (optional) */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*val = string_to_number(pos);
+	kfree(string);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handle generic proc file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+proc_close(struct inode *inode, struct file *file)
+{
+	struct proc_data *pdata = file->private_data;
+	ENTER();
+	if (pdata) {
+		if (pdata->on_close != NULL)
+			pdata->on_close(inode, file);
+		kfree(pdata->rdbuf);
+		kfree(pdata->wrbuf);
+		kfree(pdata);
+	}
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle generic proc file read
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to output buffer
+ *  @param len     number of byte to read
+ *  @param offset  A pointer to offset of file
+ *  @return		number of output data
+ */
+static ssize_t
+proc_read(struct file *file, char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	if ((!pdata->rdbuf) || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->rdlen)
+		return 0;
+	if (len > pdata->rdlen - pos)
+		len = pdata->rdlen - pos;
+	if (copy_to_user(buffer, pdata->rdbuf + pos, len))
+		return -EFAULT;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle generic proc file write
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to input buffer
+ *  @param len     number of byte to write
+ *  @param offset  A pointer to offset of file
+ *  @return		number of input data
+ */
+static ssize_t
+proc_write(struct file *file,
+	   const char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	int func = 0, reg = 0, val = 0;
+	int config_data = 0;
+	char *line = NULL;
+
+	if (!pdata->wrbuf || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->maxwrlen)
+		return 0;
+	if (len > pdata->maxwrlen - pos)
+		len = pdata->maxwrlen - pos;
+	if (copy_from_user(pdata->wrbuf + pos, buffer, len))
+		return -EFAULT;
+	if (!strncmp(pdata->wrbuf + pos, "fw_reload", strlen("fw_reload"))) {
+		if (!strncmp
+		    (pdata->wrbuf + pos, "fw_reload=", strlen("fw_reload="))) {
+			line = pdata->wrbuf + pos;
+			line += strlen("fw_reload") + 1;
+			config_data = string_to_number(line);
+		} else
+			config_data = FW_RELOAD_SDIO_INBAND_RESET;
+		PRINTM(MSG, "Request fw_reload=%d\n", config_data);
+		bt_request_fw_reload(pdata->pbt, config_data);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "sdcmd52rw=", strlen("sdcmd52rw="))) {
+		parse_cmd52_string(pdata->wrbuf + pos, len, &func, &reg, &val);
+		sd_write_cmd52_val(pdata->pbt, func, reg, val);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "debug_dump", strlen("debug_dump"))) {
+		bt_dump_sdio_regs(pdata->pbt);
+		bt_dump_firmware_info_v2(pdata->pbt);
+	}
+
+	if (pos + len > pdata->wrlen)
+		pdata->wrlen = len + file->f_pos;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle the generic file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return		N/A
+ */
+static void
+proc_on_close(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata = file->private_data;
+	char *line;
+	int i;
+	ENTER();
+	if (!pdata->wrlen)
+		return;
+	line = pdata->wrbuf;
+	while (line[0]) {
+		for (i = 0; i < priv->num_items; i++) {
+			if (!strncmp
+			    (line, priv->pdata[i].name,
+			     strlen(priv->pdata[i].name))) {
+				line += strlen(priv->pdata[i].name) + 1;
+				if (priv->pdata[i].size == 1)
+					*((u8 *)priv->pdata[i].addr) =
+						(u8)string_to_number(line);
+				else if (priv->pdata[i].size == 2)
+					*((u16 *) priv->pdata[i].addr) =
+						(u16) string_to_number(line);
+				else if (priv->pdata[i].size == 4)
+					*((u32 *)priv->pdata[i].addr) =
+						(u32)string_to_number(line);
+			}
+		}
+		while (line[0] && line[0] != '\n')
+			line++;
+		if (line[0])
+			line++;
+	}
+	if (priv->pbt->bt_dev.hscmd || priv->pbt->bt_dev.pscmd
+	    || priv->pbt->bt_dev.sdio_pull_ctrl
+	    || priv->pbt->bt_dev.test_mode || priv->pbt->bt_dev.hscfgcmd) {
+		bt_prepare_command(priv->pbt);
+		wake_up_interruptible(&priv->pbt->MainThread.waitQ);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handle the generic file open
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS or other error no.
+ */
+static int
+proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata;
+	int i;
+	char *p;
+	u32 val = 0;
+	ENTER();
+	priv->pbt->adapter->skb_pending =
+		skb_queue_len(&priv->pbt->adapter->tx_queue);
+	file->private_data = kzalloc(sizeof(struct proc_data), GFP_KERNEL);
+	if (file->private_data == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for proc_data\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	pdata = (struct proc_data *)file->private_data;
+	pdata->pbt = priv->pbt;
+	pdata->rdbuf = kmalloc(priv->bufsize, GFP_KERNEL);
+	if (pdata->rdbuf == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for rdbuf\n");
+		kfree(file->private_data);
+		LEAVE();
+		return -ENOMEM;
+	}
+	if (priv->fileflag == DEFAULT_FILE_PERM) {
+		pdata->wrbuf = kzalloc(priv->bufsize, GFP_KERNEL);
+		if (pdata->wrbuf == NULL) {
+			PRINTM(ERROR, "BT: Can not alloc mem for wrbuf\n");
+			kfree(pdata->rdbuf);
+			kfree(file->private_data);
+			return -ENOMEM;
+		}
+		pdata->maxwrlen = priv->bufsize;
+		pdata->on_close = proc_on_close;
+	}
+	p = pdata->rdbuf;
+	for (i = 0; i < priv->num_items; i++) {
+		if (priv->pdata[i].size == 1)
+			val = *((u8 *)priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 2)
+			val = *((u16 *) priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 4)
+			val = *((u32 *)priv->pdata[i].addr);
+		if (priv->pdata[i].flag & SHOW_INT)
+			p += sprintf(p, "%s=%d\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_HEX)
+			p += sprintf(p, "%s=0x%x\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_STRING) {
+			if (!strncmp
+			    (priv->pdata[i].name, "sdcmd52rw",
+			     strlen("sdcmd52rw"))) {
+				sd_read_cmd52_val(priv->pbt);
+				form_cmd52_string(priv->pbt);
+			}
+			p += sprintf(p, "%s=%s\n", priv->pdata[i].name,
+				     (char *)priv->pdata[i].addr);
+		}
+	}
+	pdata->rdlen = strlen(pdata->rdbuf);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/** Proc read ops */
+static const struct file_operations proc_read_ops = {
+	.read = proc_read,
+	.open = proc_open,
+	.release = proc_close
+};
+
+/** Proc Read-Write ops */
+static const struct file_operations proc_rw_ops = {
+	.read = proc_read,
+	.write = proc_write,
+	.open = proc_open,
+	.release = proc_close
+};
+
+static struct proc_private_data proc_files[] = {
+	{"status", S_IRUGO, 1024,
+	 sizeof(status_items) / sizeof(status_items[0]),
+	 &status_items[0], NULL, &proc_read_ops}
+	,
+	{"config", DEFAULT_FILE_PERM, 512,
+	 sizeof(config_items) / sizeof(config_items[0]), &config_items[0], NULL,
+	 &proc_rw_ops}
+	,
+	{"debug", DEFAULT_FILE_PERM, 512,
+	 sizeof(debug_items) / sizeof(debug_items[0]), &debug_items[0], NULL,
+	 &proc_rw_ops}
+	,
+};
+
+/**
+ *  @brief This function initializes proc entry
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param m_dev    A pointer to struct m_dev
+ *  @param seq      Sequence number
+ *
+ *  @return	BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct proc_dir_entry *entry;
+	int i, j;
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	if (proc_mbt) {
+		priv->dev_proc[seq].proc_entry =
+			proc_mkdir(m_dev->name, proc_mbt);
+		if (!priv->dev_proc[seq].proc_entry) {
+			PRINTM(ERROR, "BT: Could not mkdir %s!\n", m_dev->name);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->dev_proc[seq].pfiles =
+			kmalloc(sizeof(proc_files), GFP_ATOMIC);
+		if (!priv->dev_proc[seq].pfiles) {
+			PRINTM(ERROR,
+			       "BT: Could not alloc memory for pfile!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy((u8 *)priv->dev_proc[seq].pfiles, (u8 *)proc_files,
+		       sizeof(proc_files));
+		priv->dev_proc[seq].num_proc_files = ARRAY_SIZE(proc_files);
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++)
+			priv->dev_proc[seq].pfiles[j].pdata = NULL;
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+			priv->dev_proc[seq].pfiles[j].pdata =
+				kmalloc(priv->dev_proc[seq].pfiles[j].
+					num_items * sizeof(struct item_data),
+					GFP_ATOMIC);
+			if (!priv->dev_proc[seq].pfiles[j].pdata) {
+				PRINTM(ERROR,
+				       "BT: Could not alloc memory for pdata!\n");
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			memcpy((u8 *)priv->dev_proc[seq].pfiles[j].pdata,
+			       (u8 *)proc_files[j].pdata,
+			       priv->dev_proc[seq].pfiles[j].num_items *
+			       sizeof(struct item_data));
+			for (i = 0; i < priv->dev_proc[seq].pfiles[j].num_items;
+			     i++) {
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_DEV)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)&priv->bt_dev;
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_ADAPTER)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)priv->adapter;
+			}
+			priv->dev_proc[seq].pfiles[j].pbt = priv;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			entry = proc_create_data(proc_files[j].name,
+						 S_IFREG | proc_files[j].
+						 fileflag,
+						 priv->dev_proc[seq].proc_entry,
+						 proc_files[j].fops,
+						 &priv->dev_proc[seq].
+						 pfiles[j]);
+			if (entry == NULL)
+#else
+			entry = create_proc_entry(proc_files[j].name,
+						  S_IFREG | proc_files[j].
+						  fileflag,
+						  priv->dev_proc[seq].
+						  proc_entry);
+			if (entry) {
+				entry->data = &priv->dev_proc[seq].pfiles[j];
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
+				entry->owner = THIS_MODULE;
+#endif
+				entry->proc_fops = proc_files[j].fops;
+			} else
+#endif
+				PRINTM(MSG, "BT: Fail to create proc %s\n",
+				       proc_files[j].name);
+		}
+	}
+done:
+	if (ret == BT_STATUS_FAILURE) {
+		if (priv->dev_proc[seq].proc_entry) {
+			remove_proc_entry(m_dev->name, proc_mbt);
+			priv->dev_proc[seq].proc_entry = NULL;
+		}
+		if (priv->dev_proc[seq].pfiles) {
+			for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+				if (priv->dev_proc[seq].pfiles[j].pdata) {
+					kfree(priv->dev_proc[seq].pfiles[j].
+					      pdata);
+					priv->dev_proc[seq].pfiles[j].pdata =
+						NULL;
+				}
+			}
+			kfree(priv->dev_proc[seq].pfiles);
+			priv->dev_proc[seq].pfiles = NULL;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return	N/A
+ */
+void
+bt_proc_remove(bt_private *priv)
+{
+	int j, i;
+	ENTER();
+	PRINTM(INFO, "BT: Remove Proc Interface\n");
+	if (proc_mbt) {
+		for (i = 0; i < MAX_RADIO_FUNC; i++) {
+			if (!priv->dev_proc[i].proc_entry)
+				continue;
+			for (j = 0; j < ARRAY_SIZE(proc_files); j++) {
+				remove_proc_entry(proc_files[j].name,
+						  priv->dev_proc[i].proc_entry);
+			}
+			remove_proc_entry(priv->bt_dev.m_dev[i].name, proc_mbt);
+			priv->dev_proc[i].proc_entry = NULL;
+
+			if (priv->dev_proc[i].pfiles) {
+				for (j = 0;
+				     j < priv->dev_proc[i].num_proc_files;
+				     j++) {
+					if (priv->dev_proc[i].pfiles[j].pdata) {
+						kfree(priv->dev_proc[i].
+						      pfiles[j].pdata);
+						priv->dev_proc[i].pfiles[j].
+							pdata = NULL;
+					}
+				}
+				kfree(priv->dev_proc[i].pfiles);
+				priv->dev_proc[i].pfiles = NULL;
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function creates proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_root_proc_init(void)
+{
+	PRINTM(INFO, "BT: Create Proc Interface\n");
+	proc_mbt = proc_mkdir("mbt", PROC_DIR);
+	if (!proc_mbt) {
+		PRINTM(ERROR, "BT: Cannot create proc interface\n");
+		return BT_STATUS_FAILURE;
+	}
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS
+ */
+int
+bt_root_proc_remove(void)
+{
+	remove_proc_entry("mbt", PROC_DIR);
+	proc_mbt = NULL;
+	return BT_STATUS_SUCCESS;
+}
diff --git a/bt_sd8897/bt/bt_sdio.h b/bt_sd8897/bt/bt_sdio.h
new file mode 100644
index 0000000..8e18b7c
--- /dev/null
+++ b/bt_sd8897/bt/bt_sdio.h
@@ -0,0 +1,429 @@
+/** @file bt_sdio.h
+ *  @brief This file contains SDIO (interface) module
+ *  related macros, enum, and structure.
+ *
+ *  Copyright (C) 2007-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_SDIO_H_
+#define _BT_SDIO_H_
+
+#include <linux/irqreturn.h>
+
+/** SD8787 card type */
+#define CARD_TYPE_SD8787   0x01
+/** SD8777 card type */
+#define CARD_TYPE_SD8777   0x02
+/** SD8887 card type */
+#define CARD_TYPE_SD8887   0x03
+/** SD8897 card type */
+#define CARD_TYPE_SD8897   0x04
+/** SD8797 card type */
+#define CARD_TYPE_SD8797   0x05
+/** SD8977 card type */
+#define CARD_TYPE_SD8977   0x06
+/** SD8997 card type */
+#define CARD_TYPE_SD8997   0x07
+/** SD8987 card type */
+#define CARD_TYPE_SD8987   0x08
+
+/** IRQ return type */
+typedef irqreturn_t IRQ_RET_TYPE;
+/** IRQ return */
+#define IRQ_RET		(return IRQ_HANDLED)
+/** ISR notifier function */
+typedef IRQ_RET_TYPE (*isr_notifier_fn_t) (s32 irq, void *dev_id,
+					   struct pt_regs * reg);
+
+/** SDIO header length */
+#define SDIO_HEADER_LEN			4
+
+/** 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
+/* SD block size can not bigger than 64 due to buf size limit in firmware */
+/** define SD block size for data Tx/Rx */
+#define SD_BLOCK_SIZE			64
+/** define SD block size for firmware download */
+#define SD_BLOCK_SIZE_FW_DL		256
+
+/** Number of blocks for firmware transfer */
+#define FIRMWARE_TRANSFER_NBLOCK	2
+
+/** Firmware ready */
+#define FIRMWARE_READY			0xfedc
+
+/* Bus Interface Control Reg 0x07 */
+/** SD BUS width 1 */
+#define SD_BUS_WIDTH_1			0x00
+/** SD BUS width 4 */
+#define SD_BUS_WIDTH_4			0x02
+/** SD BUS width mask */
+#define SD_BUS_WIDTH_MASK		0x03
+/** Asynchronous interrupt mode */
+#define ASYNC_INT_MODE			0x20
+
+/** magic register */
+#define CARD_MAGIC_REG          0xF0
+/** magic value */
+#define MAGIC_VAL               0x24
+
+/* Host Control Registers */
+/** Host Control Registers : Configuration */
+#define CONFIGURATION_REG		0x00
+/** Host Control Registers : Host without Command 53 finish host*/
+#define HOST_TO_CARD_EVENT		(0x1U << 3)
+/** Host Control Registers : Host terminates Command 53 */
+#define HOST_TERM_CMD53			(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 : Host interrupt RSR */
+#define HOST_INT_RSR_REG		0x01
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR		(0x1U)
+
+/** Host Control Registers : Host interrupt mask */
+#define HOST_INT_MASK_REG		0x02
+
+/** 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)
+/** Enable Host interrupt mask */
+#define HIM_ENABLE			(UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
+/** Disable Host interrupt mask */
+#define	HIM_DISABLE			0xff
+
+#define HOST_INTSTATUS_REG		0x03
+/** 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)
+
+/** 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
+
+/** Host Control Registers : Host interrupt status */
+#define HOST_INT_STATUS_REG		0x28
+/** Host Control Registers : Upload CRC error */
+#define UP_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 */
+/** Card Control Registers : Read SQ base address A0 register */
+#define SQ_READ_BASE_ADDRESS_A0_REG		0x40
+/** Card Control Registers : Read SQ base address A1 register */
+#define SQ_READ_BASE_ADDRESS_A1_REG		0x41
+/** Card Control Registers : Read SQ base address A2 register */
+#define SQ_READ_BASE_ADDRESS_A2_REG		0x42
+/** Card Control Registers : Read SQ base address A3 register */
+#define SQ_READ_BASE_ADDRESS_A3_REG		0x43
+/** Card Control Registers : Read SQ base address B0 register */
+#define SQ_READ_BASE_ADDRESS_B0_REG		0x44
+/** Card Control Registers : Read SQ base address B1 register */
+#define SQ_READ_BASE_ADDRESS_B1_REG		0x45
+/** Card Control Registers : Read SQ base address B2 register */
+#define SQ_READ_BASE_ADDRESS_B2_REG		0x46
+/** Card Control Registers : Read SQ base address B3 register */
+#define SQ_READ_BASE_ADDRESS_B3_REG		0x47
+
+/** Card Control Registers : Card status register */
+#define CARD_STATUS_REG					0x30
+/** 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 interrupt mask register */
+#define HOST_INTERRUPT_MASK_REG			0x34
+/** 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 : Card interrupt status register */
+#define CARD_INTERRUPT_STATUS_REG		0x38
+/** 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 : Card interrupt RSR register */
+#define CARD_INTERRUPT_RSR_REG			0x3c
+/** 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 : Debug 0 register */
+#define DEBUG_0_REG						0x70
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0						(0x1U)
+/** Card Control Registers : Debug 1 register */
+#define DEBUG_1_REG						0x71
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1						(0x1U)
+/** Card Control Registers : Debug 2 register */
+#define DEBUG_2_REG						0x72
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2						(0x1U)
+/** Card Control Registers : Debug 3 register */
+#define DEBUG_3_REG						0x73
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3						(0x1U)
+
+/** Host Control Registers : I/O port 0 */
+#define IO_PORT_0_REG			0x78
+/** Host Control Registers : I/O port 1 */
+#define IO_PORT_1_REG			0x79
+/** Host Control Registers : I/O port 2 */
+#define IO_PORT_2_REG			0x7A
+
+/** Firmware status 0 register */
+#define CARD_FW_STATUS0_REG		0x60
+/** Firmware status 1 register */
+#define CARD_FW_STATUS1_REG		0x61
+/** Rx length register */
+#define CARD_RX_LEN_REG			0x62
+/** Rx unit register */
+#define CARD_RX_UNIT_REG		0x63
+/** Card Control Registers : Miscellaneous Configuration Register */
+#define CARD_MISC_CFG_REG		0x6C
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT		(0x1U << 4)
+
+/** Card Control Registers : Card OCR 0 register */
+#define CARD_OCR_0_REG			0x68
+/** Card Control Registers : Card OCR 1 register */
+#define CARD_OCR_1_REG			0x69
+/** Card Control Registers : Card OCR 3 register */
+#define CARD_OCR_3_REG			0x6A
+/** Card Control Registers : Card config register */
+#define CARD_CONFIG_REG			0x6B
+/** Card Control Registers : Card revision register */
+#define CARD_REVISION_REG		0x5c
+/** Card Control Registers : Command 53 finish G BUS */
+#define CMD53_FINISH_GBUS		(0x1U << 1)
+/** Card Control Registers : SD negative edge */
+#define SD_NEG_EDGE				(0x1U << 0)
+
+/* Special registers in function 0 of the SDxx card */
+/** Special register in function 0 of the SDxxx card : Scratch 0 */
+#define	SCRATCH_0_REG			0x80fe
+/** Special register in function 0 of the SDxxx card : Scratch 1 */
+#define	SCRATCH_1_REG			0x80ff
+/** Host F1 read base 0 */
+#define HOST_F1_RD_BASE_0		0x0040
+/** Host F1 read base 1 */
+#define HOST_F1_RD_BASE_1		0x0041
+/** Host F1 card ready */
+#define HOST_F1_CARD_RDY		0x0020
+
+/** Chip Id Register 0 */
+#define CARD_CHIP_ID_0_REG		0x801c
+/** Chip Id Register 1 */
+#define CARD_CHIP_ID_1_REG		0x801d
+
+struct sdio_mmc_card {
+	/** sdio_func structure pointer */
+	struct sdio_func *func;
+	/** bt_private structure pointer */
+	bt_private *priv;
+};
+
+struct sdio_card_reg {
+	u8 cfg;
+	u8 host_int_mask;	// HOST_INT_MASK_REG
+	u8 host_intstatus;	// HOST_INTSTATUS_REG
+	u8 host_int_rsr_reg;	// HOST_INT_RSR_REG
+	u8 card_misc_cfg_reg;	// CARD_MISC_CFG_REG
+	u8 card_status;		// CARD_STATUS_REG
+	u8 sq_read_base_addr_a0;	// SQ_READ_BASE_ADDRESS_A0_REG
+	u8 sq_read_base_addr_a1;	// SQ_READ_BASE_ADDRESS_A1_REG
+	u8 card_revision;	// CARD_REVISION_REG
+	u8 card_fw_status0;	// CARD_FW_STATUS0_REG
+	u8 card_fw_status1;	// CARD_FW_STATUS1_REG
+	u8 card_rx_len;		// CARD_RX_LEN_REG
+	u8 card_rx_unit;	// CARD_RX_UNIT_REG
+	u8 io_port_0;		// IO_PORT_0_REG
+	u8 io_port_1;		// IO_PORT_1_REG
+	u8 io_port_2;		// IO_PORT_2_REG
+};
+
+struct sdio_device {
+	const struct sdio_card_reg *reg;
+};
+
+static const struct sdio_card_reg bt_reg_87xx = {
+	.cfg = 0x00,
+	.host_int_mask = 0x02,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x03,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x01,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0x6c,	// CARD_MISC_CFG_REG
+	.card_status = 0x30,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0x40,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0x41,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0x5C,	// CARD_REVISION_REG
+	.card_fw_status0 = 0x60,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0x61,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0x62,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0x63,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0x78,	// IO_PORT_0_REG
+	.io_port_1 = 0x79,	// IO_PORT_1_REG
+	.io_port_2 = 0x7a,	// IO_PORT_2_REG
+};
+
+static const struct sdio_card_reg bt_reg_8887 = {
+	.cfg = 0x00,
+	.host_int_mask = 0x08,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x0C,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x04,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0xD8,	// CARD_MISC_CFG_REG
+	.card_status = 0x5C,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0x6C,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0x6D,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0xC8,	// CARD_REVISION_REG
+	.card_fw_status0 = 0x88,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0x89,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0x8A,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0x8B,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0xE4,	// IO_PORT_0_REG
+	.io_port_1 = 0xE5,	// IO_PORT_1_REG
+	.io_port_2 = 0xE6,	// IO_PORT_2_REG
+};
+
+static const struct sdio_card_reg bt_reg_8897 = {
+	.cfg = 0x00,
+	.host_int_mask = 0x02,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x03,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x01,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0xCC,	// CARD_MISC_CFG_REG
+	.card_status = 0x50,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0x60,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0x61,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0xBC,	// CARD_REVISION_REG
+	.card_fw_status0 = 0xC0,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0xC1,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0xC2,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0xC3,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0xD8,	// IO_PORT_0_REG
+	.io_port_1 = 0xD9,	// IO_PORT_1_REG
+	.io_port_2 = 0xDA,	// IO_PORT_2_REG
+};
+
+static const struct sdio_card_reg bt_reg_8977_8997 = {
+	.cfg = 0x00,
+	.host_int_mask = 0x08,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x0C,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x04,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0xD8,	// CARD_MISC_CFG_REG
+	.card_status = 0x5C,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0xF8,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0xF9,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0xC8,	// CARD_REVISION_REG
+	.card_fw_status0 = 0xE8,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0xE9,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0xEA,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0xEB,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0xE4,	// IO_PORT_0_REG
+	.io_port_1 = 0xE5,	// IO_PORT_1_REG
+	.io_port_2 = 0xE6,	// IO_PORT_2_REG
+};
+
+static const struct sdio_device bt_sdio_sd8787 = {
+	.reg = &bt_reg_87xx,
+};
+
+static const struct sdio_device bt_sdio_sd8777 = {
+	.reg = &bt_reg_87xx,
+};
+
+static const struct sdio_device bt_sdio_sd8887 = {
+	.reg = &bt_reg_8887,
+};
+
+static const struct sdio_device bt_sdio_sd8897 = {
+	.reg = &bt_reg_8897,
+};
+
+static const struct sdio_device bt_sdio_sd8797 = {
+	.reg = &bt_reg_87xx,
+};
+
+static const struct sdio_device bt_sdio_sd8977 = {
+	.reg = &bt_reg_8977_8997,
+};
+
+static const struct sdio_device bt_sdio_sd8997 = {
+	.reg = &bt_reg_8977_8997,
+};
+
+static const struct sdio_device bt_sdio_sd8987 = {
+	.reg = &bt_reg_8977_8997,
+};
+
+/** DMA alignment value */
+#define DMA_ALIGNMENT	64
+/** 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))
+
+/** This function read cmd52 register */
+int sd_write_reg(bt_private *priv, int reg, u8 val);
+/** This function write cmd52 value to register */
+int sd_read_reg(bt_private *priv, int reg, u8 *data);
+/** This function reads the Cmd52 value in dev structure */
+int sd_read_cmd52_val(bt_private *priv);
+/** This function updates card reg based on the Cmd52 value in dev structure */
+int sd_write_cmd52_val(bt_private *priv, int func, int reg, int val);
+
+void sdio_update_card_type(bt_private *priv, void *card);
+int sdio_get_sdio_device(bt_private *priv);
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** This function tells lower driver that BT is suspended */
+void bt_is_suspended(bt_private *priv);
+#endif
+#endif
+#endif
+#endif /* _BT_SDIO_H_ */
diff --git a/bt_sd8897/bt/bt_sdiommc.c b/bt_sd8897/bt/bt_sdiommc.c
new file mode 100644
index 0000000..83a76fc
--- /dev/null
+++ b/bt_sd8897/bt/bt_sdiommc.c
@@ -0,0 +1,2355 @@
+/** @file bt_sdiommc.c
+ *  @brief This file contains SDIO IF (interface) module
+ *  related functions.
+ *
+ * Copyright (C) 2007-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/mmc/sdio_func.h>
+#include        <linux/mmc/sdio.h>
+#include        <linux/mmc/card.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** define marvell vendor id */
+#define MARVELL_VENDOR_ID 0x02df
+
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD53_RETRY 	3
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD52_RETRY     3
+/** Firmware name */
+static char *fw_name;
+/** fw serial download flag */
+extern int bt_fw_serial;
+int bt_intmode = INT_MODE_SDIO;
+/** request firmware nowait */
+int bt_req_fw_nowait;
+static int multi_fn = BIT(2);
+
+#define DEFAULT_FW_NAME ""
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB2   28
+/** FW header for CRC check disable */
+static u8 fw_crc_header_rb_2[FW_CRC_HEADER_RB2] = {
+	0x05, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+	0x9d, 0x32, 0xbb, 0x11, 0x01, 0x00, 0x00, 0x7f,
+	0x00, 0x00, 0x00, 0x00, 0x67, 0xd6, 0xfc, 0x25
+};
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB   24
+/** FW header for CRC check disable */
+static u8 fw_crc_header_rb_1[FW_CRC_HEADER_RB] = {
+	0x01, 0x00, 0x00, 0x00, 0x04, 0xfd, 0x00, 0x04,
+	0x08, 0x00, 0x00, 0x00, 0x26, 0x52, 0x2a, 0x7b,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/** Default firmware name */
+#define DEFAULT_FW_NAME_8777 "mrvl/sd8777_uapsta.bin"
+#define DEFAULT_FW_NAME_8787 "mrvl/sd8787_uapsta.bin"
+#define DEFAULT_FW_NAME_8797 "mrvl/sd8797_uapsta.bin"
+#define DEFAULT_FW_NAME_8887 "mrvl/sd8887_uapsta.bin"
+#define DEFAULT_FW_NAME_8897 "mrvl/sd8897_uapsta.bin"
+#define DEFAULT_FW_NAME_8977 "mrvl/sdsd8977_combo.bin"
+#define DEFAULT_FW_NAME_8997 "mrvl/sdsd8997_combo.bin"
+
+/** SD8787 chip revision ID */
+#define SD8787_W0      0x30
+#define SD8787_W1      0x31
+#define SD8787_A0_A1   0x40
+/** SD8797 chip revision ID */
+#define SD8797_A0       0x00
+#define SD8797_B0       0x10
+/** SD8897 chip revision ID */
+#define SD8897_A0       0x10
+#define SD8897_B0       0x20
+
+/** SD8887 chip revision ID */
+#define SD8887_A0       0x0
+#define SD8887_A2       0x2
+#define SD8887_A0_FW_NAME "mrvl/sd8887_uapsta.bin"
+#define SD8887_A2_FW_NAME "mrvl/sd8887_uapsta_a2.bin"
+#define SD8887_A2_BT_FW_NAME "mrvl/sd8887_bt_a2.bin"
+
+#define SD8897_A0_FW_NAME "mrvl/sd8897_uapsta_a0.bin"
+#define SD8897_B0_FW_NAME "mrvl/sd8897_uapsta.bin"
+
+#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin"
+#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin"
+#define SD8797_A0_FW_NAME "mrvl/sd8797_uapsta_a0.bin"
+#define SD8797_B0_FW_NAME "mrvl/sd8797_uapsta.bin"
+
+/** SD8977 chip revision ID */
+#define SD8977_V0       0x0
+#define SD8977_V1       0x8
+#define SD8977_V2       0x9
+#define SD8977_V0_FW_NAME "mrvl/sdsd8977_combo.bin"
+#define SD8977_V0_BT_FW_NAME "mrvl/sd8977_bt.bin"
+#define SD8977_V1_FW_NAME "mrvl/sdsd8977_combo_v1.bin"
+#define SD8977_V1_BT_FW_NAME "mrvl/sd8977_bt_v1.bin"
+#define SD8977_V2_FW_NAME "mrvl/sdsd8977_combo_v2.bin"
+#define SD8977_V2_BT_FW_NAME "mrvl/sd8977_bt_v2.bin"
+
+/** SD8997 chip revision ID */
+#define SD8997_Z        0x02
+#define SD8997_V2       0x10
+#define SD8997_Z_FW_NAME "mrvl/sdsd8997_combo.bin"
+#define SD8997_Z_BT_FW_NAME "mrvl/sd8997_bt.bin"
+#define SD8997_V2_FW_NAME "mrvl/sdsd8997_combo_v2.bin"
+#define SD8997_V2_BT_FW_NAME "mrvl/sd8997_bt_v2.bin"
+#define SD8997_V3_FW_NAME "mrvl/sdsd8997_combo_v3.bin"
+#define SD8997_V3_BT_FW_NAME "mrvl/sd8997_bt_v3.bin"
+
+/** SD8987 */
+#define SD8987_FW_NAME  "mrvl/sdsd8987_combo.bin"
+#define SD8987_BT_FW_NAME "mrvl/sd8987_bt.bin"
+
+/** Function number 2 */
+#define FN2			2
+/** Device ID for SD8787 FN2 */
+#define SD_DEVICE_ID_8787_BT_FN2    0x911A
+/** Device ID for SD8787 FN3 */
+#define SD_DEVICE_ID_8787_BT_FN3    0x911B
+/** Device ID for SD8777 FN2 */
+#define SD_DEVICE_ID_8777_BT_FN2    0x9132
+/** Device ID for SD8777 FN3 */
+#define SD_DEVICE_ID_8777_BT_FN3    0x9133
+/** Device ID for SD8887 FN2 */
+#define SD_DEVICE_ID_8887_BT_FN2    0x9136
+/** Device ID for SD8887 FN3 */
+#define SD_DEVICE_ID_8887_BT_FN3    0x9137
+/** Device ID for SD8897 FN2 */
+#define SD_DEVICE_ID_8897_BT_FN2    0x912E
+/** Device ID for SD8897 FN3 */
+#define SD_DEVICE_ID_8897_BT_FN3    0x912F
+/** Device ID for SD8797 FN2 */
+#define SD_DEVICE_ID_8797_BT_FN2    0x912A
+/** Device ID for SD8797 FN3 */
+#define SD_DEVICE_ID_8797_BT_FN3    0x912B
+/** Device ID for SD8977 FN2 */
+#define SD_DEVICE_ID_8977_BT_FN2    0x9146
+/** Device ID for SD8997 FN2 */
+#define SD_DEVICE_ID_8997_BT_FN2    0x9142
+/** Device ID for SD8987 FN2 */
+#define SD_DEVICE_ID_8987_BT_FN2    0x914a
+/** Device ID for SD8987 FN3 */
+#define SD_DEVICE_ID_8987_BT_FN3    0x914b
+
+/** Array of SDIO device ids when multi_fn=0x12 */
+static const struct sdio_device_id bt_ids[] = {
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8787_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8777_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8887_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8897_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8797_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8977_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8997_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8987_BT_FN2)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(sdio, bt_ids);
+
+/********************************************************
+		Global Variables
+********************************************************/
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+extern int mbt_pm_keep_power;
+#endif
+
+extern bt_private *m_priv[];
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief This function gets rx_unit value
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_get_rx_unit(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_unit_reg = priv->psdio_device->reg->card_rx_unit;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_unit_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		priv->bt_dev.rx_unit = reg;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads fwstatus registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_read_firmware_status(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 fws0;
+	u8 fws1;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = priv->psdio_device->reg->card_fw_status0;
+	u8 card_fw_status1_reg = priv->psdio_device->reg->card_fw_status1;
+
+	ENTER();
+
+	fws0 = sdio_readb(card->func, card_fw_status0_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	fws1 = sdio_readb(card->func, card_fw_status1_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	*dat = (((u16) fws1) << 8) | fws0;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function reads rx length
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sd_read_rx_len(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_len_reg = priv->psdio_device->reg->card_rx_len;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_len_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		*dat = (u16) reg << priv->bt_dev.rx_unit;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables the host interrupts mask
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_enable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = priv->psdio_device->reg->host_int_mask;
+
+	ENTER();
+
+	sdio_writeb(card->func, mask, host_int_mask_reg, &ret);
+	if (ret) {
+		PRINTM(WARN, "BT: Unable to enable the host interrupt!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function disables the host interrupts mask.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sbi_disable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_FAILURE;
+	u8 host_int_mask;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = priv->psdio_device->reg->host_int_mask;
+
+	ENTER();
+
+	/* Read back the host_int_mask register */
+	host_int_mask = sdio_readb(card->func, host_int_mask_reg, &ret);
+	if (ret)
+		goto done;
+
+	/* Update with the mask and write back to the register */
+	host_int_mask &= ~mask;
+	sdio_writeb(card->func, host_int_mask, host_int_mask_reg, &ret);
+	if (ret < 0) {
+		PRINTM(WARN, "BT: Unable to diable the host interrupt!\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function polls the card status register
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param bits     the bit mask
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_poll_card_status(bt_private *priv, u8 bits)
+{
+	int tries;
+	int rval;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 cs;
+	u8 card_status_reg = priv->psdio_device->reg->card_status;
+
+	ENTER();
+
+	for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
+		cs = sdio_readb(card->func, card_status_reg, &rval);
+		if (rval != 0)
+			break;
+		if (rval == 0 && (cs & bits) == bits) {
+			LEAVE();
+			return BT_STATUS_SUCCESS;
+		}
+		udelay(1);
+	}
+	PRINTM(ERROR,
+	       "BT: sdio_poll_card_status failed (%d), tries = %d, cs = 0x%x\n",
+	       rval, tries, cs);
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_cmd52_val(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 func, reg, val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	func = priv->bt_dev.cmd52_func;
+	reg = priv->bt_dev.cmd52_reg;
+	sdio_claim_host(card->func);
+	if (func)
+		val = sdio_readb(card->func, reg, &ret);
+	else
+		val = sdio_f0_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	if (ret) {
+		PRINTM(ERROR, "BT: Cannot read value from func %d reg %d\n",
+		       func, reg);
+	} else {
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param func     Stores func variable
+ *  @param reg      Stores reg variable
+ *  @param val      Stores val variable
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_cmd52_val(bt_private *priv, int func, int reg, int val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	if (val >= 0) {
+		/* Perform actual write only if val is provided */
+		sdio_claim_host(card->func);
+		if (func)
+			sdio_writeb(card->func, val, reg, &ret);
+		else
+			sdio_f0_writeb(card->func, val, reg, &ret);
+		sdio_release_host(card->func);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: Cannot write value (0x%x) to func %d reg %d\n",
+			       val, func, reg);
+			goto done;
+		}
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	/* Save current func and reg for future read */
+	priv->bt_dev.cmd52_func = func;
+	priv->bt_dev.cmd52_reg = reg;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to write
+ *  @param val      value
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_reg(bt_private *priv, int reg, u8 val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, val, reg, &ret);
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to read
+ *  @param data		Data
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_reg(bt_private *priv, int reg, u8 *data)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	val = sdio_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	*data = val;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function probes the card
+ *
+ *  @param func    A pointer to sdio_func structure.
+ *  @param id      A pointer to structure sdio_device_id
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_probe_card(struct sdio_func *func, const struct sdio_device_id *id)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *card = NULL;
+
+	ENTER();
+
+	PRINTM(INFO, "BT: vendor=0x%x,device=0x%x,class=%d,fn=%d\n", id->vendor,
+	       id->device, id->class, func->num);
+	card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
+	if (!card) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	card->func = func;
+#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_disable_func(func);
+		sdio_release_host(func);
+		PRINTM(FATAL, "BT: sdio_enable_func() failed: ret=%d\n", ret);
+		kfree(card);
+		LEAVE();
+		return -EIO;
+	}
+	sdio_release_host(func);
+	priv = bt_add_card(card);
+	if (!priv) {
+		sdio_claim_host(func);
+		sdio_disable_func(func);
+		sdio_release_host(func);
+		ret = BT_STATUS_FAILURE;
+		kfree(card);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param pollnum  Number of times to poll fw status
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_verify_fw_download(bt_private *priv, int pollnum)
+{
+	int ret = BT_STATUS_FAILURE;
+	u16 firmwarestat = 0;
+	int tries;
+
+	ENTER();
+
+	/* Wait for firmware initialization event */
+	for (tries = 0; tries < pollnum; tries++) {
+		if (sd_read_firmware_status(priv, &firmwarestat) < 0)
+			continue;
+		if (firmwarestat == FIRMWARE_READY) {
+			PRINTM(MSG, "BT FW is active(%d)\n", tries);
+			ret = BT_STATUS_SUCCESS;
+			break;
+		}
+		mdelay(100);
+	}
+	if ((pollnum > 1) && (ret != BT_STATUS_SUCCESS)) {
+		PRINTM(ERROR,
+		       "Fail to poll firmware status: firmwarestat=0x%x\n",
+		       firmwarestat);
+		bt_dump_sdio_regs(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Transfers firmware to card
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @param fw        A Pointer to fw image
+ *  @param fw_len    fw image len
+ *  @return          BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_init_fw_dpc(bt_private *priv, u8 *fw, int fw_len)
+{
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 *firmware = fw;
+	int firmwarelen = fw_len;
+	u8 base0;
+	u8 base1;
+	int ret = BT_STATUS_SUCCESS;
+	int offset;
+	void *tmpfwbuf = NULL;
+	int tmpfwbufsz;
+	u8 *fwbuf;
+	u16 len;
+	int txlen = 0;
+	int tx_blocks = 0;
+	int i = 0;
+	int tries = 0;
+#ifdef FW_DOWNLOAD_SPEED
+	u32 tv1, tv2;
+#endif
+	u8 sq_read_base_address_a0_reg =
+		priv->psdio_device->reg->sq_read_base_addr_a0;
+	u8 sq_read_base_address_a1_reg =
+		priv->psdio_device->reg->sq_read_base_addr_a1;
+	u8 crc_buffer = 0;
+	u8 *header_crc_fw = NULL;
+	u8 header_crc_fw_len = 0;
+
+	if (priv->card_type == CARD_TYPE_SD8787) {
+		header_crc_fw = fw_crc_header_rb_1;
+		header_crc_fw_len = FW_CRC_HEADER_RB;
+	} else if (priv->card_type == CARD_TYPE_SD8777) {
+		header_crc_fw = fw_crc_header_rb_2;
+		header_crc_fw_len = FW_CRC_HEADER_RB2;
+	}
+
+	ENTER();
+
+	PRINTM(INFO, "BT: Downloading FW image (%d bytes)\n", firmwarelen);
+
+#ifdef FW_DOWNLOAD_SPEED
+	tv1 = get_utimeofday();
+#endif
+
+	tmpfwbufsz = BT_UPLD_SIZE + DMA_ALIGNMENT;
+	tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
+	if (!tmpfwbuf) {
+		PRINTM(ERROR,
+		       "BT: Unable to allocate buffer for firmware. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	/* Ensure aligned firmware buffer */
+	fwbuf = (u8 *)ALIGN_ADDR(tmpfwbuf, DMA_ALIGNMENT);
+
+	if (!(priv->fw_crc_check)
+	    && ((priv->card_type == CARD_TYPE_SD8787) ||
+		(priv->card_type == CARD_TYPE_SD8777))
+		) {
+		/* CRC check not required, use custom header first */
+		firmware = header_crc_fw;
+		firmwarelen = header_crc_fw_len;
+		crc_buffer = 1;
+	}
+
+	/* Perform firmware data transfer */
+	offset = 0;
+	do {
+		/* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits
+		 */
+		ret = sd_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: FW download with helper poll status timeout @ %d\n",
+			       offset);
+			goto done;
+		}
+		if (!crc_buffer)
+			/* More data? */
+			if (offset >= firmwarelen)
+				break;
+
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			base0 = sdio_readb(card->func,
+					   sq_read_base_address_a0_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE0 register read failed:"
+				       " base0=0x%04X(%d). Terminating download\n",
+				       base0, base0);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			base1 = sdio_readb(card->func,
+					   sq_read_base_address_a1_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE1 register read failed:"
+				       " base1=0x%04X(%d). Terminating download\n",
+				       base1, base1);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			len = (((u16) base1) << 8) | base0;
+
+			if (len != 0)
+				break;
+			udelay(10);
+		}
+
+		if (len == 0)
+			break;
+		else if (len > BT_UPLD_SIZE) {
+			PRINTM(FATAL,
+			       "BT: FW download failure @ %d, invalid length %d\n",
+			       offset, len);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	/** ignore CRC check before download the first packet */
+		if (offset == 0 && (len & BIT(0)))
+			len &= ~BIT(0);
+		txlen = len;
+
+		if (len & BIT(0)) {
+			i++;
+			if (i >= MAX_CMD53_RETRY) {
+				PRINTM(FATAL,
+				       "BT: FW download failure @ %d, over max retry count\n",
+				       offset);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(ERROR,
+			       "BT: FW CRC error indicated by the helper:"
+			       " len = 0x%04X, txlen = %d\n", len, txlen);
+			len &= ~BIT(0);
+
+			PRINTM(ERROR, "BT: retry: %d, offset %d\n", i, offset);
+			/* Setting this to 0 to resend from same offset */
+			txlen = 0;
+		} else {
+			i = 0;
+
+			/* Set blocksize to transfer - checking for last block */
+			if (firmwarelen - offset < txlen)
+				txlen = firmwarelen - offset;
+
+			PRINTM(INFO, ".");
+
+			tx_blocks =
+				(txlen + SD_BLOCK_SIZE_FW_DL -
+				 1) / SD_BLOCK_SIZE_FW_DL;
+
+			/* Copy payload to buffer */
+			memcpy(fwbuf, &firmware[offset], txlen);
+		}
+
+		/* Send data */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, fwbuf,
+				   tx_blocks * SD_BLOCK_SIZE_FW_DL);
+
+		if (ret < 0) {
+			PRINTM(ERROR,
+			       "BT: FW download, write iomem (%d) failed @ %d\n",
+			       i, offset);
+			sdio_writeb(card->func, 0x04, CONFIGURATION_REG, &ret);
+			if (ret)
+				PRINTM(ERROR, "write ioreg failed (CFG)\n");
+		}
+
+		offset += txlen;
+		if (crc_buffer
+		    && ((priv->card_type == CARD_TYPE_SD8787) ||
+			(priv->card_type == CARD_TYPE_SD8777))
+			) {
+			if (offset >= header_crc_fw_len) {
+				/* Custom header download complete, restore
+				   original FW */
+				offset = 0;
+				firmware = fw;
+				firmwarelen = fw_len;
+				crc_buffer = 0;
+			}
+		}
+	} while (TRUE);
+
+	PRINTM(MSG, "BT: FW download over, size %d bytes\n", offset);
+
+	ret = BT_STATUS_SUCCESS;
+done:
+#ifdef FW_DOWNLOAD_SPEED
+	tv2 = get_utimeofday();
+	PRINTM(INFO, "FW: %d.%03d.%03d ", tv1 / 1000000,
+	       (tv1 % 1000000) / 1000, tv1 % 1000);
+	PRINTM(INFO, " -> %d.%03d.%03d ", tv2 / 1000000,
+	       (tv2 % 1000000) / 1000, tv2 % 1000);
+	tv2 -= tv1;
+	PRINTM(INFO, " == %d.%03d.%03d\n", tv2 / 1000000,
+	       (tv2 % 1000000) / 1000, tv2 % 1000);
+#endif
+	kfree(tmpfwbuf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *
+ * @param fw_firmware  A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_request_fw_dpc(const struct firmware *fw_firmware, void *context)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = (bt_private *)context;
+	struct sdio_mmc_card *card = NULL;
+	struct m_dev *m_dev_bt = NULL;
+	struct m_dev *m_dev_nfc = NULL;
+	struct timeval tstamp;
+	int index;
+
+	ENTER();
+
+	m_dev_bt = &priv->bt_dev.m_dev[BT_SEQ];
+	m_dev_nfc = &priv->bt_dev.m_dev[NFC_SEQ];
+
+	if ((priv == NULL) || (priv->adapter == NULL) ||
+	    (priv->bt_dev.card == NULL) || (m_dev_bt == NULL)
+	    || (m_dev_nfc == NULL)
+		) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	if (!fw_firmware) {
+		do_gettimeofday(&tstamp);
+		if (tstamp.tv_sec >
+		    (priv->req_fw_time.tv_sec + REQUEST_FW_TIMEOUT)) {
+			PRINTM(ERROR,
+			       "BT: No firmware image found. Skipping download\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		PRINTM(ERROR,
+		       "BT: No firmware image found! Retrying download\n");
+		/* Wait a second here before calling the callback again */
+		os_sched_timeout(1000);
+		sd_download_firmware_w_helper(priv);
+		LEAVE();
+		return ret;
+	}
+
+	priv->firmware = fw_firmware;
+
+	if (BT_STATUS_FAILURE ==
+	    sd_init_fw_dpc(priv, (u8 *)priv->firmware->data,
+			   priv->firmware->size)) {
+		PRINTM(ERROR,
+		       "BT: sd_init_fw_dpc failed (download fw with nowait: %d). Terminating download\n",
+		       bt_req_fw_nowait);
+		sdio_release_host(card->func);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* check if the fimware is downloaded successfully or not */
+	if (sd_verify_fw_download(priv, MAX_FIRMWARE_POLL_TRIES)) {
+		PRINTM(ERROR, "BT: FW failed to be active in time!\n");
+		ret = BT_STATUS_FAILURE;
+		sdio_release_host(card->func);
+		goto done;
+	}
+	sdio_release_host(card->func);
+	sbi_enable_host_int(priv);
+	if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+		PRINTM(ERROR,
+		       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	LEAVE();
+	return ret;
+
+done:
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	/* For synchronous download cleanup will be done in add_card */
+	if (!bt_req_fw_nowait)
+		return ret;
+	PRINTM(INFO, "unregister device\n");
+	sbi_unregister_dev(priv);
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+	bt_proc_remove(priv);
+	clean_up_m_devs(priv);
+	bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware     A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             None
+ **/
+static void
+sd_request_fw_callback(const struct firmware *firmware, void *context)
+{
+	ENTER();
+	sd_request_fw_dpc(firmware, context);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function downloads firmware image to the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sd_download_firmware_w_helper(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	int err;
+	char *cur_fw_name = NULL;
+
+	ENTER();
+
+	cur_fw_name = fw_name;
+
+	if (fw_name == NULL) {
+		if (priv->card_type == CARD_TYPE_SD8787)
+			cur_fw_name = DEFAULT_FW_NAME_8787;
+		else if (priv->card_type == CARD_TYPE_SD8777)
+			cur_fw_name = DEFAULT_FW_NAME_8777;
+		else if (priv->card_type == CARD_TYPE_SD8887) {
+			/* Check revision ID */
+			switch (priv->adapter->chip_rev) {
+			case SD8887_A0:
+				cur_fw_name = SD8887_A0_FW_NAME;
+				break;
+			case SD8887_A2:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8887_A2_FW_NAME;
+				else
+					cur_fw_name = SD8887_A2_BT_FW_NAME;
+				break;
+			default:
+				cur_fw_name = DEFAULT_FW_NAME_8887;
+				break;
+			}
+		} else if (priv->card_type == CARD_TYPE_SD8897)
+			cur_fw_name = DEFAULT_FW_NAME_8897;
+		else if (priv->card_type == CARD_TYPE_SD8797)
+			cur_fw_name = DEFAULT_FW_NAME_8797;
+		else if (priv->card_type == CARD_TYPE_SD8977) {
+			switch (priv->adapter->chip_rev) {
+			case SD8977_V0:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8977_V0_FW_NAME;
+				else
+					cur_fw_name = SD8977_V0_BT_FW_NAME;
+				break;
+			case SD8977_V1:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8977_V1_FW_NAME;
+				else
+					cur_fw_name = SD8977_V1_BT_FW_NAME;
+				break;
+			case SD8977_V2:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8977_V2_FW_NAME;
+				else
+					cur_fw_name = SD8977_V2_BT_FW_NAME;
+				break;
+			default:
+				cur_fw_name = DEFAULT_FW_NAME_8977;
+				break;
+			}
+		} else if (priv->card_type == CARD_TYPE_SD8997)
+			switch (priv->adapter->chip_rev) {
+			case SD8997_Z:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8997_Z_FW_NAME;
+				else
+					cur_fw_name = SD8997_Z_BT_FW_NAME;
+				break;
+			case SD8997_V2:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload) {
+					if (priv->adapter->magic_val ==
+					    MAGIC_VAL)
+						cur_fw_name = SD8997_V3_FW_NAME;
+					else
+						cur_fw_name = SD8997_V2_FW_NAME;
+				} else {
+					if (priv->adapter->magic_val ==
+					    MAGIC_VAL)
+						cur_fw_name =
+							SD8997_V3_BT_FW_NAME;
+					else
+						cur_fw_name =
+							SD8997_V2_BT_FW_NAME;
+				}
+				break;
+			default:
+				cur_fw_name = DEFAULT_FW_NAME_8997;
+				break;
+		} else if (priv->card_type == CARD_TYPE_SD8987) {
+			if (bt_fw_serial == 1
+			    && !priv->fw_reload && !bt_fw_reload)
+				cur_fw_name = SD8987_FW_NAME;
+			else
+				cur_fw_name = SD8987_BT_FW_NAME;
+		}
+	}
+
+	PRINTM(MSG, "BT Request firmware: %s\n", cur_fw_name);
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      sd_request_fw_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#endif
+#endif
+		if (ret < 0)
+			PRINTM(FATAL,
+			       "BT: request_firmware_nowait() failed, error code = %#x\n",
+			       ret);
+	} else {
+		err = request_firmware(&priv->firmware, cur_fw_name,
+				       priv->hotplug_device);
+		if (err < 0) {
+			PRINTM(FATAL,
+			       "BT: request_firmware() failed, error code = %#x\n",
+			       err);
+			ret = BT_STATUS_FAILURE;
+		} else
+			ret = sd_request_fw_dpc(priv->firmware, priv);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads data from the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_card_to_host(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u16 buf_len = 0;
+	int buf_block_len;
+	int blksz;
+	struct sk_buff *skb = NULL;
+	u32 type;
+	u8 *payload = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+	struct m_dev *mdev_nfc = &(priv->bt_dev.m_dev[NFC_SEQ]);
+	struct nfc_dev *nfc_dev =
+		(struct nfc_dev *)priv->bt_dev.m_dev[NFC_SEQ].dev_pointer;
+	struct m_dev *mdev_debug = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
+	struct debug_dev *debug_dev =
+		(struct debug_dev *)priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int i = 0;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	do {
+		/* Read the length of data to be transferred */
+		ret = sd_read_rx_len(priv, &buf_len);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR, "BT: Read scratch reg failed (%d)\n", i);
+			if (i >= MAX_CMD52_RETRY) {
+				ret = BT_STATUS_FAILURE;
+				goto exit;
+			}
+			udelay(20);
+		}
+	}
+	while (ret == BT_STATUS_FAILURE);
+
+	/* Allocate buffer */
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (buf_len + blksz - 1) / blksz;
+	if (buf_len <= BT_HEADER_LEN ||
+	    (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+		PRINTM(ERROR, "BT: card_to_host, invalid packet length: %d\n",
+		       buf_len);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	skb = bt_skb_alloc(buf_block_len * blksz + DMA_ALIGNMENT, GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		goto exit;
+	}
+	if ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)) {
+		skb_put(skb,
+			DMA_ALIGNMENT -
+			((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+		skb_pull(skb,
+			 DMA_ALIGNMENT -
+			 ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+	}
+
+	payload = skb->data;
+	i = 0;
+	do {
+		ret = sdio_readsb(card->func, payload, priv->bt_dev.ioport,
+				  buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: card_to_host, read iomem (%d) failed: %d\n",
+			       i, ret);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY) {
+				kfree_skb(skb);
+				skb = NULL;
+				goto exit;
+			}
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	/* This is SDIO specific header length: byte[2][1][0], * type: byte[3]
+	   (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
+	buf_len = payload[0];
+	buf_len |= (u16) payload[1] << 8;
+	type = payload[3];
+	PRINTM(DATA, "BT: SDIO Blk Rd %s: len=%d type=%d\n", mbt_dev->name,
+	       buf_len, type);
+	if (buf_len > buf_block_len * blksz) {
+		PRINTM(ERROR,
+		       "BT: Drop invalid rx pkt, len in hdr=%d, cmd53 length=%d\n",
+		       buf_len, buf_block_len * blksz);
+		ret = BT_STATUS_FAILURE;
+		kfree_skb(skb);
+		skb = NULL;
+		goto exit;
+	}
+	DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Rd", payload, buf_len);
+	switch (type) {
+	case HCI_ACLDATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (*(u16 *) skb->data == 0xffff) {
+			skb_queue_tail(&priv->adapter->fwdump_queue, skb);
+			break;
+		}
+		bt_recv_frame(priv, skb);
+		break;
+	case HCI_SCODATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		bt_recv_frame(priv, skb);
+		break;
+	case HCI_EVENT_PKT:
+		/** add EVT Demux */
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (BT_STATUS_SUCCESS == check_evtpkt(priv, skb))
+			break;
+		switch (skb->data[0]) {
+		case 0x0E:
+			/** cmd complete */
+			if (priv->debug_device_pending) {
+				if (priv->debug_ocf_ogf[0] == skb->data[3] &&
+				    priv->debug_ocf_ogf[1] == skb->data[4]) {
+					priv->debug_device_pending = 0;
+					priv->debug_ocf_ogf[0] = 0;
+					priv->debug_ocf_ogf[1] = 0;
+					/** debug cmd complete */
+					if (debug_dev) {
+						skb->dev = (void *)mdev_debug;
+						mdev_recv_frame(skb);
+						mdev_debug->stat.byte_rx +=
+							buf_len;
+					}
+					break;
+				}
+			}
+			if (skb->data[3] == 0x81 && skb->data[4] == 0xFE) {
+				/** NFC cmd complete */
+				if (nfc_dev) {
+					skb->dev = (void *)mdev_nfc;
+					mdev_recv_frame(skb);
+					mdev_nfc->stat.byte_rx += buf_len;
+				}
+				break;
+			}
+			bt_recv_frame(priv, skb);
+			break;
+		case 0x0F:
+			/** cmd status */
+			if (skb->data[4] == 0x81 && skb->data[5] == 0xFE) {
+				/** NFC cmd ststus */
+				if (nfc_dev) {
+					skb->dev = (void *)mdev_nfc;
+					mdev_recv_frame(skb);
+					mdev_nfc->stat.byte_rx += buf_len;
+				}
+				break;
+			}
+			bt_recv_frame(priv, skb);
+			break;
+		case 0xFF:
+			/** Vendor specific pkt */
+			if (skb->data[2] == 0xC0) {
+				/** NFC EVT */
+				if (nfc_dev) {
+					skb->dev = (void *)mdev_nfc;
+					mdev_recv_frame(skb);
+					mdev_nfc->stat.byte_rx += buf_len;
+				}
+				break;
+			}
+			bt_recv_frame(priv, skb);
+			break;
+		default:
+			bt_recv_frame(priv, skb);
+			break;
+		}
+		break;
+	case MRVL_VENDOR_PKT:
+		/* Just think here need to back compatible FM */
+		bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (BT_STATUS_SUCCESS != bt_process_event(priv, skb))
+			bt_recv_frame(priv, skb);
+		break;
+	default:
+		/* Driver specified event and command resp should be handle
+		   here */
+		PRINTM(INFO, "BT: Unknown PKT type:%d\n", type);
+		kfree_skb(skb);
+		skb = NULL;
+		break;
+	}
+exit:
+	if (ret) {
+		if (mbt_dev)
+			mdev_bt->stat.err_rx++;
+		PRINTM(ERROR, "error when recv pkt!\n");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes the card
+ *
+ *  @param func    A pointer to sdio_func structure
+ *  @return        N/A
+ */
+static void
+sd_remove_card(struct sdio_func *func)
+{
+	struct sdio_mmc_card *card;
+
+	ENTER();
+
+	if (func) {
+		card = sdio_get_drvdata(func);
+		if (card) {
+			bt_remove_card(card->priv);
+			kfree(card);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the interrupt.
+ *
+ *  @param func  A pointer to sdio_func structure
+ *  @return      N/A
+ */
+static void
+sd_interrupt(struct sdio_func *func)
+{
+	bt_private *priv;
+	struct m_dev *m_dev = NULL;
+	struct sdio_mmc_card *card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 ireg = 0;
+	u8 host_intstatus_reg = 0;
+
+	ENTER();
+
+	card = sdio_get_drvdata(func);
+	if (!card || !card->priv) {
+		PRINTM(INFO,
+		       "BT: %s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
+		       __func__, func, card);
+		LEAVE();
+		return;
+	}
+	priv = card->priv;
+	host_intstatus_reg = priv->psdio_device->reg->host_intstatus;
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	if (priv->card_type == CARD_TYPE_SD8887 ||
+	    priv->card_type == CARD_TYPE_SD8897 ||
+	    priv->card_type == CARD_TYPE_SD8977 ||
+	    priv->card_type == CARD_TYPE_SD8997 ||
+	    priv->card_type == CARD_TYPE_SD8987) {
+		ret = sdio_readsb(card->func, priv->adapter->hw_regs, 0,
+				  SD_BLOCK_SIZE);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: sdio_read_ioreg: cmd53 read int status register failed %d\n",
+			       ret);
+			goto done;
+		}
+		ireg = priv->adapter->hw_regs[host_intstatus_reg];
+	} else {
+		ireg = sdio_readb(card->func, host_intstatus_reg, &ret);
+	}
+	if (ret) {
+		PRINTM(ERROR,
+		       "BT: sdio_read_ioreg: CMD52 read int status register failed %d\n",
+		       ret);
+		goto done;
+	}
+	if (ireg != 0) {
+		/*
+		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+		 * Clear the interrupt status register and re-enable
+		 * the interrupt
+		 */
+		PRINTM(INTR, "BT: INT %s: sdio_ireg = 0x%x\n", m_dev->name,
+		       ireg);
+		priv->adapter->irq_recv = ireg;
+		if (priv->card_type == CARD_TYPE_SD8777 ||
+		    priv->card_type == CARD_TYPE_SD8787) {
+			sdio_writeb(card->func,
+				    ~(ireg) & (DN_LD_HOST_INT_STATUS |
+					       UP_LD_HOST_INT_STATUS),
+				    host_intstatus_reg, &ret);
+			if (ret) {
+				PRINTM(ERROR,
+				       "BT: sdio_write_ioreg: clear int status register failed\n");
+				goto done;
+			}
+		}
+	} else {
+		PRINTM(ERROR, "BT: ERR: ireg=0\n");
+	}
+	OS_INT_DISABLE;
+	priv->adapter->sd_ireg |= ireg;
+	OS_INT_RESTORE;
+	bt_interrupt(m_dev);
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interfaces are present
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @param val    Winner status (0: winner)
+ *  @return       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_check_winner_status(bt_private *priv, u8 *val)
+{
+
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = priv->psdio_device->reg->card_fw_status0;
+
+	ENTER();
+	winner = sdio_readb(cardp->func, card_fw_status0_reg, &ret);
+	if (ret != BT_STATUS_SUCCESS) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** @brief This function tells lower driver that BT is suspended
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        None
+ */
+void
+bt_is_suspended(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	priv->adapter->is_suspended = TRUE;
+	sdio_func_suspended(card->func);
+}
+#endif
+
+/** @brief This function handles client driver suspend
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+int
+bt_sdio_suspend(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is suspended\n",
+		       sdio_func_id(func));
+		return -ENOSYS;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO suspend\n", m_dev->name);
+	mbt_hci_suspend_dev(m_dev);
+	skb_queue_purge(&priv->adapter->tx_queue);
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+#ifdef BLE_WAKEUP
+		/** Set BLE Wake up pattern */
+		if (BT_STATUS_SUCCESS != bt_config_ble_wakeup(priv))
+			PRINTM(ERROR, "BT: Set ble wakeup pattern fail!\n");
+#endif
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+			PRINTM(CMD, "BT: HS not actived, suspend fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to suspend!\n");
+			}
+		}
+	}
+
+	priv->adapter->is_suspended = TRUE;
+
+	LEAVE();
+	/* We will keep the power when hs enabled successfully */
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state == HS_ACTIVATED)) {
+#ifdef MMC_PM_SKIP_RESUME_PROBE
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER and "
+		       "MMC_PM_SKIP_RESUME_PROBE\n");
+		return sdio_set_host_pm_flags(func,
+					      MMC_PM_KEEP_POWER |
+					      MMC_PM_SKIP_RESUME_PROBE);
+#else
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER\n");
+		return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+#endif
+	} else {
+		PRINTM(CMD, "BT: suspend without MMC_PM_KEEP_POWER\n");
+		return BT_STATUS_SUCCESS;
+	}
+}
+
+void
+bt_sdio_shutdown(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: shutdown: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is shutdown\n",
+		       sdio_func_id(func));
+		return;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return;
+	}
+
+	priv = cardp->priv;
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+#ifdef BLE_WAKEUP
+		/** Set BLE Wake up pattern */
+		if (BT_STATUS_SUCCESS != bt_config_ble_wakeup(priv))
+			PRINTM(ERROR, "BT: Set ble wakeup pattern fail!\n");
+#endif
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+			PRINTM(CMD, "BT: HS not actived, shutdown fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to shutdown!\n");
+			}
+		}
+	}
+	LEAVE();
+}
+
+/** @brief This function handles client driver resume
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_sdio_resume(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: resume: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+	priv->adapter->is_suspended = FALSE;
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO resume\n", m_dev->name);
+#ifdef BLE_WAKEUP
+	if (priv->ble_wakeup_buf) {
+		PRINTM(CMD, "BT: Send system resume event\n");
+		bt_send_system_event(priv, FALSE);
+	}
+#endif
+	mbt_hci_resume_dev(m_dev);
+	sbi_wakeup_firmware(priv);
+	priv->adapter->hs_state = HS_DEACTIVATED;
+	PRINTM(CMD, "BT:%s: HS DEACTIVATED in Resume!\n", m_dev->name);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+#endif
+#endif
+
+/********************************************************
+		Global Functions
+********************************************************/
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+static const struct dev_pm_ops bt_sdio_pm_ops = {
+	.suspend = bt_sdio_suspend,
+	.resume = bt_sdio_resume,
+};
+#endif
+#endif
+static struct sdio_driver sdio_bt = {
+	.name = "sdio_bt",
+	.id_table = bt_ids,
+	.probe = sd_probe_card,
+	.remove = sd_remove_card,
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+	.drv = {
+		.pm = &bt_sdio_pm_ops,
+		.shutdown = bt_sdio_shutdown,
+		}
+#endif
+#endif
+};
+
+/**
+ *  @brief This function registers the bt module in bus driver.
+ *
+ *  @return	   An int pointer that keeps returned value
+ */
+int *
+sbi_register(void)
+{
+	int *ret;
+
+	ENTER();
+
+	if (sdio_register_driver(&sdio_bt) != 0) {
+		PRINTM(FATAL, "BT: SD Driver Registration Failed\n");
+		LEAVE();
+		return NULL;
+	} else
+		ret = (int *)1;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function de-registers the bt module in bus driver.
+ *
+ *  @return        N/A
+ */
+void
+sbi_unregister(void)
+{
+	ENTER();
+	sdio_unregister_driver(&sdio_bt);
+	LEAVE();
+}
+
+/**
+ *  @brief This function registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_dev(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	u8 chiprev;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	struct sdio_func *func;
+	u8 host_intstatus_reg = priv->psdio_device->reg->host_intstatus;
+	u8 host_int_rsr_reg = priv->psdio_device->reg->host_int_rsr_reg;
+	u8 card_misc_cfg_reg = priv->psdio_device->reg->card_misc_cfg_reg;
+	u8 card_revision_reg = priv->psdio_device->reg->card_revision;
+	u8 io_port_0_reg = priv->psdio_device->reg->io_port_0;
+	u8 io_port_1_reg = priv->psdio_device->reg->io_port_1;
+	u8 io_port_2_reg = priv->psdio_device->reg->io_port_2;
+	u8 card_magic_reg = CARD_MAGIC_REG;
+	u8 magic_val = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: Error: card or function is NULL!\n");
+		goto failed;
+	}
+	func = card->func;
+	priv->hotplug_device = &func->dev;
+
+	/* Initialize the private structure */
+	strncpy(priv->bt_dev.name, "bt_sdio0", sizeof(priv->bt_dev.name));
+	priv->bt_dev.ioport = 0;
+	priv->bt_dev.fn = func->num;
+
+	sdio_claim_host(func);
+	ret = sdio_claim_irq(func, sd_interrupt);
+	if (ret) {
+		PRINTM(FATAL, ": sdio_claim_irq failed: ret=%d\n", ret);
+		goto release_host;
+	}
+	ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
+	if (ret) {
+		PRINTM(FATAL, ": %s: cannot set SDIO block size\n", __func__);
+		goto release_irq;
+	}
+
+	/* read Revision Register to get the chip revision number */
+	chiprev = sdio_readb(func, card_revision_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_REVISION_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->chip_rev = chiprev;
+	PRINTM(INFO, "revision=%#x\n", chiprev);
+
+	magic_val = sdio_readb(func, card_magic_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_MAGIC_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->magic_val = magic_val;
+	PRINTM(INFO, "magic_val=%#x\n", magic_val);
+
+	/*
+	 * Read the HOST_INTSTATUS_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.
+	 */
+	reg = sdio_readb(func, host_intstatus_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+
+	/* Read the IO port */
+	reg = sdio_readb(func, io_port_0_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= reg;
+
+	reg = sdio_readb(func, io_port_1_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 8);
+
+	reg = sdio_readb(func, io_port_2_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 16);
+
+	PRINTM(INFO, ": SDIO FUNC%d IO port: 0x%x\n", priv->bt_dev.fn,
+	       priv->bt_dev.ioport);
+
+	if (priv->card_type == CARD_TYPE_SD8977) {
+		if (bt_intmode == INT_MODE_GPIO) {
+			PRINTM(MSG, "Enable GPIO-1 INT\n");
+			sdio_writeb(func, ENABLE_GPIO_1_INT_MODE,
+				    SCRATCH_REG_32, &ret);
+			if (ret < 0)
+				goto release_irq;
+		}
+	}
+
+#define SDIO_INT_MASK       0x3F
+	if (priv->card_type == CARD_TYPE_SD8887 ||
+	    priv->card_type == CARD_TYPE_SD8897 ||
+	    priv->card_type == CARD_TYPE_SD8797 ||
+	    priv->card_type == CARD_TYPE_SD8977 ||
+	    priv->card_type == CARD_TYPE_SD8997 ||
+	    priv->card_type == CARD_TYPE_SD8987) {
+		/* Set Host interrupt reset to read to clear */
+		reg = sdio_readb(func, host_int_rsr_reg, &ret);
+		if (ret < 0)
+			goto release_irq;
+		sdio_writeb(func, reg | SDIO_INT_MASK, host_int_rsr_reg, &ret);
+		if (ret < 0)
+			goto release_irq;
+		/* Set auto re-enable */
+		reg = sdio_readb(func, card_misc_cfg_reg, &ret);
+		if (ret < 0)
+			goto release_irq;
+		sdio_writeb(func, reg | AUTO_RE_ENABLE_INT, card_misc_cfg_reg,
+			    &ret);
+		if (ret < 0)
+			goto release_irq;
+	}
+
+	sdio_set_drvdata(func, card);
+	sdio_release_host(func);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+release_irq:
+	sdio_release_irq(func);
+release_host:
+	sdio_release_host(func);
+failed:
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function de-registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_unregister_dev(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	if (card && card->func) {
+		sdio_claim_host(card->func);
+		sdio_release_irq(card->func);
+		sdio_disable_func(card->func);
+		sdio_release_host(card->func);
+		sdio_set_drvdata(card->func, NULL);
+	}
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function enables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_enable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sd_enable_host_int_mask(priv, HIM_ENABLE);
+	sd_get_rx_unit(priv);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function disables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sbi_disable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sbi_disable_host_int_mask(priv, HIM_DISABLE);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param payload A pointer to the data/cmd buffer
+ *  @param nb      Length of data/cmd
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	int ret = BT_STATUS_SUCCESS;
+	int buf_block_len;
+	int blksz;
+	int i = 0;
+	u8 *buf = NULL;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	buf = payload;
+
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (nb + blksz - 1) / blksz;
+	/* Allocate buffer and copy payload */
+	if ((t_ptr)payload & (DMA_ALIGNMENT - 1)) {
+		if (nb > MAX_TX_BUF_SIZE) {
+			PRINTM(ERROR, "BT: Invalid tx packet, size=%d\n", nb);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		}
+		/* Ensure 8-byte aligned CMD buffer */
+		buf = priv->adapter->tx_buf;
+		memcpy(buf, payload, nb);
+	}
+	sdio_claim_host(card->func);
+	do {
+		/* Transfer data to card */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, buf,
+				   buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: host_to_card, write iomem (%d) failed: %d\n",
+			       i, ret);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY)
+				goto exit;
+		} else {
+			PRINTM(DATA, "BT: SDIO Blk Wr %s: len=%d\n",
+			       m_dev->name, nb);
+			DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Wr", payload, nb);
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	priv->bt_dev.tx_dnld_rdy = FALSE;
+exit:
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_download_fw(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	sdio_claim_host(card->func);
+	if (BT_STATUS_SUCCESS == sd_verify_fw_download(priv, 1)) {
+		PRINTM(MSG, "BT: FW already downloaded!\n");
+		sdio_release_host(card->func);
+		sbi_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+	/* Check if other interface is downloading */
+	ret = sd_check_winner_status(priv, &winner);
+	if (ret == BT_STATUS_FAILURE) {
+		PRINTM(FATAL, "BT read winner status failed!\n");
+		goto done;
+	}
+	if (winner) {
+		PRINTM(MSG, "BT is not the winner (0x%x). Skip FW download\n",
+		       winner);
+		/* check if the fimware is downloaded successfully or not */
+		if (sd_verify_fw_download(priv, MAX_MULTI_INTERFACE_POLL_TRIES)) {
+			PRINTM(FATAL, "BT: FW failed to be active in time!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		sdio_release_host(card->func);
+		sbi_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+
+	do_gettimeofday(&priv->req_fw_time);
+	/* Download the main firmware via the helper firmware */
+	if (sd_download_firmware_w_helper(priv)) {
+		PRINTM(INFO, "BT: FW download failed!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+	goto exit;
+done:
+	sdio_release_host(card->func);
+exit:
+	LEAVE();
+	return ret;
+err_register:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the interrupt status and handle it accordingly.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_get_int_status(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 sdio_ireg = 0;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	OS_INT_DISABLE;
+	sdio_ireg = priv->adapter->sd_ireg;
+	priv->adapter->sd_ireg = 0;
+	OS_INT_RESTORE;
+	sdio_claim_host(card->func);
+	priv->adapter->irq_done = sdio_ireg;
+	if (sdio_ireg & DN_LD_HOST_INT_STATUS) {	/* tx_done INT */
+		if (priv->bt_dev.tx_dnld_rdy) {	/* tx_done already received */
+			PRINTM(INFO,
+			       "BT: warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
+			       priv->bt_dev.tx_dnld_rdy, sdio_ireg);
+		} else {
+			priv->bt_dev.tx_dnld_rdy = TRUE;
+		}
+	}
+	if (sdio_ireg & UP_LD_HOST_INT_STATUS)
+		sd_card_to_host(priv);
+
+	ret = BT_STATUS_SUCCESS;
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function wakeup firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sbi_wakeup_firmware(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
+	sdio_release_host(card->func);
+	PRINTM(CMD, "BT wake up firmware\n");
+
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function updates the SDIO card types
+ *
+ *  @param priv     A Pointer to the bt_private structure
+ *  @param card     A Pointer to card
+ *
+ *  @return         N/A
+ */
+void
+sdio_update_card_type(bt_private *priv, void *card)
+{
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)card;
+
+	/* Update card type */
+	if (cardp->func->device == SD_DEVICE_ID_8777_BT_FN2 ||
+	    cardp->func->device == SD_DEVICE_ID_8777_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8777;
+	else if (cardp->func->device == SD_DEVICE_ID_8787_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8787_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8787;
+	else if (cardp->func->device == SD_DEVICE_ID_8887_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8887_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8887;
+	else if (cardp->func->device == SD_DEVICE_ID_8897_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8897_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8897;
+	else if (cardp->func->device == SD_DEVICE_ID_8797_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8797_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8797;
+	else if (cardp->func->device == SD_DEVICE_ID_8977_BT_FN2)
+		priv->card_type = CARD_TYPE_SD8977;
+	else if (cardp->func->device == SD_DEVICE_ID_8997_BT_FN2)
+		priv->card_type = CARD_TYPE_SD8997;
+	else if (cardp->func->device == SD_DEVICE_ID_8987_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8987_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8987;
+}
+
+/**
+ *  @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
+ */
+int
+sdio_get_sdio_device(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u16 card_type = priv->card_type;
+
+	ENTER();
+
+	switch (card_type) {
+	case CARD_TYPE_SD8777:
+		priv->psdio_device = &bt_sdio_sd8777;
+		break;
+	case CARD_TYPE_SD8787:
+		priv->psdio_device = &bt_sdio_sd8787;
+		break;
+	case CARD_TYPE_SD8887:
+		priv->psdio_device = &bt_sdio_sd8887;
+		break;
+	case CARD_TYPE_SD8897:
+		priv->psdio_device = &bt_sdio_sd8897;
+		break;
+	case CARD_TYPE_SD8797:
+		priv->psdio_device = &bt_sdio_sd8797;
+		break;
+	case CARD_TYPE_SD8977:
+		priv->psdio_device = &bt_sdio_sd8977;
+		break;
+	case CARD_TYPE_SD8997:
+		priv->psdio_device = &bt_sdio_sd8997;
+		break;
+	case CARD_TYPE_SD8987:
+		priv->psdio_device = &bt_sdio_sd8987;
+		break;
+	default:
+		PRINTM(ERROR, "BT can't get right card type \n");
+		ret = BT_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+#define SD8897_INIT_START_REG  0xDC
+#define SD8897_INIT_END_REG  0xE1
+#define SD8887_INIT_START_REG  0xA0
+#define SD8887_INIT_END_REG  0xA5
+#define SD8977_SD8997_INIT_START_REG 0xF1
+#define SD8977_SD8997_INIT_END_REG 0xF6
+
+/** @brief This function dump the SDIO register
+ *
+ *  @param priv     A Pointer to the bt_private structure
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_sdio_regs(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+	char buf[256], *ptr;
+	u8 loop, func, data;
+	unsigned int reg, reg_start, reg_end;
+	u8 index = 0;
+	unsigned int reg_table_8887[] = { 0x58, 0x59, 0x5c, 0x60, 0x64, 0x70,
+		0x71, 0x72, 0x73, 0xd8, 0xd9, 0xda
+	};
+	u8 loop_num = 0;
+	unsigned int *reg_table = NULL;
+	u8 reg_table_size = 0;
+	unsigned int init_reg_start = 0;
+	unsigned int init_reg_end = 0;
+	if (priv->card_type == CARD_TYPE_SD8887) {
+		init_reg_start = SD8887_INIT_START_REG;
+		init_reg_end = SD8887_INIT_END_REG;
+	} else if (priv->card_type == CARD_TYPE_SD8897) {
+		init_reg_start = SD8897_INIT_START_REG;
+		init_reg_end = SD8897_INIT_END_REG;
+	} else if (priv->card_type == CARD_TYPE_SD8977 ||
+		   priv->card_type == CARD_TYPE_SD8997 ||
+		   priv->card_type == CARD_TYPE_SD8987) {
+		init_reg_start = SD8977_SD8997_INIT_START_REG;
+		init_reg_end = SD8977_SD8997_INIT_END_REG;
+	}
+
+	if (priv->card_type == CARD_TYPE_SD8887) {
+		loop_num = 3;
+		reg_table = reg_table_8887;
+		reg_table_size = sizeof(reg_table_8887) / sizeof(int);
+	} else
+		loop_num = 2;
+	if (priv->adapter->ps_state)
+		sbi_wakeup_firmware(priv);
+
+	sdio_claim_host(card->func);
+	for (loop = 0; loop < loop_num; 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 == 2) {
+			/* Read specific registers of SDIO function1 */
+			index = 0;
+			func = 2;
+			reg_start = reg_table[index++];
+			reg_end = reg_table[reg_table_size - 1];
+		} else {
+			func = 2;
+			reg_start = 0;
+			reg_end = 0x09;
+		}
+		if (loop == 2)
+			ptr += sprintf(ptr, "SDIO Func%d: ", func);
+		else
+			ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", func,
+				       reg_start, reg_end);
+		for (reg = reg_start; reg <= reg_end;) {
+			if (func == 0)
+				data = sdio_f0_readb(card->func, reg, &ret);
+			else
+				data = sdio_readb(card->func, reg, &ret);
+			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(MSG, "%s\n", buf);
+	}
+
+	if (init_reg_start) {
+		memset(buf, 0, sizeof(buf));
+		ptr = buf;
+		ptr += sprintf(ptr, "Init Status Reg (%#x-%#x): ",
+			       init_reg_start, init_reg_end);
+		for (reg = init_reg_start; reg <= init_reg_end;) {
+			data = sdio_readb(card->func, reg, &ret);
+			if (!ret)
+				ptr += sprintf(ptr, "%02x ", data);
+			else {
+				ptr += sprintf(ptr, "ERR");
+				break;
+			}
+			reg++;
+		}
+		PRINTM(MSG, "%s\n", buf);
+	}
+	sdio_release_host(card->func);
+}
+
+module_param(fw_name, charp, 0);
+MODULE_PARM_DESC(fw_name, "Firmware name");
+module_param(bt_req_fw_nowait, int, 0);
+MODULE_PARM_DESC(bt_req_fw_nowait,
+		 "0: Use request_firmware API; 1: Use request_firmware_nowait API");
+module_param(multi_fn, int, 0);
+MODULE_PARM_DESC(multi_fn, "Bit 2: FN2;");
+
+module_param(bt_intmode, int, 0);
+MODULE_PARM_DESC(bt_intmode, "0: INT_MODE_SDIO, 1: INT_MODE_GPIO");
diff --git a/bt_sd8897/bt/hci_wrapper.h b/bt_sd8897/bt/hci_wrapper.h
new file mode 100644
index 0000000..3537a17
--- /dev/null
+++ b/bt_sd8897/bt/hci_wrapper.h
@@ -0,0 +1,180 @@
+/** @file hci_wrapper.h
+ *  @brief This file contains HCI related definitions
+ *
+ *  Copyright (C) 2011-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _HCI_WRAPPER_H_
+#define _HCI_WRAPPER_H_
+
+#include <linux/module.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+/**  Define Seq num */
+#define BT_SEQ      0
+#define NFC_SEQ     2
+#define DEBUG_SEQ   3
+
+/** Define dev type */
+#define BT_TYPE     1
+#define BT_AMP_TYPE 2
+#define NFC_TYPE    4
+#define DEBUG_TYPE  5
+
+/** Define spec type */
+#define BLUEZ_SPEC     1
+#define IANYWHERE_SPEC 2
+#define GENERIC_SPEC   3
+
+/** Define lock/unlock wrapper */
+#define mdev_req_lock(d)		down(&d->req_lock)
+#define mdev_req_unlock(d)		up(&d->req_lock)
+
+/** Length of device name */
+#define DEV_NAME_LEN				32
+
+/** Define struct m_dev */
+struct m_dev {
+	char name[DEV_NAME_LEN];
+	int index;
+	unsigned long flags;
+	spinlock_t lock;
+	struct semaphore req_lock;
+	struct sk_buff_head rx_q;
+	wait_queue_head_t req_wait_q;
+	struct hci_dev_stats stat;
+	struct module *owner;
+	void *dev_pointer;
+	int dev_type;
+	int spec_type;
+	void *driver_data;
+	int read_continue_flag;
+	int wait_rx_complete;
+	int rx_complete_flag;
+	wait_queue_head_t rx_wait_q;
+	spinlock_t rxlock;
+	atomic_t extra_cnt;
+
+	struct sk_buff *evt_skb;
+	struct sk_buff *acl_skb;
+	struct sk_buff *sco_skb;
+
+	int (*open) (struct m_dev * m_dev);
+	int (*close) (struct m_dev * m_dev);
+	int (*flush) (struct m_dev * m_dev);
+	int (*send) (struct m_dev * m_dev, struct sk_buff * skb);
+	void (*destruct) (struct m_dev * m_dev);
+	void (*notify) (struct m_dev * m_dev, unsigned int evt);
+	int (*ioctl) (struct m_dev * m_dev, unsigned int cmd, void *arg);
+	void (*query) (struct m_dev * m_dev, void *arg);
+
+};
+
+/** Define struct mbt_dev */
+struct mbt_dev {
+	/** maybe could add some private member later */
+	char name[DEV_NAME_LEN];
+	unsigned long flags;
+	__u8 type;
+
+	__u16 pkt_type;
+	__u16 esco_type;
+	__u16 link_policy;
+	__u16 link_mode;
+
+	__u32 idle_timeout;
+	__u16 sniff_min_interval;
+	__u16 sniff_max_interval;
+
+	struct sk_buff *reassembly[3];
+
+	atomic_t promisc;
+};
+
+/** Define 'nfc' interface specific struct fm_dev */
+struct nfc_dev {
+	/** maybe could add some private member later */
+	char name[DEV_NAME_LEN];
+	unsigned long flags;
+};
+
+struct debug_dev {
+	/** maybe could add some private member later */
+	char name[DEV_NAME_LEN];
+	unsigned long flags;
+};
+
+/** This function frees m_dev allocation */
+void free_m_dev(struct m_dev *m_dev);
+
+/**
+ *  @brief This function receives frames
+ *
+ *  @param skb	A pointer to struct sk_buff
+ *  @return	0--success otherwise error code
+ */
+static inline int
+mdev_recv_frame(struct sk_buff *skb)
+{
+	struct m_dev *m_dev = (struct m_dev *)skb->dev;
+	if (!m_dev || (!test_bit(HCI_UP, &m_dev->flags)
+		       && !test_bit(HCI_INIT, &m_dev->flags))) {
+		kfree_skb(skb);
+		return -ENXIO;
+	}
+
+	/* Incomming skb */
+	bt_cb(skb)->incoming = 1;
+
+	/* Time stamp */
+	__net_timestamp(skb);
+
+	/* Queue frame for rx task */
+	skb_queue_tail(&m_dev->rx_q, skb);
+
+	/* Wakeup rx thread */
+	wake_up_interruptible(&m_dev->req_wait_q);
+
+	return 0;
+}
+
+/**
+ *  @brief mbt dev suspend handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_suspend_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+/**
+ *  @brief mbt dev resume handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_resume_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+#endif /* _HCI_WRAPPER_H_ */
diff --git a/bt_sd8897/bt/mbt_char.c b/bt_sd8897/bt/mbt_char.c
new file mode 100644
index 0000000..22f650a
--- /dev/null
+++ b/bt_sd8897/bt/mbt_char.c
@@ -0,0 +1,815 @@
+/** @file mbt_char.c
+  *
+  * @brief This file contains the char device function calls
+  *
+  * Copyright (C) 2010-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/path.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+
+#include "bt_drv.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+#include <linux/sched/signal.h>
+#endif
+#include "mbt_char.h"
+
+static LIST_HEAD(char_dev_list);
+
+static DEFINE_SPINLOCK(char_dev_list_lock);
+
+static int mbtchar_major = MBTCHAR_MAJOR_NUM;
+
+/**
+ *	@brief  Gets char device structure
+ *
+ *	@param dev		A pointer to char_dev
+ *
+ *	@return			kobject structure
+ */
+struct kobject *
+chardev_get(struct char_dev *dev)
+{
+	struct kobject *kobj;
+
+	kobj = bt_priv_get(dev->m_dev->driver_data);
+	if (!kobj)
+		return NULL;
+	PRINTM(INFO, "dev get kobj\n");
+	kobj = kobject_get(&dev->kobj);
+	if (!kobj)
+		bt_priv_put(dev->m_dev->driver_data);
+	return kobj;
+}
+
+/**
+ *	@brief  Prints char device structure
+ *
+ *	@param dev		A pointer to char_dev
+ *
+ *	@return			N/A
+ */
+void
+chardev_put(struct char_dev *dev)
+{
+	if (dev) {
+		struct m_dev *m_dev = dev->m_dev;
+		PRINTM(INFO, "dev put kobj\n");
+		kobject_put(&dev->kobj);
+		if (m_dev)
+			bt_priv_put(m_dev->driver_data);
+	}
+}
+
+/**
+ *	@brief Changes permissions of the dev
+ *
+ *	@param name	pointer to character
+ *	@param mode		mode_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chmod(char *name, mode_t mode)
+{
+	struct path path;
+	struct inode *inode;
+	struct iattr newattrs;
+	int ret;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chmod(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief Changes ownership of the dev
+ *
+ *	@param name	pointer to character
+ *	@param user		uid_t type data
+ *	@param group	gid_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chown(char *name, uid_t user, gid_t group)
+{
+	struct path path;
+	struct inode *inode = NULL;
+	struct iattr newattrs;
+	int ret = 0;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chown(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+	newattrs.ia_valid = ATTR_CTIME;
+	if (user != (uid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_UID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_uid = user;
+#else
+		newattrs.ia_uid = KUIDT_INIT(user);
+#endif
+	}
+	if (group != (gid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_GID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_gid = group;
+#else
+		newattrs.ia_gid = KGIDT_INIT(group);
+#endif
+	}
+	if (!S_ISDIR(inode->i_mode))
+		newattrs.ia_valid |=
+			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief write handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes written
+ */
+ssize_t
+chardev_write(struct file * filp, const char *buf, size_t count, loff_t * f_pos)
+{
+	int nwrite = 0;
+	struct sk_buff *skb;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	if (!test_bit(HCI_UP, &m_dev->flags)) {
+		LEAVE();
+		return -EBUSY;
+	}
+	nwrite = count;
+	skb = bt_skb_alloc(count, GFP_ATOMIC);
+	if (!skb) {
+		PRINTM(ERROR, "mbtchar_write(): fail to alloc skb\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	if (copy_from_user((void *)skb_put(skb, count), buf, count)) {
+		PRINTM(ERROR, "mbtchar_write(): cp_from_user failed\n");
+		kfree_skb(skb);
+		nwrite = -EFAULT;
+		goto exit;
+	}
+
+	skb->dev = (void *)m_dev;
+	bt_cb(skb)->pkt_type = *((unsigned char *)skb->data);
+	skb_pull(skb, 1);
+
+	PRINTM(DATA, "Write: pkt_type: 0x%x, len=%d @%lu\n",
+	       bt_cb(skb)->pkt_type, skb->len, jiffies);
+	DBG_HEXDUMP(DAT_D, "chardev_write", skb->data, skb->len);
+
+	/* Send skb to the hci wrapper layer */
+	if (m_dev->send(m_dev, skb)) {
+		PRINTM(ERROR, "Write: Fail\n");
+		nwrite = 0;
+		/* Send failed */
+		kfree_skb(skb);
+	}
+exit:
+	LEAVE();
+	return nwrite;
+}
+
+/**
+ *	@brief read handler for BT char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes read
+ */
+ssize_t
+chardev_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t ret = 0;
+	struct sk_buff *skb = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	/* Wait for rx data */
+	add_wait_queue(&m_dev->req_wait_q, &wait);
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		skb = skb_dequeue(&m_dev->rx_q);
+		if (skb)
+			break;
+		if (!test_bit(HCI_UP, &m_dev->flags)) {
+			ret = -EBUSY;
+			break;
+		}
+
+		if (filp->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			break;
+		}
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&m_dev->req_wait_q, &wait);
+
+	if (!skb)
+		goto out;
+
+	if (m_dev->read_continue_flag == 0) {
+		/* Put type byte before the data */
+		memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+		PRINTM(DATA, "Read: pkt_type: 0x%x, len=%d @%lu\n",
+		       bt_cb(skb)->pkt_type, skb->len, jiffies);
+	}
+	DBG_HEXDUMP(DAT_D, "chardev_read", skb->data, skb->len);
+	if (skb->len > count) {
+		/* user data length is smaller than the skb length */
+		if (copy_to_user(buf, skb->data, count)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		skb_pull(skb, count);
+		skb_queue_head(&m_dev->rx_q, skb);
+		m_dev->read_continue_flag = 1;
+		wake_up_interruptible(&m_dev->req_wait_q);
+		ret = count;
+		goto out;
+	} else {
+		if (copy_to_user(buf, skb->data, skb->len)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		m_dev->read_continue_flag = 0;
+		ret = skb->len;
+	}
+outf:
+	kfree_skb(skb);
+out:
+	if (m_dev->wait_rx_complete && skb_queue_empty(&m_dev->rx_q)) {
+		m_dev->rx_complete_flag = TRUE;
+		wake_up_interruptible(&m_dev->rx_wait_q);
+	}
+	LEAVE();
+	return ret;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+char_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, void *arg)
+#else
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+char_ioctl(struct file *filp, unsigned int cmd, void *arg)
+#endif
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+	case MBTCHAR_IOCTL_RELEASE:
+		m_dev->close(m_dev);
+		break;
+	case MBTCHAR_IOCTL_QUERY_TYPE:
+		m_dev->query(m_dev, arg);
+		break;
+	default:
+		m_dev->ioctl(m_dev, cmd, arg);
+		break;
+	}
+	LEAVE();
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl(struct inode *inode, struct file *filp,
+	      unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, (void *)arg);
+#else
+	return char_ioctl(filp, cmd, (void *)arg);
+#endif
+}
+
+#ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl_compat(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl_compat(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, compat_ptr(arg));
+#else
+	return char_ioctl(filp, cmd, compat_ptr(arg));
+#endif
+}
+#endif /* CONFIG_COMPAT */
+
+/**
+ *	@brief open handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_open(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = NULL;
+	struct m_dev *m_dev = NULL;
+	struct char_dev *cdev = NULL;
+	struct list_head *p = NULL;
+	ENTER();
+
+	list_for_each(p, &char_dev_list) {
+		cdev = list_entry(p, struct char_dev, list);
+		if (mbtchar_major == MAJOR(inode->i_cdev->dev) &&
+		    cdev->minor == MINOR(inode->i_cdev->dev)) {
+			dev = cdev;
+			break;
+		}
+	}
+	if (!dev) {
+		PRINTM(ERROR, "cannot find dev from inode\n");
+		LEAVE();
+		return -ENXIO;
+	}
+	if (!chardev_get(dev)) {
+		LEAVE();
+		return -ENXIO;
+	}
+	filp->private_data = dev;	/* for other methods */
+	m_dev = dev->m_dev;
+	mdev_req_lock(m_dev);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)
+	if (test_bit(HCI_UP, &m_dev->flags)) {
+		atomic_inc(&m_dev->extra_cnt);
+		goto done;
+	}
+#endif
+	if (m_dev->open(m_dev)) {
+		ret = -EIO;
+		goto done;
+	}
+	set_bit(HCI_UP, &m_dev->flags);
+
+done:
+	mdev_req_unlock(m_dev);
+	if (ret)
+		chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief release handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_release(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)
+	if (m_dev && (atomic_dec_if_positive(&m_dev->extra_cnt) >= 0)) {
+		LEAVE();
+		return ret;
+	}
+#endif
+	if (m_dev)
+		ret = dev->m_dev->close(dev->m_dev);
+	filp->private_data = NULL;
+	chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief poll handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param wait		pointer to poll_table structure
+ *	@return			mask
+ */
+static unsigned int
+chardev_poll(struct file *filp, poll_table * wait)
+{
+	unsigned int mask;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+
+	m_dev = dev->m_dev;
+	poll_wait(filp, &m_dev->req_wait_q, wait);
+	mask = POLLOUT | POLLWRNORM;
+	if (skb_peek(&m_dev->rx_q))
+		mask |= POLLIN | POLLRDNORM;
+	if (!test_bit(HCI_UP, &(m_dev->flags)))
+		mask |= POLLHUP;
+	PRINTM(INFO, "poll mask=0x%x\n", mask);
+	LEAVE();
+	return mask;
+}
+
+/* File ops for the Char driver */
+const struct file_operations chardev_fops = {
+	.owner = THIS_MODULE,
+	.read = chardev_read,
+	.write = chardev_write,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	.ioctl = chardev_ioctl,
+#else
+	.unlocked_ioctl = chardev_ioctl,
+#endif
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = chardev_ioctl_compat,
+#endif
+	.open = chardev_open,
+	.release = chardev_release,
+	.poll = chardev_poll,
+};
+
+/**
+ *	@brief This function creates the char dev
+ *
+ *	@param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param mod_name		A pointer to char
+ *  @param dev_name		A pointer to char
+ *	@return				0--success otherwise failure
+ */
+int
+register_char_dev(struct char_dev *dev, struct class *char_class,
+		  char *mod_name, char *dev_name)
+{
+	int ret = 0, dev_num;
+	unsigned long flags;
+	ENTER();
+	/* create the chrdev region */
+	if (mbtchar_major) {
+		dev_num = MKDEV(mbtchar_major, dev->minor);
+		ret = register_chrdev_region(dev_num, 1, mod_name);
+	} else {
+		PRINTM(INFO, "chardev: no major # yet\n");
+		ret = alloc_chrdev_region((dev_t *) & dev_num, dev->minor, 1,
+					  mod_name);
+	}
+
+	if (ret) {
+		PRINTM(ERROR, "chardev: create chrdev_region failed\n");
+		LEAVE();
+		return ret;
+	}
+	if (!mbtchar_major) {
+		/* Store the allocated dev major # */
+		mbtchar_major = MAJOR(dev_num);
+	}
+	dev->cdev = cdev_alloc();
+	dev->cdev->ops = &chardev_fops;
+	dev->cdev->owner = chardev_fops.owner;
+	dev_num = MKDEV(mbtchar_major, dev->minor);
+
+	if (cdev_add(dev->cdev, dev_num, 1)) {
+		PRINTM(ERROR, "chardev: cdev_add failed\n");
+		ret = -EFAULT;
+		goto free_cdev_region;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), NULL, dev_name);
+	}
+	if (dev->dev_type == NFC_TYPE) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), NULL, dev_name);
+	}
+	if (dev->dev_type == DEBUG_TYPE) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), NULL, dev_name);
+	}
+#else
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), dev_name);
+	}
+	if (dev->dev_type == NFC_TYPE) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), dev_name);
+	}
+	if (dev->dev_type == DEBUG_TYPE) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), dev_name);
+	}
+#endif
+	PRINTM(INFO, "register char dev=%s\n", dev_name);
+
+	/** modify later */
+
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_add_tail(&dev->list, &char_dev_list);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+
+	LEAVE();
+	return ret;
+free_cdev_region:
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief This function deletes the char dev
+ *
+ *  @param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param dev_name		A pointer to char
+ *  @return				0--success otherwise failure
+ */
+int
+unregister_char_dev(struct char_dev *dev, struct class *char_class,
+		    char *dev_name)
+{
+	ENTER();
+	device_destroy(char_class, MKDEV(mbtchar_major, dev->minor));
+	cdev_del(dev->cdev);
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	PRINTM(INFO, "unregister char dev=%s\n", dev_name);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param char_class	A pointer to class struct
+ *  @return				N/A
+ */
+void
+chardev_cleanup(struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	do {
+		dev = NULL;
+		list_for_each(p, &char_dev_list) {
+			dev = list_entry(p, struct char_dev, list);
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			unregister_char_dev(dev, char_class, dev->m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	} while (dev);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	class_destroy(char_class);
+	LEAVE();
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param m_dev	A pointer to m_dev struct
+ *  @param char_class	A pointer to class struct
+ *  @return			N/A
+ */
+void
+chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_for_each(p, &char_dev_list) {
+		dev = list_entry(p, struct char_dev, list);
+		if (dev->minor == m_dev->index) {
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			dev->m_dev = NULL;
+			unregister_char_dev(dev, char_class, m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	LEAVE();
+}
diff --git a/bt_sd8897/bt/mbt_char.h b/bt_sd8897/bt/mbt_char.h
new file mode 100644
index 0000000..9997a38
--- /dev/null
+++ b/bt_sd8897/bt/mbt_char.h
@@ -0,0 +1,72 @@
+/** @file mbt_char.h
+  *
+  * @brief This file contains mbtchar driver specific defines etc
+  *
+  * Copyright (C) 2010-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+#ifndef __MBT_CHAR_H__
+#define __MBT_CHAR_H__
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+
+/** Define ioctl */
+#define MBTCHAR_IOCTL_RELEASE       _IO('M', 1)
+#define MBTCHAR_IOCTL_QUERY_TYPE    _IO('M', 2)
+#ifdef BLE_WAKEUP
+#define MBTCHAR_IOCTL_BLE_WAKEUP_PARAM _IO('M', 4)
+#endif
+
+#define MBTCHAR_MAJOR_NUM            (0)
+
+/** Interface specific macros */
+#define MBTCHAR_MINOR_BASE           (0)
+#define FMCHAR_MINOR_BASE            (10)
+#define NFCCHAR_MINOR_BASE           (20)
+#define DEBUGCHAR_MINOR_BASE         (30)
+
+/** Declaration of char_dev struct */
+struct char_dev {
+	struct list_head list;
+	int minor;
+	int dev_type;
+	struct cdev *cdev;
+	struct m_dev *m_dev;
+	struct kobject kobj;
+};
+
+/** Changes permissions of the dev */
+int mbtchar_chmod(char *name, mode_t mode);
+
+/** Changes ownership of the dev */
+int mbtchar_chown(char *name, uid_t user, gid_t group);
+
+/**	This function creates the char dev */
+int register_char_dev(struct char_dev *dev, struct class *char_class,
+		      char *mod_name, char *dev_name);
+
+/**	This function deletes the char dev */
+int unregister_char_dev(struct char_dev *dev, struct class *char_class,
+			char *dev_name);
+
+/**	This function cleans module */
+void chardev_cleanup(struct class *char_class);
+
+/**	This function cleans module */
+void chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class);
+
+#endif /*__MBT_CHAR_H__*/
diff --git a/bt_sd8897/config/bt_cal_data.conf b/bt_sd8897/config/bt_cal_data.conf
new file mode 100644
index 0000000..13aac4e
--- /dev/null
+++ b/bt_sd8897/config/bt_cal_data.conf
@@ -0,0 +1,5 @@
+00 1C 01 37 FF FF FF FF 02 04 7F 01
+CE BA 00 00 00 2D C6 C0 00 00 00 00
+00 F0 00 00
+
+
diff --git a/bt_sd8897/config/bt_init_cfg.conf b/bt_sd8897/config/bt_init_cfg.conf
new file mode 100644
index 0000000..deb5a63
--- /dev/null
+++ b/bt_sd8897/config/bt_init_cfg.conf
@@ -0,0 +1,11 @@
+# File: init_cfg_.conf
+
+# MAC address (interface: address)
+#ifdef BT_HCI_BLUEZ
+mac_addr= hci0: 00:50:43:20:43:21
+#else
+mac_addr= mbtchar0: 00:50:43:20:43:21
+#endif
+# Register (type, offset, value)
+bt_reg=2,0x00000026,0x0040
+
diff --git a/bt_sd8987/Makefile b/bt_sd8987/Makefile
new file mode 100644
index 0000000..40037dd
--- /dev/null
+++ b/bt_sd8987/Makefile
@@ -0,0 +1,188 @@
+# File: Makefile
+# Copyright (C) 2007-2018, Marvell International Ltd.
+#
+
+CC=		$(CROSS_COMPILE)clang
+LD=		$(CROSS_COMPILE)ld.lld
+
+BACKUP=		/root/backup
+YMD=		`date +%Y%m%d%H%M`
+
+#############################################################################
+# Configuration Options
+#############################################################################
+
+# Debug Option
+# DEBUG LEVEL n/1/2:
+# n: NO DEBUG
+# 1: PRINTM(MSG,...), PRINTM(FATAL,...), PRINTM(WARN,...) and PRINTM(INFO,...)
+# 2: All PRINTM()
+CONFIG_DEBUG=1
+
+
+# SDIO suspend/resume
+CONFIG_SDIO_SUSPEND_RESUME=y
+
+
+CONFIG_BLE_WAKEUP=y
+
+#############################################################################
+# Select Platform Tools
+#############################################################################
+
+MODEXT = ko
+
+ifeq ($(CONFIG_64BIT), y)
+	EXTRA_CFLAGS += -DMBT_64BIT
+endif
+
+ifeq ($(CONFIG_T50), y)
+        EXTRA_CFLAGS += -DT50
+        EXTRA_CFLAGS += -DT40
+        EXTRA_CFLAGS += -DT3T
+endif
+
+ifeq ($(CONFIG_BLE_WAKEUP), y)
+        EXTRA_CFLAGS += -DBLE_WAKEUP
+endif
+
+
+
+
+
+KERNELDIR?=KBUILD_SRC
+
+EXTRA_CFLAGS += -I$(KERNELDIR)/include
+
+EXTRA_CFLAGS += -I$(M)/../mbtchar_src
+EXTRA_CFLAGS += -I$(M)/bt
+LD += -S
+
+#ifdef SD8xxx
+BINDIR = ../bin_sd8xxx_btchar
+#endif
+BINDIR = ../bin_sd8987_btchar
+
+
+#############################################################################
+# Compiler Flags
+#############################################################################
+	EXTRA_CFLAGS += -DFPNUM='"36"'
+
+ifeq ($(CONFIG_DEBUG),1)
+	EXTRA_CFLAGS += -DDEBUG_LEVEL1
+endif
+
+ifeq ($(CONFIG_DEBUG),2)
+	EXTRA_CFLAGS += -DDEBUG_LEVEL1
+	EXTRA_CFLAGS += -DDEBUG_LEVEL2
+	DBG=	-dbg
+endif
+
+ifeq ($(CONFIG_SDIO_SUSPEND_RESUME),y)
+	EXTRA_CFLAGS += -DSDIO_SUSPEND_RESUME
+endif
+
+#############################################################################
+# Make Targets
+#############################################################################
+
+BT_CHAR_OBJS = bt_char/bt_main.o bt_char/bt_sdiommc.o bt_char/bt_proc.o bt_char/mbt_char.o
+BT_CHAR_OBJS += bt_char/bt_init.o
+
+BT_BLOCK_OBJS = bt/bt_main.o bt/bt_sdiommc.o bt/bt_proc.o bt/mbt_char.o
+BT_BLOCK_OBJS += bt/bt_init.o
+
+ifneq ($(KERNELRELEASE),)
+
+ifneq ($(CONFIG_BERLIN_SDIO_BT_8987_CHAR_DRV),)
+
+BTOBJS = bt_char/bt_main.o bt_char/bt_sdiommc.o bt_char/bt_proc.o bt_char/mbt_char.o
+BTOBJS += bt_char/bt_init.o
+obj-$(CONFIG_BERLIN_SDIO_BT_8987_CHAR_DRV) := bt8xxx.o
+
+else
+
+BTOBJS = bt/bt_main.o bt/bt_sdiommc.o bt/bt_proc.o bt/mbt_char.o
+BTOBJS += bt/bt_init.o
+obj-m := bt8xxx.o
+
+endif
+
+obj-$(MODULE_LINK) := bt8xxx.o
+bt8xxx-objs := $(BTOBJS)
+
+
+
+# Otherwise we were called directly from the command line; invoke the kernel build system.
+else
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) modules
+endif
+
+###############################################################
+
+export		CC LD EXTRA_CFLAGS KERNELDIR
+
+.PHONY: app/fm_app clean distclean
+
+app/fm_app:
+	$(MAKE) -C  $@
+
+echo:
+
+build:		echo default
+
+	@if [ ! -d $(BINDIR) ]; then \
+		mkdir $(BINDIR); \
+	fi
+
+ifeq ($(CONFIG_MULTI_INTERFACE), y)
+	cp -f mbt8xxx_sdio.$(MODEXT) $(BINDIR)/mbt8987_sdio$(DBG).$(MODEXT)
+else
+	cp -f mbt8xxx.$(MODEXT) $(BINDIR)/mbt8987$(DBG).$(MODEXT)
+endif
+	cp -r config $(BINDIR)
+
+
+
+
+
+	cp -f README $(BINDIR)
+
+	$(MAKE) -C app/fm_app $@ INSTALLDIR=$(BINDIR);
+	cp -f app/fm_app/fmapp $(BINDIR);
+
+clean:
+	-find . -name "*.o" -exec rm {} \;
+	-find . -name "*.ko" -exec rm {} \;
+	-find . -name ".*.cmd" -exec rm {} \;
+	-find . -name "*.mod.c" -exec rm {} \;
+	-find . -name "*.symvers" -exec rm {} \;
+	-find . -name "modules.order" -exec rm {} \;
+	-find . -name ".*.dwo" -exec rm {} \;
+	-find . -name "*dwo" -exec rm {} \;
+	-rm -rf .tmp_versions
+	$(MAKE) -C app/fm_app $@
+
+install: default
+
+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
+	$(MAKE) -C app/fm_app $@
+# End of file;
+
diff --git a/bt_sd8987/bt/bt_drv.h b/bt_sd8987/bt/bt_drv.h
new file mode 100644
index 0000000..aa6fa19
--- /dev/null
+++ b/bt_sd8987/bt/bt_drv.h
@@ -0,0 +1,885 @@
+/** @file bt_drv.h
+ *  @brief This header file contains global constant/enum definitions,
+ *  global variable declaration.
+ *
+ *  Copyright (C) 2007-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_DRV_H_
+#define _BT_DRV_H_
+
+#include <linux/version.h>
+#include <linux/kthread.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+
+#include "hci_wrapper.h"
+
+/** MAX adapter BT driver supported */
+#define MAX_BT_ADAPTER    3
+
+#ifndef BIT
+/** BIT definition */
+#define BIT(x) (1UL << (x))
+#endif
+
+#ifdef MBT_64BIT
+typedef u64 t_ptr;
+#else
+typedef u32 t_ptr;
+#endif
+
+/** max number of adapter supported */
+#define MAX_BT_ADAPTER      3
+/** Define drv_mode bit */
+#define DRV_MODE_BT         BIT(0)
+
+/** Define devFeature bit */
+#define DEV_FEATURE_BT     BIT(0)
+#define DEV_FEATURE_BTAMP     BIT(1)
+#define DEV_FEATURE_BLE     BIT(2)
+
+/** Define maximum number of radio func supported */
+#define MAX_RADIO_FUNC     3
+
+/** MAC address print format */
+#ifndef MACSTR
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+
+/** MAC address print arguments */
+#ifndef MAC2STR
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#endif
+
+/** Debug level : Message */
+#define	DBG_MSG			BIT(0)
+/** Debug level : Fatal */
+#define DBG_FATAL		BIT(1)
+/** Debug level : Error */
+#define DBG_ERROR		BIT(2)
+/** Debug level : Data */
+#define DBG_DATA		BIT(3)
+/** Debug level : Command */
+#define DBG_CMD			BIT(4)
+/** Debug level : Event */
+#define DBG_EVENT		BIT(5)
+/** Debug level : Interrupt */
+#define DBG_INTR		BIT(6)
+
+/** Debug entry : Data dump */
+#define DBG_DAT_D		BIT(16)
+/** Debug entry : Data dump */
+#define DBG_CMD_D		BIT(17)
+
+/** Debug level : Entry */
+#define DBG_ENTRY		BIT(28)
+/** Debug level : Warning */
+#define DBG_WARN		BIT(29)
+/** Debug level : Informative */
+#define DBG_INFO		BIT(30)
+
+#ifdef	DEBUG_LEVEL1
+extern u32 mbt_drvdbg;
+
+#ifdef	DEBUG_LEVEL2
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  \
+	do {if (mbt_drvdbg & DBG_INFO)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...) \
+	do {if (mbt_drvdbg & DBG_WARN)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) \
+	do {if (mbt_drvdbg & DBG_ENTRY) \
+		printk(KERN_DEBUG msg); } while (0)
+#else
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  do {} while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...)  do {} while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) do {} while (0)
+#endif /* DEBUG_LEVEL2 */
+
+/** Print interrupt message */
+#define	PRINTM_INTR(msg...)  \
+	do {if (mbt_drvdbg & DBG_INTR)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print event message */
+#define	PRINTM_EVENT(msg...) \
+	do {if (mbt_drvdbg & DBG_EVENT) \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print command message */
+#define	PRINTM_CMD(msg...)   \
+	do {if (mbt_drvdbg & DBG_CMD)   \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data message */
+#define	PRINTM_DATA(msg...)  \
+	do {if (mbt_drvdbg & DBG_DATA)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print error message */
+#define	PRINTM_ERROR(msg...) \
+	do {if (mbt_drvdbg & DBG_ERROR) \
+		printk(KERN_ERR msg); } while (0)
+/** Print fatal message */
+#define	PRINTM_FATAL(msg...) \
+	do {if (mbt_drvdbg & DBG_FATAL) \
+		printk(KERN_ERR msg); } while (0)
+/** Print message */
+#define	PRINTM_MSG(msg...)   \
+	do {if (mbt_drvdbg & DBG_MSG)   \
+		printk(KERN_ALERT msg); } while (0)
+
+/** Print data dump message */
+#define	PRINTM_DAT_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_DAT_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data dump message */
+#define	PRINTM_CMD_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_CMD_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+
+/** Print message with required level */
+#define	PRINTM(level, msg...) PRINTM_##level(msg)
+
+/** Debug dump buffer length */
+#define DBG_DUMP_BUF_LEN	64
+/** Maximum number of dump per line */
+#define MAX_DUMP_PER_LINE	16
+/** Maximum data dump length */
+#define MAX_DATA_DUMP_LEN	48
+
+/**
+ * @brief Prints buffer data upto provided length
+ *
+ * @param prompt          Char pointer
+ * @param buf			  Buffer
+ * @param len    		  Length
+ *
+ * @return                N/A
+ */
+static inline void
+hexdump(char *prompt, u8 *buf, int len)
+{
+	int i;
+	char dbgdumpbuf[DBG_DUMP_BUF_LEN];
+	char *ptr = dbgdumpbuf;
+
+	printk(KERN_DEBUG "%s: len=%d\n", prompt, len);
+	for (i = 1; i <= len; i++) {
+		ptr += snprintf(ptr, 4, "%02x ", *buf);
+		buf++;
+		if (i % MAX_DUMP_PER_LINE == 0) {
+			*ptr = 0;
+			printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+			ptr = dbgdumpbuf;
+		}
+	}
+	if (len % MAX_DUMP_PER_LINE) {
+		*ptr = 0;
+		printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+	}
+}
+
+/** Debug hexdump of debug data */
+#define DBG_HEXDUMP_DAT_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_DAT_D) \
+		hexdump(x, y, z); } while (0)
+/** Debug hexdump of debug command */
+#define DBG_HEXDUMP_CMD_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_CMD_D) \
+		hexdump(x, y, z); } while (0)
+
+/** Debug hexdump */
+#define	DBG_HEXDUMP(level, x, y, z)    DBG_HEXDUMP_##level(x, y, z)
+
+/** Mark entry point */
+#define	ENTER()			PRINTM(ENTRY, "Enter: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+/** Mark exit point */
+#define	LEAVE()			PRINTM(ENTRY, "Leave: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+#else
+/** Do nothing */
+#define	PRINTM(level, msg...) do {} while (0)
+/** Do nothing */
+#define DBG_HEXDUMP(level, x, y, z)    do {} while (0)
+/** Do nothing */
+#define	ENTER()  do {} while (0)
+/** Do nothing */
+#define	LEAVE()  do {} while (0)
+#endif /* DEBUG_LEVEL1 */
+
+/** Bluetooth upload size */
+#define	BT_UPLD_SIZE				2312
+/** Bluetooth status success */
+#define BT_STATUS_SUCCESS			(0)
+/** Bluetooth status pending */
+#define BT_STATUS_PENDING           (1)
+/** Bluetooth status failure */
+#define BT_STATUS_FAILURE			(-1)
+
+#ifndef	TRUE
+/** True value */
+#define TRUE			1
+#endif
+#ifndef	FALSE
+/** False value */
+#define	FALSE			0
+#endif
+
+/** Set thread state */
+#define OS_SET_THREAD_STATE(x)		set_current_state(x)
+/** Time to wait until Host Sleep state change in millisecond */
+#define WAIT_UNTIL_HS_STATE_CHANGED 2000
+/** Time to wait cmd resp in millisecond */
+#define WAIT_UNTIL_CMD_RESP	    5000
+
+/** Sleep until a condition gets true or a timeout elapses */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	interruptible_sleep_on_timeout(&waitq, ((timeout) * HZ / 1000))
+#else
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
+#endif
+
+#define os_wait_timeout(waitq, cond, timeout) \
+         wait_event_timeout(waitq, cond, ((timeout) * HZ / 1000))
+
+/** bt thread structure */
+typedef struct {
+	/** Task */
+	struct task_struct *task;
+	/** Queue */
+	wait_queue_head_t waitQ;
+	/** PID */
+	pid_t pid;
+	/** Private structure */
+	void *priv;
+} bt_thread;
+
+/**
+ * @brief Activates bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline void
+bt_activate_thread(bt_thread *thr)
+{
+	/** Initialize the wait queue */
+	init_waitqueue_head(&thr->waitQ);
+
+	/** Record the thread pid */
+	thr->pid = current->pid;
+}
+
+/**
+ * @brief De-activates bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline void
+bt_deactivate_thread(bt_thread *thr)
+{
+	thr->pid = 0;
+	return;
+}
+
+/**
+ * @brief Creates bt thread
+ *
+ * @param btfunc          Function pointer
+ * @param thr			  A pointer to bt_thread structure
+ * @param name    		  Char pointer
+ *
+ * @return                N/A
+ */
+static inline void
+bt_create_thread(int (*btfunc) (void *), bt_thread *thr, char *name)
+{
+	thr->task = kthread_run(btfunc, thr, "%s", name);
+}
+
+/**
+ * @brief Delete bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline int
+bt_terminate_thread(bt_thread *thr)
+{
+	/* Check if the thread is active or not */
+	if (!thr->pid)
+		return -1;
+
+	kthread_stop(thr->task);
+	return 0;
+}
+
+/**
+ * @brief  Set scheduled timeout
+ *
+ * @param millisec		 Time unit in ms
+ *
+ * @return                N/A
+ */
+static inline void
+os_sched_timeout(u32 millisec)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	schedule_timeout((millisec * HZ) / 1000);
+}
+
+#ifndef __ATTRIB_ALIGN__
+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
+#endif
+
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__ __attribute__((packed))
+#endif
+
+/** Data structure for the Marvell Bluetooth device */
+typedef struct _bt_dev {
+	/** device name */
+	char name[DEV_NAME_LEN];
+	/** card pointer */
+	void *card;
+	/** IO port */
+	u32 ioport;
+	/** m_dev structure */
+	struct m_dev m_dev[MAX_RADIO_FUNC];
+
+	/** Tx download ready flag */
+	u8 tx_dnld_rdy;
+	/** Function */
+	u8 fn;
+	/** Rx unit */
+	u8 rx_unit;
+	/** Power Save mode : Timeout configuration */
+	u16 idle_timeout;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save command */
+	u8 pscmd;
+	/** Host Sleep mode */
+	u8 hsmode;
+	/** Host Sleep command */
+	u8 hscmd;
+	/** Low byte is gap, high byte is GPIO */
+	u16 gpio_gap;
+	/** Host Sleep configuration command */
+	u8 hscfgcmd;
+	/** Host Send Cmd Flag		 */
+	u8 sendcmdflag;
+	/** opcode for Send Cmd */
+	u16 send_cmd_opcode;
+	/** Device Type			*/
+	u8 devType;
+	/** Device Features    */
+	u8 devFeature;
+	/** cmd52 function */
+	u8 cmd52_func;
+	/** cmd52 register */
+	u8 cmd52_reg;
+	/** cmd52 value */
+	u8 cmd52_val;
+	/** SDIO pull control command */
+	u8 sdio_pull_ctrl;
+	/** Low 2 bytes is pullUp, high 2 bytes for pull-down */
+	u32 sdio_pull_cfg;
+	/** Test mode command */
+	u8 test_mode;
+} bt_dev_t, *pbt_dev_t;
+
+/** Marvell bt adapter structure */
+typedef struct _bt_adapter {
+	/** Chip revision ID */
+	u8 chip_rev;
+    /** magic val */
+	u8 magic_val;
+	/** Surprise removed flag */
+	u8 SurpriseRemoved;
+	/** IRQ number */
+	int irq;
+	/** Interrupt counter */
+	u32 IntCounter;
+	/** Tx packet queue */
+	struct sk_buff_head tx_queue;
+
+	/** Pointer of fw dump file name */
+	char *fwdump_fname;
+	/** Pending Tx packet queue */
+	struct sk_buff_head pending_queue;
+	/** tx lock flag */
+	u8 tx_lock;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save state */
+	u8 ps_state;
+	/** Host Sleep state */
+	u8 hs_state;
+	/** hs skip count */
+	u32 hs_skip;
+	/** suspend_fail flag */
+	u8 suspend_fail;
+	/** suspended flag */
+	u8 is_suspended;
+	/** Number of wakeup tries */
+	u8 WakeupTries;
+	/** Host Sleep wait queue */
+	wait_queue_head_t cmd_wait_q __ATTRIB_ALIGN__;
+	/** Host Cmd complet state */
+	u8 cmd_complete;
+	/** indicate using wait event timeout */
+	u8 wait_event_timeout;
+	/** last irq recv */
+	u8 irq_recv;
+	/** last irq processed */
+	u8 irq_done;
+	/** sdio int status */
+	u8 sd_ireg;
+     /** buf allocated for transmit */
+	u8 *tx_buffer;
+    /** buf for transmit */
+	u8 *tx_buf;
+    /** buf allocated for read interrupt status */
+	u8 *hw_regs_buf;
+    /** buf for read interrupt status */
+	u8 *hw_regs;
+	/** tx pending */
+	u32 skb_pending;
+/** Version string buffer length */
+#define MAX_VER_STR_LEN         128
+	/** Driver version */
+	u8 drv_ver[MAX_VER_STR_LEN];
+	/** Number of command timeout */
+	u32 num_cmd_timeout;
+} bt_adapter, *pbt_adapter;
+
+/** Length of prov name */
+#define PROC_NAME_LEN				32
+
+/** Item data structure */
+struct item_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** Size */
+	u32 size;
+	/** Address */
+	t_ptr addr;
+	/** Offset */
+	u32 offset;
+	/** Flag */
+	u32 flag;
+};
+
+/** Proc private data structure */
+struct proc_private_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** File flag */
+	u32 fileflag;
+	/** Buffer size */
+	u32 bufsize;
+	/** Number of items */
+	u32 num_items;
+	/** Item data */
+	struct item_data *pdata;
+	/** Private structure */
+	struct _bt_private *pbt;
+	/** File operations */
+	const struct file_operations *fops;
+};
+
+/** Device proc structure */
+struct device_proc {
+	/** Proc directory entry */
+	struct proc_dir_entry *proc_entry;
+	/** num of proc files */
+	u8 num_proc_files;
+	/** pointer to proc_private_data */
+	struct proc_private_data *pfiles;
+};
+
+/** Private structure for the MV device */
+typedef struct _bt_private {
+	/** Bluetooth device */
+	bt_dev_t bt_dev;
+	/** Adapter */
+	bt_adapter *adapter;
+	/** Firmware helper */
+	const struct firmware *fw_helper;
+	/** Firmware */
+	const struct firmware *firmware;
+	/** Init user configure file */
+	const struct firmware *init_user_cfg;
+	/** Init user configure wait queue token */
+	u16 init_user_conf_wait_flag;
+	/** Init user configure file wait queue */
+	wait_queue_head_t init_user_conf_wait_q __ATTRIB_ALIGN__;
+	/** Firmware request start time */
+	struct timeval req_fw_time;
+	/** Hotplug device */
+	struct device *hotplug_device;
+	/** thread to service interrupts */
+	bt_thread MainThread;
+	 /** proc data */
+	struct device_proc dev_proc[MAX_RADIO_FUNC];
+	/** Driver lock */
+	spinlock_t driver_lock;
+	/** Driver lock flags */
+	ulong driver_flags;
+	/** Driver reference flags */
+	struct kobject kobj;
+	/** CRC check flag */
+	u16 fw_crc_check;
+	/** Card type */
+	u16 card_type;
+	/** sdio device */
+	const struct sdio_device *psdio_device;
+	u8 fw_reload;
+    /** fw dump state */
+	u8 fw_dump;
+} bt_private, *pbt_private;
+
+/** Disable interrupt */
+#define OS_INT_DISABLE	spin_lock_irqsave(&priv->driver_lock, \
+						priv->driver_flags)
+/** Enable interrupt */
+#define	OS_INT_RESTORE	spin_unlock_irqrestore(&priv->driver_lock, \
+						priv->driver_flags)
+
+#ifndef HCI_BT_AMP
+/** BT_AMP flag for device type */
+#define  HCI_BT_AMP		0x80
+#endif
+
+/** Device type of BT */
+#define DEV_TYPE_BT		0x00
+/** Device type of AMP */
+#define DEV_TYPE_AMP		0x01
+
+/** Marvell vendor packet */
+#define MRVL_VENDOR_PKT			0xFE
+
+/** Bluetooth command : Get FW Version */
+#define BT_CMD_GET_FW_VERSION       0x0F
+/** Bluetooth command : Sleep mode */
+#define BT_CMD_AUTO_SLEEP_MODE		0x23
+/** Bluetooth command : Host Sleep configuration */
+#define BT_CMD_HOST_SLEEP_CONFIG	0x59
+/** Bluetooth command : Host Sleep enable */
+#define BT_CMD_HOST_SLEEP_ENABLE	0x5A
+/** Bluetooth command : Module Configuration request */
+#define BT_CMD_MODULE_CFG_REQ		0x5B
+/** Bluetooth command : PMIC Configure */
+#define BT_CMD_PMIC_CONFIGURE           0x7D
+
+/** Bluetooth command : SDIO pull up down configuration request */
+#define BT_CMD_SDIO_PULL_CFG_REQ	0x69
+/** Bluetooth command : Set Evt Filter Command */
+#define BT_CMD_SET_EVT_FILTER		0x05
+/** Bluetooth command : Enable Write Scan Command */
+#define BT_CMD_ENABLE_WRITE_SCAN	0x1A
+/** Bluetooth command : Enable Device under test mode */
+#define BT_CMD_ENABLE_DEVICE_TESTMODE	0x03
+/** Sub Command: Module Bring Up Request */
+#define MODULE_BRINGUP_REQ		0xF1
+/** Sub Command: Module Shut Down Request */
+#define MODULE_SHUTDOWN_REQ		0xF2
+/** Module already up */
+#define MODULE_CFG_RESP_ALREADY_UP      0x0c
+/** Sub Command: Host Interface Control Request */
+#define MODULE_INTERFACE_CTRL_REQ	0xF5
+
+/** Bluetooth event : Power State */
+#define BT_EVENT_POWER_STATE		0x20
+
+/** Bluetooth Power State : Enable */
+#define BT_PS_ENABLE			0x02
+/** Bluetooth Power State : Disable */
+#define BT_PS_DISABLE			0x03
+/** Bluetooth Power State : Sleep */
+#define BT_PS_SLEEP			0x01
+/** Bluetooth Power State : Awake */
+#define BT_PS_AWAKE			0x02
+
+/** Vendor OGF */
+#define VENDOR_OGF				0x3F
+/** OGF for reset */
+#define RESET_OGF		0x03
+/** Bluetooth command : Reset */
+#define BT_CMD_RESET	0x03
+
+/** Host Sleep activated */
+#define HS_ACTIVATED			0x01
+/** Host Sleep deactivated */
+#define HS_DEACTIVATED			0x00
+
+/** Power Save sleep */
+#define PS_SLEEP			0x01
+/** Power Save awake */
+#define PS_AWAKE			0x00
+
+/** bt header length */
+#define BT_HEADER_LEN			4
+
+#ifndef MAX
+/** Return maximum of two */
+#define MAX(a, b)		((a) > (b) ? (a) : (b))
+#endif
+
+/** This is for firmware specific length */
+#define EXTRA_LEN	36
+
+/** Command buffer size for Marvell driver */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+
+/** Bluetooth Rx packet buffer size for Marvell driver */
+#define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \
+	(HCI_MAX_FRAME_SIZE + EXTRA_LEN)
+
+/** Buffer size to allocate */
+#define ALLOC_BUF_SIZE	(((MAX(MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \
+			MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \
+			+ SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
+
+/** Request FW timeout in second */
+#define REQUEST_FW_TIMEOUT		30
+
+/** 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
+
+/** default idle time */
+#define DEFAULT_IDLE_TIME           1000
+
+#define BT_CMD_HEADER_SIZE    3
+
+#define BT_CMD_DATA_LEN    128
+#define BT_EVT_DATA_LEN    8
+
+/** BT command structure */
+typedef struct _BT_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[BT_CMD_DATA_LEN];
+} __ATTRIB_PACK__ BT_CMD;
+
+/** BT event structure */
+typedef struct _BT_EVENT {
+	/** Event Counter */
+	u8 EC;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[BT_EVT_DATA_LEN];
+} BT_EVENT;
+
+#if defined(SDIO_SUSPEND_RESUME)
+#define DEF_GPIO_GAP        0xffff
+#endif
+
+/** This function verify the received event pkt */
+int check_evtpkt(bt_private *priv, struct sk_buff *skb);
+
+/* Prototype of global function */
+/** This function gets the priv reference */
+struct kobject *bt_priv_get(bt_private *priv);
+/** This function release the priv reference */
+void bt_priv_put(bt_private *priv);
+/** This function adds the card */
+bt_private *bt_add_card(void *card);
+/** This function removes the card */
+int bt_remove_card(void *card);
+/** This function handles the interrupt */
+void bt_interrupt(struct m_dev *m_dev);
+
+/** This function creates proc interface directory structure */
+int bt_root_proc_init(void);
+/** This function removes proc interface directory structure */
+int bt_root_proc_remove(void);
+/** This function initializes proc entry */
+int bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq);
+/** This function removes proc interface */
+void bt_proc_remove(bt_private *priv);
+
+/** This function process the received event */
+int bt_process_event(bt_private *priv, struct sk_buff *skb);
+/** This function enables host sleep */
+int bt_enable_hs(bt_private *priv, bool is_shutdown);
+/** This function used to send command to firmware */
+int bt_prepare_command(bt_private *priv);
+/** This function frees the structure of adapter */
+void bt_free_adapter(bt_private *priv);
+/** This function handle the receive packet */
+void bt_recv_frame(bt_private *priv, struct sk_buff *skb);
+void bt_store_firmware_dump(bt_private *priv, u8 *buf, u32 len);
+
+/** clean up m_devs */
+void clean_up_m_devs(bt_private *priv);
+/** bt driver call this function to register to bus driver */
+int *sbi_register(void);
+/** bt driver call this function to unregister to bus driver */
+void sbi_unregister(void);
+/** bt driver calls this function to register the device  */
+int sbi_register_dev(bt_private *priv);
+/** bt driver calls this function to unregister the device */
+int sbi_unregister_dev(bt_private *priv);
+/** This function initializes firmware */
+int sbi_download_fw(bt_private *priv);
+/** Configures hardware to quit deep sleep state */
+int sbi_wakeup_firmware(bt_private *priv);
+/** Module configuration and register device */
+int sbi_register_conf_dpc(bt_private *priv);
+
+/** This function is used to send the data/cmd to hardware */
+int sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb);
+/** This function reads the current interrupt status register */
+int sbi_get_int_status(bt_private *priv);
+/** This function enables the host interrupts */
+int sbi_enable_host_int(bt_private *priv);
+/** This function disables the host interrupts */
+int sbi_disable_host_int(bt_private *priv);
+
+/** bt fw reload flag */
+extern int bt_fw_reload;
+/** 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
+/** This function reload firmware */
+void bt_request_fw_reload(bt_private *priv, int mode);
+#define MAX_TX_BUF_SIZE     2312
+/** This function downloads firmware image to the card */
+int sd_download_firmware_w_helper(bt_private *priv);
+void bt_dump_sdio_regs(bt_private *priv);
+#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
+/* dumps the firmware to /var/ or /data/ */
+void bt_dump_firmware_info_v2(bt_private *priv);
+
+/** 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
+
+/** Bluetooth command : Mac address configuration */
+#define BT_CMD_CONFIG_MAC_ADDR		0x22
+/** Bluetooth command : Write CSU register */
+#define BT_CMD_CSU_WRITE_REG		0x66
+/** Bluetooth command : Load calibrate data */
+#define BT_CMD_LOAD_CONFIG_DATA     0x61
+/** Bluetooth command : Load calibrate ext data */
+#define BT_CMD_LOAD_CONFIG_DATA_EXT     0x60
+
+/** Bluetooth command : BLE deepsleep */
+#define BT_CMD_BLE_DEEP_SLEEP       0x8b
+
+/** BT_BLE command structure */
+typedef struct _BT_BLE_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** deepsleep flag */
+	u8 deepsleep;
+} __ATTRIB_PACK__ BT_BLE_CMD;
+
+/** BT_CSU command structure */
+typedef struct _BT_CSU_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** reg type */
+	u8 type;
+	/** address */
+	u8 offset[4];
+	/** Data */
+	u8 value[2];
+} __ATTRIB_PACK__ BT_CSU_CMD;
+
+/** This function sets mac address */
+int bt_set_mac_address(bt_private *priv, u8 *mac);
+/** This function writes value to CSU registers */
+int bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value);
+/** BT set user defined init data and param */
+int bt_init_config(bt_private *priv, char *cfg_file);
+/** BT PMIC Configure command */
+int bt_pmic_configure(bt_private *priv);
+/** This function load the calibrate data */
+int bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac);
+/** This function load the calibrate ext data */
+int bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len);
+/** BT set user defined calibration data */
+int bt_cal_config(bt_private *priv, char *cfg_file, char *mac);
+/** BT set user defined calibration ext data */
+int bt_cal_config_ext(bt_private *priv, char *cfg_file);
+int bt_init_mac_address(bt_private *priv, char *mac);
+
+int bt_set_independent_reset(bt_private *priv);
+/** Bluetooth command : Independent reset */
+#define BT_CMD_INDEPENDENT_RESET     0x0D
+
+/** BT HCI command structure */
+typedef struct _BT_HCI_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** cmd type */
+	u8 cmd_type;
+	/** cmd len */
+	u8 cmd_len;
+	/** Data */
+	u8 data[6];
+} __ATTRIB_PACK__ BT_HCI_CMD;
+
+#endif /* _BT_DRV_H_ */
diff --git a/bt_sd8987/bt/bt_init.c b/bt_sd8987/bt/bt_init.c
new file mode 100644
index 0000000..904b66f
--- /dev/null
+++ b/bt_sd8987/bt/bt_init.c
@@ -0,0 +1,752 @@
+/** @file bt_init.c
+  *
+  * @brief This file contains the init functions for BlueTooth
+  * driver.
+  *
+  * Copyright (C) 2011-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/string.h>
+#include <linux/firmware.h>
+
+#include "bt_drv.h"
+
+extern int bt_req_fw_nowait;
+
+#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
+			 || ('a' <= (c) && (c) <= 'f') \
+			 || ('A' <= (c) && (c) <= 'F'))
+
+#define isdigit(c)	(('0' <= (c) && (c) <= '9'))
+#define isspace(c)  (c <= ' ' && (c == ' ' || (c <= 13 && c >= 9)))
+/**
+ *  @brief Returns hex value of a give character
+ *
+ *  @param chr	Character to be converted
+ *
+ *  @return	The converted character if chr is a valid hex, else 0
+ */
+static int
+bt_hexval(char chr)
+{
+	ENTER();
+
+	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;
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @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
+ */
+static char *
+bt_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 Returns hex value of a given ascii string
+ *
+ *  @param a	String to be converted
+ *
+ *  @return	hex value
+ */
+static int
+bt_atox(const char *a)
+{
+	int i = 0;
+	ENTER();
+	while (isxdigit(*a))
+		i = i * 16 + bt_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief Converts 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
+ */
+static void
+bt_mac2u8(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;
+	}
+	memcpy(mac_buff, buf, strlen(buf));
+
+	begin = mac_buff;
+	for (i = 0; i < ETH_ALEN; ++i) {
+		end = bt_strsep(&begin, ':', '/');
+		if (end)
+			mac_addr[i] = bt_atox(end);
+	}
+
+	kfree(mac_buff);
+	LEAVE();
+}
+
+/**
+ *  @brief Returns integer value of a given ascii string
+ *
+ *  @param data    Converted data to be returned
+ *  @param a       String to be converted
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_atoi(int *data, char *a)
+{
+	int i, val = 0, len;
+
+	ENTER();
+
+	len = strlen(a);
+	if (!strncmp(a, "0x", 2)) {
+		a = a + 2;
+		len -= 2;
+		*data = bt_atox(a);
+		return BT_STATUS_SUCCESS;
+	}
+	for (i = 0; i < len; i++) {
+		if (isdigit(a[i])) {
+			val = val * 10 + (a[i] - '0');
+		} else {
+			PRINTM(ERROR, "Invalid char %c in string %s\n", a[i],
+			       a);
+			return BT_STATUS_FAILURE;
+		}
+	}
+	*data = val;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief parse cal-data
+ *
+ *  @param src      a pointer to cal-data string
+ *  @param len      len of cal-data
+ *  @param dst      a pointer to return cal-data
+ *  @param dst_size size of dest buffer
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 *dst_size)
+{
+	const u8 *ptr;
+	u8 *dptr;
+	u32 count = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	ptr = src;
+	dptr = dst;
+
+	while ((ptr - src) < len) {
+		if (*ptr && isspace(*ptr)) {
+			ptr++;
+			continue;
+		}
+
+		if (isxdigit(*ptr)) {
+			if ((dptr - dst) >= *dst_size) {
+				PRINTM(ERROR, "cal_file size too big!!!\n");
+				goto done;
+			}
+			*dptr++ = bt_atox((const char *)ptr);
+			ptr += 2;
+			count++;
+		} else {
+			ptr++;
+		}
+	}
+	if (dptr == dst) {
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	*dst_size = count;
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT get one line data from ASCII format data
+ *
+ *    @param data         Source data
+ *    @param size         Source data length
+ *    @param line_pos     Destination data
+ *    @return             -1 or length of the line
+ */
+int
+parse_cfg_get_line(u8 *data, u32 size, u8 *line_pos)
+{
+	static s32 pos;
+	u8 *src, *dest;
+
+	if (pos >= size) {	/* reach the end */
+		pos = 0;	/* Reset position for rfkill */
+		return -1;
+	}
+	memset(line_pos, 0, MAX_LINE_LEN);
+	src = data + pos;
+	dest = line_pos;
+
+	while ((dest - line_pos < MAX_LINE_LEN - 1) && pos < size &&
+	       *src != '\x0A' && *src != '\0') {
+		if (*src != ' ' && *src != '\t')	/* parse space */
+			*dest++ = *src++;
+		else
+			src++;
+		pos++;
+	}
+	*dest = '\0';
+	/* parse new line */
+	pos++;
+	return strlen((const char *)line_pos);
+}
+
+/**
+ *    @brief BT parse ASCII format data to MAC address
+ *
+ *    @param priv          BT private handle
+ *    @param data          Source data
+ *    @param size          data length
+ *    @return              BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_init_cfg(bt_private *priv, u8 *data, u32 size)
+{
+	u8 *pos;
+	u8 *intf_s, *intf_e;
+	u8 s[MAX_LINE_LEN];	/* 1 line data */
+	u32 line_len;
+	char dev_name[MAX_PARAM_LEN];
+	u8 buf[MAX_PARAM_LEN];
+	u8 bt_addr[MAX_MAC_ADDR_LEN];
+	u8 bt_mac[ETH_ALEN];
+	int setting = 0;
+	u8 type = 0;
+	u16 value = 0;
+	u32 offset = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	memset(dev_name, 0, sizeof(dev_name));
+	memset(bt_addr, 0, sizeof(bt_addr));
+	memset(bt_mac, 0, sizeof(bt_mac));
+
+	while ((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;	/* Need n't process this line */
+
+		/* Process MAC addr */
+		if (strncmp((char *)pos, "mac_addr", 8) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ':');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				if ((intf_e - intf_s) > MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Too long interface name %d\n",
+					       __LINE__);
+					goto done;
+				}
+				strncpy(dev_name, (const char *)intf_s + 1,
+					intf_e - intf_s - 1);
+				dev_name[intf_e - intf_s - 1] = '\0';
+				strncpy((char *)bt_addr,
+					(const char *)intf_e + 1,
+					MAX_MAC_ADDR_LEN - 1);
+				bt_addr[MAX_MAC_ADDR_LEN - 1] = '\0';
+				/* Convert MAC format */
+				bt_mac2u8(bt_mac, (char *)bt_addr);
+				PRINTM(CMD,
+				       "HCI: %s new BT Address " MACSTR "\n",
+				       dev_name, MAC2STR(bt_mac));
+				if (BT_STATUS_SUCCESS !=
+				    bt_set_mac_address(priv, bt_mac)) {
+					PRINTM(FATAL,
+					       "BT: Fail to set mac address\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+		}
+		/* Process REG value */
+		else if (strncmp((char *)pos, "bt_reg", 6) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ',');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				/* Copy type */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s + 1,
+					1);
+				buf[1] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					type = (u8)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg type\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			intf_e = (u8 *)strchr((const char *)intf_s, ',');
+			if (intf_e != NULL) {
+				if ((intf_e - intf_s) >= MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Regsier offset is too long %d\n",
+					       __LINE__);
+					goto done;
+				}
+				/* Copy offset */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s,
+					intf_e - intf_s);
+				buf[intf_e - intf_s] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					offset = (u32)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg offset\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			if ((strlen((const char *)intf_s) >= MAX_PARAM_LEN)) {
+				PRINTM(ERROR,
+				       "BT: Regsier value is too long %d\n",
+				       __LINE__);
+				goto done;
+			}
+			/* Copy value */
+			memset(buf, 0, sizeof(buf));
+			strncpy((char *)buf, (const char *)intf_s, sizeof(buf));
+			if (0 == bt_atoi(&setting, (char *)buf))
+				value = (u16) setting;
+			else {
+				PRINTM(ERROR, "BT: Fail to parse reg value\n");
+				goto done;
+			}
+
+			PRINTM(CMD,
+			       "BT: Write reg type: %d offset: 0x%x value: 0x%x\n",
+			       type, offset, value);
+			if (BT_STATUS_SUCCESS !=
+			    bt_write_reg(priv, type, offset, value)) {
+				PRINTM(FATAL,
+				       "BT: Write reg failed. type: %d offset: 0x%x value: 0x%x\n",
+				       type, offset, value);
+				goto done;
+			}
+		}
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief BT 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 bt_private structure
+ *
+ * @return          N/A
+ */
+static void
+bt_request_init_user_conf_callback(const struct firmware *firmware,
+				   void *context)
+{
+	bt_private *priv = (bt_private *)context;
+
+	ENTER();
+
+	if (!firmware)
+		PRINTM(ERROR, "BT user init config request firmware failed\n");
+
+	priv->init_user_cfg = firmware;
+	priv->init_user_conf_wait_flag = TRUE;
+	wake_up_interruptible(&priv->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *    @brief BT set user defined init data and param
+ *
+ *    @param priv     BT private handle
+ *    @param cfg_file user cofig file
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_config(bt_private *priv, char *cfg_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if ((request_firmware(&cfg, cfg_file, priv->hotplug_device)) < 0) {
+		PRINTM(FATAL, "BT: request_firmware() %s failed\n", cfg_file);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (cfg)
+		ret = bt_process_init_cfg(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg(bt_private *priv, u8 *data, u32 size, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	u8 cal_data[32];
+	u8 *mac_data = NULL;
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+	u8 *pcal_data = cal_data;
+
+	memset(bt_mac, 0, sizeof(bt_mac));
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (mac != NULL) {
+		/* Convert MAC format */
+		bt_mac2u8(bt_mac, mac);
+		PRINTM(CMD, "HCI: new BT Address " MACSTR "\n",
+		       MAC2STR(bt_mac));
+		mac_data = bt_mac;
+	}
+	if (BT_STATUS_SUCCESS != bt_load_cal_data(priv, pcal_data, mac_data)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg_ext(bt_private *priv, u8 *data, u32 size)
+{
+	u8 cal_data[128];
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (BT_STATUS_SUCCESS !=
+	    bt_load_cal_data_ext(priv, cal_data, cal_data_len)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config(bt_private *priv, char *cal_file, char *mac)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size, mac);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config_ext(bt_private *priv, char *cal_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config_ext() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg_ext(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT init mac address from bt_mac parametre when insmod
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param bt_mac  mac address buf
+ *    @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_mac_address(bt_private *priv, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	memset(bt_mac, 0, sizeof(bt_mac));
+	bt_mac2u8(bt_mac, mac);
+	PRINTM(CMD, "HCI: New BT Address " MACSTR "\n", MAC2STR(bt_mac));
+	ret = bt_set_mac_address(priv, bt_mac);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(FATAL,
+		       "BT: Fail to set mac address from insmod parametre.\n");
+
+	LEAVE();
+	return ret;
+}
diff --git a/bt_sd8987/bt/bt_main.c b/bt_sd8987/bt/bt_main.c
new file mode 100644
index 0000000..8086c0a
--- /dev/null
+++ b/bt_sd8987/bt/bt_main.c
@@ -0,0 +1,3652 @@
+/** @file bt_main.c
+  *
+  * @brief This file contains the major functions in BlueTooth
+  * driver. It includes init, exit, open, close and main
+  * thread etc..
+  *
+  * Copyright (C) 2007-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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.
+  *
+  */
+/**
+  * @mainpage M-BT Linux Driver
+  *
+  * @section overview_sec Overview
+  *
+  * The M-BT is a Linux reference driver for Marvell Bluetooth chipset.
+  *
+  * @section copyright_sec Copyright
+  *
+  * Copyright (C) 2007-2019, Marvell International Ltd.
+  *
+  */
+#include <linux/module.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
+
+#include <linux/mmc/sdio_func.h>
+
+#include "bt_drv.h"
+#include "mbt_char.h"
+#include "bt_sdio.h"
+
+/** Version */
+#define VERSION "C4X14113"
+
+/** Driver version */
+static char mbt_driver_version[] = "SD8XXX-%s-" VERSION "-(" "FP" FPNUM ")"
+#ifdef DEBUG_LEVEL2
+	"-dbg"
+#endif
+	" ";
+
+/** SD8787 Card */
+#define CARD_SD8787     "SD8787"
+/** SD8777 Card */
+#define CARD_SD8777     "SD8777"
+/** SD8887 Card */
+#define CARD_SD8887     "SD8887"
+/** SD8897 Card */
+#define CARD_SD8897     "SD8897"
+/** SD8797 Card */
+#define CARD_SD8797     "SD8797"
+/** SD8977 Card */
+#define CARD_SD8977     "SD8977"
+/** SD8978 Card */
+#define CARD_SD8978     "SD8978"
+/** SD8997 Card */
+#define CARD_SD8997     "SD8997"
+/** SD8987 Card */
+#define CARD_SD8987     "SD8987"
+
+/** Declare and initialize fw_version */
+static char fw_version[32] = "0.0.0.p0";
+
+#define AID_SYSTEM        1000	/* system server */
+
+#define AID_BLUETOOTH     1002	/* bluetooth subsystem */
+
+#define AID_NET_BT_STACK  3008	/* bluetooth stack */
+
+/** Define module name */
+
+#define MODULE_NAME  "bt_fm_nfc"
+
+/** Declaration of chardev class */
+static struct class *chardev_class;
+
+/** Interface specific variables */
+
+/**
+ * The global variable of a pointer to bt_private
+ * structure variable
+ **/
+bt_private *m_priv[MAX_BT_ADAPTER];
+
+/** Default Driver mode */
+static int drv_mode = (DRV_MODE_BT);
+
+/** fw reload flag */
+int bt_fw_reload;
+/** fw serial download flag */
+int bt_fw_serial = 1;
+
+/** Firmware flag */
+static int fw = 1;
+/** default powermode */
+static int psmode = 1;
+/** default BLE deep sleep */
+static int deep_sleep = 1;
+/** Default CRC check control */
+static int fw_crc_check = 1;
+/** Init config file (MAC address, register etc.) */
+static char *init_cfg;
+/** Calibration config file (MAC address, init powe etc.) */
+static char *cal_cfg;
+/** Calibration config file EXT */
+static char *cal_cfg_ext;
+/** Init MAC address */
+static char *bt_mac;
+static int btindrst = -1;
+
+/** Setting mbt_drvdbg value based on DEBUG level */
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define DEFAULT_DEBUG_MASK  (0xffffffff & ~DBG_EVENT)
+#else
+#define DEFAULT_DEBUG_MASK  (DBG_MSG | DBG_FATAL | DBG_ERROR)
+#endif /* DEBUG_LEVEL2 */
+u32 mbt_drvdbg = DEFAULT_DEBUG_MASK;
+#endif
+
+#ifdef CONFIG_OF
+static int dts_enable = 1;
+#endif
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+int mbt_pm_keep_power = 1;
+#endif
+
+static int btpmic = 0;
+
+/** Offset of sequence number in event */
+#define OFFSET_SEQNUM 4
+
+/**
+ *  @brief handle received packet
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *
+ *  @return        N/A
+ */
+void
+bt_recv_frame(bt_private *priv, struct sk_buff *skb)
+{
+	struct hci_dev *hdev = NULL;
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type == BLUEZ_SPEC)
+		hdev = (struct hci_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer;
+	if (hdev) {
+		skb->dev = (void *)hdev;
+		hdev->stat.byte_rx += skb->len;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+		hci_recv_frame(skb);
+#else
+		hci_recv_frame(hdev, skb);
+#endif
+	}
+	return;
+}
+
+/**
+ *  @brief Alloc bt device
+ *
+ *  @return    pointer to structure mbt_dev or NULL
+ */
+struct mbt_dev *
+alloc_mbt_dev(void)
+{
+	struct mbt_dev *mbt_dev;
+	ENTER();
+
+	mbt_dev = kzalloc(sizeof(struct mbt_dev), GFP_KERNEL);
+	if (!mbt_dev) {
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return mbt_dev;
+}
+
+/**
+ *  @brief Frees m_dev
+ *
+ *  @return    N/A
+ */
+void
+free_m_dev(struct m_dev *m_dev)
+{
+	ENTER();
+	kfree(m_dev->dev_pointer);
+	m_dev->dev_pointer = NULL;
+	LEAVE();
+}
+
+/**
+ *  @brief clean up m_devs
+ *
+ *  @return    N/A
+ */
+void
+clean_up_m_devs(bt_private *priv)
+{
+	struct m_dev *m_dev = NULL;
+	struct hci_dev *hdev = NULL;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+		PRINTM(MSG, "BT: Delete %s\n", m_dev->name);
+		if (m_dev->spec_type == BLUEZ_SPEC) {
+			hdev = (struct hci_dev *)m_dev->dev_pointer;
+			/** check if dev->name has been assigned */
+			if (strstr(hdev->name, "hci"))
+				hci_unregister_dev(hdev);
+			hci_free_dev(hdev);
+		}
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = NULL;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function verify the received event pkt
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+--------+
+ *  | Event  | Length |  ncmd  |      Opcode     |
+ *  +--------+--------+--------+--------+--------+
+ *  | 1-byte | 1-byte | 1-byte |      2-byte     |
+ *  +--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+check_evtpkt(bt_private *priv, struct sk_buff *skb)
+{
+	struct hci_event_hdr *hdr = (struct hci_event_hdr *)skb->data;
+	struct hci_ev_cmd_complete *ec;
+	u16 opcode, ocf;
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (!priv->bt_dev.sendcmdflag) {
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	if (hdr->evt == HCI_EV_CMD_COMPLETE) {
+		ec = (struct hci_ev_cmd_complete *)
+			(skb->data + HCI_EVENT_HDR_SIZE);
+		opcode = __le16_to_cpu(ec->opcode);
+		ocf = hci_opcode_ocf(opcode);
+		PRINTM(CMD,
+		       "BT: CMD_COMPLTE opcode=0x%x, ocf=0x%x, send_cmd_opcode=0x%x\n",
+		       opcode, ocf, priv->bt_dev.send_cmd_opcode);
+		if (opcode != priv->bt_dev.send_cmd_opcode) {
+			ret = BT_STATUS_FAILURE;
+			goto exit;
+		}
+		switch (ocf) {
+		case BT_CMD_MODULE_CFG_REQ:
+		case BT_CMD_BLE_DEEP_SLEEP:
+		case BT_CMD_CONFIG_MAC_ADDR:
+		case BT_CMD_CSU_WRITE_REG:
+		case BT_CMD_LOAD_CONFIG_DATA:
+		case BT_CMD_LOAD_CONFIG_DATA_EXT:
+		case BT_CMD_AUTO_SLEEP_MODE:
+		case BT_CMD_HOST_SLEEP_CONFIG:
+		case BT_CMD_SDIO_PULL_CFG_REQ:
+		case BT_CMD_SET_EVT_FILTER:
+			// case BT_CMD_ENABLE_DEVICE_TESTMODE:
+		case BT_CMD_PMIC_CONFIGURE:
+		case BT_CMD_INDEPENDENT_RESET:
+			priv->bt_dev.sendcmdflag = FALSE;
+			priv->adapter->cmd_complete = TRUE;
+			wake_up_interruptible(&priv->adapter->cmd_wait_q);
+			break;
+		case BT_CMD_GET_FW_VERSION:
+			{
+				u8 *pos = (skb->data + HCI_EVENT_HDR_SIZE +
+					   sizeof(struct hci_ev_cmd_complete) +
+					   1);
+				snprintf(fw_version, sizeof(fw_version),
+					 "%u.%u.%u.p%u", pos[2], pos[1], pos[0],
+					 pos[3]);
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+				break;
+			}
+		case BT_CMD_RESET:
+		case BT_CMD_ENABLE_WRITE_SCAN:
+			{
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				if (priv->adapter->wait_event_timeout == TRUE) {
+					wake_up(&priv->adapter->cmd_wait_q);
+					priv->adapter->wait_event_timeout =
+						FALSE;
+				} else
+					wake_up_interruptible(&priv->adapter->
+							      cmd_wait_q);
+			}
+			break;
+		case BT_CMD_HOST_SLEEP_ENABLE:
+			priv->bt_dev.sendcmdflag = FALSE;
+			break;
+		default:
+			/** Ignore command not defined but send by driver */
+			if (opcode == priv->bt_dev.send_cmd_opcode) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			} else {
+				ret = BT_STATUS_FAILURE;
+			}
+			break;
+		}
+	} else
+		ret = BT_STATUS_FAILURE;
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+*  @brief This function stores the FW dumps received from events
+*
+*  @param priv    A pointer to bt_private structure
+*  @param skb     A pointer to rx skb
+*
+*  @return        N/A
+*/
+void
+bt_store_firmware_dump(bt_private *priv, u8 *buf, u32 len)
+{
+	struct file *pfile_fwdump = NULL;
+	loff_t pos = 0;
+	u16 seqnum = 0;
+	struct timeval t;
+	u32 sec;
+
+	ENTER();
+
+	seqnum = __le16_to_cpu(*(u16 *) (buf + OFFSET_SEQNUM));
+
+	if (priv->adapter->fwdump_fname && seqnum != 1) {
+		pfile_fwdump =
+			filp_open((const char *)priv->adapter->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		if (IS_ERR(pfile_fwdump)) {
+			PRINTM(MSG, "Cannot create firmware dump file.\n");
+			LEAVE();
+			return;
+		}
+	} else {
+		if (!priv->adapter->fwdump_fname) {
+			gfp_t flag;
+			flag = (in_atomic() ||
+				irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+			priv->adapter->fwdump_fname = kzalloc(64, flag);
+		} else
+			memset(priv->adapter->fwdump_fname, 0, 64);
+
+		do_gettimeofday(&t);
+		sec = (u32)t.tv_sec;
+		sprintf(priv->adapter->fwdump_fname, "%s%u",
+			"/var/log/bt_fwdump_", sec);
+		pfile_fwdump =
+			filp_open(priv->adapter->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		if (IS_ERR(pfile_fwdump)) {
+			sprintf(priv->adapter->fwdump_fname, "%s%u",
+				"/data/bt_fwdump_", sec);
+			pfile_fwdump =
+				filp_open((const char *)priv->adapter->
+					  fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		}
+	}
+
+	if (IS_ERR(pfile_fwdump)) {
+		PRINTM(MSG, "Cannot create firmware dump file\n");
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile_fwdump, buf, len, &pos);
+#else
+	kernel_write(pfile_fwdump, buf, len, &pos);
+#endif
+	filp_close(pfile_fwdump, NULL);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function process the received event
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+-----+
+ *  |   EC   | Length |           Data        |
+ *  +--------+--------+--------+--------+-----+
+ *  | 1-byte | 1-byte |          n-byte       |
+ *  +--------+--------+--------+--------+-----+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_event(bt_private *priv, struct sk_buff *skb)
+{
+	int ret = BT_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	BT_EVENT *pevent;
+
+	ENTER();
+	if (!m_dev) {
+		PRINTM(CMD, "BT: bt_process_event without m_dev\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pevent = (BT_EVENT *)skb->data;
+	if (pevent->EC != 0xff) {
+		PRINTM(CMD, "BT: Not Marvell Event=0x%x\n", pevent->EC);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	switch (pevent->data[0]) {
+	case BT_CMD_AUTO_SLEEP_MODE:
+		if (pevent->data[2] == BT_STATUS_SUCCESS) {
+			if (pevent->data[1] == BT_PS_ENABLE)
+				priv->adapter->psmode = 1;
+			else
+				priv->adapter->psmode = 0;
+			PRINTM(CMD, "BT: PS Mode %s:%s\n", m_dev->name,
+			       (priv->adapter->psmode) ? "Enable" : "Disable");
+
+		} else {
+			PRINTM(CMD, "BT: PS Mode Command Fail %s\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_CONFIG:
+		if (pevent->data[3] == BT_STATUS_SUCCESS) {
+			PRINTM(CMD, "BT: %s: gpio=0x%x, gap=0x%x\n",
+			       m_dev->name, pevent->data[1], pevent->data[2]);
+		} else {
+			PRINTM(CMD, "BT: %s: HSCFG Command Fail\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_ENABLE:
+		if (pevent->data[1] == BT_STATUS_SUCCESS) {
+			priv->adapter->hs_state = HS_ACTIVATED;
+			if (priv->adapter->suspend_fail == FALSE) {
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+				bt_is_suspended(priv);
+#endif
+#endif
+#endif
+				if (priv->adapter->wait_event_timeout) {
+					wake_up(&priv->adapter->cmd_wait_q);
+					priv->adapter->wait_event_timeout =
+						FALSE;
+				} else
+					wake_up_interruptible(&priv->adapter->
+							      cmd_wait_q);
+
+			}
+			if (priv->adapter->psmode)
+				priv->adapter->ps_state = PS_SLEEP;
+			PRINTM(CMD, "BT: EVENT %s: HS ACTIVATED!\n",
+			       m_dev->name);
+
+		} else {
+			PRINTM(CMD, "BT: %s: HS Enable Fail\n", m_dev->name);
+		}
+		break;
+	case BT_CMD_MODULE_CFG_REQ:
+		if ((priv->bt_dev.sendcmdflag == TRUE) &&
+		    ((pevent->data[1] == MODULE_BRINGUP_REQ)
+		     || (pevent->data[1] == MODULE_SHUTDOWN_REQ))) {
+			if (pevent->data[1] == MODULE_BRINGUP_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2] && (pevent->data[2] !=
+							    MODULE_CFG_RESP_ALREADY_UP))
+				       ? "Bring up Fail" : "Bring up success");
+				priv->bt_dev.devType = pevent->data[3];
+				PRINTM(CMD, "devType:%s\n",
+				       (pevent->data[3] ==
+					DEV_TYPE_AMP) ? "AMP controller" :
+				       "BR/EDR controller");
+				priv->bt_dev.devFeature = pevent->data[4];
+				PRINTM(CMD, "devFeature:  %s,    %s,    %s"
+				       "\n",
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BT) ?
+					"BT Feature" : "No BT Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BTAMP) ?
+					"BTAMP Feature" : "No BTAMP Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BLE) ?
+					"BLE Feature" : "No BLE Feature")
+					);
+			}
+			if (pevent->data[1] == MODULE_SHUTDOWN_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2]) ? "Shut down Fail"
+				       : "Shut down success");
+
+			}
+			if (pevent->data[2]) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			}
+		} else {
+			PRINTM(CMD, "BT_CMD_MODULE_CFG_REQ resp for APP\n");
+			ret = BT_STATUS_FAILURE;
+		}
+		break;
+	case BT_EVENT_POWER_STATE:
+		if (pevent->data[1] == BT_PS_SLEEP)
+			priv->adapter->ps_state = PS_SLEEP;
+		if (priv->adapter->ps_state == PS_SLEEP
+		    && (priv->card_type == CARD_TYPE_SD8887)
+			)
+			os_sched_timeout(5);
+		PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+		       (priv->adapter->ps_state) ? "PS_SLEEP" : "PS_AWAKE");
+
+		break;
+	case BT_CMD_SDIO_PULL_CFG_REQ:
+		if (pevent->data[pevent->length - 1] == BT_STATUS_SUCCESS)
+			PRINTM(CMD, "BT: %s: SDIO pull configuration success\n",
+			       m_dev->name);
+
+		else {
+			PRINTM(CMD, "BT: %s: SDIO pull configuration fail\n",
+			       m_dev->name);
+
+		}
+		break;
+	default:
+		PRINTM(CMD, "BT: Unknown Event=%d %s\n", pevent->data[0],
+		       m_dev->name);
+		ret = BT_STATUS_FAILURE;
+		break;
+	}
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function save the dump info to file
+ *
+ *  @param dir_name     directory name
+ *  @param file_name    file_name
+ *  @param buf			buffer
+ *  @param buf_len		buffer length
+ *
+ *  @return   		    0 --success otherwise fail
+ */
+int
+bt_save_dump_info_to_file(char *dir_name, char *file_name, u8 *buf, u32 buf_len)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct file *pfile = NULL;
+	u8 name[64];
+	loff_t pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	if (!dir_name || !file_name || !buf) {
+		PRINTM(ERROR, "Can't save dump info to file\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(name, 0, sizeof(name));
+	snprintf((char *)name, sizeof(name), "%s/%s", dir_name, file_name);
+	pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MSG,
+		       "Create file %s error, try to save dump file in /var\n",
+		       name);
+		memset(name, 0, sizeof(name));
+		snprintf((char *)name, sizeof(name), "%s/%s", "/var",
+			 file_name);
+		pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(ERROR, "Create Dump file for %s error\n", name);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MSG, "Dump data %s saved in %s\n", file_name, name);
+
+	pos = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	vfs_write(pfile, (const char __user *)buf, buf_len, &pos);
+	set_fs(fs);
+#else
+	kernel_write(pfile, (const char __user *)buf, buf_len, &pos);
+#endif
+	filp_close(pfile, NULL);
+
+	PRINTM(MSG, "Dump data %s saved in %s successfully\n", file_name, name);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#define DEBUG_HOST_READY		0xEE
+#define DEBUG_FW_DONE			0xFF
+#define DUMP_MAX_POLL_TRIES			200
+
+#define DEBUG_DUMP_CTRL_REG_8897               0xE2
+#define DEBUG_DUMP_START_REG_8897              0xE3
+#define DEBUG_DUMP_END_REG_8897                0xEA
+#define DEBUG_DUMP_CTRL_REG_8887               0xA2
+#define DEBUG_DUMP_START_REG_8887              0xA3
+#define DEBUG_DUMP_END_REG_8887                0xAA
+#define DEBUG_DUMP_CTRL_REG_8977               0xF0
+#define DEBUG_DUMP_START_REG_8977              0xF1
+#define DEBUG_DUMP_END_REG_8977                0xF8
+#define DEBUG_DUMP_CTRL_REG_8978               0xF0
+#define DEBUG_DUMP_START_REG_8978              0xF1
+#define DEBUG_DUMP_END_REG_8978                0xF8
+#define DEBUG_DUMP_CTRL_REG_8997               0xF0
+#define DEBUG_DUMP_START_REG_8997              0xF1
+#define DEBUG_DUMP_END_REG_8997                0xF8
+#define DEBUG_DUMP_CTRL_REG_8987               0xF0
+#define DEBUG_DUMP_START_REG_8987              0xF1
+#define DEBUG_DUMP_END_REG_8987                0xF8
+
+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
+#define MAX_FULL_NAME_LEN               32
+
+/** Memory type mapping structure */
+typedef struct {
+	/** memory name */
+	u8 mem_name[MAX_NAME_LEN];
+	/** memory pointer */
+	u8 *mem_Ptr;
+	/** file structure */
+	struct file *pfile_mem;
+	/** donbe flag */
+	u8 done_flag;
+	/** dump type */
+	u8 type;
+} memory_type_mapping;
+
+memory_type_mapping bt_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},
+	{"EXT8", NULL, NULL, 0xF8},
+	{"EXT9", NULL, NULL, 0xF9},
+	{"EXT10", NULL, NULL, 0xFA},
+	{"EXT11", NULL, NULL, 0xFB},
+	{"EXT12", NULL, NULL, 0xFC},
+	{"EXT13", NULL, NULL, 0xFD},
+	{"EXTLAST", NULL, NULL, 0xFE},
+};
+
+typedef enum {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+} rdwr_status;
+
+/**
+ *  @brief This function read/write firmware via cmd52
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+rdwr_status
+bt_cmd52_rdwr_firmware(bt_private *priv, u8 doneflag)
+{
+	int ret = 0;
+	int tries = 0;
+	u8 ctrl_data = 0;
+	u8 dbg_dump_ctrl_reg = 0;
+
+	if (priv->card_type == CARD_TYPE_SD8887)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8887;
+	else if (priv->card_type == CARD_TYPE_SD8897)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8897;
+	else if (priv->card_type == CARD_TYPE_SD8977)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8977;
+	else if (priv->card_type == CARD_TYPE_SD8978)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8978;
+	else if (priv->card_type == CARD_TYPE_SD8997)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8997;
+	else if (priv->card_type == CARD_TYPE_SD8987)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8987;
+
+	sdio_writeb(((struct sdio_mmc_card *)priv->bt_dev.card)->func,
+		    DEBUG_HOST_READY, dbg_dump_ctrl_reg, &ret);
+	if (ret) {
+		PRINTM(ERROR, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	for (tries = 0; tries < DUMP_MAX_POLL_TRIES; tries++) {
+		ctrl_data =
+			sdio_readb(((struct sdio_mmc_card *)priv->bt_dev.card)->
+				   func, dbg_dump_ctrl_reg, &ret);
+		if (ret) {
+			PRINTM(ERROR, "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(INFO,
+			       "The ctrl reg was changed, re-try again!\n");
+			sdio_writeb(((struct sdio_mmc_card *)priv->bt_dev.
+				     card)->func, DEBUG_HOST_READY,
+				    dbg_dump_ctrl_reg, &ret);
+			if (ret) {
+				PRINTM(ERROR, "SDIO Write ERR\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		udelay(100);
+	}
+	if (ctrl_data == DEBUG_HOST_READY) {
+		PRINTM(ERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	return RDWR_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_firmware_info_v2(bt_private *priv)
+{
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	u8 *dbg_ptr = NULL;
+	u8 dump_num = 0;
+	u8 idx = 0;
+	u8 doneflag = 0;
+	rdwr_status stat;
+	u8 i = 0;
+	u8 read_reg = 0;
+	u32 memory_size = 0;
+	u8 path_name[64], file_name[32];
+	u8 *end_ptr = NULL;
+	u8 dbg_dump_start_reg = 0;
+	u8 dbg_dump_end_reg = 0;
+
+	if (!priv) {
+		PRINTM(ERROR, "Could not dump firmwware info\n");
+		return;
+	}
+
+	if ((priv->card_type != CARD_TYPE_SD8887) &&
+	    (priv->card_type != CARD_TYPE_SD8897)
+	    && (priv->card_type != CARD_TYPE_SD8977) &&
+	    (priv->card_type != CARD_TYPE_SD8997)
+	    && (priv->card_type != CARD_TYPE_SD8987) &&
+	    (priv->card_type != CARD_TYPE_SD8978)) {
+		PRINTM(MSG, "card_type %d don't support FW dump\n",
+		       priv->card_type);
+		return;
+	}
+
+	memset(path_name, 0, sizeof(path_name));
+	strcpy((char *)path_name, "/data");
+	PRINTM(MSG, "Create DUMP directory success:dir_name=%s\n", path_name);
+
+	if (priv->card_type == CARD_TYPE_SD8887) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8887;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8887;
+	} else if (priv->card_type == CARD_TYPE_SD8897) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8897;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8897;
+	} else if (priv->card_type == CARD_TYPE_SD8977) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8977;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8977;
+	} else if (priv->card_type == CARD_TYPE_SD8978) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8978;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8978;
+	} else if (priv->card_type == CARD_TYPE_SD8997) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8997;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8997;
+	} else if (priv->card_type == CARD_TYPE_SD8987) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8987;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8987;
+	}
+
+	sbi_wakeup_firmware(priv);
+	sdio_claim_host(((struct sdio_mmc_card *)priv->bt_dev.card)->func);
+	priv->fw_dump = TRUE;
+	/* start dump fw memory */
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT START ====\n");
+	/* read the number of the memories which will dump */
+	if (RDWR_STATUS_FAILURE == bt_cmd52_rdwr_firmware(priv, doneflag))
+		goto done;
+	reg = dbg_dump_start_reg;
+	dump_num =
+		sdio_readb(((struct sdio_mmc_card *)priv->bt_dev.card)->func,
+			   reg, &ret);
+	if (ret) {
+		PRINTM(MSG, "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 ==
+		    bt_cmd52_rdwr_firmware(priv, doneflag))
+			goto done;
+		memory_size = 0;
+		reg = dbg_dump_start_reg;
+		for (i = 0; i < 4; i++) {
+			read_reg =
+				sdio_readb(((struct sdio_mmc_card *)priv->
+					    bt_dev.card)->func, reg, &ret);
+			if (ret) {
+				PRINTM(MSG, "SDIO READ ERR\n");
+				goto done;
+			}
+			memory_size |= (read_reg << i * 8);
+			reg++;
+		}
+		if (memory_size == 0) {
+			PRINTM(MSG, "Firmware Dump Finished!\n");
+			break;
+		} else {
+			PRINTM(MSG, "%s_SIZE=0x%x\n",
+			       bt_mem_type_mapping_tbl[idx].mem_name,
+			       memory_size);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr =
+				vmalloc(memory_size + 1);
+			if ((ret != BT_STATUS_SUCCESS) ||
+			    !bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+				PRINTM(ERROR,
+				       "Error: vmalloc %s buffer failed!!!\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name);
+				goto done;
+			}
+			dbg_ptr = bt_mem_type_mapping_tbl[idx].mem_Ptr;
+			end_ptr = dbg_ptr + memory_size;
+		}
+		doneflag = bt_mem_type_mapping_tbl[idx].done_flag;
+		PRINTM(MSG, "Start %s output, please wait...\n",
+		       bt_mem_type_mapping_tbl[idx].mem_name);
+		do {
+			stat = bt_cmd52_rdwr_firmware(priv, 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++) {
+				*dbg_ptr =
+					sdio_readb(((struct sdio_mmc_card *)
+						    priv->bt_dev.card)->func,
+						   reg, &ret);
+				if (ret) {
+					PRINTM(MSG, "SDIO READ ERR\n");
+					goto done;
+				}
+				if (dbg_ptr < end_ptr)
+					dbg_ptr++;
+				else
+					PRINTM(MSG,
+					       "pre-allocced buf is not enough\n");
+			}
+			if (RDWR_STATUS_DONE == stat) {
+				PRINTM(MSG, "%s done:"
+				       "size = 0x%x\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name,
+				       (unsigned int)(dbg_ptr -
+						      bt_mem_type_mapping_tbl
+						      [idx].mem_Ptr));
+				memset(file_name, 0, sizeof(file_name));
+				snprintf((char *)file_name, sizeof(file_name),
+					 "%s%s", "file_bt_",
+					 bt_mem_type_mapping_tbl[idx].mem_name);
+				if (BT_STATUS_SUCCESS !=
+				    bt_save_dump_info_to_file((char *)path_name,
+							      (char *)file_name,
+							      bt_mem_type_mapping_tbl
+							      [idx].mem_Ptr,
+							      memory_size))
+					PRINTM(MSG,
+					       "Can't save dump file %s in %s\n",
+					       file_name, path_name);
+				vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+				bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+				break;
+			}
+		} while (1);
+	}
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT END ====\n");
+	/* end dump fw memory */
+done:
+	priv->fw_dump = FALSE;
+	sdio_release_host(((struct sdio_mmc_card *)priv->bt_dev.card)->func);
+	for (idx = 0; idx < dump_num; idx++) {
+		if (bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+			vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+		}
+	}
+	PRINTM(MSG, "==== DEBUG MODE END ====\n");
+	return;
+}
+
+/**
+ *  @brief This function shows debug info for timeout of command sending.
+ *
+ *  @param adapter  A pointer to bt_private
+ *  @param cmd      Timeout command id
+ *
+ *  @return         N/A
+ */
+static void
+bt_cmd_timeout_func(bt_private *priv, u16 cmd)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+
+	adapter->num_cmd_timeout++;
+
+	PRINTM(ERROR, "Version = %s\n", adapter->drv_ver);
+	PRINTM(ERROR, "Timeout Command id = 0x%x\n", cmd);
+	PRINTM(ERROR, "Number of command timeout = %d\n",
+	       adapter->num_cmd_timeout);
+	PRINTM(ERROR, "Interrupt counter = %d\n", adapter->IntCounter);
+	PRINTM(ERROR, "Power Save mode = %d\n", adapter->psmode);
+	PRINTM(ERROR, "Power Save state = %d\n", adapter->ps_state);
+	PRINTM(ERROR, "Host Sleep state = %d\n", adapter->hs_state);
+	PRINTM(ERROR, "hs skip count = %d\n", adapter->hs_skip);
+	PRINTM(ERROR, "suspend_fail flag = %d\n", adapter->suspend_fail);
+	PRINTM(ERROR, "suspended flag = %d\n", adapter->is_suspended);
+	PRINTM(ERROR, "Number of wakeup tries = %d\n", adapter->WakeupTries);
+	PRINTM(ERROR, "Host Cmd complet state = %d\n", adapter->cmd_complete);
+	PRINTM(ERROR, "Last irq recv = %d\n", adapter->irq_recv);
+	PRINTM(ERROR, "Last irq processed = %d\n", adapter->irq_done);
+	PRINTM(ERROR, "tx pending = %d\n", adapter->skb_pending);
+	PRINTM(ERROR, "sdio int status = %d\n", adapter->sd_ireg);
+	bt_dump_sdio_regs(priv);
+	LEAVE();
+}
+
+/**
+ *  @brief This function queue frame
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    N/A
+ */
+static void
+bt_queue_frame(bt_private *priv, struct sk_buff *skb)
+{
+	skb_queue_tail(&priv->adapter->tx_queue, skb);
+}
+
+/**
+ *  @brief This function send reset cmd to firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return	       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_reset_command(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((RESET_OGF << 10) | BT_CMD_RESET);
+	pcmd->length = 0x00;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, 3);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue Reset Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Reset timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_RESET);
+	} else {
+		PRINTM(CMD, "BT: Reset Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends module cfg cmd to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param subcmd  sub command
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_module_cfg_cmd(bt_private *priv, int subcmd)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_MODULE_CFG_REQ);
+	pcmd->length = 1;
+	pcmd->data[0] = subcmd;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue module cfg Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	/*
+	   On some Android platforms certain delay is needed for HCI daemon to
+	   remove this module and close itself gracefully. Otherwise it hangs.
+	   This 10ms delay is a workaround for such platforms as the root cause
+	   has not been found yet. */
+	mdelay(10);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: module_cfg_cmd(%#x): timeout sendcmdflag=%d\n",
+		       subcmd, priv->bt_dev.sendcmdflag);
+		bt_cmd_timeout_func(priv, BT_CMD_MODULE_CFG_REQ);
+	} else {
+		PRINTM(CMD, "BT: module cfg Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables power save mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_ps(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_AUTO_SLEEP_MODE);
+	if (priv->bt_dev.psmode)
+		pcmd->data[0] = BT_PS_ENABLE;
+	else
+		pcmd->data[0] = BT_PS_DISABLE;
+	if (priv->bt_dev.idle_timeout) {
+		pcmd->length = 3;
+		pcmd->data[1] = (u8)(priv->bt_dev.idle_timeout & 0x00ff);
+		pcmd->data[2] = (priv->bt_dev.idle_timeout & 0xff00) >> 8;
+	} else {
+		pcmd->length = 1;
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PSMODE Command(0x%x):%d\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: psmode timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_AUTO_SLEEP_MODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends hscfg command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_hscfg_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_CONFIG);
+	pcmd->length = 2;
+	pcmd->data[0] = (priv->bt_dev.gpio_gap & 0xff00) >> 8;
+	pcmd->data[1] = (u8)(priv->bt_dev.gpio_gap & 0x00ff);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue HSCFG Command(0x%x),gpio=0x%x,gap=0x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0], pcmd->data[1]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: HSCFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_CONFIG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends sdio pull ctrl command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_sdio_pull_ctrl_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_SDIO_PULL_CFG_REQ);
+	pcmd->length = 4;
+	pcmd->data[0] = (priv->bt_dev.sdio_pull_cfg & 0x000000ff);
+	pcmd->data[1] = (priv->bt_dev.sdio_pull_cfg & 0x0000ff00) >> 8;
+	pcmd->data[2] = (priv->bt_dev.sdio_pull_cfg & 0x00ff0000) >> 16;
+	pcmd->data[3] = (priv->bt_dev.sdio_pull_cfg & 0xff000000) >> 24;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD,
+	       "Queue SDIO PULL CFG Command(0x%x), PullUp=0x%x%x,PullDown=0x%x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[1], pcmd->data[0],
+	       pcmd->data[3], pcmd->data[2]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: SDIO PULL CFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SDIO_PULL_CFG_REQ);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends command to configure PMIC
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_pmic_configure(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_PMIC_CONFIGURE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PMIC Configure Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: PMIC Configure timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_PMIC_CONFIGURE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables host sleep
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param is_shutdown  indicate shutdown mode
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_hs(bt_private *priv, bool is_shutdown)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	priv->adapter->suspend_fail = FALSE;
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_ENABLE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->adapter->wait_event_timeout = is_shutdown;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	PRINTM(CMD, "Queue hs enable Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (is_shutdown) {
+		if (!os_wait_timeout
+		    (priv->adapter->cmd_wait_q, priv->adapter->hs_state,
+		     WAIT_UNTIL_HS_STATE_CHANGED)) {
+			PRINTM(MSG, "BT: Enable host sleep timeout:\n");
+			priv->adapter->wait_event_timeout = FALSE;
+			bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_ENABLE);
+		}
+	} else {
+		if (!os_wait_interruptible_timeout
+		    (priv->adapter->cmd_wait_q, priv->adapter->hs_state,
+		     WAIT_UNTIL_HS_STATE_CHANGED)) {
+			PRINTM(MSG, "BT: Enable host sleep timeout:\n");
+			bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_ENABLE);
+		}
+	}
+	OS_INT_DISABLE;
+	if ((priv->adapter->hs_state == HS_ACTIVATED) ||
+	    (priv->adapter->is_suspended == TRUE)) {
+		OS_INT_RESTORE;
+		PRINTM(MSG, "BT: suspend success! skip=%d\n",
+		       priv->adapter->hs_skip);
+	} else {
+		priv->adapter->suspend_fail = TRUE;
+		OS_INT_RESTORE;
+		priv->adapter->hs_skip++;
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG,
+		       "BT: suspend skipped! "
+		       "state=%d skip=%d ps_state= %d WakeupTries=%d\n",
+		       priv->adapter->hs_state, priv->adapter->hs_skip,
+		       priv->adapter->ps_state, priv->adapter->WakeupTries);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Set Evt Filter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_evt_filter(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_SET_EVT_FILTER);
+	pcmd->length = 0x03;
+	pcmd->data[0] = 0x02;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Set Evt Filter Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set Evt Filter timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SET_EVT_FILTER);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Write Scan - Page and Inquiry
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_write_scan(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_ENABLE_WRITE_SCAN);
+	pcmd->length = 0x01;
+	pcmd->data[0] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Enable Write Scan Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Write Scan timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_WRITE_SCAN);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Device under test mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_device_under_testmode(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((0x06 << 10) | BT_CMD_ENABLE_DEVICE_TESTMODE);
+	pcmd->length = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue enable device under testmode Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Device under TEST mode timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_DEVICE_TESTMODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables test mode and send cmd
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_test_mode(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	/** Set Evt Filter Command */
+	ret = bt_set_evt_filter(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Set Evt filter fail\n");
+		goto exit;
+	}
+
+	/** Enable Write Scan Command */
+	ret = bt_enable_write_scan(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Enable Write Scan fail\n");
+		goto exit;
+	}
+
+	/** Enable Device under test mode */
+	ret = bt_enable_device_under_testmode(priv);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(ERROR,
+		       "BT test_mode: Enable device under testmode fail\n");
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+#define DISABLE_RESET  0x0
+#define ENABLE_OUTBAND_RESET 0x1
+#define ENABLE_INBAND_RESET  0x02
+#define DEFAULT_GPIO 0xff
+/**
+ *  @brief This function set GPIO pin
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_independent_reset(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	u8 mode, gpio;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_INDEPENDENT_RESET);
+	mode = btindrst & 0xff;
+	gpio = (btindrst & 0xff00) >> 8;
+	if (mode == ENABLE_OUTBAND_RESET) {
+		pcmd->data[0] = ENABLE_OUTBAND_RESET;
+		if (!gpio)
+			pcmd->data[1] = DEFAULT_GPIO;
+		else
+			pcmd->data[1] = gpio;
+	} else if (mode == ENABLE_INBAND_RESET) {
+		pcmd->data[0] = ENABLE_INBAND_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else if (mode == DISABLE_RESET) {
+		pcmd->data[0] = DISABLE_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else {
+		PRINTM(WARN, "Unsupport mode\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	PRINTM(CMD, "BT: independant reset mode=%d gpio=%d\n", mode, gpio);
+	pcmd->length = 2;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Independent reset : timeout!\n");
+		bt_cmd_timeout_func(priv, BT_CMD_INDEPENDENT_RESET);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets ble deepsleep mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mode    TRUE/FALSE
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_ble_deepsleep(bt_private *priv, int mode)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_BLE_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_BLE_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_BLE_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_BLE_DEEP_SLEEP);
+	pcmd->length = 1;
+	pcmd->deepsleep = mode;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_BLE_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set BLE deepsleep = %d (0x%x)\n", mode,
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set BLE deepsleep timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_BLE_DEEP_SLEEP);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets FW version
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_get_fw_version(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_GET_FW_VERSION);
+	pcmd->length = 0x01;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, 4);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Get FW version: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_GET_FW_VERSION);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets mac address
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_mac_address(bt_private *priv, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	int i = 0;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CONFIG_MAC_ADDR);
+	pcmd->length = 8;
+	pcmd->cmd_type = MRVL_VENDOR_PKT;
+	pcmd->cmd_len = 6;
+	for (i = 0; i < 6; i++)
+		pcmd->data[i] = mac[5 - i];
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_HCI_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set mac addr " MACSTR " (0x%x)\n", MAC2STR(mac),
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set mac addr: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CONFIG_MAC_ADDR);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	int i = 0;
+	/* u8 config_data[28] = {0x37 0x01 0x1c 0x00 0xFF 0xFF 0xFF 0xFF 0x01
+	   0x7f 0x04 0x02 0x00 0x00 0xBA 0xCE 0xC0 0xC6 0x2D 0x00 0x00 0x00
+	   0x00 0x00 0x00 0x00 0xF0}; */
+
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA);
+	pcmd->length = 0x20;
+	pcmd->data[0] = 0x00;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x00;
+	pcmd->data[3] = 0x1C;
+	/* swip cal-data byte */
+	for (i = 4; i < 32; i++)
+		pcmd->data[i] = *(config_data + ((i / 4) * 8 - 1 - i));
+	if (mac != NULL) {
+		pcmd->data[2] = 0x01;	/* skip checksum */
+		for (i = 24; i < 30; i++)
+			pcmd->data[i] = mac[29 - i];
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate data: ", pcmd->data, 32);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate EXT data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+
+	ENTER();
+
+	if (cfg_data_len > BT_CMD_DATA_LEN) {
+		PRINTM(WARN, "cfg_data_len is too long exceed %d.\n",
+		       BT_CMD_DATA_LEN);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA_EXT);
+	pcmd->length = cfg_data_len;
+
+	memcpy(pcmd->data, config_data, cfg_data_len);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate ext data", pcmd->data, pcmd->length);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate ext data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA_EXT);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function writes value to CSU registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param type    reg type
+ *  @param offset  register address
+ *  @param value   register value to write
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CSU_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CSU_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CSU_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CSU_WRITE_REG);
+	pcmd->length = 7;
+	pcmd->type = type;
+	pcmd->offset[0] = (offset & 0x000000ff);
+	pcmd->offset[1] = (offset & 0x0000ff00) >> 8;
+	pcmd->offset[2] = (offset & 0x00ff0000) >> 16;
+	pcmd->offset[3] = (offset & 0xff000000) >> 24;
+	pcmd->value[0] = (value & 0x00ff);
+	pcmd->value[1] = (value & 0xff00) >> 8;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_CSU_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set CSU reg type=%d reg=0x%x value=0x%x\n",
+	       type, offset, value);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Set CSU reg timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CSU_WRITE_REG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function used to restore tx_queue
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        N/A
+ */
+void
+bt_restore_tx_queue(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	while (!skb_queue_empty(&priv->adapter->pending_queue)) {
+		skb = skb_dequeue(&priv->adapter->pending_queue);
+		if (skb)
+			bt_queue_frame(priv, skb);
+	}
+	wake_up_interruptible(&priv->MainThread.waitQ);
+}
+
+/**
+ *  @brief This function used to send command to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_prepare_command(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (priv->bt_dev.hscfgcmd) {
+		priv->bt_dev.hscfgcmd = 0;
+		ret = bt_send_hscfg_cmd(priv);
+	}
+	if (priv->bt_dev.pscmd) {
+		priv->bt_dev.pscmd = 0;
+		ret = bt_enable_ps(priv);
+	}
+	if (priv->bt_dev.sdio_pull_ctrl) {
+		priv->bt_dev.sdio_pull_ctrl = 0;
+		ret = bt_send_sdio_pull_ctrl_cmd(priv);
+	}
+	if (priv->bt_dev.hscmd) {
+		priv->bt_dev.hscmd = 0;
+		if (priv->bt_dev.hsmode)
+			ret = bt_enable_hs(priv, FALSE);
+		else {
+			ret = sbi_wakeup_firmware(priv);
+			priv->adapter->hs_state = HS_DEACTIVATED;
+		}
+	}
+	if (priv->bt_dev.test_mode) {
+		priv->bt_dev.test_mode = 0;
+		ret = bt_enable_test_mode(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Update tx state
+ *
+ * @param priv          A pointer to bt_private structure
+ * @param skb			A pointer to sk_buff structure
+ *
+ * @return                N/A
+ */
+static void
+update_stat_byte_tx(bt_private *priv, struct sk_buff *skb)
+{
+	((struct hci_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer)->stat.
+		byte_tx += skb->len;
+}
+
+/**
+ * @brief Update tx error state
+ *
+ * @param priv          A pointer to bt_private structure
+ * @param skb			A pointer to sk_buff structure
+ *
+ * @return                N/A
+ */
+static void
+update_stat_err_tx(bt_private *priv, struct sk_buff *skb)
+{
+	((struct hci_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer)->stat.
+		err_tx++;
+}
+
+/** @brief This function processes a single packet
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to skb which includes TX packet
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+send_single_packet(bt_private *priv, struct sk_buff *skb)
+{
+	int ret;
+	struct sk_buff *new_skb = NULL;
+	ENTER();
+	if (!skb || !skb->data) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	if (!skb->len || ((skb->len + BT_HEADER_LEN) > BT_UPLD_SIZE)) {
+		PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
+		       BT_UPLD_SIZE);
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	if (skb_headroom(skb) < BT_HEADER_LEN) {
+		new_skb = skb_realloc_headroom(skb, BT_HEADER_LEN);
+		if (!new_skb) {
+			PRINTM(ERROR, "TX error: realloc_headroom failed %d\n",
+			       BT_HEADER_LEN);
+			kfree_skb(skb);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		} else {
+			if (new_skb != skb)
+				dev_kfree_skb_any(skb);
+			skb = new_skb;
+		}
+	}
+	/* This is SDIO/PCIE specific header length: byte[3][2][1], * type:
+	   byte[0] (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor)
+	 */
+	skb_push(skb, BT_HEADER_LEN);
+	skb->data[0] = (skb->len & 0x0000ff);
+	skb->data[1] = (skb->len & 0x00ff00) >> 8;
+	skb->data[2] = (skb->len & 0xff0000) >> 16;
+	skb->data[3] = bt_cb(skb)->pkt_type;
+	if (bt_cb(skb)->pkt_type == MRVL_VENDOR_PKT)
+		PRINTM(CMD, "DNLD_CMD: ocf_ogf=0x%x len=%d\n",
+		       __le16_to_cpu(*((u16 *) & skb->data[4])), skb->len);
+	ret = sbi_host_to_card(priv, skb->data, skb->len);
+	if (ret == BT_STATUS_FAILURE)
+		update_stat_err_tx(priv, skb);
+	else
+		update_stat_byte_tx(priv, skb);
+	if (ret != BT_STATUS_PENDING)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+#ifdef CONFIG_OF
+/**
+ *  @brief This function read the initial parameter from device tress
+ *
+ *
+ *  @return         N/A
+ */
+static void
+bt_init_from_dev_tree(void)
+{
+	struct device_node *dt_node = NULL;
+	struct property *prop;
+	u32 data;
+	const char *string_data;
+
+	ENTER();
+
+	if (!dts_enable) {
+		PRINTM(CMD, "DTS is disabled!");
+		return;
+	}
+
+	dt_node = of_find_node_by_name(NULL, "sd8xxx-bt");
+	if (!dt_node) {
+		LEAVE();
+		return;
+	}
+	for_each_property_of_node(dt_node, prop) {
+#ifdef DEBUG_LEVEL1
+		if (!strncmp(prop->name, "mbt_drvdbg", strlen("mbt_drvdbg"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(CMD, "mbt_drvdbg=0x%x\n", data);
+				mbt_drvdbg = data;
+			}
+		}
+#endif
+		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(CMD, "init_cfg=%s\n", init_cfg);
+			}
+		} else if (!strncmp
+			   (prop->name, "cal_cfg_ext", strlen("cal_cfg_ext"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg_ext = (char *)string_data;
+				PRINTM(CMD, "cal_cfg_ext=%s\n", cal_cfg_ext);
+			}
+		} else if (!strncmp(prop->name, "cal_cfg", strlen("cal_cfg"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg = (char *)string_data;
+				PRINTM(CMD, "cal_cfg=%s\n", cal_cfg);
+			}
+		} else if (!strncmp(prop->name, "bt_mac", strlen("bt_mac"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				bt_mac = (char *)string_data;
+				PRINTM(CMD, "bt_mac=%s\n", bt_mac);
+			}
+		} else if (!strncmp(prop->name, "btindrst", strlen("btindrst"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btindrst = data;
+				PRINTM(CMD, "btindrst=%d\n", btindrst);
+			}
+		} else if (!strncmp(prop->name, "btpmic", strlen("btpmic"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btpmic = data;
+				PRINTM(CMD, "btpmic=%d\n", btpmic);
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function initializes the adapter structure
+ *  and set default value to the member of adapter.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+static void
+bt_init_adapter(bt_private *priv)
+{
+	ENTER();
+#ifdef CONFIG_OF
+	bt_init_from_dev_tree();
+#endif
+	skb_queue_head_init(&priv->adapter->tx_queue);
+	skb_queue_head_init(&priv->adapter->pending_queue);
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+	priv->adapter->fwdump_fname = NULL;
+	init_waitqueue_head(&priv->adapter->cmd_wait_q);
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (fw == 0) {
+		sbi_enable_host_int(priv);
+		goto done;
+	}
+	sbi_disable_host_int(priv);
+	if ((priv->card_type == CARD_TYPE_SD8787) ||
+	    (priv->card_type == CARD_TYPE_SD8777))
+		priv->fw_crc_check = fw_crc_check;
+	if (sbi_download_fw(priv)) {
+		PRINTM(ERROR, " FW failed to be download!\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#define FW_POLL_TRIES 100
+#define SD8897_FW_RESET_REG  0x0E8
+#define SD8887_FW_RESET_REG  0x0B6
+#define SD8977_SD8978_SD8997_FW_RESET_REG  0x0EE
+#define SD8887_SD8897_FW_RESET_VAL  1
+#define SD8977_SD8978_SD8997_FW_RESET_VAL  0x99
+
+/**
+ *  @brief This function reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   FW reload mode
+ *
+ *  @return       0--success, otherwise failure
+ */
+static int
+bt_reload_fw(bt_private *priv, int mode)
+{
+	int ret = 0, tries = 0;
+	u8 value = 1;
+	u32 reset_reg = 0;
+	u8 reset_val = 0;
+
+	ENTER();
+	if ((mode != FW_RELOAD_SDIO_INBAND_RESET) &&
+	    (mode != FW_RELOAD_NO_EMULATION)) {
+		PRINTM(ERROR, "Invalid fw reload mode=%d\n", mode);
+		return -EFAULT;
+	}
+
+    /** flush pending tx_queue */
+	skb_queue_purge(&priv->adapter->tx_queue);
+	if (mode == FW_RELOAD_SDIO_INBAND_RESET) {
+		if (priv->card_type == CARD_TYPE_SD8887) {
+			reset_reg = SD8887_FW_RESET_REG;
+			reset_val = SD8887_SD8897_FW_RESET_VAL;
+		} else if (priv->card_type == CARD_TYPE_SD8897) {
+			reset_reg = SD8897_FW_RESET_REG;
+			reset_val = SD8887_SD8897_FW_RESET_VAL;
+		} else if ((priv->card_type == CARD_TYPE_SD8977) ||
+			   (priv->card_type == CARD_TYPE_SD8997) ||
+			   (priv->card_type == CARD_TYPE_SD8978) ||
+			   (priv->card_type == CARD_TYPE_SD8987)) {
+			reset_reg = SD8977_SD8978_SD8997_FW_RESET_REG;
+			reset_val = SD8977_SD8978_SD8997_FW_RESET_VAL;
+		}
+		sbi_disable_host_int(priv);
+	    /** Wake up firmware firstly */
+		sbi_wakeup_firmware(priv);
+
+	/** wait SOC fully wake up */
+		for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_write_reg(priv, reset_reg, 0xba);
+			if (!ret) {
+				ret = sd_read_reg(priv, reset_reg, &value);
+				if (!ret && (value == 0xba)) {
+					PRINTM(MSG, "Fw wake up\n");
+					break;
+				}
+			}
+			udelay(1000);
+		}
+
+		ret = sd_write_reg(priv, reset_reg, reset_val);
+		if (ret) {
+			PRINTM(ERROR, "Failed to write register.\n");
+			goto done;
+		}
+
+	    /** Poll register around 1 ms */
+		for (; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_read_reg(priv, reset_reg, &value);
+			if (ret) {
+				PRINTM(ERROR, "Failed to read register.\n");
+				goto done;
+			}
+			if (value == 0)
+			    /** FW is ready */
+				break;
+			udelay(1000);
+		}
+		if (value) {
+			PRINTM(ERROR,
+			       "Failed to poll FW reset register %X=0x%x\n",
+			       reset_reg, value);
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	sbi_enable_host_int(priv);
+	/** reload FW */
+	ret = bt_init_fw(priv);
+	if (ret) {
+		PRINTM(ERROR, "Re download firmware failed.\n");
+		ret = -EFAULT;
+	}
+	LEAVE();
+	return ret;
+done:
+	sbi_enable_host_int(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function request to reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   fw reload mode.
+ *
+ *  @return         N/A
+ */
+void
+bt_request_fw_reload(bt_private *priv, int mode)
+{
+	ENTER();
+	if (mode == FW_RELOAD_WITH_EMULATION) {
+		bt_fw_reload = FW_RELOAD_WITH_EMULATION;
+		PRINTM(MSG, "BT: FW reload with re-emulation...\n");
+		LEAVE();
+		return;
+	}
+	/** Reload FW */
+	priv->fw_reload = TRUE;
+	if (bt_reload_fw(priv, mode)) {
+		PRINTM(ERROR, "FW reload fail\n");
+		goto done;
+	}
+	priv->fw_reload = FALSE;
+	/** Other operation here? */
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function frees the structure of adapter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+void
+bt_free_adapter(bt_private *priv)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	kfree(adapter->tx_buffer);
+	kfree(adapter->hw_regs_buf);
+	/* Free allocated memory for fwdump filename */
+	if (adapter->fwdump_fname) {
+		kfree(adapter->fwdump_fname);
+		adapter->fwdump_fname = NULL;
+	}
+	/* Free the adapter object itself */
+	kfree(adapter);
+	priv->adapter = NULL;
+
+	LEAVE();
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+/**
+ *  @brief This function handles the BT ioctl
+ *
+ *  @param hdev     A pointer to hci_dev structure
+ *  @cmd            ioctl cmd
+ *  @arg            argument
+ *  @return    -ENOIOCTLCMD
+ */
+static int
+bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
+{
+	ENTER();
+	LEAVE();
+	return -ENOIOCTLCMD;
+}
+#endif
+
+/**
+ *  @brief This function handles the wrapper_dev ioctl
+ *
+ *  @param hev     A pointer to wrapper_dev structure
+ *  @cmd            ioctl cmd
+ *  @arg            argument
+ *  @return    -ENOIOCTLCMD
+ */
+static int
+mdev_ioctl(struct m_dev *m_dev, unsigned int cmd, void *arg)
+{
+	bt_private *priv = NULL;
+	int ret = 0;
+
+	ENTER();
+
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Ioctl for unknown device (m_dev=NULL)\n");
+		ret = -ENODEV;
+		goto done;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "HCI_RUNNING not set, flag=0x%lx\n",
+		       m_dev->flags);
+		ret = -EBUSY;
+		goto done;
+	}
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+	default:
+		break;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles BT destruct
+ *
+ *  @param hdev    A pointer to hci_dev structure
+ *
+ *  @return    N/A
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
+static void
+bt_destruct(struct hci_dev *hdev)
+{
+	ENTER();
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function handles wrapper device destruct
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    N/A
+ */
+static void
+mdev_destruct(struct m_dev *m_dev)
+{
+	ENTER();
+	LEAVE();
+	return;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+/**
+ *  @brief This function handles the BT transmit
+ *
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    BT_STATUS_SUCCESS or other error no.
+ */
+static int
+bt_send_frame(struct sk_buff *skb)
+#else
+/**
+ *  @brief This function handles the BT transmit
+ *
+ *  @param hdev    A pointer to hci_dev structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    BT_STATUS_SUCCESS or other error no.
+ */
+static int
+bt_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
+#endif
+{
+	bt_private *priv = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
+#else
+	skb->dev = (void *)hdev;
+#endif
+
+	ENTER();
+	PRINTM(DATA, "bt_send_frame %s: Type=%d, len=%d\n", hdev->name,
+	       bt_cb(skb)->pkt_type, skb->len);
+	DBG_HEXDUMP(CMD_D, "bt_send_frame", skb->data, skb->len);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	if (!hdev || !hci_get_drvdata(hdev)) {
+#else
+	if (!hdev || !hdev->driver_data) {
+#endif
+		PRINTM(ERROR, "Frame for unknown HCI device (hdev=NULL)\n");
+		LEAVE();
+		return -ENODEV;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	priv = (bt_private *)hci_get_drvdata(hdev);
+#else
+	priv = (bt_private *)hdev->driver_data;
+#endif
+	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+		PRINTM(ERROR, "Fail test HCI_RUNNING, flag=0x%lx\n",
+		       hdev->flags);
+		LEAVE();
+		return -EBUSY;
+	}
+	switch (bt_cb(skb)->pkt_type) {
+	case HCI_COMMAND_PKT:
+		hdev->stat.cmd_tx++;
+		break;
+	case HCI_ACLDATA_PKT:
+		hdev->stat.acl_tx++;
+		break;
+	case HCI_SCODATA_PKT:
+		hdev->stat.sco_tx++;
+		break;
+	}
+	if (priv->adapter->tx_lock == TRUE)
+		skb_queue_tail(&priv->adapter->pending_queue, skb);
+	else
+		bt_queue_frame(priv, skb);
+
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the wrapper device transmit
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    BT_STATUS_SUCCESS or other error no.
+ */
+static int
+mdev_send_frame(struct m_dev *m_dev, struct sk_buff *skb)
+{
+	bt_private *priv = NULL;
+
+	ENTER();
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Frame for unknown HCI device (m_dev=NULL)\n");
+		LEAVE();
+		return -ENODEV;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "Fail test HCI_RUNNING, flag=0x%lx\n",
+		       m_dev->flags);
+		LEAVE();
+		return -EBUSY;
+	}
+	switch (bt_cb(skb)->pkt_type) {
+	case HCI_COMMAND_PKT:
+		m_dev->stat.cmd_tx++;
+		break;
+	case HCI_ACLDATA_PKT:
+		m_dev->stat.acl_tx++;
+		break;
+	case HCI_SCODATA_PKT:
+		m_dev->stat.sco_tx++;
+		break;
+	}
+
+	if (priv->adapter->tx_lock == TRUE)
+		skb_queue_tail(&priv->adapter->pending_queue, skb);
+	else
+		bt_queue_frame(priv, skb);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function flushes the transmit queue
+ *
+ *  @param hdev     A pointer to hci_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+bt_flush(struct hci_dev *hdev)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	bt_private *priv = (bt_private *)hci_get_drvdata(hdev);
+#else
+	bt_private *priv = (bt_private *)hdev->driver_data;
+#endif
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	skb_queue_purge(&priv->adapter->pending_queue);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function flushes the transmit queue
+ *
+ *  @param m_dev     A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_flush(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	skb_queue_purge(&priv->adapter->pending_queue);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function closes the bluetooth device
+ *
+ *  @param hdev    A pointer to hci_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+bt_close(struct hci_dev *hdev)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	bt_private *priv = (bt_private *)hci_get_drvdata(hdev);
+#else
+	bt_private *priv = (bt_private *)hdev->driver_data;
+#endif
+
+	ENTER();
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 3, 0)
+	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) {
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+#endif
+	skb_queue_purge(&priv->adapter->tx_queue);
+
+	module_put(THIS_MODULE);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function closes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_close(struct m_dev *m_dev)
+{
+
+	ENTER();
+	mdev_req_lock(m_dev);
+	if (!test_and_clear_bit(HCI_UP, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+
+	if (m_dev->flush)
+		m_dev->flush(m_dev);
+	/* wait up pending read and unregister char dev */
+	wake_up_interruptible(&m_dev->req_wait_q);
+	/* Drop queues */
+	skb_queue_purge(&m_dev->rx_q);
+	if (!test_and_clear_bit(HCI_RUNNING, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+	module_put(THIS_MODULE);
+	m_dev->flags = 0;
+	mdev_req_unlock(m_dev);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function opens the bluetooth device
+ *
+ *  @param hdev    A pointer to hci_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+static int
+bt_open(struct hci_dev *hdev)
+{
+	ENTER();
+	if (try_module_get(THIS_MODULE) == 0)
+		return BT_STATUS_FAILURE;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 3, 0)
+	set_bit(HCI_RUNNING, &hdev->flags);
+#endif
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function opens the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+static int
+mdev_open(struct m_dev *m_dev)
+{
+	ENTER();
+
+	if (try_module_get(THIS_MODULE) == 0)
+		return BT_STATUS_FAILURE;
+
+	set_bit(HCI_RUNNING, &m_dev->flags);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function queries the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param arg     arguement
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+mdev_query(struct m_dev *m_dev, void *arg)
+{
+	struct mbt_dev *mbt_dev = (struct mbt_dev *)m_dev->dev_pointer;
+
+	ENTER();
+	if (copy_to_user(arg, &mbt_dev->type, sizeof(mbt_dev->type)))
+		PRINTM(ERROR, "IOCTL_QUERY_TYPE: Fail copy to user\n");
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+init_m_dev(struct m_dev *m_dev)
+{
+	m_dev->dev_pointer = NULL;
+	m_dev->driver_data = NULL;
+	m_dev->dev_type = 0;
+	m_dev->spec_type = 0;
+	skb_queue_head_init(&m_dev->rx_q);
+	init_waitqueue_head(&m_dev->req_wait_q);
+	init_waitqueue_head(&m_dev->rx_wait_q);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+	init_MUTEX(&m_dev->req_lock);
+#else
+	sema_init(&m_dev->req_lock, 1);
+#endif
+	spin_lock_init(&m_dev->rxlock);
+	memset(&m_dev->stat, 0, sizeof(struct hci_dev_stats));
+	m_dev->open = mdev_open;
+	m_dev->close = mdev_close;
+	m_dev->flush = mdev_flush;
+	m_dev->send = mdev_send_frame;
+	m_dev->destruct = mdev_destruct;
+	m_dev->ioctl = mdev_ioctl;
+	m_dev->query = mdev_query;
+	m_dev->owner = THIS_MODULE;
+
+}
+
+/**
+ *  @brief This function handles the major job in bluetooth driver.
+ *  it handles the event generated by firmware, rx data received
+ *  from firmware and tx data sent from kernel.
+ *
+ *  @param data    A pointer to bt_thread structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+static int
+bt_service_main_thread(void *data)
+{
+	bt_thread *thread = data;
+	bt_private *priv = thread->priv;
+	bt_adapter *adapter = priv->adapter;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
+	wait_queue_t wait;
+#else
+	wait_queue_entry_t wait;
+#endif
+	struct sk_buff *skb;
+	ENTER();
+	bt_activate_thread(thread);
+	init_waitqueue_entry(&wait, current);
+	current->flags |= PF_NOFREEZE;
+
+	for (;;) {
+		add_wait_queue(&thread->waitQ, &wait);
+		OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE);
+		if (priv->adapter->WakeupTries ||
+		    ((!priv->adapter->IntCounter) &&
+		     (!priv->bt_dev.tx_dnld_rdy ||
+		      skb_queue_empty(&priv->adapter->tx_queue))
+		    )) {
+			PRINTM(INFO, "Main: Thread sleeping...\n");
+			schedule();
+		}
+		OS_SET_THREAD_STATE(TASK_RUNNING);
+		remove_wait_queue(&thread->waitQ, &wait);
+		if (kthread_should_stop() || adapter->SurpriseRemoved) {
+			PRINTM(INFO, "main-thread: break from main thread: "
+			       "SurpriseRemoved=0x%x\n",
+			       adapter->SurpriseRemoved);
+			break;
+		}
+
+		PRINTM(INFO, "Main: Thread waking up...\n");
+
+		if (priv->adapter->IntCounter) {
+			OS_INT_DISABLE;
+			adapter->IntCounter = 0;
+			OS_INT_RESTORE;
+			sbi_get_int_status(priv);
+		} else if ((priv->adapter->ps_state == PS_SLEEP) &&
+			   (!skb_queue_empty(&priv->adapter->tx_queue)
+			   )) {
+			priv->adapter->WakeupTries++;
+			sbi_wakeup_firmware(priv);
+			continue;
+		}
+		if (priv->adapter->ps_state == PS_SLEEP)
+			continue;
+		if (priv->bt_dev.tx_dnld_rdy == TRUE) {
+			if (!skb_queue_empty(&priv->adapter->tx_queue)) {
+				skb = skb_dequeue(&priv->adapter->tx_queue);
+				if (skb)
+					send_single_packet(priv, skb);
+			}
+		}
+	}
+	bt_deactivate_thread(thread);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the interrupt. it will change PS
+ *  state if applicable. it will wake up main_thread to handle
+ *  the interrupt event as well.
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @return        N/A
+ */
+void
+bt_interrupt(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	if (!priv || !priv->adapter) {
+		LEAVE();
+		return;
+	}
+	PRINTM(INTR, "*\n");
+	priv->adapter->ps_state = PS_AWAKE;
+	if (priv->adapter->hs_state == HS_ACTIVATED) {
+		PRINTM(CMD, "BT: %s: HS DEACTIVATED in ISR!\n", m_dev->name);
+		priv->adapter->hs_state = HS_DEACTIVATED;
+	}
+	priv->adapter->WakeupTries = 0;
+	priv->adapter->IntCounter++;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	LEAVE();
+}
+
+/**
+ * @brief  Dynamic release of bt private
+ *
+ * @param kobj          A pointer to kobject structure
+ *
+ * @return                N/A
+ */
+static void
+bt_private_dynamic_release(struct kobject *kobj)
+{
+	bt_private *priv = container_of(kobj, bt_private, kobj);
+	ENTER();
+	PRINTM(INFO, "free bt priv\n");
+	kfree(priv);
+	LEAVE();
+}
+
+static struct kobj_type ktype_bt_private_dynamic = {
+	.release = bt_private_dynamic_release,
+};
+
+/**
+ * @brief  Allocation of bt private
+ *
+ * @param           	N/A
+ *
+ * @return              bt_private
+ */
+static bt_private *
+bt_alloc_priv(void)
+{
+	bt_private *priv;
+	ENTER();
+	priv = kzalloc(sizeof(bt_private), GFP_KERNEL);
+	if (priv) {
+		kobject_init(&priv->kobj, &ktype_bt_private_dynamic);
+		PRINTM(INFO, "alloc bt priv\n");
+	}
+	LEAVE();
+	return priv;
+}
+
+/**
+ * @brief  Get bt private structure
+ *
+ * @param priv          A pointer to bt_private structure
+ *
+ * @return              kobject structure
+ */
+struct kobject *
+bt_priv_get(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv get object");
+	return kobject_get(&priv->kobj);
+}
+
+/**
+ * @brief  Get bt private structure
+ *
+ * @param priv          A pointer to bt_private structure
+ *
+ * @return              N/A
+ */
+void
+bt_priv_put(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv put object");
+	kobject_put(&priv->kobj);
+}
+
+/**
+ *  @brief This function send init commands to firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_init_cmd(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = bt_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+	if (ret < 0) {
+		PRINTM(FATAL, "Module cfg command send failed!\n");
+		goto done;
+	}
+	if (btindrst != -1) {
+		ret = bt_set_independent_reset(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Independent reset failed!\n");
+			goto done;
+		}
+	}
+	if (btpmic
+	    && ((priv->card_type == CARD_TYPE_SD8997) ||
+		(priv->card_type == CARD_TYPE_SD8977) ||
+		(priv->card_type == CARD_TYPE_SD8978))
+		) {
+		if (BT_STATUS_SUCCESS != bt_pmic_configure(priv)) {
+			PRINTM(FATAL, "BT: PMIC Configure failed \n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	ret = bt_set_ble_deepsleep(priv, deep_sleep ? TRUE : FALSE);
+	if (ret < 0) {
+		PRINTM(FATAL, "%s BLE deepsleep failed!\n",
+		       deep_sleep ? "Enable" : "Disable");
+		goto done;
+	}
+	if (psmode) {
+		priv->bt_dev.psmode = TRUE;
+		priv->bt_dev.idle_timeout = DEFAULT_IDLE_TIME;
+		ret = bt_enable_ps(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Enable PS mode failed!\n");
+			goto done;
+		}
+	}
+#if defined(SDIO_SUSPEND_RESUME)
+	priv->bt_dev.gpio_gap = DEF_GPIO_GAP;
+	ret = bt_send_hscfg_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "Send HSCFG failed!\n");
+		goto done;
+	}
+#endif
+	priv->bt_dev.sdio_pull_cfg = 0xffffffff;
+	priv->bt_dev.sdio_pull_ctrl = 0;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reinit firmware after redownload firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_reinit_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+	/* block all the packet from bluez */
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext)
+		priv->adapter->tx_lock = TRUE;
+
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext) {
+		priv->adapter->tx_lock = FALSE;
+		bt_restore_tx_queue(priv);
+	}
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+done:
+	return ret;
+}
+
+/**
+ *  @brief Module configuration and register device
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @return      BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_conf_dpc(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct hci_dev *hdev = NULL;
+	unsigned char dev_type = 0;
+
+	ENTER();
+
+	priv->bt_dev.tx_dnld_rdy = TRUE;
+	if (priv->fw_reload) {
+		bt_reinit_fw(priv);
+		LEAVE();
+		return ret;
+	}
+
+	if (drv_mode & DRV_MODE_BT) {
+		hdev = hci_alloc_dev();
+		if (!hdev) {
+			PRINTM(FATAL, "Can not allocate HCI device\n");
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		hdev->open = bt_open;
+		hdev->close = bt_close;
+		hdev->flush = bt_flush;
+		hdev->send = bt_send_frame;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
+		hdev->destruct = bt_destruct;
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+		hdev->ioctl = bt_ioctl;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+		hci_set_drvdata(hdev, priv);
+#else
+		hdev->driver_data = priv;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
+		hdev->owner = THIS_MODULE;
+#endif
+		priv->bt_dev.m_dev[BT_SEQ].dev_type = BT_TYPE;
+		priv->bt_dev.m_dev[BT_SEQ].spec_type = BLUEZ_SPEC;
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = (void *)hdev;
+		priv->bt_dev.m_dev[BT_SEQ].driver_data = priv;
+		priv->bt_dev.m_dev[BT_SEQ].read_continue_flag = 0;
+	}
+
+	dev_type = HCI_SDIO;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+	if (hdev)
+		hdev->bus = dev_type;
+#else
+	if (hdev)
+		hdev->type = dev_type;
+#endif /* >= 2.6.34 */
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+
+	/** Process device tree init parameters before register hci device.
+	 *  Since uplayer device has not yet registered, no need to block tx queue.
+	 * */
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	} else if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Get FW version */
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+
+	if (hdev) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+		hdev->dev_type = priv->bt_dev.devType;
+#endif
+		ret = hci_register_dev(hdev);
+		if (ret < 0) {
+			PRINTM(FATAL, "Can not register HCI device\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		snprintf((char *)priv->bt_dev.m_dev[BT_SEQ].name,
+			 sizeof(priv->bt_dev.m_dev[BT_SEQ].name), hdev->name);
+		bt_proc_init(priv, &(priv->bt_dev.m_dev[BT_SEQ]), BT_SEQ);
+	}
+
+done:
+	LEAVE();
+	return ret;
+err_kmalloc:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function adds the card. it will probe the
+ *  card, allocate the bt_priv and initialize the device.
+ *
+ *  @param card    A pointer to card
+ *  @return        A pointer to bt_private structure
+ */
+
+bt_private *
+bt_add_card(void *card)
+{
+	bt_private *priv = NULL;
+	int index = 0;
+
+	ENTER();
+
+	priv = bt_alloc_priv();
+	if (!priv) {
+		PRINTM(FATAL, "Can not allocate priv\n");
+		LEAVE();
+		return NULL;
+	}
+	/* Save the handle */
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == NULL)
+			break;
+	}
+	if (index < MAX_BT_ADAPTER) {
+		m_priv[index] = priv;
+	} else {
+		PRINTM(ERROR, "Exceeded maximum cards supported!\n");
+		goto err_kmalloc;
+	}
+	/* allocate buffer for bt_adapter */
+	priv->adapter = kzalloc(sizeof(bt_adapter), GFP_KERNEL);
+	if (!priv->adapter) {
+		PRINTM(FATAL, "Allocate buffer for bt_adapter failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buffer =
+		kzalloc(MAX_TX_BUF_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->tx_buffer) {
+		PRINTM(FATAL, "Allocate buffer for transmit\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buf =
+		(u8 *)ALIGN_ADDR(priv->adapter->tx_buffer, DMA_ALIGNMENT);
+	priv->adapter->hw_regs_buf =
+		kzalloc(SD_BLOCK_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->hw_regs_buf) {
+		PRINTM(FATAL, "Allocate buffer for INT read buf failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->hw_regs =
+		(u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf, DMA_ALIGNMENT);
+	bt_init_adapter(priv);
+
+	PRINTM(INFO, "Starting kthread...\n");
+	priv->MainThread.priv = priv;
+	spin_lock_init(&priv->driver_lock);
+
+	bt_create_thread(bt_service_main_thread, &priv->MainThread,
+			 "bt_main_service");
+
+	/* wait for mainthread to up */
+	while (!priv->MainThread.pid)
+		os_sched_timeout(1);
+
+	sdio_update_card_type(priv, card);
+	/* Update driver version */
+	if (priv->card_type == CARD_TYPE_SD8787)
+		memcpy(mbt_driver_version, CARD_SD8787, strlen(CARD_SD8787));
+	else if (priv->card_type == CARD_TYPE_SD8777)
+		memcpy(mbt_driver_version, CARD_SD8777, strlen(CARD_SD8777));
+	else if (priv->card_type == CARD_TYPE_SD8887)
+		memcpy(mbt_driver_version, CARD_SD8887, strlen(CARD_SD8887));
+	else if (priv->card_type == CARD_TYPE_SD8897)
+		memcpy(mbt_driver_version, CARD_SD8897, strlen(CARD_SD8897));
+	else if (priv->card_type == CARD_TYPE_SD8797)
+		memcpy(mbt_driver_version, CARD_SD8797, strlen(CARD_SD8797));
+	else if (priv->card_type == CARD_TYPE_SD8977)
+		memcpy(mbt_driver_version, CARD_SD8977, strlen(CARD_SD8977));
+	else if (priv->card_type == CARD_TYPE_SD8978)
+		memcpy(mbt_driver_version, CARD_SD8978, strlen(CARD_SD8978));
+	else if (priv->card_type == CARD_TYPE_SD8997)
+		memcpy(mbt_driver_version, CARD_SD8997, strlen(CARD_SD8997));
+	else if (priv->card_type == CARD_TYPE_SD8987)
+		memcpy(mbt_driver_version, CARD_SD8987, strlen(CARD_SD8987));
+
+	if (BT_STATUS_SUCCESS != sdio_get_sdio_device(priv))
+		goto err_kmalloc;
+
+	/** user config file */
+	init_waitqueue_head(&priv->init_user_conf_wait_q);
+
+	priv->bt_dev.card = card;
+
+	((struct sdio_mmc_card *)card)->priv = priv;
+	priv->adapter->sd_ireg = 0;
+	/*
+	 * Register the device. Fillup the private data structure with
+	 * relevant information from the card and request for the required
+	 * IRQ.
+	 */
+	if (sbi_register_dev(priv) < 0) {
+		PRINTM(FATAL, "Failed to register bt device!\n");
+		goto err_registerdev;
+	}
+	if (bt_init_fw(priv)) {
+		PRINTM(FATAL, "BT Firmware Init Failed\n");
+		goto err_init_fw;
+	}
+	LEAVE();
+	return priv;
+
+err_init_fw:
+	clean_up_m_devs(priv);
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+err_registerdev:
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+err_kmalloc:
+	if (priv->adapter)
+		bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function send hardware remove event
+ *
+ *  @param priv    A pointer to bt_private
+ *  @return        N/A
+ */
+void
+bt_send_hw_remove_event(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	struct hci_dev *hdev = NULL;
+	ENTER();
+	if (!priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		LEAVE();
+		return;
+	}
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type == BLUEZ_SPEC)
+		hdev = (struct hci_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer;
+#define HCI_HARDWARE_ERROR_EVT  0x10
+#define HCI_HARDWARE_REMOVE     0x24
+	skb = bt_skb_alloc(3, GFP_ATOMIC);
+	skb->data[0] = HCI_HARDWARE_ERROR_EVT;
+	skb->data[1] = 1;
+	skb->data[2] = HCI_HARDWARE_REMOVE;
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb_put(skb, 3);
+	if (hdev) {
+		skb->dev = (void *)hdev;
+		PRINTM(MSG, "Send HW ERROR event\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+		hci_recv_frame(skb);
+#else
+		hci_recv_frame(hdev, skb);
+#endif
+		os_sched_timeout(5);
+		hdev->stat.byte_rx += 3;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function removes the card.
+ *
+ *  @param card    A pointer to card
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_remove_card(void *card)
+{
+	bt_private *priv = (bt_private *)card;
+	int index;
+	ENTER();
+	if (!priv) {
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv->adapter->SurpriseRemoved = TRUE;
+
+	bt_send_hw_remove_event(priv);
+	wake_up_interruptible(&priv->adapter->cmd_wait_q);
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid) {
+		os_sched_timeout(1);
+		wake_up_interruptible(&priv->MainThread.waitQ);
+	}
+
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+	clean_up_m_devs(priv);
+	PRINTM(INFO, "Free Adapter\n");
+	bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function initializes module.
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_module(void)
+{
+	int ret = BT_STATUS_SUCCESS;
+	int index;
+	ENTER();
+	PRINTM(MSG, "BT: Loading driver\n");
+	/* Init the bt_private pointer array first */
+	for (index = 0; index < MAX_BT_ADAPTER; index++)
+		m_priv[index] = NULL;
+	bt_root_proc_init();
+
+	/** create char device class */
+	chardev_class = class_create(THIS_MODULE, MODULE_NAME);
+	if (IS_ERR(chardev_class)) {
+		PRINTM(ERROR, "Unable to allocate class\n");
+		bt_root_proc_remove();
+		ret = PTR_ERR(chardev_class);
+		goto done;
+	}
+
+	if (sbi_register() == NULL) {
+		bt_root_proc_remove();
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	if (ret)
+		PRINTM(MSG, "BT: Driver loading failed\n");
+	else
+		PRINTM(MSG, "BT: Driver loaded successfully\n");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function cleans module
+ *
+ *  @return        N/A
+ */
+static void
+bt_exit_module(void)
+{
+	bt_private *priv;
+	int index;
+	ENTER();
+	PRINTM(MSG, "BT: Unloading driver\n");
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		priv = m_priv[index];
+		if (!priv)
+			continue;
+		if (priv && !priv->adapter->SurpriseRemoved) {
+			if (BT_STATUS_SUCCESS == bt_send_reset_command(priv))
+				bt_send_module_cfg_cmd(priv,
+						       MODULE_SHUTDOWN_REQ);
+		}
+		sbi_disable_host_int(priv);
+
+	}
+
+	sbi_unregister();
+
+	bt_root_proc_remove();
+	class_destroy(chardev_class);
+	PRINTM(MSG, "BT: Driver unloaded\n");
+	LEAVE();
+}
+
+module_init(bt_init_module);
+module_exit(bt_exit_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell Bluetooth Driver Ver. " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+module_param(fw, int, 0);
+MODULE_PARM_DESC(fw, "0: Skip firmware download; otherwise: Download firmware");
+module_param(fw_crc_check, int, 0);
+MODULE_PARM_DESC(fw_crc_check,
+		 "1: Enable FW download CRC check (default); 0: Disable FW download CRC check");
+module_param(psmode, int, 0);
+MODULE_PARM_DESC(psmode, "1: Enable powermode; 0: Disable powermode");
+module_param(deep_sleep, int, 0);
+MODULE_PARM_DESC(deep_sleep, "1: Enable deep sleep; 0: Disable deep sleep");
+#ifdef CONFIG_OF
+module_param(dts_enable, int, 0);
+MODULE_PARM_DESC(dts_enable, "0: Disable DTS; 1: Enable DTS");
+#endif
+#ifdef	DEBUG_LEVEL1
+module_param(mbt_drvdbg, uint, 0);
+MODULE_PARM_DESC(mbt_drvdbg, "BIT3:DBG_DATA BIT4:DBG_CMD 0xFF:DBG_ALL");
+#endif
+#ifdef SDIO_SUSPEND_RESUME
+module_param(mbt_pm_keep_power, int, 0);
+MODULE_PARM_DESC(mbt_pm_keep_power, "1: PM keep power; 0: PM no power");
+#endif
+module_param(init_cfg, charp, 0);
+MODULE_PARM_DESC(init_cfg, "BT init config file name");
+module_param(cal_cfg, charp, 0);
+MODULE_PARM_DESC(cal_cfg, "BT calibrate file name");
+module_param(cal_cfg_ext, charp, 0);
+MODULE_PARM_DESC(cal_cfg_ext, "BT calibrate ext file name");
+module_param(bt_mac, charp, 0660);
+MODULE_PARM_DESC(bt_mac, "BT init mac address");
+module_param(drv_mode, int, 0);
+MODULE_PARM_DESC(drv_mode, "Bit 0: BT/AMP/BLE;");
+module_param(bt_fw_reload, int, 0);
+MODULE_PARM_DESC(bt_fw_reload,
+		 "0: disable fw_reload; 1: enable fw reload feature");
+module_param(btindrst, int, 0);
+MODULE_PARM_DESC(btindrst,
+		 "Independent reset configuration; high byte:GPIO pin number;low byte:0x0:disable, 0x1:out-band reset, 0x2:in-band reset.");
+module_param(btpmic, int, 0);
+MODULE_PARM_DESC(btpmic,
+		 "1: Send pmic configure cmd to firmware; 0: No pmic configure cmd sent to firmware (default)");
+module_param(bt_fw_serial, int, 0);
+MODULE_PARM_DESC(bt_fw_serial,
+		 "0: Support parallel download FW; 1: Support serial download FW");
diff --git a/bt_sd8987/bt/bt_proc.c b/bt_sd8987/bt/bt_proc.c
new file mode 100644
index 0000000..0264c94
--- /dev/null
+++ b/bt_sd8987/bt/bt_proc.c
@@ -0,0 +1,723 @@
+/** @file bt_proc.c
+  *
+  * @brief This file handle the functions for proc files
+  *
+  * Copyright (C) 2007-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/proc_fs.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** proc diretory root */
+#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
+
+/** Proc mbt directory entry */
+static struct proc_dir_entry *proc_mbt;
+
+#define     CMD52_STR_LEN   50
+static char cmd52_string[CMD52_STR_LEN];
+
+/** proc data structure */
+struct proc_data {
+	/** Read length */
+	int rdlen;
+	/** Read buffer */
+	char *rdbuf;
+	/** Write length */
+	int wrlen;
+	/** Maximum write length */
+	int maxwrlen;
+	/** Write buffer */
+	char *wrbuf;
+	/** Private structure */
+	struct _bt_private *pbt;
+	void (*on_close) (struct inode *, struct file *);
+};
+
+/** Default file permission */
+#define DEFAULT_FILE_PERM  0644
+
+/** Bluetooth device offset */
+#define OFFSET_BT_DEV		0x01
+/** Bluetooth adapter offset */
+#define OFFSET_BT_ADAPTER	0x02
+/** Show integer */
+#define SHOW_INT		0x10
+/** Show hex */
+#define SHOW_HEX		0x20
+/** Show string */
+#define SHOW_STRING		0x40
+
+/** Device size */
+#define item_dev_size(n) (sizeof((bt_dev_t *)0)->n)
+/** Device address */
+#define item_dev_addr(n) ((t_ptr) &((bt_dev_t *)0)->n)
+
+/** Adapter size */
+#define item_adapter_size(n) (sizeof((bt_adapter *)0)->n)
+/** Adapter address */
+#define item_adapter_addr(n) ((t_ptr) &((bt_adapter *)0)->n)
+
+static struct item_data config_items[] = {
+#ifdef	DEBUG_LEVEL1
+	{"drvdbg", sizeof(u32), (t_ptr)&mbt_drvdbg, 0, SHOW_HEX}
+	,
+#endif
+	{"idle_timeout", item_dev_size(idle_timeout), 0,
+	 item_dev_addr(idle_timeout), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"psmode", item_dev_size(psmode), 0, item_dev_addr(psmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"pscmd", item_dev_size(pscmd), 0, item_dev_addr(pscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hsmode", item_dev_size(hsmode), 0, item_dev_addr(hsmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hscmd", item_dev_size(hscmd), 0, item_dev_addr(hscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"gpio_gap", item_dev_size(gpio_gap), 0, item_dev_addr(gpio_gap),
+	 OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"hscfgcmd", item_dev_size(hscfgcmd), 0, item_dev_addr(hscfgcmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"sdio_pull_cfg", item_dev_size(sdio_pull_cfg), 0,
+	 item_dev_addr(sdio_pull_cfg), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"sdio_pull_ctrl", item_dev_size(sdio_pull_ctrl), 0,
+	 item_dev_addr(sdio_pull_ctrl), OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"test_mode", item_dev_size(test_mode), 0, item_dev_addr(test_mode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+
+};
+
+static struct item_data status_items[] = {
+	{"version", item_adapter_size(drv_ver), 0, item_adapter_addr(drv_ver),
+	 OFFSET_BT_ADAPTER | SHOW_STRING},
+	{"tx_dnld_rdy", item_dev_size(tx_dnld_rdy), 0,
+	 item_dev_addr(tx_dnld_rdy),
+	 OFFSET_BT_DEV | SHOW_INT},
+	{"psmode", item_adapter_size(psmode), 0, item_adapter_addr(psmode),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_state", item_adapter_size(hs_state), 0,
+	 item_adapter_addr(hs_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_skip", item_adapter_size(hs_skip), 0, item_adapter_addr(hs_skip),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"ps_state", item_adapter_size(ps_state), 0,
+	 item_adapter_addr(ps_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"WakeupTries", item_adapter_size(WakeupTries), 0,
+	 item_adapter_addr(WakeupTries), OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_recv", item_adapter_size(irq_recv), 0,
+	 item_adapter_addr(irq_recv),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_done", item_adapter_size(irq_done), 0,
+	 item_adapter_addr(irq_done),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"skb_pending", item_adapter_size(skb_pending), 0,
+	 item_adapter_addr(skb_pending), OFFSET_BT_ADAPTER | SHOW_INT},
+};
+
+static struct item_data debug_items[] = {
+	{"sdcmd52rw", 0, (t_ptr)cmd52_string, 0, SHOW_STRING},
+};
+
+/**
+ *  @brief convert string to number
+ *
+ *  @param s	pointer to numbered string
+ *  @return	converted number from string s
+ */
+int
+string_to_number(char *s)
+{
+	int r = 0;
+	int base = 0;
+	int pn = 1;
+
+	if (strncmp(s, "-", 1) == 0) {
+		pn = -1;
+		s++;
+	}
+	if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
+		base = 16;
+		s += 2;
+	} else
+		base = 10;
+
+	for (s = s; *s != 0; 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 Create cmd52 string
+ *
+ *  @param priv	A pointer to bt_private structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+form_cmd52_string(bt_private *priv)
+{
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	snprintf(cmd52_string, CMD52_STR_LEN - 1, "BT: %d 0x%0x 0x%02X",
+		 priv->bt_dev.cmd52_func, priv->bt_dev.cmd52_reg,
+		 priv->bt_dev.cmd52_val);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/*
+ *  @brief Parse cmd52 string
+ *
+ *  @param buffer  A pointer user buffer
+ *  @param len     Length of 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 __user * buffer, size_t len,
+		   int *func, int *reg, int *val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	char *string = NULL;
+	char *pos = NULL;
+
+	ENTER();
+
+	string = kzalloc(CMD52_STR_LEN, GFP_KERNEL);
+	if (!string) {
+		PRINTM(ERROR, "BT: Can not alloc mem for cmd52 string\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	memcpy(string, buffer + strlen("sdcmd52rw="),
+	       len - strlen("sdcmd52rw="));
+	string = strstrip(string);
+
+	*func = -1;
+	*reg = -1;
+	*val = -1;
+
+	/* Get func */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*func = string_to_number(pos);
+
+	/* Get reg */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*reg = string_to_number(pos);
+
+	/* Get val (optional) */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*val = string_to_number(pos);
+	kfree(string);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handle generic proc file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+proc_close(struct inode *inode, struct file *file)
+{
+	struct proc_data *pdata = file->private_data;
+	ENTER();
+	if (pdata) {
+		if (pdata->on_close != NULL)
+			pdata->on_close(inode, file);
+		kfree(pdata->rdbuf);
+		kfree(pdata->wrbuf);
+		kfree(pdata);
+	}
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle generic proc file read
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to output buffer
+ *  @param len     number of byte to read
+ *  @param offset  A pointer to offset of file
+ *  @return		number of output data
+ */
+static ssize_t
+proc_read(struct file *file, char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	if ((!pdata->rdbuf) || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->rdlen)
+		return 0;
+	if (len > pdata->rdlen - pos)
+		len = pdata->rdlen - pos;
+	if (copy_to_user(buffer, pdata->rdbuf + pos, len))
+		return -EFAULT;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle generic proc file write
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to input buffer
+ *  @param len     number of byte to write
+ *  @param offset  A pointer to offset of file
+ *  @return		number of input data
+ */
+static ssize_t
+proc_write(struct file *file,
+	   const char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	int func = 0, reg = 0, val = 0;
+	int config_data = 0;
+	char *line = NULL;
+
+	if (!pdata->wrbuf || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->maxwrlen)
+		return 0;
+	if (len > pdata->maxwrlen - pos)
+		len = pdata->maxwrlen - pos;
+	if (copy_from_user(pdata->wrbuf + pos, buffer, len))
+		return -EFAULT;
+	if (!strncmp(pdata->wrbuf + pos, "fw_reload", strlen("fw_reload"))) {
+		if (!strncmp
+		    (pdata->wrbuf + pos, "fw_reload=", strlen("fw_reload="))) {
+			line = pdata->wrbuf + pos;
+			line += strlen("fw_reload") + 1;
+			config_data = string_to_number(line);
+		} else
+			config_data = FW_RELOAD_SDIO_INBAND_RESET;
+		PRINTM(MSG, "Request fw_reload=%d\n", config_data);
+		bt_request_fw_reload(pdata->pbt, config_data);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "sdcmd52rw=", strlen("sdcmd52rw="))) {
+		parse_cmd52_string(pdata->wrbuf + pos, len, &func, &reg, &val);
+		sd_write_cmd52_val(pdata->pbt, func, reg, val);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "debug_dump", strlen("debug_dump"))) {
+		bt_dump_sdio_regs(pdata->pbt);
+		bt_dump_firmware_info_v2(pdata->pbt);
+	}
+
+	if (pos + len > pdata->wrlen)
+		pdata->wrlen = len + file->f_pos;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle the generic file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return		N/A
+ */
+static void
+proc_on_close(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata = file->private_data;
+	char *line;
+	int i;
+	ENTER();
+	if (!pdata->wrlen)
+		return;
+	line = pdata->wrbuf;
+	while (line[0]) {
+		for (i = 0; i < priv->num_items; i++) {
+			if (!strncmp
+			    (line, priv->pdata[i].name,
+			     strlen(priv->pdata[i].name))) {
+				line += strlen(priv->pdata[i].name) + 1;
+				if (priv->pdata[i].size == 1)
+					*((u8 *)priv->pdata[i].addr) =
+						(u8)string_to_number(line);
+				else if (priv->pdata[i].size == 2)
+					*((u16 *) priv->pdata[i].addr) =
+						(u16) string_to_number(line);
+				else if (priv->pdata[i].size == 4)
+					*((u32 *)priv->pdata[i].addr) =
+						(u32)string_to_number(line);
+			}
+		}
+		while (line[0] && line[0] != '\n')
+			line++;
+		if (line[0])
+			line++;
+	}
+	if (priv->pbt->bt_dev.hscmd || priv->pbt->bt_dev.pscmd
+	    || priv->pbt->bt_dev.sdio_pull_ctrl
+	    || priv->pbt->bt_dev.test_mode || priv->pbt->bt_dev.hscfgcmd) {
+		bt_prepare_command(priv->pbt);
+		wake_up_interruptible(&priv->pbt->MainThread.waitQ);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handle the generic file open
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS or other error no.
+ */
+static int
+proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata;
+	int i;
+	char *p;
+	u32 val = 0;
+	ENTER();
+	priv->pbt->adapter->skb_pending =
+		skb_queue_len(&priv->pbt->adapter->tx_queue);
+	file->private_data = kzalloc(sizeof(struct proc_data), GFP_KERNEL);
+	if (file->private_data == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for proc_data\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	pdata = (struct proc_data *)file->private_data;
+	pdata->pbt = priv->pbt;
+	pdata->rdbuf = kmalloc(priv->bufsize, GFP_KERNEL);
+	if (pdata->rdbuf == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for rdbuf\n");
+		kfree(file->private_data);
+		LEAVE();
+		return -ENOMEM;
+	}
+	if (priv->fileflag == DEFAULT_FILE_PERM) {
+		pdata->wrbuf = kzalloc(priv->bufsize, GFP_KERNEL);
+		if (pdata->wrbuf == NULL) {
+			PRINTM(ERROR, "BT: Can not alloc mem for wrbuf\n");
+			kfree(pdata->rdbuf);
+			kfree(file->private_data);
+			return -ENOMEM;
+		}
+		pdata->maxwrlen = priv->bufsize;
+		pdata->on_close = proc_on_close;
+	}
+	p = pdata->rdbuf;
+	for (i = 0; i < priv->num_items; i++) {
+		if (priv->pdata[i].size == 1)
+			val = *((u8 *)priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 2)
+			val = *((u16 *) priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 4)
+			val = *((u32 *)priv->pdata[i].addr);
+		if (priv->pdata[i].flag & SHOW_INT)
+			p += sprintf(p, "%s=%d\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_HEX)
+			p += sprintf(p, "%s=0x%x\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_STRING) {
+			if (!strncmp
+			    (priv->pdata[i].name, "sdcmd52rw",
+			     strlen("sdcmd52rw"))) {
+				sd_read_cmd52_val(priv->pbt);
+				form_cmd52_string(priv->pbt);
+			}
+			p += sprintf(p, "%s=%s\n", priv->pdata[i].name,
+				     (char *)priv->pdata[i].addr);
+		}
+	}
+	pdata->rdlen = strlen(pdata->rdbuf);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/** Proc read ops */
+static const struct file_operations proc_read_ops = {
+	.read = proc_read,
+	.open = proc_open,
+	.release = proc_close
+};
+
+/** Proc Read-Write ops */
+static const struct file_operations proc_rw_ops = {
+	.read = proc_read,
+	.write = proc_write,
+	.open = proc_open,
+	.release = proc_close
+};
+
+static struct proc_private_data proc_files[] = {
+	{"status", S_IRUGO, 1024,
+	 sizeof(status_items) / sizeof(status_items[0]),
+	 &status_items[0], NULL, &proc_read_ops}
+	,
+	{"config", DEFAULT_FILE_PERM, 512,
+	 sizeof(config_items) / sizeof(config_items[0]), &config_items[0], NULL,
+	 &proc_rw_ops}
+	,
+	{"debug", DEFAULT_FILE_PERM, 512,
+	 sizeof(debug_items) / sizeof(debug_items[0]), &debug_items[0], NULL,
+	 &proc_rw_ops}
+	,
+};
+
+/**
+ *  @brief This function initializes proc entry
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param m_dev    A pointer to struct m_dev
+ *  @param seq      Sequence number
+ *
+ *  @return	BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct proc_dir_entry *entry;
+	int i, j;
+
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	if (proc_mbt) {
+		priv->dev_proc[seq].proc_entry =
+			proc_mkdir(m_dev->name, proc_mbt);
+		if (!priv->dev_proc[seq].proc_entry) {
+			PRINTM(ERROR, "BT: Could not mkdir %s!\n", m_dev->name);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+
+		priv->dev_proc[seq].pfiles =
+			kmalloc(sizeof(proc_files), GFP_ATOMIC);
+		if (!priv->dev_proc[seq].pfiles) {
+			PRINTM(ERROR,
+			       "BT: Could not alloc memory for pfile!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy((u8 *)priv->dev_proc[seq].pfiles, (u8 *)proc_files,
+		       sizeof(proc_files));
+		priv->dev_proc[seq].num_proc_files = ARRAY_SIZE(proc_files);
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++)
+			priv->dev_proc[seq].pfiles[j].pdata = NULL;
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+			priv->dev_proc[seq].pfiles[j].pdata =
+				kmalloc(priv->dev_proc[seq].pfiles[j].
+					num_items * sizeof(struct item_data),
+					GFP_ATOMIC);
+			if (!priv->dev_proc[seq].pfiles[j].pdata) {
+				PRINTM(ERROR,
+				       "BT: Could not alloc memory for pdata!\n");
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			memcpy((u8 *)priv->dev_proc[seq].pfiles[j].pdata,
+			       (u8 *)proc_files[j].pdata,
+			       priv->dev_proc[seq].pfiles[j].num_items *
+			       sizeof(struct item_data));
+			for (i = 0; i < priv->dev_proc[seq].pfiles[j].num_items;
+			     i++) {
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_DEV)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)&priv->bt_dev;
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_ADAPTER)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)priv->adapter;
+			}
+			priv->dev_proc[seq].pfiles[j].pbt = priv;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			entry = proc_create_data(proc_files[j].name,
+						 S_IFREG | proc_files[j].
+						 fileflag,
+						 priv->dev_proc[seq].proc_entry,
+						 proc_files[j].fops,
+						 &priv->dev_proc[seq].
+						 pfiles[j]);
+			if (entry == NULL)
+#else
+			entry = create_proc_entry(proc_files[j].name,
+						  S_IFREG | proc_files[j].
+						  fileflag,
+						  priv->dev_proc[seq].
+						  proc_entry);
+			if (entry) {
+				entry->data = &priv->dev_proc[seq].pfiles[j];
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
+				entry->owner = THIS_MODULE;
+#endif
+				entry->proc_fops = proc_files[j].fops;
+			} else
+#endif
+				PRINTM(MSG, "BT: Fail to create proc %s\n",
+				       proc_files[j].name);
+		}
+	}
+done:
+	if (ret == BT_STATUS_FAILURE) {
+		if (priv->dev_proc[seq].proc_entry) {
+			remove_proc_entry(m_dev->name, proc_mbt);
+			priv->dev_proc[seq].proc_entry = NULL;
+		}
+		if (priv->dev_proc[seq].pfiles) {
+			for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+				if (priv->dev_proc[seq].pfiles[j].pdata) {
+					kfree(priv->dev_proc[seq].pfiles[j].
+					      pdata);
+					priv->dev_proc[seq].pfiles[j].pdata =
+						NULL;
+				}
+			}
+			kfree(priv->dev_proc[seq].pfiles);
+			priv->dev_proc[seq].pfiles = NULL;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return	N/A
+ */
+void
+bt_proc_remove(bt_private *priv)
+{
+	int j, i;
+
+	ENTER();
+	PRINTM(INFO, "BT: Remove Proc Interface\n");
+	if (proc_mbt) {
+		for (i = 0; i < MAX_RADIO_FUNC; i++) {
+			if (!priv->dev_proc[i].proc_entry)
+				continue;
+			for (j = 0; j < ARRAY_SIZE(proc_files); j++) {
+				remove_proc_entry(proc_files[j].name,
+						  priv->dev_proc[i].proc_entry);
+			}
+			remove_proc_entry(priv->bt_dev.m_dev[i].name, proc_mbt);
+			priv->dev_proc[i].proc_entry = NULL;
+
+			if (priv->dev_proc[i].pfiles) {
+				for (j = 0;
+				     j < priv->dev_proc[i].num_proc_files;
+				     j++) {
+					if (priv->dev_proc[i].pfiles[j].pdata) {
+						kfree(priv->dev_proc[i].
+						      pfiles[j].pdata);
+						priv->dev_proc[i].pfiles[j].
+							pdata = NULL;
+					}
+				}
+				kfree(priv->dev_proc[i].pfiles);
+				priv->dev_proc[i].pfiles = NULL;
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function creates proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_root_proc_init(void)
+{
+	PRINTM(INFO, "BT: Create Proc Interface\n");
+	proc_mbt = proc_mkdir("mbt", PROC_DIR);
+	if (!proc_mbt) {
+		PRINTM(ERROR, "BT: Cannot create proc interface\n");
+		return BT_STATUS_FAILURE;
+	}
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS
+ */
+int
+bt_root_proc_remove(void)
+{
+	remove_proc_entry("mbt", PROC_DIR);
+	proc_mbt = NULL;
+	return BT_STATUS_SUCCESS;
+}
diff --git a/bt_sd8987/bt/bt_sdio.h b/bt_sd8987/bt/bt_sdio.h
new file mode 100644
index 0000000..3fced8f
--- /dev/null
+++ b/bt_sd8987/bt/bt_sdio.h
@@ -0,0 +1,435 @@
+/** @file bt_sdio.h
+ *  @brief This file contains SDIO (interface) module
+ *  related macros, enum, and structure.
+ *
+ *  Copyright (C) 2007-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_SDIO_H_
+#define _BT_SDIO_H_
+
+#include <linux/irqreturn.h>
+
+/** SD8787 card type */
+#define CARD_TYPE_SD8787   0x01
+/** SD8777 card type */
+#define CARD_TYPE_SD8777   0x02
+/** SD8887 card type */
+#define CARD_TYPE_SD8887   0x03
+/** SD8897 card type */
+#define CARD_TYPE_SD8897   0x04
+/** SD8797 card type */
+#define CARD_TYPE_SD8797   0x05
+/** SD8977 card type */
+#define CARD_TYPE_SD8977   0x06
+/** SD8997 card type */
+#define CARD_TYPE_SD8997   0x07
+/** SD8987 card type */
+#define CARD_TYPE_SD8987   0x08
+/** SD8978 card type */
+#define CARD_TYPE_SD8978   0x09
+
+/** IRQ return type */
+typedef irqreturn_t IRQ_RET_TYPE;
+/** IRQ return */
+#define IRQ_RET		(return IRQ_HANDLED)
+/** ISR notifier function */
+typedef IRQ_RET_TYPE (*isr_notifier_fn_t) (s32 irq, void *dev_id,
+					   struct pt_regs * reg);
+
+/** SDIO header length */
+#define SDIO_HEADER_LEN			4
+
+/** 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
+/* SD block size can not bigger than 64 due to buf size limit in firmware */
+/** define SD block size for data Tx/Rx */
+#define SD_BLOCK_SIZE			64
+/** define SD block size for firmware download */
+#define SD_BLOCK_SIZE_FW_DL		256
+
+/** Number of blocks for firmware transfer */
+#define FIRMWARE_TRANSFER_NBLOCK	2
+
+/** Firmware ready */
+#define FIRMWARE_READY			0xfedc
+
+/* Bus Interface Control Reg 0x07 */
+/** SD BUS width 1 */
+#define SD_BUS_WIDTH_1			0x00
+/** SD BUS width 4 */
+#define SD_BUS_WIDTH_4			0x02
+/** SD BUS width mask */
+#define SD_BUS_WIDTH_MASK		0x03
+/** Asynchronous interrupt mode */
+#define ASYNC_INT_MODE			0x20
+
+/** magic register */
+#define CARD_MAGIC_REG          0xF0
+/** magic value */
+#define MAGIC_VAL               0x24
+
+/* Host Control Registers */
+/** Host Control Registers : Configuration */
+#define CONFIGURATION_REG		0x00
+/** Host Control Registers : Host without Command 53 finish host*/
+#define HOST_TO_CARD_EVENT		(0x1U << 3)
+/** Host Control Registers : Host terminates Command 53 */
+#define HOST_TERM_CMD53			(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 : Host interrupt RSR */
+#define HOST_INT_RSR_REG		0x01
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR		(0x1U)
+
+/** Host Control Registers : Host interrupt mask */
+#define HOST_INT_MASK_REG		0x02
+
+/** 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)
+/** Enable Host interrupt mask */
+#define HIM_ENABLE			(UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
+/** Disable Host interrupt mask */
+#define	HIM_DISABLE			0xff
+
+#define HOST_INTSTATUS_REG		0x03
+/** 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)
+
+/** 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
+
+/** Host Control Registers : Host interrupt status */
+#define HOST_INT_STATUS_REG		0x28
+/** Host Control Registers : Upload CRC error */
+#define UP_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 */
+/** Card Control Registers : Read SQ base address A0 register */
+#define SQ_READ_BASE_ADDRESS_A0_REG		0x40
+/** Card Control Registers : Read SQ base address A1 register */
+#define SQ_READ_BASE_ADDRESS_A1_REG		0x41
+/** Card Control Registers : Read SQ base address A2 register */
+#define SQ_READ_BASE_ADDRESS_A2_REG		0x42
+/** Card Control Registers : Read SQ base address A3 register */
+#define SQ_READ_BASE_ADDRESS_A3_REG		0x43
+/** Card Control Registers : Read SQ base address B0 register */
+#define SQ_READ_BASE_ADDRESS_B0_REG		0x44
+/** Card Control Registers : Read SQ base address B1 register */
+#define SQ_READ_BASE_ADDRESS_B1_REG		0x45
+/** Card Control Registers : Read SQ base address B2 register */
+#define SQ_READ_BASE_ADDRESS_B2_REG		0x46
+/** Card Control Registers : Read SQ base address B3 register */
+#define SQ_READ_BASE_ADDRESS_B3_REG		0x47
+
+/** Card Control Registers : Card status register */
+#define CARD_STATUS_REG					0x30
+/** 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 interrupt mask register */
+#define HOST_INTERRUPT_MASK_REG			0x34
+/** 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 : Card interrupt status register */
+#define CARD_INTERRUPT_STATUS_REG		0x38
+/** 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 : Card interrupt RSR register */
+#define CARD_INTERRUPT_RSR_REG			0x3c
+/** 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 : Debug 0 register */
+#define DEBUG_0_REG						0x70
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0						(0x1U)
+/** Card Control Registers : Debug 1 register */
+#define DEBUG_1_REG						0x71
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1						(0x1U)
+/** Card Control Registers : Debug 2 register */
+#define DEBUG_2_REG						0x72
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2						(0x1U)
+/** Card Control Registers : Debug 3 register */
+#define DEBUG_3_REG						0x73
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3						(0x1U)
+
+/** Host Control Registers : I/O port 0 */
+#define IO_PORT_0_REG			0x78
+/** Host Control Registers : I/O port 1 */
+#define IO_PORT_1_REG			0x79
+/** Host Control Registers : I/O port 2 */
+#define IO_PORT_2_REG			0x7A
+
+/** Firmware status 0 register */
+#define CARD_FW_STATUS0_REG		0x60
+/** Firmware status 1 register */
+#define CARD_FW_STATUS1_REG		0x61
+/** Rx length register */
+#define CARD_RX_LEN_REG			0x62
+/** Rx unit register */
+#define CARD_RX_UNIT_REG		0x63
+/** Card Control Registers : Miscellaneous Configuration Register */
+#define CARD_MISC_CFG_REG		0x6C
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT		(0x1U << 4)
+
+/** Card Control Registers : Card OCR 0 register */
+#define CARD_OCR_0_REG			0x68
+/** Card Control Registers : Card OCR 1 register */
+#define CARD_OCR_1_REG			0x69
+/** Card Control Registers : Card OCR 3 register */
+#define CARD_OCR_3_REG			0x6A
+/** Card Control Registers : Card config register */
+#define CARD_CONFIG_REG			0x6B
+/** Card Control Registers : Card revision register */
+#define CARD_REVISION_REG		0x5c
+/** Card Control Registers : Command 53 finish G BUS */
+#define CMD53_FINISH_GBUS		(0x1U << 1)
+/** Card Control Registers : SD negative edge */
+#define SD_NEG_EDGE				(0x1U << 0)
+
+/* Special registers in function 0 of the SDxx card */
+/** Special register in function 0 of the SDxxx card : Scratch 0 */
+#define	SCRATCH_0_REG			0x80fe
+/** Special register in function 0 of the SDxxx card : Scratch 1 */
+#define	SCRATCH_1_REG			0x80ff
+/** Host F1 read base 0 */
+#define HOST_F1_RD_BASE_0		0x0040
+/** Host F1 read base 1 */
+#define HOST_F1_RD_BASE_1		0x0041
+/** Host F1 card ready */
+#define HOST_F1_CARD_RDY		0x0020
+
+/** Chip Id Register 0 */
+#define CARD_CHIP_ID_0_REG		0x801c
+/** Chip Id Register 1 */
+#define CARD_CHIP_ID_1_REG		0x801d
+
+struct sdio_mmc_card {
+	/** sdio_func structure pointer */
+	struct sdio_func *func;
+	/** bt_private structure pointer */
+	bt_private *priv;
+};
+
+struct sdio_card_reg {
+	u8 cfg;
+	u8 host_int_mask;	// HOST_INT_MASK_REG
+	u8 host_intstatus;	// HOST_INTSTATUS_REG
+	u8 host_int_rsr_reg;	// HOST_INT_RSR_REG
+	u8 card_misc_cfg_reg;	// CARD_MISC_CFG_REG
+	u8 card_status;		// CARD_STATUS_REG
+	u8 sq_read_base_addr_a0;	// SQ_READ_BASE_ADDRESS_A0_REG
+	u8 sq_read_base_addr_a1;	// SQ_READ_BASE_ADDRESS_A1_REG
+	u8 card_revision;	// CARD_REVISION_REG
+	u8 card_fw_status0;	// CARD_FW_STATUS0_REG
+	u8 card_fw_status1;	// CARD_FW_STATUS1_REG
+	u8 card_rx_len;		// CARD_RX_LEN_REG
+	u8 card_rx_unit;	// CARD_RX_UNIT_REG
+	u8 io_port_0;		// IO_PORT_0_REG
+	u8 io_port_1;		// IO_PORT_1_REG
+	u8 io_port_2;		// IO_PORT_2_REG
+};
+
+struct sdio_device {
+	const struct sdio_card_reg *reg;
+};
+
+static const struct sdio_card_reg bt_reg_87xx = {
+	.cfg = 0x00,
+	.host_int_mask = 0x02,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x03,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x01,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0x6c,	// CARD_MISC_CFG_REG
+	.card_status = 0x30,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0x40,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0x41,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0x5C,	// CARD_REVISION_REG
+	.card_fw_status0 = 0x60,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0x61,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0x62,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0x63,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0x78,	// IO_PORT_0_REG
+	.io_port_1 = 0x79,	// IO_PORT_1_REG
+	.io_port_2 = 0x7a,	// IO_PORT_2_REG
+};
+
+static const struct sdio_card_reg bt_reg_8887 = {
+	.cfg = 0x00,
+	.host_int_mask = 0x08,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x0C,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x04,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0xD8,	// CARD_MISC_CFG_REG
+	.card_status = 0x5C,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0x6C,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0x6D,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0xC8,	// CARD_REVISION_REG
+	.card_fw_status0 = 0x88,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0x89,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0x8A,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0x8B,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0xE4,	// IO_PORT_0_REG
+	.io_port_1 = 0xE5,	// IO_PORT_1_REG
+	.io_port_2 = 0xE6,	// IO_PORT_2_REG
+};
+
+static const struct sdio_card_reg bt_reg_8897 = {
+	.cfg = 0x00,
+	.host_int_mask = 0x02,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x03,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x01,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0xCC,	// CARD_MISC_CFG_REG
+	.card_status = 0x50,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0x60,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0x61,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0xBC,	// CARD_REVISION_REG
+	.card_fw_status0 = 0xC0,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0xC1,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0xC2,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0xC3,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0xD8,	// IO_PORT_0_REG
+	.io_port_1 = 0xD9,	// IO_PORT_1_REG
+	.io_port_2 = 0xDA,	// IO_PORT_2_REG
+};
+
+static const struct sdio_card_reg bt_reg_8977_8978_8997 = {
+	.cfg = 0x00,
+	.host_int_mask = 0x08,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x0C,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x04,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0xD8,	// CARD_MISC_CFG_REG
+	.card_status = 0x5C,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0xF8,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0xF9,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0xC8,	// CARD_REVISION_REG
+	.card_fw_status0 = 0xE8,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0xE9,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0xEA,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0xEB,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0xE4,	// IO_PORT_0_REG
+	.io_port_1 = 0xE5,	// IO_PORT_1_REG
+	.io_port_2 = 0xE6,	// IO_PORT_2_REG
+};
+
+static const struct sdio_device bt_sdio_sd8787 = {
+	.reg = &bt_reg_87xx,
+};
+
+static const struct sdio_device bt_sdio_sd8777 = {
+	.reg = &bt_reg_87xx,
+};
+
+static const struct sdio_device bt_sdio_sd8887 = {
+	.reg = &bt_reg_8887,
+};
+
+static const struct sdio_device bt_sdio_sd8897 = {
+	.reg = &bt_reg_8897,
+};
+
+static const struct sdio_device bt_sdio_sd8797 = {
+	.reg = &bt_reg_87xx,
+};
+
+static const struct sdio_device bt_sdio_sd8977 = {
+	.reg = &bt_reg_8977_8978_8997,
+};
+
+static const struct sdio_device bt_sdio_sd8978 = {
+	.reg = &bt_reg_8977_8978_8997,
+};
+
+static const struct sdio_device bt_sdio_sd8997 = {
+	.reg = &bt_reg_8977_8978_8997,
+};
+
+static const struct sdio_device bt_sdio_sd8987 = {
+	.reg = &bt_reg_8977_8978_8997,
+};
+
+/** DMA alignment value */
+#define DMA_ALIGNMENT	64
+/** 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))
+
+/** This function read cmd52 register */
+int sd_write_reg(bt_private *priv, int reg, u8 val);
+/** This function write cmd52 value to register */
+int sd_read_reg(bt_private *priv, int reg, u8 *data);
+/** This function reads the Cmd52 value in dev structure */
+int sd_read_cmd52_val(bt_private *priv);
+/** This function updates card reg based on the Cmd52 value in dev structure */
+int sd_write_cmd52_val(bt_private *priv, int func, int reg, int val);
+
+void sdio_update_card_type(bt_private *priv, void *card);
+int sdio_get_sdio_device(bt_private *priv);
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** This function tells lower driver that BT is suspended */
+void bt_is_suspended(bt_private *priv);
+#endif
+#endif
+#endif
+#endif /* _BT_SDIO_H_ */
diff --git a/bt_sd8987/bt/bt_sdiommc.c b/bt_sd8987/bt/bt_sdiommc.c
new file mode 100644
index 0000000..0a6f951
--- /dev/null
+++ b/bt_sd8987/bt/bt_sdiommc.c
@@ -0,0 +1,2337 @@
+/** @file bt_sdiommc.c
+ *  @brief This file contains SDIO IF (interface) module
+ *  related functions.
+ *
+ * Copyright (C) 2007-2019, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/mmc/sdio_func.h>
+#include        <linux/mmc/sdio.h>
+#include        <linux/mmc/card.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** define marvell vendor id */
+#define MARVELL_VENDOR_ID 0x02df
+
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD53_RETRY 	3
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD52_RETRY     3
+/** Firmware name */
+static char *fw_name;
+/** fw serial download flag */
+extern int bt_fw_serial;
+int bt_intmode = INT_MODE_SDIO;
+/** request firmware nowait */
+int bt_req_fw_nowait;
+static int multi_fn = BIT(2);
+
+#define DEFAULT_FW_NAME ""
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB2   28
+/** FW header for CRC check disable */
+static u8 fw_crc_header_rb_2[FW_CRC_HEADER_RB2] = {
+	0x05, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+	0x9d, 0x32, 0xbb, 0x11, 0x01, 0x00, 0x00, 0x7f,
+	0x00, 0x00, 0x00, 0x00, 0x67, 0xd6, 0xfc, 0x25
+};
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB   24
+/** FW header for CRC check disable */
+static u8 fw_crc_header_rb_1[FW_CRC_HEADER_RB] = {
+	0x01, 0x00, 0x00, 0x00, 0x04, 0xfd, 0x00, 0x04,
+	0x08, 0x00, 0x00, 0x00, 0x26, 0x52, 0x2a, 0x7b,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/** Default firmware name */
+#define DEFAULT_FW_NAME_8777 "mrvl/sd8777_uapsta.bin"
+#define DEFAULT_FW_NAME_8787 "mrvl/sd8787_uapsta.bin"
+#define DEFAULT_FW_NAME_8797 "mrvl/sd8797_uapsta.bin"
+#define DEFAULT_FW_NAME_8887 "mrvl/sd8887_uapsta.bin"
+#define DEFAULT_FW_NAME_8897 "mrvl/sd8897_uapsta.bin"
+#define DEFAULT_FW_NAME_8977 "mrvl/sdsd8977_combo.bin"
+#define DEFAULT_FW_NAME_8978 "mrvl/sdsd8978_combo.bin"
+#define DEFAULT_FW_NAME_8997 "mrvl/sdsd8997_combo.bin"
+
+/** SD8787 chip revision ID */
+#define SD8787_W0      0x30
+#define SD8787_W1      0x31
+#define SD8787_A0_A1   0x40
+/** SD8797 chip revision ID */
+#define SD8797_A0       0x00
+#define SD8797_B0       0x10
+/** SD8897 chip revision ID */
+#define SD8897_A0       0x10
+#define SD8897_B0       0x20
+
+/** SD8887 chip revision ID */
+#define SD8887_A0       0x0
+#define SD8887_A2       0x2
+#define SD8887_A0_FW_NAME "mrvl/sd8887_uapsta.bin"
+#define SD8887_A2_FW_NAME "mrvl/sd8887_uapsta_a2.bin"
+#define SD8887_A2_BT_FW_NAME "mrvl/sd8887_bt_a2.bin"
+
+#define SD8897_A0_FW_NAME "mrvl/sd8897_uapsta_a0.bin"
+#define SD8897_B0_FW_NAME "mrvl/sd8897_uapsta.bin"
+
+#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin"
+#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin"
+#define SD8797_A0_FW_NAME "mrvl/sd8797_uapsta_a0.bin"
+#define SD8797_B0_FW_NAME "mrvl/sd8797_uapsta.bin"
+
+/** SD8977 chip revision ID */
+#define SD8977_V0       0x0
+#define SD8977_V1       0x8
+#define SD8977_V2       0x9
+#define SD8977_V0_FW_NAME "mrvl/sdsd8977_combo.bin"
+#define SD8977_V0_BT_FW_NAME "mrvl/sd8977_bt.bin"
+#define SD8977_V1_FW_NAME "mrvl/sdsd8977_combo_v1.bin"
+#define SD8977_V1_BT_FW_NAME "mrvl/sd8977_bt_v1.bin"
+#define SD8977_V2_FW_NAME "mrvl/sdsd8977_combo_v2.bin"
+#define SD8977_V2_BT_FW_NAME "mrvl/sd8977_bt_v2.bin"
+/** SD8978 FW NAME */
+#define SD8978_FW_NAME      "mrvl/sdsd8978_combo.bin"
+#define SD8978_BT_FW_NAME   "mrvl/sd8978_bt.bin"
+
+/** SD8997 chip revision ID */
+#define SD8997_Z        0x02
+#define SD8997_V2       0x10
+#define SD8997_Z_FW_NAME "mrvl/sdsd8997_combo.bin"
+#define SD8997_Z_BT_FW_NAME "mrvl/sd8997_bt.bin"
+#define SD8997_V2_FW_NAME "mrvl/sdsd8997_combo_v2.bin"
+#define SD8997_V2_BT_FW_NAME "mrvl/sd8997_bt_v2.bin"
+#define SD8997_V3_FW_NAME "mrvl/sdsd8997_combo_v3.bin"
+#define SD8997_V3_BT_FW_NAME "mrvl/sd8997_bt_v3.bin"
+
+/** SD8987 */
+#define SD8987_FW_NAME  "mrvl/sdsd8987_combo.bin"
+#define SD8987_BT_FW_NAME "mrvl/sd8987_bt.bin"
+
+/** Function number 2 */
+#define FN2			2
+/** Device ID for SD8787 FN2 */
+#define SD_DEVICE_ID_8787_BT_FN2    0x911A
+/** Device ID for SD8787 FN3 */
+#define SD_DEVICE_ID_8787_BT_FN3    0x911B
+/** Device ID for SD8777 FN2 */
+#define SD_DEVICE_ID_8777_BT_FN2    0x9132
+/** Device ID for SD8777 FN3 */
+#define SD_DEVICE_ID_8777_BT_FN3    0x9133
+/** Device ID for SD8887 FN2 */
+#define SD_DEVICE_ID_8887_BT_FN2    0x9136
+/** Device ID for SD8887 FN3 */
+#define SD_DEVICE_ID_8887_BT_FN3    0x9137
+/** Device ID for SD8897 FN2 */
+#define SD_DEVICE_ID_8897_BT_FN2    0x912E
+/** Device ID for SD8897 FN3 */
+#define SD_DEVICE_ID_8897_BT_FN3    0x912F
+/** Device ID for SD8797 FN2 */
+#define SD_DEVICE_ID_8797_BT_FN2    0x912A
+/** Device ID for SD8797 FN3 */
+#define SD_DEVICE_ID_8797_BT_FN3    0x912B
+/** Device ID for SD8977 FN2 */
+#define SD_DEVICE_ID_8977_BT_FN2    0x9146
+/** Device ID for SD8978 FN2 */
+#define SD_DEVICE_ID_8978_BT_FN2    0x915a
+/** Device ID for SD8997 FN2 */
+#define SD_DEVICE_ID_8997_BT_FN2    0x9142
+/** Device ID for SD8987 FN2 */
+#define SD_DEVICE_ID_8987_BT_FN2    0x914a
+/** Device ID for SD8987 FN3 */
+#define SD_DEVICE_ID_8987_BT_FN3    0x914b
+
+/** Array of SDIO device ids when multi_fn=0x12 */
+static const struct sdio_device_id bt_ids[] = {
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8787_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8777_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8887_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8897_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8797_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8977_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8978_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8997_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8987_BT_FN2)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(sdio, bt_ids);
+
+#ifdef SDIO_OOB_IRQ
+extern int mrvl_sdio_claim_irq(struct sdio_func *func,
+			       sdio_irq_handler_t * handler);
+extern int mrvl_sdio_release_irq(struct sdio_func *func);
+extern int mrvl_sdio_suspend(struct sdio_func *func);
+extern int mrvl_sdio_resume(struct sdio_func *func);
+#endif
+
+/********************************************************
+		Global Variables
+********************************************************/
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+extern int mbt_pm_keep_power;
+#endif
+
+extern bt_private *m_priv[];
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief This function gets rx_unit value
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_get_rx_unit(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_unit_reg = priv->psdio_device->reg->card_rx_unit;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_unit_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		priv->bt_dev.rx_unit = reg;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads fwstatus registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_read_firmware_status(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 fws0;
+	u8 fws1;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = priv->psdio_device->reg->card_fw_status0;
+	u8 card_fw_status1_reg = priv->psdio_device->reg->card_fw_status1;
+
+	ENTER();
+
+	fws0 = sdio_readb(card->func, card_fw_status0_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	fws1 = sdio_readb(card->func, card_fw_status1_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	*dat = (((u16) fws1) << 8) | fws0;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function reads rx length
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sd_read_rx_len(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_len_reg = priv->psdio_device->reg->card_rx_len;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_len_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		*dat = (u16) reg << priv->bt_dev.rx_unit;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables the host interrupts mask
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_enable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = priv->psdio_device->reg->host_int_mask;
+
+	ENTER();
+
+	sdio_writeb(card->func, mask, host_int_mask_reg, &ret);
+	if (ret) {
+		PRINTM(WARN, "BT: Unable to enable the host interrupt!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function disables the host interrupts mask.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sbi_disable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_FAILURE;
+	u8 host_int_mask;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = priv->psdio_device->reg->host_int_mask;
+
+	ENTER();
+
+	/* Read back the host_int_mask register */
+	host_int_mask = sdio_readb(card->func, host_int_mask_reg, &ret);
+	if (ret)
+		goto done;
+
+	/* Update with the mask and write back to the register */
+	host_int_mask &= ~mask;
+	sdio_writeb(card->func, host_int_mask, host_int_mask_reg, &ret);
+	if (ret < 0) {
+		PRINTM(WARN, "BT: Unable to diable the host interrupt!\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function polls the card status register
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param bits     the bit mask
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_poll_card_status(bt_private *priv, u8 bits)
+{
+	int tries;
+	int rval;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 cs;
+	u8 card_status_reg = priv->psdio_device->reg->card_status;
+
+	ENTER();
+
+	for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
+		cs = sdio_readb(card->func, card_status_reg, &rval);
+		if (rval != 0)
+			break;
+		if (rval == 0 && (cs & bits) == bits) {
+			LEAVE();
+			return BT_STATUS_SUCCESS;
+		}
+		udelay(1);
+	}
+	PRINTM(ERROR,
+	       "BT: sdio_poll_card_status failed (%d), tries = %d, cs = 0x%x\n",
+	       rval, tries, cs);
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_cmd52_val(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 func, reg, val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	func = priv->bt_dev.cmd52_func;
+	reg = priv->bt_dev.cmd52_reg;
+	sdio_claim_host(card->func);
+	if (func)
+		val = sdio_readb(card->func, reg, &ret);
+	else
+		val = sdio_f0_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	if (ret) {
+		PRINTM(ERROR, "BT: Cannot read value from func %d reg %d\n",
+		       func, reg);
+	} else {
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param func     Stores func variable
+ *  @param reg      Stores reg variable
+ *  @param val      Stores val variable
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_cmd52_val(bt_private *priv, int func, int reg, int val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	if (val >= 0) {
+		/* Perform actual write only if val is provided */
+		sdio_claim_host(card->func);
+		if (func)
+			sdio_writeb(card->func, val, reg, &ret);
+		else
+			sdio_f0_writeb(card->func, val, reg, &ret);
+		sdio_release_host(card->func);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: Cannot write value (0x%x) to func %d reg %d\n",
+			       val, func, reg);
+			goto done;
+		}
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	/* Save current func and reg for future read */
+	priv->bt_dev.cmd52_func = func;
+	priv->bt_dev.cmd52_reg = reg;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to write
+ *  @param val      value
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_reg(bt_private *priv, int reg, u8 val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, val, reg, &ret);
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to read
+ *  @param data		Data
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_reg(bt_private *priv, int reg, u8 *data)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	val = sdio_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	*data = val;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function probes the card
+ *
+ *  @param func    A pointer to sdio_func structure.
+ *  @param id      A pointer to structure sdio_device_id
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_probe_card(struct sdio_func *func, const struct sdio_device_id *id)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *card = NULL;
+
+	ENTER();
+
+	PRINTM(INFO, "BT: vendor=0x%x,device=0x%x,class=%d,fn=%d\n", id->vendor,
+	       id->device, id->class, func->num);
+	card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
+	if (!card) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	card->func = func;
+#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_disable_func(func);
+		sdio_release_host(func);
+		PRINTM(FATAL, "BT: sdio_enable_func() failed: ret=%d\n", ret);
+		kfree(card);
+		LEAVE();
+		return -EIO;
+	}
+	sdio_release_host(func);
+	priv = bt_add_card(card);
+	if (!priv) {
+		sdio_claim_host(func);
+		sdio_disable_func(func);
+		sdio_release_host(func);
+		ret = BT_STATUS_FAILURE;
+		kfree(card);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param pollnum  Number of times to poll fw status
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_verify_fw_download(bt_private *priv, int pollnum)
+{
+	int ret = BT_STATUS_FAILURE;
+	u16 firmwarestat = 0;
+	int tries;
+
+	ENTER();
+
+	/* Wait for firmware initialization event */
+	for (tries = 0; tries < pollnum; tries++) {
+		if (sd_read_firmware_status(priv, &firmwarestat) < 0)
+			continue;
+		if (firmwarestat == FIRMWARE_READY) {
+			PRINTM(MSG, "BT FW is active(%d)\n", tries);
+			ret = BT_STATUS_SUCCESS;
+			break;
+		}
+		mdelay(100);
+	}
+	if ((pollnum > 1) && (ret != BT_STATUS_SUCCESS)) {
+		PRINTM(ERROR,
+		       "Fail to poll firmware status: firmwarestat=0x%x\n",
+		       firmwarestat);
+		bt_dump_sdio_regs(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Transfers firmware to card
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @param fw        A Pointer to fw image
+ *  @param fw_len    fw image len
+ *  @return          BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_init_fw_dpc(bt_private *priv, u8 *fw, int fw_len)
+{
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 *firmware = fw;
+	int firmwarelen = fw_len;
+	u8 base0;
+	u8 base1;
+	int ret = BT_STATUS_SUCCESS;
+	int offset;
+	void *tmpfwbuf = NULL;
+	int tmpfwbufsz;
+	u8 *fwbuf;
+	u16 len;
+	int txlen = 0;
+	int tx_blocks = 0;
+	int i = 0;
+	int tries = 0;
+#ifdef FW_DOWNLOAD_SPEED
+	u32 tv1, tv2;
+#endif
+	u8 sq_read_base_address_a0_reg =
+		priv->psdio_device->reg->sq_read_base_addr_a0;
+	u8 sq_read_base_address_a1_reg =
+		priv->psdio_device->reg->sq_read_base_addr_a1;
+	u8 crc_buffer = 0;
+	u8 *header_crc_fw = NULL;
+	u8 header_crc_fw_len = 0;
+
+	if (priv->card_type == CARD_TYPE_SD8787) {
+		header_crc_fw = fw_crc_header_rb_1;
+		header_crc_fw_len = FW_CRC_HEADER_RB;
+	} else if (priv->card_type == CARD_TYPE_SD8777) {
+		header_crc_fw = fw_crc_header_rb_2;
+		header_crc_fw_len = FW_CRC_HEADER_RB2;
+	}
+
+	ENTER();
+
+	PRINTM(INFO, "BT: Downloading FW image (%d bytes)\n", firmwarelen);
+
+#ifdef FW_DOWNLOAD_SPEED
+	tv1 = get_utimeofday();
+#endif
+
+	tmpfwbufsz = BT_UPLD_SIZE + DMA_ALIGNMENT;
+	tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
+	if (!tmpfwbuf) {
+		PRINTM(ERROR,
+		       "BT: Unable to allocate buffer for firmware. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	/* Ensure aligned firmware buffer */
+	fwbuf = (u8 *)ALIGN_ADDR(tmpfwbuf, DMA_ALIGNMENT);
+
+	if (!(priv->fw_crc_check)
+	    && ((priv->card_type == CARD_TYPE_SD8787) ||
+		(priv->card_type == CARD_TYPE_SD8777))
+		) {
+		/* CRC check not required, use custom header first */
+		firmware = header_crc_fw;
+		firmwarelen = header_crc_fw_len;
+		crc_buffer = 1;
+	}
+
+	/* Perform firmware data transfer */
+	offset = 0;
+	do {
+		/* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits
+		 */
+		ret = sd_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: FW download with helper poll status timeout @ %d\n",
+			       offset);
+			goto done;
+		}
+		if (!crc_buffer)
+			/* More data? */
+			if (offset >= firmwarelen)
+				break;
+
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			base0 = sdio_readb(card->func,
+					   sq_read_base_address_a0_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE0 register read failed:"
+				       " base0=0x%04X(%d). Terminating download\n",
+				       base0, base0);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			base1 = sdio_readb(card->func,
+					   sq_read_base_address_a1_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE1 register read failed:"
+				       " base1=0x%04X(%d). Terminating download\n",
+				       base1, base1);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			len = (((u16) base1) << 8) | base0;
+
+			if (len != 0)
+				break;
+			udelay(10);
+		}
+
+		if (len == 0)
+			break;
+		else if (len > BT_UPLD_SIZE) {
+			PRINTM(FATAL,
+			       "BT: FW download failure @ %d, invalid length %d\n",
+			       offset, len);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	/** ignore CRC check before download the first packet */
+		if (offset == 0 && (len & BIT(0)))
+			len &= ~BIT(0);
+		txlen = len;
+
+		if (len & BIT(0)) {
+			i++;
+			if (i >= MAX_CMD53_RETRY) {
+				PRINTM(FATAL,
+				       "BT: FW download failure @ %d, over max retry count\n",
+				       offset);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(ERROR,
+			       "BT: FW CRC error indicated by the helper:"
+			       " len = 0x%04X, txlen = %d\n", len, txlen);
+			len &= ~BIT(0);
+
+			PRINTM(ERROR, "BT: retry: %d, offset %d\n", i, offset);
+			/* Setting this to 0 to resend from same offset */
+			txlen = 0;
+		} else {
+			i = 0;
+
+			/* Set blocksize to transfer - checking for last block */
+			if (firmwarelen - offset < txlen)
+				txlen = firmwarelen - offset;
+
+			PRINTM(INFO, ".");
+
+			tx_blocks =
+				(txlen + SD_BLOCK_SIZE_FW_DL -
+				 1) / SD_BLOCK_SIZE_FW_DL;
+
+			/* Copy payload to buffer */
+			memcpy(fwbuf, &firmware[offset], txlen);
+		}
+
+		/* Send data */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, fwbuf,
+				   tx_blocks * SD_BLOCK_SIZE_FW_DL);
+
+		if (ret < 0) {
+			PRINTM(ERROR,
+			       "BT: FW download, write iomem (%d) failed @ %d\n",
+			       i, offset);
+			sdio_writeb(card->func, 0x04, CONFIGURATION_REG, &ret);
+			if (ret)
+				PRINTM(ERROR, "write ioreg failed (CFG)\n");
+		}
+
+		offset += txlen;
+		if (crc_buffer
+		    && ((priv->card_type == CARD_TYPE_SD8787) ||
+			(priv->card_type == CARD_TYPE_SD8777))
+			) {
+			if (offset >= header_crc_fw_len) {
+				/* Custom header download complete, restore
+				   original FW */
+				offset = 0;
+				firmware = fw;
+				firmwarelen = fw_len;
+				crc_buffer = 0;
+			}
+		}
+	} while (TRUE);
+
+	PRINTM(MSG, "BT: FW download over, size %d bytes\n", offset);
+
+	ret = BT_STATUS_SUCCESS;
+done:
+#ifdef FW_DOWNLOAD_SPEED
+	tv2 = get_utimeofday();
+	PRINTM(INFO, "FW: %d.%03d.%03d ", tv1 / 1000000,
+	       (tv1 % 1000000) / 1000, tv1 % 1000);
+	PRINTM(INFO, " -> %d.%03d.%03d ", tv2 / 1000000,
+	       (tv2 % 1000000) / 1000, tv2 % 1000);
+	tv2 -= tv1;
+	PRINTM(INFO, " == %d.%03d.%03d\n", tv2 / 1000000,
+	       (tv2 % 1000000) / 1000, tv2 % 1000);
+#endif
+	kfree(tmpfwbuf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *
+ * @param fw_firmware  A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_request_fw_dpc(const struct firmware *fw_firmware, void *context)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = (bt_private *)context;
+	struct sdio_mmc_card *card = NULL;
+	struct m_dev *m_dev_bt = NULL;
+	struct timeval tstamp;
+	int index;
+
+	ENTER();
+
+	m_dev_bt = &priv->bt_dev.m_dev[BT_SEQ];
+
+	if ((priv == NULL) || (priv->adapter == NULL) ||
+	    (priv->bt_dev.card == NULL) || (m_dev_bt == NULL)
+		) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	if (!fw_firmware) {
+		do_gettimeofday(&tstamp);
+		if (tstamp.tv_sec >
+		    (priv->req_fw_time.tv_sec + REQUEST_FW_TIMEOUT)) {
+			PRINTM(ERROR,
+			       "BT: No firmware image found. Skipping download\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		PRINTM(ERROR,
+		       "BT: No firmware image found! Retrying download\n");
+		/* Wait a second here before calling the callback again */
+		os_sched_timeout(1000);
+		sd_download_firmware_w_helper(priv);
+		LEAVE();
+		return ret;
+	}
+
+	priv->firmware = fw_firmware;
+
+	if (BT_STATUS_FAILURE ==
+	    sd_init_fw_dpc(priv, (u8 *)priv->firmware->data,
+			   priv->firmware->size)) {
+		PRINTM(ERROR,
+		       "BT: sd_init_fw_dpc failed (download fw with nowait: %d). Terminating download\n",
+		       bt_req_fw_nowait);
+		sdio_release_host(card->func);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* check if the fimware is downloaded successfully or not */
+	if (sd_verify_fw_download(priv, MAX_FIRMWARE_POLL_TRIES)) {
+		PRINTM(ERROR, "BT: FW failed to be active in time!\n");
+		ret = BT_STATUS_FAILURE;
+		sdio_release_host(card->func);
+		goto done;
+	}
+	sdio_release_host(card->func);
+	sbi_enable_host_int(priv);
+	if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+		PRINTM(ERROR,
+		       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	LEAVE();
+	return ret;
+
+done:
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	/* For synchronous download cleanup will be done in add_card */
+	if (!bt_req_fw_nowait)
+		return ret;
+	PRINTM(INFO, "unregister device\n");
+	sbi_unregister_dev(priv);
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+	bt_proc_remove(priv);
+	clean_up_m_devs(priv);
+	bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware     A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             None
+ **/
+static void
+sd_request_fw_callback(const struct firmware *firmware, void *context)
+{
+	ENTER();
+	sd_request_fw_dpc(firmware, context);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function downloads firmware image to the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sd_download_firmware_w_helper(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	int err;
+	char *cur_fw_name = NULL;
+
+	ENTER();
+
+	cur_fw_name = fw_name;
+
+	if (fw_name == NULL) {
+		if (priv->card_type == CARD_TYPE_SD8787)
+			cur_fw_name = DEFAULT_FW_NAME_8787;
+		else if (priv->card_type == CARD_TYPE_SD8777)
+			cur_fw_name = DEFAULT_FW_NAME_8777;
+		else if (priv->card_type == CARD_TYPE_SD8887) {
+			/* Check revision ID */
+			switch (priv->adapter->chip_rev) {
+			case SD8887_A0:
+				cur_fw_name = SD8887_A0_FW_NAME;
+				break;
+			case SD8887_A2:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8887_A2_FW_NAME;
+				else
+					cur_fw_name = SD8887_A2_BT_FW_NAME;
+				break;
+			default:
+				cur_fw_name = DEFAULT_FW_NAME_8887;
+				break;
+			}
+		} else if (priv->card_type == CARD_TYPE_SD8897)
+			cur_fw_name = DEFAULT_FW_NAME_8897;
+		else if (priv->card_type == CARD_TYPE_SD8797)
+			cur_fw_name = DEFAULT_FW_NAME_8797;
+		else if (priv->card_type == CARD_TYPE_SD8977) {
+			switch (priv->adapter->chip_rev) {
+			case SD8977_V0:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8977_V0_FW_NAME;
+				else
+					cur_fw_name = SD8977_V0_BT_FW_NAME;
+				break;
+			case SD8977_V1:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8977_V1_FW_NAME;
+				else
+					cur_fw_name = SD8977_V1_BT_FW_NAME;
+				break;
+			case SD8977_V2:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8977_V2_FW_NAME;
+				else
+					cur_fw_name = SD8977_V2_BT_FW_NAME;
+				break;
+			default:
+				cur_fw_name = DEFAULT_FW_NAME_8977;
+				break;
+			}
+		} else if (priv->card_type == CARD_TYPE_SD8978) {
+			if (bt_fw_serial == 1
+			    && !priv->fw_reload && !bt_fw_reload)
+				cur_fw_name = SD8978_FW_NAME;
+			else
+				cur_fw_name = SD8978_BT_FW_NAME;
+		} else if (priv->card_type == CARD_TYPE_SD8997)
+			switch (priv->adapter->chip_rev) {
+			case SD8997_Z:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8997_Z_FW_NAME;
+				else
+					cur_fw_name = SD8997_Z_BT_FW_NAME;
+				break;
+			case SD8997_V2:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload) {
+					if (priv->adapter->magic_val ==
+					    MAGIC_VAL)
+						cur_fw_name = SD8997_V3_FW_NAME;
+					else
+						cur_fw_name = SD8997_V2_FW_NAME;
+				} else {
+					if (priv->adapter->magic_val ==
+					    MAGIC_VAL)
+						cur_fw_name =
+							SD8997_V3_BT_FW_NAME;
+					else
+						cur_fw_name =
+							SD8997_V2_BT_FW_NAME;
+				}
+				break;
+			default:
+				cur_fw_name = DEFAULT_FW_NAME_8997;
+				break;
+		} else if (priv->card_type == CARD_TYPE_SD8987) {
+			if (bt_fw_serial == 1
+			    && !priv->fw_reload && !bt_fw_reload)
+				cur_fw_name = SD8987_FW_NAME;
+			else
+				cur_fw_name = SD8987_BT_FW_NAME;
+		}
+	}
+
+	PRINTM(MSG, "BT Request firmware: %s\n", cur_fw_name);
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      sd_request_fw_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#endif
+#endif
+		if (ret < 0)
+			PRINTM(FATAL,
+			       "BT: request_firmware_nowait() failed, error code = %#x\n",
+			       ret);
+	} else {
+		err = request_firmware(&priv->firmware, cur_fw_name,
+				       priv->hotplug_device);
+		if (err < 0) {
+			PRINTM(FATAL,
+			       "BT: request_firmware() failed, error code = %#x\n",
+			       err);
+			ret = BT_STATUS_FAILURE;
+		} else
+			ret = sd_request_fw_dpc(priv->firmware, priv);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads data from the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_card_to_host(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u16 buf_len = 0;
+	int buf_block_len;
+	int blksz;
+	struct sk_buff *skb = NULL;
+	u32 type;
+	u8 *payload = NULL;
+	struct hci_dev *hdev = NULL;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int i = 0;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type == BLUEZ_SPEC)
+		hdev = (struct hci_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer;
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	do {
+		/* Read the length of data to be transferred */
+		ret = sd_read_rx_len(priv, &buf_len);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR, "BT: Read scratch reg failed (%d)\n", i);
+			if (i >= MAX_CMD52_RETRY) {
+				ret = BT_STATUS_FAILURE;
+				goto exit;
+			}
+			udelay(20);
+		}
+	}
+	while (ret == BT_STATUS_FAILURE);
+
+	/* Allocate buffer */
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (buf_len + blksz - 1) / blksz;
+	if (buf_len <= BT_HEADER_LEN ||
+	    (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+		PRINTM(ERROR, "BT: card_to_host, invalid packet length: %d\n",
+		       buf_len);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	skb = bt_skb_alloc(buf_block_len * blksz + DMA_ALIGNMENT, GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		goto exit;
+	}
+	if ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)) {
+		skb_put(skb,
+			DMA_ALIGNMENT -
+			((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+		skb_pull(skb,
+			 DMA_ALIGNMENT -
+			 ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+	}
+
+	payload = skb->data;
+	i = 0;
+	do {
+		ret = sdio_readsb(card->func, payload, priv->bt_dev.ioport,
+				  buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: card_to_host, read iomem (%d) failed: %d\n",
+			       i, ret);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY) {
+				kfree_skb(skb);
+				skb = NULL;
+				goto exit;
+			}
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	/* This is SDIO specific header length: byte[2][1][0], * type: byte[3]
+	   (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
+	buf_len = payload[0];
+	buf_len |= (u16) payload[1] << 8;
+	type = payload[3];
+	PRINTM(DATA, "BT: SDIO Blk Rd %s: len=%d type=%d\n", hdev->name,
+	       buf_len, type);
+	if (buf_len > buf_block_len * blksz) {
+		PRINTM(ERROR,
+		       "BT: Drop invalid rx pkt, len in hdr=%d, cmd53 length=%d\n",
+		       buf_len, buf_block_len * blksz);
+		ret = BT_STATUS_FAILURE;
+		kfree_skb(skb);
+		skb = NULL;
+		goto exit;
+	}
+	DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Rd", payload, buf_len);
+	switch (type) {
+	case HCI_ACLDATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (*(u16 *) skb->data == 0xffff) {
+			bt_store_firmware_dump(priv, skb->data, skb->len);
+			dev_kfree_skb_any(skb);
+			break;
+		}
+		bt_recv_frame(priv, skb);
+		break;
+	case HCI_SCODATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		bt_recv_frame(priv, skb);
+		break;
+	case HCI_EVENT_PKT:
+		/** add EVT Demux */
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (BT_STATUS_SUCCESS == check_evtpkt(priv, skb))
+			break;
+		switch (skb->data[0]) {
+		case 0x0E:
+			/** cmd complete */
+			bt_recv_frame(priv, skb);
+			break;
+		case 0x0F:
+			/** cmd status */
+			bt_recv_frame(priv, skb);
+			break;
+		case 0xFF:
+			/** Vendor specific pkt */
+			bt_recv_frame(priv, skb);
+			break;
+		default:
+			bt_recv_frame(priv, skb);
+			break;
+		}
+		break;
+	case MRVL_VENDOR_PKT:
+		/* Just think here need to back compatible FM */
+		bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (BT_STATUS_SUCCESS != bt_process_event(priv, skb))
+			bt_recv_frame(priv, skb);
+		break;
+	default:
+		/* Driver specified event and command resp should be handle
+		   here */
+		PRINTM(INFO, "BT: Unknown PKT type:%d\n", type);
+		kfree_skb(skb);
+		skb = NULL;
+		break;
+	}
+exit:
+	if (ret) {
+		if (hdev)
+			hdev->stat.err_rx++;
+		PRINTM(ERROR, "error when recv pkt!\n");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes the card
+ *
+ *  @param func    A pointer to sdio_func structure
+ *  @return        N/A
+ */
+static void
+sd_remove_card(struct sdio_func *func)
+{
+	struct sdio_mmc_card *card;
+
+	ENTER();
+
+	if (func) {
+		card = sdio_get_drvdata(func);
+		if (card) {
+			bt_remove_card(card->priv);
+			kfree(card);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the interrupt.
+ *
+ *  @param func  A pointer to sdio_func structure
+ *  @return      N/A
+ */
+static void
+sd_interrupt(struct sdio_func *func)
+{
+	bt_private *priv;
+	struct m_dev *m_dev = NULL;
+	struct sdio_mmc_card *card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 ireg = 0;
+	u8 host_intstatus_reg = 0;
+
+	ENTER();
+
+	card = sdio_get_drvdata(func);
+	if (!card || !card->priv) {
+		PRINTM(INFO,
+		       "BT: %s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
+		       __func__, func, card);
+		LEAVE();
+		return;
+	}
+	priv = card->priv;
+	host_intstatus_reg = priv->psdio_device->reg->host_intstatus;
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	if (priv->card_type == CARD_TYPE_SD8887 ||
+	    priv->card_type == CARD_TYPE_SD8897 ||
+	    priv->card_type == CARD_TYPE_SD8977 ||
+	    priv->card_type == CARD_TYPE_SD8997 ||
+	    priv->card_type == CARD_TYPE_SD8987 ||
+	    priv->card_type == CARD_TYPE_SD8978) {
+		ret = sdio_readsb(card->func, priv->adapter->hw_regs, 0,
+				  SD_BLOCK_SIZE);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: sdio_read_ioreg: cmd53 read int status register failed %d\n",
+			       ret);
+			goto done;
+		}
+		ireg = priv->adapter->hw_regs[host_intstatus_reg];
+	} else {
+		ireg = sdio_readb(card->func, host_intstatus_reg, &ret);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: sdio_read_ioreg: CMD52 read int status register failed %d\n",
+			       ret);
+			goto done;
+		}
+	}
+	if (ireg != 0) {
+		/*
+		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+		 * Clear the interrupt status register and re-enable
+		 * the interrupt
+		 */
+		PRINTM(INTR, "BT: INT %s: sdio_ireg = 0x%x\n", m_dev->name,
+		       ireg);
+		priv->adapter->irq_recv = ireg;
+		if (priv->card_type == CARD_TYPE_SD8777 ||
+		    priv->card_type == CARD_TYPE_SD8787) {
+			sdio_writeb(card->func,
+				    ~(ireg) & (DN_LD_HOST_INT_STATUS |
+					       UP_LD_HOST_INT_STATUS),
+				    host_intstatus_reg, &ret);
+			if (ret) {
+				PRINTM(ERROR,
+				       "BT: sdio_write_ioreg: clear int status register failed\n");
+				goto done;
+			}
+		}
+	} else {
+		PRINTM(ERROR, "BT: ERR: ireg=0\n");
+	}
+	OS_INT_DISABLE;
+	priv->adapter->sd_ireg |= ireg;
+	OS_INT_RESTORE;
+	bt_interrupt(m_dev);
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interfaces are present
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @param val    Winner status (0: winner)
+ *  @return       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_check_winner_status(bt_private *priv, u8 *val)
+{
+
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = priv->psdio_device->reg->card_fw_status0;
+
+	ENTER();
+	winner = sdio_readb(cardp->func, card_fw_status0_reg, &ret);
+	if (ret != BT_STATUS_SUCCESS) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** @brief This function tells lower driver that BT is suspended
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        None
+ */
+void
+bt_is_suspended(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	priv->adapter->is_suspended = TRUE;
+	sdio_func_suspended(card->func);
+}
+#endif
+
+/** @brief This function handles client driver suspend
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+int
+bt_sdio_suspend(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+	struct hci_dev *hcidev;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is suspended\n",
+		       sdio_func_id(func));
+		return -ENOSYS;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO suspend\n", m_dev->name);
+	hcidev = (struct hci_dev *)m_dev->dev_pointer;
+	hci_suspend_dev(hcidev);
+	skb_queue_purge(&priv->adapter->tx_queue);
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv, FALSE)) {
+			PRINTM(CMD, "BT: HS not actived, suspend fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv, FALSE)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to suspend!\n");
+			}
+		}
+	}
+
+	priv->adapter->is_suspended = TRUE;
+
+#ifdef SDIO_OOB_IRQ
+	mrvl_sdio_suspend(func);
+#endif
+	LEAVE();
+	/* We will keep the power when hs enabled successfully */
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state == HS_ACTIVATED)) {
+#ifdef MMC_PM_SKIP_RESUME_PROBE
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER and "
+		       "MMC_PM_SKIP_RESUME_PROBE\n");
+		return sdio_set_host_pm_flags(func,
+					      MMC_PM_KEEP_POWER |
+					      MMC_PM_SKIP_RESUME_PROBE);
+#else
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER\n");
+		return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+#endif
+	} else {
+		PRINTM(CMD, "BT: suspend without MMC_PM_KEEP_POWER\n");
+		return BT_STATUS_SUCCESS;
+	}
+}
+
+void
+bt_sdio_shutdown(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: shutdown: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is shutdown\n",
+		       sdio_func_id(func));
+		return;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return;
+	}
+
+	priv = cardp->priv;
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv, TRUE)) {
+			PRINTM(CMD, "BT: HS not actived, shutdown fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv, TRUE)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to shutdown!\n");
+			}
+		}
+	}
+	LEAVE();
+}
+
+/** @brief This function handles client driver resume
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_sdio_resume(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+	struct hci_dev *hcidev;
+
+	ENTER();
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: resume: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+	priv->adapter->is_suspended = FALSE;
+#ifdef SDIO_OOB_IRQ
+	mrvl_sdio_resume(func);
+#endif
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO resume\n", m_dev->name);
+	hcidev = (struct hci_dev *)m_dev->dev_pointer;
+	hci_resume_dev(hcidev);
+	sbi_wakeup_firmware(priv);
+	priv->adapter->hs_state = HS_DEACTIVATED;
+	PRINTM(CMD, "BT:%s: HS DEACTIVATED in Resume!\n", m_dev->name);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+#endif
+#endif
+
+/********************************************************
+		Global Functions
+********************************************************/
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+static const struct dev_pm_ops bt_sdio_pm_ops = {
+	.suspend = bt_sdio_suspend,
+	.resume = bt_sdio_resume,
+};
+#endif
+#endif
+static struct sdio_driver sdio_bt = {
+	.name = "sdio_bt",
+	.id_table = bt_ids,
+	.probe = sd_probe_card,
+	.remove = sd_remove_card,
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+	.drv = {
+		.pm = &bt_sdio_pm_ops,
+		.shutdown = bt_sdio_shutdown,
+		}
+#endif
+#endif
+};
+
+/**
+ *  @brief This function registers the bt module in bus driver.
+ *
+ *  @return	   An int pointer that keeps returned value
+ */
+int *
+sbi_register(void)
+{
+	int *ret;
+
+	ENTER();
+
+	if (sdio_register_driver(&sdio_bt) != 0) {
+		PRINTM(FATAL, "BT: SD Driver Registration Failed\n");
+		LEAVE();
+		return NULL;
+	} else
+		ret = (int *)1;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function de-registers the bt module in bus driver.
+ *
+ *  @return        N/A
+ */
+void
+sbi_unregister(void)
+{
+	ENTER();
+	sdio_unregister_driver(&sdio_bt);
+	LEAVE();
+}
+
+/**
+ *  @brief This function registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_dev(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	u8 chiprev;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	struct sdio_func *func;
+	u8 host_intstatus_reg = priv->psdio_device->reg->host_intstatus;
+	u8 host_int_rsr_reg = priv->psdio_device->reg->host_int_rsr_reg;
+	u8 card_misc_cfg_reg = priv->psdio_device->reg->card_misc_cfg_reg;
+	u8 card_revision_reg = priv->psdio_device->reg->card_revision;
+	u8 io_port_0_reg = priv->psdio_device->reg->io_port_0;
+	u8 io_port_1_reg = priv->psdio_device->reg->io_port_1;
+	u8 io_port_2_reg = priv->psdio_device->reg->io_port_2;
+	u8 card_magic_reg = CARD_MAGIC_REG;
+	u8 magic_val = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: Error: card or function is NULL!\n");
+		goto failed;
+	}
+	func = card->func;
+	priv->hotplug_device = &func->dev;
+
+	/* Initialize the private structure */
+	strncpy(priv->bt_dev.name, "bt_sdio0", sizeof(priv->bt_dev.name));
+	priv->bt_dev.ioport = 0;
+	priv->bt_dev.fn = func->num;
+
+	sdio_claim_host(func);
+#ifdef SDIO_OOB_IRQ
+	ret = mrvl_sdio_claim_irq(func, sd_interrupt);
+#else
+	ret = sdio_claim_irq(func, sd_interrupt);
+#endif
+	if (ret) {
+		PRINTM(FATAL, ": sdio_claim_irq failed: ret=%d\n", ret);
+		goto release_host;
+	}
+	ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
+	if (ret) {
+		PRINTM(FATAL, ": %s: cannot set SDIO block size\n", __func__);
+		goto release_irq;
+	}
+
+	/* read Revision Register to get the chip revision number */
+	chiprev = sdio_readb(func, card_revision_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_REVISION_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->chip_rev = chiprev;
+	PRINTM(INFO, "revision=%#x\n", chiprev);
+
+	magic_val = sdio_readb(func, card_magic_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_MAGIC_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->magic_val = magic_val;
+	PRINTM(INFO, "magic_val=%#x\n", magic_val);
+
+	/*
+	 * Read the HOST_INTSTATUS_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.
+	 */
+	reg = sdio_readb(func, host_intstatus_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+
+	/* Read the IO port */
+	reg = sdio_readb(func, io_port_0_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= reg;
+
+	reg = sdio_readb(func, io_port_1_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 8);
+
+	reg = sdio_readb(func, io_port_2_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 16);
+
+	PRINTM(INFO, ": SDIO FUNC%d IO port: 0x%x\n", priv->bt_dev.fn,
+	       priv->bt_dev.ioport);
+
+	if (priv->card_type == CARD_TYPE_SD8977 ||
+	    priv->card_type == CARD_TYPE_SD8978) {
+		if (bt_intmode == INT_MODE_GPIO) {
+			PRINTM(MSG, "Enable GPIO-1 INT\n");
+			sdio_writeb(func, ENABLE_GPIO_1_INT_MODE,
+				    SCRATCH_REG_32, &ret);
+			if (ret < 0)
+				goto release_irq;
+		}
+	}
+
+#define SDIO_INT_MASK       0x3F
+	if (priv->card_type == CARD_TYPE_SD8887 ||
+	    priv->card_type == CARD_TYPE_SD8897 ||
+	    priv->card_type == CARD_TYPE_SD8797 ||
+	    priv->card_type == CARD_TYPE_SD8977 ||
+	    priv->card_type == CARD_TYPE_SD8997 ||
+	    priv->card_type == CARD_TYPE_SD8987 ||
+	    priv->card_type == CARD_TYPE_SD8978) {
+		/* Set Host interrupt reset to read to clear */
+		reg = sdio_readb(func, host_int_rsr_reg, &ret);
+		if (ret < 0)
+			goto release_irq;
+		sdio_writeb(func, reg | SDIO_INT_MASK, host_int_rsr_reg, &ret);
+		if (ret < 0)
+			goto release_irq;
+		/* Set auto re-enable */
+		reg = sdio_readb(func, card_misc_cfg_reg, &ret);
+		if (ret < 0)
+			goto release_irq;
+		sdio_writeb(func, reg | AUTO_RE_ENABLE_INT, card_misc_cfg_reg,
+			    &ret);
+		if (ret < 0)
+			goto release_irq;
+	}
+
+	sdio_set_drvdata(func, card);
+	sdio_release_host(func);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+release_irq:
+#ifdef SDIO_OOB_IRQ
+	mrvl_sdio_release_irq(func);
+#else
+	sdio_release_irq(func);
+#endif
+release_host:
+	sdio_release_host(func);
+failed:
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function de-registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_unregister_dev(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	if (card && card->func) {
+		sdio_claim_host(card->func);
+#ifdef SDIO_OOB_IRQ
+		mrvl_sdio_release_irq(card->func);
+#else
+		sdio_release_irq(card->func);
+#endif
+		sdio_disable_func(card->func);
+		sdio_release_host(card->func);
+		sdio_set_drvdata(card->func, NULL);
+	}
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function enables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_enable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sd_enable_host_int_mask(priv, HIM_ENABLE);
+	sd_get_rx_unit(priv);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function disables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sbi_disable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sbi_disable_host_int_mask(priv, HIM_DISABLE);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param payload A pointer to the data/cmd buffer
+ *  @param nb      Length of data/cmd
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	int ret = BT_STATUS_SUCCESS;
+	int buf_block_len;
+	int blksz;
+	int i = 0;
+	u8 *buf = NULL;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	buf = payload;
+
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (nb + blksz - 1) / blksz;
+	/* Allocate buffer and copy payload */
+	if ((t_ptr)payload & (DMA_ALIGNMENT - 1)) {
+		if (nb > MAX_TX_BUF_SIZE) {
+			PRINTM(ERROR, "BT: Invalid tx packet, size=%d\n", nb);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		}
+		/* Ensure 8-byte aligned CMD buffer */
+		buf = priv->adapter->tx_buf;
+		memcpy(buf, payload, nb);
+	}
+	sdio_claim_host(card->func);
+	do {
+		/* Transfer data to card */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, buf,
+				   buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: host_to_card, write iomem (%d) failed: %d\n",
+			       i, ret);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY)
+				goto exit;
+		} else {
+			PRINTM(DATA, "BT: SDIO Blk Wr %s: len=%d\n",
+			       m_dev->name, nb);
+			DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Wr", payload, nb);
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	priv->bt_dev.tx_dnld_rdy = FALSE;
+exit:
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_download_fw(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	sdio_claim_host(card->func);
+	if (BT_STATUS_SUCCESS == sd_verify_fw_download(priv, 1)) {
+		PRINTM(MSG, "BT: FW already downloaded!\n");
+		sdio_release_host(card->func);
+		sbi_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+	/* Check if other interface is downloading */
+	ret = sd_check_winner_status(priv, &winner);
+	if (ret == BT_STATUS_FAILURE) {
+		PRINTM(FATAL, "BT read winner status failed!\n");
+		goto done;
+	}
+	if (winner) {
+		PRINTM(MSG, "BT is not the winner (0x%x). Skip FW download\n",
+		       winner);
+		/* check if the fimware is downloaded successfully or not */
+		if (sd_verify_fw_download(priv, MAX_MULTI_INTERFACE_POLL_TRIES)) {
+			PRINTM(FATAL, "BT: FW failed to be active in time!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		sdio_release_host(card->func);
+		sbi_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+
+	do_gettimeofday(&priv->req_fw_time);
+	/* Download the main firmware via the helper firmware */
+	if (sd_download_firmware_w_helper(priv)) {
+		PRINTM(INFO, "BT: FW download failed!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+	goto exit;
+done:
+	sdio_release_host(card->func);
+exit:
+	LEAVE();
+	return ret;
+err_register:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the interrupt status and handle it accordingly.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_get_int_status(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 sdio_ireg = 0;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	OS_INT_DISABLE;
+	sdio_ireg = priv->adapter->sd_ireg;
+	priv->adapter->sd_ireg = 0;
+	OS_INT_RESTORE;
+	sdio_claim_host(card->func);
+	priv->adapter->irq_done = sdio_ireg;
+	if (sdio_ireg & DN_LD_HOST_INT_STATUS) {	/* tx_done INT */
+		if (priv->bt_dev.tx_dnld_rdy) {	/* tx_done already received */
+			PRINTM(INFO,
+			       "BT: warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
+			       priv->bt_dev.tx_dnld_rdy, sdio_ireg);
+		} else {
+			priv->bt_dev.tx_dnld_rdy = TRUE;
+		}
+	}
+	if (sdio_ireg & UP_LD_HOST_INT_STATUS)
+		sd_card_to_host(priv);
+
+	ret = BT_STATUS_SUCCESS;
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function wakeup firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sbi_wakeup_firmware(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
+	sdio_release_host(card->func);
+	PRINTM(CMD, "BT wake up firmware\n");
+
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function updates the SDIO card types
+ *
+ *  @param priv     A Pointer to the bt_private structure
+ *  @param card     A Pointer to card
+ *
+ *  @return         N/A
+ */
+void
+sdio_update_card_type(bt_private *priv, void *card)
+{
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)card;
+
+	/* Update card type */
+	if (cardp->func->device == SD_DEVICE_ID_8777_BT_FN2 ||
+	    cardp->func->device == SD_DEVICE_ID_8777_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8777;
+	else if (cardp->func->device == SD_DEVICE_ID_8787_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8787_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8787;
+	else if (cardp->func->device == SD_DEVICE_ID_8887_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8887_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8887;
+	else if (cardp->func->device == SD_DEVICE_ID_8897_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8897_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8897;
+	else if (cardp->func->device == SD_DEVICE_ID_8797_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8797_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8797;
+	else if (cardp->func->device == SD_DEVICE_ID_8977_BT_FN2)
+		priv->card_type = CARD_TYPE_SD8977;
+	else if (cardp->func->device == SD_DEVICE_ID_8978_BT_FN2)
+		priv->card_type = CARD_TYPE_SD8978;
+	else if (cardp->func->device == SD_DEVICE_ID_8997_BT_FN2)
+		priv->card_type = CARD_TYPE_SD8997;
+	else if (cardp->func->device == SD_DEVICE_ID_8987_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8987_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8987;
+}
+
+/**
+ *  @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
+ */
+int
+sdio_get_sdio_device(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u16 card_type = priv->card_type;
+
+	ENTER();
+
+	switch (card_type) {
+	case CARD_TYPE_SD8777:
+		priv->psdio_device = &bt_sdio_sd8777;
+		break;
+	case CARD_TYPE_SD8787:
+		priv->psdio_device = &bt_sdio_sd8787;
+		break;
+	case CARD_TYPE_SD8887:
+		priv->psdio_device = &bt_sdio_sd8887;
+		break;
+	case CARD_TYPE_SD8897:
+		priv->psdio_device = &bt_sdio_sd8897;
+		break;
+	case CARD_TYPE_SD8797:
+		priv->psdio_device = &bt_sdio_sd8797;
+		break;
+	case CARD_TYPE_SD8977:
+		priv->psdio_device = &bt_sdio_sd8977;
+		break;
+	case CARD_TYPE_SD8978:
+		priv->psdio_device = &bt_sdio_sd8978;
+		break;
+	case CARD_TYPE_SD8997:
+		priv->psdio_device = &bt_sdio_sd8997;
+		break;
+	case CARD_TYPE_SD8987:
+		priv->psdio_device = &bt_sdio_sd8987;
+		break;
+	default:
+		PRINTM(ERROR, "BT can't get right card type \n");
+		ret = BT_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+#define SD8897_INIT_START_REG  0xDC
+#define SD8897_INIT_END_REG  0xE1
+#define SD8887_INIT_START_REG  0xA0
+#define SD8887_INIT_END_REG  0xA5
+#define SD8977_SD8978_SD8997_INIT_START_REG 0xF1
+#define SD8977_SD8978_SD8997_INIT_END_REG 0xF6
+
+/** @brief This function dump the SDIO register
+ *
+ *  @param priv     A Pointer to the bt_private structure
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_sdio_regs(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+	char buf[256], *ptr;
+	u8 loop, func, data;
+	unsigned int reg, reg_start, reg_end;
+	u8 index = 0;
+	unsigned int reg_table_8887[] = { 0x58, 0x59, 0x5c, 0x60, 0x64, 0x70,
+		0x71, 0x72, 0x73, 0xd8, 0xd9, 0xda
+	};
+	u8 loop_num = 0;
+	unsigned int *reg_table = NULL;
+	u8 reg_table_size = 0;
+	unsigned int init_reg_start = 0;
+	unsigned int init_reg_end = 0;
+	if (priv->card_type == CARD_TYPE_SD8887) {
+		init_reg_start = SD8887_INIT_START_REG;
+		init_reg_end = SD8887_INIT_END_REG;
+	} else if (priv->card_type == CARD_TYPE_SD8897) {
+		init_reg_start = SD8897_INIT_START_REG;
+		init_reg_end = SD8897_INIT_END_REG;
+	} else if (priv->card_type == CARD_TYPE_SD8977 ||
+		   priv->card_type == CARD_TYPE_SD8997 ||
+		   priv->card_type == CARD_TYPE_SD8987 ||
+		   priv->card_type == CARD_TYPE_SD8978) {
+		init_reg_start = SD8977_SD8978_SD8997_INIT_START_REG;
+		init_reg_end = SD8977_SD8978_SD8997_INIT_END_REG;
+	}
+
+	if (priv->card_type == CARD_TYPE_SD8887) {
+		loop_num = 3;
+		reg_table = reg_table_8887;
+		reg_table_size = sizeof(reg_table_8887) / sizeof(int);
+	} else
+		loop_num = 2;
+	if (priv->adapter->ps_state)
+		sbi_wakeup_firmware(priv);
+
+	sdio_claim_host(card->func);
+	for (loop = 0; loop < loop_num; 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 == 2) {
+			/* Read specific registers of SDIO function1 */
+			index = 0;
+			func = 2;
+			reg_start = reg_table[index++];
+			reg_end = reg_table[reg_table_size - 1];
+		} else {
+			func = 2;
+			reg_start = 0;
+			reg_end = 0x09;
+		}
+		if (loop == 2)
+			ptr += sprintf(ptr, "SDIO Func%d: ", func);
+		else
+			ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", func,
+				       reg_start, reg_end);
+		for (reg = reg_start; reg <= reg_end;) {
+			if (func == 0)
+				data = sdio_f0_readb(card->func, reg, &ret);
+			else
+				data = sdio_readb(card->func, reg, &ret);
+			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(MSG, "%s\n", buf);
+	}
+
+	if (init_reg_start) {
+		memset(buf, 0, sizeof(buf));
+		ptr = buf;
+		ptr += sprintf(ptr, "Init Status Reg (%#x-%#x): ",
+			       init_reg_start, init_reg_end);
+		for (reg = init_reg_start; reg <= init_reg_end;) {
+			data = sdio_readb(card->func, reg, &ret);
+			if (!ret)
+				ptr += sprintf(ptr, "%02x ", data);
+			else {
+				ptr += sprintf(ptr, "ERR");
+				break;
+			}
+			reg++;
+		}
+		PRINTM(MSG, "%s\n", buf);
+	}
+	sdio_release_host(card->func);
+}
+
+module_param(fw_name, charp, 0);
+MODULE_PARM_DESC(fw_name, "Firmware name");
+module_param(bt_req_fw_nowait, int, 0);
+MODULE_PARM_DESC(bt_req_fw_nowait,
+		 "0: Use request_firmware API; 1: Use request_firmware_nowait API");
+module_param(multi_fn, int, 0);
+MODULE_PARM_DESC(multi_fn, "Bit 2: FN2;");
+
+module_param(bt_intmode, int, 0);
+MODULE_PARM_DESC(bt_intmode, "0: INT_MODE_SDIO, 1: INT_MODE_GPIO");
diff --git a/bt_sd8987/bt/hci_wrapper.h b/bt_sd8987/bt/hci_wrapper.h
new file mode 100644
index 0000000..c3c5035
--- /dev/null
+++ b/bt_sd8987/bt/hci_wrapper.h
@@ -0,0 +1,163 @@
+/** @file hci_wrapper.h
+ *  @brief This file contains HCI related definitions
+ *
+ *  Copyright (C) 2011-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _HCI_WRAPPER_H_
+#define _HCI_WRAPPER_H_
+
+#include <linux/module.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+/**  Define Seq num */
+#define BT_SEQ      0
+
+/** Define dev type */
+#define BT_TYPE     1
+#define BT_AMP_TYPE 2
+
+/** Define spec type */
+#define BLUEZ_SPEC     1
+#define IANYWHERE_SPEC 2
+#define GENERIC_SPEC   3
+
+/** Define lock/unlock wrapper */
+#define mdev_req_lock(d)		down(&d->req_lock)
+#define mdev_req_unlock(d)		up(&d->req_lock)
+
+/** Length of device name */
+#define DEV_NAME_LEN				32
+
+/** Define struct m_dev */
+struct m_dev {
+	char name[DEV_NAME_LEN];
+	int index;
+	unsigned long flags;
+	spinlock_t lock;
+	struct semaphore req_lock;
+	struct sk_buff_head rx_q;
+	wait_queue_head_t req_wait_q;
+	struct hci_dev_stats stat;
+	struct module *owner;
+	void *dev_pointer;
+	int dev_type;
+	int spec_type;
+	void *driver_data;
+	int read_continue_flag;
+	int wait_rx_complete;
+	int rx_complete_flag;
+	wait_queue_head_t rx_wait_q;
+	spinlock_t rxlock;
+	atomic_t extra_cnt;
+
+	struct sk_buff *evt_skb;
+	struct sk_buff *acl_skb;
+	struct sk_buff *sco_skb;
+
+	int (*open) (struct m_dev * m_dev);
+	int (*close) (struct m_dev * m_dev);
+	int (*flush) (struct m_dev * m_dev);
+	int (*send) (struct m_dev * m_dev, struct sk_buff * skb);
+	void (*destruct) (struct m_dev * m_dev);
+	void (*notify) (struct m_dev * m_dev, unsigned int evt);
+	int (*ioctl) (struct m_dev * m_dev, unsigned int cmd, void *arg);
+	void (*query) (struct m_dev * m_dev, void *arg);
+
+};
+
+/** Define struct mbt_dev */
+struct mbt_dev {
+	/** maybe could add some private member later */
+	char name[DEV_NAME_LEN];
+	unsigned long flags;
+	__u8 type;
+
+	__u16 pkt_type;
+	__u16 esco_type;
+	__u16 link_policy;
+	__u16 link_mode;
+
+	__u32 idle_timeout;
+	__u16 sniff_min_interval;
+	__u16 sniff_max_interval;
+
+	struct sk_buff *reassembly[3];
+
+	atomic_t promisc;
+};
+
+/** This function frees m_dev allocation */
+void free_m_dev(struct m_dev *m_dev);
+
+/**
+ *  @brief This function receives frames
+ *
+ *  @param skb	A pointer to struct sk_buff
+ *  @return	0--success otherwise error code
+ */
+static inline int
+mdev_recv_frame(struct sk_buff *skb)
+{
+	struct m_dev *m_dev = (struct m_dev *)skb->dev;
+	if (!m_dev || (!test_bit(HCI_UP, &m_dev->flags)
+		       && !test_bit(HCI_INIT, &m_dev->flags))) {
+		kfree_skb(skb);
+		return -ENXIO;
+	}
+
+	/* Incomming skb */
+	bt_cb(skb)->incoming = 1;
+
+	/* Time stamp */
+	__net_timestamp(skb);
+
+	/* Queue frame for rx task */
+	skb_queue_tail(&m_dev->rx_q, skb);
+
+	/* Wakeup rx thread */
+	wake_up_interruptible(&m_dev->req_wait_q);
+
+	return 0;
+}
+
+/**
+ *  @brief mbt dev suspend handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_suspend_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+/**
+ *  @brief mbt dev resume handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_resume_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+#endif /* _HCI_WRAPPER_H_ */
diff --git a/bt_sd8987/bt/mbt_char.c b/bt_sd8987/bt/mbt_char.c
new file mode 100644
index 0000000..f863bc6
--- /dev/null
+++ b/bt_sd8987/bt/mbt_char.c
@@ -0,0 +1,799 @@
+/** @file mbt_char.c
+  *
+  * @brief This file contains the char device function calls
+  *
+  * Copyright (C) 2010-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/path.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+
+#include "bt_drv.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+#include <linux/sched/signal.h>
+#endif
+#include "mbt_char.h"
+
+static LIST_HEAD(char_dev_list);
+
+static DEFINE_SPINLOCK(char_dev_list_lock);
+
+static int mbtchar_major = MBTCHAR_MAJOR_NUM;
+
+/**
+ *	@brief  Gets char device structure
+ *
+ *	@param dev		A pointer to char_dev
+ *
+ *	@return			kobject structure
+ */
+struct kobject *
+chardev_get(struct char_dev *dev)
+{
+	struct kobject *kobj;
+
+	kobj = bt_priv_get(dev->m_dev->driver_data);
+	if (!kobj)
+		return NULL;
+	PRINTM(INFO, "dev get kobj\n");
+	kobj = kobject_get(&dev->kobj);
+	if (!kobj)
+		bt_priv_put(dev->m_dev->driver_data);
+	return kobj;
+}
+
+/**
+ *	@brief  Prints char device structure
+ *
+ *	@param dev		A pointer to char_dev
+ *
+ *	@return			N/A
+ */
+void
+chardev_put(struct char_dev *dev)
+{
+	if (dev) {
+		struct m_dev *m_dev = dev->m_dev;
+		PRINTM(INFO, "dev put kobj\n");
+		kobject_put(&dev->kobj);
+		if (m_dev)
+			bt_priv_put(m_dev->driver_data);
+	}
+}
+
+/**
+ *	@brief Changes permissions of the dev
+ *
+ *	@param name	pointer to character
+ *	@param mode		mode_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chmod(char *name, mode_t mode)
+{
+	struct path path;
+	struct inode *inode;
+	struct iattr newattrs;
+	int ret;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chmod(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief Changes ownership of the dev
+ *
+ *	@param name	pointer to character
+ *	@param user		uid_t type data
+ *	@param group	gid_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chown(char *name, uid_t user, gid_t group)
+{
+	struct path path;
+	struct inode *inode = NULL;
+	struct iattr newattrs;
+	int ret = 0;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chown(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+	newattrs.ia_valid = ATTR_CTIME;
+	if (user != (uid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_UID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_uid = user;
+#else
+		newattrs.ia_uid = KUIDT_INIT(user);
+#endif
+	}
+	if (group != (gid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_GID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_gid = group;
+#else
+		newattrs.ia_gid = KGIDT_INIT(group);
+#endif
+	}
+	if (!S_ISDIR(inode->i_mode))
+		newattrs.ia_valid |=
+			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief write handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes written
+ */
+ssize_t
+chardev_write(struct file * filp, const char *buf, size_t count, loff_t * f_pos)
+{
+	int nwrite = 0;
+	struct sk_buff *skb;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	if (!test_bit(HCI_UP, &m_dev->flags)) {
+		LEAVE();
+		return -EBUSY;
+	}
+	nwrite = count;
+	skb = bt_skb_alloc(count, GFP_ATOMIC);
+	if (!skb) {
+		PRINTM(ERROR, "mbtchar_write(): fail to alloc skb\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	if (copy_from_user((void *)skb_put(skb, count), buf, count)) {
+		PRINTM(ERROR, "mbtchar_write(): cp_from_user failed\n");
+		kfree_skb(skb);
+		nwrite = -EFAULT;
+		goto exit;
+	}
+
+	skb->dev = (void *)m_dev;
+	bt_cb(skb)->pkt_type = *((unsigned char *)skb->data);
+	skb_pull(skb, 1);
+
+	PRINTM(DATA, "Write: pkt_type: 0x%x, len=%d @%lu\n",
+	       bt_cb(skb)->pkt_type, skb->len, jiffies);
+	DBG_HEXDUMP(DAT_D, "chardev_write", skb->data, skb->len);
+
+	/* Send skb to the hci wrapper layer */
+	if (m_dev->send(m_dev, skb)) {
+		PRINTM(ERROR, "Write: Fail\n");
+		nwrite = 0;
+		/* Send failed */
+		kfree_skb(skb);
+	}
+exit:
+	LEAVE();
+	return nwrite;
+}
+
+/**
+ *	@brief read handler for BT char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes read
+ */
+ssize_t
+chardev_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t ret = 0;
+	struct sk_buff *skb = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	/* Wait for rx data */
+	add_wait_queue(&m_dev->req_wait_q, &wait);
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		skb = skb_dequeue(&m_dev->rx_q);
+		if (skb)
+			break;
+		if (!test_bit(HCI_UP, &m_dev->flags)) {
+			ret = -EBUSY;
+			break;
+		}
+
+		if (filp->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			break;
+		}
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&m_dev->req_wait_q, &wait);
+
+	if (!skb)
+		goto out;
+
+	if (m_dev->read_continue_flag == 0) {
+		/* Put type byte before the data */
+		memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+		PRINTM(DATA, "Read: pkt_type: 0x%x, len=%d @%lu\n",
+		       bt_cb(skb)->pkt_type, skb->len, jiffies);
+	}
+	DBG_HEXDUMP(DAT_D, "chardev_read", skb->data, skb->len);
+	if (skb->len > count) {
+		/* user data length is smaller than the skb length */
+		if (copy_to_user(buf, skb->data, count)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		skb_pull(skb, count);
+		skb_queue_head(&m_dev->rx_q, skb);
+		m_dev->read_continue_flag = 1;
+		wake_up_interruptible(&m_dev->req_wait_q);
+		ret = count;
+		goto out;
+	} else {
+		if (copy_to_user(buf, skb->data, skb->len)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		m_dev->read_continue_flag = 0;
+		ret = skb->len;
+	}
+outf:
+	kfree_skb(skb);
+out:
+	if (m_dev->wait_rx_complete && skb_queue_empty(&m_dev->rx_q)) {
+		m_dev->rx_complete_flag = TRUE;
+		wake_up_interruptible(&m_dev->rx_wait_q);
+	}
+	LEAVE();
+	return ret;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+char_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, void *arg)
+#else
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+char_ioctl(struct file *filp, unsigned int cmd, void *arg)
+#endif
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+	case MBTCHAR_IOCTL_RELEASE:
+		m_dev->close(m_dev);
+		break;
+	case MBTCHAR_IOCTL_QUERY_TYPE:
+		m_dev->query(m_dev, arg);
+		break;
+	default:
+		m_dev->ioctl(m_dev, cmd, arg);
+		break;
+	}
+	LEAVE();
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl(struct inode *inode, struct file *filp,
+	      unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, (void *)arg);
+#else
+	return char_ioctl(filp, cmd, (void *)arg);
+#endif
+}
+
+#ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl_compat(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl_compat(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, compat_ptr(arg));
+#else
+	return char_ioctl(filp, cmd, compat_ptr(arg));
+#endif
+}
+#endif /* CONFIG_COMPAT */
+
+/**
+ *	@brief open handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_open(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = NULL;
+	struct m_dev *m_dev = NULL;
+	struct char_dev *cdev = NULL;
+	struct list_head *p = NULL;
+	ENTER();
+
+	list_for_each(p, &char_dev_list) {
+		cdev = list_entry(p, struct char_dev, list);
+		if (mbtchar_major == MAJOR(inode->i_cdev->dev) &&
+		    cdev->minor == MINOR(inode->i_cdev->dev)) {
+			dev = cdev;
+			break;
+		}
+	}
+	if (!dev) {
+		PRINTM(ERROR, "cannot find dev from inode\n");
+		LEAVE();
+		return -ENXIO;
+	}
+	if (!chardev_get(dev)) {
+		LEAVE();
+		return -ENXIO;
+	}
+	filp->private_data = dev;	/* for other methods */
+	m_dev = dev->m_dev;
+	mdev_req_lock(m_dev);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)
+	if (test_bit(HCI_UP, &m_dev->flags)) {
+		atomic_inc(&m_dev->extra_cnt);
+		goto done;
+	}
+#endif
+	if (m_dev->open(m_dev)) {
+		ret = -EIO;
+		goto done;
+	}
+	set_bit(HCI_UP, &m_dev->flags);
+
+done:
+	mdev_req_unlock(m_dev);
+	if (ret)
+		chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief release handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_release(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)
+	if (m_dev && (atomic_dec_if_positive(&m_dev->extra_cnt) >= 0)) {
+		LEAVE();
+		return ret;
+	}
+#endif
+	if (m_dev)
+		ret = dev->m_dev->close(dev->m_dev);
+	filp->private_data = NULL;
+	chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief poll handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param wait		pointer to poll_table structure
+ *	@return			mask
+ */
+static unsigned int
+chardev_poll(struct file *filp, poll_table * wait)
+{
+	unsigned int mask;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+
+	m_dev = dev->m_dev;
+	poll_wait(filp, &m_dev->req_wait_q, wait);
+	mask = POLLOUT | POLLWRNORM;
+	if (skb_peek(&m_dev->rx_q))
+		mask |= POLLIN | POLLRDNORM;
+	if (!test_bit(HCI_UP, &(m_dev->flags)))
+		mask |= POLLHUP;
+	PRINTM(INFO, "poll mask=0x%x\n", mask);
+	LEAVE();
+	return mask;
+}
+
+/* File ops for the Char driver */
+const struct file_operations chardev_fops = {
+	.owner = THIS_MODULE,
+	.read = chardev_read,
+	.write = chardev_write,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	.ioctl = chardev_ioctl,
+#else
+	.unlocked_ioctl = chardev_ioctl,
+#endif
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = chardev_ioctl_compat,
+#endif
+	.open = chardev_open,
+	.release = chardev_release,
+	.poll = chardev_poll,
+};
+
+/**
+ *	@brief This function creates the char dev
+ *
+ *	@param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param mod_name		A pointer to char
+ *  @param dev_name		A pointer to char
+ *	@return				0--success otherwise failure
+ */
+int
+register_char_dev(struct char_dev *dev, struct class *char_class,
+		  char *mod_name, char *dev_name)
+{
+	int ret = 0, dev_num;
+	unsigned long flags;
+	ENTER();
+	/* create the chrdev region */
+	if (mbtchar_major) {
+		dev_num = MKDEV(mbtchar_major, dev->minor);
+		ret = register_chrdev_region(dev_num, 1, mod_name);
+	} else {
+		PRINTM(INFO, "chardev: no major # yet\n");
+		ret = alloc_chrdev_region((dev_t *) & dev_num, dev->minor, 1,
+					  mod_name);
+	}
+
+	if (ret) {
+		PRINTM(ERROR, "chardev: create chrdev_region failed\n");
+		LEAVE();
+		return ret;
+	}
+	if (!mbtchar_major) {
+		/* Store the allocated dev major # */
+		mbtchar_major = MAJOR(dev_num);
+	}
+	dev->cdev = cdev_alloc();
+	dev->cdev->ops = &chardev_fops;
+	dev->cdev->owner = chardev_fops.owner;
+	dev_num = MKDEV(mbtchar_major, dev->minor);
+
+	if (cdev_add(dev->cdev, dev_num, 1)) {
+		PRINTM(ERROR, "chardev: cdev_add failed\n");
+		ret = -EFAULT;
+		goto free_cdev_region;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), NULL, dev_name);
+	}
+#else
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), dev_name);
+	}
+#endif
+	PRINTM(INFO, "register char dev=%s\n", dev_name);
+
+	/** modify later */
+
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_add_tail(&dev->list, &char_dev_list);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+
+	LEAVE();
+	return ret;
+free_cdev_region:
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief This function deletes the char dev
+ *
+ *  @param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param dev_name		A pointer to char
+ *  @return				0--success otherwise failure
+ */
+int
+unregister_char_dev(struct char_dev *dev, struct class *char_class,
+		    char *dev_name)
+{
+	ENTER();
+	device_destroy(char_class, MKDEV(mbtchar_major, dev->minor));
+	cdev_del(dev->cdev);
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	PRINTM(INFO, "unregister char dev=%s\n", dev_name);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param char_class	A pointer to class struct
+ *  @return				N/A
+ */
+void
+chardev_cleanup(struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	do {
+		dev = NULL;
+		list_for_each(p, &char_dev_list) {
+			dev = list_entry(p, struct char_dev, list);
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			unregister_char_dev(dev, char_class, dev->m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	} while (dev);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	class_destroy(char_class);
+	LEAVE();
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param m_dev	A pointer to m_dev struct
+ *  @param char_class	A pointer to class struct
+ *  @return			N/A
+ */
+void
+chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_for_each(p, &char_dev_list) {
+		dev = list_entry(p, struct char_dev, list);
+		if (dev->minor == m_dev->index) {
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			dev->m_dev = NULL;
+			unregister_char_dev(dev, char_class, m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	LEAVE();
+}
diff --git a/bt_sd8987/bt/mbt_char.h b/bt_sd8987/bt/mbt_char.h
new file mode 100644
index 0000000..d753601
--- /dev/null
+++ b/bt_sd8987/bt/mbt_char.h
@@ -0,0 +1,67 @@
+/** @file mbt_char.h
+  *
+  * @brief This file contains mbtchar driver specific defines etc
+  *
+  * Copyright (C) 2010-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+#ifndef __MBT_CHAR_H__
+#define __MBT_CHAR_H__
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+
+/** Define ioctl */
+#define MBTCHAR_IOCTL_RELEASE       _IO('M', 1)
+#define MBTCHAR_IOCTL_QUERY_TYPE    _IO('M', 2)
+
+#define MBTCHAR_MAJOR_NUM            (0)
+
+/** Interface specific macros */
+#define FMCHAR_MINOR_BASE            (10)
+#define NFCCHAR_MINOR_BASE           (20)
+
+/** Declaration of char_dev struct */
+struct char_dev {
+	struct list_head list;
+	int minor;
+	int dev_type;
+	struct cdev *cdev;
+	struct m_dev *m_dev;
+	struct kobject kobj;
+};
+
+/** Changes permissions of the dev */
+int mbtchar_chmod(char *name, mode_t mode);
+
+/** Changes ownership of the dev */
+int mbtchar_chown(char *name, uid_t user, gid_t group);
+
+/**	This function creates the char dev */
+int register_char_dev(struct char_dev *dev, struct class *char_class,
+		      char *mod_name, char *dev_name);
+
+/**	This function deletes the char dev */
+int unregister_char_dev(struct char_dev *dev, struct class *char_class,
+			char *dev_name);
+
+/**	This function cleans module */
+void chardev_cleanup(struct class *char_class);
+
+/**	This function cleans module */
+void chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class);
+
+#endif /*__MBT_CHAR_H__*/
diff --git a/bt_sd8987/bt_char/bt_drv.h b/bt_sd8987/bt_char/bt_drv.h
new file mode 100644
index 0000000..2c4c9c6
--- /dev/null
+++ b/bt_sd8987/bt_char/bt_drv.h
@@ -0,0 +1,924 @@
+/** @file bt_drv.h
+ *  @brief This header file contains global constant/enum definitions,
+ *  global variable declaration.
+ *
+ *  Copyright (C) 2007-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_DRV_H_
+#define _BT_DRV_H_
+
+#include <linux/version.h>
+#include <linux/kthread.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+
+#include "hci_wrapper.h"
+
+/** MAX adapter BT driver supported */
+#define MAX_BT_ADAPTER    3
+
+#ifndef BIT
+/** BIT definition */
+#define BIT(x) (1UL << (x))
+#endif
+
+#ifdef MBT_64BIT
+typedef u64 t_ptr;
+#else
+typedef u32 t_ptr;
+#endif
+
+/** max number of adapter supported */
+#define MAX_BT_ADAPTER      3
+/** Define drv_mode bit */
+#define DRV_MODE_BT         BIT(0)
+
+/** Define devFeature bit */
+#define DEV_FEATURE_BT     BIT(0)
+#define DEV_FEATURE_BTAMP     BIT(1)
+#define DEV_FEATURE_BLE     BIT(2)
+
+/** Define maximum number of radio func supported */
+#define MAX_RADIO_FUNC     4
+
+/** MAC address print format */
+#ifndef MACSTR
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+
+/** MAC address print arguments */
+#ifndef MAC2STR
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#endif
+
+/** Debug level : Message */
+#define	DBG_MSG			BIT(0)
+/** Debug level : Fatal */
+#define DBG_FATAL		BIT(1)
+/** Debug level : Error */
+#define DBG_ERROR		BIT(2)
+/** Debug level : Data */
+#define DBG_DATA		BIT(3)
+/** Debug level : Command */
+#define DBG_CMD			BIT(4)
+/** Debug level : Event */
+#define DBG_EVENT		BIT(5)
+/** Debug level : Interrupt */
+#define DBG_INTR		BIT(6)
+
+/** Debug entry : Data dump */
+#define DBG_DAT_D		BIT(16)
+/** Debug entry : Data dump */
+#define DBG_CMD_D		BIT(17)
+
+/** Debug level : Entry */
+#define DBG_ENTRY		BIT(28)
+/** Debug level : Warning */
+#define DBG_WARN		BIT(29)
+/** Debug level : Informative */
+#define DBG_INFO		BIT(30)
+
+#ifdef	DEBUG_LEVEL1
+extern u32 mbt_drvdbg;
+
+#ifdef	DEBUG_LEVEL2
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  \
+	do {if (mbt_drvdbg & DBG_INFO)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...) \
+	do {if (mbt_drvdbg & DBG_WARN)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) \
+	do {if (mbt_drvdbg & DBG_ENTRY) \
+		printk(KERN_DEBUG msg); } while (0)
+#else
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  do {} while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...)  do {} while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) do {} while (0)
+#endif /* DEBUG_LEVEL2 */
+
+/** Print interrupt message */
+#define	PRINTM_INTR(msg...)  \
+	do {if (mbt_drvdbg & DBG_INTR)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print event message */
+#define	PRINTM_EVENT(msg...) \
+	do {if (mbt_drvdbg & DBG_EVENT) \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print command message */
+#define	PRINTM_CMD(msg...)   \
+	do {if (mbt_drvdbg & DBG_CMD)   \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data message */
+#define	PRINTM_DATA(msg...)  \
+	do {if (mbt_drvdbg & DBG_DATA)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print error message */
+#define	PRINTM_ERROR(msg...) \
+	do {if (mbt_drvdbg & DBG_ERROR) \
+		printk(KERN_ERR msg); } while (0)
+/** Print fatal message */
+#define	PRINTM_FATAL(msg...) \
+	do {if (mbt_drvdbg & DBG_FATAL) \
+		printk(KERN_ERR msg); } while (0)
+/** Print message */
+#define	PRINTM_MSG(msg...)   \
+	do {if (mbt_drvdbg & DBG_MSG)   \
+		printk(KERN_ALERT msg); } while (0)
+
+/** Print data dump message */
+#define	PRINTM_DAT_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_DAT_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data dump message */
+#define	PRINTM_CMD_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_CMD_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+
+/** Print message with required level */
+#define	PRINTM(level, msg...) PRINTM_##level(msg)
+
+/** Debug dump buffer length */
+#define DBG_DUMP_BUF_LEN	64
+/** Maximum number of dump per line */
+#define MAX_DUMP_PER_LINE	16
+/** Maximum data dump length */
+#define MAX_DATA_DUMP_LEN	48
+
+/**
+ * @brief Prints buffer data upto provided length
+ *
+ * @param prompt          Char pointer
+ * @param buf			  Buffer
+ * @param len    		  Length
+ *
+ * @return                N/A
+ */
+static inline void
+hexdump(char *prompt, u8 *buf, int len)
+{
+	int i;
+	char dbgdumpbuf[DBG_DUMP_BUF_LEN];
+	char *ptr = dbgdumpbuf;
+
+	printk(KERN_DEBUG "%s: len=%d\n", prompt, len);
+	for (i = 1; i <= len; i++) {
+		ptr += snprintf(ptr, 4, "%02x ", *buf);
+		buf++;
+		if (i % MAX_DUMP_PER_LINE == 0) {
+			*ptr = 0;
+			printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+			ptr = dbgdumpbuf;
+		}
+	}
+	if (len % MAX_DUMP_PER_LINE) {
+		*ptr = 0;
+		printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+	}
+}
+
+/** Debug hexdump of debug data */
+#define DBG_HEXDUMP_DAT_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_DAT_D) \
+		hexdump(x, y, z); } while (0)
+/** Debug hexdump of debug command */
+#define DBG_HEXDUMP_CMD_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_CMD_D) \
+		hexdump(x, y, z); } while (0)
+
+/** Debug hexdump */
+#define	DBG_HEXDUMP(level, x, y, z)    DBG_HEXDUMP_##level(x, y, z)
+
+/** Mark entry point */
+#define	ENTER()			PRINTM(ENTRY, "Enter: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+/** Mark exit point */
+#define	LEAVE()			PRINTM(ENTRY, "Leave: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+#else
+/** Do nothing */
+#define	PRINTM(level, msg...) do {} while (0)
+/** Do nothing */
+#define DBG_HEXDUMP(level, x, y, z)    do {} while (0)
+/** Do nothing */
+#define	ENTER()  do {} while (0)
+/** Do nothing */
+#define	LEAVE()  do {} while (0)
+#endif /* DEBUG_LEVEL1 */
+
+/** Bluetooth upload size */
+#define	BT_UPLD_SIZE				2312
+/** Bluetooth status success */
+#define BT_STATUS_SUCCESS			(0)
+/** Bluetooth status pending */
+#define BT_STATUS_PENDING           (1)
+/** Bluetooth status failure */
+#define BT_STATUS_FAILURE			(-1)
+
+#ifndef	TRUE
+/** True value */
+#define TRUE			1
+#endif
+#ifndef	FALSE
+/** False value */
+#define	FALSE			0
+#endif
+
+/** Set thread state */
+#define OS_SET_THREAD_STATE(x)		set_current_state(x)
+/** Time to wait until Host Sleep state change in millisecond */
+#define WAIT_UNTIL_HS_STATE_CHANGED 2000
+/** Time to wait cmd resp in millisecond */
+#define WAIT_UNTIL_CMD_RESP	    5000
+
+/** Sleep until a condition gets true or a timeout elapses */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	interruptible_sleep_on_timeout(&waitq, ((timeout) * HZ / 1000))
+#else
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
+#endif
+
+#define os_wait_timeout(waitq, cond, timeout) \
+         wait_event_timeout(waitq, cond, ((timeout) * HZ / 1000))
+
+/** bt thread structure */
+typedef struct {
+	/** Task */
+	struct task_struct *task;
+	/** Queue */
+	wait_queue_head_t waitQ;
+	/** PID */
+	pid_t pid;
+	/** Private structure */
+	void *priv;
+} bt_thread;
+
+/**
+ * @brief Activates bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline void
+bt_activate_thread(bt_thread *thr)
+{
+	/** Initialize the wait queue */
+	init_waitqueue_head(&thr->waitQ);
+
+	/** Record the thread pid */
+	thr->pid = current->pid;
+}
+
+/**
+ * @brief De-activates bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline void
+bt_deactivate_thread(bt_thread *thr)
+{
+	thr->pid = 0;
+	return;
+}
+
+/**
+ * @brief Creates bt thread
+ *
+ * @param btfunc          Function pointer
+ * @param thr			  A pointer to bt_thread structure
+ * @param name    		  Char pointer
+ *
+ * @return                N/A
+ */
+static inline void
+bt_create_thread(int (*btfunc) (void *), bt_thread *thr, char *name)
+{
+	thr->task = kthread_run(btfunc, thr, "%s", name);
+}
+
+/**
+ * @brief Delete bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline int
+bt_terminate_thread(bt_thread *thr)
+{
+	/* Check if the thread is active or not */
+	if (!thr->pid)
+		return -1;
+
+	kthread_stop(thr->task);
+	return 0;
+}
+
+/**
+ * @brief  Set scheduled timeout
+ *
+ * @param millisec		 Time unit in ms
+ *
+ * @return                N/A
+ */
+static inline void
+os_sched_timeout(u32 millisec)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	schedule_timeout((millisec * HZ) / 1000);
+}
+
+#ifndef __ATTRIB_ALIGN__
+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
+#endif
+
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__ __attribute__((packed))
+#endif
+
+/** Data structure for the Marvell Bluetooth device */
+typedef struct _bt_dev {
+	/** device name */
+	char name[DEV_NAME_LEN];
+	/** card pointer */
+	void *card;
+	/** IO port */
+	u32 ioport;
+	/** m_dev structure */
+	struct m_dev m_dev[MAX_RADIO_FUNC];
+
+	/** Tx download ready flag */
+	u8 tx_dnld_rdy;
+	/** Function */
+	u8 fn;
+	/** Rx unit */
+	u8 rx_unit;
+	/** Power Save mode : Timeout configuration */
+	u16 idle_timeout;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save command */
+	u8 pscmd;
+	/** Host Sleep mode */
+	u8 hsmode;
+	/** Host Sleep command */
+	u8 hscmd;
+	/** Low byte is gap, high byte is GPIO */
+	u16 gpio_gap;
+	/** Host Sleep configuration command */
+	u8 hscfgcmd;
+	/** Host Send Cmd Flag		 */
+	u8 sendcmdflag;
+	/** opcode for Send Cmd */
+	u16 send_cmd_opcode;
+	/** Device Type			*/
+	u8 devType;
+	/** Device Features    */
+	u8 devFeature;
+	/** cmd52 function */
+	u8 cmd52_func;
+	/** cmd52 register */
+	u8 cmd52_reg;
+	/** cmd52 value */
+	u8 cmd52_val;
+	/** SDIO pull control command */
+	u8 sdio_pull_ctrl;
+	/** Low 2 bytes is pullUp, high 2 bytes for pull-down */
+	u32 sdio_pull_cfg;
+	/** Test mode command */
+	u8 test_mode;
+} bt_dev_t, *pbt_dev_t;
+
+/** Marvell bt adapter structure */
+typedef struct _bt_adapter {
+	/** Chip revision ID */
+	u8 chip_rev;
+    /** magic val */
+	u8 magic_val;
+	/** Surprise removed flag */
+	u8 SurpriseRemoved;
+	/** IRQ number */
+	int irq;
+	/** Interrupt counter */
+	u32 IntCounter;
+	/** Tx packet queue */
+	struct sk_buff_head tx_queue;
+
+	/** Pointer of fw dump file name */
+	char *fwdump_fname;
+	/** Pending Tx packet queue */
+	struct sk_buff_head pending_queue;
+	/** tx lock flag */
+	u8 tx_lock;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save state */
+	u8 ps_state;
+	/** Host Sleep state */
+	u8 hs_state;
+	/** hs skip count */
+	u32 hs_skip;
+	/** suspend_fail flag */
+	u8 suspend_fail;
+	/** suspended flag */
+	u8 is_suspended;
+	/** Number of wakeup tries */
+	u8 WakeupTries;
+	/** Host Sleep wait queue */
+	wait_queue_head_t cmd_wait_q __ATTRIB_ALIGN__;
+	/** Host Cmd complet state */
+	u8 cmd_complete;
+	/** indicate using wait event timeout */
+	u8 wait_event_timeout;
+	/** last irq recv */
+	u8 irq_recv;
+	/** last irq processed */
+	u8 irq_done;
+	/** sdio int status */
+	u8 sd_ireg;
+     /** buf allocated for transmit */
+	u8 *tx_buffer;
+    /** buf for transmit */
+	u8 *tx_buf;
+    /** buf allocated for read interrupt status */
+	u8 *hw_regs_buf;
+    /** buf for read interrupt status */
+	u8 *hw_regs;
+	/** tx pending */
+	u32 skb_pending;
+/** Version string buffer length */
+#define MAX_VER_STR_LEN         128
+	/** Driver version */
+	u8 drv_ver[MAX_VER_STR_LEN];
+	/** Number of command timeout */
+	u32 num_cmd_timeout;
+} bt_adapter, *pbt_adapter;
+
+/** Length of prov name */
+#define PROC_NAME_LEN				32
+
+/** Item data structure */
+struct item_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** Size */
+	u32 size;
+	/** Address */
+	t_ptr addr;
+	/** Offset */
+	u32 offset;
+	/** Flag */
+	u32 flag;
+};
+
+/** Proc private data structure */
+struct proc_private_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** File flag */
+	u32 fileflag;
+	/** Buffer size */
+	u32 bufsize;
+	/** Number of items */
+	u32 num_items;
+	/** Item data */
+	struct item_data *pdata;
+	/** Private structure */
+	struct _bt_private *pbt;
+	/** File operations */
+	const struct file_operations *fops;
+};
+
+/** Device proc structure */
+struct device_proc {
+	/** Proc directory entry */
+	struct proc_dir_entry *proc_entry;
+	/** num of proc files */
+	u8 num_proc_files;
+	/** pointer to proc_private_data */
+	struct proc_private_data *pfiles;
+};
+
+/** Private structure for the MV device */
+typedef struct _bt_private {
+	/** Bluetooth device */
+	bt_dev_t bt_dev;
+	/** Adapter */
+	bt_adapter *adapter;
+	/** Firmware helper */
+	const struct firmware *fw_helper;
+	/** Firmware */
+	const struct firmware *firmware;
+	/** Init user configure file */
+	const struct firmware *init_user_cfg;
+	/** Init user configure wait queue token */
+	u16 init_user_conf_wait_flag;
+	/** Init user configure file wait queue */
+	wait_queue_head_t init_user_conf_wait_q __ATTRIB_ALIGN__;
+	/** Firmware request start time */
+	struct timeval req_fw_time;
+	/** Hotplug device */
+	struct device *hotplug_device;
+	/** thread to service interrupts */
+	bt_thread MainThread;
+	 /** proc data */
+	struct device_proc dev_proc[MAX_RADIO_FUNC];
+	/** Driver lock */
+	spinlock_t driver_lock;
+	/** Driver lock flags */
+	ulong driver_flags;
+	/** Driver reference flags */
+	struct kobject kobj;
+	/** CRC check flag */
+	u16 fw_crc_check;
+	/** Card type */
+	u16 card_type;
+	/** sdio device */
+	const struct sdio_device *psdio_device;
+	int debug_device_pending;
+	int debug_ocf_ogf[2];
+	u8 fw_reload;
+#ifdef BLE_WAKEUP
+	u8 ble_wakeup_buf_size;
+	u8 *ble_wakeup_buf;
+    /** white list address: address count + count* address*/
+	u8 white_list[61];
+#endif
+    /** fw dump state */
+	u8 fw_dump;
+} bt_private, *pbt_private;
+
+/** Disable interrupt */
+#define OS_INT_DISABLE	spin_lock_irqsave(&priv->driver_lock, \
+						priv->driver_flags)
+/** Enable interrupt */
+#define	OS_INT_RESTORE	spin_unlock_irqrestore(&priv->driver_lock, \
+						priv->driver_flags)
+
+#ifndef HCI_BT_AMP
+/** BT_AMP flag for device type */
+#define  HCI_BT_AMP		0x80
+#endif
+
+/** Device type of BT */
+#define DEV_TYPE_BT		0x00
+/** Device type of AMP */
+#define DEV_TYPE_AMP		0x01
+
+/** Marvell vendor packet */
+#define MRVL_VENDOR_PKT			0xFE
+
+/** Bluetooth command : Get FW Version */
+#define BT_CMD_GET_FW_VERSION       0x0F
+/** Bluetooth command : Sleep mode */
+#define BT_CMD_AUTO_SLEEP_MODE		0x23
+/** Bluetooth command : Host Sleep configuration */
+#define BT_CMD_HOST_SLEEP_CONFIG	0x59
+/** Bluetooth command : Host Sleep enable */
+#define BT_CMD_HOST_SLEEP_ENABLE	0x5A
+/** Bluetooth command : Module Configuration request */
+#define BT_CMD_MODULE_CFG_REQ		0x5B
+#ifdef BLE_WAKEUP
+/** Bluetooth command : Get whitelist */
+#define BT_CMD_GET_WHITELIST        0x9C
+
+#define HCI_BLE_GRP_BLE_CMDS                 0x08
+#define HCI_BT_SET_EVENTMASK_OCF           0x0001
+#define HCI_BLE_ADD_DEV_TO_WHITELIST_OCF     0x0011
+#define HCI_BLE_SET_SCAN_PARAMETERS_OCF      0x000B
+#define HCI_BLE_SET_SCAN_ENABLE_OCF          0x000C
+
+#endif
+/** Bluetooth command : PMIC Configure */
+#define BT_CMD_PMIC_CONFIGURE           0x7D
+
+/** Bluetooth command : SDIO pull up down configuration request */
+#define BT_CMD_SDIO_PULL_CFG_REQ	0x69
+/** Bluetooth command : Set Evt Filter Command */
+#define BT_CMD_SET_EVT_FILTER		0x05
+/** Bluetooth command : Enable Write Scan Command */
+#define BT_CMD_ENABLE_WRITE_SCAN	0x1A
+/** Bluetooth command : Enable Device under test mode */
+#define BT_CMD_ENABLE_DEVICE_TESTMODE	0x03
+/** Sub Command: Module Bring Up Request */
+#define MODULE_BRINGUP_REQ		0xF1
+/** Sub Command: Module Shut Down Request */
+#define MODULE_SHUTDOWN_REQ		0xF2
+/** Module already up */
+#define MODULE_CFG_RESP_ALREADY_UP      0x0c
+/** Sub Command: Host Interface Control Request */
+#define MODULE_INTERFACE_CTRL_REQ	0xF5
+
+/** Bluetooth event : Power State */
+#define BT_EVENT_POWER_STATE		0x20
+
+/** Bluetooth Power State : Enable */
+#define BT_PS_ENABLE			0x02
+/** Bluetooth Power State : Disable */
+#define BT_PS_DISABLE			0x03
+/** Bluetooth Power State : Sleep */
+#define BT_PS_SLEEP			0x01
+/** Bluetooth Power State : Awake */
+#define BT_PS_AWAKE			0x02
+
+/** Vendor OGF */
+#define VENDOR_OGF				0x3F
+/** OGF for reset */
+#define RESET_OGF		0x03
+/** Bluetooth command : Reset */
+#define BT_CMD_RESET	0x03
+
+/** Host Sleep activated */
+#define HS_ACTIVATED			0x01
+/** Host Sleep deactivated */
+#define HS_DEACTIVATED			0x00
+
+/** Power Save sleep */
+#define PS_SLEEP			0x01
+/** Power Save awake */
+#define PS_AWAKE			0x00
+
+/** bt header length */
+#define BT_HEADER_LEN			4
+
+#ifndef MAX
+/** Return maximum of two */
+#define MAX(a, b)		((a) > (b) ? (a) : (b))
+#endif
+
+/** This is for firmware specific length */
+#define EXTRA_LEN	36
+
+/** Command buffer size for Marvell driver */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+
+/** Bluetooth Rx packet buffer size for Marvell driver */
+#define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \
+	(HCI_MAX_FRAME_SIZE + EXTRA_LEN)
+
+/** Buffer size to allocate */
+#define ALLOC_BUF_SIZE	(((MAX(MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \
+			MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \
+			+ SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
+
+/** Request FW timeout in second */
+#define REQUEST_FW_TIMEOUT		30
+
+/** 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
+
+/** default idle time */
+#define DEFAULT_IDLE_TIME           1000
+
+#define BT_CMD_HEADER_SIZE    3
+
+#define BT_CMD_DATA_LEN    128
+#define BT_EVT_DATA_LEN    8
+
+/** BT command structure */
+typedef struct _BT_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[BT_CMD_DATA_LEN];
+} __ATTRIB_PACK__ BT_CMD;
+
+/** BT event structure */
+typedef struct _BT_EVENT {
+	/** Event Counter */
+	u8 EC;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[BT_EVT_DATA_LEN];
+} BT_EVENT;
+
+#if defined(SDIO_SUSPEND_RESUME)
+#define DEF_GPIO_GAP        0xffff
+#endif
+
+#ifdef BLE_WAKEUP
+#define BD_ADDR_SIZE 6
+/** Vendor specific event */
+#define VENDOR_SPECIFIC_EVENT     0xff
+/** system suspend event */
+#define HCI_SYSTEM_SUSPEND_EVT    0x80
+/** system suspend */
+#define HCI_SYSTEM_SUSPEND        0x00
+/** system resume */
+#define HCI_SYSTEM_RESUME         0x01
+/** This function enables ble wake up pattern */
+int bt_config_ble_wakeup(bt_private *priv, bool is_shutdown);
+int bt_send_system_event(bt_private *priv, u8 flag);
+void bt_send_hw_remove_event(bt_private *priv);
+#endif
+
+/** This function verify the received event pkt */
+int check_evtpkt(bt_private *priv, struct sk_buff *skb);
+
+/* Prototype of global function */
+/** This function gets the priv reference */
+struct kobject *bt_priv_get(bt_private *priv);
+/** This function release the priv reference */
+void bt_priv_put(bt_private *priv);
+/** This function adds the card */
+bt_private *bt_add_card(void *card);
+/** This function removes the card */
+int bt_remove_card(void *card);
+/** This function handles the interrupt */
+void bt_interrupt(struct m_dev *m_dev);
+
+/** This function creates proc interface directory structure */
+int bt_root_proc_init(void);
+/** This function removes proc interface directory structure */
+int bt_root_proc_remove(void);
+/** This function initializes proc entry */
+int bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq);
+/** This function removes proc interface */
+void bt_proc_remove(bt_private *priv);
+
+/** This function process the received event */
+int bt_process_event(bt_private *priv, struct sk_buff *skb);
+/** This function enables host sleep */
+int bt_enable_hs(bt_private *priv, bool is_shutdown);
+/** This function used to send command to firmware */
+int bt_prepare_command(bt_private *priv);
+/** This function frees the structure of adapter */
+void bt_free_adapter(bt_private *priv);
+/** This function handle the receive packet */
+void bt_recv_frame(bt_private *priv, struct sk_buff *skb);
+void bt_store_firmware_dump(bt_private *priv, u8 *buf, u32 len);
+
+/** clean up m_devs */
+void clean_up_m_devs(bt_private *priv);
+/** bt driver call this function to register to bus driver */
+int *sbi_register(void);
+/** bt driver call this function to unregister to bus driver */
+void sbi_unregister(void);
+/** bt driver calls this function to register the device  */
+int sbi_register_dev(bt_private *priv);
+/** bt driver calls this function to unregister the device */
+int sbi_unregister_dev(bt_private *priv);
+/** This function initializes firmware */
+int sbi_download_fw(bt_private *priv);
+/** Configures hardware to quit deep sleep state */
+int sbi_wakeup_firmware(bt_private *priv);
+/** Module configuration and register device */
+int sbi_register_conf_dpc(bt_private *priv);
+
+/** This function is used to send the data/cmd to hardware */
+int sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb);
+/** This function reads the current interrupt status register */
+int sbi_get_int_status(bt_private *priv);
+/** This function enables the host interrupts */
+int sbi_enable_host_int(bt_private *priv);
+/** This function disables the host interrupts */
+int sbi_disable_host_int(bt_private *priv);
+
+/** bt fw reload flag */
+extern int bt_fw_reload;
+/** 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
+/** This function reload firmware */
+void bt_request_fw_reload(bt_private *priv, int mode);
+#define MAX_TX_BUF_SIZE     2312
+/** This function downloads firmware image to the card */
+int sd_download_firmware_w_helper(bt_private *priv);
+void bt_dump_sdio_regs(bt_private *priv);
+#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
+/* dumps the firmware to /var/ or /data/ */
+void bt_dump_firmware_info_v2(bt_private *priv);
+
+/** 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
+
+/** Bluetooth command : Mac address configuration */
+#define BT_CMD_CONFIG_MAC_ADDR		0x22
+/** Bluetooth command : Write CSU register */
+#define BT_CMD_CSU_WRITE_REG		0x66
+/** Bluetooth command : Load calibrate data */
+#define BT_CMD_LOAD_CONFIG_DATA     0x61
+/** Bluetooth command : Load calibrate ext data */
+#define BT_CMD_LOAD_CONFIG_DATA_EXT     0x60
+
+/** Bluetooth command : BLE deepsleep */
+#define BT_CMD_BLE_DEEP_SLEEP       0x8b
+
+/** BT_BLE command structure */
+typedef struct _BT_BLE_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** deepsleep flag */
+	u8 deepsleep;
+} __ATTRIB_PACK__ BT_BLE_CMD;
+
+/** BT_CSU command structure */
+typedef struct _BT_CSU_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** reg type */
+	u8 type;
+	/** address */
+	u8 offset[4];
+	/** Data */
+	u8 value[2];
+} __ATTRIB_PACK__ BT_CSU_CMD;
+
+/** This function sets mac address */
+int bt_set_mac_address(bt_private *priv, u8 *mac);
+/** This function writes value to CSU registers */
+int bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value);
+/** BT set user defined init data and param */
+int bt_init_config(bt_private *priv, char *cfg_file);
+/** BT set uer defined init commands */
+int bt_init_cmds(bt_private *priv, char *init_cmds_file);
+/** BT process command */
+int bt_process_commands(bt_private *priv, u8 *cmd_data, u32 cmd_len);
+/** BT PMIC Configure command */
+int bt_pmic_configure(bt_private *priv);
+/** This function load the calibrate data */
+int bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac);
+/** This function load the calibrate ext data */
+int bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len);
+/** BT set user defined calibration data */
+int bt_cal_config(bt_private *priv, char *cfg_file, char *mac);
+/** BT set user defined calibration ext data */
+int bt_cal_config_ext(bt_private *priv, char *cfg_file);
+int bt_init_mac_address(bt_private *priv, char *mac);
+
+int bt_set_independent_reset(bt_private *priv);
+/** Bluetooth command : Independent reset */
+#define BT_CMD_INDEPENDENT_RESET     0x0D
+
+/** BT HCI command structure */
+typedef struct _BT_HCI_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** cmd type */
+	u8 cmd_type;
+	/** cmd len */
+	u8 cmd_len;
+	/** Data */
+	u8 data[6];
+} __ATTRIB_PACK__ BT_HCI_CMD;
+
+#endif /* _BT_DRV_H_ */
diff --git a/bt_sd8987/bt_char/bt_init.c b/bt_sd8987/bt_char/bt_init.c
new file mode 100644
index 0000000..270a4aa
--- /dev/null
+++ b/bt_sd8987/bt_char/bt_init.c
@@ -0,0 +1,871 @@
+/** @file bt_init.c
+  *
+  * @brief This file contains the init functions for BlueTooth
+  * driver.
+  *
+  * Copyright (C) 2011-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/string.h>
+#include <linux/firmware.h>
+
+#include "bt_drv.h"
+
+extern int bt_req_fw_nowait;
+
+#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
+			 || ('a' <= (c) && (c) <= 'f') \
+			 || ('A' <= (c) && (c) <= 'F'))
+
+#define isdigit(c)	(('0' <= (c) && (c) <= '9'))
+#define isspace(c)  (c <= ' ' && (c == ' ' || (c <= 13 && c >= 9)))
+/**
+ *  @brief Returns hex value of a give character
+ *
+ *  @param chr	Character to be converted
+ *
+ *  @return	The converted character if chr is a valid hex, else 0
+ */
+static int
+bt_hexval(char chr)
+{
+	ENTER();
+
+	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;
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @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
+ */
+static char *
+bt_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 Returns hex value of a given ascii string
+ *
+ *  @param a	String to be converted
+ *
+ *  @return	hex value
+ */
+static int
+bt_atox(const char *a)
+{
+	int i = 0;
+	ENTER();
+	while (isxdigit(*a))
+		i = i * 16 + bt_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief Converts 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
+ */
+static void
+bt_mac2u8(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;
+	}
+	memcpy(mac_buff, buf, strlen(buf));
+
+	begin = mac_buff;
+	for (i = 0; i < ETH_ALEN; ++i) {
+		end = bt_strsep(&begin, ':', '/');
+		if (end)
+			mac_addr[i] = bt_atox(end);
+	}
+
+	kfree(mac_buff);
+	LEAVE();
+}
+
+/**
+ *  @brief Returns integer value of a given ascii string
+ *
+ *  @param data    Converted data to be returned
+ *  @param a       String to be converted
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_atoi(int *data, char *a)
+{
+	int i, val = 0, len;
+
+	ENTER();
+
+	len = strlen(a);
+	if (!strncmp(a, "0x", 2)) {
+		a = a + 2;
+		len -= 2;
+		*data = bt_atox(a);
+		return BT_STATUS_SUCCESS;
+	}
+	for (i = 0; i < len; i++) {
+		if (isdigit(a[i])) {
+			val = val * 10 + (a[i] - '0');
+		} else {
+			PRINTM(ERROR, "Invalid char %c in string %s\n", a[i],
+			       a);
+			return BT_STATUS_FAILURE;
+		}
+	}
+	*data = val;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief parse cal-data
+ *
+ *  @param src      a pointer to cal-data string
+ *  @param len      len of cal-data
+ *  @param dst      a pointer to return cal-data
+ *  @param dst_size size of dest buffer
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 *dst_size)
+{
+	const u8 *ptr;
+	u8 *dptr;
+	u32 count = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	ptr = src;
+	dptr = dst;
+
+	while ((ptr - src) < len) {
+		if (*ptr && isspace(*ptr)) {
+			ptr++;
+			continue;
+		}
+
+		if (isxdigit(*ptr)) {
+			if ((dptr - dst) >= *dst_size) {
+				PRINTM(ERROR, "cal_file size too big!!!\n");
+				goto done;
+			}
+			*dptr++ = bt_atox((const char *)ptr);
+			ptr += 2;
+			count++;
+		} else {
+			ptr++;
+		}
+	}
+	if (dptr == dst) {
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	*dst_size = count;
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief parse ASCII format raw data to hex format
+ *
+ *    @param priv         bt_private
+ *    @param data         Source data
+ *    @param size         Source data length
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+bt_process_init_raw_cmds(bt_private *priv, u8 *data, u32 size)
+{
+	int ret = 0;
+	u8 *pos = data;
+	u8 *intf_s, *intf_e;
+	u8 *buf = NULL;
+	u8 *ptr = NULL;
+	u8 cmd_len = 0;
+	bool start_raw = false;
+	gfp_t flag;
+
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	buf = kzalloc(MRVDRV_SIZE_OF_CMD_BUFFER, flag);
+
+	if (!buf) {
+		PRINTM(ERROR, "Could not allocate buffer space!\n");
+		return -EFAULT;
+	}
+	ptr = buf;
+	while ((pos - data) < size) {
+		while ((*pos == ' ' || *pos == '\t') && ((pos - data) < size))
+			pos++;
+		if (*pos == '#') {	/* Line comment */
+			while ((*pos != '\n') && ((pos - data) < size))
+				pos++;
+			pos++;
+		}
+		if ((*pos == '\r' && *(pos + 1) == '\n') || *pos == '\n' ||
+		    *pos == '\0') {
+			pos++;
+			continue;	/* Needn't process this line */
+		}
+
+		if (*pos == '}') {
+			/* For hostcmd data conf */
+			cmd_len = *(buf + sizeof(u16));
+			ret = bt_process_commands(priv, buf,
+						  cmd_len + BT_CMD_HEADER_SIZE);
+			memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+			ptr = buf;
+			start_raw = false;
+			pos++;
+			continue;
+		}
+
+		if (start_raw == false) {
+			intf_s = strchr(pos, '=');
+			if (intf_s)
+				intf_e = strchr(intf_s, '{');
+			else
+				intf_e = NULL;
+
+			if (intf_s && intf_e) {
+				start_raw = true;
+				pos = intf_e + 1;
+				continue;
+			}
+		}
+
+		if (start_raw) {
+			/* Raw data block exists */
+			while ((*pos != '\n') && ((pos - data) < size)) {
+				if (isxdigit(*pos)) {
+					if((ptr-buf) < MRVDRV_SIZE_OF_CMD_BUFFER)
+						*ptr++ = bt_atox(pos);
+					pos += 2;
+				} else
+					pos++;
+			}
+		}
+	}
+	kfree(buf);
+	return ret;
+}
+
+/**
+ *    @brief BT set user init commands
+ *
+ *    @param priv     BT private handle
+ *    @param init_cmds_file user init commands file
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+
+int
+bt_init_cmds(bt_private *priv, char *init_cmds_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if ((request_firmware(&cfg, init_cmds_file, priv->hotplug_device)) < 0) {
+		PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+		       init_cmds_file);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (cfg) {
+		ret = bt_process_init_raw_cmds(priv, (u8 *)cfg->data,
+					       cfg->size);
+	}
+	else {
+		ret = BT_STATUS_FAILURE;
+	}
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT get one line data from ASCII format data
+ *
+ *    @param data         Source data
+ *    @param size         Source data length
+ *    @param line_pos     Destination data
+ *    @return             -1 or length of the line
+ */
+int
+parse_cfg_get_line(u8 *data, u32 size, u8 *line_pos)
+{
+	static s32 pos;
+	u8 *src, *dest;
+
+	if (pos >= size) {	/* reach the end */
+		pos = 0;	/* Reset position for rfkill */
+		return -1;
+	}
+	memset(line_pos, 0, MAX_LINE_LEN);
+	src = data + pos;
+	dest = line_pos;
+
+	while ((dest - line_pos < MAX_LINE_LEN - 1) && pos < size &&
+	       *src != '\x0A' && *src != '\0') {
+		if (*src != ' ' && *src != '\t')	/* parse space */
+			*dest++ = *src++;
+		else
+			src++;
+		pos++;
+	}
+	*dest = '\0';
+	/* parse new line */
+	pos++;
+	return strlen((const char *)line_pos);
+}
+
+/**
+ *    @brief BT parse ASCII format data to MAC address
+ *
+ *    @param priv          BT private handle
+ *    @param data          Source data
+ *    @param size          data length
+ *    @return              BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_init_cfg(bt_private *priv, u8 *data, u32 size)
+{
+	u8 *pos;
+	u8 *intf_s, *intf_e;
+	u8 s[MAX_LINE_LEN];	/* 1 line data */
+	u32 line_len;
+	char dev_name[MAX_PARAM_LEN];
+	u8 buf[MAX_PARAM_LEN];
+	u8 bt_addr[MAX_MAC_ADDR_LEN];
+	u8 bt_mac[ETH_ALEN];
+	int setting = 0;
+	u8 type = 0;
+	u16 value = 0;
+	u32 offset = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	memset(dev_name, 0, sizeof(dev_name));
+	memset(bt_addr, 0, sizeof(bt_addr));
+	memset(bt_mac, 0, sizeof(bt_mac));
+
+	while ((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;	/* Need n't process this line */
+
+		/* Process MAC addr */
+		if (strncmp((char *)pos, "mac_addr", 8) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ':');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				if ((intf_e - intf_s) > MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Too long interface name %d\n",
+					       __LINE__);
+					goto done;
+				}
+				strncpy(dev_name, (const char *)intf_s + 1,
+					intf_e - intf_s - 1);
+				dev_name[intf_e - intf_s - 1] = '\0';
+				strncpy((char *)bt_addr,
+					(const char *)intf_e + 1,
+					MAX_MAC_ADDR_LEN - 1);
+				bt_addr[MAX_MAC_ADDR_LEN - 1] = '\0';
+				/* Convert MAC format */
+				bt_mac2u8(bt_mac, (char *)bt_addr);
+				PRINTM(CMD,
+				       "HCI: %s new BT Address " MACSTR "\n",
+				       dev_name, MAC2STR(bt_mac));
+				if (BT_STATUS_SUCCESS !=
+				    bt_set_mac_address(priv, bt_mac)) {
+					PRINTM(FATAL,
+					       "BT: Fail to set mac address\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+		}
+		/* Process REG value */
+		else if (strncmp((char *)pos, "bt_reg", 6) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ',');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				/* Copy type */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s + 1,
+					1);
+				buf[1] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					type = (u8)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg type\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			intf_e = (u8 *)strchr((const char *)intf_s, ',');
+			if (intf_e != NULL) {
+				if ((intf_e - intf_s) >= MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Regsier offset is too long %d\n",
+					       __LINE__);
+					goto done;
+				}
+				/* Copy offset */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s,
+					intf_e - intf_s);
+				buf[intf_e - intf_s] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					offset = (u32)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg offset\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			if ((strlen((const char *)intf_s) >= MAX_PARAM_LEN)) {
+				PRINTM(ERROR,
+				       "BT: Regsier value is too long %d\n",
+				       __LINE__);
+				goto done;
+			}
+			/* Copy value */
+			memset(buf, 0, sizeof(buf));
+			strncpy((char *)buf, (const char *)intf_s, sizeof(buf));
+			if (0 == bt_atoi(&setting, (char *)buf))
+				value = (u16) setting;
+			else {
+				PRINTM(ERROR, "BT: Fail to parse reg value\n");
+				goto done;
+			}
+
+			PRINTM(CMD,
+			       "BT: Write reg type: %d offset: 0x%x value: 0x%x\n",
+			       type, offset, value);
+			if (BT_STATUS_SUCCESS !=
+			    bt_write_reg(priv, type, offset, value)) {
+				PRINTM(FATAL,
+				       "BT: Write reg failed. type: %d offset: 0x%x value: 0x%x\n",
+				       type, offset, value);
+				goto done;
+			}
+		}
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief BT 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 bt_private structure
+ *
+ * @return          N/A
+ */
+static void
+bt_request_init_user_conf_callback(const struct firmware *firmware,
+				   void *context)
+{
+	bt_private *priv = (bt_private *)context;
+
+	ENTER();
+
+	if (!firmware)
+		PRINTM(ERROR, "BT user init config request firmware failed\n");
+
+	priv->init_user_cfg = firmware;
+	priv->init_user_conf_wait_flag = TRUE;
+	wake_up_interruptible(&priv->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *    @brief BT set user defined init data and param
+ *
+ *    @param priv     BT private handle
+ *    @param cfg_file user cofig file
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_config(bt_private *priv, char *cfg_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if ((request_firmware(&cfg, cfg_file, priv->hotplug_device)) < 0) {
+		PRINTM(FATAL, "BT: request_firmware() %s failed\n", cfg_file);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (cfg)
+		ret = bt_process_init_cfg(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg(bt_private *priv, u8 *data, u32 size, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	u8 cal_data[32];
+	u8 *mac_data = NULL;
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+	u8 *pcal_data = cal_data;
+
+	memset(bt_mac, 0, sizeof(bt_mac));
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (mac != NULL) {
+		/* Convert MAC format */
+		bt_mac2u8(bt_mac, mac);
+		PRINTM(CMD, "HCI: new BT Address " MACSTR "\n",
+		       MAC2STR(bt_mac));
+		mac_data = bt_mac;
+	}
+	if (BT_STATUS_SUCCESS != bt_load_cal_data(priv, pcal_data, mac_data)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg_ext(bt_private *priv, u8 *data, u32 size)
+{
+	u8 cal_data[128];
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (BT_STATUS_SUCCESS !=
+	    bt_load_cal_data_ext(priv, cal_data, cal_data_len)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config(bt_private *priv, char *cal_file, char *mac)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size, mac);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config_ext(bt_private *priv, char *cal_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config_ext() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg_ext(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT init mac address from bt_mac parametre when insmod
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param bt_mac  mac address buf
+ *    @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_mac_address(bt_private *priv, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	memset(bt_mac, 0, sizeof(bt_mac));
+	bt_mac2u8(bt_mac, mac);
+	PRINTM(CMD, "HCI: New BT Address " MACSTR "\n", MAC2STR(bt_mac));
+	ret = bt_set_mac_address(priv, bt_mac);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(FATAL,
+		       "BT: Fail to set mac address from insmod parametre.\n");
+
+	LEAVE();
+	return ret;
+}
diff --git a/bt_sd8987/bt_char/bt_main.c b/bt_sd8987/bt_char/bt_main.c
new file mode 100644
index 0000000..ffd0936
--- /dev/null
+++ b/bt_sd8987/bt_char/bt_main.c
@@ -0,0 +1,4083 @@
+/** @file bt_main.c
+  *
+  * @brief This file contains the major functions in BlueTooth
+  * driver. It includes init, exit, open, close and main
+  * thread etc..
+  *
+  * Copyright (C) 2007-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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.
+  *
+  */
+/**
+  * @mainpage M-BT Linux Driver
+  *
+  * @section overview_sec Overview
+  *
+  * The M-BT is a Linux reference driver for Marvell Bluetooth chipset.
+  *
+  * @section copyright_sec Copyright
+  *
+  * Copyright (C) 2007-2019, Marvell International Ltd.
+  *
+  */
+#include <linux/module.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
+
+#include <linux/mmc/sdio_func.h>
+
+#include "bt_drv.h"
+#include "mbt_char.h"
+#include "bt_sdio.h"
+
+/** Version */
+#define VERSION "C4X14114"
+
+/** Driver version */
+static char mbt_driver_version[] = "SD8XXX-%s-" VERSION "-(" "FP" FPNUM ")"
+#ifdef DEBUG_LEVEL2
+	"-dbg"
+#endif
+	" ";
+
+/** SD8787 Card */
+#define CARD_SD8787     "SD8787"
+/** SD8777 Card */
+#define CARD_SD8777     "SD8777"
+/** SD8887 Card */
+#define CARD_SD8887     "SD8887"
+/** SD8897 Card */
+#define CARD_SD8897     "SD8897"
+/** SD8797 Card */
+#define CARD_SD8797     "SD8797"
+/** SD8977 Card */
+#define CARD_SD8977     "SD8977"
+/** SD8978 Card */
+#define CARD_SD8978     "SD8978"
+/** SD8997 Card */
+#define CARD_SD8997     "SD8997"
+/** SD8987 Card */
+#define CARD_SD8987     "SD8987"
+
+/** Declare and initialize fw_version */
+static char fw_version[32] = "0.0.0.p0";
+
+#define AID_SYSTEM        1000	/* system server */
+
+#define AID_BLUETOOTH     1002	/* bluetooth subsystem */
+
+#define AID_NET_BT_STACK  3008	/* bluetooth stack */
+
+/** Define module name */
+
+#define MODULE_NAME  "bt_fm_nfc"
+
+/** Declaration of chardev class */
+static struct class *chardev_class;
+
+/** Interface specific variables */
+static int mbtchar_minor;
+static int debugchar_minor;
+
+/**
+ * The global variable of a pointer to bt_private
+ * structure variable
+ **/
+bt_private *m_priv[MAX_BT_ADAPTER];
+
+/** Default Driver mode */
+static int drv_mode = (DRV_MODE_BT);
+
+/** BT interface name */
+static char *bt_name;
+/** BT debug interface name */
+static char *debug_name;
+
+/** fw reload flag */
+int bt_fw_reload;
+/** fw serial download flag */
+int bt_fw_serial = 1;
+
+/** Firmware flag */
+static int fw = 1;
+/** default powermode */
+static int psmode = 1;
+/** default BLE deep sleep */
+static int deep_sleep = 1;
+/** Default CRC check control */
+static int fw_crc_check = 1;
+/** init cmds file */
+static char *init_cmds;
+/** Init config file (MAC address, register etc.) */
+static char *init_cfg;
+/** Calibration config file (MAC address, init powe etc.) */
+static char *cal_cfg;
+/** Calibration config file EXT */
+static char *cal_cfg_ext;
+/** Init MAC address */
+static char *bt_mac;
+static int btindrst = -1;
+
+/** Setting mbt_drvdbg value based on DEBUG level */
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define DEFAULT_DEBUG_MASK  (0xffffffff & ~DBG_EVENT)
+#else
+#define DEFAULT_DEBUG_MASK  (DBG_MSG | DBG_FATAL | DBG_ERROR)
+#endif /* DEBUG_LEVEL2 */
+u32 mbt_drvdbg = DEFAULT_DEBUG_MASK;
+#endif
+
+#ifdef CONFIG_OF
+static int dts_enable = 1;
+#endif
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+int mbt_pm_keep_power = 1;
+#endif
+
+static int debug_intf = 1;
+
+static int btpmic = 0;
+
+/** Offset of sequence number in event */
+#define OFFSET_SEQNUM 4
+
+/**
+ *  @brief handle received packet
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *
+ *  @return        N/A
+ */
+void
+bt_recv_frame(bt_private *priv, struct sk_buff *skb)
+{
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		mdev_bt->stat.byte_rx += skb->len;
+		mdev_recv_frame(skb);
+	}
+	return;
+}
+
+/**
+ *  @brief Alloc bt device
+ *
+ *  @return    pointer to structure mbt_dev or NULL
+ */
+struct mbt_dev *
+alloc_mbt_dev(void)
+{
+	struct mbt_dev *mbt_dev;
+	ENTER();
+
+	mbt_dev = kzalloc(sizeof(struct mbt_dev), GFP_KERNEL);
+	if (!mbt_dev) {
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return mbt_dev;
+}
+
+/**
+ *  @brief Alloc debug device
+ *
+ *  @return    pointer to structure debug_level or NULL
+ */
+struct debug_dev *
+alloc_debug_dev(void)
+{
+	struct debug_dev *debug_dev;
+	ENTER();
+
+	debug_dev = kzalloc(sizeof(struct debug_dev), GFP_KERNEL);
+	if (!debug_dev) {
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return debug_dev;
+}
+
+/**
+ *  @brief Frees m_dev
+ *
+ *  @return    N/A
+ */
+void
+free_m_dev(struct m_dev *m_dev)
+{
+	ENTER();
+	kfree(m_dev->dev_pointer);
+	m_dev->dev_pointer = NULL;
+	LEAVE();
+}
+
+/**
+ *  @brief clean up m_devs
+ *
+ *  @return    N/A
+ */
+void
+clean_up_m_devs(bt_private *priv)
+{
+	struct m_dev *m_dev = NULL;
+	int i;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+		PRINTM(MSG, "BT: Delete %s\n", m_dev->name);
+		if (m_dev->spec_type == IANYWHERE_SPEC) {
+			if ((drv_mode & DRV_MODE_BT) && (mbtchar_minor > 0))
+				mbtchar_minor--;
+			m_dev->close(m_dev);
+			for (i = 0; i < 3; i++)
+				kfree_skb(((struct mbt_dev *)
+					   (m_dev->dev_pointer))->
+					  reassembly[i]);
+			/**  unregister m_dev to char_dev */
+			if (chardev_class)
+				chardev_cleanup_one(m_dev, chardev_class);
+			free_m_dev(m_dev);
+		}
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = NULL;
+	}
+	if (priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer) {
+		m_dev = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
+		PRINTM(MSG, "BT: Delete %s\n", m_dev->name);
+		if ((debug_intf) && (debugchar_minor > 0))
+			debugchar_minor--;
+		/** unregister m_dev to char_dev */
+		if (chardev_class)
+			chardev_cleanup_one(m_dev, chardev_class);
+		free_m_dev(m_dev);
+		priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer = NULL;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function verify the received event pkt
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+--------+
+ *  | Event  | Length |  ncmd  |      Opcode     |
+ *  +--------+--------+--------+--------+--------+
+ *  | 1-byte | 1-byte | 1-byte |      2-byte     |
+ *  +--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+check_evtpkt(bt_private *priv, struct sk_buff *skb)
+{
+	struct hci_event_hdr *hdr = (struct hci_event_hdr *)skb->data;
+	struct hci_ev_cmd_complete *ec;
+	u16 opcode, ocf;
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (!priv->bt_dev.sendcmdflag) {
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	if (hdr->evt == HCI_EV_CMD_COMPLETE) {
+		ec = (struct hci_ev_cmd_complete *)
+			(skb->data + HCI_EVENT_HDR_SIZE);
+		opcode = __le16_to_cpu(ec->opcode);
+		ocf = hci_opcode_ocf(opcode);
+		PRINTM(CMD,
+		       "BT: CMD_COMPLTE opcode=0x%x, ocf=0x%x, send_cmd_opcode=0x%x\n",
+		       opcode, ocf, priv->bt_dev.send_cmd_opcode);
+		if (opcode != priv->bt_dev.send_cmd_opcode) {
+			ret = BT_STATUS_FAILURE;
+			goto exit;
+		}
+		switch (ocf) {
+		case BT_CMD_MODULE_CFG_REQ:
+		case BT_CMD_BLE_DEEP_SLEEP:
+		case BT_CMD_CONFIG_MAC_ADDR:
+		case BT_CMD_CSU_WRITE_REG:
+		case BT_CMD_LOAD_CONFIG_DATA:
+		case BT_CMD_LOAD_CONFIG_DATA_EXT:
+		case BT_CMD_AUTO_SLEEP_MODE:
+		case BT_CMD_HOST_SLEEP_CONFIG:
+		case BT_CMD_SDIO_PULL_CFG_REQ:
+		case BT_CMD_SET_EVT_FILTER:
+			// case BT_CMD_ENABLE_DEVICE_TESTMODE:
+		case BT_CMD_PMIC_CONFIGURE:
+		case BT_CMD_INDEPENDENT_RESET:
+			priv->bt_dev.sendcmdflag = FALSE;
+			priv->adapter->cmd_complete = TRUE;
+			wake_up_interruptible(&priv->adapter->cmd_wait_q);
+			break;
+		case BT_CMD_GET_FW_VERSION:
+			{
+				u8 *pos = (skb->data + HCI_EVENT_HDR_SIZE +
+					   sizeof(struct hci_ev_cmd_complete) +
+					   1);
+				snprintf(fw_version, sizeof(fw_version),
+					 "%u.%u.%u.p%u", pos[2], pos[1], pos[0],
+					 pos[3]);
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+				break;
+			}
+#ifdef BLE_WAKEUP
+		case BT_CMD_GET_WHITELIST:
+			{
+				u8 *pos = (skb->data + HCI_EVENT_HDR_SIZE +
+					   sizeof(struct hci_ev_cmd_complete) +
+					   1);
+
+				if ((hdr->plen -
+				     sizeof(struct hci_ev_cmd_complete) - 1) <=
+				    sizeof(priv->white_list))
+					memcpy(priv->white_list, pos,
+					       hdr->plen -
+					       sizeof(struct
+						      hci_ev_cmd_complete) - 1);
+
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+				break;
+			}
+#endif
+		case BT_CMD_RESET:
+		case BT_CMD_ENABLE_WRITE_SCAN:
+#ifdef BLE_WAKEUP
+		case HCI_BT_SET_EVENTMASK_OCF:
+		case HCI_BLE_ADD_DEV_TO_WHITELIST_OCF:
+		case HCI_BLE_SET_SCAN_PARAMETERS_OCF:
+		case HCI_BLE_SET_SCAN_ENABLE_OCF:
+#endif
+			{
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				if (priv->adapter->wait_event_timeout == TRUE) {
+					wake_up(&priv->adapter->cmd_wait_q);
+					priv->adapter->wait_event_timeout =
+						FALSE;
+				} else
+					wake_up_interruptible(&priv->adapter->
+							      cmd_wait_q);
+			}
+			break;
+		case BT_CMD_HOST_SLEEP_ENABLE:
+			priv->bt_dev.sendcmdflag = FALSE;
+			break;
+		default:
+			/** Ignore command not defined but send by driver */
+			if (opcode == priv->bt_dev.send_cmd_opcode) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			} else {
+				ret = BT_STATUS_FAILURE;
+			}
+			break;
+		}
+	} else
+		ret = BT_STATUS_FAILURE;
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+*  @brief This function stores the FW dumps received from events
+*
+*  @param priv    A pointer to bt_private structure
+*  @param skb     A pointer to rx skb
+*
+*  @return        N/A
+*/
+void
+bt_store_firmware_dump(bt_private *priv, u8 *buf, u32 len)
+{
+	struct file *pfile_fwdump = NULL;
+	loff_t pos = 0;
+	u16 seqnum = 0;
+	struct timeval t;
+	u32 sec;
+
+	ENTER();
+
+	seqnum = __le16_to_cpu(*(u16 *) (buf + OFFSET_SEQNUM));
+
+	if (priv->adapter->fwdump_fname && seqnum != 1) {
+		pfile_fwdump =
+			filp_open((const char *)priv->adapter->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		if (IS_ERR(pfile_fwdump)) {
+			PRINTM(MSG, "Cannot create firmware dump file.\n");
+			LEAVE();
+			return;
+		}
+	} else {
+		if (!priv->adapter->fwdump_fname) {
+			gfp_t flag;
+			flag = (in_atomic() ||
+				irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+			priv->adapter->fwdump_fname = kzalloc(64, flag);
+		} else
+			memset(priv->adapter->fwdump_fname, 0, 64);
+
+		do_gettimeofday(&t);
+		sec = (u32)t.tv_sec;
+		sprintf(priv->adapter->fwdump_fname, "%s%u",
+			"/var/log/bt_fwdump_", sec);
+		pfile_fwdump =
+			filp_open(priv->adapter->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		if (IS_ERR(pfile_fwdump)) {
+			sprintf(priv->adapter->fwdump_fname, "%s%u",
+				"/data/bt_fwdump_", sec);
+			pfile_fwdump =
+				filp_open((const char *)priv->adapter->
+					  fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		}
+	}
+
+	if (IS_ERR(pfile_fwdump)) {
+		PRINTM(MSG, "Cannot create firmware dump file\n");
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile_fwdump, buf, len, &pos);
+#else
+	kernel_write(pfile_fwdump, buf, len, &pos);
+#endif
+	filp_close(pfile_fwdump, NULL);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function process the received event
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+-----+
+ *  |   EC   | Length |           Data        |
+ *  +--------+--------+--------+--------+-----+
+ *  | 1-byte | 1-byte |          n-byte       |
+ *  +--------+--------+--------+--------+-----+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_event(bt_private *priv, struct sk_buff *skb)
+{
+	int ret = BT_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	BT_EVENT *pevent;
+
+	ENTER();
+	if (!m_dev) {
+		PRINTM(CMD, "BT: bt_process_event without m_dev\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pevent = (BT_EVENT *)skb->data;
+	if (pevent->EC != 0xff) {
+		PRINTM(CMD, "BT: Not Marvell Event=0x%x\n", pevent->EC);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	switch (pevent->data[0]) {
+	case BT_CMD_AUTO_SLEEP_MODE:
+		if (pevent->data[2] == BT_STATUS_SUCCESS) {
+			if (pevent->data[1] == BT_PS_ENABLE)
+				priv->adapter->psmode = 1;
+			else
+				priv->adapter->psmode = 0;
+			PRINTM(CMD, "BT: PS Mode %s:%s\n", m_dev->name,
+			       (priv->adapter->psmode) ? "Enable" : "Disable");
+
+		} else {
+			PRINTM(CMD, "BT: PS Mode Command Fail %s\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_CONFIG:
+		if (pevent->data[3] == BT_STATUS_SUCCESS) {
+			PRINTM(CMD, "BT: %s: gpio=0x%x, gap=0x%x\n",
+			       m_dev->name, pevent->data[1], pevent->data[2]);
+		} else {
+			PRINTM(CMD, "BT: %s: HSCFG Command Fail\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_ENABLE:
+		if (pevent->data[1] == BT_STATUS_SUCCESS) {
+			priv->adapter->hs_state = HS_ACTIVATED;
+			if (priv->adapter->suspend_fail == FALSE) {
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+				bt_is_suspended(priv);
+#endif
+#endif
+#endif
+				if (priv->adapter->wait_event_timeout) {
+					wake_up(&priv->adapter->cmd_wait_q);
+					priv->adapter->wait_event_timeout =
+						FALSE;
+				} else
+					wake_up_interruptible(&priv->adapter->
+							      cmd_wait_q);
+
+			}
+			if (priv->adapter->psmode)
+				priv->adapter->ps_state = PS_SLEEP;
+			PRINTM(CMD, "BT: EVENT %s: HS ACTIVATED!\n",
+			       m_dev->name);
+
+		} else {
+			PRINTM(CMD, "BT: %s: HS Enable Fail\n", m_dev->name);
+		}
+		break;
+	case BT_CMD_MODULE_CFG_REQ:
+		if ((priv->bt_dev.sendcmdflag == TRUE) &&
+		    ((pevent->data[1] == MODULE_BRINGUP_REQ)
+		     || (pevent->data[1] == MODULE_SHUTDOWN_REQ))) {
+			if (pevent->data[1] == MODULE_BRINGUP_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2] && (pevent->data[2] !=
+							    MODULE_CFG_RESP_ALREADY_UP))
+				       ? "Bring up Fail" : "Bring up success");
+				priv->bt_dev.devType = pevent->data[3];
+				PRINTM(CMD, "devType:%s\n",
+				       (pevent->data[3] ==
+					DEV_TYPE_AMP) ? "AMP controller" :
+				       "BR/EDR controller");
+				priv->bt_dev.devFeature = pevent->data[4];
+				PRINTM(CMD, "devFeature:  %s,    %s,    %s"
+				       "\n",
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BT) ?
+					"BT Feature" : "No BT Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BTAMP) ?
+					"BTAMP Feature" : "No BTAMP Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BLE) ?
+					"BLE Feature" : "No BLE Feature")
+					);
+			}
+			if (pevent->data[1] == MODULE_SHUTDOWN_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2]) ? "Shut down Fail"
+				       : "Shut down success");
+
+			}
+			if (pevent->data[2]) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			}
+		} else {
+			PRINTM(CMD, "BT_CMD_MODULE_CFG_REQ resp for APP\n");
+			ret = BT_STATUS_FAILURE;
+		}
+		break;
+	case BT_EVENT_POWER_STATE:
+		if (pevent->data[1] == BT_PS_SLEEP)
+			priv->adapter->ps_state = PS_SLEEP;
+		if (priv->adapter->ps_state == PS_SLEEP
+		    && (priv->card_type == CARD_TYPE_SD8887)
+			)
+			os_sched_timeout(5);
+		PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+		       (priv->adapter->ps_state) ? "PS_SLEEP" : "PS_AWAKE");
+
+		break;
+	case BT_CMD_SDIO_PULL_CFG_REQ:
+		if (pevent->data[pevent->length - 1] == BT_STATUS_SUCCESS)
+			PRINTM(CMD, "BT: %s: SDIO pull configuration success\n",
+			       m_dev->name);
+
+		else {
+			PRINTM(CMD, "BT: %s: SDIO pull configuration fail\n",
+			       m_dev->name);
+
+		}
+		break;
+	default:
+		PRINTM(CMD, "BT: Unknown Event=%d %s\n", pevent->data[0],
+		       m_dev->name);
+		ret = BT_STATUS_FAILURE;
+		break;
+	}
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function save the dump info to file
+ *
+ *  @param dir_name     directory name
+ *  @param file_name    file_name
+ *  @param buf			buffer
+ *  @param buf_len		buffer length
+ *
+ *  @return   		    0 --success otherwise fail
+ */
+int
+bt_save_dump_info_to_file(char *dir_name, char *file_name, u8 *buf, u32 buf_len)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct file *pfile = NULL;
+	u8 name[64];
+	loff_t pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	if (!dir_name || !file_name || !buf) {
+		PRINTM(ERROR, "Can't save dump info to file\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(name, 0, sizeof(name));
+	snprintf((char *)name, sizeof(name), "%s/%s", dir_name, file_name);
+	pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MSG,
+		       "Create file %s error, try to save dump file in /var\n",
+		       name);
+		memset(name, 0, sizeof(name));
+		snprintf((char *)name, sizeof(name), "%s/%s", "/var",
+			 file_name);
+		pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(ERROR, "Create Dump file for %s error\n", name);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MSG, "Dump data %s saved in %s\n", file_name, name);
+
+	pos = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	vfs_write(pfile, (const char __user *)buf, buf_len, &pos);
+	set_fs(fs);
+#else
+	kernel_write(pfile, (const char __user *)buf, buf_len, &pos);
+#endif
+	filp_close(pfile, NULL);
+
+	PRINTM(MSG, "Dump data %s saved in %s successfully\n", file_name, name);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#define DEBUG_HOST_READY		0xEE
+#define DEBUG_FW_DONE			0xFF
+#define DUMP_MAX_POLL_TRIES			200
+
+#define DEBUG_DUMP_CTRL_REG_8897               0xE2
+#define DEBUG_DUMP_START_REG_8897              0xE3
+#define DEBUG_DUMP_END_REG_8897                0xEA
+#define DEBUG_DUMP_CTRL_REG_8887               0xA2
+#define DEBUG_DUMP_START_REG_8887              0xA3
+#define DEBUG_DUMP_END_REG_8887                0xAA
+#define DEBUG_DUMP_CTRL_REG_8977               0xF0
+#define DEBUG_DUMP_START_REG_8977              0xF1
+#define DEBUG_DUMP_END_REG_8977                0xF8
+#define DEBUG_DUMP_CTRL_REG_8978               0xF0
+#define DEBUG_DUMP_START_REG_8978              0xF1
+#define DEBUG_DUMP_END_REG_8978                0xF8
+#define DEBUG_DUMP_CTRL_REG_8997               0xF0
+#define DEBUG_DUMP_START_REG_8997              0xF1
+#define DEBUG_DUMP_END_REG_8997                0xF8
+#define DEBUG_DUMP_CTRL_REG_8987               0xF0
+#define DEBUG_DUMP_START_REG_8987              0xF1
+#define DEBUG_DUMP_END_REG_8987                0xF8
+
+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
+#define MAX_FULL_NAME_LEN               32
+
+/** Memory type mapping structure */
+typedef struct {
+	/** memory name */
+	u8 mem_name[MAX_NAME_LEN];
+	/** memory pointer */
+	u8 *mem_Ptr;
+	/** file structure */
+	struct file *pfile_mem;
+	/** donbe flag */
+	u8 done_flag;
+	/** dump type */
+	u8 type;
+} memory_type_mapping;
+
+memory_type_mapping bt_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},
+	{"EXT8", NULL, NULL, 0xF8},
+	{"EXT9", NULL, NULL, 0xF9},
+	{"EXT10", NULL, NULL, 0xFA},
+	{"EXT11", NULL, NULL, 0xFB},
+	{"EXT12", NULL, NULL, 0xFC},
+	{"EXT13", NULL, NULL, 0xFD},
+	{"EXTLAST", NULL, NULL, 0xFE},
+};
+
+typedef enum {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+} rdwr_status;
+
+/**
+ *  @brief This function read/write firmware via cmd52
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+rdwr_status
+bt_cmd52_rdwr_firmware(bt_private *priv, u8 doneflag)
+{
+	int ret = 0;
+	int tries = 0;
+	u8 ctrl_data = 0;
+	u8 dbg_dump_ctrl_reg = 0;
+
+	if (priv->card_type == CARD_TYPE_SD8887)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8887;
+	else if (priv->card_type == CARD_TYPE_SD8897)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8897;
+	else if (priv->card_type == CARD_TYPE_SD8977)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8977;
+	else if (priv->card_type == CARD_TYPE_SD8978)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8978;
+	else if (priv->card_type == CARD_TYPE_SD8997)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8997;
+	else if (priv->card_type == CARD_TYPE_SD8987)
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8987;
+
+	ret = sd_write_reg(priv, dbg_dump_ctrl_reg, DEBUG_HOST_READY);
+	if (ret) {
+		PRINTM(ERROR, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	for (tries = 0; tries < DUMP_MAX_POLL_TRIES; tries++) {
+		ret = sd_read_reg(priv, dbg_dump_ctrl_reg, &ctrl_data);
+		if (ret) {
+			PRINTM(ERROR, "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(INFO,
+			       "The ctrl reg was changed, re-try again!\n");
+			ret = sd_write_reg(priv, dbg_dump_ctrl_reg,
+					   DEBUG_HOST_READY);
+			if (ret) {
+				PRINTM(ERROR, "SDIO Write ERR\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		udelay(100);
+	}
+	if (ctrl_data == DEBUG_HOST_READY) {
+		PRINTM(ERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	return RDWR_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_firmware_info_v2(bt_private *priv)
+{
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	u8 *dbg_ptr = NULL;
+	u8 dump_num = 0;
+	u8 idx = 0;
+	u8 doneflag = 0;
+	rdwr_status stat;
+	u8 i = 0;
+	u8 read_reg = 0;
+	u32 memory_size = 0;
+	u8 path_name[64], file_name[32];
+	u8 *end_ptr = NULL;
+	u8 dbg_dump_start_reg = 0;
+	u8 dbg_dump_end_reg = 0;
+
+	if (!priv) {
+		PRINTM(ERROR, "Could not dump firmwware info\n");
+		return;
+	}
+
+	if ((priv->card_type != CARD_TYPE_SD8887) &&
+	    (priv->card_type != CARD_TYPE_SD8897)
+	    && (priv->card_type != CARD_TYPE_SD8977) &&
+	    (priv->card_type != CARD_TYPE_SD8997)
+	    && (priv->card_type != CARD_TYPE_SD8987) &&
+	    (priv->card_type != CARD_TYPE_SD8978)) {
+		PRINTM(MSG, "card_type %d don't support FW dump\n",
+		       priv->card_type);
+		return;
+	}
+
+	memset(path_name, 0, sizeof(path_name));
+	strcpy((char *)path_name, "/data");
+	PRINTM(MSG, "Create DUMP directory success:dir_name=%s\n", path_name);
+
+	if (priv->card_type == CARD_TYPE_SD8887) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8887;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8887;
+	} else if (priv->card_type == CARD_TYPE_SD8897) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8897;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8897;
+	} else if (priv->card_type == CARD_TYPE_SD8977) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8977;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8977;
+	} else if (priv->card_type == CARD_TYPE_SD8978) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8978;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8978;
+	} else if (priv->card_type == CARD_TYPE_SD8997) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8997;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8997;
+	} else if (priv->card_type == CARD_TYPE_SD8987) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8987;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8987;
+	}
+
+	sbi_wakeup_firmware(priv);
+	priv->fw_dump = TRUE;
+	/* start dump fw memory */
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT START ====\n");
+	/* read the number of the memories which will dump */
+	if (RDWR_STATUS_FAILURE == bt_cmd52_rdwr_firmware(priv, doneflag))
+		goto done;
+	reg = dbg_dump_start_reg;
+	ret = sd_read_reg(priv, reg, &dump_num);
+	if (ret) {
+		PRINTM(MSG, "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 ==
+		    bt_cmd52_rdwr_firmware(priv, doneflag))
+			goto done;
+		memory_size = 0;
+		reg = dbg_dump_start_reg;
+		for (i = 0; i < 4; i++) {
+			ret = sd_read_reg(priv, reg, &read_reg);
+			if (ret) {
+				PRINTM(MSG, "SDIO READ ERR\n");
+				goto done;
+			}
+			memory_size |= (read_reg << i * 8);
+			reg++;
+		}
+		if (memory_size == 0) {
+			PRINTM(MSG, "Firmware Dump Finished!\n");
+			break;
+		} else {
+			PRINTM(MSG, "%s_SIZE=0x%x\n",
+			       bt_mem_type_mapping_tbl[idx].mem_name,
+			       memory_size);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr =
+				vmalloc(memory_size + 1);
+			if ((ret != BT_STATUS_SUCCESS) ||
+			    !bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+				PRINTM(ERROR,
+				       "Error: vmalloc %s buffer failed!!!\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name);
+				goto done;
+			}
+			dbg_ptr = bt_mem_type_mapping_tbl[idx].mem_Ptr;
+			end_ptr = dbg_ptr + memory_size;
+		}
+		doneflag = bt_mem_type_mapping_tbl[idx].done_flag;
+		PRINTM(MSG, "Start %s output, please wait...\n",
+		       bt_mem_type_mapping_tbl[idx].mem_name);
+		do {
+			stat = bt_cmd52_rdwr_firmware(priv, 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 = sd_read_reg(priv, reg, dbg_ptr);
+				if (ret) {
+					PRINTM(MSG, "SDIO READ ERR\n");
+					goto done;
+				}
+				if (dbg_ptr < end_ptr)
+					dbg_ptr++;
+				else
+					PRINTM(MSG,
+					       "pre-allocced buf is not enough\n");
+			}
+			if (RDWR_STATUS_DONE == stat) {
+				PRINTM(MSG, "%s done:"
+				       "size = 0x%x\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name,
+				       (unsigned int)(dbg_ptr -
+						      bt_mem_type_mapping_tbl
+						      [idx].mem_Ptr));
+				memset(file_name, 0, sizeof(file_name));
+				snprintf((char *)file_name, sizeof(file_name),
+					 "%s%s", "file_bt_",
+					 bt_mem_type_mapping_tbl[idx].mem_name);
+				if (BT_STATUS_SUCCESS !=
+				    bt_save_dump_info_to_file((char *)path_name,
+							      (char *)file_name,
+							      bt_mem_type_mapping_tbl
+							      [idx].mem_Ptr,
+							      memory_size))
+					PRINTM(MSG,
+					       "Can't save dump file %s in %s\n",
+					       file_name, path_name);
+				vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+				bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+				break;
+			}
+		} while (1);
+	}
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT END ====\n");
+	/* end dump fw memory */
+done:
+	priv->fw_dump = FALSE;
+	for (idx = 0; idx < dump_num; idx++) {
+		if (bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+			vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+		}
+	}
+	PRINTM(MSG, "==== DEBUG MODE END ====\n");
+	return;
+}
+
+/**
+ *  @brief This function shows debug info for timeout of command sending.
+ *
+ *  @param adapter  A pointer to bt_private
+ *  @param cmd      Timeout command id
+ *
+ *  @return         N/A
+ */
+static void
+bt_cmd_timeout_func(bt_private *priv, u16 cmd)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+
+	adapter->num_cmd_timeout++;
+
+	PRINTM(ERROR, "Version = %s\n", adapter->drv_ver);
+	PRINTM(ERROR, "Timeout Command id = 0x%x\n", cmd);
+	PRINTM(ERROR, "Number of command timeout = %d\n",
+	       adapter->num_cmd_timeout);
+	PRINTM(ERROR, "Interrupt counter = %d\n", adapter->IntCounter);
+	PRINTM(ERROR, "Power Save mode = %d\n", adapter->psmode);
+	PRINTM(ERROR, "Power Save state = %d\n", adapter->ps_state);
+	PRINTM(ERROR, "Host Sleep state = %d\n", adapter->hs_state);
+	PRINTM(ERROR, "hs skip count = %d\n", adapter->hs_skip);
+	PRINTM(ERROR, "suspend_fail flag = %d\n", adapter->suspend_fail);
+	PRINTM(ERROR, "suspended flag = %d\n", adapter->is_suspended);
+	PRINTM(ERROR, "Number of wakeup tries = %d\n", adapter->WakeupTries);
+	PRINTM(ERROR, "Host Cmd complet state = %d\n", adapter->cmd_complete);
+	PRINTM(ERROR, "Last irq recv = %d\n", adapter->irq_recv);
+	PRINTM(ERROR, "Last irq processed = %d\n", adapter->irq_done);
+	PRINTM(ERROR, "tx pending = %d\n", adapter->skb_pending);
+	PRINTM(ERROR, "sdio int status = %d\n", adapter->sd_ireg);
+	bt_dump_sdio_regs(priv);
+	LEAVE();
+}
+
+/**
+ *  @brief This function queue frame
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    N/A
+ */
+static void
+bt_queue_frame(bt_private *priv, struct sk_buff *skb)
+{
+	skb_queue_tail(&priv->adapter->tx_queue, skb);
+}
+
+/**
+ *  @brief This function send reset cmd to firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return	       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_reset_command(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((RESET_OGF << 10) | BT_CMD_RESET);
+	pcmd->length = 0x00;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, 3);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue Reset Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Reset timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_RESET);
+	} else {
+		PRINTM(CMD, "BT: Reset Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends module cfg cmd to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param subcmd  sub command
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_module_cfg_cmd(bt_private *priv, int subcmd)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_MODULE_CFG_REQ);
+	pcmd->length = 1;
+	pcmd->data[0] = subcmd;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue module cfg Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	/*
+	   On some Android platforms certain delay is needed for HCI daemon to
+	   remove this module and close itself gracefully. Otherwise it hangs.
+	   This 10ms delay is a workaround for such platforms as the root cause
+	   has not been found yet. */
+	mdelay(10);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: module_cfg_cmd(%#x): timeout sendcmdflag=%d\n",
+		       subcmd, priv->bt_dev.sendcmdflag);
+		bt_cmd_timeout_func(priv, BT_CMD_MODULE_CFG_REQ);
+	} else {
+		PRINTM(CMD, "BT: module cfg Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables power save mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_ps(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_AUTO_SLEEP_MODE);
+	if (priv->bt_dev.psmode)
+		pcmd->data[0] = BT_PS_ENABLE;
+	else
+		pcmd->data[0] = BT_PS_DISABLE;
+	if (priv->bt_dev.idle_timeout) {
+		pcmd->length = 3;
+		pcmd->data[1] = (u8)(priv->bt_dev.idle_timeout & 0x00ff);
+		pcmd->data[2] = (priv->bt_dev.idle_timeout & 0xff00) >> 8;
+	} else {
+		pcmd->length = 1;
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PSMODE Command(0x%x):%d\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: psmode timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_AUTO_SLEEP_MODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends hscfg command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_hscfg_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_CONFIG);
+	pcmd->length = 2;
+	pcmd->data[0] = (priv->bt_dev.gpio_gap & 0xff00) >> 8;
+	pcmd->data[1] = (u8)(priv->bt_dev.gpio_gap & 0x00ff);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue HSCFG Command(0x%x),gpio=0x%x,gap=0x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0], pcmd->data[1]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: HSCFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_CONFIG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends sdio pull ctrl command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_sdio_pull_ctrl_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_SDIO_PULL_CFG_REQ);
+	pcmd->length = 4;
+	pcmd->data[0] = (priv->bt_dev.sdio_pull_cfg & 0x000000ff);
+	pcmd->data[1] = (priv->bt_dev.sdio_pull_cfg & 0x0000ff00) >> 8;
+	pcmd->data[2] = (priv->bt_dev.sdio_pull_cfg & 0x00ff0000) >> 16;
+	pcmd->data[3] = (priv->bt_dev.sdio_pull_cfg & 0xff000000) >> 24;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD,
+	       "Queue SDIO PULL CFG Command(0x%x), PullUp=0x%x%x,PullDown=0x%x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[1], pcmd->data[0],
+	       pcmd->data[3], pcmd->data[2]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: SDIO PULL CFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SDIO_PULL_CFG_REQ);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends command to configure PMIC
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_pmic_configure(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_PMIC_CONFIGURE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PMIC Configure Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: PMIC Configure timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_PMIC_CONFIGURE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables host sleep
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param is_shutdown  indicate shutdown mode
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_hs(bt_private *priv, bool is_shutdown)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	priv->adapter->suspend_fail = FALSE;
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_ENABLE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->adapter->wait_event_timeout = is_shutdown;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	PRINTM(CMD, "Queue hs enable Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (is_shutdown) {
+		if (!os_wait_timeout
+		    (priv->adapter->cmd_wait_q, priv->adapter->hs_state,
+		     WAIT_UNTIL_HS_STATE_CHANGED)) {
+			PRINTM(MSG, "BT: Enable host sleep timeout:\n");
+			priv->adapter->wait_event_timeout = FALSE;
+			bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_ENABLE);
+		}
+	} else {
+		if (!os_wait_interruptible_timeout
+		    (priv->adapter->cmd_wait_q, priv->adapter->hs_state,
+		     WAIT_UNTIL_HS_STATE_CHANGED)) {
+			PRINTM(MSG, "BT: Enable host sleep timeout:\n");
+			bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_ENABLE);
+		}
+	}
+	OS_INT_DISABLE;
+	if ((priv->adapter->hs_state == HS_ACTIVATED) ||
+	    (priv->adapter->is_suspended == TRUE)) {
+		OS_INT_RESTORE;
+		PRINTM(MSG, "BT: suspend success! skip=%d\n",
+		       priv->adapter->hs_skip);
+	} else {
+		priv->adapter->suspend_fail = TRUE;
+		OS_INT_RESTORE;
+		priv->adapter->hs_skip++;
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG,
+		       "BT: suspend skipped! "
+		       "state=%d skip=%d ps_state= %d WakeupTries=%d\n",
+		       priv->adapter->hs_state, priv->adapter->hs_skip,
+		       priv->adapter->ps_state, priv->adapter->WakeupTries);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Set Evt Filter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_evt_filter(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_SET_EVT_FILTER);
+	pcmd->length = 0x03;
+	pcmd->data[0] = 0x02;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Set Evt Filter Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set Evt Filter timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SET_EVT_FILTER);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Write Scan - Page and Inquiry
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_write_scan(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_ENABLE_WRITE_SCAN);
+	pcmd->length = 0x01;
+	pcmd->data[0] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Enable Write Scan Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Write Scan timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_WRITE_SCAN);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Device under test mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_device_under_testmode(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((0x06 << 10) | BT_CMD_ENABLE_DEVICE_TESTMODE);
+	pcmd->length = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue enable device under testmode Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Device under TEST mode timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_DEVICE_TESTMODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables test mode and send cmd
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_test_mode(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	/** Set Evt Filter Command */
+	ret = bt_set_evt_filter(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Set Evt filter fail\n");
+		goto exit;
+	}
+
+	/** Enable Write Scan Command */
+	ret = bt_enable_write_scan(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Enable Write Scan fail\n");
+		goto exit;
+	}
+
+	/** Enable Device under test mode */
+	ret = bt_enable_device_under_testmode(priv);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(ERROR,
+		       "BT test_mode: Enable device under testmode fail\n");
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+#define DISABLE_RESET  0x0
+#define ENABLE_OUTBAND_RESET 0x1
+#define ENABLE_INBAND_RESET  0x02
+#define DEFAULT_GPIO 0xff
+/**
+ *  @brief This function set GPIO pin
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_independent_reset(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	u8 mode, gpio;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_INDEPENDENT_RESET);
+	mode = btindrst & 0xff;
+	gpio = (btindrst & 0xff00) >> 8;
+	if (mode == ENABLE_OUTBAND_RESET) {
+		pcmd->data[0] = ENABLE_OUTBAND_RESET;
+		if (!gpio)
+			pcmd->data[1] = DEFAULT_GPIO;
+		else
+			pcmd->data[1] = gpio;
+	} else if (mode == ENABLE_INBAND_RESET) {
+		pcmd->data[0] = ENABLE_INBAND_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else if (mode == DISABLE_RESET) {
+		pcmd->data[0] = DISABLE_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else {
+		PRINTM(WARN, "Unsupport mode\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	PRINTM(CMD, "BT: independant reset mode=%d gpio=%d\n", mode, gpio);
+	pcmd->length = 2;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Independent reset : timeout!\n");
+		bt_cmd_timeout_func(priv, BT_CMD_INDEPENDENT_RESET);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets ble deepsleep mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mode    TRUE/FALSE
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_ble_deepsleep(bt_private *priv, int mode)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_BLE_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_BLE_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_BLE_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_BLE_DEEP_SLEEP);
+	pcmd->length = 1;
+	pcmd->deepsleep = mode;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_BLE_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set BLE deepsleep = %d (0x%x)\n", mode,
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set BLE deepsleep timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_BLE_DEEP_SLEEP);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets FW version
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_get_fw_version(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_GET_FW_VERSION);
+	pcmd->length = 0x01;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, 4);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Get FW version: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_GET_FW_VERSION);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets mac address
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_mac_address(bt_private *priv, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	int i = 0;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CONFIG_MAC_ADDR);
+	pcmd->length = 8;
+	pcmd->cmd_type = MRVL_VENDOR_PKT;
+	pcmd->cmd_len = 6;
+	for (i = 0; i < 6; i++)
+		pcmd->data[i] = mac[5 - i];
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_HCI_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set mac addr " MACSTR " (0x%x)\n", MAC2STR(mac),
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set mac addr: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CONFIG_MAC_ADDR);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate EXT data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_commands(bt_private *priv, u8 *cmd_data, u32 cmd_len)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	u16 ogf = 0;
+
+	ENTER();
+	PRINTM(CMD, "BT: init cmds: len=%d\n", cmd_len);
+	if (cmd_len > BT_CMD_DATA_LEN) {
+		PRINTM(WARN, "cfg_data_len is too long exceed %d.\n",
+		       BT_CMD_DATA_LEN);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	memcpy(skb->data, cmd_data, cmd_len);
+	pcmd = (BT_CMD *)skb->data;
+
+	ogf = hci_opcode_ogf(pcmd->ocf_ogf);
+	if (ogf == VENDOR_OGF)
+		bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	else
+		bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "init_cmds", skb->data, skb->len);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load init cmds: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA_EXT);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	int i = 0;
+	/* u8 config_data[28] = {0x37 0x01 0x1c 0x00 0xFF 0xFF 0xFF 0xFF 0x01
+	   0x7f 0x04 0x02 0x00 0x00 0xBA 0xCE 0xC0 0xC6 0x2D 0x00 0x00 0x00
+	   0x00 0x00 0x00 0x00 0xF0}; */
+
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA);
+	pcmd->length = 0x20;
+	pcmd->data[0] = 0x00;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x00;
+	pcmd->data[3] = 0x1C;
+	/* swip cal-data byte */
+	for (i = 4; i < 32; i++)
+		pcmd->data[i] = *(config_data + ((i / 4) * 8 - 1 - i));
+	if (mac != NULL) {
+		pcmd->data[2] = 0x01;	/* skip checksum */
+		for (i = 24; i < 30; i++)
+			pcmd->data[i] = mac[29 - i];
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate data: ", pcmd->data, 32);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate EXT data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+
+	ENTER();
+
+	if (cfg_data_len > BT_CMD_DATA_LEN) {
+		PRINTM(WARN, "cfg_data_len is too long exceed %d.\n",
+		       BT_CMD_DATA_LEN);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA_EXT);
+	pcmd->length = cfg_data_len;
+
+	memcpy(pcmd->data, config_data, cfg_data_len);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate ext data", pcmd->data, pcmd->length);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate ext data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA_EXT);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function writes value to CSU registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param type    reg type
+ *  @param offset  register address
+ *  @param value   register value to write
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CSU_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CSU_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CSU_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CSU_WRITE_REG);
+	pcmd->length = 7;
+	pcmd->type = type;
+	pcmd->offset[0] = (offset & 0x000000ff);
+	pcmd->offset[1] = (offset & 0x0000ff00) >> 8;
+	pcmd->offset[2] = (offset & 0x00ff0000) >> 16;
+	pcmd->offset[3] = (offset & 0xff000000) >> 24;
+	pcmd->value[0] = (value & 0x00ff);
+	pcmd->value[1] = (value & 0xff00) >> 8;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_CSU_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set CSU reg type=%d reg=0x%x value=0x%x\n",
+	       type, offset, value);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Set CSU reg timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CSU_WRITE_REG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function used to restore tx_queue
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        N/A
+ */
+void
+bt_restore_tx_queue(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	while (!skb_queue_empty(&priv->adapter->pending_queue)) {
+		skb = skb_dequeue(&priv->adapter->pending_queue);
+		if (skb)
+			bt_queue_frame(priv, skb);
+	}
+	wake_up_interruptible(&priv->MainThread.waitQ);
+}
+
+/**
+ *  @brief This function used to send command to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_prepare_command(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (priv->bt_dev.hscfgcmd) {
+		priv->bt_dev.hscfgcmd = 0;
+		ret = bt_send_hscfg_cmd(priv);
+	}
+	if (priv->bt_dev.pscmd) {
+		priv->bt_dev.pscmd = 0;
+		ret = bt_enable_ps(priv);
+	}
+	if (priv->bt_dev.sdio_pull_ctrl) {
+		priv->bt_dev.sdio_pull_ctrl = 0;
+		ret = bt_send_sdio_pull_ctrl_cmd(priv);
+	}
+	if (priv->bt_dev.hscmd) {
+		priv->bt_dev.hscmd = 0;
+		if (priv->bt_dev.hsmode)
+			ret = bt_enable_hs(priv, FALSE);
+		else {
+			ret = sbi_wakeup_firmware(priv);
+			priv->adapter->hs_state = HS_DEACTIVATED;
+		}
+	}
+	if (priv->bt_dev.test_mode) {
+		priv->bt_dev.test_mode = 0;
+		ret = bt_enable_test_mode(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function processes a single packet
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to skb which includes TX packet
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+send_single_packet(bt_private *priv, struct sk_buff *skb)
+{
+	int ret;
+	struct sk_buff *new_skb = NULL;
+	ENTER();
+	if (!skb || !skb->data) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	if (!skb->len || ((skb->len + BT_HEADER_LEN) > BT_UPLD_SIZE)) {
+		PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
+		       BT_UPLD_SIZE);
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	if (skb_headroom(skb) < BT_HEADER_LEN) {
+		new_skb = skb_realloc_headroom(skb, BT_HEADER_LEN);
+		if (!new_skb) {
+			PRINTM(ERROR, "TX error: realloc_headroom failed %d\n",
+			       BT_HEADER_LEN);
+			kfree_skb(skb);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		} else {
+			if (new_skb != skb)
+				dev_kfree_skb_any(skb);
+			skb = new_skb;
+		}
+	}
+	/* This is SDIO/PCIE specific header length: byte[3][2][1], * type:
+	   byte[0] (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor)
+	 */
+	skb_push(skb, BT_HEADER_LEN);
+	skb->data[0] = (skb->len & 0x0000ff);
+	skb->data[1] = (skb->len & 0x00ff00) >> 8;
+	skb->data[2] = (skb->len & 0xff0000) >> 16;
+	skb->data[3] = bt_cb(skb)->pkt_type;
+	if (bt_cb(skb)->pkt_type == MRVL_VENDOR_PKT)
+		PRINTM(CMD, "DNLD_CMD: ocf_ogf=0x%x len=%d\n",
+		       __le16_to_cpu(*((u16 *) & skb->data[4])), skb->len);
+	ret = sbi_host_to_card(priv, skb->data, skb->len);
+	if (ret == BT_STATUS_FAILURE)
+		((struct m_dev *)skb->dev)->stat.err_tx++;
+	else
+		((struct m_dev *)skb->dev)->stat.byte_tx += skb->len;
+	if (ret != BT_STATUS_PENDING)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+#ifdef CONFIG_OF
+/**
+ *  @brief This function read the initial parameter from device tress
+ *
+ *
+ *  @return         N/A
+ */
+static void
+bt_init_from_dev_tree(void)
+{
+	struct device_node *dt_node = NULL;
+	struct property *prop;
+	u32 data;
+	const char *string_data;
+
+	ENTER();
+
+	if (!dts_enable) {
+		PRINTM(CMD, "DTS is disabled!");
+		return;
+	}
+
+	dt_node = of_find_node_by_name(NULL, "sd8xxx-bt");
+	if (!dt_node) {
+		LEAVE();
+		return;
+	}
+	for_each_property_of_node(dt_node, prop) {
+#ifdef DEBUG_LEVEL1
+		if (!strncmp(prop->name, "mbt_drvdbg", strlen("mbt_drvdbg"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(CMD, "mbt_drvdbg=0x%x\n", data);
+				mbt_drvdbg = data;
+			}
+		}
+#endif
+		else if (!strncmp(prop->name, "init_cmds", strlen("init_cmds"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				init_cmds = (char *)string_data;
+				PRINTM(CMD, "init_cmds=%s\n", init_cmds);
+			}
+		} 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(CMD, "init_cfg=%s\n", init_cfg);
+			}
+		} else if (!strncmp
+			   (prop->name, "cal_cfg_ext", strlen("cal_cfg_ext"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg_ext = (char *)string_data;
+				PRINTM(CMD, "cal_cfg_ext=%s\n", cal_cfg_ext);
+			}
+		} else if (!strncmp(prop->name, "cal_cfg", strlen("cal_cfg"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg = (char *)string_data;
+				PRINTM(CMD, "cal_cfg=%s\n", cal_cfg);
+			}
+		} else if (!strncmp(prop->name, "bt_mac", strlen("bt_mac"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				bt_mac = (char *)string_data;
+				PRINTM(CMD, "bt_mac=%s\n", bt_mac);
+			}
+		} else if (!strncmp(prop->name, "btindrst", strlen("btindrst"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btindrst = data;
+				PRINTM(CMD, "btindrst=%d\n", btindrst);
+			}
+		} else if (!strncmp(prop->name, "btpmic", strlen("btpmic"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btpmic = data;
+				PRINTM(CMD, "btpmic=%d\n", btpmic);
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+#endif
+
+#ifdef BLE_WAKEUP
+/**
+ *  @brief This function send getting whitelist cmd to FW
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_get_whitelist_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_GET_WHITELIST);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(MSG, "Queue get whitelist Command(0x%x):%d\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0]);
+
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Get BLE_GET_WHITELIST: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_GET_WHITELIST);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function send  whitelist cmd to FW
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param is_shutdown  indicate shutdown mode
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_send_whitelist_cmd(bt_private *priv, bool is_shutdown)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	u8 count = 0, i = 0;
+	BT_CMD *pcmd;
+	ENTER();
+
+	count = priv->white_list[0];
+	for (i = 0; (i < count) && (i < 10); i++) {
+		skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+		if (skb == NULL) {
+			PRINTM(WARN, "No free skb\n");
+			ret = BT_STATUS_FAILURE;
+			goto exit;
+		}
+		pcmd = (BT_CMD *)skb->data;
+		pcmd->ocf_ogf =
+			__cpu_to_le16((HCI_BLE_GRP_BLE_CMDS << 10) |
+				      HCI_BLE_ADD_DEV_TO_WHITELIST_OCF);
+		pcmd->length = 7;
+		bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+		pcmd->data[0] = 0;
+		memcpy(&pcmd->data[1], &priv->white_list[1 + i * 6], 6);
+		skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+		skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+		skb_queue_head(&priv->adapter->tx_queue, skb);
+		PRINTM(MSG, "Queue send whitelist Command(0x%x):%d\n",
+		       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0]);
+
+		priv->bt_dev.sendcmdflag = TRUE;
+		priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+		priv->adapter->cmd_complete = FALSE;
+		priv->adapter->wait_event_timeout = is_shutdown;
+		wake_up_interruptible(&priv->MainThread.waitQ);
+		if (is_shutdown) {
+			if (!os_wait_timeout
+			    (priv->adapter->cmd_wait_q,
+			     priv->adapter->cmd_complete,
+			     WAIT_UNTIL_CMD_RESP)) {
+				ret = BT_STATUS_FAILURE;
+				priv->adapter->wait_event_timeout = FALSE;
+				PRINTM(ERROR,
+				       "BT: Get BLE_GET_WHITELIST: timeout:\n");
+				bt_cmd_timeout_func(priv,
+						    HCI_BLE_ADD_DEV_TO_WHITELIST_OCF);
+			}
+		} else {
+			if (!os_wait_interruptible_timeout
+			    (priv->adapter->cmd_wait_q,
+			     priv->adapter->cmd_complete,
+			     WAIT_UNTIL_CMD_RESP)) {
+				ret = BT_STATUS_FAILURE;
+				PRINTM(ERROR,
+				       "BT: Get BLE_GET_WHITELIST: timeout:\n");
+				bt_cmd_timeout_func(priv,
+						    HCI_BLE_ADD_DEV_TO_WHITELIST_OCF);
+			}
+		}
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function initializes the adapter structure
+ *  and set default value to the member of adapter.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+static void
+bt_init_adapter(bt_private *priv)
+{
+	ENTER();
+#ifdef CONFIG_OF
+	bt_init_from_dev_tree();
+#endif
+	skb_queue_head_init(&priv->adapter->tx_queue);
+	skb_queue_head_init(&priv->adapter->pending_queue);
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+	priv->adapter->fwdump_fname = NULL;
+	init_waitqueue_head(&priv->adapter->cmd_wait_q);
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (fw == 0) {
+		sbi_enable_host_int(priv);
+		goto done;
+	}
+	sbi_disable_host_int(priv);
+	if ((priv->card_type == CARD_TYPE_SD8787) ||
+	    (priv->card_type == CARD_TYPE_SD8777))
+		priv->fw_crc_check = fw_crc_check;
+	if (sbi_download_fw(priv)) {
+		PRINTM(ERROR, " FW failed to be download!\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#define FW_POLL_TRIES 100
+#define SD8897_FW_RESET_REG  0x0E8
+#define SD8887_FW_RESET_REG  0x0B6
+#define SD8977_SD8978_SD8997_FW_RESET_REG  0x0EE
+#define SD8887_SD8897_FW_RESET_VAL  1
+#define SD8977_SD8978_SD8997_FW_RESET_VAL  0x99
+
+/**
+ *  @brief This function reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   FW reload mode
+ *
+ *  @return       0--success, otherwise failure
+ */
+static int
+bt_reload_fw(bt_private *priv, int mode)
+{
+	int ret = 0, tries = 0;
+	u8 value = 1;
+	u32 reset_reg = 0;
+	u8 reset_val = 0;
+
+	ENTER();
+	if ((mode != FW_RELOAD_SDIO_INBAND_RESET) &&
+	    (mode != FW_RELOAD_NO_EMULATION)) {
+		PRINTM(ERROR, "Invalid fw reload mode=%d\n", mode);
+		return -EFAULT;
+	}
+
+    /** flush pending tx_queue */
+	skb_queue_purge(&priv->adapter->tx_queue);
+	if (mode == FW_RELOAD_SDIO_INBAND_RESET) {
+		if (priv->card_type == CARD_TYPE_SD8887) {
+			reset_reg = SD8887_FW_RESET_REG;
+			reset_val = SD8887_SD8897_FW_RESET_VAL;
+		} else if (priv->card_type == CARD_TYPE_SD8897) {
+			reset_reg = SD8897_FW_RESET_REG;
+			reset_val = SD8887_SD8897_FW_RESET_VAL;
+		} else if ((priv->card_type == CARD_TYPE_SD8977) ||
+			   (priv->card_type == CARD_TYPE_SD8997) ||
+			   (priv->card_type == CARD_TYPE_SD8978) ||
+			   (priv->card_type == CARD_TYPE_SD8987)) {
+			reset_reg = SD8977_SD8978_SD8997_FW_RESET_REG;
+			reset_val = SD8977_SD8978_SD8997_FW_RESET_VAL;
+		}
+		sbi_disable_host_int(priv);
+	    /** Wake up firmware firstly */
+		sbi_wakeup_firmware(priv);
+
+	/** wait SOC fully wake up */
+		for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_write_reg(priv, reset_reg, 0xba);
+			if (!ret) {
+				ret = sd_read_reg(priv, reset_reg, &value);
+				if (!ret && (value == 0xba)) {
+					PRINTM(MSG, "Fw wake up\n");
+					break;
+				}
+			}
+			udelay(1000);
+		}
+
+		ret = sd_write_reg(priv, reset_reg, reset_val);
+		if (ret) {
+			PRINTM(ERROR, "Failed to write register.\n");
+			goto done;
+		}
+
+	    /** Poll register around 1 ms */
+		for (; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_read_reg(priv, reset_reg, &value);
+			if (ret) {
+				PRINTM(ERROR, "Failed to read register.\n");
+				goto done;
+			}
+			if (value == 0)
+			    /** FW is ready */
+				break;
+			udelay(1000);
+		}
+		if (value) {
+			PRINTM(ERROR,
+			       "Failed to poll FW reset register %X=0x%x\n",
+			       reset_reg, value);
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	sbi_enable_host_int(priv);
+	/** reload FW */
+	ret = bt_init_fw(priv);
+	if (ret) {
+		PRINTM(ERROR, "Re download firmware failed.\n");
+		ret = -EFAULT;
+	}
+	LEAVE();
+	return ret;
+done:
+	sbi_enable_host_int(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function request to reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   fw reload mode.
+ *
+ *  @return         N/A
+ */
+void
+bt_request_fw_reload(bt_private *priv, int mode)
+{
+	ENTER();
+	if (mode == FW_RELOAD_WITH_EMULATION) {
+		bt_fw_reload = FW_RELOAD_WITH_EMULATION;
+		PRINTM(MSG, "BT: FW reload with re-emulation...\n");
+		LEAVE();
+		return;
+	}
+	/** Reload FW */
+	priv->fw_reload = TRUE;
+	if (bt_reload_fw(priv, mode)) {
+		PRINTM(ERROR, "FW reload fail\n");
+		goto done;
+	}
+	priv->fw_reload = FALSE;
+	/** Other operation here? */
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function frees the structure of adapter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+void
+bt_free_adapter(bt_private *priv)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	kfree(adapter->tx_buffer);
+	kfree(adapter->hw_regs_buf);
+	/* Free allocated memory for fwdump filename */
+	if (adapter->fwdump_fname) {
+		kfree(adapter->fwdump_fname);
+		adapter->fwdump_fname = NULL;
+	}
+	/* Free the adapter object itself */
+	kfree(adapter);
+	priv->adapter = NULL;
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the wrapper_dev ioctl
+ *
+ *  @param hev     A pointer to wrapper_dev structure
+ *  @cmd            ioctl cmd
+ *  @arg            argument
+ *  @return    -ENOIOCTLCMD
+ */
+static int
+mdev_ioctl(struct m_dev *m_dev, unsigned int cmd, void *arg)
+{
+	bt_private *priv = NULL;
+	int ret = 0;
+#ifdef BLE_WAKEUP
+	u16 len;
+#endif
+
+	ENTER();
+
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Ioctl for unknown device (m_dev=NULL)\n");
+		ret = -ENODEV;
+		goto done;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "HCI_RUNNING not set, flag=0x%lx\n",
+		       m_dev->flags);
+		ret = -EBUSY;
+		goto done;
+	}
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+#ifdef BLE_WAKEUP
+	case MBTCHAR_IOCTL_BLE_WAKEUP_PARAM:
+		PRINTM(MSG, "BT: Set ble wakeup parameters\n");
+		if (copy_from_user(&len, arg, sizeof(u16))) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Fail to copy ble wakeup params length\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		/** Convert little endian length */
+		len = __le16_to_cpu(len);
+		if (len < 2) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Invalid ble wakeup params len %d\n",
+			       len);
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((len + sizeof(u16)) > priv->ble_wakeup_buf_size) {
+			if (priv->ble_wakeup_buf) {
+				kfree(priv->ble_wakeup_buf);
+				priv->ble_wakeup_buf = NULL;
+				priv->ble_wakeup_buf_size = 0;
+			}
+			priv->ble_wakeup_buf =
+				kzalloc(len + sizeof(u16), GFP_KERNEL);
+			if (!priv->ble_wakeup_buf) {
+				PRINTM(ERROR, "BT_IOCTL: Fail to alloc buffer\t"
+				       "for ble wakeup parameters\n");
+				ret = -ENOMEM;
+				goto done;
+			}
+			priv->ble_wakeup_buf_size = len + sizeof(u16);
+		}
+		if (copy_from_user
+		    (priv->ble_wakeup_buf, arg, len + sizeof(u16))) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Fail to copy ble wakeup params\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		DBG_HEXDUMP(DAT_D, "BLE_WAKEUP_PARAM:", priv->ble_wakeup_buf,
+			    len + sizeof(u16));
+		break;
+	case MBTCHAR_IOCTL_BLE_GET_WHITELIST:
+		bt_get_whitelist_cmd(priv);
+		DBG_HEXDUMP(DAT_D, "white_list:", priv->white_list,
+			    sizeof(priv->white_list));
+		break;
+#endif
+	default:
+		break;
+	}
+
+done:
+#ifdef BLE_WAKEUP
+	if (ret && priv->ble_wakeup_buf) {
+		kfree(priv->ble_wakeup_buf);
+		priv->ble_wakeup_buf = NULL;
+		priv->ble_wakeup_buf_size = 0;
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles wrapper device destruct
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    N/A
+ */
+static void
+mdev_destruct(struct m_dev *m_dev)
+{
+	ENTER();
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handles the wrapper device transmit
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    BT_STATUS_SUCCESS or other error no.
+ */
+static int
+mdev_send_frame(struct m_dev *m_dev, struct sk_buff *skb)
+{
+	bt_private *priv = NULL;
+
+	ENTER();
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Frame for unknown HCI device (m_dev=NULL)\n");
+		LEAVE();
+		return -ENODEV;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "Fail test HCI_RUNNING, flag=0x%lx\n",
+		       m_dev->flags);
+		LEAVE();
+		return -EBUSY;
+	}
+	switch (bt_cb(skb)->pkt_type) {
+	case HCI_COMMAND_PKT:
+		m_dev->stat.cmd_tx++;
+		break;
+	case HCI_ACLDATA_PKT:
+		m_dev->stat.acl_tx++;
+		break;
+	case HCI_SCODATA_PKT:
+		m_dev->stat.sco_tx++;
+		break;
+	}
+
+	if (m_dev->dev_type == DEBUG_TYPE) {
+		/* remember the ogf_ocf */
+		priv->debug_device_pending = 1;
+		priv->debug_ocf_ogf[0] = skb->data[0];
+		priv->debug_ocf_ogf[1] = skb->data[1];
+		PRINTM(CMD, "debug_ocf_ogf[0]=0x%x debug_ocf_ogf[1]=0x%x\n",
+		       priv->debug_ocf_ogf[0], priv->debug_ocf_ogf[1]);
+	}
+
+	if (priv->adapter->tx_lock == TRUE)
+		skb_queue_tail(&priv->adapter->pending_queue, skb);
+	else
+		bt_queue_frame(priv, skb);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function flushes the transmit queue
+ *
+ *  @param m_dev     A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_flush(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	skb_queue_purge(&priv->adapter->pending_queue);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function closes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_close(struct m_dev *m_dev)
+{
+
+	ENTER();
+	mdev_req_lock(m_dev);
+	if (!test_and_clear_bit(HCI_UP, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+
+	if (m_dev->flush)
+		m_dev->flush(m_dev);
+	/* wait up pending read and unregister char dev */
+	wake_up_interruptible(&m_dev->req_wait_q);
+	/* Drop queues */
+	skb_queue_purge(&m_dev->rx_q);
+	if (!test_and_clear_bit(HCI_RUNNING, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+	module_put(THIS_MODULE);
+	m_dev->flags = 0;
+	mdev_req_unlock(m_dev);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function opens the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+static int
+mdev_open(struct m_dev *m_dev)
+{
+	ENTER();
+
+	if (try_module_get(THIS_MODULE) == 0)
+		return BT_STATUS_FAILURE;
+
+	set_bit(HCI_RUNNING, &m_dev->flags);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function queries the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param arg     arguement
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+mdev_query(struct m_dev *m_dev, void *arg)
+{
+	struct mbt_dev *mbt_dev = (struct mbt_dev *)m_dev->dev_pointer;
+
+	ENTER();
+	if (copy_to_user(arg, &mbt_dev->type, sizeof(mbt_dev->type)))
+		PRINTM(ERROR, "IOCTL_QUERY_TYPE: Fail copy to user\n");
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+init_m_dev(struct m_dev *m_dev)
+{
+	m_dev->dev_pointer = NULL;
+	m_dev->driver_data = NULL;
+	m_dev->dev_type = 0;
+	m_dev->spec_type = 0;
+	skb_queue_head_init(&m_dev->rx_q);
+	init_waitqueue_head(&m_dev->req_wait_q);
+	init_waitqueue_head(&m_dev->rx_wait_q);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+	init_MUTEX(&m_dev->req_lock);
+#else
+	sema_init(&m_dev->req_lock, 1);
+#endif
+	spin_lock_init(&m_dev->rxlock);
+	memset(&m_dev->stat, 0, sizeof(struct hci_dev_stats));
+	m_dev->open = mdev_open;
+	m_dev->close = mdev_close;
+	m_dev->flush = mdev_flush;
+	m_dev->send = mdev_send_frame;
+	m_dev->destruct = mdev_destruct;
+	m_dev->ioctl = mdev_ioctl;
+	m_dev->query = mdev_query;
+	m_dev->owner = THIS_MODULE;
+
+}
+
+/**
+ *  @brief This function handles the major job in bluetooth driver.
+ *  it handles the event generated by firmware, rx data received
+ *  from firmware and tx data sent from kernel.
+ *
+ *  @param data    A pointer to bt_thread structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+static int
+bt_service_main_thread(void *data)
+{
+	bt_thread *thread = data;
+	bt_private *priv = thread->priv;
+	bt_adapter *adapter = priv->adapter;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
+	wait_queue_t wait;
+#else
+	wait_queue_entry_t wait;
+#endif
+	struct sk_buff *skb;
+	ENTER();
+	bt_activate_thread(thread);
+	init_waitqueue_entry(&wait, current);
+	current->flags |= PF_NOFREEZE;
+
+	for (;;) {
+		add_wait_queue(&thread->waitQ, &wait);
+		OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE);
+		if (priv->adapter->WakeupTries ||
+		    ((!priv->adapter->IntCounter) &&
+		     (!priv->bt_dev.tx_dnld_rdy ||
+		      skb_queue_empty(&priv->adapter->tx_queue))
+		    )) {
+			PRINTM(INFO, "Main: Thread sleeping...\n");
+			schedule();
+		}
+		OS_SET_THREAD_STATE(TASK_RUNNING);
+		remove_wait_queue(&thread->waitQ, &wait);
+		if (kthread_should_stop() || adapter->SurpriseRemoved) {
+			PRINTM(INFO, "main-thread: break from main thread: "
+			       "SurpriseRemoved=0x%x\n",
+			       adapter->SurpriseRemoved);
+			break;
+		}
+
+		PRINTM(INFO, "Main: Thread waking up...\n");
+
+		if (priv->adapter->IntCounter) {
+			OS_INT_DISABLE;
+			adapter->IntCounter = 0;
+			OS_INT_RESTORE;
+			sbi_get_int_status(priv);
+		} else if ((priv->adapter->ps_state == PS_SLEEP) &&
+			   (!skb_queue_empty(&priv->adapter->tx_queue)
+			   )) {
+			priv->adapter->WakeupTries++;
+			sbi_wakeup_firmware(priv);
+			continue;
+		}
+		if (priv->adapter->ps_state == PS_SLEEP)
+			continue;
+		if (priv->bt_dev.tx_dnld_rdy == TRUE) {
+			if (!skb_queue_empty(&priv->adapter->tx_queue)) {
+				skb = skb_dequeue(&priv->adapter->tx_queue);
+				if (skb)
+					send_single_packet(priv, skb);
+			}
+		}
+	}
+	bt_deactivate_thread(thread);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the interrupt. it will change PS
+ *  state if applicable. it will wake up main_thread to handle
+ *  the interrupt event as well.
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @return        N/A
+ */
+void
+bt_interrupt(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	if (!priv || !priv->adapter) {
+		LEAVE();
+		return;
+	}
+	PRINTM(INTR, "*\n");
+	priv->adapter->ps_state = PS_AWAKE;
+	if (priv->adapter->hs_state == HS_ACTIVATED) {
+		PRINTM(CMD, "BT: %s: HS DEACTIVATED in ISR!\n", m_dev->name);
+		priv->adapter->hs_state = HS_DEACTIVATED;
+	}
+	priv->adapter->WakeupTries = 0;
+	priv->adapter->IntCounter++;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	LEAVE();
+}
+
+/**
+ * @brief  Dynamic release of char dev
+ *
+ * @param kobj          A pointer to kobject structure
+ *
+ * @return                N/A
+ */
+static void
+char_dev_release_dynamic(struct kobject *kobj)
+{
+	struct char_dev *cdev = container_of(kobj, struct char_dev, kobj);
+	ENTER();
+	PRINTM(INFO, "free char_dev\n");
+	kfree(cdev);
+	LEAVE();
+}
+
+static struct kobj_type ktype_char_dev_dynamic = {
+	.release = char_dev_release_dynamic,
+};
+
+/**
+ * @brief  Allocation of char dev
+ *
+ * @param           	N/A
+ *
+ * @return              char_dev
+ */
+static struct char_dev *
+alloc_char_dev(void)
+{
+	struct char_dev *cdev;
+	ENTER();
+	cdev = kzalloc(sizeof(struct char_dev), GFP_KERNEL);
+	if (cdev) {
+		kobject_init(&cdev->kobj, &ktype_char_dev_dynamic);
+		PRINTM(INFO, "alloc char_dev\n");
+	}
+	return cdev;
+}
+
+/**
+ * @brief  Dynamic release of bt private
+ *
+ * @param kobj          A pointer to kobject structure
+ *
+ * @return                N/A
+ */
+static void
+bt_private_dynamic_release(struct kobject *kobj)
+{
+	bt_private *priv = container_of(kobj, bt_private, kobj);
+	ENTER();
+	PRINTM(INFO, "free bt priv\n");
+	kfree(priv);
+	LEAVE();
+}
+
+static struct kobj_type ktype_bt_private_dynamic = {
+	.release = bt_private_dynamic_release,
+};
+
+/**
+ * @brief  Allocation of bt private
+ *
+ * @param           	N/A
+ *
+ * @return              bt_private
+ */
+static bt_private *
+bt_alloc_priv(void)
+{
+	bt_private *priv;
+	ENTER();
+	priv = kzalloc(sizeof(bt_private), GFP_KERNEL);
+	if (priv) {
+		kobject_init(&priv->kobj, &ktype_bt_private_dynamic);
+		PRINTM(INFO, "alloc bt priv\n");
+	}
+	LEAVE();
+	return priv;
+}
+
+/**
+ * @brief  Get bt private structure
+ *
+ * @param priv          A pointer to bt_private structure
+ *
+ * @return              kobject structure
+ */
+struct kobject *
+bt_priv_get(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv get object");
+	return kobject_get(&priv->kobj);
+}
+
+/**
+ * @brief  Get bt private structure
+ *
+ * @param priv          A pointer to bt_private structure
+ *
+ * @return              N/A
+ */
+void
+bt_priv_put(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv put object");
+	kobject_put(&priv->kobj);
+}
+
+/**
+ *  @brief This function send init commands to firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_init_cmd(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = bt_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+	if (ret < 0) {
+		PRINTM(FATAL, "Module cfg command send failed!\n");
+		goto done;
+	}
+	PRINTM(MSG, "BT: btindrst=0x%x\n", btindrst);
+	if (btindrst != -1) {
+		ret = bt_set_independent_reset(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Independent reset failed!\n");
+			goto done;
+		}
+	}
+	if (btpmic
+	    && ((priv->card_type == CARD_TYPE_SD8997) ||
+		(priv->card_type == CARD_TYPE_SD8977) ||
+		(priv->card_type == CARD_TYPE_SD8978))
+		) {
+		if (BT_STATUS_SUCCESS != bt_pmic_configure(priv)) {
+			PRINTM(FATAL, "BT: PMIC Configure failed \n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	ret = bt_set_ble_deepsleep(priv, deep_sleep ? TRUE : FALSE);
+	if (ret < 0) {
+		PRINTM(FATAL, "%s BLE deepsleep failed!\n",
+		       deep_sleep ? "Enable" : "Disable");
+		goto done;
+	}
+	if (psmode) {
+		priv->bt_dev.psmode = TRUE;
+		priv->bt_dev.idle_timeout = DEFAULT_IDLE_TIME;
+		ret = bt_enable_ps(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Enable PS mode failed!\n");
+			goto done;
+		}
+	}
+#if defined(SDIO_SUSPEND_RESUME)
+	priv->bt_dev.gpio_gap = DEF_GPIO_GAP;
+	ret = bt_send_hscfg_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "Send HSCFG failed!\n");
+		goto done;
+	}
+#endif
+	priv->bt_dev.sdio_pull_cfg = 0xffffffff;
+	priv->bt_dev.sdio_pull_ctrl = 0;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reinit firmware after redownload firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_reinit_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+	/* block all the packet from bluez */
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext)
+		priv->adapter->tx_lock = TRUE;
+
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext) {
+		priv->adapter->tx_lock = FALSE;
+		bt_restore_tx_queue(priv);
+	}
+
+	if (init_cmds) {
+		if (BT_STATUS_SUCCESS != bt_init_cmds(priv, init_cmds)) {
+			PRINTM(FATAL, "BT: Set user init commands failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+done:
+	return ret;
+}
+
+/**
+ *  @brief Module configuration and register device
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @return      BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_conf_dpc(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct mbt_dev *mbt_dev = NULL;
+	struct debug_dev *debug_dev = NULL;
+	int i = 0;
+	struct char_dev *char_dev = NULL;
+	char dev_file[DEV_NAME_LEN + 5];
+	unsigned char dev_type = 0;
+
+	ENTER();
+
+	priv->bt_dev.tx_dnld_rdy = TRUE;
+	if (priv->fw_reload) {
+		bt_reinit_fw(priv);
+		LEAVE();
+		return ret;
+	}
+
+	if (drv_mode & DRV_MODE_BT) {
+		mbt_dev = alloc_mbt_dev();
+		if (!mbt_dev) {
+			PRINTM(FATAL, "Can not allocate mbt dev\n");
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		init_m_dev(&(priv->bt_dev.m_dev[BT_SEQ]));
+		priv->bt_dev.m_dev[BT_SEQ].dev_type = BT_TYPE;
+		priv->bt_dev.m_dev[BT_SEQ].spec_type = IANYWHERE_SPEC;
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = (void *)mbt_dev;
+		priv->bt_dev.m_dev[BT_SEQ].driver_data = priv;
+	}
+
+	dev_type = HCI_SDIO;
+
+	if (mbt_dev)
+		mbt_dev->type = dev_type;
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+
+	if (mbt_dev && priv->bt_dev.devType == DEV_TYPE_AMP) {
+		mbt_dev->type |= HCI_BT_AMP;
+		priv->bt_dev.m_dev[BT_SEQ].dev_type = BT_AMP_TYPE;
+	}
+	/** Process device tree init parameters before register hci device.
+	 *  Since uplayer device has not yet registered, no need to block tx queue.
+	 * */
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	} else if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (init_cmds) {
+		if (BT_STATUS_SUCCESS != bt_init_cmds(priv, init_cmds)) {
+			PRINTM(FATAL, "BT: Set user init commands failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Get FW version */
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+
+	if (mbt_dev) {
+		/** init mbt_dev */
+		mbt_dev->flags = 0;
+		mbt_dev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
+		mbt_dev->esco_type = (ESCO_HV1);
+		mbt_dev->link_mode = (HCI_LM_ACCEPT);
+
+		mbt_dev->idle_timeout = 0;
+		mbt_dev->sniff_max_interval = 800;
+		mbt_dev->sniff_min_interval = 80;
+		for (i = 0; i < 3; i++)
+			mbt_dev->reassembly[i] = NULL;
+		atomic_set(&mbt_dev->promisc, 0);
+
+		/** alloc char dev node */
+		char_dev = alloc_char_dev();
+		if (!char_dev) {
+			class_destroy(chardev_class);
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		char_dev->minor = MBTCHAR_MINOR_BASE + mbtchar_minor;
+		if (mbt_dev->type & HCI_BT_AMP)
+			char_dev->dev_type = BT_AMP_TYPE;
+		else
+			char_dev->dev_type = BT_TYPE;
+
+		if (bt_name)
+			snprintf(mbt_dev->name, sizeof(mbt_dev->name), "%s%d",
+				 bt_name, mbtchar_minor);
+		else
+			snprintf(mbt_dev->name, sizeof(mbt_dev->name),
+				 "mbtchar%d", mbtchar_minor);
+		snprintf(dev_file, sizeof(dev_file), "/dev/%s", mbt_dev->name);
+		mbtchar_minor++;
+		PRINTM(MSG, "BT: Create %s\n", dev_file);
+
+		/** register m_dev to BT char device */
+		priv->bt_dev.m_dev[BT_SEQ].index = char_dev->minor;
+		char_dev->m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+
+		/** create BT char device node */
+		register_char_dev(char_dev, chardev_class, MODULE_NAME,
+				  mbt_dev->name);
+
+		/** chmod & chown for BT char device */
+		mbtchar_chown(dev_file, AID_SYSTEM, AID_NET_BT_STACK);
+		mbtchar_chmod(dev_file, 0666);
+
+		/** create proc device */
+		snprintf(priv->bt_dev.m_dev[BT_SEQ].name,
+			 sizeof(priv->bt_dev.m_dev[BT_SEQ].name),
+			 mbt_dev->name);
+		bt_proc_init(priv, &(priv->bt_dev.m_dev[BT_SEQ]), BT_SEQ);
+	}
+
+	if ((debug_intf) && ((drv_mode & DRV_MODE_BT)
+	    )) {
+		/** alloc debug_dev */
+		debug_dev = alloc_debug_dev();
+		if (!debug_dev) {
+			PRINTM(FATAL, "Can not allocate debug dev\n");
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+
+		/** init m_dev */
+		init_m_dev(&(priv->bt_dev.m_dev[DEBUG_SEQ]));
+		priv->bt_dev.m_dev[DEBUG_SEQ].dev_type = DEBUG_TYPE;
+		priv->bt_dev.m_dev[DEBUG_SEQ].spec_type = GENERIC_SPEC;
+		priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer = (void *)debug_dev;
+		priv->bt_dev.m_dev[DEBUG_SEQ].driver_data = priv;
+
+		/** create char device for Debug */
+		char_dev = alloc_char_dev();
+		if (!char_dev) {
+			class_destroy(chardev_class);
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		char_dev->minor = DEBUGCHAR_MINOR_BASE + debugchar_minor;
+		char_dev->dev_type = DEBUG_TYPE;
+		if (debug_name)
+			snprintf(debug_dev->name, sizeof(debug_dev->name),
+				 "%s%d", debug_name, debugchar_minor);
+		else
+			snprintf(debug_dev->name, sizeof(debug_dev->name),
+				 "mdebugchar%d", debugchar_minor);
+		snprintf(dev_file, sizeof(dev_file), "/dev/%s",
+			 debug_dev->name);
+		PRINTM(MSG, "BT: Create %s\n", dev_file);
+		debugchar_minor++;
+
+		/** register char dev */
+		priv->bt_dev.m_dev[DEBUG_SEQ].index = char_dev->minor;
+		char_dev->m_dev = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
+		register_char_dev(char_dev, chardev_class, MODULE_NAME,
+				  debug_dev->name);
+
+		/** chmod for debug char device */
+		mbtchar_chmod(dev_file, 0666);
+
+		/** create proc device */
+		snprintf(priv->bt_dev.m_dev[DEBUG_SEQ].name,
+			 sizeof(priv->bt_dev.m_dev[DEBUG_SEQ].name),
+			 debug_dev->name);
+		bt_proc_init(priv, &(priv->bt_dev.m_dev[DEBUG_SEQ]), DEBUG_SEQ);
+	}
+
+done:
+	LEAVE();
+	return ret;
+err_kmalloc:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function adds the card. it will probe the
+ *  card, allocate the bt_priv and initialize the device.
+ *
+ *  @param card    A pointer to card
+ *  @return        A pointer to bt_private structure
+ */
+
+bt_private *
+bt_add_card(void *card)
+{
+	bt_private *priv = NULL;
+	int index = 0;
+
+	ENTER();
+
+	priv = bt_alloc_priv();
+	if (!priv) {
+		PRINTM(FATAL, "Can not allocate priv\n");
+		LEAVE();
+		return NULL;
+	}
+	/* Save the handle */
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == NULL)
+			break;
+	}
+	if (index < MAX_BT_ADAPTER) {
+		m_priv[index] = priv;
+	} else {
+		PRINTM(ERROR, "Exceeded maximum cards supported!\n");
+		goto err_kmalloc;
+	}
+	/* allocate buffer for bt_adapter */
+	priv->adapter = kzalloc(sizeof(bt_adapter), GFP_KERNEL);
+	if (!priv->adapter) {
+		PRINTM(FATAL, "Allocate buffer for bt_adapter failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buffer =
+		kzalloc(MAX_TX_BUF_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->tx_buffer) {
+		PRINTM(FATAL, "Allocate buffer for transmit\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buf =
+		(u8 *)ALIGN_ADDR(priv->adapter->tx_buffer, DMA_ALIGNMENT);
+	priv->adapter->hw_regs_buf =
+		kzalloc(SD_BLOCK_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->hw_regs_buf) {
+		PRINTM(FATAL, "Allocate buffer for INT read buf failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->hw_regs =
+		(u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf, DMA_ALIGNMENT);
+	bt_init_adapter(priv);
+
+	PRINTM(INFO, "Starting kthread...\n");
+	priv->MainThread.priv = priv;
+	spin_lock_init(&priv->driver_lock);
+
+	bt_create_thread(bt_service_main_thread, &priv->MainThread,
+			 "bt_main_service");
+
+	/* wait for mainthread to up */
+	while (!priv->MainThread.pid)
+		os_sched_timeout(1);
+
+	sdio_update_card_type(priv, card);
+	/* Update driver version */
+	if (priv->card_type == CARD_TYPE_SD8787)
+		memcpy(mbt_driver_version, CARD_SD8787, strlen(CARD_SD8787));
+	else if (priv->card_type == CARD_TYPE_SD8777)
+		memcpy(mbt_driver_version, CARD_SD8777, strlen(CARD_SD8777));
+	else if (priv->card_type == CARD_TYPE_SD8887)
+		memcpy(mbt_driver_version, CARD_SD8887, strlen(CARD_SD8887));
+	else if (priv->card_type == CARD_TYPE_SD8897)
+		memcpy(mbt_driver_version, CARD_SD8897, strlen(CARD_SD8897));
+	else if (priv->card_type == CARD_TYPE_SD8797)
+		memcpy(mbt_driver_version, CARD_SD8797, strlen(CARD_SD8797));
+	else if (priv->card_type == CARD_TYPE_SD8977)
+		memcpy(mbt_driver_version, CARD_SD8977, strlen(CARD_SD8977));
+	else if (priv->card_type == CARD_TYPE_SD8978)
+		memcpy(mbt_driver_version, CARD_SD8978, strlen(CARD_SD8978));
+	else if (priv->card_type == CARD_TYPE_SD8997)
+		memcpy(mbt_driver_version, CARD_SD8997, strlen(CARD_SD8997));
+	else if (priv->card_type == CARD_TYPE_SD8987)
+		memcpy(mbt_driver_version, CARD_SD8987, strlen(CARD_SD8987));
+
+	if (BT_STATUS_SUCCESS != sdio_get_sdio_device(priv))
+		goto err_kmalloc;
+
+	/** user config file */
+	init_waitqueue_head(&priv->init_user_conf_wait_q);
+
+	priv->bt_dev.card = card;
+
+	((struct sdio_mmc_card *)card)->priv = priv;
+	priv->adapter->sd_ireg = 0;
+	/*
+	 * Register the device. Fillup the private data structure with
+	 * relevant information from the card and request for the required
+	 * IRQ.
+	 */
+	if (sbi_register_dev(priv) < 0) {
+		PRINTM(FATAL, "Failed to register bt device!\n");
+		goto err_registerdev;
+	}
+	if (bt_init_fw(priv)) {
+		PRINTM(FATAL, "BT Firmware Init Failed\n");
+		goto err_init_fw;
+	}
+	LEAVE();
+	return priv;
+
+err_init_fw:
+	clean_up_m_devs(priv);
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+err_registerdev:
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+err_kmalloc:
+	if (priv->adapter)
+		bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function send hardware remove event
+ *
+ *  @param priv    A pointer to bt_private
+ *  @return        N/A
+ */
+void
+bt_send_hw_remove_event(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+	ENTER();
+	if (!priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		LEAVE();
+		return;
+	}
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+#define HCI_HARDWARE_ERROR_EVT  0x10
+#define HCI_HARDWARE_REMOVE     0x24
+	skb = bt_skb_alloc(3, GFP_ATOMIC);
+	skb->data[0] = HCI_HARDWARE_ERROR_EVT;
+	skb->data[1] = 1;
+	skb->data[2] = HCI_HARDWARE_REMOVE;
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb_put(skb, 3);
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		PRINTM(MSG, "Send HW ERROR event\n");
+		if (!mdev_recv_frame(skb)) {
+#define RX_WAIT_TIMEOUT				300
+			mdev_bt->wait_rx_complete = TRUE;
+			mdev_bt->rx_complete_flag = FALSE;
+			if (os_wait_interruptible_timeout
+			    (mdev_bt->rx_wait_q, mdev_bt->rx_complete_flag,
+			     RX_WAIT_TIMEOUT))
+				PRINTM(MSG, "BT stack received the event\n");
+			mdev_bt->stat.byte_rx += 3;
+		}
+	}
+	LEAVE();
+	return;
+}
+
+#ifdef BLE_WAKEUP
+/**
+ *  @brief This function used to config BLE wakeup pattern
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param is_shutdown  indicate shutdown mode
+ *  @return        N/A
+ */
+int
+bt_config_ble_wakeup(bt_private *priv, bool is_shutdown)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	u16 ocf = 0, left_len;
+	u8 len, more_cmd;
+	u8 *pos;
+
+	ENTER();
+
+	if (!priv->ble_wakeup_buf) {
+		PRINTM(ERROR, "BT: no ble wakeup parameters found\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MSG, "Config ble wakeup pattern\n");
+
+	pos = priv->ble_wakeup_buf;
+	left_len = *(u16 *) pos;
+	left_len = __le16_to_cpu(left_len);
+	pos += sizeof(u16);
+
+	while (left_len >= 2) {
+		more_cmd = *pos;
+		len = *(pos + 1);
+		if (((len + 2) > left_len) ||
+		    (!more_cmd && ((len + 2) < left_len))) {
+			PRINTM(ERROR, "Invalid ble parameters\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		if (ocf == BT_CMD_ENABLE_WRITE_SCAN)
+			bt_send_whitelist_cmd(priv, is_shutdown);
+		skb = bt_skb_alloc(len, GFP_ATOMIC);
+		if (!skb) {
+			PRINTM(ERROR, "BT BLE WAKEUP: fail to alloc skb\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy(skb_put(skb, len), pos + 2, len);
+		bt_cb(skb)->pkt_type = *(u8 *)skb->data;
+		skb_pull(skb, 1);
+		DBG_HEXDUMP(DAT_D, "BLE_WAKEUP_CMD:", skb->data, skb->len);
+		skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+		skb_queue_head(&priv->adapter->tx_queue, skb);
+		priv->bt_dev.sendcmdflag = TRUE;
+		priv->bt_dev.send_cmd_opcode = *(u16 *) skb->data;
+		ocf = hci_opcode_ocf(priv->bt_dev.send_cmd_opcode);
+		priv->adapter->cmd_complete = FALSE;
+		priv->adapter->wait_event_timeout = is_shutdown;
+
+		wake_up_interruptible(&priv->MainThread.waitQ);
+		if (is_shutdown) {
+			if (!os_wait_timeout
+			    (priv->adapter->cmd_wait_q,
+			     priv->adapter->cmd_complete,
+			     WAIT_UNTIL_CMD_RESP)) {
+				ret = BT_STATUS_FAILURE;
+				priv->adapter->wait_event_timeout = FALSE;
+				PRINTM(ERROR,
+				       "BT: Set  Set ble wakeup cmd 0x%x timeout:\n",
+				       priv->bt_dev.send_cmd_opcode);
+				bt_cmd_timeout_func(priv, ocf);
+				goto done;
+			}
+		} else {
+			if (!os_wait_interruptible_timeout
+			    (priv->adapter->cmd_wait_q,
+			     priv->adapter->cmd_complete,
+			     WAIT_UNTIL_CMD_RESP)) {
+				ret = BT_STATUS_FAILURE;
+				PRINTM(ERROR,
+				       "BT: Set  Set ble wakeup cmd 0x%x timeout:\n",
+				       priv->bt_dev.send_cmd_opcode);
+				bt_cmd_timeout_func(priv, ocf);
+				goto done;
+			}
+		}
+
+		pos += len + 2;
+		left_len -= len + 2;
+	}
+
+done:
+	if (ret != BT_STATUS_SUCCESS) {
+		if (priv->ble_wakeup_buf) {
+			kfree(priv->ble_wakeup_buf);
+			priv->ble_wakeup_buf = NULL;
+			priv->ble_wakeup_buf_size = 0;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function send system suspend event
+ *
+ *  @param priv    A pointer to bt_private
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_send_system_event(bt_private *priv, u8 flag)
+{
+	struct sk_buff *skb = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+
+	ENTER();
+
+	if (!priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+
+	skb = bt_skb_alloc(4, GFP_ATOMIC);
+	if (!skb) {
+		PRINTM(ERROR, "Fail to allocate sys suspend event skb\n");
+		return BT_STATUS_FAILURE;
+	}
+	skb->data[0] = VENDOR_SPECIFIC_EVENT;
+	skb->data[1] = 2;
+	skb->data[2] = HCI_SYSTEM_SUSPEND_EVT;
+	if (flag)
+		skb->data[3] = HCI_SYSTEM_SUSPEND;
+	else
+		skb->data[3] = HCI_SYSTEM_RESUME;
+
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb_put(skb, 4);
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		PRINTM(MSG, "Send system %s event\n",
+		       flag ? "suspend" : "resume");
+		if (!mdev_recv_frame(skb)) {
+#define RX_WAIT_TIMEOUT                         300
+			mdev_bt->wait_rx_complete = TRUE;
+			mdev_bt->rx_complete_flag = FALSE;
+			if (os_wait_interruptible_timeout(mdev_bt->rx_wait_q,
+							  mdev_bt->
+							  rx_complete_flag,
+							  RX_WAIT_TIMEOUT))
+				PRINTM(MSG, "BT stack received the event\n");
+			mdev_bt->stat.byte_rx += 4;
+		}
+	}
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function removes the card.
+ *
+ *  @param card    A pointer to card
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_remove_card(void *card)
+{
+	bt_private *priv = (bt_private *)card;
+	int index;
+	ENTER();
+	if (!priv) {
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv->adapter->SurpriseRemoved = TRUE;
+
+	bt_send_hw_remove_event(priv);
+#ifdef BLE_WAKEUP
+	if (priv->ble_wakeup_buf) {
+		kfree(priv->ble_wakeup_buf);
+		priv->ble_wakeup_buf = NULL;
+		priv->ble_wakeup_buf_size = 0;
+	}
+#endif
+	wake_up_interruptible(&priv->adapter->cmd_wait_q);
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid) {
+		os_sched_timeout(1);
+		wake_up_interruptible(&priv->MainThread.waitQ);
+	}
+
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+	clean_up_m_devs(priv);
+	PRINTM(INFO, "Free Adapter\n");
+	bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function initializes module.
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_module(void)
+{
+	int ret = BT_STATUS_SUCCESS;
+	int index;
+	ENTER();
+	PRINTM(MSG, "BT: Loading driver\n");
+	/* Init the bt_private pointer array first */
+	for (index = 0; index < MAX_BT_ADAPTER; index++)
+		m_priv[index] = NULL;
+	bt_root_proc_init();
+
+	/** create char device class */
+	chardev_class = class_create(THIS_MODULE, MODULE_NAME);
+	if (IS_ERR(chardev_class)) {
+		PRINTM(ERROR, "Unable to allocate class\n");
+		bt_root_proc_remove();
+		ret = PTR_ERR(chardev_class);
+		goto done;
+	}
+
+	if (sbi_register() == NULL) {
+		bt_root_proc_remove();
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	if (ret)
+		PRINTM(MSG, "BT: Driver loading failed\n");
+	else
+		PRINTM(MSG, "BT: Driver loaded successfully\n");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function cleans module
+ *
+ *  @return        N/A
+ */
+static void
+bt_exit_module(void)
+{
+	bt_private *priv;
+	int index;
+	ENTER();
+	PRINTM(MSG, "BT: Unloading driver\n");
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		priv = m_priv[index];
+		if (!priv)
+			continue;
+		if (priv && !priv->adapter->SurpriseRemoved) {
+			if (BT_STATUS_SUCCESS == bt_send_reset_command(priv))
+				bt_send_module_cfg_cmd(priv,
+						       MODULE_SHUTDOWN_REQ);
+		}
+		sbi_disable_host_int(priv);
+
+	}
+
+	sbi_unregister();
+
+	bt_root_proc_remove();
+	class_destroy(chardev_class);
+	PRINTM(MSG, "BT: Driver unloaded\n");
+	LEAVE();
+}
+
+module_init(bt_init_module);
+module_exit(bt_exit_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell Bluetooth Driver Ver. " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+module_param(fw, int, 0);
+MODULE_PARM_DESC(fw, "0: Skip firmware download; otherwise: Download firmware");
+module_param(fw_crc_check, int, 0);
+MODULE_PARM_DESC(fw_crc_check,
+		 "1: Enable FW download CRC check (default); 0: Disable FW download CRC check");
+module_param(psmode, int, 0);
+MODULE_PARM_DESC(psmode, "1: Enable powermode; 0: Disable powermode");
+module_param(deep_sleep, int, 0);
+MODULE_PARM_DESC(deep_sleep, "1: Enable deep sleep; 0: Disable deep sleep");
+#ifdef CONFIG_OF
+module_param(dts_enable, int, 0);
+MODULE_PARM_DESC(dts_enable, "0: Disable DTS; 1: Enable DTS");
+#endif
+#ifdef	DEBUG_LEVEL1
+module_param(mbt_drvdbg, uint, 0);
+MODULE_PARM_DESC(mbt_drvdbg, "BIT3:DBG_DATA BIT4:DBG_CMD 0xFF:DBG_ALL");
+#endif
+#ifdef SDIO_SUSPEND_RESUME
+module_param(mbt_pm_keep_power, int, 0);
+MODULE_PARM_DESC(mbt_pm_keep_power, "1: PM keep power; 0: PM no power");
+#endif
+module_param(init_cfg, charp, 0);
+MODULE_PARM_DESC(init_cfg, "BT init config file name");
+module_param(cal_cfg, charp, 0);
+MODULE_PARM_DESC(cal_cfg, "BT calibrate file name");
+module_param(cal_cfg_ext, charp, 0);
+MODULE_PARM_DESC(cal_cfg_ext, "BT calibrate ext file name");
+module_param(bt_mac, charp, 0660);
+MODULE_PARM_DESC(bt_mac, "BT init mac address");
+module_param(init_cmds, charp, 0);
+MODULE_PARM_DESC(init_cmds, "BT init commands file name");
+module_param(drv_mode, int, 0);
+MODULE_PARM_DESC(drv_mode, "Bit 0: BT/AMP/BLE;");
+module_param(bt_name, charp, 0);
+MODULE_PARM_DESC(bt_name, "BT interface name");
+module_param(debug_intf, int, 0);
+MODULE_PARM_DESC(debug_intf,
+		 "1: Enable debug interface; 0: Disable debug interface ");
+module_param(debug_name, charp, 0);
+MODULE_PARM_DESC(debug_name, "Debug interface name");
+module_param(bt_fw_reload, int, 0);
+MODULE_PARM_DESC(bt_fw_reload,
+		 "0: disable fw_reload; 1: enable fw reload feature");
+module_param(btindrst, int, 0);
+MODULE_PARM_DESC(btindrst,
+		 "Independent reset configuration; high byte:GPIO pin number;low byte:0x0:disable, 0x1:out-band reset, 0x2:in-band reset.");
+module_param(btpmic, int, 0);
+MODULE_PARM_DESC(btpmic,
+		 "1: Send pmic configure cmd to firmware; 0: No pmic configure cmd sent to firmware (default)");
+module_param(bt_fw_serial, int, 0);
+MODULE_PARM_DESC(bt_fw_serial,
+		 "0: Support parallel download FW; 1: Support serial download FW");
diff --git a/bt_sd8987/bt_char/bt_proc.c b/bt_sd8987/bt_char/bt_proc.c
new file mode 100644
index 0000000..0264c94
--- /dev/null
+++ b/bt_sd8987/bt_char/bt_proc.c
@@ -0,0 +1,723 @@
+/** @file bt_proc.c
+  *
+  * @brief This file handle the functions for proc files
+  *
+  * Copyright (C) 2007-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/proc_fs.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** proc diretory root */
+#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
+
+/** Proc mbt directory entry */
+static struct proc_dir_entry *proc_mbt;
+
+#define     CMD52_STR_LEN   50
+static char cmd52_string[CMD52_STR_LEN];
+
+/** proc data structure */
+struct proc_data {
+	/** Read length */
+	int rdlen;
+	/** Read buffer */
+	char *rdbuf;
+	/** Write length */
+	int wrlen;
+	/** Maximum write length */
+	int maxwrlen;
+	/** Write buffer */
+	char *wrbuf;
+	/** Private structure */
+	struct _bt_private *pbt;
+	void (*on_close) (struct inode *, struct file *);
+};
+
+/** Default file permission */
+#define DEFAULT_FILE_PERM  0644
+
+/** Bluetooth device offset */
+#define OFFSET_BT_DEV		0x01
+/** Bluetooth adapter offset */
+#define OFFSET_BT_ADAPTER	0x02
+/** Show integer */
+#define SHOW_INT		0x10
+/** Show hex */
+#define SHOW_HEX		0x20
+/** Show string */
+#define SHOW_STRING		0x40
+
+/** Device size */
+#define item_dev_size(n) (sizeof((bt_dev_t *)0)->n)
+/** Device address */
+#define item_dev_addr(n) ((t_ptr) &((bt_dev_t *)0)->n)
+
+/** Adapter size */
+#define item_adapter_size(n) (sizeof((bt_adapter *)0)->n)
+/** Adapter address */
+#define item_adapter_addr(n) ((t_ptr) &((bt_adapter *)0)->n)
+
+static struct item_data config_items[] = {
+#ifdef	DEBUG_LEVEL1
+	{"drvdbg", sizeof(u32), (t_ptr)&mbt_drvdbg, 0, SHOW_HEX}
+	,
+#endif
+	{"idle_timeout", item_dev_size(idle_timeout), 0,
+	 item_dev_addr(idle_timeout), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"psmode", item_dev_size(psmode), 0, item_dev_addr(psmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"pscmd", item_dev_size(pscmd), 0, item_dev_addr(pscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hsmode", item_dev_size(hsmode), 0, item_dev_addr(hsmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hscmd", item_dev_size(hscmd), 0, item_dev_addr(hscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"gpio_gap", item_dev_size(gpio_gap), 0, item_dev_addr(gpio_gap),
+	 OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"hscfgcmd", item_dev_size(hscfgcmd), 0, item_dev_addr(hscfgcmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"sdio_pull_cfg", item_dev_size(sdio_pull_cfg), 0,
+	 item_dev_addr(sdio_pull_cfg), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"sdio_pull_ctrl", item_dev_size(sdio_pull_ctrl), 0,
+	 item_dev_addr(sdio_pull_ctrl), OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"test_mode", item_dev_size(test_mode), 0, item_dev_addr(test_mode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+
+};
+
+static struct item_data status_items[] = {
+	{"version", item_adapter_size(drv_ver), 0, item_adapter_addr(drv_ver),
+	 OFFSET_BT_ADAPTER | SHOW_STRING},
+	{"tx_dnld_rdy", item_dev_size(tx_dnld_rdy), 0,
+	 item_dev_addr(tx_dnld_rdy),
+	 OFFSET_BT_DEV | SHOW_INT},
+	{"psmode", item_adapter_size(psmode), 0, item_adapter_addr(psmode),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_state", item_adapter_size(hs_state), 0,
+	 item_adapter_addr(hs_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_skip", item_adapter_size(hs_skip), 0, item_adapter_addr(hs_skip),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"ps_state", item_adapter_size(ps_state), 0,
+	 item_adapter_addr(ps_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"WakeupTries", item_adapter_size(WakeupTries), 0,
+	 item_adapter_addr(WakeupTries), OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_recv", item_adapter_size(irq_recv), 0,
+	 item_adapter_addr(irq_recv),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_done", item_adapter_size(irq_done), 0,
+	 item_adapter_addr(irq_done),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"skb_pending", item_adapter_size(skb_pending), 0,
+	 item_adapter_addr(skb_pending), OFFSET_BT_ADAPTER | SHOW_INT},
+};
+
+static struct item_data debug_items[] = {
+	{"sdcmd52rw", 0, (t_ptr)cmd52_string, 0, SHOW_STRING},
+};
+
+/**
+ *  @brief convert string to number
+ *
+ *  @param s	pointer to numbered string
+ *  @return	converted number from string s
+ */
+int
+string_to_number(char *s)
+{
+	int r = 0;
+	int base = 0;
+	int pn = 1;
+
+	if (strncmp(s, "-", 1) == 0) {
+		pn = -1;
+		s++;
+	}
+	if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
+		base = 16;
+		s += 2;
+	} else
+		base = 10;
+
+	for (s = s; *s != 0; 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 Create cmd52 string
+ *
+ *  @param priv	A pointer to bt_private structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+form_cmd52_string(bt_private *priv)
+{
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	snprintf(cmd52_string, CMD52_STR_LEN - 1, "BT: %d 0x%0x 0x%02X",
+		 priv->bt_dev.cmd52_func, priv->bt_dev.cmd52_reg,
+		 priv->bt_dev.cmd52_val);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/*
+ *  @brief Parse cmd52 string
+ *
+ *  @param buffer  A pointer user buffer
+ *  @param len     Length of 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 __user * buffer, size_t len,
+		   int *func, int *reg, int *val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	char *string = NULL;
+	char *pos = NULL;
+
+	ENTER();
+
+	string = kzalloc(CMD52_STR_LEN, GFP_KERNEL);
+	if (!string) {
+		PRINTM(ERROR, "BT: Can not alloc mem for cmd52 string\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	memcpy(string, buffer + strlen("sdcmd52rw="),
+	       len - strlen("sdcmd52rw="));
+	string = strstrip(string);
+
+	*func = -1;
+	*reg = -1;
+	*val = -1;
+
+	/* Get func */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*func = string_to_number(pos);
+
+	/* Get reg */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*reg = string_to_number(pos);
+
+	/* Get val (optional) */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*val = string_to_number(pos);
+	kfree(string);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handle generic proc file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+proc_close(struct inode *inode, struct file *file)
+{
+	struct proc_data *pdata = file->private_data;
+	ENTER();
+	if (pdata) {
+		if (pdata->on_close != NULL)
+			pdata->on_close(inode, file);
+		kfree(pdata->rdbuf);
+		kfree(pdata->wrbuf);
+		kfree(pdata);
+	}
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle generic proc file read
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to output buffer
+ *  @param len     number of byte to read
+ *  @param offset  A pointer to offset of file
+ *  @return		number of output data
+ */
+static ssize_t
+proc_read(struct file *file, char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	if ((!pdata->rdbuf) || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->rdlen)
+		return 0;
+	if (len > pdata->rdlen - pos)
+		len = pdata->rdlen - pos;
+	if (copy_to_user(buffer, pdata->rdbuf + pos, len))
+		return -EFAULT;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle generic proc file write
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to input buffer
+ *  @param len     number of byte to write
+ *  @param offset  A pointer to offset of file
+ *  @return		number of input data
+ */
+static ssize_t
+proc_write(struct file *file,
+	   const char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	int func = 0, reg = 0, val = 0;
+	int config_data = 0;
+	char *line = NULL;
+
+	if (!pdata->wrbuf || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->maxwrlen)
+		return 0;
+	if (len > pdata->maxwrlen - pos)
+		len = pdata->maxwrlen - pos;
+	if (copy_from_user(pdata->wrbuf + pos, buffer, len))
+		return -EFAULT;
+	if (!strncmp(pdata->wrbuf + pos, "fw_reload", strlen("fw_reload"))) {
+		if (!strncmp
+		    (pdata->wrbuf + pos, "fw_reload=", strlen("fw_reload="))) {
+			line = pdata->wrbuf + pos;
+			line += strlen("fw_reload") + 1;
+			config_data = string_to_number(line);
+		} else
+			config_data = FW_RELOAD_SDIO_INBAND_RESET;
+		PRINTM(MSG, "Request fw_reload=%d\n", config_data);
+		bt_request_fw_reload(pdata->pbt, config_data);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "sdcmd52rw=", strlen("sdcmd52rw="))) {
+		parse_cmd52_string(pdata->wrbuf + pos, len, &func, &reg, &val);
+		sd_write_cmd52_val(pdata->pbt, func, reg, val);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "debug_dump", strlen("debug_dump"))) {
+		bt_dump_sdio_regs(pdata->pbt);
+		bt_dump_firmware_info_v2(pdata->pbt);
+	}
+
+	if (pos + len > pdata->wrlen)
+		pdata->wrlen = len + file->f_pos;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle the generic file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return		N/A
+ */
+static void
+proc_on_close(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata = file->private_data;
+	char *line;
+	int i;
+	ENTER();
+	if (!pdata->wrlen)
+		return;
+	line = pdata->wrbuf;
+	while (line[0]) {
+		for (i = 0; i < priv->num_items; i++) {
+			if (!strncmp
+			    (line, priv->pdata[i].name,
+			     strlen(priv->pdata[i].name))) {
+				line += strlen(priv->pdata[i].name) + 1;
+				if (priv->pdata[i].size == 1)
+					*((u8 *)priv->pdata[i].addr) =
+						(u8)string_to_number(line);
+				else if (priv->pdata[i].size == 2)
+					*((u16 *) priv->pdata[i].addr) =
+						(u16) string_to_number(line);
+				else if (priv->pdata[i].size == 4)
+					*((u32 *)priv->pdata[i].addr) =
+						(u32)string_to_number(line);
+			}
+		}
+		while (line[0] && line[0] != '\n')
+			line++;
+		if (line[0])
+			line++;
+	}
+	if (priv->pbt->bt_dev.hscmd || priv->pbt->bt_dev.pscmd
+	    || priv->pbt->bt_dev.sdio_pull_ctrl
+	    || priv->pbt->bt_dev.test_mode || priv->pbt->bt_dev.hscfgcmd) {
+		bt_prepare_command(priv->pbt);
+		wake_up_interruptible(&priv->pbt->MainThread.waitQ);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handle the generic file open
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS or other error no.
+ */
+static int
+proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata;
+	int i;
+	char *p;
+	u32 val = 0;
+	ENTER();
+	priv->pbt->adapter->skb_pending =
+		skb_queue_len(&priv->pbt->adapter->tx_queue);
+	file->private_data = kzalloc(sizeof(struct proc_data), GFP_KERNEL);
+	if (file->private_data == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for proc_data\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	pdata = (struct proc_data *)file->private_data;
+	pdata->pbt = priv->pbt;
+	pdata->rdbuf = kmalloc(priv->bufsize, GFP_KERNEL);
+	if (pdata->rdbuf == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for rdbuf\n");
+		kfree(file->private_data);
+		LEAVE();
+		return -ENOMEM;
+	}
+	if (priv->fileflag == DEFAULT_FILE_PERM) {
+		pdata->wrbuf = kzalloc(priv->bufsize, GFP_KERNEL);
+		if (pdata->wrbuf == NULL) {
+			PRINTM(ERROR, "BT: Can not alloc mem for wrbuf\n");
+			kfree(pdata->rdbuf);
+			kfree(file->private_data);
+			return -ENOMEM;
+		}
+		pdata->maxwrlen = priv->bufsize;
+		pdata->on_close = proc_on_close;
+	}
+	p = pdata->rdbuf;
+	for (i = 0; i < priv->num_items; i++) {
+		if (priv->pdata[i].size == 1)
+			val = *((u8 *)priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 2)
+			val = *((u16 *) priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 4)
+			val = *((u32 *)priv->pdata[i].addr);
+		if (priv->pdata[i].flag & SHOW_INT)
+			p += sprintf(p, "%s=%d\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_HEX)
+			p += sprintf(p, "%s=0x%x\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_STRING) {
+			if (!strncmp
+			    (priv->pdata[i].name, "sdcmd52rw",
+			     strlen("sdcmd52rw"))) {
+				sd_read_cmd52_val(priv->pbt);
+				form_cmd52_string(priv->pbt);
+			}
+			p += sprintf(p, "%s=%s\n", priv->pdata[i].name,
+				     (char *)priv->pdata[i].addr);
+		}
+	}
+	pdata->rdlen = strlen(pdata->rdbuf);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/** Proc read ops */
+static const struct file_operations proc_read_ops = {
+	.read = proc_read,
+	.open = proc_open,
+	.release = proc_close
+};
+
+/** Proc Read-Write ops */
+static const struct file_operations proc_rw_ops = {
+	.read = proc_read,
+	.write = proc_write,
+	.open = proc_open,
+	.release = proc_close
+};
+
+static struct proc_private_data proc_files[] = {
+	{"status", S_IRUGO, 1024,
+	 sizeof(status_items) / sizeof(status_items[0]),
+	 &status_items[0], NULL, &proc_read_ops}
+	,
+	{"config", DEFAULT_FILE_PERM, 512,
+	 sizeof(config_items) / sizeof(config_items[0]), &config_items[0], NULL,
+	 &proc_rw_ops}
+	,
+	{"debug", DEFAULT_FILE_PERM, 512,
+	 sizeof(debug_items) / sizeof(debug_items[0]), &debug_items[0], NULL,
+	 &proc_rw_ops}
+	,
+};
+
+/**
+ *  @brief This function initializes proc entry
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param m_dev    A pointer to struct m_dev
+ *  @param seq      Sequence number
+ *
+ *  @return	BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct proc_dir_entry *entry;
+	int i, j;
+
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	if (proc_mbt) {
+		priv->dev_proc[seq].proc_entry =
+			proc_mkdir(m_dev->name, proc_mbt);
+		if (!priv->dev_proc[seq].proc_entry) {
+			PRINTM(ERROR, "BT: Could not mkdir %s!\n", m_dev->name);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+
+		priv->dev_proc[seq].pfiles =
+			kmalloc(sizeof(proc_files), GFP_ATOMIC);
+		if (!priv->dev_proc[seq].pfiles) {
+			PRINTM(ERROR,
+			       "BT: Could not alloc memory for pfile!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy((u8 *)priv->dev_proc[seq].pfiles, (u8 *)proc_files,
+		       sizeof(proc_files));
+		priv->dev_proc[seq].num_proc_files = ARRAY_SIZE(proc_files);
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++)
+			priv->dev_proc[seq].pfiles[j].pdata = NULL;
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+			priv->dev_proc[seq].pfiles[j].pdata =
+				kmalloc(priv->dev_proc[seq].pfiles[j].
+					num_items * sizeof(struct item_data),
+					GFP_ATOMIC);
+			if (!priv->dev_proc[seq].pfiles[j].pdata) {
+				PRINTM(ERROR,
+				       "BT: Could not alloc memory for pdata!\n");
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			memcpy((u8 *)priv->dev_proc[seq].pfiles[j].pdata,
+			       (u8 *)proc_files[j].pdata,
+			       priv->dev_proc[seq].pfiles[j].num_items *
+			       sizeof(struct item_data));
+			for (i = 0; i < priv->dev_proc[seq].pfiles[j].num_items;
+			     i++) {
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_DEV)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)&priv->bt_dev;
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_ADAPTER)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)priv->adapter;
+			}
+			priv->dev_proc[seq].pfiles[j].pbt = priv;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			entry = proc_create_data(proc_files[j].name,
+						 S_IFREG | proc_files[j].
+						 fileflag,
+						 priv->dev_proc[seq].proc_entry,
+						 proc_files[j].fops,
+						 &priv->dev_proc[seq].
+						 pfiles[j]);
+			if (entry == NULL)
+#else
+			entry = create_proc_entry(proc_files[j].name,
+						  S_IFREG | proc_files[j].
+						  fileflag,
+						  priv->dev_proc[seq].
+						  proc_entry);
+			if (entry) {
+				entry->data = &priv->dev_proc[seq].pfiles[j];
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
+				entry->owner = THIS_MODULE;
+#endif
+				entry->proc_fops = proc_files[j].fops;
+			} else
+#endif
+				PRINTM(MSG, "BT: Fail to create proc %s\n",
+				       proc_files[j].name);
+		}
+	}
+done:
+	if (ret == BT_STATUS_FAILURE) {
+		if (priv->dev_proc[seq].proc_entry) {
+			remove_proc_entry(m_dev->name, proc_mbt);
+			priv->dev_proc[seq].proc_entry = NULL;
+		}
+		if (priv->dev_proc[seq].pfiles) {
+			for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+				if (priv->dev_proc[seq].pfiles[j].pdata) {
+					kfree(priv->dev_proc[seq].pfiles[j].
+					      pdata);
+					priv->dev_proc[seq].pfiles[j].pdata =
+						NULL;
+				}
+			}
+			kfree(priv->dev_proc[seq].pfiles);
+			priv->dev_proc[seq].pfiles = NULL;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return	N/A
+ */
+void
+bt_proc_remove(bt_private *priv)
+{
+	int j, i;
+
+	ENTER();
+	PRINTM(INFO, "BT: Remove Proc Interface\n");
+	if (proc_mbt) {
+		for (i = 0; i < MAX_RADIO_FUNC; i++) {
+			if (!priv->dev_proc[i].proc_entry)
+				continue;
+			for (j = 0; j < ARRAY_SIZE(proc_files); j++) {
+				remove_proc_entry(proc_files[j].name,
+						  priv->dev_proc[i].proc_entry);
+			}
+			remove_proc_entry(priv->bt_dev.m_dev[i].name, proc_mbt);
+			priv->dev_proc[i].proc_entry = NULL;
+
+			if (priv->dev_proc[i].pfiles) {
+				for (j = 0;
+				     j < priv->dev_proc[i].num_proc_files;
+				     j++) {
+					if (priv->dev_proc[i].pfiles[j].pdata) {
+						kfree(priv->dev_proc[i].
+						      pfiles[j].pdata);
+						priv->dev_proc[i].pfiles[j].
+							pdata = NULL;
+					}
+				}
+				kfree(priv->dev_proc[i].pfiles);
+				priv->dev_proc[i].pfiles = NULL;
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function creates proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_root_proc_init(void)
+{
+	PRINTM(INFO, "BT: Create Proc Interface\n");
+	proc_mbt = proc_mkdir("mbt", PROC_DIR);
+	if (!proc_mbt) {
+		PRINTM(ERROR, "BT: Cannot create proc interface\n");
+		return BT_STATUS_FAILURE;
+	}
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS
+ */
+int
+bt_root_proc_remove(void)
+{
+	remove_proc_entry("mbt", PROC_DIR);
+	proc_mbt = NULL;
+	return BT_STATUS_SUCCESS;
+}
diff --git a/bt_sd8987/bt_char/bt_sdio.h b/bt_sd8987/bt_char/bt_sdio.h
new file mode 100644
index 0000000..3fced8f
--- /dev/null
+++ b/bt_sd8987/bt_char/bt_sdio.h
@@ -0,0 +1,435 @@
+/** @file bt_sdio.h
+ *  @brief This file contains SDIO (interface) module
+ *  related macros, enum, and structure.
+ *
+ *  Copyright (C) 2007-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_SDIO_H_
+#define _BT_SDIO_H_
+
+#include <linux/irqreturn.h>
+
+/** SD8787 card type */
+#define CARD_TYPE_SD8787   0x01
+/** SD8777 card type */
+#define CARD_TYPE_SD8777   0x02
+/** SD8887 card type */
+#define CARD_TYPE_SD8887   0x03
+/** SD8897 card type */
+#define CARD_TYPE_SD8897   0x04
+/** SD8797 card type */
+#define CARD_TYPE_SD8797   0x05
+/** SD8977 card type */
+#define CARD_TYPE_SD8977   0x06
+/** SD8997 card type */
+#define CARD_TYPE_SD8997   0x07
+/** SD8987 card type */
+#define CARD_TYPE_SD8987   0x08
+/** SD8978 card type */
+#define CARD_TYPE_SD8978   0x09
+
+/** IRQ return type */
+typedef irqreturn_t IRQ_RET_TYPE;
+/** IRQ return */
+#define IRQ_RET		(return IRQ_HANDLED)
+/** ISR notifier function */
+typedef IRQ_RET_TYPE (*isr_notifier_fn_t) (s32 irq, void *dev_id,
+					   struct pt_regs * reg);
+
+/** SDIO header length */
+#define SDIO_HEADER_LEN			4
+
+/** 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
+/* SD block size can not bigger than 64 due to buf size limit in firmware */
+/** define SD block size for data Tx/Rx */
+#define SD_BLOCK_SIZE			64
+/** define SD block size for firmware download */
+#define SD_BLOCK_SIZE_FW_DL		256
+
+/** Number of blocks for firmware transfer */
+#define FIRMWARE_TRANSFER_NBLOCK	2
+
+/** Firmware ready */
+#define FIRMWARE_READY			0xfedc
+
+/* Bus Interface Control Reg 0x07 */
+/** SD BUS width 1 */
+#define SD_BUS_WIDTH_1			0x00
+/** SD BUS width 4 */
+#define SD_BUS_WIDTH_4			0x02
+/** SD BUS width mask */
+#define SD_BUS_WIDTH_MASK		0x03
+/** Asynchronous interrupt mode */
+#define ASYNC_INT_MODE			0x20
+
+/** magic register */
+#define CARD_MAGIC_REG          0xF0
+/** magic value */
+#define MAGIC_VAL               0x24
+
+/* Host Control Registers */
+/** Host Control Registers : Configuration */
+#define CONFIGURATION_REG		0x00
+/** Host Control Registers : Host without Command 53 finish host*/
+#define HOST_TO_CARD_EVENT		(0x1U << 3)
+/** Host Control Registers : Host terminates Command 53 */
+#define HOST_TERM_CMD53			(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 : Host interrupt RSR */
+#define HOST_INT_RSR_REG		0x01
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR		(0x1U)
+
+/** Host Control Registers : Host interrupt mask */
+#define HOST_INT_MASK_REG		0x02
+
+/** 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)
+/** Enable Host interrupt mask */
+#define HIM_ENABLE			(UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
+/** Disable Host interrupt mask */
+#define	HIM_DISABLE			0xff
+
+#define HOST_INTSTATUS_REG		0x03
+/** 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)
+
+/** 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
+
+/** Host Control Registers : Host interrupt status */
+#define HOST_INT_STATUS_REG		0x28
+/** Host Control Registers : Upload CRC error */
+#define UP_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 */
+/** Card Control Registers : Read SQ base address A0 register */
+#define SQ_READ_BASE_ADDRESS_A0_REG		0x40
+/** Card Control Registers : Read SQ base address A1 register */
+#define SQ_READ_BASE_ADDRESS_A1_REG		0x41
+/** Card Control Registers : Read SQ base address A2 register */
+#define SQ_READ_BASE_ADDRESS_A2_REG		0x42
+/** Card Control Registers : Read SQ base address A3 register */
+#define SQ_READ_BASE_ADDRESS_A3_REG		0x43
+/** Card Control Registers : Read SQ base address B0 register */
+#define SQ_READ_BASE_ADDRESS_B0_REG		0x44
+/** Card Control Registers : Read SQ base address B1 register */
+#define SQ_READ_BASE_ADDRESS_B1_REG		0x45
+/** Card Control Registers : Read SQ base address B2 register */
+#define SQ_READ_BASE_ADDRESS_B2_REG		0x46
+/** Card Control Registers : Read SQ base address B3 register */
+#define SQ_READ_BASE_ADDRESS_B3_REG		0x47
+
+/** Card Control Registers : Card status register */
+#define CARD_STATUS_REG					0x30
+/** 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 interrupt mask register */
+#define HOST_INTERRUPT_MASK_REG			0x34
+/** 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 : Card interrupt status register */
+#define CARD_INTERRUPT_STATUS_REG		0x38
+/** 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 : Card interrupt RSR register */
+#define CARD_INTERRUPT_RSR_REG			0x3c
+/** 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 : Debug 0 register */
+#define DEBUG_0_REG						0x70
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0						(0x1U)
+/** Card Control Registers : Debug 1 register */
+#define DEBUG_1_REG						0x71
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1						(0x1U)
+/** Card Control Registers : Debug 2 register */
+#define DEBUG_2_REG						0x72
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2						(0x1U)
+/** Card Control Registers : Debug 3 register */
+#define DEBUG_3_REG						0x73
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3						(0x1U)
+
+/** Host Control Registers : I/O port 0 */
+#define IO_PORT_0_REG			0x78
+/** Host Control Registers : I/O port 1 */
+#define IO_PORT_1_REG			0x79
+/** Host Control Registers : I/O port 2 */
+#define IO_PORT_2_REG			0x7A
+
+/** Firmware status 0 register */
+#define CARD_FW_STATUS0_REG		0x60
+/** Firmware status 1 register */
+#define CARD_FW_STATUS1_REG		0x61
+/** Rx length register */
+#define CARD_RX_LEN_REG			0x62
+/** Rx unit register */
+#define CARD_RX_UNIT_REG		0x63
+/** Card Control Registers : Miscellaneous Configuration Register */
+#define CARD_MISC_CFG_REG		0x6C
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT		(0x1U << 4)
+
+/** Card Control Registers : Card OCR 0 register */
+#define CARD_OCR_0_REG			0x68
+/** Card Control Registers : Card OCR 1 register */
+#define CARD_OCR_1_REG			0x69
+/** Card Control Registers : Card OCR 3 register */
+#define CARD_OCR_3_REG			0x6A
+/** Card Control Registers : Card config register */
+#define CARD_CONFIG_REG			0x6B
+/** Card Control Registers : Card revision register */
+#define CARD_REVISION_REG		0x5c
+/** Card Control Registers : Command 53 finish G BUS */
+#define CMD53_FINISH_GBUS		(0x1U << 1)
+/** Card Control Registers : SD negative edge */
+#define SD_NEG_EDGE				(0x1U << 0)
+
+/* Special registers in function 0 of the SDxx card */
+/** Special register in function 0 of the SDxxx card : Scratch 0 */
+#define	SCRATCH_0_REG			0x80fe
+/** Special register in function 0 of the SDxxx card : Scratch 1 */
+#define	SCRATCH_1_REG			0x80ff
+/** Host F1 read base 0 */
+#define HOST_F1_RD_BASE_0		0x0040
+/** Host F1 read base 1 */
+#define HOST_F1_RD_BASE_1		0x0041
+/** Host F1 card ready */
+#define HOST_F1_CARD_RDY		0x0020
+
+/** Chip Id Register 0 */
+#define CARD_CHIP_ID_0_REG		0x801c
+/** Chip Id Register 1 */
+#define CARD_CHIP_ID_1_REG		0x801d
+
+struct sdio_mmc_card {
+	/** sdio_func structure pointer */
+	struct sdio_func *func;
+	/** bt_private structure pointer */
+	bt_private *priv;
+};
+
+struct sdio_card_reg {
+	u8 cfg;
+	u8 host_int_mask;	// HOST_INT_MASK_REG
+	u8 host_intstatus;	// HOST_INTSTATUS_REG
+	u8 host_int_rsr_reg;	// HOST_INT_RSR_REG
+	u8 card_misc_cfg_reg;	// CARD_MISC_CFG_REG
+	u8 card_status;		// CARD_STATUS_REG
+	u8 sq_read_base_addr_a0;	// SQ_READ_BASE_ADDRESS_A0_REG
+	u8 sq_read_base_addr_a1;	// SQ_READ_BASE_ADDRESS_A1_REG
+	u8 card_revision;	// CARD_REVISION_REG
+	u8 card_fw_status0;	// CARD_FW_STATUS0_REG
+	u8 card_fw_status1;	// CARD_FW_STATUS1_REG
+	u8 card_rx_len;		// CARD_RX_LEN_REG
+	u8 card_rx_unit;	// CARD_RX_UNIT_REG
+	u8 io_port_0;		// IO_PORT_0_REG
+	u8 io_port_1;		// IO_PORT_1_REG
+	u8 io_port_2;		// IO_PORT_2_REG
+};
+
+struct sdio_device {
+	const struct sdio_card_reg *reg;
+};
+
+static const struct sdio_card_reg bt_reg_87xx = {
+	.cfg = 0x00,
+	.host_int_mask = 0x02,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x03,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x01,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0x6c,	// CARD_MISC_CFG_REG
+	.card_status = 0x30,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0x40,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0x41,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0x5C,	// CARD_REVISION_REG
+	.card_fw_status0 = 0x60,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0x61,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0x62,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0x63,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0x78,	// IO_PORT_0_REG
+	.io_port_1 = 0x79,	// IO_PORT_1_REG
+	.io_port_2 = 0x7a,	// IO_PORT_2_REG
+};
+
+static const struct sdio_card_reg bt_reg_8887 = {
+	.cfg = 0x00,
+	.host_int_mask = 0x08,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x0C,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x04,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0xD8,	// CARD_MISC_CFG_REG
+	.card_status = 0x5C,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0x6C,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0x6D,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0xC8,	// CARD_REVISION_REG
+	.card_fw_status0 = 0x88,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0x89,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0x8A,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0x8B,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0xE4,	// IO_PORT_0_REG
+	.io_port_1 = 0xE5,	// IO_PORT_1_REG
+	.io_port_2 = 0xE6,	// IO_PORT_2_REG
+};
+
+static const struct sdio_card_reg bt_reg_8897 = {
+	.cfg = 0x00,
+	.host_int_mask = 0x02,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x03,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x01,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0xCC,	// CARD_MISC_CFG_REG
+	.card_status = 0x50,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0x60,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0x61,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0xBC,	// CARD_REVISION_REG
+	.card_fw_status0 = 0xC0,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0xC1,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0xC2,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0xC3,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0xD8,	// IO_PORT_0_REG
+	.io_port_1 = 0xD9,	// IO_PORT_1_REG
+	.io_port_2 = 0xDA,	// IO_PORT_2_REG
+};
+
+static const struct sdio_card_reg bt_reg_8977_8978_8997 = {
+	.cfg = 0x00,
+	.host_int_mask = 0x08,	// HOST_INT_MASK_REG
+	.host_intstatus = 0x0C,	// HOST_INTSTATUS_REG
+	.host_int_rsr_reg = 0x04,	// HOST_INT_RSR_REG
+	.card_misc_cfg_reg = 0xD8,	// CARD_MISC_CFG_REG
+	.card_status = 0x5C,	// CARD_STATUS_REG
+	.sq_read_base_addr_a0 = 0xF8,	// SQ_READ_BASE_ADDRESS_A0_REG
+	.sq_read_base_addr_a1 = 0xF9,	// SQ_READ_BASE_ADDRESS_A1_REG
+	.card_revision = 0xC8,	// CARD_REVISION_REG
+	.card_fw_status0 = 0xE8,	// CARD_FW_STATUS0_REG
+	.card_fw_status1 = 0xE9,	// CARD_FW_STATUS1_REG
+	.card_rx_len = 0xEA,	// CARD_RX_LEN_REG
+	.card_rx_unit = 0xEB,	// CARD_RX_UNIT_REG
+	.io_port_0 = 0xE4,	// IO_PORT_0_REG
+	.io_port_1 = 0xE5,	// IO_PORT_1_REG
+	.io_port_2 = 0xE6,	// IO_PORT_2_REG
+};
+
+static const struct sdio_device bt_sdio_sd8787 = {
+	.reg = &bt_reg_87xx,
+};
+
+static const struct sdio_device bt_sdio_sd8777 = {
+	.reg = &bt_reg_87xx,
+};
+
+static const struct sdio_device bt_sdio_sd8887 = {
+	.reg = &bt_reg_8887,
+};
+
+static const struct sdio_device bt_sdio_sd8897 = {
+	.reg = &bt_reg_8897,
+};
+
+static const struct sdio_device bt_sdio_sd8797 = {
+	.reg = &bt_reg_87xx,
+};
+
+static const struct sdio_device bt_sdio_sd8977 = {
+	.reg = &bt_reg_8977_8978_8997,
+};
+
+static const struct sdio_device bt_sdio_sd8978 = {
+	.reg = &bt_reg_8977_8978_8997,
+};
+
+static const struct sdio_device bt_sdio_sd8997 = {
+	.reg = &bt_reg_8977_8978_8997,
+};
+
+static const struct sdio_device bt_sdio_sd8987 = {
+	.reg = &bt_reg_8977_8978_8997,
+};
+
+/** DMA alignment value */
+#define DMA_ALIGNMENT	64
+/** 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))
+
+/** This function read cmd52 register */
+int sd_write_reg(bt_private *priv, int reg, u8 val);
+/** This function write cmd52 value to register */
+int sd_read_reg(bt_private *priv, int reg, u8 *data);
+/** This function reads the Cmd52 value in dev structure */
+int sd_read_cmd52_val(bt_private *priv);
+/** This function updates card reg based on the Cmd52 value in dev structure */
+int sd_write_cmd52_val(bt_private *priv, int func, int reg, int val);
+
+void sdio_update_card_type(bt_private *priv, void *card);
+int sdio_get_sdio_device(bt_private *priv);
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** This function tells lower driver that BT is suspended */
+void bt_is_suspended(bt_private *priv);
+#endif
+#endif
+#endif
+#endif /* _BT_SDIO_H_ */
diff --git a/bt_sd8987/bt_char/bt_sdiommc.c b/bt_sd8987/bt_char/bt_sdiommc.c
new file mode 100644
index 0000000..d7f51bb
--- /dev/null
+++ b/bt_sd8987/bt_char/bt_sdiommc.c
@@ -0,0 +1,2397 @@
+/** @file bt_sdiommc.c
+ *  @brief This file contains SDIO IF (interface) module
+ *  related functions.
+ *
+ * Copyright (C) 2007-2019, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/mmc/sdio_func.h>
+#include        <linux/mmc/sdio.h>
+#include        <linux/mmc/card.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** define marvell vendor id */
+#define MARVELL_VENDOR_ID 0x02df
+
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD53_RETRY 	3
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD52_RETRY     3
+/** Firmware name */
+static char *fw_name;
+/** fw serial download flag */
+extern int bt_fw_serial;
+int bt_intmode = INT_MODE_SDIO;
+/** request firmware nowait */
+int bt_req_fw_nowait;
+static int multi_fn = BIT(2);
+
+#define DEFAULT_FW_NAME ""
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB2   28
+/** FW header for CRC check disable */
+static u8 fw_crc_header_rb_2[FW_CRC_HEADER_RB2] = {
+	0x05, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+	0x9d, 0x32, 0xbb, 0x11, 0x01, 0x00, 0x00, 0x7f,
+	0x00, 0x00, 0x00, 0x00, 0x67, 0xd6, 0xfc, 0x25
+};
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB   24
+/** FW header for CRC check disable */
+static u8 fw_crc_header_rb_1[FW_CRC_HEADER_RB] = {
+	0x01, 0x00, 0x00, 0x00, 0x04, 0xfd, 0x00, 0x04,
+	0x08, 0x00, 0x00, 0x00, 0x26, 0x52, 0x2a, 0x7b,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/** Default firmware name */
+#define DEFAULT_FW_NAME_8777 "mrvl/sd8777_uapsta.bin"
+#define DEFAULT_FW_NAME_8787 "mrvl/sd8787_uapsta.bin"
+#define DEFAULT_FW_NAME_8797 "mrvl/sd8797_uapsta.bin"
+#define DEFAULT_FW_NAME_8887 "mrvl/sd8887_uapsta.bin"
+#define DEFAULT_FW_NAME_8897 "mrvl/sd8897_uapsta.bin"
+#define DEFAULT_FW_NAME_8977 "mrvl/sdsd8977_combo.bin"
+#define DEFAULT_FW_NAME_8978 "mrvl/sdsd8978_combo.bin"
+#define DEFAULT_FW_NAME_8997 "mrvl/sdsd8997_combo.bin"
+
+/** SD8787 chip revision ID */
+#define SD8787_W0      0x30
+#define SD8787_W1      0x31
+#define SD8787_A0_A1   0x40
+/** SD8797 chip revision ID */
+#define SD8797_A0       0x00
+#define SD8797_B0       0x10
+/** SD8897 chip revision ID */
+#define SD8897_A0       0x10
+#define SD8897_B0       0x20
+
+/** SD8887 chip revision ID */
+#define SD8887_A0       0x0
+#define SD8887_A2       0x2
+#define SD8887_A0_FW_NAME "mrvl/sd8887_uapsta.bin"
+#define SD8887_A2_FW_NAME "mrvl/sd8887_uapsta_a2.bin"
+#define SD8887_A2_BT_FW_NAME "mrvl/sd8887_bt_a2.bin"
+
+#define SD8897_A0_FW_NAME "mrvl/sd8897_uapsta_a0.bin"
+#define SD8897_B0_FW_NAME "mrvl/sd8897_uapsta.bin"
+
+#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin"
+#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin"
+#define SD8797_A0_FW_NAME "mrvl/sd8797_uapsta_a0.bin"
+#define SD8797_B0_FW_NAME "mrvl/sd8797_uapsta.bin"
+
+/** SD8977 chip revision ID */
+#define SD8977_V0       0x0
+#define SD8977_V1       0x8
+#define SD8977_V2       0x9
+#define SD8977_V0_FW_NAME "mrvl/sdsd8977_combo.bin"
+#define SD8977_V0_BT_FW_NAME "mrvl/sd8977_bt.bin"
+#define SD8977_V1_FW_NAME "mrvl/sdsd8977_combo_v1.bin"
+#define SD8977_V1_BT_FW_NAME "mrvl/sd8977_bt_v1.bin"
+#define SD8977_V2_FW_NAME "mrvl/sdsd8977_combo_v2.bin"
+#define SD8977_V2_BT_FW_NAME "mrvl/sd8977_bt_v2.bin"
+/** SD8978 FW NAME */
+#define SD8978_FW_NAME      "mrvl/sdsd8978_combo.bin"
+#define SD8978_BT_FW_NAME   "mrvl/sd8978_bt.bin"
+
+/** SD8997 chip revision ID */
+#define SD8997_Z        0x02
+#define SD8997_V2       0x10
+#define SD8997_Z_FW_NAME "mrvl/sdsd8997_combo.bin"
+#define SD8997_Z_BT_FW_NAME "mrvl/sd8997_bt.bin"
+#define SD8997_V2_FW_NAME "mrvl/sdsd8997_combo_v2.bin"
+#define SD8997_V2_BT_FW_NAME "mrvl/sd8997_bt_v2.bin"
+#define SD8997_V3_FW_NAME "mrvl/sdsd8997_combo_v3.bin"
+#define SD8997_V3_BT_FW_NAME "mrvl/sd8997_bt_v3.bin"
+
+/** SD8987 */
+#define SD8987_FW_NAME  "mrvl/sdsd8987_combo.bin"
+#define SD8987_BT_FW_NAME "mrvl/sd8987_bt.bin"
+
+/** Function number 2 */
+#define FN2			2
+/** Device ID for SD8787 FN2 */
+#define SD_DEVICE_ID_8787_BT_FN2    0x911A
+/** Device ID for SD8787 FN3 */
+#define SD_DEVICE_ID_8787_BT_FN3    0x911B
+/** Device ID for SD8777 FN2 */
+#define SD_DEVICE_ID_8777_BT_FN2    0x9132
+/** Device ID for SD8777 FN3 */
+#define SD_DEVICE_ID_8777_BT_FN3    0x9133
+/** Device ID for SD8887 FN2 */
+#define SD_DEVICE_ID_8887_BT_FN2    0x9136
+/** Device ID for SD8887 FN3 */
+#define SD_DEVICE_ID_8887_BT_FN3    0x9137
+/** Device ID for SD8897 FN2 */
+#define SD_DEVICE_ID_8897_BT_FN2    0x912E
+/** Device ID for SD8897 FN3 */
+#define SD_DEVICE_ID_8897_BT_FN3    0x912F
+/** Device ID for SD8797 FN2 */
+#define SD_DEVICE_ID_8797_BT_FN2    0x912A
+/** Device ID for SD8797 FN3 */
+#define SD_DEVICE_ID_8797_BT_FN3    0x912B
+/** Device ID for SD8977 FN2 */
+#define SD_DEVICE_ID_8977_BT_FN2    0x9146
+/** Device ID for SD8978 FN2 */
+#define SD_DEVICE_ID_8978_BT_FN2    0x915a
+/** Device ID for SD8997 FN2 */
+#define SD_DEVICE_ID_8997_BT_FN2    0x9142
+/** Device ID for SD8987 FN2 */
+#define SD_DEVICE_ID_8987_BT_FN2    0x914a
+/** Device ID for SD8987 FN3 */
+#define SD_DEVICE_ID_8987_BT_FN3    0x914b
+
+/** Array of SDIO device ids when multi_fn=0x12 */
+static const struct sdio_device_id bt_ids[] = {
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8787_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8777_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8887_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8897_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8797_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8977_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8978_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8997_BT_FN2)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8987_BT_FN2)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(sdio, bt_ids);
+
+#ifdef SDIO_OOB_IRQ
+extern int mrvl_sdio_claim_irq(struct sdio_func *func,
+			       sdio_irq_handler_t * handler);
+extern int mrvl_sdio_release_irq(struct sdio_func *func);
+extern int mrvl_sdio_suspend(struct sdio_func *func);
+extern int mrvl_sdio_resume(struct sdio_func *func);
+#endif
+
+/********************************************************
+		Global Variables
+********************************************************/
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+extern int mbt_pm_keep_power;
+#endif
+
+extern bt_private *m_priv[];
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief This function gets rx_unit value
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_get_rx_unit(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_unit_reg = priv->psdio_device->reg->card_rx_unit;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_unit_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		priv->bt_dev.rx_unit = reg;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads fwstatus registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_read_firmware_status(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 fws0;
+	u8 fws1;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = priv->psdio_device->reg->card_fw_status0;
+	u8 card_fw_status1_reg = priv->psdio_device->reg->card_fw_status1;
+
+	ENTER();
+
+	fws0 = sdio_readb(card->func, card_fw_status0_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	fws1 = sdio_readb(card->func, card_fw_status1_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	*dat = (((u16) fws1) << 8) | fws0;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function reads rx length
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sd_read_rx_len(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_len_reg = priv->psdio_device->reg->card_rx_len;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_len_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		*dat = (u16) reg << priv->bt_dev.rx_unit;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables the host interrupts mask
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_enable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = priv->psdio_device->reg->host_int_mask;
+
+	ENTER();
+
+	sdio_writeb(card->func, mask, host_int_mask_reg, &ret);
+	if (ret) {
+		PRINTM(WARN, "BT: Unable to enable the host interrupt!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function disables the host interrupts mask.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sbi_disable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_FAILURE;
+	u8 host_int_mask;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = priv->psdio_device->reg->host_int_mask;
+
+	ENTER();
+
+	/* Read back the host_int_mask register */
+	host_int_mask = sdio_readb(card->func, host_int_mask_reg, &ret);
+	if (ret)
+		goto done;
+
+	/* Update with the mask and write back to the register */
+	host_int_mask &= ~mask;
+	sdio_writeb(card->func, host_int_mask, host_int_mask_reg, &ret);
+	if (ret < 0) {
+		PRINTM(WARN, "BT: Unable to diable the host interrupt!\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function polls the card status register
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param bits     the bit mask
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_poll_card_status(bt_private *priv, u8 bits)
+{
+	int tries;
+	int rval;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 cs;
+	u8 card_status_reg = priv->psdio_device->reg->card_status;
+
+	ENTER();
+
+	for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
+		cs = sdio_readb(card->func, card_status_reg, &rval);
+		if (rval != 0)
+			break;
+		if (rval == 0 && (cs & bits) == bits) {
+			LEAVE();
+			return BT_STATUS_SUCCESS;
+		}
+		udelay(1);
+	}
+	PRINTM(ERROR,
+	       "BT: sdio_poll_card_status failed (%d), tries = %d, cs = 0x%x\n",
+	       rval, tries, cs);
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_cmd52_val(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 func, reg, val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	func = priv->bt_dev.cmd52_func;
+	reg = priv->bt_dev.cmd52_reg;
+	sdio_claim_host(card->func);
+	if (func)
+		val = sdio_readb(card->func, reg, &ret);
+	else
+		val = sdio_f0_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	if (ret) {
+		PRINTM(ERROR, "BT: Cannot read value from func %d reg %d\n",
+		       func, reg);
+	} else {
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param func     Stores func variable
+ *  @param reg      Stores reg variable
+ *  @param val      Stores val variable
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_cmd52_val(bt_private *priv, int func, int reg, int val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	if (val >= 0) {
+		/* Perform actual write only if val is provided */
+		sdio_claim_host(card->func);
+		if (func)
+			sdio_writeb(card->func, val, reg, &ret);
+		else
+			sdio_f0_writeb(card->func, val, reg, &ret);
+		sdio_release_host(card->func);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: Cannot write value (0x%x) to func %d reg %d\n",
+			       val, func, reg);
+			goto done;
+		}
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	/* Save current func and reg for future read */
+	priv->bt_dev.cmd52_func = func;
+	priv->bt_dev.cmd52_reg = reg;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to write
+ *  @param val      value
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_reg(bt_private *priv, int reg, u8 val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, val, reg, &ret);
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to read
+ *  @param data		Data
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_reg(bt_private *priv, int reg, u8 *data)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	val = sdio_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	*data = val;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads FN0 reg value
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to read
+ *  @param data		Data
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_f0_read_reg(bt_private *priv, int reg, u8 *data)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	val = sdio_f0_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	*data = val;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function probes the card
+ *
+ *  @param func    A pointer to sdio_func structure.
+ *  @param id      A pointer to structure sdio_device_id
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_probe_card(struct sdio_func *func, const struct sdio_device_id *id)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *card = NULL;
+
+	ENTER();
+
+	PRINTM(INFO, "BT: vendor=0x%x,device=0x%x,class=%d,fn=%d\n", id->vendor,
+	       id->device, id->class, func->num);
+	card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
+	if (!card) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	card->func = func;
+#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_disable_func(func);
+		sdio_release_host(func);
+		PRINTM(FATAL, "BT: sdio_enable_func() failed: ret=%d\n", ret);
+		kfree(card);
+		LEAVE();
+		return -EIO;
+	}
+	sdio_release_host(func);
+	priv = bt_add_card(card);
+	if (!priv) {
+		sdio_claim_host(func);
+		sdio_disable_func(func);
+		sdio_release_host(func);
+		ret = BT_STATUS_FAILURE;
+		kfree(card);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param pollnum  Number of times to poll fw status
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_verify_fw_download(bt_private *priv, int pollnum)
+{
+	int ret = BT_STATUS_FAILURE;
+	u16 firmwarestat = 0;
+	int tries;
+
+	ENTER();
+
+	/* Wait for firmware initialization event */
+	for (tries = 0; tries < pollnum; tries++) {
+		if (sd_read_firmware_status(priv, &firmwarestat) < 0)
+			continue;
+		if (firmwarestat == FIRMWARE_READY) {
+			PRINTM(MSG, "BT FW is active(%d)\n", tries);
+			ret = BT_STATUS_SUCCESS;
+			break;
+		}
+		mdelay(100);
+	}
+	if ((pollnum > 1) && (ret != BT_STATUS_SUCCESS)) {
+		PRINTM(ERROR,
+		       "Fail to poll firmware status: firmwarestat=0x%x\n",
+		       firmwarestat);
+		bt_dump_sdio_regs(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Transfers firmware to card
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @param fw        A Pointer to fw image
+ *  @param fw_len    fw image len
+ *  @return          BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_init_fw_dpc(bt_private *priv, u8 *fw, int fw_len)
+{
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 *firmware = fw;
+	int firmwarelen = fw_len;
+	u8 base0;
+	u8 base1;
+	int ret = BT_STATUS_SUCCESS;
+	int offset;
+	void *tmpfwbuf = NULL;
+	int tmpfwbufsz;
+	u8 *fwbuf;
+	u16 len;
+	int txlen = 0;
+	int tx_blocks = 0;
+	int i = 0;
+	int tries = 0;
+#ifdef FW_DOWNLOAD_SPEED
+	u32 tv1, tv2;
+#endif
+	u8 sq_read_base_address_a0_reg =
+		priv->psdio_device->reg->sq_read_base_addr_a0;
+	u8 sq_read_base_address_a1_reg =
+		priv->psdio_device->reg->sq_read_base_addr_a1;
+	u8 crc_buffer = 0;
+	u8 *header_crc_fw = NULL;
+	u8 header_crc_fw_len = 0;
+
+	if (priv->card_type == CARD_TYPE_SD8787) {
+		header_crc_fw = fw_crc_header_rb_1;
+		header_crc_fw_len = FW_CRC_HEADER_RB;
+	} else if (priv->card_type == CARD_TYPE_SD8777) {
+		header_crc_fw = fw_crc_header_rb_2;
+		header_crc_fw_len = FW_CRC_HEADER_RB2;
+	}
+
+	ENTER();
+
+	PRINTM(INFO, "BT: Downloading FW image (%d bytes)\n", firmwarelen);
+
+#ifdef FW_DOWNLOAD_SPEED
+	tv1 = get_utimeofday();
+#endif
+
+	tmpfwbufsz = BT_UPLD_SIZE + DMA_ALIGNMENT;
+	tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
+	if (!tmpfwbuf) {
+		PRINTM(ERROR,
+		       "BT: Unable to allocate buffer for firmware. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	/* Ensure aligned firmware buffer */
+	fwbuf = (u8 *)ALIGN_ADDR(tmpfwbuf, DMA_ALIGNMENT);
+
+	if (!(priv->fw_crc_check)
+	    && ((priv->card_type == CARD_TYPE_SD8787) ||
+		(priv->card_type == CARD_TYPE_SD8777))
+		) {
+		/* CRC check not required, use custom header first */
+		firmware = header_crc_fw;
+		firmwarelen = header_crc_fw_len;
+		crc_buffer = 1;
+	}
+
+	/* Perform firmware data transfer */
+	offset = 0;
+	do {
+		/* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits
+		 */
+		ret = sd_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: FW download with helper poll status timeout @ %d\n",
+			       offset);
+			goto done;
+		}
+		if (!crc_buffer)
+			/* More data? */
+			if (offset >= firmwarelen)
+				break;
+
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			base0 = sdio_readb(card->func,
+					   sq_read_base_address_a0_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE0 register read failed:"
+				       " base0=0x%04X(%d). Terminating download\n",
+				       base0, base0);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			base1 = sdio_readb(card->func,
+					   sq_read_base_address_a1_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE1 register read failed:"
+				       " base1=0x%04X(%d). Terminating download\n",
+				       base1, base1);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			len = (((u16) base1) << 8) | base0;
+
+			if (len != 0)
+				break;
+			udelay(10);
+		}
+
+		if (len == 0)
+			break;
+		else if (len > BT_UPLD_SIZE) {
+			PRINTM(FATAL,
+			       "BT: FW download failure @ %d, invalid length %d\n",
+			       offset, len);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	/** ignore CRC check before download the first packet */
+		if (offset == 0 && (len & BIT(0)))
+			len &= ~BIT(0);
+		txlen = len;
+
+		if (len & BIT(0)) {
+			i++;
+			if (i >= MAX_CMD53_RETRY) {
+				PRINTM(FATAL,
+				       "BT: FW download failure @ %d, over max retry count\n",
+				       offset);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(ERROR,
+			       "BT: FW CRC error indicated by the helper:"
+			       " len = 0x%04X, txlen = %d\n", len, txlen);
+			len &= ~BIT(0);
+
+			PRINTM(ERROR, "BT: retry: %d, offset %d\n", i, offset);
+			/* Setting this to 0 to resend from same offset */
+			txlen = 0;
+		} else {
+			i = 0;
+
+			/* Set blocksize to transfer - checking for last block */
+			if (firmwarelen - offset < txlen)
+				txlen = firmwarelen - offset;
+
+			PRINTM(INFO, ".");
+
+			tx_blocks =
+				(txlen + SD_BLOCK_SIZE_FW_DL -
+				 1) / SD_BLOCK_SIZE_FW_DL;
+
+			/* Copy payload to buffer */
+			memcpy(fwbuf, &firmware[offset], txlen);
+		}
+
+		/* Send data */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, fwbuf,
+				   tx_blocks * SD_BLOCK_SIZE_FW_DL);
+
+		if (ret < 0) {
+			PRINTM(ERROR,
+			       "BT: FW download, write iomem (%d) failed @ %d\n",
+			       i, offset);
+			sdio_writeb(card->func, 0x04, CONFIGURATION_REG, &ret);
+			if (ret)
+				PRINTM(ERROR, "write ioreg failed (CFG)\n");
+		}
+
+		offset += txlen;
+		if (crc_buffer
+		    && ((priv->card_type == CARD_TYPE_SD8787) ||
+			(priv->card_type == CARD_TYPE_SD8777))
+			) {
+			if (offset >= header_crc_fw_len) {
+				/* Custom header download complete, restore
+				   original FW */
+				offset = 0;
+				firmware = fw;
+				firmwarelen = fw_len;
+				crc_buffer = 0;
+			}
+		}
+	} while (TRUE);
+
+	PRINTM(MSG, "BT: FW download over, size %d bytes\n", offset);
+
+	ret = BT_STATUS_SUCCESS;
+done:
+#ifdef FW_DOWNLOAD_SPEED
+	tv2 = get_utimeofday();
+	PRINTM(INFO, "FW: %d.%03d.%03d ", tv1 / 1000000,
+	       (tv1 % 1000000) / 1000, tv1 % 1000);
+	PRINTM(INFO, " -> %d.%03d.%03d ", tv2 / 1000000,
+	       (tv2 % 1000000) / 1000, tv2 % 1000);
+	tv2 -= tv1;
+	PRINTM(INFO, " == %d.%03d.%03d\n", tv2 / 1000000,
+	       (tv2 % 1000000) / 1000, tv2 % 1000);
+#endif
+	kfree(tmpfwbuf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *
+ * @param fw_firmware  A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_request_fw_dpc(const struct firmware *fw_firmware, void *context)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = (bt_private *)context;
+	struct sdio_mmc_card *card = NULL;
+	struct m_dev *m_dev_bt = NULL;
+	struct timeval tstamp;
+	int index;
+
+	ENTER();
+
+	m_dev_bt = &priv->bt_dev.m_dev[BT_SEQ];
+
+	if ((priv == NULL) || (priv->adapter == NULL) ||
+	    (priv->bt_dev.card == NULL) || (m_dev_bt == NULL)
+		) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	if (!fw_firmware) {
+		do_gettimeofday(&tstamp);
+		if (tstamp.tv_sec >
+		    (priv->req_fw_time.tv_sec + REQUEST_FW_TIMEOUT)) {
+			PRINTM(ERROR,
+			       "BT: No firmware image found. Skipping download\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		PRINTM(ERROR,
+		       "BT: No firmware image found! Retrying download\n");
+		/* Wait a second here before calling the callback again */
+		os_sched_timeout(1000);
+		sd_download_firmware_w_helper(priv);
+		LEAVE();
+		return ret;
+	}
+
+	priv->firmware = fw_firmware;
+
+	if (BT_STATUS_FAILURE ==
+	    sd_init_fw_dpc(priv, (u8 *)priv->firmware->data,
+			   priv->firmware->size)) {
+		PRINTM(ERROR,
+		       "BT: sd_init_fw_dpc failed (download fw with nowait: %d). Terminating download\n",
+		       bt_req_fw_nowait);
+		sdio_release_host(card->func);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* check if the fimware is downloaded successfully or not */
+	if (sd_verify_fw_download(priv, MAX_FIRMWARE_POLL_TRIES)) {
+		PRINTM(ERROR, "BT: FW failed to be active in time!\n");
+		ret = BT_STATUS_FAILURE;
+		sdio_release_host(card->func);
+		goto done;
+	}
+	sdio_release_host(card->func);
+	sbi_enable_host_int(priv);
+	if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+		PRINTM(ERROR,
+		       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	LEAVE();
+	return ret;
+
+done:
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	/* For synchronous download cleanup will be done in add_card */
+	if (!bt_req_fw_nowait)
+		return ret;
+	PRINTM(INFO, "unregister device\n");
+	sbi_unregister_dev(priv);
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+	bt_proc_remove(priv);
+	clean_up_m_devs(priv);
+	bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware     A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             None
+ **/
+static void
+sd_request_fw_callback(const struct firmware *firmware, void *context)
+{
+	ENTER();
+	sd_request_fw_dpc(firmware, context);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function downloads firmware image to the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sd_download_firmware_w_helper(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	int err;
+	char *cur_fw_name = NULL;
+
+	ENTER();
+
+	cur_fw_name = fw_name;
+
+	if (fw_name == NULL) {
+		if (priv->card_type == CARD_TYPE_SD8787)
+			cur_fw_name = DEFAULT_FW_NAME_8787;
+		else if (priv->card_type == CARD_TYPE_SD8777)
+			cur_fw_name = DEFAULT_FW_NAME_8777;
+		else if (priv->card_type == CARD_TYPE_SD8887) {
+			/* Check revision ID */
+			switch (priv->adapter->chip_rev) {
+			case SD8887_A0:
+				cur_fw_name = SD8887_A0_FW_NAME;
+				break;
+			case SD8887_A2:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8887_A2_FW_NAME;
+				else
+					cur_fw_name = SD8887_A2_BT_FW_NAME;
+				break;
+			default:
+				cur_fw_name = DEFAULT_FW_NAME_8887;
+				break;
+			}
+		} else if (priv->card_type == CARD_TYPE_SD8897)
+			cur_fw_name = DEFAULT_FW_NAME_8897;
+		else if (priv->card_type == CARD_TYPE_SD8797)
+			cur_fw_name = DEFAULT_FW_NAME_8797;
+		else if (priv->card_type == CARD_TYPE_SD8977) {
+			switch (priv->adapter->chip_rev) {
+			case SD8977_V0:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8977_V0_FW_NAME;
+				else
+					cur_fw_name = SD8977_V0_BT_FW_NAME;
+				break;
+			case SD8977_V1:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8977_V1_FW_NAME;
+				else
+					cur_fw_name = SD8977_V1_BT_FW_NAME;
+				break;
+			case SD8977_V2:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8977_V2_FW_NAME;
+				else
+					cur_fw_name = SD8977_V2_BT_FW_NAME;
+				break;
+			default:
+				cur_fw_name = DEFAULT_FW_NAME_8977;
+				break;
+			}
+		} else if (priv->card_type == CARD_TYPE_SD8978) {
+			if (bt_fw_serial == 1
+			    && !priv->fw_reload && !bt_fw_reload)
+				cur_fw_name = SD8978_FW_NAME;
+			else
+				cur_fw_name = SD8978_BT_FW_NAME;
+		} else if (priv->card_type == CARD_TYPE_SD8997)
+			switch (priv->adapter->chip_rev) {
+			case SD8997_Z:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload)
+					cur_fw_name = SD8997_Z_FW_NAME;
+				else
+					cur_fw_name = SD8997_Z_BT_FW_NAME;
+				break;
+			case SD8997_V2:
+				if (bt_fw_serial == 1
+				    && !priv->fw_reload && !bt_fw_reload) {
+					if (priv->adapter->magic_val ==
+					    MAGIC_VAL)
+						cur_fw_name = SD8997_V3_FW_NAME;
+					else
+						cur_fw_name = SD8997_V2_FW_NAME;
+				} else {
+					if (priv->adapter->magic_val ==
+					    MAGIC_VAL)
+						cur_fw_name =
+							SD8997_V3_BT_FW_NAME;
+					else
+						cur_fw_name =
+							SD8997_V2_BT_FW_NAME;
+				}
+				break;
+			default:
+				cur_fw_name = DEFAULT_FW_NAME_8997;
+				break;
+		} else if (priv->card_type == CARD_TYPE_SD8987) {
+			if (bt_fw_serial == 1
+			    && !priv->fw_reload && !bt_fw_reload)
+				cur_fw_name = SD8987_FW_NAME;
+			else
+				cur_fw_name = SD8987_BT_FW_NAME;
+		}
+	}
+
+	PRINTM(MSG, "BT Request firmware: %s\n", cur_fw_name);
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      sd_request_fw_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#endif
+#endif
+		if (ret < 0)
+			PRINTM(FATAL,
+			       "BT: request_firmware_nowait() failed, error code = %#x\n",
+			       ret);
+	} else {
+		err = request_firmware(&priv->firmware, cur_fw_name,
+				       priv->hotplug_device);
+		if (err < 0) {
+			PRINTM(FATAL,
+			       "BT: request_firmware() failed, error code = %#x\n",
+			       err);
+			ret = BT_STATUS_FAILURE;
+		} else
+			ret = sd_request_fw_dpc(priv->firmware, priv);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads data from the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_card_to_host(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u16 buf_len = 0;
+	int buf_block_len;
+	int blksz;
+	struct sk_buff *skb = NULL;
+	u32 type;
+	u8 *payload = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+	struct m_dev *mdev_debug = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
+	struct debug_dev *debug_dev =
+		(struct debug_dev *)priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int i = 0;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	do {
+		/* Read the length of data to be transferred */
+		ret = sd_read_rx_len(priv, &buf_len);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR, "BT: Read scratch reg failed (%d)\n", i);
+			if (i >= MAX_CMD52_RETRY) {
+				ret = BT_STATUS_FAILURE;
+				goto exit;
+			}
+			udelay(20);
+		}
+	}
+	while (ret == BT_STATUS_FAILURE);
+
+	/* Allocate buffer */
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (buf_len + blksz - 1) / blksz;
+	if (buf_len <= BT_HEADER_LEN ||
+	    (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+		PRINTM(ERROR, "BT: card_to_host, invalid packet length: %d\n",
+		       buf_len);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	skb = bt_skb_alloc(buf_block_len * blksz + DMA_ALIGNMENT, GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		goto exit;
+	}
+	if ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)) {
+		skb_put(skb,
+			DMA_ALIGNMENT -
+			((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+		skb_pull(skb,
+			 DMA_ALIGNMENT -
+			 ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+	}
+
+	payload = skb->data;
+	i = 0;
+	do {
+		ret = sdio_readsb(card->func, payload, priv->bt_dev.ioport,
+				  buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: card_to_host, read iomem (%d) failed: %d\n",
+			       i, ret);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY) {
+				kfree_skb(skb);
+				skb = NULL;
+				goto exit;
+			}
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	/* This is SDIO specific header length: byte[2][1][0], * type: byte[3]
+	   (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
+	buf_len = payload[0];
+	buf_len |= (u16) payload[1] << 8;
+	type = payload[3];
+	PRINTM(DATA, "BT: SDIO Blk Rd %s: len=%d type=%d\n", mbt_dev->name,
+	       buf_len, type);
+	if (buf_len > buf_block_len * blksz) {
+		PRINTM(ERROR,
+		       "BT: Drop invalid rx pkt, len in hdr=%d, cmd53 length=%d\n",
+		       buf_len, buf_block_len * blksz);
+		ret = BT_STATUS_FAILURE;
+		kfree_skb(skb);
+		skb = NULL;
+		goto exit;
+	}
+	DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Rd", payload, buf_len);
+	switch (type) {
+	case HCI_ACLDATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (*(u16 *) skb->data == 0xffff) {
+			bt_store_firmware_dump(priv, skb->data, skb->len);
+			dev_kfree_skb_any(skb);
+			break;
+		}
+		bt_recv_frame(priv, skb);
+		break;
+	case HCI_SCODATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		bt_recv_frame(priv, skb);
+		break;
+	case HCI_EVENT_PKT:
+		/** add EVT Demux */
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (BT_STATUS_SUCCESS == check_evtpkt(priv, skb))
+			break;
+		switch (skb->data[0]) {
+		case 0x0E:
+			/** cmd complete */
+			if (priv->debug_device_pending) {
+				if (priv->debug_ocf_ogf[0] == skb->data[3] &&
+				    priv->debug_ocf_ogf[1] == skb->data[4]) {
+					priv->debug_device_pending = 0;
+					priv->debug_ocf_ogf[0] = 0;
+					priv->debug_ocf_ogf[1] = 0;
+					/** debug cmd complete */
+					if (debug_dev) {
+						skb->dev = (void *)mdev_debug;
+						mdev_recv_frame(skb);
+						mdev_debug->stat.byte_rx +=
+							buf_len;
+					}
+					break;
+				}
+			}
+			bt_recv_frame(priv, skb);
+			break;
+		case 0x0F:
+			/** cmd status */
+			bt_recv_frame(priv, skb);
+			break;
+		case 0xFF:
+			/** Vendor specific pkt */
+			bt_recv_frame(priv, skb);
+			break;
+		default:
+			bt_recv_frame(priv, skb);
+			break;
+		}
+		break;
+	case MRVL_VENDOR_PKT:
+		/* Just think here need to back compatible FM */
+		bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (BT_STATUS_SUCCESS != bt_process_event(priv, skb))
+			bt_recv_frame(priv, skb);
+		break;
+	default:
+		/* Driver specified event and command resp should be handle
+		   here */
+		PRINTM(INFO, "BT: Unknown PKT type:%d\n", type);
+		kfree_skb(skb);
+		skb = NULL;
+		break;
+	}
+exit:
+	if (ret) {
+		if (mbt_dev)
+			mdev_bt->stat.err_rx++;
+		PRINTM(ERROR, "error when recv pkt!\n");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes the card
+ *
+ *  @param func    A pointer to sdio_func structure
+ *  @return        N/A
+ */
+static void
+sd_remove_card(struct sdio_func *func)
+{
+	struct sdio_mmc_card *card;
+
+	ENTER();
+
+	if (func) {
+		card = sdio_get_drvdata(func);
+		if (card) {
+			bt_remove_card(card->priv);
+			kfree(card);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the interrupt.
+ *
+ *  @param func  A pointer to sdio_func structure
+ *  @return      N/A
+ */
+static void
+sd_interrupt(struct sdio_func *func)
+{
+	bt_private *priv;
+	struct m_dev *m_dev = NULL;
+	struct sdio_mmc_card *card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 ireg = 0;
+	u8 host_intstatus_reg = 0;
+
+	ENTER();
+
+	card = sdio_get_drvdata(func);
+	if (!card || !card->priv) {
+		PRINTM(INFO,
+		       "BT: %s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
+		       __func__, func, card);
+		LEAVE();
+		return;
+	}
+	priv = card->priv;
+	host_intstatus_reg = priv->psdio_device->reg->host_intstatus;
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	if (priv->card_type == CARD_TYPE_SD8887 ||
+	    priv->card_type == CARD_TYPE_SD8897 ||
+	    priv->card_type == CARD_TYPE_SD8977 ||
+	    priv->card_type == CARD_TYPE_SD8997 ||
+	    priv->card_type == CARD_TYPE_SD8987 ||
+	    priv->card_type == CARD_TYPE_SD8978) {
+		ret = sdio_readsb(card->func, priv->adapter->hw_regs, 0,
+				  SD_BLOCK_SIZE);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: sdio_read_ioreg: cmd53 read int status register failed %d\n",
+			       ret);
+			goto done;
+		}
+		ireg = priv->adapter->hw_regs[host_intstatus_reg];
+	} else {
+		ireg = sdio_readb(card->func, host_intstatus_reg, &ret);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: sdio_read_ioreg: CMD52 read int status register failed %d\n",
+			       ret);
+			goto done;
+		}
+	}
+	if (ireg != 0) {
+		/*
+		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+		 * Clear the interrupt status register and re-enable
+		 * the interrupt
+		 */
+		PRINTM(INTR, "BT: INT %s: sdio_ireg = 0x%x\n", m_dev->name,
+		       ireg);
+		priv->adapter->irq_recv = ireg;
+		if (priv->card_type == CARD_TYPE_SD8777 ||
+		    priv->card_type == CARD_TYPE_SD8787) {
+			sdio_writeb(card->func,
+				    ~(ireg) & (DN_LD_HOST_INT_STATUS |
+					       UP_LD_HOST_INT_STATUS),
+				    host_intstatus_reg, &ret);
+			if (ret) {
+				PRINTM(ERROR,
+				       "BT: sdio_write_ioreg: clear int status register failed\n");
+				goto done;
+			}
+		}
+	} else {
+		PRINTM(ERROR, "BT: ERR: ireg=0\n");
+	}
+	OS_INT_DISABLE;
+	priv->adapter->sd_ireg |= ireg;
+	OS_INT_RESTORE;
+	bt_interrupt(m_dev);
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interfaces are present
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @param val    Winner status (0: winner)
+ *  @return       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_check_winner_status(bt_private *priv, u8 *val)
+{
+
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = priv->psdio_device->reg->card_fw_status0;
+
+	ENTER();
+	winner = sdio_readb(cardp->func, card_fw_status0_reg, &ret);
+	if (ret != BT_STATUS_SUCCESS) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** @brief This function tells lower driver that BT is suspended
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        None
+ */
+void
+bt_is_suspended(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	priv->adapter->is_suspended = TRUE;
+	sdio_func_suspended(card->func);
+}
+#endif
+
+/** @brief This function handles client driver suspend
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+int
+bt_sdio_suspend(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is suspended\n",
+		       sdio_func_id(func));
+		return -ENOSYS;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO suspend\n", m_dev->name);
+	mbt_hci_suspend_dev(m_dev);
+	skb_queue_purge(&priv->adapter->tx_queue);
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+#ifdef BLE_WAKEUP
+		/** Set BLE Wake up pattern */
+		if (BT_STATUS_SUCCESS != bt_config_ble_wakeup(priv, FALSE))
+			PRINTM(ERROR, "BT: Set ble wakeup pattern fail!\n");
+#endif
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv, FALSE)) {
+			PRINTM(CMD, "BT: HS not actived, suspend fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv, FALSE)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to suspend!\n");
+			}
+		}
+	}
+
+	priv->adapter->is_suspended = TRUE;
+
+#ifdef SDIO_OOB_IRQ
+	mrvl_sdio_suspend(func);
+#endif
+	LEAVE();
+	/* We will keep the power when hs enabled successfully */
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state == HS_ACTIVATED)) {
+#ifdef MMC_PM_SKIP_RESUME_PROBE
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER and "
+		       "MMC_PM_SKIP_RESUME_PROBE\n");
+		return sdio_set_host_pm_flags(func,
+					      MMC_PM_KEEP_POWER |
+					      MMC_PM_SKIP_RESUME_PROBE);
+#else
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER\n");
+		return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+#endif
+	} else {
+		PRINTM(CMD, "BT: suspend without MMC_PM_KEEP_POWER\n");
+		return BT_STATUS_SUCCESS;
+	}
+}
+
+void
+bt_sdio_shutdown(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: shutdown: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is shutdown\n",
+		       sdio_func_id(func));
+		return;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return;
+	}
+
+	priv = cardp->priv;
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+#ifdef BLE_WAKEUP
+		/** Set BLE Wake up pattern */
+		if (BT_STATUS_SUCCESS != bt_config_ble_wakeup(priv, TRUE))
+			PRINTM(ERROR, "BT: Set ble wakeup pattern fail!\n");
+#endif
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv, TRUE)) {
+			PRINTM(CMD, "BT: HS not actived, shutdown fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv, TRUE)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to shutdown!\n");
+			}
+		}
+	}
+	LEAVE();
+}
+
+/** @brief This function handles client driver resume
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_sdio_resume(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: resume: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+#ifdef BLE_WAKEUP
+	if (priv->ble_wakeup_buf) {
+
+		if (priv->adapter->is_suspended == TRUE) {
+			PRINTM(CMD, "BT, send bt_send_hw_remove_event\n");
+			bt_send_hw_remove_event(priv);
+		} else {
+			PRINTM(CMD, "BT: Send system resume event\n");;
+			bt_send_system_event(priv, FALSE);
+		}
+	}
+#endif
+	priv->adapter->is_suspended = FALSE;
+#ifdef SDIO_OOB_IRQ
+	mrvl_sdio_resume(func);
+#endif
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO resume\n", m_dev->name);
+	mbt_hci_resume_dev(m_dev);
+	sbi_wakeup_firmware(priv);
+	priv->adapter->hs_state = HS_DEACTIVATED;
+	PRINTM(CMD, "BT:%s: HS DEACTIVATED in Resume!\n", m_dev->name);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+#endif
+#endif
+
+/********************************************************
+		Global Functions
+********************************************************/
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+static const struct dev_pm_ops bt_sdio_pm_ops = {
+	.suspend = bt_sdio_suspend,
+	.resume = bt_sdio_resume,
+};
+#endif
+#endif
+static struct sdio_driver sdio_bt = {
+	.name = "sdio_bt",
+	.id_table = bt_ids,
+	.probe = sd_probe_card,
+	.remove = sd_remove_card,
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+	.drv = {
+		.pm = &bt_sdio_pm_ops,
+		.shutdown = bt_sdio_shutdown,
+		}
+#endif
+#endif
+};
+
+/**
+ *  @brief This function registers the bt module in bus driver.
+ *
+ *  @return	   An int pointer that keeps returned value
+ */
+int *
+sbi_register(void)
+{
+	int *ret;
+
+	ENTER();
+
+	if (sdio_register_driver(&sdio_bt) != 0) {
+		PRINTM(FATAL, "BT: SD Driver Registration Failed\n");
+		LEAVE();
+		return NULL;
+	} else
+		ret = (int *)1;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function de-registers the bt module in bus driver.
+ *
+ *  @return        N/A
+ */
+void
+sbi_unregister(void)
+{
+	ENTER();
+	sdio_unregister_driver(&sdio_bt);
+	LEAVE();
+}
+
+/**
+ *  @brief This function registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_dev(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	u8 chiprev;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	struct sdio_func *func;
+	u8 host_intstatus_reg = priv->psdio_device->reg->host_intstatus;
+	u8 host_int_rsr_reg = priv->psdio_device->reg->host_int_rsr_reg;
+	u8 card_misc_cfg_reg = priv->psdio_device->reg->card_misc_cfg_reg;
+	u8 card_revision_reg = priv->psdio_device->reg->card_revision;
+	u8 io_port_0_reg = priv->psdio_device->reg->io_port_0;
+	u8 io_port_1_reg = priv->psdio_device->reg->io_port_1;
+	u8 io_port_2_reg = priv->psdio_device->reg->io_port_2;
+	u8 card_magic_reg = CARD_MAGIC_REG;
+	u8 magic_val = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: Error: card or function is NULL!\n");
+		goto failed;
+	}
+	func = card->func;
+	priv->hotplug_device = &func->dev;
+
+	/* Initialize the private structure */
+	strncpy(priv->bt_dev.name, "bt_sdio0", sizeof(priv->bt_dev.name));
+	priv->bt_dev.ioport = 0;
+	priv->bt_dev.fn = func->num;
+
+	sdio_claim_host(func);
+#ifdef SDIO_OOB_IRQ
+	ret = mrvl_sdio_claim_irq(func, sd_interrupt);
+#else
+	ret = sdio_claim_irq(func, sd_interrupt);
+#endif
+	if (ret) {
+		PRINTM(FATAL, ": sdio_claim_irq failed: ret=%d\n", ret);
+		goto release_host;
+	}
+	ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
+	if (ret) {
+		PRINTM(FATAL, ": %s: cannot set SDIO block size\n", __func__);
+		goto release_irq;
+	}
+
+	/* read Revision Register to get the chip revision number */
+	chiprev = sdio_readb(func, card_revision_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_REVISION_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->chip_rev = chiprev;
+	PRINTM(INFO, "revision=%#x\n", chiprev);
+
+	magic_val = sdio_readb(func, card_magic_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_MAGIC_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->magic_val = magic_val;
+	PRINTM(INFO, "magic_val=%#x\n", magic_val);
+
+	/*
+	 * Read the HOST_INTSTATUS_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.
+	 */
+	reg = sdio_readb(func, host_intstatus_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+
+	/* Read the IO port */
+	reg = sdio_readb(func, io_port_0_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= reg;
+
+	reg = sdio_readb(func, io_port_1_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 8);
+
+	reg = sdio_readb(func, io_port_2_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 16);
+
+	PRINTM(INFO, ": SDIO FUNC%d IO port: 0x%x\n", priv->bt_dev.fn,
+	       priv->bt_dev.ioport);
+
+	if (priv->card_type == CARD_TYPE_SD8977 ||
+	    priv->card_type == CARD_TYPE_SD8978) {
+		if (bt_intmode == INT_MODE_GPIO) {
+			PRINTM(MSG, "Enable GPIO-1 INT\n");
+			sdio_writeb(func, ENABLE_GPIO_1_INT_MODE,
+				    SCRATCH_REG_32, &ret);
+			if (ret < 0)
+				goto release_irq;
+		}
+	}
+
+#define SDIO_INT_MASK       0x3F
+	if (priv->card_type == CARD_TYPE_SD8887 ||
+	    priv->card_type == CARD_TYPE_SD8897 ||
+	    priv->card_type == CARD_TYPE_SD8797 ||
+	    priv->card_type == CARD_TYPE_SD8977 ||
+	    priv->card_type == CARD_TYPE_SD8997 ||
+	    priv->card_type == CARD_TYPE_SD8987 ||
+	    priv->card_type == CARD_TYPE_SD8978) {
+		/* Set Host interrupt reset to read to clear */
+		reg = sdio_readb(func, host_int_rsr_reg, &ret);
+		if (ret < 0)
+			goto release_irq;
+		sdio_writeb(func, reg | SDIO_INT_MASK, host_int_rsr_reg, &ret);
+		if (ret < 0)
+			goto release_irq;
+		/* Set auto re-enable */
+		reg = sdio_readb(func, card_misc_cfg_reg, &ret);
+		if (ret < 0)
+			goto release_irq;
+		sdio_writeb(func, reg | AUTO_RE_ENABLE_INT, card_misc_cfg_reg,
+			    &ret);
+		if (ret < 0)
+			goto release_irq;
+	}
+
+	sdio_set_drvdata(func, card);
+	sdio_release_host(func);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+release_irq:
+#ifdef SDIO_OOB_IRQ
+	mrvl_sdio_release_irq(func);
+#else
+	sdio_release_irq(func);
+#endif
+release_host:
+	sdio_release_host(func);
+failed:
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function de-registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_unregister_dev(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	if (card && card->func) {
+		sdio_claim_host(card->func);
+#ifdef SDIO_OOB_IRQ
+		mrvl_sdio_release_irq(card->func);
+#else
+		sdio_release_irq(card->func);
+#endif
+		sdio_disable_func(card->func);
+		sdio_release_host(card->func);
+		sdio_set_drvdata(card->func, NULL);
+	}
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function enables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_enable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sd_enable_host_int_mask(priv, HIM_ENABLE);
+	sd_get_rx_unit(priv);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function disables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sbi_disable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sbi_disable_host_int_mask(priv, HIM_DISABLE);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param payload A pointer to the data/cmd buffer
+ *  @param nb      Length of data/cmd
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	int ret = BT_STATUS_SUCCESS;
+	int buf_block_len;
+	int blksz;
+	int i = 0;
+	u8 *buf = NULL;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	buf = payload;
+
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (nb + blksz - 1) / blksz;
+	/* Allocate buffer and copy payload */
+	if ((t_ptr)payload & (DMA_ALIGNMENT - 1)) {
+		if (nb > MAX_TX_BUF_SIZE) {
+			PRINTM(ERROR, "BT: Invalid tx packet, size=%d\n", nb);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		}
+		/* Ensure 8-byte aligned CMD buffer */
+		buf = priv->adapter->tx_buf;
+		memcpy(buf, payload, nb);
+	}
+	sdio_claim_host(card->func);
+	do {
+		/* Transfer data to card */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, buf,
+				   buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: host_to_card, write iomem (%d) failed: %d\n",
+			       i, ret);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY)
+				goto exit;
+		} else {
+			PRINTM(DATA, "BT: SDIO Blk Wr %s: len=%d\n",
+			       m_dev->name, nb);
+			DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Wr", payload, nb);
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	priv->bt_dev.tx_dnld_rdy = FALSE;
+exit:
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_download_fw(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	sdio_claim_host(card->func);
+	if (BT_STATUS_SUCCESS == sd_verify_fw_download(priv, 1)) {
+		PRINTM(MSG, "BT: FW already downloaded!\n");
+		sdio_release_host(card->func);
+		sbi_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+	/* Check if other interface is downloading */
+	ret = sd_check_winner_status(priv, &winner);
+	if (ret == BT_STATUS_FAILURE) {
+		PRINTM(FATAL, "BT read winner status failed!\n");
+		goto done;
+	}
+	if (winner) {
+		PRINTM(MSG, "BT is not the winner (0x%x). Skip FW download\n",
+		       winner);
+		/* check if the fimware is downloaded successfully or not */
+		if (sd_verify_fw_download(priv, MAX_MULTI_INTERFACE_POLL_TRIES)) {
+			PRINTM(FATAL, "BT: FW failed to be active in time!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		sdio_release_host(card->func);
+		sbi_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+
+	do_gettimeofday(&priv->req_fw_time);
+	/* Download the main firmware via the helper firmware */
+	if (sd_download_firmware_w_helper(priv)) {
+		PRINTM(INFO, "BT: FW download failed!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+	goto exit;
+done:
+	sdio_release_host(card->func);
+exit:
+	LEAVE();
+	return ret;
+err_register:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the interrupt status and handle it accordingly.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_get_int_status(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 sdio_ireg = 0;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	OS_INT_DISABLE;
+	sdio_ireg = priv->adapter->sd_ireg;
+	priv->adapter->sd_ireg = 0;
+	OS_INT_RESTORE;
+	sdio_claim_host(card->func);
+	priv->adapter->irq_done = sdio_ireg;
+	if (sdio_ireg & DN_LD_HOST_INT_STATUS) {	/* tx_done INT */
+		if (priv->bt_dev.tx_dnld_rdy) {	/* tx_done already received */
+			PRINTM(INFO,
+			       "BT: warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
+			       priv->bt_dev.tx_dnld_rdy, sdio_ireg);
+		} else {
+			priv->bt_dev.tx_dnld_rdy = TRUE;
+		}
+	}
+	if (sdio_ireg & UP_LD_HOST_INT_STATUS)
+		sd_card_to_host(priv);
+
+	ret = BT_STATUS_SUCCESS;
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function wakeup firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sbi_wakeup_firmware(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
+	sdio_release_host(card->func);
+	PRINTM(CMD, "BT wake up firmware\n");
+
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function updates the SDIO card types
+ *
+ *  @param priv     A Pointer to the bt_private structure
+ *  @param card     A Pointer to card
+ *
+ *  @return         N/A
+ */
+void
+sdio_update_card_type(bt_private *priv, void *card)
+{
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)card;
+
+	/* Update card type */
+	if (cardp->func->device == SD_DEVICE_ID_8777_BT_FN2 ||
+	    cardp->func->device == SD_DEVICE_ID_8777_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8777;
+	else if (cardp->func->device == SD_DEVICE_ID_8787_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8787_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8787;
+	else if (cardp->func->device == SD_DEVICE_ID_8887_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8887_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8887;
+	else if (cardp->func->device == SD_DEVICE_ID_8897_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8897_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8897;
+	else if (cardp->func->device == SD_DEVICE_ID_8797_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8797_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8797;
+	else if (cardp->func->device == SD_DEVICE_ID_8977_BT_FN2)
+		priv->card_type = CARD_TYPE_SD8977;
+	else if (cardp->func->device == SD_DEVICE_ID_8978_BT_FN2)
+		priv->card_type = CARD_TYPE_SD8978;
+	else if (cardp->func->device == SD_DEVICE_ID_8997_BT_FN2)
+		priv->card_type = CARD_TYPE_SD8997;
+	else if (cardp->func->device == SD_DEVICE_ID_8987_BT_FN2 ||
+		 cardp->func->device == SD_DEVICE_ID_8987_BT_FN3)
+		priv->card_type = CARD_TYPE_SD8987;
+}
+
+/**
+ *  @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
+ */
+int
+sdio_get_sdio_device(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u16 card_type = priv->card_type;
+
+	ENTER();
+
+	switch (card_type) {
+	case CARD_TYPE_SD8777:
+		priv->psdio_device = &bt_sdio_sd8777;
+		break;
+	case CARD_TYPE_SD8787:
+		priv->psdio_device = &bt_sdio_sd8787;
+		break;
+	case CARD_TYPE_SD8887:
+		priv->psdio_device = &bt_sdio_sd8887;
+		break;
+	case CARD_TYPE_SD8897:
+		priv->psdio_device = &bt_sdio_sd8897;
+		break;
+	case CARD_TYPE_SD8797:
+		priv->psdio_device = &bt_sdio_sd8797;
+		break;
+	case CARD_TYPE_SD8977:
+		priv->psdio_device = &bt_sdio_sd8977;
+		break;
+	case CARD_TYPE_SD8978:
+		priv->psdio_device = &bt_sdio_sd8978;
+		break;
+	case CARD_TYPE_SD8997:
+		priv->psdio_device = &bt_sdio_sd8997;
+		break;
+	case CARD_TYPE_SD8987:
+		priv->psdio_device = &bt_sdio_sd8987;
+		break;
+	default:
+		PRINTM(ERROR, "BT can't get right card type \n");
+		ret = BT_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+#define SD8897_INIT_START_REG  0xDC
+#define SD8897_INIT_END_REG  0xE1
+#define SD8887_INIT_START_REG  0xA0
+#define SD8887_INIT_END_REG  0xA5
+#define SD8977_SD8978_SD8997_INIT_START_REG 0xF1
+#define SD8977_SD8978_SD8997_INIT_END_REG 0xF6
+
+/** @brief This function dump the SDIO register
+ *
+ *  @param priv     A Pointer to the bt_private structure
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_sdio_regs(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	char buf[256], *ptr;
+	u8 loop, func, data;
+	unsigned int reg, reg_start, reg_end;
+	u8 index = 0;
+	unsigned int reg_table_8887[] = { 0x58, 0x59, 0x5c, 0x60, 0x64, 0x70,
+		0x71, 0x72, 0x73, 0xd8, 0xd9, 0xda
+	};
+	u8 loop_num = 0;
+	unsigned int *reg_table = NULL;
+	u8 reg_table_size = 0;
+	unsigned int init_reg_start = 0;
+	unsigned int init_reg_end = 0;
+	if (priv->card_type == CARD_TYPE_SD8887) {
+		init_reg_start = SD8887_INIT_START_REG;
+		init_reg_end = SD8887_INIT_END_REG;
+	} else if (priv->card_type == CARD_TYPE_SD8897) {
+		init_reg_start = SD8897_INIT_START_REG;
+		init_reg_end = SD8897_INIT_END_REG;
+	} else if (priv->card_type == CARD_TYPE_SD8977 ||
+		   priv->card_type == CARD_TYPE_SD8997 ||
+		   priv->card_type == CARD_TYPE_SD8987 ||
+		   priv->card_type == CARD_TYPE_SD8978) {
+		init_reg_start = SD8977_SD8978_SD8997_INIT_START_REG;
+		init_reg_end = SD8977_SD8978_SD8997_INIT_END_REG;
+	}
+
+	if (priv->card_type == CARD_TYPE_SD8887) {
+		loop_num = 3;
+		reg_table = reg_table_8887;
+		reg_table_size = sizeof(reg_table_8887) / sizeof(int);
+	} else
+		loop_num = 2;
+	if (priv->adapter->ps_state)
+		sbi_wakeup_firmware(priv);
+
+	for (loop = 0; loop < loop_num; 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 == 2) {
+			/* Read specific registers of SDIO function1 */
+			index = 0;
+			func = 2;
+			reg_start = reg_table[index++];
+			reg_end = reg_table[reg_table_size - 1];
+		} else {
+			func = 2;
+			reg_start = 0;
+			reg_end = 0x09;
+		}
+		if (loop == 2)
+			ptr += sprintf(ptr, "SDIO Func%d: ", func);
+		else
+			ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", func,
+				       reg_start, reg_end);
+		for (reg = reg_start; reg <= reg_end;) {
+			if (func == 0)
+				ret = sd_f0_read_reg(priv, reg, &data);
+			else
+				ret = sd_read_reg(priv, 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(MSG, "%s\n", buf);
+	}
+
+	if (init_reg_start) {
+		memset(buf, 0, sizeof(buf));
+		ptr = buf;
+		ptr += sprintf(ptr, "Init Status Reg (%#x-%#x): ",
+			       init_reg_start, init_reg_end);
+		for (reg = init_reg_start; reg <= init_reg_end;) {
+			ret = sd_read_reg(priv, reg, &data);
+			if (!ret)
+				ptr += sprintf(ptr, "%02x ", data);
+			else {
+				ptr += sprintf(ptr, "ERR");
+				break;
+			}
+			reg++;
+		}
+		PRINTM(MSG, "%s\n", buf);
+	}
+}
+
+module_param(fw_name, charp, 0);
+MODULE_PARM_DESC(fw_name, "Firmware name");
+module_param(bt_req_fw_nowait, int, 0);
+MODULE_PARM_DESC(bt_req_fw_nowait,
+		 "0: Use request_firmware API; 1: Use request_firmware_nowait API");
+module_param(multi_fn, int, 0);
+MODULE_PARM_DESC(multi_fn, "Bit 2: FN2;");
+
+module_param(bt_intmode, int, 0);
+MODULE_PARM_DESC(bt_intmode, "0: INT_MODE_SDIO, 1: INT_MODE_GPIO");
diff --git a/bt_sd8987/bt_char/hci_wrapper.h b/bt_sd8987/bt_char/hci_wrapper.h
new file mode 100644
index 0000000..a780b69
--- /dev/null
+++ b/bt_sd8987/bt_char/hci_wrapper.h
@@ -0,0 +1,173 @@
+/** @file hci_wrapper.h
+ *  @brief This file contains HCI related definitions
+ *
+ *  Copyright (C) 2011-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _HCI_WRAPPER_H_
+#define _HCI_WRAPPER_H_
+
+#include <linux/module.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+/**  Define Seq num */
+#define BT_SEQ      0
+#define DEBUG_SEQ   3
+
+/** Define dev type */
+#define BT_TYPE     1
+#define BT_AMP_TYPE 2
+#define DEBUG_TYPE  5
+
+/** Define spec type */
+#define BLUEZ_SPEC     1
+#define IANYWHERE_SPEC 2
+#define GENERIC_SPEC   3
+
+/** Define lock/unlock wrapper */
+#define mdev_req_lock(d)		down(&d->req_lock)
+#define mdev_req_unlock(d)		up(&d->req_lock)
+
+/** Length of device name */
+#define DEV_NAME_LEN				32
+
+/** Define struct m_dev */
+struct m_dev {
+	char name[DEV_NAME_LEN];
+	int index;
+	unsigned long flags;
+	spinlock_t lock;
+	struct semaphore req_lock;
+	struct sk_buff_head rx_q;
+	wait_queue_head_t req_wait_q;
+	struct hci_dev_stats stat;
+	struct module *owner;
+	void *dev_pointer;
+	int dev_type;
+	int spec_type;
+	void *driver_data;
+	int wait_rx_complete;
+	int rx_complete_flag;
+	wait_queue_head_t rx_wait_q;
+	spinlock_t rxlock;
+	atomic_t extra_cnt;
+
+	struct sk_buff *evt_skb;
+	struct sk_buff *acl_skb;
+	struct sk_buff *sco_skb;
+
+	int (*open) (struct m_dev * m_dev);
+	int (*close) (struct m_dev * m_dev);
+	int (*flush) (struct m_dev * m_dev);
+	int (*send) (struct m_dev * m_dev, struct sk_buff * skb);
+	void (*destruct) (struct m_dev * m_dev);
+	void (*notify) (struct m_dev * m_dev, unsigned int evt);
+	int (*ioctl) (struct m_dev * m_dev, unsigned int cmd, void *arg);
+	void (*query) (struct m_dev * m_dev, void *arg);
+
+};
+
+/** Define struct mbt_dev */
+struct mbt_dev {
+	/** maybe could add some private member later */
+	char name[DEV_NAME_LEN];
+	unsigned long flags;
+	__u8 type;
+
+	__u16 pkt_type;
+	__u16 esco_type;
+	__u16 link_policy;
+	__u16 link_mode;
+
+	__u32 idle_timeout;
+	__u16 sniff_min_interval;
+	__u16 sniff_max_interval;
+
+	struct sk_buff *reassembly[3];
+
+	atomic_t promisc;
+};
+
+struct debug_dev {
+	/** maybe could add some private member later */
+	char name[DEV_NAME_LEN];
+	unsigned long flags;
+};
+
+/** This function frees m_dev allocation */
+void free_m_dev(struct m_dev *m_dev);
+
+/**
+ *  @brief This function receives frames
+ *
+ *  @param skb	A pointer to struct sk_buff
+ *  @return	0--success otherwise error code
+ */
+static inline int
+mdev_recv_frame(struct sk_buff *skb)
+{
+	struct m_dev *m_dev = (struct m_dev *)skb->dev;
+	if (!m_dev || (!test_bit(HCI_UP, &m_dev->flags)
+		       && !test_bit(HCI_INIT, &m_dev->flags))) {
+		kfree_skb(skb);
+		return -ENXIO;
+	}
+
+	/* Incomming skb */
+	bt_cb(skb)->incoming = 1;
+
+	/* Time stamp */
+	__net_timestamp(skb);
+
+	/* Put type byte before the data */
+	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+
+	/* Queue frame for rx task */
+	skb_queue_tail(&m_dev->rx_q, skb);
+
+	/* Wakeup rx thread */
+	wake_up_interruptible(&m_dev->req_wait_q);
+
+	return 0;
+}
+
+/**
+ *  @brief mbt dev suspend handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_suspend_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+/**
+ *  @brief mbt dev resume handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_resume_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+#endif /* _HCI_WRAPPER_H_ */
diff --git a/bt_sd8987/bt_char/mbt_char.c b/bt_sd8987/bt_char/mbt_char.c
new file mode 100644
index 0000000..e758427
--- /dev/null
+++ b/bt_sd8987/bt_char/mbt_char.c
@@ -0,0 +1,797 @@
+/** @file mbt_char.c
+  *
+  * @brief This file contains the char device function calls
+  *
+  * Copyright (C) 2010-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/path.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+
+#include "bt_drv.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+#include <linux/sched/signal.h>
+#endif
+#include "mbt_char.h"
+
+#ifndef MIN
+/** Find minimum value */
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+static LIST_HEAD(char_dev_list);
+
+static DEFINE_SPINLOCK(char_dev_list_lock);
+
+static int mbtchar_major = MBTCHAR_MAJOR_NUM;
+
+/**
+ *	@brief  Gets char device structure
+ *
+ *	@param dev		A pointer to char_dev
+ *
+ *	@return			kobject structure
+ */
+struct kobject *
+chardev_get(struct char_dev *dev)
+{
+	struct kobject *kobj;
+
+	kobj = bt_priv_get(dev->m_dev->driver_data);
+	if (!kobj)
+		return NULL;
+	PRINTM(INFO, "dev get kobj\n");
+	kobj = kobject_get(&dev->kobj);
+	if (!kobj)
+		bt_priv_put(dev->m_dev->driver_data);
+	return kobj;
+}
+
+/**
+ *	@brief  Prints char device structure
+ *
+ *	@param dev		A pointer to char_dev
+ *
+ *	@return			N/A
+ */
+void
+chardev_put(struct char_dev *dev)
+{
+	if (dev) {
+		struct m_dev *m_dev = dev->m_dev;
+		PRINTM(INFO, "dev put kobj\n");
+		kobject_put(&dev->kobj);
+		if (m_dev)
+			bt_priv_put(m_dev->driver_data);
+	}
+}
+
+/**
+ *	@brief Changes permissions of the dev
+ *
+ *	@param name	pointer to character
+ *	@param mode		mode_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chmod(char *name, mode_t mode)
+{
+	struct path path;
+	struct inode *inode;
+	struct iattr newattrs;
+	int ret;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chmod(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief Changes ownership of the dev
+ *
+ *	@param name	pointer to character
+ *	@param user		uid_t type data
+ *	@param group	gid_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chown(char *name, uid_t user, gid_t group)
+{
+	struct path path;
+	struct inode *inode = NULL;
+	struct iattr newattrs;
+	int ret = 0;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chown(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	newattrs.ia_valid = ATTR_CTIME;
+	if (user != (uid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_UID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_uid = user;
+#else
+		newattrs.ia_uid = KUIDT_INIT(user);
+#endif
+	}
+	if (group != (gid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_GID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_gid = group;
+#else
+		newattrs.ia_gid = KGIDT_INIT(group);
+#endif
+	}
+	if (!S_ISDIR(inode->i_mode))
+		newattrs.ia_valid |=
+			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief write handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes written
+ */
+ssize_t
+chardev_write(struct file * filp, const char *buf, size_t count, loff_t * f_pos)
+{
+	int nwrite = 0;
+	struct sk_buff *skb;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	if (!test_bit(HCI_UP, &m_dev->flags)) {
+		LEAVE();
+		return -EBUSY;
+	}
+	nwrite = count;
+	skb = bt_skb_alloc(count, GFP_ATOMIC);
+	if (!skb) {
+		PRINTM(ERROR, "mbtchar_write(): fail to alloc skb\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	if (copy_from_user((void *)skb_put(skb, count), buf, count)) {
+		PRINTM(ERROR, "mbtchar_write(): cp_from_user failed\n");
+		kfree_skb(skb);
+		nwrite = -EFAULT;
+		goto exit;
+	}
+
+	skb->dev = (void *)m_dev;
+	bt_cb(skb)->pkt_type = *((unsigned char *)skb->data);
+	skb_pull(skb, 1);
+
+	PRINTM(DATA, "Write: pkt_type: 0x%x, len=%d @%lu\n",
+	       bt_cb(skb)->pkt_type, skb->len, jiffies);
+	DBG_HEXDUMP(DAT_D, "chardev_write", skb->data, skb->len);
+
+	/* Send skb to the hci wrapper layer */
+	if (m_dev->send(m_dev, skb)) {
+		PRINTM(ERROR, "Write: Fail\n");
+		nwrite = 0;
+		/* Send failed */
+		kfree_skb(skb);
+	}
+exit:
+	LEAVE();
+	return nwrite;
+}
+
+/**
+ *	@brief read handler for BT char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes read
+ */
+ssize_t
+chardev_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t ret = 0;
+	struct sk_buff *skb = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	/* Wait for rx data */
+	add_wait_queue(&m_dev->req_wait_q, &wait);
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		skb = skb_dequeue(&m_dev->rx_q);
+		if (skb)
+			break;
+		if (!test_bit(HCI_UP, &m_dev->flags)) {
+			ret = -EBUSY;
+			break;
+		}
+
+		if (filp->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			break;
+		}
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&m_dev->req_wait_q, &wait);
+
+	if (!skb)
+		goto out;
+
+	PRINTM(DATA, "BT: chardev_read count=%d pkt_type: 0x%x, len=%d %p\n",
+		(int)count, bt_cb(skb)->pkt_type, skb->len, skb);
+	DBG_HEXDUMP(DAT_D, "chardev_read", skb->data,MIN((int)count,skb->len));
+	if (skb->len > count) {
+		/* user data length is smaller than the skb length */
+		if (copy_to_user(buf, skb->data, count)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		skb_pull(skb, count);
+		skb_queue_head(&m_dev->rx_q, skb);
+		wake_up_interruptible(&m_dev->req_wait_q);
+		ret = count;
+		goto out;
+	} else {
+		if (copy_to_user(buf, skb->data, skb->len)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		ret = skb->len;
+		PRINTM(DATA, "BT: chardev_read complete %p\n",skb);
+	}
+outf:
+	kfree_skb(skb);
+out:
+	if (m_dev->wait_rx_complete && skb_queue_empty(&m_dev->rx_q)) {
+		m_dev->rx_complete_flag = TRUE;
+		wake_up_interruptible(&m_dev->rx_wait_q);
+	}
+	LEAVE();
+	return ret;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+char_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, void *arg)
+#else
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+char_ioctl(struct file *filp, unsigned int cmd, void *arg)
+#endif
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+	case MBTCHAR_IOCTL_RELEASE:
+		m_dev->close(m_dev);
+		break;
+	case MBTCHAR_IOCTL_QUERY_TYPE:
+		m_dev->query(m_dev, arg);
+		break;
+	default:
+		m_dev->ioctl(m_dev, cmd, arg);
+		break;
+	}
+	LEAVE();
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl(struct inode *inode, struct file *filp,
+	      unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, (void *)arg);
+#else
+	return char_ioctl(filp, cmd, (void *)arg);
+#endif
+}
+
+#ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl_compat(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl_compat(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, compat_ptr(arg));
+#else
+	return char_ioctl(filp, cmd, compat_ptr(arg));
+#endif
+}
+#endif /* CONFIG_COMPAT */
+
+/**
+ *	@brief open handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_open(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = NULL;
+	struct m_dev *m_dev = NULL;
+	struct char_dev *cdev = NULL;
+	struct list_head *p = NULL;
+	ENTER();
+
+	list_for_each(p, &char_dev_list) {
+		cdev = list_entry(p, struct char_dev, list);
+		if (mbtchar_major == MAJOR(inode->i_cdev->dev) &&
+		    cdev->minor == MINOR(inode->i_cdev->dev)) {
+			dev = cdev;
+			break;
+		}
+	}
+	if (!dev) {
+		PRINTM(ERROR, "cannot find dev from inode\n");
+		LEAVE();
+		return -ENXIO;
+	}
+	if (!chardev_get(dev)) {
+		LEAVE();
+		return -ENXIO;
+	}
+	filp->private_data = dev;	/* for other methods */
+	m_dev = dev->m_dev;
+	mdev_req_lock(m_dev);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)
+	if (test_bit(HCI_UP, &m_dev->flags)) {
+		atomic_inc(&m_dev->extra_cnt);
+		goto done;
+	}
+#endif
+	if (m_dev->open(m_dev)) {
+		ret = -EIO;
+		goto done;
+	}
+	set_bit(HCI_UP, &m_dev->flags);
+
+done:
+	mdev_req_unlock(m_dev);
+	if (ret)
+		chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief release handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_release(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)
+	if (m_dev && (atomic_dec_if_positive(&m_dev->extra_cnt) >= 0)) {
+		LEAVE();
+		return ret;
+	}
+#endif
+	if (m_dev)
+		ret = dev->m_dev->close(dev->m_dev);
+	filp->private_data = NULL;
+	chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief poll handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param wait		pointer to poll_table structure
+ *	@return			mask
+ */
+static unsigned int
+chardev_poll(struct file *filp, poll_table * wait)
+{
+	unsigned int mask;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+
+	m_dev = dev->m_dev;
+	poll_wait(filp, &m_dev->req_wait_q, wait);
+	mask = POLLOUT | POLLWRNORM;
+	if (skb_peek(&m_dev->rx_q))
+		mask |= POLLIN | POLLRDNORM;
+	if (!test_bit(HCI_UP, &(m_dev->flags)))
+		mask |= POLLHUP;
+	PRINTM(INFO, "poll mask=0x%x\n", mask);
+	LEAVE();
+	return mask;
+}
+
+/* File ops for the Char driver */
+const struct file_operations chardev_fops = {
+	.owner = THIS_MODULE,
+	.read = chardev_read,
+	.write = chardev_write,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	.ioctl = chardev_ioctl,
+#else
+	.unlocked_ioctl = chardev_ioctl,
+#endif
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = chardev_ioctl_compat,
+#endif
+	.open = chardev_open,
+	.release = chardev_release,
+	.poll = chardev_poll,
+};
+
+/**
+ *	@brief This function creates the char dev
+ *
+ *	@param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param mod_name		A pointer to char
+ *  @param dev_name		A pointer to char
+ *	@return				0--success otherwise failure
+ */
+int
+register_char_dev(struct char_dev *dev, struct class *char_class,
+		  char *mod_name, char *dev_name)
+{
+	int ret = 0, dev_num;
+	unsigned long flags;
+	ENTER();
+	/* create the chrdev region */
+	if (mbtchar_major) {
+		dev_num = MKDEV(mbtchar_major, dev->minor);
+		ret = register_chrdev_region(dev_num, 1, mod_name);
+	} else {
+		PRINTM(INFO, "chardev: no major # yet\n");
+		ret = alloc_chrdev_region((dev_t *) & dev_num, dev->minor, 1,
+					  mod_name);
+	}
+
+	if (ret) {
+		PRINTM(ERROR, "chardev: create chrdev_region failed\n");
+		LEAVE();
+		return ret;
+	}
+	if (!mbtchar_major) {
+		/* Store the allocated dev major # */
+		mbtchar_major = MAJOR(dev_num);
+	}
+	dev->cdev = cdev_alloc();
+	dev->cdev->ops = &chardev_fops;
+	dev->cdev->owner = chardev_fops.owner;
+	dev_num = MKDEV(mbtchar_major, dev->minor);
+
+	if (cdev_add(dev->cdev, dev_num, 1)) {
+		PRINTM(ERROR, "chardev: cdev_add failed\n");
+		ret = -EFAULT;
+		goto free_cdev_region;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), NULL, dev_name);
+	}
+	if (dev->dev_type == DEBUG_TYPE) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), NULL, dev_name);
+	}
+#else
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), dev_name);
+	}
+	if (dev->dev_type == DEBUG_TYPE) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), dev_name);
+	}
+#endif
+	PRINTM(INFO, "register char dev=%s\n", dev_name);
+
+	/** modify later */
+
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_add_tail(&dev->list, &char_dev_list);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+
+	LEAVE();
+	return ret;
+free_cdev_region:
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief This function deletes the char dev
+ *
+ *  @param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param dev_name		A pointer to char
+ *  @return				0--success otherwise failure
+ */
+int
+unregister_char_dev(struct char_dev *dev, struct class *char_class,
+		    char *dev_name)
+{
+	ENTER();
+	device_destroy(char_class, MKDEV(mbtchar_major, dev->minor));
+	cdev_del(dev->cdev);
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	PRINTM(INFO, "unregister char dev=%s\n", dev_name);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param char_class	A pointer to class struct
+ *  @return				N/A
+ */
+void
+chardev_cleanup(struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	do {
+		dev = NULL;
+		list_for_each(p, &char_dev_list) {
+			dev = list_entry(p, struct char_dev, list);
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			unregister_char_dev(dev, char_class, dev->m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	} while (dev);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	class_destroy(char_class);
+	LEAVE();
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param m_dev	A pointer to m_dev struct
+ *  @param char_class	A pointer to class struct
+ *  @return			N/A
+ */
+void
+chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_for_each(p, &char_dev_list) {
+		dev = list_entry(p, struct char_dev, list);
+		if (dev->minor == m_dev->index) {
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			dev->m_dev = NULL;
+			unregister_char_dev(dev, char_class, m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	LEAVE();
+}
diff --git a/bt_sd8987/bt_char/mbt_char.h b/bt_sd8987/bt_char/mbt_char.h
new file mode 100644
index 0000000..6b34088
--- /dev/null
+++ b/bt_sd8987/bt_char/mbt_char.h
@@ -0,0 +1,73 @@
+/** @file mbt_char.h
+  *
+  * @brief This file contains mbtchar driver specific defines etc
+  *
+  * Copyright (C) 2010-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+#ifndef __MBT_CHAR_H__
+#define __MBT_CHAR_H__
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+
+/** Define ioctl */
+#define MBTCHAR_IOCTL_RELEASE       _IO('M', 1)
+#define MBTCHAR_IOCTL_QUERY_TYPE    _IO('M', 2)
+#ifdef BLE_WAKEUP
+#define MBTCHAR_IOCTL_BLE_WAKEUP_PARAM _IO('M', 4)
+#define MBTCHAR_IOCTL_BLE_GET_WHITELIST _IO('M', 5)
+#endif
+
+#define MBTCHAR_MAJOR_NUM            (0)
+
+/** Interface specific macros */
+#define MBTCHAR_MINOR_BASE           (0)
+#define FMCHAR_MINOR_BASE            (10)
+#define NFCCHAR_MINOR_BASE           (20)
+#define DEBUGCHAR_MINOR_BASE         (30)
+
+/** Declaration of char_dev struct */
+struct char_dev {
+	struct list_head list;
+	int minor;
+	int dev_type;
+	struct cdev *cdev;
+	struct m_dev *m_dev;
+	struct kobject kobj;
+};
+
+/** Changes permissions of the dev */
+int mbtchar_chmod(char *name, mode_t mode);
+
+/** Changes ownership of the dev */
+int mbtchar_chown(char *name, uid_t user, gid_t group);
+
+/**	This function creates the char dev */
+int register_char_dev(struct char_dev *dev, struct class *char_class,
+		      char *mod_name, char *dev_name);
+
+/**	This function deletes the char dev */
+int unregister_char_dev(struct char_dev *dev, struct class *char_class,
+			char *dev_name);
+
+/**	This function cleans module */
+void chardev_cleanup(struct class *char_class);
+
+/**	This function cleans module */
+void chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class);
+
+#endif /*__MBT_CHAR_H__*/
diff --git a/bt_sd8997/Makefile b/bt_sd8997/Makefile
new file mode 100644
index 0000000..ada84eb
--- /dev/null
+++ b/bt_sd8997/Makefile
@@ -0,0 +1,194 @@
+# File: Makefile
+# Copyright (C) 2007-2018, Marvell International Ltd.
+#
+
+CC=		$(CROSS_COMPILE)gcc
+LD=		$(CROSS_COMPILE)ld
+
+BACKUP=		/root/backup
+YMD=		`date +%Y%m%d%H%M`
+
+#############################################################################
+# Configuration Options
+#############################################################################
+
+# Debug Option
+# DEBUG LEVEL n/1/2:
+# n: NO DEBUG
+# 1: PRINTM(MSG,...), PRINTM(FATAL,...), PRINTM(WARN,...) and PRINTM(INFO,...)
+# 2: All PRINTM()
+CONFIG_DEBUG=1
+
+
+# SDIO suspend/resume
+CONFIG_SDIO_SUSPEND_RESUME=y
+
+
+CONFIG_BLE_WAKEUP=y
+
+#############################################################################
+# Select Platform Tools
+#############################################################################
+
+MODEXT = ko
+
+ifeq ($(CONFIG_64BIT), y)
+	EXTRA_CFLAGS += -DMBT_64BIT
+endif
+
+ifeq ($(CONFIG_T50), y)
+        EXTRA_CFLAGS += -DT50
+        EXTRA_CFLAGS += -DT40
+        EXTRA_CFLAGS += -DT3T
+endif
+
+ifeq ($(CONFIG_BLE_WAKEUP), y)
+        EXTRA_CFLAGS += -DBLE_WAKEUP
+endif
+
+
+
+
+KERNELDIR ?= /usr/src/arm/linux-4.9.61-bg5ct
+CROSS_COMPILE ?= /usr/local/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
+
+
+KERNELVERSION_X86 := 	$(shell uname -r)
+KERNELDIR?=/lib/modules/$(KERNELVERSION_X86)/build
+
+EXTRA_CFLAGS += -I$(KERNELDIR)/include
+
+EXTRA_CFLAGS += -I$(M)/../mbtchar_src
+EXTRA_CFLAGS += -I$(M)/bt
+LD += -S
+
+#ifdef SD8xxx
+BINDIR = ../bin_sd8xxx_btchar
+#endif
+BINDIR = ../bin_sd8997_btchar
+
+
+#############################################################################
+# Compiler Flags
+#############################################################################
+	EXTRA_CFLAGS += -DFPNUM='"36"'
+
+ifeq ($(CONFIG_DEBUG),1)
+	EXTRA_CFLAGS += -DDEBUG_LEVEL1
+endif
+
+ifeq ($(CONFIG_DEBUG),2)
+	EXTRA_CFLAGS += -DDEBUG_LEVEL1
+	EXTRA_CFLAGS += -DDEBUG_LEVEL2
+	DBG=	-dbg
+endif
+
+ifeq ($(CONFIG_SDIO_SUSPEND_RESUME),y)
+	EXTRA_CFLAGS += -DSDIO_SUSPEND_RESUME
+endif
+
+#############################################################################
+# Make Targets
+#############################################################################
+
+BT_CHAR_OBJS = bt_char/bt_main.o bt_char/bt_sdiommc.o bt_char/bt_proc.o bt_char/mbt_char.o
+BT_CHAR_OBJS += bt_char/bt_init.o
+
+BT_BLOCK_OBJS = bt/bt_main.o bt/bt_sdiommc.o bt/bt_proc.o bt/mbt_char.o
+BT_BLOCK_OBJS += bt/bt_init.o
+
+ifneq ($(KERNELRELEASE),)
+
+ifeq ($(CONFIG_BERLIN_SDIO_BT_8997_CHAR_DRV),y)
+BTOBJS = $(BT_CHAR_OBJS)
+MODULE_LINK = y
+endif
+ifeq ($(CONFIG_BERLIN_SDIO_BT_8997_CHAR_DRV),m)
+BTOBJS = $(BT_CHAR_OBJS)
+MODULE_LINK = m
+endif
+ifeq ($(CONFIG_BERLIN_SDIO_BT_8997),y)
+BTOBJS = $(BT_BLOCK_OBJS)
+MODULE_LINK = y
+endif
+ifeq ($(CONFIG_BERLIN_SDIO_BT_8997),m)
+BTOBJS = $(BT_BLOCK_OBJS)
+MODULE_LINK = m
+endif
+
+obj-$(MODULE_LINK) := bt8xxx.o
+bt8xxx-objs := $(BTOBJS)
+
+
+
+# Otherwise we were called directly from the command line; invoke the kernel build system.
+else
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) modules
+endif
+
+###############################################################
+
+export		CC LD EXTRA_CFLAGS KERNELDIR
+
+.PHONY: app/fm_app clean distclean
+
+app/fm_app:
+	$(MAKE) -C  $@
+
+echo:
+
+build:		echo default
+
+	@if [ ! -d $(BINDIR) ]; then \
+		mkdir $(BINDIR); \
+	fi
+
+ifeq ($(CONFIG_MULTI_INTERFACE), y)
+	cp -f mbt8xxx_sdio.$(MODEXT) $(BINDIR)/mbt8997_sdio$(DBG).$(MODEXT)
+else
+	cp -f mbt8xxx.$(MODEXT) $(BINDIR)/mbt8997$(DBG).$(MODEXT)
+endif
+	cp -r config $(BINDIR)
+
+
+
+
+
+	cp -f README $(BINDIR)
+
+	$(MAKE) -C app/fm_app $@ INSTALLDIR=$(BINDIR);
+	cp -f app/fm_app/fmapp $(BINDIR);
+
+clean:
+	-find . -name "*.o" -exec rm {} \;
+	-find . -name "*.ko" -exec rm {} \;
+	-find . -name ".*.cmd" -exec rm {} \;
+	-find . -name "*.mod.c" -exec rm {} \;
+	-find . -name "*.symvers" -exec rm {} \;
+	-find . -name "modules.order" -exec rm {} \;
+	-find . -name ".*.dwo" -exec rm {} \;
+	-find . -name "*dwo" -exec rm {} \;
+	-rm -rf .tmp_versions
+	$(MAKE) -C app/fm_app $@
+
+install: default
+
+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
+	$(MAKE) -C app/fm_app $@
+# End of file;
diff --git a/bt_sd8997/bt/bt_drv.h b/bt_sd8997/bt/bt_drv.h
new file mode 100644
index 0000000..3a75eb0
--- /dev/null
+++ b/bt_sd8997/bt/bt_drv.h
@@ -0,0 +1,858 @@
+/** @file bt_drv.h
+ *  @brief This header file contains global constant/enum definitions,
+ *  global variable declaration.
+ *
+ *  Copyright (C) 2007-2017, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_DRV_H_
+#define _BT_DRV_H_
+
+#include <linux/version.h>
+#include <linux/kthread.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+
+#include "hci_wrapper.h"
+
+#ifndef BIT
+/** BIT definition */
+#define BIT(x) (1UL << (x))
+#endif
+
+#ifdef MBT_64BIT
+typedef u64 t_ptr;
+#else
+typedef u32 t_ptr;
+#endif
+
+/** Define drv_mode bit */
+#define DRV_MODE_BT         BIT(0)
+
+/** Define devFeature bit */
+#define DEV_FEATURE_BT     BIT(0)
+#define DEV_FEATURE_BTAMP     BIT(1)
+#define DEV_FEATURE_BLE     BIT(2)
+
+/** Define maximum number of radio func supported */
+#define MAX_RADIO_FUNC     3
+
+/** MAC address print format */
+#ifndef MACSTR
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+
+/** MAC address print arguments */
+#ifndef MAC2STR
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#endif
+
+/** Debug level : Message */
+#define	DBG_MSG			BIT(0)
+/** Debug level : Fatal */
+#define DBG_FATAL		BIT(1)
+/** Debug level : Error */
+#define DBG_ERROR		BIT(2)
+/** Debug level : Data */
+#define DBG_DATA		BIT(3)
+/** Debug level : Command */
+#define DBG_CMD			BIT(4)
+/** Debug level : Event */
+#define DBG_EVENT		BIT(5)
+/** Debug level : Interrupt */
+#define DBG_INTR		BIT(6)
+
+/** Debug entry : Data dump */
+#define DBG_DAT_D		BIT(16)
+/** Debug entry : Data dump */
+#define DBG_CMD_D		BIT(17)
+
+/** Debug level : Entry */
+#define DBG_ENTRY		BIT(28)
+/** Debug level : Warning */
+#define DBG_WARN		BIT(29)
+/** Debug level : Informative */
+#define DBG_INFO		BIT(30)
+
+#ifdef	DEBUG_LEVEL1
+extern u32 mbt_drvdbg;
+
+#ifdef	DEBUG_LEVEL2
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  \
+	do {if (mbt_drvdbg & DBG_INFO)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...) \
+	do {if (mbt_drvdbg & DBG_WARN)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) \
+	do {if (mbt_drvdbg & DBG_ENTRY) \
+		printk(KERN_DEBUG msg); } while (0)
+#else
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  do {} while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...)  do {} while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) do {} while (0)
+#endif /* DEBUG_LEVEL2 */
+
+/** Print interrupt message */
+#define	PRINTM_INTR(msg...)  \
+	do {if (mbt_drvdbg & DBG_INTR)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print event message */
+#define	PRINTM_EVENT(msg...) \
+	do {if (mbt_drvdbg & DBG_EVENT) \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print command message */
+#define	PRINTM_CMD(msg...)   \
+	do {if (mbt_drvdbg & DBG_CMD)   \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data message */
+#define	PRINTM_DATA(msg...)  \
+	do {if (mbt_drvdbg & DBG_DATA)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print error message */
+#define	PRINTM_ERROR(msg...) \
+	do {if (mbt_drvdbg & DBG_ERROR) \
+		printk(KERN_ERR msg); } while (0)
+/** Print fatal message */
+#define	PRINTM_FATAL(msg...) \
+	do {if (mbt_drvdbg & DBG_FATAL) \
+		printk(KERN_ERR msg); } while (0)
+/** Print message */
+#define	PRINTM_MSG(msg...)   \
+	do {if (mbt_drvdbg & DBG_MSG)   \
+		printk(KERN_ALERT msg); } while (0)
+
+/** Print data dump message */
+#define	PRINTM_DAT_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_DAT_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data dump message */
+#define	PRINTM_CMD_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_CMD_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+
+/** Print message with required level */
+#define	PRINTM(level, msg...) PRINTM_##level(msg)
+
+/** Debug dump buffer length */
+#define DBG_DUMP_BUF_LEN	64
+/** Maximum number of dump per line */
+#define MAX_DUMP_PER_LINE	16
+/** Maximum data dump length */
+#define MAX_DATA_DUMP_LEN	48
+
+static inline void
+hexdump(char *prompt, u8 *buf, int len)
+{
+	int i;
+	char dbgdumpbuf[DBG_DUMP_BUF_LEN];
+	char *ptr = dbgdumpbuf;
+
+	printk(KERN_DEBUG "%s: len=%d\n", prompt, len);
+	for (i = 1; i <= len; i++) {
+		ptr += snprintf(ptr, 4, "%02x ", *buf);
+		buf++;
+		if (i % MAX_DUMP_PER_LINE == 0) {
+			*ptr = 0;
+			printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+			ptr = dbgdumpbuf;
+		}
+	}
+	if (len % MAX_DUMP_PER_LINE) {
+		*ptr = 0;
+		printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+	}
+}
+
+/** Debug hexdump of debug data */
+#define DBG_HEXDUMP_DAT_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_DAT_D) \
+		hexdump(x, y, z); } while (0)
+/** Debug hexdump of debug command */
+#define DBG_HEXDUMP_CMD_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_CMD_D) \
+		hexdump(x, y, z); } while (0)
+
+/** Debug hexdump */
+#define	DBG_HEXDUMP(level, x, y, z)    DBG_HEXDUMP_##level(x, y, z)
+
+/** Mark entry point */
+#define	ENTER()			PRINTM(ENTRY, "Enter: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+/** Mark exit point */
+#define	LEAVE()			PRINTM(ENTRY, "Leave: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+#else
+/** Do nothing */
+#define	PRINTM(level, msg...) do {} while (0)
+/** Do nothing */
+#define DBG_HEXDUMP(level, x, y, z)    do {} while (0)
+/** Do nothing */
+#define	ENTER()  do {} while (0)
+/** Do nothing */
+#define	LEAVE()  do {} while (0)
+#endif /* DEBUG_LEVEL1 */
+
+/** Bluetooth upload size */
+#define	BT_UPLD_SIZE				2312
+/** Bluetooth status success */
+#define BT_STATUS_SUCCESS			(0)
+/** Bluetooth status failure */
+#define BT_STATUS_FAILURE			(-1)
+
+#ifndef	TRUE
+/** True value */
+#define TRUE			1
+#endif
+#ifndef	FALSE
+/** False value */
+#define	FALSE			0
+#endif
+
+/** Set thread state */
+#define OS_SET_THREAD_STATE(x)		set_current_state(x)
+/** Time to wait until Host Sleep state change in millisecond */
+#define WAIT_UNTIL_HS_STATE_CHANGED 2000
+/** Time to wait cmd resp in millisecond */
+#define WAIT_UNTIL_CMD_RESP	    5000
+
+/** Sleep until a condition gets true or a timeout elapses */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	interruptible_sleep_on_timeout(&waitq, ((timeout) * HZ / 1000))
+#else
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
+#endif
+
+typedef struct {
+	/** Task */
+	struct task_struct *task;
+	/** Queue */
+	wait_queue_head_t waitQ;
+	/** PID */
+	pid_t pid;
+	/** Private structure */
+	void *priv;
+} bt_thread;
+
+static inline void
+bt_activate_thread(bt_thread *thr)
+{
+	/** Initialize the wait queue */
+	init_waitqueue_head(&thr->waitQ);
+
+	/** Record the thread pid */
+	thr->pid = current->pid;
+}
+
+static inline void
+bt_deactivate_thread(bt_thread *thr)
+{
+	thr->pid = 0;
+	return;
+}
+
+static inline void
+bt_create_thread(int (*btfunc) (void *), bt_thread *thr, char *name)
+{
+	thr->task = kthread_run(btfunc, thr, "%s", name);
+}
+
+static inline int
+bt_terminate_thread(bt_thread *thr)
+{
+	/* Check if the thread is active or not */
+	if (!thr->pid)
+		return -1;
+
+	kthread_stop(thr->task);
+	return 0;
+}
+
+static inline void
+os_sched_timeout(u32 millisec)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	schedule_timeout((millisec * HZ) / 1000);
+}
+
+#ifndef __ATTRIB_ALIGN__
+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
+#endif
+
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__ __attribute__((packed))
+#endif
+
+/** BT histogram command */
+#define BT_CMD_HISTOGRAM            0xEA
+/** max antenna num */
+#define MAX_ANTENNA_NUM             2
+/** BDR 1M */
+#define BDR_RATE_1M					1
+/** EDR 2/3 M */
+#define EDR_RATE_2_3M			    2
+/** BLE 1M */
+#define BLE_RATE_1M                 5
+/** max bt link number */
+#define MAX_BT_LINK                 10
+/** max ble link number */
+#define MAX_BLE_LINK                16
+
+typedef struct _bt_link_stat {
+    /** txrx rate 1: BDR_1M, 2:EDR 2/3 M, 3:BLE 1M */
+	u8 txrxrate;
+    /** power: -30 = N = 20 dbm*/
+	s8 txpower;
+    /** rssi: -127 to +20 (For BT), -128 to +127 (For BLE) */
+	s8 rssi;
+} __ATTRIB_PACK__ bt_link_stat;
+
+typedef struct _bt_histogram_data {
+	u8 antenna;
+	u8 powerclass;
+	bt_link_stat link[MAX_BT_LINK + MAX_BLE_LINK];
+} __ATTRIB_PACK__ bt_histogram_data;
+
+typedef struct _bt_hist_proc_data {
+    /** antenna */
+	u8 antenna;
+	/** Private structure */
+	struct _bt_private *pbt;
+} bt_hist_proc_data;
+
+/** Data structure for the Marvell Bluetooth device */
+typedef struct _bt_dev {
+	/** device name */
+	char name[DEV_NAME_LEN];
+	/** card pointer */
+	void *card;
+	/** IO port */
+	u32 ioport;
+
+	struct m_dev m_dev[MAX_RADIO_FUNC];
+
+	/** Tx download ready flag */
+	u8 tx_dnld_rdy;
+	/** Function */
+	u8 fn;
+	/** Rx unit */
+	u8 rx_unit;
+	/** Power Save mode : Timeout configuration */
+	u16 idle_timeout;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save command */
+	u8 pscmd;
+	/** Host Sleep mode */
+	u8 hsmode;
+	/** Host Sleep command */
+	u8 hscmd;
+	/** Low byte is gap, high byte is GPIO */
+	u16 gpio_gap;
+	/** Host Sleep configuration command */
+	u8 hscfgcmd;
+	/** Host Send Cmd Flag		 */
+	u8 sendcmdflag;
+	/** opcode for Send Cmd */
+	u16 send_cmd_opcode;
+	/** Device Type			*/
+	u8 devType;
+	/** Device Features    */
+	u8 devFeature;
+	/** cmd52 function */
+	u8 cmd52_func;
+	/** cmd52 register */
+	u8 cmd52_reg;
+	/** cmd52 value */
+	u8 cmd52_val;
+	/** SDIO pull control command */
+	u8 sdio_pull_ctrl;
+	/** Low 2 bytes is pullUp, high 2 bytes for pull-down */
+	u32 sdio_pull_cfg;
+	/** Test mode command */
+	u8 test_mode;
+} bt_dev_t, *pbt_dev_t;
+
+typedef struct _bt_adapter {
+	/** Chip revision ID */
+	u8 chip_rev;
+    /** magic val */
+	u8 magic_val;
+	/** Surprise removed flag */
+	u8 SurpriseRemoved;
+	/** IRQ number */
+	int irq;
+	/** Interrupt counter */
+	u32 IntCounter;
+	/** Tx packet queue */
+	struct sk_buff_head tx_queue;
+	/** Pending Tx packet queue */
+	struct sk_buff_head pending_queue;
+	/** tx lock flag */
+	u8 tx_lock;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save state */
+	u8 ps_state;
+	/** Host Sleep state */
+	u8 hs_state;
+	/** hs skip count */
+	u32 hs_skip;
+	/** suspend_fail flag */
+	u8 suspend_fail;
+	/** suspended flag */
+	u8 is_suspended;
+	/** Number of wakeup tries */
+	u8 WakeupTries;
+	/** Host Sleep wait queue */
+	wait_queue_head_t cmd_wait_q __ATTRIB_ALIGN__;
+	/** Host Cmd complet state */
+	u8 cmd_complete;
+	/** last irq recv */
+	u8 irq_recv;
+	/** last irq processed */
+	u8 irq_done;
+	/** sdio int status */
+	u8 sd_ireg;
+     /** buf allocated for transmit */
+	u8 *tx_buffer;
+    /** buf for transmit */
+	u8 *tx_buf;
+    /** buf allocated for read interrupt status */
+	u8 *hw_regs_buf;
+    /** buf for read interrupt status */
+	u8 *hw_regs;
+	/** tx pending */
+	u32 skb_pending;
+/** Version string buffer length */
+#define MAX_VER_STR_LEN         128
+	/** Driver version */
+	u8 drv_ver[MAX_VER_STR_LEN];
+	/** Number of command timeout */
+	u32 num_cmd_timeout;
+} bt_adapter, *pbt_adapter;
+
+/** Length of prov name */
+#define PROC_NAME_LEN				32
+
+struct item_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** Size */
+	u32 size;
+	/** Address */
+	t_ptr addr;
+	/** Offset */
+	u32 offset;
+	/** Flag */
+	u32 flag;
+};
+
+struct proc_private_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** File flag */
+	u32 fileflag;
+	/** Buffer size */
+	u32 bufsize;
+	/** Number of items */
+	u32 num_items;
+	/** Item data */
+	struct item_data *pdata;
+	/** Private structure */
+	struct _bt_private *pbt;
+	/** File operations */
+	const struct file_operations *fops;
+};
+
+struct device_proc {
+	/** Proc directory entry */
+	struct proc_dir_entry *proc_entry;
+    /** proc entry for hist */
+	struct proc_dir_entry *hist_entry;
+	/** num of proc files */
+	u8 num_proc_files;
+	/** pointer to proc_private_data */
+	struct proc_private_data *pfiles;
+};
+
+/** Private structure for the MV device */
+typedef struct _bt_private {
+	/** Bluetooth device */
+	bt_dev_t bt_dev;
+	/** Adapter */
+	bt_adapter *adapter;
+	/** Firmware helper */
+	const struct firmware *fw_helper;
+	/** Firmware */
+	const struct firmware *firmware;
+	/** Init user configure file */
+	const struct firmware *init_user_cfg;
+	/** Init user configure wait queue token */
+	u16 init_user_conf_wait_flag;
+	/** Init user configure file wait queue */
+	wait_queue_head_t init_user_conf_wait_q __ATTRIB_ALIGN__;
+	/** Firmware request start time */
+	struct timeval req_fw_time;
+	/** Hotplug device */
+	struct device *hotplug_device;
+	/** thread to service interrupts */
+	bt_thread MainThread;
+	 /** proc data */
+	struct device_proc dev_proc[MAX_RADIO_FUNC];
+	/** Driver lock */
+	spinlock_t driver_lock;
+	/** Driver lock flags */
+	ulong driver_flags;
+	/** Driver reference flags */
+	struct kobject kobj;
+	u8 fw_reload;
+	/* hist_data_len */
+	u8 hist_data_len;
+    /** hist data */
+	bt_histogram_data hist_data[MAX_ANTENNA_NUM];
+    /** hist proc data */
+	bt_hist_proc_data hist_proc[MAX_ANTENNA_NUM];
+#ifdef BLE_WAKEUP
+	u8 ble_wakeup_buf_size;
+	u8 *ble_wakeup_buf;
+#endif
+} bt_private, *pbt_private;
+
+int bt_get_histogram(bt_private *priv);
+
+/** Disable interrupt */
+#define OS_INT_DISABLE	spin_lock_irqsave(&priv->driver_lock, \
+						priv->driver_flags)
+/** Enable interrupt */
+#define	OS_INT_RESTORE	spin_unlock_irqrestore(&priv->driver_lock, \
+						priv->driver_flags)
+
+#ifndef HCI_BT_AMP
+/** BT_AMP flag for device type */
+#define  HCI_BT_AMP		0x80
+#endif
+
+/** Device type of BT */
+#define DEV_TYPE_BT		0x00
+/** Device type of AMP */
+#define DEV_TYPE_AMP		0x01
+
+/** Marvell vendor packet */
+#define MRVL_VENDOR_PKT			0xFE
+
+/** Bluetooth command : Get FW Version */
+#define BT_CMD_GET_FW_VERSION       0x0F
+/** Bluetooth command : Sleep mode */
+#define BT_CMD_AUTO_SLEEP_MODE		0x23
+/** Bluetooth command : Host Sleep configuration */
+#define BT_CMD_HOST_SLEEP_CONFIG	0x59
+/** Bluetooth command : Host Sleep enable */
+#define BT_CMD_HOST_SLEEP_ENABLE	0x5A
+/** Bluetooth command : Module Configuration request */
+#define BT_CMD_MODULE_CFG_REQ		0x5B
+
+/** Bluetooth command : PMIC Configure */
+#define BT_CMD_PMIC_CONFIGURE           0x7D
+
+/** Bluetooth command : SDIO pull up down configuration request */
+#define BT_CMD_SDIO_PULL_CFG_REQ	0x69
+/** Bluetooth command : Set Evt Filter Command */
+#define BT_CMD_SET_EVT_FILTER		0x05
+/** Bluetooth command : Enable Write Scan Command */
+#define BT_CMD_ENABLE_WRITE_SCAN	0x1A
+/** Bluetooth command : Enable Device under test mode */
+#define BT_CMD_ENABLE_DEVICE_TESTMODE	0x03
+/** Sub Command: Module Bring Up Request */
+#define MODULE_BRINGUP_REQ		0xF1
+/** Sub Command: Module Shut Down Request */
+#define MODULE_SHUTDOWN_REQ		0xF2
+/** Module already up */
+#define MODULE_CFG_RESP_ALREADY_UP      0x0c
+/** Sub Command: Host Interface Control Request */
+#define MODULE_INTERFACE_CTRL_REQ	0xF5
+
+/** Bluetooth event : Power State */
+#define BT_EVENT_POWER_STATE		0x20
+
+/** Bluetooth Power State : Enable */
+#define BT_PS_ENABLE			0x02
+/** Bluetooth Power State : Disable */
+#define BT_PS_DISABLE			0x03
+/** Bluetooth Power State : Sleep */
+#define BT_PS_SLEEP			0x01
+/** Bluetooth Power State : Awake */
+#define BT_PS_AWAKE			0x02
+
+/** Vendor OGF */
+#define VENDOR_OGF				0x3F
+/** OGF for reset */
+#define RESET_OGF		0x03
+/** Bluetooth command : Reset */
+#define BT_CMD_RESET	0x03
+
+/** Host Sleep activated */
+#define HS_ACTIVATED			0x01
+/** Host Sleep deactivated */
+#define HS_DEACTIVATED			0x00
+
+/** Power Save sleep */
+#define PS_SLEEP			0x01
+/** Power Save awake */
+#define PS_AWAKE			0x00
+
+/** bt header length */
+#define BT_HEADER_LEN			4
+
+#ifndef MAX
+/** Return maximum of two */
+#define MAX(a, b)		((a) > (b) ? (a) : (b))
+#endif
+
+/** This is for firmware specific length */
+#define EXTRA_LEN	36
+
+/** Command buffer size for Marvell driver */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+
+/** Bluetooth Rx packet buffer size for Marvell driver */
+#define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \
+	(HCI_MAX_FRAME_SIZE + EXTRA_LEN)
+
+/** Buffer size to allocate */
+#define ALLOC_BUF_SIZE	(((MAX(MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \
+			MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \
+			+ SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
+
+/** Request FW timeout in second */
+#define REQUEST_FW_TIMEOUT		30
+
+/** 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
+
+/** default idle time */
+#define DEFAULT_IDLE_TIME           1000
+
+#define BT_CMD_HEADER_SIZE    3
+
+typedef struct _BT_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[128];
+} __ATTRIB_PACK__ BT_CMD;
+
+typedef struct _BT_EVENT {
+	/** Event Counter */
+	u8 EC;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[8];
+} BT_EVENT;
+
+#if defined(SDIO_SUSPEND_RESUME)
+#define DEF_GPIO_GAP        0xffff
+#endif
+
+#ifdef BLE_WAKEUP
+#define BD_ADDR_SIZE 6
+/** Vendor specific event */
+#define VENDOR_SPECIFIC_EVENT     0xff
+/** system suspend event */
+#define HCI_SYSTEM_SUSPEND_EVT    0x80
+/** system suspend */
+#define HCI_SYSTEM_SUSPEND        0x00
+/** system resume */
+#define HCI_SYSTEM_RESUME         0x01
+/** This function enables ble wake up pattern */
+int bt_config_ble_wakeup(bt_private *priv);
+int bt_send_system_event(bt_private *priv, u8 flag);
+#endif
+
+/** This function verify the received event pkt */
+int check_evtpkt(bt_private *priv, struct sk_buff *skb);
+
+/* Prototype of global function */
+/** This function gets the priv reference */
+struct kobject *bt_priv_get(bt_private *priv);
+/** This function release the priv reference */
+void bt_priv_put(bt_private *priv);
+/** This function adds the card */
+bt_private *bt_add_card(void *card);
+/** This function removes the card */
+int bt_remove_card(void *card);
+/** This function handles the interrupt */
+void bt_interrupt(struct m_dev *m_dev);
+
+/** This function creates proc interface directory structure */
+int bt_root_proc_init(void);
+/** This function removes proc interface directory structure */
+int bt_root_proc_remove(void);
+/** This function initializes proc entry */
+int bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq);
+/** This function removes proc interface */
+void bt_proc_remove(bt_private *priv);
+
+/** This function process the received event */
+int bt_process_event(bt_private *priv, struct sk_buff *skb);
+/** This function enables host sleep */
+int bt_enable_hs(bt_private *priv);
+/** This function used to send command to firmware */
+int bt_prepare_command(bt_private *priv);
+/** This function frees the structure of adapter */
+void bt_free_adapter(bt_private *priv);
+
+/** clean up m_devs */
+void clean_up_m_devs(bt_private *priv);
+/** bt driver call this function to register to bus driver */
+int *sbi_register(void);
+/** bt driver call this function to unregister to bus driver */
+void sbi_unregister(void);
+/** bt driver calls this function to register the device  */
+int sbi_register_dev(bt_private *priv);
+/** bt driver calls this function to unregister the device */
+int sbi_unregister_dev(bt_private *priv);
+/** This function initializes firmware */
+int sbi_download_fw(bt_private *priv);
+/** Configures hardware to quit deep sleep state */
+int sbi_wakeup_firmware(bt_private *priv);
+/** Module configuration and register device */
+int sbi_register_conf_dpc(bt_private *priv);
+
+/** This function is used to send the data/cmd to hardware */
+int sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb);
+/** This function reads the current interrupt status register */
+int sbi_get_int_status(bt_private *priv);
+
+/** bt fw reload flag */
+extern int bt_fw_reload;
+/** 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
+/** This function reload firmware */
+void bt_request_fw_reload(bt_private *priv, int mode);
+/** This function enables the host interrupts */
+int sd_enable_host_int(bt_private *priv);
+/** This function disables the host interrupts */
+int sd_disable_host_int(bt_private *priv);
+#define MAX_TX_BUF_SIZE     2312
+/** This function downloads firmware image to the card */
+int sd_download_firmware_w_helper(bt_private *priv);
+void bt_dump_sdio_regs(bt_private *priv);
+/* dumps the firmware to /var/ or /data/ */
+void bt_dump_firmware_info_v2(bt_private *priv);
+
+/** 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
+
+/** Bluetooth command : Mac address configuration */
+#define BT_CMD_CONFIG_MAC_ADDR		0x22
+/** Bluetooth command : Write CSU register */
+#define BT_CMD_CSU_WRITE_REG		0x66
+/** Bluetooth command : Load calibrate data */
+#define BT_CMD_LOAD_CONFIG_DATA     0x61
+/** Bluetooth command : Load calibrate ext data */
+#define BT_CMD_LOAD_CONFIG_DATA_EXT     0x60
+
+/** Bluetooth command : BLE deepsleep */
+#define BT_CMD_BLE_DEEP_SLEEP       0x8b
+
+typedef struct _BT_BLE_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** deepsleep flag */
+	u8 deepsleep;
+} __ATTRIB_PACK__ BT_BLE_CMD;
+
+typedef struct _BT_CSU_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** reg type */
+	u8 type;
+	/** address */
+	u8 offset[4];
+	/** Data */
+	u8 value[2];
+} __ATTRIB_PACK__ BT_CSU_CMD;
+
+/** This function sets mac address */
+int bt_set_mac_address(bt_private *priv, u8 *mac);
+/** This function writes value to CSU registers */
+int bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value);
+/** BT set user defined init data and param */
+int bt_init_config(bt_private *priv, char *cfg_file);
+/** BT PMIC Configure command */
+int bt_pmic_configure(bt_private *priv);
+/** This function load the calibrate data */
+int bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac);
+/** This function load the calibrate ext data */
+int bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len);
+/** BT set user defined calibration data */
+int bt_cal_config(bt_private *priv, char *cfg_file, char *mac);
+/** BT set user defined calibration ext data */
+int bt_cal_config_ext(bt_private *priv, char *cfg_file);
+int bt_init_mac_address(bt_private *priv, char *mac);
+
+int bt_set_independent_reset(bt_private *priv);
+/** Bluetooth command : Independent reset */
+#define BT_CMD_INDEPENDENT_RESET     0x0D
+
+typedef struct _BT_HCI_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** cmd type */
+	u8 cmd_type;
+	/** cmd len */
+	u8 cmd_len;
+	/** Data */
+	u8 data[6];
+} __ATTRIB_PACK__ BT_HCI_CMD;
+
+#endif /* _BT_DRV_H_ */
diff --git a/bt_sd8997/bt/bt_init.c b/bt_sd8997/bt/bt_init.c
new file mode 100644
index 0000000..498c0de
--- /dev/null
+++ b/bt_sd8997/bt/bt_init.c
@@ -0,0 +1,751 @@
+/** @file bt_init.c
+  *
+  * @brief This file contains the init functions for BlueTooth
+  * driver.
+  *
+  * Copyright (C) 2011-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/string.h>
+#include <linux/firmware.h>
+
+#include "bt_drv.h"
+
+extern int bt_req_fw_nowait;
+
+#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
+			 || ('a' <= (c) && (c) <= 'f') \
+			 || ('A' <= (c) && (c) <= 'F'))
+
+#define isdigit(c)	(('0' <= (c) && (c) <= '9'))
+#define isspace(c)  (c <= ' ' && (c == ' ' || (c <= 13 && c >= 9)))
+/**
+ *  @brief Returns hex value of a give character
+ *
+ *  @param chr	Character to be converted
+ *
+ *  @return	The converted character if chr is a valid hex, else 0
+ */
+static int
+bt_hexval(char chr)
+{
+	ENTER();
+
+	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;
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @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
+ */
+static char *
+bt_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 Returns hex value of a given ascii string
+ *
+ *  @param a	String to be converted
+ *
+ *  @return	hex value
+ */
+static int
+bt_atox(const char *a)
+{
+	int i = 0;
+	ENTER();
+	while (isxdigit(*a))
+		i = i * 16 + bt_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief Converts 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
+ */
+static void
+bt_mac2u8(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;
+	}
+	memcpy(mac_buff, buf, strlen(buf));
+
+	begin = mac_buff;
+	for (i = 0; i < ETH_ALEN; ++i) {
+		end = bt_strsep(&begin, ':', '/');
+		if (end)
+			mac_addr[i] = bt_atox(end);
+	}
+
+	kfree(mac_buff);
+	LEAVE();
+}
+
+/**
+ *  @brief Returns integer value of a given ascii string
+ *
+ *  @param data    Converted data to be returned
+ *  @param a       String to be converted
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_atoi(int *data, char *a)
+{
+	int i, val = 0, len;
+
+	ENTER();
+
+	len = strlen(a);
+	if (!strncmp(a, "0x", 2)) {
+		a = a + 2;
+		len -= 2;
+		*data = bt_atox(a);
+		return BT_STATUS_SUCCESS;
+	}
+	for (i = 0; i < len; i++) {
+		if (isdigit(a[i])) {
+			val = val * 10 + (a[i] - '0');
+		} else {
+			PRINTM(ERROR, "Invalid char %c in string %s\n", a[i],
+			       a);
+			return BT_STATUS_FAILURE;
+		}
+	}
+	*data = val;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief parse cal-data
+ *
+ *  @param src      a pointer to cal-data string
+ *  @param len      len of cal-data
+ *  @param dst      a pointer to return cal-data
+ *  @param dst_size size of dest buffer
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 *dst_size)
+{
+	const u8 *ptr;
+	u8 *dptr;
+	u32 count = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	ptr = src;
+	dptr = dst;
+
+	while ((ptr - src) < len) {
+		if (*ptr && isspace(*ptr)) {
+			ptr++;
+			continue;
+		}
+
+		if (isxdigit(*ptr)) {
+			if ((dptr - dst) >= *dst_size) {
+				PRINTM(ERROR, "cal_file size too big!!!\n");
+				goto done;
+			}
+			*dptr++ = bt_atox((const char *)ptr);
+			ptr += 2;
+			count++;
+		} else {
+			ptr++;
+		}
+	}
+	if (dptr == dst) {
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	*dst_size = count;
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT get one line data from ASCII format data
+ *
+ *    @param data         Source data
+ *    @param size         Source data length
+ *    @param line_pos     Destination data
+ *    @return             -1 or length of the line
+ */
+int
+parse_cfg_get_line(u8 *data, u32 size, u8 *line_pos)
+{
+	static s32 pos;
+	u8 *src, *dest;
+
+	if (pos >= size) {	/* reach the end */
+		pos = 0;	/* Reset position for rfkill */
+		return -1;
+	}
+	memset(line_pos, 0, MAX_LINE_LEN);
+	src = data + pos;
+	dest = line_pos;
+
+	while (pos < size && *src != '\x0A' && *src != '\0') {
+		if (*src != ' ' && *src != '\t')	/* parse space */
+			*dest++ = *src++;
+		else
+			src++;
+		pos++;
+	}
+	*dest = '\0';
+	/* parse new line */
+	pos++;
+	return strlen((const char *)line_pos);
+}
+
+/**
+ *    @brief BT parse ASCII format data to MAC address
+ *
+ *    @param priv          BT private handle
+ *    @param data          Source data
+ *    @param size          data length
+ *    @return              BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_init_cfg(bt_private *priv, u8 *data, u32 size)
+{
+	u8 *pos;
+	u8 *intf_s, *intf_e;
+	u8 s[MAX_LINE_LEN];	/* 1 line data */
+	u32 line_len;
+	char dev_name[MAX_PARAM_LEN];
+	u8 buf[MAX_PARAM_LEN];
+	u8 bt_addr[MAX_MAC_ADDR_LEN];
+	u8 bt_mac[ETH_ALEN];
+	int setting = 0;
+	u8 type = 0;
+	u16 value = 0;
+	u32 offset = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	memset(dev_name, 0, sizeof(dev_name));
+	memset(bt_addr, 0, sizeof(bt_addr));
+	memset(bt_mac, 0, sizeof(bt_mac));
+
+	while ((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;	/* Need n't process this line */
+
+		/* Process MAC addr */
+		if (strncmp((char *)pos, "mac_addr", 8) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ':');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				if ((intf_e - intf_s) > MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Too long interface name %d\n",
+					       __LINE__);
+					goto done;
+				}
+				strncpy(dev_name, (const char *)intf_s + 1,
+					intf_e - intf_s - 1);
+				dev_name[intf_e - intf_s - 1] = '\0';
+				strncpy((char *)bt_addr,
+					(const char *)intf_e + 1,
+					MAX_MAC_ADDR_LEN - 1);
+				bt_addr[MAX_MAC_ADDR_LEN - 1] = '\0';
+				/* Convert MAC format */
+				bt_mac2u8(bt_mac, (char *)bt_addr);
+				PRINTM(CMD,
+				       "HCI: %s new BT Address " MACSTR "\n",
+				       dev_name, MAC2STR(bt_mac));
+				if (BT_STATUS_SUCCESS !=
+				    bt_set_mac_address(priv, bt_mac)) {
+					PRINTM(FATAL,
+					       "BT: Fail to set mac address\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+		}
+		/* Process REG value */
+		else if (strncmp((char *)pos, "bt_reg", 6) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ',');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				/* Copy type */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s + 1,
+					1);
+				buf[1] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					type = (u8)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg type\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			intf_e = (u8 *)strchr((const char *)intf_s, ',');
+			if (intf_e != NULL) {
+				if ((intf_e - intf_s) >= MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Regsier offset is too long %d\n",
+					       __LINE__);
+					goto done;
+				}
+				/* Copy offset */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s,
+					intf_e - intf_s);
+				buf[intf_e - intf_s] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					offset = (u32)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg offset\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			if ((strlen((const char *)intf_s) >= MAX_PARAM_LEN)) {
+				PRINTM(ERROR,
+				       "BT: Regsier value is too long %d\n",
+				       __LINE__);
+				goto done;
+			}
+			/* Copy value */
+			memset(buf, 0, sizeof(buf));
+			strncpy((char *)buf, (const char *)intf_s, sizeof(buf));
+			if (0 == bt_atoi(&setting, (char *)buf))
+				value = (u16) setting;
+			else {
+				PRINTM(ERROR, "BT: Fail to parse reg value\n");
+				goto done;
+			}
+
+			PRINTM(CMD,
+			       "BT: Write reg type: %d offset: 0x%x value: 0x%x\n",
+			       type, offset, value);
+			if (BT_STATUS_SUCCESS !=
+			    bt_write_reg(priv, type, offset, value)) {
+				PRINTM(FATAL,
+				       "BT: Write reg failed. type: %d offset: 0x%x value: 0x%x\n",
+				       type, offset, value);
+				goto done;
+			}
+		}
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief BT 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 bt_private structure
+ *
+ * @return          N/A
+ */
+static void
+bt_request_init_user_conf_callback(const struct firmware *firmware,
+				   void *context)
+{
+	bt_private *priv = (bt_private *)context;
+
+	ENTER();
+
+	if (!firmware)
+		PRINTM(ERROR, "BT user init config request firmware failed\n");
+
+	priv->init_user_cfg = firmware;
+	priv->init_user_conf_wait_flag = TRUE;
+	wake_up_interruptible(&priv->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *    @brief BT set user defined init data and param
+ *
+ *    @param priv     BT private handle
+ *    @param cfg_file user cofig file
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_config(bt_private *priv, char *cfg_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if ((request_firmware(&cfg, cfg_file, priv->hotplug_device)) < 0) {
+		PRINTM(FATAL, "BT: request_firmware() %s failed\n", cfg_file);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (cfg)
+		ret = bt_process_init_cfg(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg(bt_private *priv, u8 *data, u32 size, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	u8 cal_data[32];
+	u8 *mac_data = NULL;
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+	u8 *pcal_data = cal_data;
+
+	memset(bt_mac, 0, sizeof(bt_mac));
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (mac != NULL) {
+		/* Convert MAC format */
+		bt_mac2u8(bt_mac, mac);
+		PRINTM(CMD, "HCI: new BT Address " MACSTR "\n",
+		       MAC2STR(bt_mac));
+		mac_data = bt_mac;
+	}
+	if (BT_STATUS_SUCCESS != bt_load_cal_data(priv, pcal_data, mac_data)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg_ext(bt_private *priv, u8 *data, u32 size)
+{
+	u8 cal_data[128];
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (BT_STATUS_SUCCESS !=
+	    bt_load_cal_data_ext(priv, cal_data, cal_data_len)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config(bt_private *priv, char *cal_file, char *mac)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size, mac);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config_ext(bt_private *priv, char *cal_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config_ext() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg_ext(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT init mac address from bt_mac parametre when insmod
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param bt_mac  mac address buf
+ *    @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_mac_address(bt_private *priv, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	memset(bt_mac, 0, sizeof(bt_mac));
+	bt_mac2u8(bt_mac, mac);
+	PRINTM(CMD, "HCI: New BT Address " MACSTR "\n", MAC2STR(bt_mac));
+	ret = bt_set_mac_address(priv, bt_mac);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(FATAL,
+		       "BT: Fail to set mac address from insmod parametre.\n");
+
+	LEAVE();
+	return ret;
+}
diff --git a/bt_sd8997/bt/bt_main.c b/bt_sd8997/bt/bt_main.c
new file mode 100644
index 0000000..dc225fc
--- /dev/null
+++ b/bt_sd8997/bt/bt_main.c
@@ -0,0 +1,3525 @@
+/** @file bt_main.c
+  *
+  * @brief This file contains the major functions in BlueTooth
+  * driver. It includes init, exit, open, close and main
+  * thread etc..
+  *
+  * Copyright (C) 2007-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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.
+  *
+  */
+/**
+  * @mainpage M-BT Linux Driver
+  *
+  * @section overview_sec Overview
+  *
+  * The M-BT is a Linux reference driver for Marvell Bluetooth chipset.
+  *
+  * @section copyright_sec Copyright
+  *
+  * Copyright (C) 2007-2016, Marvell International Ltd.
+  *
+  */
+
+#include <linux/module.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
+
+#include <linux/mmc/sdio_func.h>
+
+#include "bt_drv.h"
+#include "mbt_char.h"
+#include "bt_sdio.h"
+
+/** Version */
+#define VERSION "C4X14113"
+
+/** Driver version */
+static char mbt_driver_version[] = "SD8997-%s-" VERSION "-(" "FP" FPNUM ")"
+#ifdef DEBUG_LEVEL2
+	"-dbg"
+#endif
+	" ";
+
+/** Declare and initialize fw_version */
+static char fw_version[32] = "0.0.0.p0";
+
+#define AID_SYSTEM        1000	/* system server */
+
+#define AID_BLUETOOTH     1002	/* bluetooth subsystem */
+
+#define AID_NET_BT_STACK  3008	/* bluetooth stack */
+
+/** Define module name */
+
+#define MODULE_NAME  "bt_fm_nfc"
+
+/** Declaration of chardev class */
+static struct class *chardev_class;
+
+/** Interface specific variables */
+
+/** Default Driver mode */
+static int drv_mode = (DRV_MODE_BT);
+
+/** fw reload flag */
+int bt_fw_reload;
+/** fw serial download flag */
+int bt_fw_serial = 1;
+
+/** Firmware flag */
+static int fw = 1;
+/** default powermode */
+static int psmode = 1;
+/** Init config file (MAC address, register etc.) */
+static char *init_cfg;
+/** Calibration config file (MAC address, init powe etc.) */
+static char *cal_cfg;
+/** Calibration config file EXT */
+static char *cal_cfg_ext;
+/** Init MAC address */
+static char *bt_mac;
+static int btindrst = -1;
+
+/** Setting mbt_drvdbg value based on DEBUG level */
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define DEFAULT_DEBUG_MASK  (0xffffffff & ~DBG_EVENT)
+#else
+#define DEFAULT_DEBUG_MASK  (DBG_MSG | DBG_FATAL | DBG_ERROR)
+#endif /* DEBUG_LEVEL2 */
+u32 mbt_drvdbg = DEFAULT_DEBUG_MASK;
+#endif
+
+#ifdef CONFIG_OF
+static int dts_enable = 1;
+#endif
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+int mbt_pm_keep_power = 1;
+#endif
+
+static int btpmic = 0;
+
+/**
+ *  @brief Alloc bt device
+ *
+ *  @return    pointer to structure mbt_dev or NULL
+ */
+struct mbt_dev *
+alloc_mbt_dev(void)
+{
+	struct mbt_dev *mbt_dev;
+	ENTER();
+
+	mbt_dev = kzalloc(sizeof(struct mbt_dev), GFP_KERNEL);
+	if (!mbt_dev) {
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return mbt_dev;
+}
+
+/**
+ *  @brief Frees m_dev
+ *
+ *  @return    N/A
+ */
+void
+free_m_dev(struct m_dev *m_dev)
+{
+	ENTER();
+	kfree(m_dev->dev_pointer);
+	m_dev->dev_pointer = NULL;
+	LEAVE();
+}
+
+/**
+ *  @brief clean up m_devs
+ *
+ *  @return    N/A
+ */
+void
+clean_up_m_devs(bt_private *priv)
+{
+	struct m_dev *m_dev = NULL;
+	struct hci_dev *hdev = NULL;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+		PRINTM(MSG, "BT: Delete %s\n", m_dev->name);
+		if (m_dev->spec_type == BLUEZ_SPEC) {
+			hdev = (struct hci_dev *)m_dev->dev_pointer;
+			/** check if dev->name has been assigned */
+			if (strstr(hdev->name, "hci"))
+				hci_unregister_dev(hdev);
+			hci_free_dev(hdev);
+		}
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = NULL;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function verify the received event pkt
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+--------+
+ *  | Event  | Length |  ncmd  |      Opcode     |
+ *  +--------+--------+--------+--------+--------+
+ *  | 1-byte | 1-byte | 1-byte |      2-byte     |
+ *  +--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+check_evtpkt(bt_private *priv, struct sk_buff *skb)
+{
+	struct hci_event_hdr *hdr = (struct hci_event_hdr *)skb->data;
+	struct hci_ev_cmd_complete *ec;
+	u16 opcode, ocf;
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (!priv->bt_dev.sendcmdflag) {
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	if (hdr->evt == HCI_EV_CMD_COMPLETE) {
+		ec = (struct hci_ev_cmd_complete *)
+			(skb->data + HCI_EVENT_HDR_SIZE);
+		opcode = __le16_to_cpu(ec->opcode);
+		ocf = hci_opcode_ocf(opcode);
+		PRINTM(CMD,
+		       "BT: CMD_COMPLTE opcode=0x%x, ocf=0x%x, send_cmd_opcode=0x%x\n",
+		       opcode, ocf, priv->bt_dev.send_cmd_opcode);
+		if (opcode != priv->bt_dev.send_cmd_opcode) {
+			ret = BT_STATUS_FAILURE;
+			goto exit;
+		}
+		switch (ocf) {
+		case BT_CMD_MODULE_CFG_REQ:
+		case BT_CMD_BLE_DEEP_SLEEP:
+		case BT_CMD_CONFIG_MAC_ADDR:
+		case BT_CMD_CSU_WRITE_REG:
+		case BT_CMD_LOAD_CONFIG_DATA:
+		case BT_CMD_LOAD_CONFIG_DATA_EXT:
+		case BT_CMD_AUTO_SLEEP_MODE:
+		case BT_CMD_HOST_SLEEP_CONFIG:
+		case BT_CMD_SDIO_PULL_CFG_REQ:
+		case BT_CMD_SET_EVT_FILTER:
+		case BT_CMD_ENABLE_WRITE_SCAN:
+			// case BT_CMD_ENABLE_DEVICE_TESTMODE:
+		case BT_CMD_RESET:
+		case BT_CMD_PMIC_CONFIGURE:
+		case BT_CMD_INDEPENDENT_RESET:
+			priv->bt_dev.sendcmdflag = FALSE;
+			priv->adapter->cmd_complete = TRUE;
+			wake_up_interruptible(&priv->adapter->cmd_wait_q);
+			break;
+		case BT_CMD_GET_FW_VERSION:
+			{
+				u8 *pos = (skb->data + HCI_EVENT_HDR_SIZE +
+					   sizeof(struct hci_ev_cmd_complete) +
+					   1);
+				snprintf(fw_version, sizeof(fw_version),
+					 "%u.%u.%u.p%u", pos[2], pos[1], pos[0],
+					 pos[3]);
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+				break;
+			}
+		case BT_CMD_HISTOGRAM:
+			{
+				u8 *status =
+					skb->data + HCI_EVENT_HDR_SIZE +
+					sizeof(struct hci_ev_cmd_complete);
+				u8 *pos =
+					(skb->data + HCI_EVENT_HDR_SIZE +
+					 sizeof(struct hci_ev_cmd_complete) +
+					 1);
+				if (*status == 0) {
+					priv->hist_data_len =
+						hdr->plen -
+						sizeof(struct
+						       hci_ev_cmd_complete) - 1;
+					if (priv->hist_data_len >
+					    sizeof(priv->hist_data))
+						priv->hist_data_len =
+							sizeof(priv->hist_data);
+					memcpy(priv->hist_data, pos,
+					       priv->hist_data_len);
+					PRINTM(CMD, "histogram len=%d\n",
+					       priv->hist_data_len);
+				}
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+				break;
+			}
+		case BT_CMD_HOST_SLEEP_ENABLE:
+			priv->bt_dev.sendcmdflag = FALSE;
+			break;
+		default:
+			/** Ignore command not defined but send by driver */
+			if (opcode == priv->bt_dev.send_cmd_opcode) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			} else {
+				ret = BT_STATUS_FAILURE;
+			}
+			break;
+		}
+	}
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function process the received event
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+-----+
+ *  |   EC   | Length |           Data        |
+ *  +--------+--------+--------+--------+-----+
+ *  | 1-byte | 1-byte |          n-byte       |
+ *  +--------+--------+--------+--------+-----+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_event(bt_private *priv, struct sk_buff *skb)
+{
+	int ret = BT_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	BT_EVENT *pevent;
+
+	ENTER();
+	pevent = (BT_EVENT *)skb->data;
+	if (pevent->EC != 0xff) {
+		PRINTM(CMD, "BT: Not Marvell Event=0x%x\n", pevent->EC);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	switch (pevent->data[0]) {
+	case BT_CMD_HISTOGRAM:
+		break;
+	case BT_CMD_AUTO_SLEEP_MODE:
+		if (pevent->data[2] == BT_STATUS_SUCCESS) {
+			if (pevent->data[1] == BT_PS_ENABLE)
+				priv->adapter->psmode = 1;
+			else
+				priv->adapter->psmode = 0;
+			PRINTM(CMD, "BT: PS Mode %s:%s\n", m_dev->name,
+			       (priv->adapter->psmode) ? "Enable" : "Disable");
+
+		} else {
+			PRINTM(CMD, "BT: PS Mode Command Fail %s\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_CONFIG:
+		if (pevent->data[3] == BT_STATUS_SUCCESS) {
+			PRINTM(CMD, "BT: %s: gpio=0x%x, gap=0x%x\n",
+			       m_dev->name, pevent->data[1], pevent->data[2]);
+		} else {
+			PRINTM(CMD, "BT: %s: HSCFG Command Fail\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_ENABLE:
+		if (pevent->data[1] == BT_STATUS_SUCCESS) {
+			priv->adapter->hs_state = HS_ACTIVATED;
+			if (priv->adapter->suspend_fail == FALSE) {
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+				bt_is_suspended(priv);
+#endif
+#endif
+#endif
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			}
+			if (priv->adapter->psmode)
+				priv->adapter->ps_state = PS_SLEEP;
+			PRINTM(CMD, "BT: EVENT %s: HS ACTIVATED!\n",
+			       m_dev->name);
+
+		} else {
+			PRINTM(CMD, "BT: %s: HS Enable Fail\n", m_dev->name);
+		}
+		break;
+	case BT_CMD_MODULE_CFG_REQ:
+		if ((priv->bt_dev.sendcmdflag == TRUE) &&
+		    ((pevent->data[1] == MODULE_BRINGUP_REQ)
+		     || (pevent->data[1] == MODULE_SHUTDOWN_REQ))) {
+			if (pevent->data[1] == MODULE_BRINGUP_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2] && (pevent->data[2] !=
+							    MODULE_CFG_RESP_ALREADY_UP))
+				       ? "Bring up Fail" : "Bring up success");
+				priv->bt_dev.devType = pevent->data[3];
+				PRINTM(CMD, "devType:%s\n",
+				       (pevent->data[3] ==
+					DEV_TYPE_AMP) ? "AMP controller" :
+				       "BR/EDR controller");
+				priv->bt_dev.devFeature = pevent->data[4];
+				PRINTM(CMD, "devFeature:  %s,    %s,    %s"
+				       "\n",
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BT) ?
+					"BT Feature" : "No BT Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BTAMP) ?
+					"BTAMP Feature" : "No BTAMP Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BLE) ?
+					"BLE Feature" : "No BLE Feature")
+					);
+			}
+			if (pevent->data[1] == MODULE_SHUTDOWN_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2]) ? "Shut down Fail"
+				       : "Shut down success");
+
+			}
+			if (pevent->data[2]) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			}
+		} else {
+			PRINTM(CMD, "BT_CMD_MODULE_CFG_REQ resp for APP\n");
+			ret = BT_STATUS_FAILURE;
+		}
+		break;
+	case BT_EVENT_POWER_STATE:
+		if (pevent->data[1] == BT_PS_SLEEP)
+			priv->adapter->ps_state = PS_SLEEP;
+		PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+		       (priv->adapter->ps_state) ? "PS_SLEEP" : "PS_AWAKE");
+
+		break;
+	case BT_CMD_SDIO_PULL_CFG_REQ:
+		if (pevent->data[pevent->length - 1] == BT_STATUS_SUCCESS)
+			PRINTM(CMD, "BT: %s: SDIO pull configuration success\n",
+			       m_dev->name);
+
+		else {
+			PRINTM(CMD, "BT: %s: SDIO pull configuration fail\n",
+			       m_dev->name);
+
+		}
+		break;
+	default:
+		PRINTM(CMD, "BT: Unknown Event=%d %s\n", pevent->data[0],
+		       m_dev->name);
+		ret = BT_STATUS_FAILURE;
+		break;
+	}
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function save the dump info to file
+ *
+ *
+ *  @param dir_name     directory name
+ *  @param file_name    file_name
+ *  @return    0 --success otherwise fail
+ */
+int
+bt_save_dump_info_to_file(char *dir_name, char *file_name, u8 *buf, u32 buf_len)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct file *pfile = NULL;
+	u8 name[64];
+	mm_segment_t fs;
+	loff_t pos;
+
+	ENTER();
+
+	if (!dir_name || !file_name || !buf) {
+		PRINTM(ERROR, "Can't save dump info to file\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(name, 0, sizeof(name));
+	sprintf((char *)name, "%s/%s", dir_name, file_name);
+	pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MSG,
+		       "Create file %s error, try to save dump file in /var\n",
+		       name);
+		memset(name, 0, sizeof(name));
+		sprintf((char *)name, "%s/%s", "/var", file_name);
+		pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(ERROR, "Create Dump file for %s error\n", name);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MSG, "Dump data %s saved in %s\n", file_name, name);
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	pos = 0;
+	vfs_write(pfile, (const char __user *)buf, buf_len, &pos);
+	filp_close(pfile, NULL);
+	set_fs(fs);
+
+	PRINTM(MSG, "Dump data %s saved in %s successfully\n", file_name, name);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#define DEBUG_HOST_READY		0xEE
+#define DEBUG_FW_DONE			0xFF
+#define DUMP_MAX_POLL_TRIES			200
+
+#define DEBUG_DUMP_CTRL_REG               0xF0
+#define DEBUG_DUMP_START_REG              0xF1
+#define DEBUG_DUMP_END_REG                0xF8
+
+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
+#define MAX_FULL_NAME_LEN               32
+
+typedef struct {
+	u8 mem_name[MAX_NAME_LEN];
+	u8 *mem_Ptr;
+	struct file *pfile_mem;
+	u8 done_flag;
+} memory_type_mapping;
+
+memory_type_mapping bt_mem_type_mapping_tbl[] = {
+	{"ITCM", NULL, NULL, 0xF0},
+	{"DTCM", NULL, NULL, 0xF1},
+	{"SQRAM", NULL, NULL, 0xF2},
+	{"APU", NULL, NULL, 0xF3},
+	{"CIU", NULL, NULL, 0xF4},
+	{"ICU", NULL, NULL, 0xF5},
+	{"MAC", NULL, NULL, 0xF6},
+	{"EXT7", NULL, NULL, 0xF7},
+	{"EXT8", NULL, NULL, 0xF8},
+	{"EXT9", NULL, NULL, 0xF9},
+	{"EXT10", NULL, NULL, 0xFA},
+	{"EXT11", NULL, NULL, 0xFB},
+	{"EXT12", NULL, NULL, 0xFC},
+	{"EXT13", NULL, NULL, 0xFD},
+	{"EXTLAST", NULL, NULL, 0xFE},
+};
+
+typedef enum {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+} rdwr_status;
+
+/**
+ *  @brief This function read/write firmware via cmd52
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+rdwr_status
+bt_cmd52_rdwr_firmware(bt_private *priv, u8 doneflag)
+{
+	int ret = 0;
+	int tries = 0;
+	u8 ctrl_data = 0;
+	u8 dbg_dump_ctrl_reg = 0;
+
+	dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG;
+
+	sdio_writeb(((struct sdio_mmc_card *)priv->bt_dev.card)->func,
+		    DEBUG_HOST_READY, dbg_dump_ctrl_reg, &ret);
+	if (ret) {
+		PRINTM(ERROR, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	for (tries = 0; tries < DUMP_MAX_POLL_TRIES; tries++) {
+		ctrl_data =
+			sdio_readb(((struct sdio_mmc_card *)priv->bt_dev.card)->
+				   func, dbg_dump_ctrl_reg, &ret);
+		if (ret) {
+			PRINTM(ERROR, "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(INFO,
+			       "The ctrl reg was changed, re-try again!\n");
+			sdio_writeb(((struct sdio_mmc_card *)priv->bt_dev.
+				     card)->func, DEBUG_HOST_READY,
+				    dbg_dump_ctrl_reg, &ret);
+			if (ret) {
+				PRINTM(ERROR, "SDIO Write ERR\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		udelay(100);
+	}
+	if (ctrl_data == DEBUG_HOST_READY) {
+		PRINTM(ERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	return RDWR_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_firmware_info_v2(bt_private *priv)
+{
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	u8 *dbg_ptr = NULL;
+	u8 dump_num = 0;
+	u8 idx = 0;
+	u8 doneflag = 0;
+	rdwr_status stat;
+	u8 i = 0;
+	u8 read_reg = 0;
+	u32 memory_size = 0;
+	u8 path_name[64], file_name[32];
+	u8 *end_ptr = NULL;
+	u8 dbg_dump_start_reg = 0;
+	u8 dbg_dump_end_reg = 0;
+
+	if (!priv) {
+		PRINTM(ERROR, "Could not dump firmwware info\n");
+		return;
+	}
+
+	memset(path_name, 0, sizeof(path_name));
+	strcpy((char *)path_name, "/data");
+	PRINTM(MSG, "Create DUMP directory success:dir_name=%s\n", path_name);
+
+	dbg_dump_start_reg = DEBUG_DUMP_START_REG;
+	dbg_dump_end_reg = DEBUG_DUMP_END_REG;
+
+	sbi_wakeup_firmware(priv);
+	sdio_claim_host(((struct sdio_mmc_card *)priv->bt_dev.card)->func);
+	/* start dump fw memory */
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT START ====\n");
+	/* read the number of the memories which will dump */
+	if (RDWR_STATUS_FAILURE == bt_cmd52_rdwr_firmware(priv, doneflag))
+		goto done;
+	reg = dbg_dump_start_reg;
+	dump_num =
+		sdio_readb(((struct sdio_mmc_card *)priv->bt_dev.card)->func,
+			   reg, &ret);
+	if (ret) {
+		PRINTM(MSG, "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 ==
+		    bt_cmd52_rdwr_firmware(priv, doneflag))
+			goto done;
+		memory_size = 0;
+		reg = dbg_dump_start_reg;
+		for (i = 0; i < 4; i++) {
+			read_reg =
+				sdio_readb(((struct sdio_mmc_card *)priv->
+					    bt_dev.card)->func, reg, &ret);
+			if (ret) {
+				PRINTM(MSG, "SDIO READ ERR\n");
+				goto done;
+			}
+			memory_size |= (read_reg << i * 8);
+			reg++;
+		}
+		if (memory_size == 0) {
+			PRINTM(MSG, "Firmware Dump Finished!\n");
+			break;
+		} else {
+			PRINTM(MSG, "%s_SIZE=0x%x\n",
+			       bt_mem_type_mapping_tbl[idx].mem_name,
+			       memory_size);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr =
+				vmalloc(memory_size + 1);
+			if ((ret != BT_STATUS_SUCCESS) ||
+			    !bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+				PRINTM(ERROR,
+				       "Error: vmalloc %s buffer failed!!!\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name);
+				goto done;
+			}
+			dbg_ptr = bt_mem_type_mapping_tbl[idx].mem_Ptr;
+			end_ptr = dbg_ptr + memory_size;
+		}
+		doneflag = bt_mem_type_mapping_tbl[idx].done_flag;
+		PRINTM(MSG, "Start %s output, please wait...\n",
+		       bt_mem_type_mapping_tbl[idx].mem_name);
+		do {
+			stat = bt_cmd52_rdwr_firmware(priv, 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++) {
+				*dbg_ptr =
+					sdio_readb(((struct sdio_mmc_card *)
+						    priv->bt_dev.card)->func,
+						   reg, &ret);
+				if (ret) {
+					PRINTM(MSG, "SDIO READ ERR\n");
+					goto done;
+				}
+				if (dbg_ptr < end_ptr)
+					dbg_ptr++;
+				else
+					PRINTM(MSG,
+					       "pre-allocced buf is not enough\n");
+			}
+			if (RDWR_STATUS_DONE == stat) {
+				PRINTM(MSG, "%s done:"
+				       "size = 0x%x\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name,
+				       (unsigned int)(dbg_ptr -
+						      bt_mem_type_mapping_tbl
+						      [idx].mem_Ptr));
+				memset(file_name, 0, sizeof(file_name));
+				sprintf((char *)file_name, "%s%s", "file_bt_",
+					bt_mem_type_mapping_tbl[idx].mem_name);
+				if (BT_STATUS_SUCCESS !=
+				    bt_save_dump_info_to_file((char *)path_name,
+							      (char *)file_name,
+							      bt_mem_type_mapping_tbl
+							      [idx].mem_Ptr,
+							      memory_size))
+					PRINTM(MSG,
+					       "Can't save dump file %s in %s\n",
+					       file_name, path_name);
+				vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+				bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+				break;
+			}
+		} while (1);
+	}
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT END ====\n");
+	/* end dump fw memory */
+done:
+	sdio_release_host(((struct sdio_mmc_card *)priv->bt_dev.card)->func);
+	for (idx = 0; idx < dump_num; idx++) {
+		if (bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+			vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+		}
+	}
+	PRINTM(MSG, "==== DEBUG MODE END ====\n");
+	return;
+}
+
+/**
+ *  @brief This function shows debug info for timeout of command sending.
+ *
+ *  @param adapter  A pointer to bt_private
+ *  @param cmd      Timeout command id
+ *
+ *  @return         N/A
+ */
+static void
+bt_cmd_timeout_func(bt_private *priv, u16 cmd)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+
+	adapter->num_cmd_timeout++;
+
+	PRINTM(ERROR, "Version = %s\n", adapter->drv_ver);
+	PRINTM(ERROR, "Timeout Command id = 0x%x\n", cmd);
+	PRINTM(ERROR, "Number of command timeout = %d\n",
+	       adapter->num_cmd_timeout);
+	PRINTM(ERROR, "Interrupt counter = %d\n", adapter->IntCounter);
+	PRINTM(ERROR, "Power Save mode = %d\n", adapter->psmode);
+	PRINTM(ERROR, "Power Save state = %d\n", adapter->ps_state);
+	PRINTM(ERROR, "Host Sleep state = %d\n", adapter->hs_state);
+	PRINTM(ERROR, "hs skip count = %d\n", adapter->hs_skip);
+	PRINTM(ERROR, "suspend_fail flag = %d\n", adapter->suspend_fail);
+	PRINTM(ERROR, "suspended flag = %d\n", adapter->is_suspended);
+	PRINTM(ERROR, "Number of wakeup tries = %d\n", adapter->WakeupTries);
+	PRINTM(ERROR, "Host Cmd complet state = %d\n", adapter->cmd_complete);
+	PRINTM(ERROR, "Last irq recv = %d\n", adapter->irq_recv);
+	PRINTM(ERROR, "Last irq processed = %d\n", adapter->irq_done);
+	PRINTM(ERROR, "tx pending = %d\n", adapter->skb_pending);
+	PRINTM(ERROR, "sdio int status = %d\n", adapter->sd_ireg);
+	bt_dump_sdio_regs(priv);
+	LEAVE();
+}
+
+/**
+ *  @brief This function send reset cmd to firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return	       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_reset_command(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((RESET_OGF << 10) | BT_CMD_RESET);
+	pcmd->length = 0x00;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, 3);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue Reset Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Reset timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_RESET);
+	} else {
+		PRINTM(CMD, "BT: Reset Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends module cfg cmd to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param subcmd  sub command
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_module_cfg_cmd(bt_private *priv, int subcmd)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_MODULE_CFG_REQ);
+	pcmd->length = 1;
+	pcmd->data[0] = subcmd;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue module cfg Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	/*
+	   On some Android platforms certain delay is needed for HCI daemon to
+	   remove this module and close itself gracefully. Otherwise it hangs.
+	   This 10ms delay is a workaround for such platforms as the root cause
+	   has not been found yet. */
+	mdelay(10);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: module_cfg_cmd(%#x): timeout sendcmdflag=%d\n",
+		       subcmd, priv->bt_dev.sendcmdflag);
+		bt_cmd_timeout_func(priv, BT_CMD_MODULE_CFG_REQ);
+	} else {
+		PRINTM(CMD, "BT: module cfg Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function to get histogram
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_get_histogram(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HISTOGRAM);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Histogram cmd(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	priv->hist_data_len = 0;
+	memset(priv->hist_data, 0, sizeof(priv->hist_data));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: histogram timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HISTOGRAM);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables power save mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_ps(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_AUTO_SLEEP_MODE);
+	if (priv->bt_dev.psmode)
+		pcmd->data[0] = BT_PS_ENABLE;
+	else
+		pcmd->data[0] = BT_PS_DISABLE;
+	if (priv->bt_dev.idle_timeout) {
+		pcmd->length = 3;
+		pcmd->data[1] = (u8)(priv->bt_dev.idle_timeout & 0x00ff);
+		pcmd->data[2] = (priv->bt_dev.idle_timeout & 0xff00) >> 8;
+	} else {
+		pcmd->length = 1;
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PSMODE Command(0x%x):%d\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: psmode timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_AUTO_SLEEP_MODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends hscfg command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_hscfg_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_CONFIG);
+	pcmd->length = 2;
+	pcmd->data[0] = (priv->bt_dev.gpio_gap & 0xff00) >> 8;
+	pcmd->data[1] = (u8)(priv->bt_dev.gpio_gap & 0x00ff);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue HSCFG Command(0x%x),gpio=0x%x,gap=0x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0], pcmd->data[1]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: HSCFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_CONFIG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends sdio pull ctrl command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_sdio_pull_ctrl_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_SDIO_PULL_CFG_REQ);
+	pcmd->length = 4;
+	pcmd->data[0] = (priv->bt_dev.sdio_pull_cfg & 0x000000ff);
+	pcmd->data[1] = (priv->bt_dev.sdio_pull_cfg & 0x0000ff00) >> 8;
+	pcmd->data[2] = (priv->bt_dev.sdio_pull_cfg & 0x00ff0000) >> 16;
+	pcmd->data[3] = (priv->bt_dev.sdio_pull_cfg & 0xff000000) >> 24;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD,
+	       "Queue SDIO PULL CFG Command(0x%x), PullUp=0x%x%x,PullDown=0x%x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[1], pcmd->data[0],
+	       pcmd->data[3], pcmd->data[2]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: SDIO PULL CFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SDIO_PULL_CFG_REQ);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends command to configure PMIC
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_pmic_configure(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_PMIC_CONFIGURE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PMIC Configure Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: PMIC Configure timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_PMIC_CONFIGURE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables host sleep
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_hs(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	priv->adapter->suspend_fail = FALSE;
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_ENABLE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	PRINTM(CMD, "Queue hs enable Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->hs_state,
+	     WAIT_UNTIL_HS_STATE_CHANGED)) {
+		PRINTM(MSG, "BT: Enable host sleep timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_ENABLE);
+	}
+	OS_INT_DISABLE;
+	if ((priv->adapter->hs_state == HS_ACTIVATED) ||
+	    (priv->adapter->is_suspended == TRUE)) {
+		OS_INT_RESTORE;
+		PRINTM(MSG, "BT: suspend success! skip=%d\n",
+		       priv->adapter->hs_skip);
+	} else {
+		priv->adapter->suspend_fail = TRUE;
+		OS_INT_RESTORE;
+		priv->adapter->hs_skip++;
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG,
+		       "BT: suspend skipped! "
+		       "state=%d skip=%d ps_state= %d WakeupTries=%d\n",
+		       priv->adapter->hs_state, priv->adapter->hs_skip,
+		       priv->adapter->ps_state, priv->adapter->WakeupTries);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Set Evt Filter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_evt_filter(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_SET_EVT_FILTER);
+	pcmd->length = 0x03;
+	pcmd->data[0] = 0x02;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Set Evt Filter Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set Evt Filter timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SET_EVT_FILTER);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Write Scan - Page and Inquiry
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_write_scan(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_ENABLE_WRITE_SCAN);
+	pcmd->length = 0x01;
+	pcmd->data[0] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Enable Write Scan Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Write Scan timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_WRITE_SCAN);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Device under test mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_device_under_testmode(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((0x06 << 10) | BT_CMD_ENABLE_DEVICE_TESTMODE);
+	pcmd->length = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue enable device under testmode Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Device under TEST mode timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_DEVICE_TESTMODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables test mode and send cmd
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_test_mode(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	/** Set Evt Filter Command */
+	ret = bt_set_evt_filter(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Set Evt filter fail\n");
+		goto exit;
+	}
+
+	/** Enable Write Scan Command */
+	ret = bt_enable_write_scan(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Enable Write Scan fail\n");
+		goto exit;
+	}
+
+	/** Enable Device under test mode */
+	ret = bt_enable_device_under_testmode(priv);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(ERROR,
+		       "BT test_mode: Enable device under testmode fail\n");
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+#define DISABLE_RESET  0x0
+#define ENABLE_OUTBAND_RESET 0x1
+#define ENABLE_INBAND_RESET  0x02
+#define DEFAULT_GPIO 0xff
+/**
+ *  @brief This function set GPIO pin
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_independent_reset(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	u8 mode, gpio;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_INDEPENDENT_RESET);
+	mode = btindrst & 0xff;
+	gpio = (btindrst & 0xff00) >> 8;
+	if (mode == ENABLE_OUTBAND_RESET) {
+		pcmd->data[0] = ENABLE_OUTBAND_RESET;
+		if (!gpio)
+			pcmd->data[1] = DEFAULT_GPIO;
+		else
+			pcmd->data[1] = gpio;
+	} else if (mode == ENABLE_INBAND_RESET) {
+		pcmd->data[0] = ENABLE_INBAND_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else if (mode == DISABLE_RESET) {
+		pcmd->data[0] = DISABLE_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else {
+		PRINTM(WARN, "Unsupport mode\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	PRINTM(CMD, "BT: independant reset mode=%d gpio=%d\n", mode, gpio);
+	pcmd->length = 2;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Independent reset : timeout!\n");
+		bt_cmd_timeout_func(priv, BT_CMD_INDEPENDENT_RESET);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets ble deepsleep mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mode    TRUE/FALSE
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_ble_deepsleep(bt_private *priv, int mode)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_BLE_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_BLE_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_BLE_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_BLE_DEEP_SLEEP);
+	pcmd->length = 1;
+	pcmd->deepsleep = mode;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_BLE_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set BLE deepsleep = %d (0x%x)\n", mode,
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set BLE deepsleep timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_BLE_DEEP_SLEEP);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets FW version
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_get_fw_version(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_GET_FW_VERSION);
+	pcmd->length = 0x01;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, 4);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Get FW version: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_GET_FW_VERSION);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets mac address
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_mac_address(bt_private *priv, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	int i = 0;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CONFIG_MAC_ADDR);
+	pcmd->length = 8;
+	pcmd->cmd_type = MRVL_VENDOR_PKT;
+	pcmd->cmd_len = 6;
+	for (i = 0; i < 6; i++)
+		pcmd->data[i] = mac[5 - i];
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_HCI_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set mac addr " MACSTR " (0x%x)\n", MAC2STR(mac),
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set mac addr: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CONFIG_MAC_ADDR);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	int i = 0;
+	/* u8 config_data[28] = {0x37 0x01 0x1c 0x00 0xFF 0xFF 0xFF 0xFF 0x01
+	   0x7f 0x04 0x02 0x00 0x00 0xBA 0xCE 0xC0 0xC6 0x2D 0x00 0x00 0x00
+	   0x00 0x00 0x00 0x00 0xF0}; */
+
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA);
+	pcmd->length = 0x20;
+	pcmd->data[0] = 0x00;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x00;
+	pcmd->data[3] = 0x1C;
+	/* swip cal-data byte */
+	for (i = 4; i < 32; i++)
+		pcmd->data[i] = *(config_data + ((i / 4) * 8 - 1 - i));
+	if (mac != NULL) {
+		pcmd->data[2] = 0x01;	/* skip checksum */
+		for (i = 24; i < 30; i++)
+			pcmd->data[i] = mac[29 - i];
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate data: ", pcmd->data, 32);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate EXT data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA_EXT);
+	pcmd->length = cfg_data_len;
+
+	memcpy(pcmd->data, config_data, cfg_data_len);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate ext data", pcmd->data, pcmd->length);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate ext data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA_EXT);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function writes value to CSU registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param type    reg type
+ *  @param offset  register address
+ *  @param value   register value to write
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CSU_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CSU_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CSU_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CSU_WRITE_REG);
+	pcmd->length = 7;
+	pcmd->type = type;
+	pcmd->offset[0] = (offset & 0x000000ff);
+	pcmd->offset[1] = (offset & 0x0000ff00) >> 8;
+	pcmd->offset[2] = (offset & 0x00ff0000) >> 16;
+	pcmd->offset[3] = (offset & 0xff000000) >> 24;
+	pcmd->value[0] = (value & 0x00ff);
+	pcmd->value[1] = (value & 0xff00) >> 8;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_CSU_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set CSU reg type=%d reg=0x%x value=0x%x\n",
+	       type, offset, value);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Set CSU reg timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CSU_WRITE_REG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function used to restore tx_queue
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        N/A
+ */
+void
+bt_restore_tx_queue(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	while (!skb_queue_empty(&priv->adapter->pending_queue)) {
+		skb = skb_dequeue(&priv->adapter->pending_queue);
+		if (skb)
+			skb_queue_tail(&priv->adapter->tx_queue, skb);
+	}
+	wake_up_interruptible(&priv->MainThread.waitQ);
+}
+
+/**
+ *  @brief This function used to send command to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_prepare_command(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (priv->bt_dev.hscfgcmd) {
+		priv->bt_dev.hscfgcmd = 0;
+		ret = bt_send_hscfg_cmd(priv);
+	}
+	if (priv->bt_dev.pscmd) {
+		priv->bt_dev.pscmd = 0;
+		ret = bt_enable_ps(priv);
+	}
+	if (priv->bt_dev.sdio_pull_ctrl) {
+		priv->bt_dev.sdio_pull_ctrl = 0;
+		ret = bt_send_sdio_pull_ctrl_cmd(priv);
+	}
+	if (priv->bt_dev.hscmd) {
+		priv->bt_dev.hscmd = 0;
+		if (priv->bt_dev.hsmode)
+			ret = bt_enable_hs(priv);
+		else {
+			ret = sbi_wakeup_firmware(priv);
+			priv->adapter->hs_state = HS_DEACTIVATED;
+		}
+	}
+	if (priv->bt_dev.test_mode) {
+		priv->bt_dev.test_mode = 0;
+		ret = bt_enable_test_mode(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function processes a single packet
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to skb which includes TX packet
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+send_single_packet(bt_private *priv, struct sk_buff *skb)
+{
+	int ret;
+	int has_realloc = 0;
+	ENTER();
+	if (!skb || !skb->data) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	if (!skb->len || ((skb->len + BT_HEADER_LEN) > BT_UPLD_SIZE)) {
+		PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
+		       BT_UPLD_SIZE);
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	if (skb_headroom(skb) < BT_HEADER_LEN) {
+		skb = skb_realloc_headroom(skb, BT_HEADER_LEN);
+		if (!skb) {
+			PRINTM(ERROR, "TX error: realloc_headroom failed %d\n",
+			       BT_HEADER_LEN);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		}
+		has_realloc = 1;
+	}
+	/* This is SDIO specific header length: byte[3][2][1], * type: byte[0]
+	   (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
+	skb_push(skb, BT_HEADER_LEN);
+	skb->data[0] = (skb->len & 0x0000ff);
+	skb->data[1] = (skb->len & 0x00ff00) >> 8;
+	skb->data[2] = (skb->len & 0xff0000) >> 16;
+	skb->data[3] = bt_cb(skb)->pkt_type;
+	if (bt_cb(skb)->pkt_type == MRVL_VENDOR_PKT)
+		PRINTM(CMD, "DNLD_CMD: ocf_ogf=0x%x len=%d\n",
+		       __le16_to_cpu(*((u16 *) & skb->data[4])), skb->len);
+	ret = sbi_host_to_card(priv, skb->data, skb->len);
+	if (has_realloc)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+static void
+update_stat_byte_tx(bt_private *priv, struct sk_buff *skb)
+{
+	((struct hci_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer)->stat.
+		byte_tx += skb->len;
+}
+
+static void
+update_stat_err_tx(bt_private *priv, struct sk_buff *skb)
+{
+	((struct hci_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer)->stat.
+		err_tx++;
+}
+
+#ifdef CONFIG_OF
+/**
+ *  @brief This function read the initial parameter from device tress
+ *
+ *
+ *  @return         N/A
+ */
+static void
+bt_init_from_dev_tree(void)
+{
+	struct device_node *dt_node = NULL;
+	struct property *prop;
+	u32 data;
+	const char *string_data;
+
+	ENTER();
+
+	if (!dts_enable) {
+		PRINTM(CMD, "DTS is disabled!");
+		return;
+	}
+
+	dt_node = of_find_node_by_name(NULL, "sd8xxx-bt");
+	if (!dt_node) {
+		LEAVE();
+		return;
+	}
+	for_each_property_of_node(dt_node, prop) {
+#ifdef DEBUG_LEVEL1
+		if (!strncmp(prop->name, "mbt_drvdbg", strlen("mbt_drvdbg"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(CMD, "mbt_drvdbg=0x%x\n", data);
+				mbt_drvdbg = data;
+			}
+		}
+#endif
+		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(CMD, "init_cfg=%s\n", init_cfg);
+			}
+		} else if (!strncmp
+			   (prop->name, "cal_cfg_ext", strlen("cal_cfg_ext"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg_ext = (char *)string_data;
+				PRINTM(CMD, "cal_cfg_ext=%s\n", cal_cfg_ext);
+			}
+		} else if (!strncmp(prop->name, "cal_cfg", strlen("cal_cfg"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg = (char *)string_data;
+				PRINTM(CMD, "cal_cfg=%s\n", cal_cfg);
+			}
+		} else if (!strncmp(prop->name, "bt_mac", strlen("bt_mac"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				bt_mac = (char *)string_data;
+				PRINTM(CMD, "bt_mac=%s\n", bt_mac);
+			}
+		} else if (!strncmp(prop->name, "btindrst", strlen("btindrst"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btindrst = data;
+				PRINTM(CMD, "btindrst=%d\n", btindrst);
+			}
+		} else if (!strncmp(prop->name, "btpmic", strlen("btpmic"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btpmic = data;
+				PRINTM(CMD, "btpmic=%d\n", btpmic);
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function initializes the adapter structure
+ *  and set default value to the member of adapter.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+static void
+bt_init_adapter(bt_private *priv)
+{
+	ENTER();
+#ifdef CONFIG_OF
+	bt_init_from_dev_tree();
+#endif
+	skb_queue_head_init(&priv->adapter->tx_queue);
+	skb_queue_head_init(&priv->adapter->pending_queue);
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+	init_waitqueue_head(&priv->adapter->cmd_wait_q);
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (fw == 0) {
+		sd_enable_host_int(priv);
+		goto done;
+	}
+	sd_disable_host_int(priv);
+	if (sbi_download_fw(priv)) {
+		PRINTM(ERROR, " FW failed to be download!\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#define FW_POLL_TRIES 100
+#define FW_RESET_REG  0x0EE
+#define FW_RESET_VAL  0x99
+
+/**
+ *  @brief This function reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   FW reload mode
+ *
+ *  @return       0--success, otherwise failure
+ */
+static int
+bt_reload_fw(bt_private *priv, int mode)
+{
+	int ret = 0, tries = 0;
+	u8 value = 1;
+	u32 reset_reg = FW_RESET_REG;
+	u8 reset_val = FW_RESET_VAL;
+
+	ENTER();
+	if ((mode != FW_RELOAD_SDIO_INBAND_RESET) &&
+	    (mode != FW_RELOAD_NO_EMULATION)) {
+		PRINTM(ERROR, "Invalid fw reload mode=%d\n", mode);
+		return -EFAULT;
+	}
+
+    /** flush pending tx_queue */
+	skb_queue_purge(&priv->adapter->tx_queue);
+	if (mode == FW_RELOAD_SDIO_INBAND_RESET) {
+		sd_disable_host_int(priv);
+	    /** Wake up firmware firstly */
+		sbi_wakeup_firmware(priv);
+
+	/** wait SOC fully wake up */
+		for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_write_reg(priv, reset_reg, 0xba);
+			if (!ret) {
+				ret = sd_read_reg(priv, reset_reg, &value);
+				if (!ret && (value == 0xba)) {
+					PRINTM(MSG, "Fw wake up\n");
+					break;
+				}
+			}
+			udelay(1000);
+		}
+
+		ret = sd_write_reg(priv, reset_reg, reset_val);
+		if (ret) {
+			PRINTM(ERROR, "Failed to write register.\n");
+			goto done;
+		}
+
+	    /** Poll register around 1 ms */
+		for (; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_read_reg(priv, reset_reg, &value);
+			if (ret) {
+				PRINTM(ERROR, "Failed to read register.\n");
+				goto done;
+			}
+			if (value == 0)
+			    /** FW is ready */
+				break;
+			udelay(1000);
+		}
+		if (value) {
+			PRINTM(ERROR,
+			       "Failed to poll FW reset register %X=0x%x\n",
+			       reset_reg, value);
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	sd_enable_host_int(priv);
+	/** reload FW */
+	ret = bt_init_fw(priv);
+	if (ret) {
+		PRINTM(ERROR, "Re download firmware failed.\n");
+		ret = -EFAULT;
+	}
+	LEAVE();
+	return ret;
+done:
+	sd_enable_host_int(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function request to reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   fw reload mode.
+ *
+ *  @return         N/A
+ */
+void
+bt_request_fw_reload(bt_private *priv, int mode)
+{
+	ENTER();
+	if (mode == FW_RELOAD_WITH_EMULATION) {
+		bt_fw_reload = FW_RELOAD_WITH_EMULATION;
+		PRINTM(MSG, "BT: FW reload with re-emulation...\n");
+		LEAVE();
+		return;
+	}
+	/** Reload FW */
+	priv->fw_reload = TRUE;
+	if (bt_reload_fw(priv, mode)) {
+		PRINTM(ERROR, "FW reload fail\n");
+		goto done;
+	}
+	priv->fw_reload = FALSE;
+	/** Other operation here? */
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function frees the structure of adapter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+void
+bt_free_adapter(bt_private *priv)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	kfree(adapter->tx_buffer);
+	kfree(adapter->hw_regs_buf);
+	/* Free the adapter object itself */
+	kfree(adapter);
+	priv->adapter = NULL;
+
+	LEAVE();
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+/**
+ *  @brief This function handles the BT ioctl
+ *
+ *  @param hdev     A pointer to hci_dev structure
+ *  @cmd            ioctl cmd
+ *  @arg            argument
+ *  @return    -ENOIOCTLCMD
+ */
+static int
+bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
+{
+	ENTER();
+	LEAVE();
+	return -ENOIOCTLCMD;
+}
+#endif
+
+/**
+ *  @brief This function handles the wrapper_dev ioctl
+ *
+ *  @param hev     A pointer to wrapper_dev structure
+ *  @cmd            ioctl cmd
+ *  @arg            argument
+ *  @return    -ENOIOCTLCMD
+ */
+static int
+mdev_ioctl(struct m_dev *m_dev, unsigned int cmd, void *arg)
+{
+	bt_private *priv = NULL;
+	int ret = 0;
+#ifdef BLE_WAKEUP
+	u16 len;
+#endif
+
+	ENTER();
+
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Ioctl for unknown device (m_dev=NULL)\n");
+		ret = -ENODEV;
+		goto done;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "HCI_RUNNING not set, flag=0x%lx\n",
+		       m_dev->flags);
+		ret = -EBUSY;
+		goto done;
+	}
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+#ifdef BLE_WAKEUP
+	case MBTCHAR_IOCTL_BLE_WAKEUP_PARAM:
+		PRINTM(MSG, "BT: Set ble wakeup parameters\n");
+		if (copy_from_user(&len, arg, sizeof(u16))) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Fail to copy ble wakeup params length\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		/** Convert little endian length */
+		len = __le16_to_cpu(len);
+		if (len < 2) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Invalid ble wakeup params len %d\n",
+			       len);
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((len + sizeof(u16)) > priv->ble_wakeup_buf_size) {
+			if (priv->ble_wakeup_buf) {
+				kfree(priv->ble_wakeup_buf);
+				priv->ble_wakeup_buf = NULL;
+				priv->ble_wakeup_buf_size = 0;
+			}
+			priv->ble_wakeup_buf =
+				kzalloc(len + sizeof(u16), GFP_KERNEL);
+			if (!priv->ble_wakeup_buf) {
+				PRINTM(ERROR, "BT_IOCTL: Fail to alloc buffer\t"
+				       "for ble wakeup parameters\n");
+				ret = -ENOMEM;
+				goto done;
+			}
+			priv->ble_wakeup_buf_size = len + sizeof(u16);
+		}
+		if (copy_from_user
+		    (priv->ble_wakeup_buf, arg, len + sizeof(u16))) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Fail to copy ble wakeup params\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		DBG_HEXDUMP(DAT_D, "BLE_WAKEUP_PARAM:", priv->ble_wakeup_buf,
+			    len + sizeof(u16));
+		break;
+#endif
+	default:
+		break;
+	}
+
+done:
+#ifdef BLE_WAKEUP
+	if (ret && priv->ble_wakeup_buf) {
+		kfree(priv->ble_wakeup_buf);
+		priv->ble_wakeup_buf = NULL;
+		priv->ble_wakeup_buf_size = 0;
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles BT destruct
+ *
+ *  @param hdev    A pointer to hci_dev structure
+ *
+ *  @return    N/A
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
+static void
+bt_destruct(struct hci_dev *hdev)
+{
+	ENTER();
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function handles wrapper device destruct
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    N/A
+ */
+static void
+mdev_destruct(struct m_dev *m_dev)
+{
+	ENTER();
+	LEAVE();
+	return;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+/**
+ *  @brief This function handles the BT transmit
+ *
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    BT_STATUS_SUCCESS or other error no.
+ */
+static int
+bt_send_frame(struct sk_buff *skb)
+#else
+/**
+ *  @brief This function handles the BT transmit
+ *
+ *  @param hdev    A pointer to hci_dev structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    BT_STATUS_SUCCESS or other error no.
+ */
+static int
+bt_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
+#endif
+{
+	bt_private *priv = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
+#else
+	skb->dev = (void *)hdev;
+#endif
+
+	ENTER();
+	PRINTM(DATA, "bt_send_frame %s: Type=%d, len=%d\n", hdev->name,
+	       bt_cb(skb)->pkt_type, skb->len);
+	DBG_HEXDUMP(CMD_D, "bt_send_frame", skb->data, skb->len);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	if (!hdev || !hci_get_drvdata(hdev)) {
+#else
+	if (!hdev || !hdev->driver_data) {
+#endif
+		PRINTM(ERROR, "Frame for unknown HCI device (hdev=NULL)\n");
+		LEAVE();
+		return -ENODEV;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	priv = (bt_private *)hci_get_drvdata(hdev);
+#else
+	priv = (bt_private *)hdev->driver_data;
+#endif
+	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+		PRINTM(ERROR, "Fail test HCI_RUNNING, flag=0x%lx\n",
+		       hdev->flags);
+		LEAVE();
+		return -EBUSY;
+	}
+	switch (bt_cb(skb)->pkt_type) {
+	case HCI_COMMAND_PKT:
+		hdev->stat.cmd_tx++;
+		break;
+	case HCI_ACLDATA_PKT:
+		hdev->stat.acl_tx++;
+		break;
+	case HCI_SCODATA_PKT:
+		hdev->stat.sco_tx++;
+		break;
+	}
+	if (priv->adapter->tx_lock == TRUE)
+		skb_queue_tail(&priv->adapter->pending_queue, skb);
+	else
+		skb_queue_tail(&priv->adapter->tx_queue, skb);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the wrapper device transmit
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    BT_STATUS_SUCCESS or other error no.
+ */
+static int
+mdev_send_frame(struct m_dev *m_dev, struct sk_buff *skb)
+{
+	bt_private *priv = NULL;
+
+	ENTER();
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Frame for unknown HCI device (m_dev=NULL)\n");
+		LEAVE();
+		return -ENODEV;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "Fail test HCI_RUNNING, flag=0x%lx\n",
+		       m_dev->flags);
+		LEAVE();
+		return -EBUSY;
+	}
+	switch (bt_cb(skb)->pkt_type) {
+	case HCI_COMMAND_PKT:
+		m_dev->stat.cmd_tx++;
+		break;
+	case HCI_ACLDATA_PKT:
+		m_dev->stat.acl_tx++;
+		break;
+	case HCI_SCODATA_PKT:
+		m_dev->stat.sco_tx++;
+		break;
+	}
+
+	if (priv->adapter->tx_lock == TRUE)
+		skb_queue_tail(&priv->adapter->pending_queue, skb);
+	else
+		skb_queue_tail(&priv->adapter->tx_queue, skb);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function flushes the transmit queue
+ *
+ *  @param hdev     A pointer to hci_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+bt_flush(struct hci_dev *hdev)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	bt_private *priv = (bt_private *)hci_get_drvdata(hdev);
+#else
+	bt_private *priv = (bt_private *)hdev->driver_data;
+#endif
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	skb_queue_purge(&priv->adapter->pending_queue);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function flushes the transmit queue
+ *
+ *  @param m_dev     A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_flush(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	skb_queue_purge(&priv->adapter->pending_queue);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function closes the bluetooth device
+ *
+ *  @param hdev    A pointer to hci_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+bt_close(struct hci_dev *hdev)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	bt_private *priv = (bt_private *)hci_get_drvdata(hdev);
+#else
+	bt_private *priv = (bt_private *)hdev->driver_data;
+#endif
+
+	ENTER();
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 3, 0)
+	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) {
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+#endif
+	skb_queue_purge(&priv->adapter->tx_queue);
+
+	module_put(THIS_MODULE);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function closes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_close(struct m_dev *m_dev)
+{
+
+	ENTER();
+	mdev_req_lock(m_dev);
+	if (!test_and_clear_bit(HCI_UP, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+
+	if (m_dev->flush)
+		m_dev->flush(m_dev);
+	/* wait up pending read and unregister char dev */
+	wake_up_interruptible(&m_dev->req_wait_q);
+	/* Drop queues */
+	skb_queue_purge(&m_dev->rx_q);
+	if (!test_and_clear_bit(HCI_RUNNING, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+	module_put(THIS_MODULE);
+	m_dev->flags = 0;
+	mdev_req_unlock(m_dev);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function opens the bluetooth device
+ *
+ *  @param hdev    A pointer to hci_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+static int
+bt_open(struct hci_dev *hdev)
+{
+	ENTER();
+	if (try_module_get(THIS_MODULE) == 0)
+		return BT_STATUS_FAILURE;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 3, 0)
+	set_bit(HCI_RUNNING, &hdev->flags);
+#endif
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function opens the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+static int
+mdev_open(struct m_dev *m_dev)
+{
+	ENTER();
+
+	if (try_module_get(THIS_MODULE) == 0)
+		return BT_STATUS_FAILURE;
+
+	set_bit(HCI_RUNNING, &m_dev->flags);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function queries the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param arg     arguement
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+mdev_query(struct m_dev *m_dev, void *arg)
+{
+	struct mbt_dev *mbt_dev = (struct mbt_dev *)m_dev->dev_pointer;
+
+	ENTER();
+	if (copy_to_user(arg, &mbt_dev->type, sizeof(mbt_dev->type)))
+		PRINTM(ERROR, "IOCTL_QUERY_TYPE: Fail copy to user\n");
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+init_m_dev(struct m_dev *m_dev)
+{
+	m_dev->dev_pointer = NULL;
+	m_dev->driver_data = NULL;
+	m_dev->dev_type = 0;
+	m_dev->spec_type = 0;
+	skb_queue_head_init(&m_dev->rx_q);
+	init_waitqueue_head(&m_dev->req_wait_q);
+	init_waitqueue_head(&m_dev->rx_wait_q);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+	init_MUTEX(&m_dev->req_lock);
+#else
+	sema_init(&m_dev->req_lock, 1);
+#endif
+	spin_lock_init(&m_dev->rxlock);
+	memset(&m_dev->stat, 0, sizeof(struct hci_dev_stats));
+	m_dev->open = mdev_open;
+	m_dev->close = mdev_close;
+	m_dev->flush = mdev_flush;
+	m_dev->send = mdev_send_frame;
+	m_dev->destruct = mdev_destruct;
+	m_dev->ioctl = mdev_ioctl;
+	m_dev->query = mdev_query;
+	m_dev->owner = THIS_MODULE;
+
+}
+
+/**
+ *  @brief This function handles the major job in bluetooth driver.
+ *  it handles the event generated by firmware, rx data received
+ *  from firmware and tx data sent from kernel.
+ *
+ *  @param data    A pointer to bt_thread structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+static int
+bt_service_main_thread(void *data)
+{
+	bt_thread *thread = data;
+	bt_private *priv = thread->priv;
+	bt_adapter *adapter = priv->adapter;
+	wait_queue_t wait;
+	struct sk_buff *skb;
+	ENTER();
+	bt_activate_thread(thread);
+	init_waitqueue_entry(&wait, current);
+	current->flags |= PF_NOFREEZE;
+
+	for (;;) {
+		add_wait_queue(&thread->waitQ, &wait);
+		OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE);
+		if (priv->adapter->WakeupTries ||
+		    ((!priv->adapter->IntCounter) &&
+		     (!priv->bt_dev.tx_dnld_rdy ||
+		      skb_queue_empty(&priv->adapter->tx_queue)))) {
+			PRINTM(INFO, "Main: Thread sleeping...\n");
+			schedule();
+		}
+		OS_SET_THREAD_STATE(TASK_RUNNING);
+		remove_wait_queue(&thread->waitQ, &wait);
+		if (kthread_should_stop() || adapter->SurpriseRemoved) {
+			PRINTM(INFO, "main-thread: break from main thread: "
+			       "SurpriseRemoved=0x%x\n",
+			       adapter->SurpriseRemoved);
+			break;
+		}
+
+		PRINTM(INFO, "Main: Thread waking up...\n");
+
+		if (priv->adapter->IntCounter) {
+			OS_INT_DISABLE;
+			adapter->IntCounter = 0;
+			OS_INT_RESTORE;
+			sbi_get_int_status(priv);
+		} else if ((priv->adapter->ps_state == PS_SLEEP) &&
+			   !skb_queue_empty(&priv->adapter->tx_queue)) {
+			priv->adapter->WakeupTries++;
+			sbi_wakeup_firmware(priv);
+			continue;
+		}
+		if (priv->adapter->ps_state == PS_SLEEP)
+			continue;
+		if (priv->bt_dev.tx_dnld_rdy == TRUE) {
+			if (!skb_queue_empty(&priv->adapter->tx_queue)) {
+				skb = skb_dequeue(&priv->adapter->tx_queue);
+				if (skb) {
+					if (send_single_packet(priv, skb))
+						update_stat_err_tx(priv, skb);
+					else
+						update_stat_byte_tx(priv, skb);
+					kfree_skb(skb);
+				}
+			}
+		}
+	}
+	bt_deactivate_thread(thread);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the interrupt. it will change PS
+ *  state if applicable. it will wake up main_thread to handle
+ *  the interrupt event as well.
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @return        N/A
+ */
+void
+bt_interrupt(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	if (!priv || !priv->adapter) {
+		LEAVE();
+		return;
+	}
+	PRINTM(INTR, "*\n");
+	priv->adapter->ps_state = PS_AWAKE;
+	if (priv->adapter->hs_state == HS_ACTIVATED) {
+		PRINTM(CMD, "BT: %s: HS DEACTIVATED in ISR!\n", m_dev->name);
+		priv->adapter->hs_state = HS_DEACTIVATED;
+	}
+	priv->adapter->WakeupTries = 0;
+	priv->adapter->IntCounter++;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	LEAVE();
+}
+
+static void
+bt_private_dynamic_release(struct kobject *kobj)
+{
+	bt_private *priv = container_of(kobj, bt_private, kobj);
+	ENTER();
+	PRINTM(INFO, "free bt priv\n");
+	kfree(priv);
+	LEAVE();
+}
+
+static struct kobj_type ktype_bt_private_dynamic = {
+	.release = bt_private_dynamic_release,
+};
+
+static bt_private *
+bt_alloc_priv(void)
+{
+	bt_private *priv;
+	ENTER();
+	priv = kzalloc(sizeof(bt_private), GFP_KERNEL);
+	if (priv) {
+		kobject_init(&priv->kobj, &ktype_bt_private_dynamic);
+		PRINTM(INFO, "alloc bt priv\n");
+	}
+	LEAVE();
+	return priv;
+}
+
+struct kobject *
+bt_priv_get(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv get object");
+	return kobject_get(&priv->kobj);
+}
+
+void
+bt_priv_put(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv put object");
+	kobject_put(&priv->kobj);
+}
+
+/**
+ *  @brief This function send init commands to firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_init_cmd(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = bt_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+	if (ret < 0) {
+		PRINTM(FATAL, "Module cfg command send failed!\n");
+		goto done;
+	}
+	if (btindrst != -1) {
+		ret = bt_set_independent_reset(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Independent reset failed!\n");
+			goto done;
+		}
+	}
+	if (btpmic) {
+		if (BT_STATUS_SUCCESS != bt_pmic_configure(priv)) {
+			PRINTM(FATAL, "BT: PMIC Configure failed \n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	ret = bt_set_ble_deepsleep(priv, TRUE);
+	if (ret < 0) {
+		PRINTM(FATAL, "Enable BLE deepsleep failed!\n");
+		goto done;
+	}
+	if (psmode) {
+		priv->bt_dev.psmode = TRUE;
+		priv->bt_dev.idle_timeout = DEFAULT_IDLE_TIME;
+		ret = bt_enable_ps(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Enable PS mode failed!\n");
+			goto done;
+		}
+	}
+#if defined(SDIO_SUSPEND_RESUME)
+	priv->bt_dev.gpio_gap = DEF_GPIO_GAP;
+	ret = bt_send_hscfg_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "Send HSCFG failed!\n");
+		goto done;
+	}
+#endif
+	priv->bt_dev.sdio_pull_cfg = 0xffffffff;
+	priv->bt_dev.sdio_pull_ctrl = 0;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reinit firmware after redownload firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_reinit_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+	/* block all the packet from bluez */
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext)
+		priv->adapter->tx_lock = TRUE;
+
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext) {
+		priv->adapter->tx_lock = FALSE;
+		bt_restore_tx_queue(priv);
+	}
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+done:
+	return ret;
+}
+
+/**
+ *  @brief Module configuration and register device
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @return      BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_conf_dpc(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct hci_dev *hdev = NULL;
+	unsigned char dev_type = 0;
+
+	ENTER();
+
+	priv->bt_dev.tx_dnld_rdy = TRUE;
+
+	if (priv->fw_reload) {
+		bt_reinit_fw(priv);
+		LEAVE();
+		return ret;
+	}
+
+	if (drv_mode & DRV_MODE_BT) {
+		hdev = hci_alloc_dev();
+		if (!hdev) {
+			PRINTM(FATAL, "Can not allocate HCI device\n");
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		hdev->open = bt_open;
+		hdev->close = bt_close;
+		hdev->flush = bt_flush;
+		hdev->send = bt_send_frame;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
+		hdev->destruct = bt_destruct;
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+		hdev->ioctl = bt_ioctl;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+		hci_set_drvdata(hdev, priv);
+#else
+		hdev->driver_data = priv;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
+		hdev->owner = THIS_MODULE;
+#endif
+		priv->bt_dev.m_dev[BT_SEQ].dev_type = BT_TYPE;
+		priv->bt_dev.m_dev[BT_SEQ].spec_type = BLUEZ_SPEC;
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = (void *)hdev;
+		priv->bt_dev.m_dev[BT_SEQ].driver_data = priv;
+		priv->bt_dev.m_dev[BT_SEQ].read_continue_flag = 0;
+	}
+
+	dev_type = HCI_SDIO;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+	if (hdev)
+		hdev->bus = dev_type;
+#else
+	if (hdev)
+		hdev->type = dev_type;
+#endif /* >= 2.6.34 */
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+
+	/** Process device tree init parameters before register hci device.
+	 *  Since uplayer device has not yet registered, no need to block tx queue.
+	 * */
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	} else if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Get FW version */
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+
+	if (hdev) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+		hdev->dev_type = priv->bt_dev.devType;
+#endif
+		ret = hci_register_dev(hdev);
+		if (ret < 0) {
+			PRINTM(FATAL, "Can not register HCI device\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		snprintf((char *)priv->bt_dev.m_dev[BT_SEQ].name,
+			 sizeof(priv->bt_dev.m_dev[BT_SEQ].name), hdev->name);
+		bt_proc_init(priv, &(priv->bt_dev.m_dev[BT_SEQ]), BT_SEQ);
+	}
+
+done:
+	LEAVE();
+	return ret;
+err_kmalloc:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function adds the card. it will probe the
+ *  card, allocate the bt_priv and initialize the device.
+ *
+ *  @param card    A pointer to card
+ *  @return        A pointer to bt_private structure
+ */
+
+bt_private *
+bt_add_card(void *card)
+{
+	bt_private *priv = NULL;
+
+	ENTER();
+
+	priv = bt_alloc_priv();
+	if (!priv) {
+		PRINTM(FATAL, "Can not allocate priv\n");
+		LEAVE();
+		return NULL;
+	}
+
+	/* allocate buffer for bt_adapter */
+	priv->adapter = kzalloc(sizeof(bt_adapter), GFP_KERNEL);
+	if (!priv->adapter) {
+		PRINTM(FATAL, "Allocate buffer for bt_adapter failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buffer =
+		kzalloc(MAX_TX_BUF_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->tx_buffer) {
+		PRINTM(FATAL, "Allocate buffer for transmit\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buf =
+		(u8 *)ALIGN_ADDR(priv->adapter->tx_buffer, DMA_ALIGNMENT);
+	priv->adapter->hw_regs_buf =
+		kzalloc(SD_BLOCK_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->hw_regs_buf) {
+		PRINTM(FATAL, "Allocate buffer for INT read buf failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->hw_regs =
+		(u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf, DMA_ALIGNMENT);
+	bt_init_adapter(priv);
+
+	PRINTM(INFO, "Starting kthread...\n");
+	priv->MainThread.priv = priv;
+	spin_lock_init(&priv->driver_lock);
+
+	bt_create_thread(bt_service_main_thread, &priv->MainThread,
+			 "bt_main_service");
+
+	/* wait for mainthread to up */
+	while (!priv->MainThread.pid)
+		os_sched_timeout(1);
+
+	/** user config file */
+	init_waitqueue_head(&priv->init_user_conf_wait_q);
+
+	priv->bt_dev.card = card;
+
+	((struct sdio_mmc_card *)card)->priv = priv;
+	priv->adapter->sd_ireg = 0;
+	/*
+	 * Register the device. Fillup the private data structure with
+	 * relevant information from the card and request for the required
+	 * IRQ.
+	 */
+	if (sbi_register_dev(priv) < 0) {
+		PRINTM(FATAL, "Failed to register bt device!\n");
+		goto err_registerdev;
+	}
+	if (bt_init_fw(priv)) {
+		PRINTM(FATAL, "BT Firmware Init Failed\n");
+		goto err_init_fw;
+	}
+	LEAVE();
+	return priv;
+
+err_init_fw:
+	clean_up_m_devs(priv);
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+err_registerdev:
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+err_kmalloc:
+	if (priv->adapter)
+		bt_free_adapter(priv);
+	bt_priv_put(priv);
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function send hardware remove event
+ *
+ *  @param priv    A pointer to bt_private
+ *  @return        N/A
+ */
+void
+bt_send_hw_remove_event(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	struct hci_dev *hdev = NULL;
+	ENTER();
+	if (!priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		LEAVE();
+		return;
+	}
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type == BLUEZ_SPEC)
+		hdev = (struct hci_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer;
+#define HCI_HARDWARE_ERROR_EVT  0x10
+#define HCI_HARDWARE_REMOVE     0x24
+	skb = bt_skb_alloc(3, GFP_ATOMIC);
+	skb->data[0] = HCI_HARDWARE_ERROR_EVT;
+	skb->data[1] = 1;
+	skb->data[2] = HCI_HARDWARE_REMOVE;
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb_put(skb, 3);
+	if (hdev) {
+		skb->dev = (void *)hdev;
+		PRINTM(MSG, "Send HW ERROR event\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+		hci_recv_frame(skb);
+#else
+		hci_recv_frame(hdev, skb);
+#endif
+		os_sched_timeout(5);
+		hdev->stat.byte_rx += 3;
+	}
+	LEAVE();
+	return;
+}
+
+#ifdef BLE_WAKEUP
+/**
+ *  @brief This function used to config BLE wakeup pattern
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        N/A
+ */
+int
+bt_config_ble_wakeup(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	u16 ocf, left_len;
+	u8 len, more_cmd;
+	u8 *pos;
+
+	ENTER();
+
+	if (!priv->ble_wakeup_buf) {
+		PRINTM(ERROR, "BT: no ble wakeup parameters found\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MSG, "Config ble wakeup pattern\n");
+
+	pos = priv->ble_wakeup_buf;
+	left_len = *(u16 *) pos;
+	left_len = __le16_to_cpu(left_len);
+	pos += sizeof(u16);
+
+	while (left_len >= 2) {
+		more_cmd = *pos;
+		len = *(pos + 1);
+		if (((len + 2) > left_len) ||
+		    (!more_cmd && ((len + 2) < left_len))) {
+			PRINTM(ERROR, "Invalid ble parameters\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		skb = bt_skb_alloc(len, GFP_ATOMIC);
+		if (!skb) {
+			PRINTM(ERROR, "BT BLE WAKEUP: fail to alloc skb\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy(skb_put(skb, len), pos + 2, len);
+		bt_cb(skb)->pkt_type = *(u8 *)skb->data;
+		skb_pull(skb, 1);
+		DBG_HEXDUMP(DAT_D, "BLE_WAKEUP_CMD:", skb->data, skb->len);
+		skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+		skb_queue_head(&priv->adapter->tx_queue, skb);
+		priv->bt_dev.sendcmdflag = TRUE;
+		priv->bt_dev.send_cmd_opcode = *(u16 *) skb->data;
+		ocf = hci_opcode_ocf(priv->bt_dev.send_cmd_opcode);
+		priv->adapter->cmd_complete = FALSE;
+
+		wake_up_interruptible(&priv->MainThread.waitQ);
+		if (!os_wait_interruptible_timeout
+		    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+		     WAIT_UNTIL_CMD_RESP)) {
+			ret = BT_STATUS_FAILURE;
+			PRINTM(ERROR,
+			       "BT: Set  Set ble wakeup cmd 0x%x timeout:\n",
+			       priv->bt_dev.send_cmd_opcode);
+			bt_cmd_timeout_func(priv, ocf);
+			goto done;
+		}
+
+		pos += len + 2;
+		left_len -= len + 2;
+	}
+
+done:
+	if (ret != BT_STATUS_SUCCESS) {
+		if (priv->ble_wakeup_buf) {
+			kfree(priv->ble_wakeup_buf);
+			priv->ble_wakeup_buf = NULL;
+			priv->ble_wakeup_buf_size = 0;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function send system suspend event
+ *
+ *  @param priv    A pointer to bt_private
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_send_system_event(bt_private *priv, u8 flag)
+{
+	struct sk_buff *skb = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+
+	ENTER();
+
+	if (!priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+
+	skb = bt_skb_alloc(4, GFP_ATOMIC);
+	if (!skb) {
+		PRINTM(ERROR, "Fail to allocate sys suspend event skb\n");
+		return BT_STATUS_FAILURE;
+	}
+	skb->data[0] = VENDOR_SPECIFIC_EVENT;
+	skb->data[1] = 2;
+	skb->data[2] = HCI_SYSTEM_SUSPEND_EVT;
+	if (flag)
+		skb->data[3] = HCI_SYSTEM_SUSPEND;
+	else
+		skb->data[3] = HCI_SYSTEM_RESUME;
+
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb_put(skb, 4);
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		PRINTM(MSG, "Send system %s event\n",
+		       flag ? "suspend" : "resume");
+		if (!mdev_recv_frame(skb)) {
+#define RX_WAIT_TIMEOUT                         300
+			mdev_bt->wait_rx_complete = TRUE;
+			mdev_bt->rx_complete_flag = FALSE;
+			if (os_wait_interruptible_timeout(mdev_bt->rx_wait_q,
+							  mdev_bt->
+							  rx_complete_flag,
+							  RX_WAIT_TIMEOUT))
+				PRINTM(MSG, "BT stack received the event\n");
+			mdev_bt->stat.byte_rx += 4;
+		}
+	}
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function removes the card.
+ *
+ *  @param card    A pointer to card
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_remove_card(void *card)
+{
+	bt_private *priv = (bt_private *)card;
+	ENTER();
+	if (!priv) {
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+	if (!priv->adapter->SurpriseRemoved) {
+		if (BT_STATUS_SUCCESS == bt_send_reset_command(priv))
+			bt_send_module_cfg_cmd(priv, MODULE_SHUTDOWN_REQ);
+		/* Disable interrupts on the card */
+		sd_disable_host_int(priv);
+		priv->adapter->SurpriseRemoved = TRUE;
+	}
+	bt_send_hw_remove_event(priv);
+#ifdef BLE_WAKEUP
+	if (priv->ble_wakeup_buf) {
+		kfree(priv->ble_wakeup_buf);
+		priv->ble_wakeup_buf = NULL;
+		priv->ble_wakeup_buf_size = 0;
+	}
+#endif
+	wake_up_interruptible(&priv->adapter->cmd_wait_q);
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid) {
+		os_sched_timeout(1);
+		wake_up_interruptible(&priv->MainThread.waitQ);
+	}
+
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+	clean_up_m_devs(priv);
+	PRINTM(INFO, "Free Adapter\n");
+	bt_free_adapter(priv);
+	bt_priv_put(priv);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function initializes module.
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_module(void)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	PRINTM(MSG, "BT: Loading driver\n");
+
+	bt_root_proc_init();
+
+	/** create char device class */
+	chardev_class = class_create(THIS_MODULE, MODULE_NAME);
+	if (IS_ERR(chardev_class)) {
+		PRINTM(ERROR, "Unable to allocate class\n");
+		bt_root_proc_remove();
+		ret = PTR_ERR(chardev_class);
+		goto done;
+	}
+
+	if (sbi_register() == NULL) {
+		bt_root_proc_remove();
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	if (ret)
+		PRINTM(MSG, "BT: Driver loading failed\n");
+	else
+		PRINTM(MSG, "BT: Driver loaded successfully\n");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function cleans module
+ *
+ *  @return        N/A
+ */
+static void
+bt_exit_module(void)
+{
+	ENTER();
+	PRINTM(MSG, "BT: Unloading driver\n");
+	sbi_unregister();
+
+	bt_root_proc_remove();
+	class_destroy(chardev_class);
+	PRINTM(MSG, "BT: Driver unloaded\n");
+	LEAVE();
+}
+
+module_init(bt_init_module);
+module_exit(bt_exit_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell Bluetooth Driver Ver. " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+module_param(fw, int, 0);
+MODULE_PARM_DESC(fw, "0: Skip firmware download; otherwise: Download firmware");
+module_param(psmode, int, 0);
+MODULE_PARM_DESC(psmode, "1: Enable powermode; 0: Disable powermode");
+#ifdef CONFIG_OF
+module_param(dts_enable, int, 0);
+MODULE_PARM_DESC(dts_enable, "0: Disable DTS; 1: Enable DTS");
+#endif
+#ifdef	DEBUG_LEVEL1
+module_param(mbt_drvdbg, uint, 0);
+MODULE_PARM_DESC(mbt_drvdbg, "BIT3:DBG_DATA BIT4:DBG_CMD 0xFF:DBG_ALL");
+#endif
+#ifdef SDIO_SUSPEND_RESUME
+module_param(mbt_pm_keep_power, int, 0);
+MODULE_PARM_DESC(mbt_pm_keep_power, "1: PM keep power; 0: PM no power");
+#endif
+module_param(init_cfg, charp, 0);
+MODULE_PARM_DESC(init_cfg, "BT init config file name");
+module_param(cal_cfg, charp, 0);
+MODULE_PARM_DESC(cal_cfg, "BT calibrate file name");
+module_param(cal_cfg_ext, charp, 0);
+MODULE_PARM_DESC(cal_cfg_ext, "BT calibrate ext file name");
+module_param(bt_mac, charp, 0660);
+MODULE_PARM_DESC(bt_mac, "BT init mac address");
+module_param(drv_mode, int, 0);
+MODULE_PARM_DESC(drv_mode, "Bit 0: BT/AMP/BLE;");
+module_param(bt_fw_reload, int, 0);
+MODULE_PARM_DESC(bt_fw_reload,
+		 "0: disable fw_reload; 1: enable fw reload feature");
+module_param(btindrst, int, 0);
+MODULE_PARM_DESC(btindrst,
+		 "Independent reset configuration; high byte:GPIO pin number;low byte:0x0:disable, 0x1:out-band reset, 0x2:in-band reset.");
+module_param(btpmic, int, 0);
+MODULE_PARM_DESC(btpmic,
+		 "1: Send pmic configure cmd to firmware; 0: No pmic configure cmd sent to firmware (default)");
+module_param(bt_fw_serial, int, 0);
+MODULE_PARM_DESC(bt_fw_serial,
+		 "0: Support parallel download FW; 1: Support serial download FW");
diff --git a/bt_sd8997/bt/bt_proc.c b/bt_sd8997/bt/bt_proc.c
new file mode 100644
index 0000000..c401791
--- /dev/null
+++ b/bt_sd8997/bt/bt_proc.c
@@ -0,0 +1,881 @@
+/** @file bt_proc.c
+  *
+  * @brief This file handle the functions for proc files
+  *
+  * Copyright (C) 2007-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/proc_fs.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** proc diretory root */
+#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
+
+/** Proc mbt directory entry */
+static struct proc_dir_entry *proc_mbt;
+
+#define     CMD52_STR_LEN   50
+static char cmd52_string[CMD52_STR_LEN];
+
+struct proc_data {
+	/** Read length */
+	int rdlen;
+	/** Read buffer */
+	char *rdbuf;
+	/** Write length */
+	int wrlen;
+	/** Maximum write length */
+	int maxwrlen;
+	/** Write buffer */
+	char *wrbuf;
+	/** Private structure */
+	struct _bt_private *pbt;
+	void (*on_close) (struct inode *, struct file *);
+};
+
+/** Default file permission */
+#define DEFAULT_FILE_PERM  0644
+
+/** Bluetooth device offset */
+#define OFFSET_BT_DEV		0x01
+/** Bluetooth adapter offset */
+#define OFFSET_BT_ADAPTER	0x02
+/** Show integer */
+#define SHOW_INT		0x10
+/** Show hex */
+#define SHOW_HEX		0x20
+/** Show string */
+#define SHOW_STRING		0x40
+
+/** Device size */
+#define item_dev_size(n) (sizeof((bt_dev_t *)0)->n)
+/** Device address */
+#define item_dev_addr(n) ((t_ptr) &((bt_dev_t *)0)->n)
+
+/** Adapter size */
+#define item_adapter_size(n) (sizeof((bt_adapter *)0)->n)
+/** Adapter address */
+#define item_adapter_addr(n) ((t_ptr) &((bt_adapter *)0)->n)
+
+static struct item_data config_items[] = {
+#ifdef	DEBUG_LEVEL1
+	{"drvdbg", sizeof(u32), (t_ptr)&mbt_drvdbg, 0, SHOW_HEX}
+	,
+#endif
+	{"idle_timeout", item_dev_size(idle_timeout), 0,
+	 item_dev_addr(idle_timeout), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"psmode", item_dev_size(psmode), 0, item_dev_addr(psmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"pscmd", item_dev_size(pscmd), 0, item_dev_addr(pscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hsmode", item_dev_size(hsmode), 0, item_dev_addr(hsmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hscmd", item_dev_size(hscmd), 0, item_dev_addr(hscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"gpio_gap", item_dev_size(gpio_gap), 0, item_dev_addr(gpio_gap),
+	 OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"hscfgcmd", item_dev_size(hscfgcmd), 0, item_dev_addr(hscfgcmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"sdio_pull_cfg", item_dev_size(sdio_pull_cfg), 0,
+	 item_dev_addr(sdio_pull_cfg), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"sdio_pull_ctrl", item_dev_size(sdio_pull_ctrl), 0,
+	 item_dev_addr(sdio_pull_ctrl), OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"test_mode", item_dev_size(test_mode), 0, item_dev_addr(test_mode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+
+};
+
+static struct item_data status_items[] = {
+	{"version", item_adapter_size(drv_ver), 0, item_adapter_addr(drv_ver),
+	 OFFSET_BT_ADAPTER | SHOW_STRING},
+	{"tx_dnld_rdy", item_dev_size(tx_dnld_rdy), 0,
+	 item_dev_addr(tx_dnld_rdy),
+	 OFFSET_BT_DEV | SHOW_INT},
+	{"psmode", item_adapter_size(psmode), 0, item_adapter_addr(psmode),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_state", item_adapter_size(hs_state), 0,
+	 item_adapter_addr(hs_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_skip", item_adapter_size(hs_skip), 0, item_adapter_addr(hs_skip),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"ps_state", item_adapter_size(ps_state), 0,
+	 item_adapter_addr(ps_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"WakeupTries", item_adapter_size(WakeupTries), 0,
+	 item_adapter_addr(WakeupTries), OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_recv", item_adapter_size(irq_recv), 0,
+	 item_adapter_addr(irq_recv),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_done", item_adapter_size(irq_done), 0,
+	 item_adapter_addr(irq_done),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"skb_pending", item_adapter_size(skb_pending), 0,
+	 item_adapter_addr(skb_pending), OFFSET_BT_ADAPTER | SHOW_INT},
+};
+
+static struct item_data debug_items[] = {
+	{"sdcmd52rw", 0, (t_ptr)cmd52_string, 0, SHOW_STRING},
+};
+
+/**
+ *  @brief convert string to number
+ *
+ *  @param s	pointer to numbered string
+ *  @return	converted number from string s
+ */
+int
+string_to_number(char *s)
+{
+	int r = 0;
+	int base = 0;
+	int pn = 1;
+
+	if (strncmp(s, "-", 1) == 0) {
+		pn = -1;
+		s++;
+	}
+	if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
+		base = 16;
+		s += 2;
+	} else
+		base = 10;
+
+	for (s = s; *s != 0; 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 Create cmd52 string
+ *
+ *  @param priv	A pointer to bt_private structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+form_cmd52_string(bt_private *priv)
+{
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	snprintf(cmd52_string, CMD52_STR_LEN - 1, "BT: %d 0x%0x 0x%02X",
+		 priv->bt_dev.cmd52_func, priv->bt_dev.cmd52_reg,
+		 priv->bt_dev.cmd52_val);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/*
+ *  @brief Parse cmd52 string
+ *
+ *  @param buffer  A pointer user buffer
+ *  @param len     Length of 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 __user * buffer, size_t len,
+		   int *func, int *reg, int *val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	char *string = NULL;
+	char *pos = NULL;
+
+	ENTER();
+
+	string = kzalloc(CMD52_STR_LEN, GFP_KERNEL);
+	if (!string) {
+		PRINTM(ERROR, "BT: Can not alloc mem for cmd52 string\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	memcpy(string, buffer + strlen("sdcmd52rw="),
+	       len - strlen("sdcmd52rw="));
+	string = strstrip(string);
+
+	*func = -1;
+	*reg = -1;
+	*val = -1;
+
+	/* Get func */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*func = string_to_number(pos);
+
+	/* Get reg */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*reg = string_to_number(pos);
+
+	/* Get val (optional) */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*val = string_to_number(pos);
+	kfree(string);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handle generic proc file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+proc_close(struct inode *inode, struct file *file)
+{
+	struct proc_data *pdata = file->private_data;
+	ENTER();
+	if (pdata) {
+		if (pdata->on_close != NULL)
+			pdata->on_close(inode, file);
+		kfree(pdata->rdbuf);
+		kfree(pdata->wrbuf);
+		kfree(pdata);
+	}
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle generic proc file read
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to output buffer
+ *  @param len     number of byte to read
+ *  @param offset  A pointer to offset of file
+ *  @return		number of output data
+ */
+static ssize_t
+proc_read(struct file *file, char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	if ((!pdata->rdbuf) || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->rdlen)
+		return 0;
+	if (len > pdata->rdlen - pos)
+		len = pdata->rdlen - pos;
+	if (copy_to_user(buffer, pdata->rdbuf + pos, len))
+		return -EFAULT;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle generic proc file write
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to input buffer
+ *  @param len     number of byte to write
+ *  @param offset  A pointer to offset of file
+ *  @return		number of input data
+ */
+static ssize_t
+proc_write(struct file *file,
+	   const char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	int func = 0, reg = 0, val = 0;
+	int config_data = 0;
+	char *line = NULL;
+
+	if (!pdata->wrbuf || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->maxwrlen)
+		return 0;
+	if (len > pdata->maxwrlen - pos)
+		len = pdata->maxwrlen - pos;
+	if (copy_from_user(pdata->wrbuf + pos, buffer, len))
+		return -EFAULT;
+	if (!strncmp(pdata->wrbuf + pos, "fw_reload", strlen("fw_reload"))) {
+		if (!strncmp
+		    (pdata->wrbuf + pos, "fw_reload=", strlen("fw_reload="))) {
+			line = pdata->wrbuf + pos;
+			line += strlen("fw_reload") + 1;
+			config_data = string_to_number(line);
+		} else
+			config_data = FW_RELOAD_SDIO_INBAND_RESET;
+		PRINTM(MSG, "Request fw_reload=%d\n", config_data);
+		bt_request_fw_reload(pdata->pbt, config_data);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "sdcmd52rw=", strlen("sdcmd52rw="))) {
+		parse_cmd52_string(pdata->wrbuf + pos, len, &func, &reg, &val);
+		sd_write_cmd52_val(pdata->pbt, func, reg, val);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "debug_dump", strlen("debug_dump"))) {
+		bt_dump_sdio_regs(pdata->pbt);
+		bt_dump_firmware_info_v2(pdata->pbt);
+	}
+
+	if (pos + len > pdata->wrlen)
+		pdata->wrlen = len + file->f_pos;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle the generic file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return		N/A
+ */
+static void
+proc_on_close(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata = file->private_data;
+	char *line;
+	int i;
+	ENTER();
+	if (!pdata->wrlen)
+		return;
+	line = pdata->wrbuf;
+	while (line[0]) {
+		for (i = 0; i < priv->num_items; i++) {
+			if (!strncmp
+			    (line, priv->pdata[i].name,
+			     strlen(priv->pdata[i].name))) {
+				line += strlen(priv->pdata[i].name) + 1;
+				if (priv->pdata[i].size == 1)
+					*((u8 *)priv->pdata[i].addr) =
+						(u8)string_to_number(line);
+				else if (priv->pdata[i].size == 2)
+					*((u16 *) priv->pdata[i].addr) =
+						(u16) string_to_number(line);
+				else if (priv->pdata[i].size == 4)
+					*((u32 *)priv->pdata[i].addr) =
+						(u32)string_to_number(line);
+			}
+		}
+		while (line[0] && line[0] != '\n')
+			line++;
+		if (line[0])
+			line++;
+	}
+	if (priv->pbt->bt_dev.hscmd || priv->pbt->bt_dev.pscmd
+	    || priv->pbt->bt_dev.sdio_pull_ctrl
+	    || priv->pbt->bt_dev.test_mode || priv->pbt->bt_dev.hscfgcmd) {
+		bt_prepare_command(priv->pbt);
+		wake_up_interruptible(&priv->pbt->MainThread.waitQ);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handle the generic file open
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS or other error no.
+ */
+static int
+proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata;
+	int i;
+	char *p;
+	u32 val = 0;
+	ENTER();
+	priv->pbt->adapter->skb_pending =
+		skb_queue_len(&priv->pbt->adapter->tx_queue);
+	file->private_data = kzalloc(sizeof(struct proc_data), GFP_KERNEL);
+	if (file->private_data == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for proc_data\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	pdata = (struct proc_data *)file->private_data;
+	pdata->pbt = priv->pbt;
+	pdata->rdbuf = kmalloc(priv->bufsize, GFP_KERNEL);
+	if (pdata->rdbuf == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for rdbuf\n");
+		kfree(file->private_data);
+		LEAVE();
+		return -ENOMEM;
+	}
+	if (priv->fileflag == DEFAULT_FILE_PERM) {
+		pdata->wrbuf = kzalloc(priv->bufsize, GFP_KERNEL);
+		if (pdata->wrbuf == NULL) {
+			PRINTM(ERROR, "BT: Can not alloc mem for wrbuf\n");
+			kfree(pdata->rdbuf);
+			kfree(file->private_data);
+			return -ENOMEM;
+		}
+		pdata->maxwrlen = priv->bufsize;
+		pdata->on_close = proc_on_close;
+	}
+	p = pdata->rdbuf;
+	for (i = 0; i < priv->num_items; i++) {
+		if (priv->pdata[i].size == 1)
+			val = *((u8 *)priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 2)
+			val = *((u16 *) priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 4)
+			val = *((u32 *)priv->pdata[i].addr);
+		if (priv->pdata[i].flag & SHOW_INT)
+			p += sprintf(p, "%s=%d\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_HEX)
+			p += sprintf(p, "%s=0x%x\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_STRING) {
+			if (!strncmp
+			    (priv->pdata[i].name, "sdcmd52rw",
+			     strlen("sdcmd52rw"))) {
+				sd_read_cmd52_val(priv->pbt);
+				form_cmd52_string(priv->pbt);
+			}
+			p += sprintf(p, "%s=%s\n", priv->pdata[i].name,
+				     (char *)priv->pdata[i].addr);
+		}
+	}
+	pdata->rdlen = strlen(pdata->rdbuf);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+static const struct file_operations proc_read_ops = {
+	.read = proc_read,
+	.open = proc_open,
+	.release = proc_close
+};
+
+static const struct file_operations proc_rw_ops = {
+	.read = proc_read,
+	.write = proc_write,
+	.open = proc_open,
+	.release = proc_close
+};
+
+static struct proc_private_data proc_files[] = {
+	{"status", S_IRUGO, 1024,
+	 sizeof(status_items) / sizeof(status_items[0]),
+	 &status_items[0], NULL, &proc_read_ops}
+	,
+	{"config", DEFAULT_FILE_PERM, 512,
+	 sizeof(config_items) / sizeof(config_items[0]), &config_items[0], NULL,
+	 &proc_rw_ops}
+	,
+	{"debug", DEFAULT_FILE_PERM, 512,
+	 sizeof(debug_items) / sizeof(debug_items[0]), &debug_items[0], NULL,
+	 &proc_rw_ops}
+	,
+};
+
+/**
+ *  @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
+bt_histogram_read(struct seq_file *sfp, void *data)
+{
+	bt_hist_proc_data *pdata = (bt_hist_proc_data *) sfp->private;
+	bt_private *priv = (bt_private *)pdata->pbt;
+	u8 ant_num;
+	int i, j;
+
+	ENTER();
+	if (!priv) {
+		LEAVE();
+		return -EFAULT;
+	}
+	bt_get_histogram(priv);
+	ant_num = priv->hist_data_len / sizeof(bt_histogram_data);
+	seq_printf(sfp, "BT histogram:\n");
+	seq_printf(sfp, "antenna: 0=2.4G antenna a,  1=2.4G antenna b\n\n");
+	if (ant_num < 1) {
+		seq_printf(sfp, "no histogram data from FW\n");
+		LEAVE();
+		return 0;
+	}
+	for (i = 0; i < ant_num; i++) {
+		if (pdata->antenna != priv->hist_data[i].antenna)
+			continue;
+		seq_printf(sfp, "antenna %d\n", priv->hist_data[i].antenna);
+		switch (priv->hist_data[i].powerclass) {
+		case 2:
+			seq_printf(sfp, "Power class=1.5\n");
+			break;
+		case 5:
+			seq_printf(sfp, "Power class=2\n");
+			break;
+		case 6:
+			seq_printf(sfp, "Power class=1\n");
+			break;
+		default:
+			seq_printf(sfp, "Power class=%d\n",
+				   priv->hist_data[i].powerclass);
+			break;
+		}
+		for (j = 0; j < (MAX_BT_LINK + MAX_BLE_LINK); j++) {
+			switch (priv->hist_data[i].link[j].txrxrate) {
+			case BDR_RATE_1M:
+				seq_printf(sfp,
+					   "BT link[%d]: TxPower=%d dBm, TxRx Rate=BDR(1 mbps), RSSI=%d dBm\n",
+					   j + 1,
+					   priv->hist_data[i].link[j].txpower,
+					   priv->hist_data[i].link[j].rssi);
+				break;
+			case EDR_RATE_2_3M:
+				seq_printf(sfp,
+					   "BT link[%d]: TxPower=%d dBm, TxRx Rate=EDR(2/3 mbps), RSSI=%d dBm\n",
+					   j + 1,
+					   priv->hist_data[i].link[j].txpower,
+					   priv->hist_data[i].link[j].rssi);
+				break;
+			case BLE_RATE_1M:
+				seq_printf(sfp,
+					   "BLE link[%d]: TxPower=%d dBm, TxRx Rate=BLE(1 mbps), RSSI=%d dBm\n",
+					   j - MAX_BT_LINK + 0x80,
+					   priv->hist_data[i].link[j].txpower,
+					   priv->hist_data[i].link[j].rssi);
+				break;
+			default:
+				if (j < MAX_BT_LINK)
+					seq_printf(sfp,
+						   "BT link[%d]: TxPower=%d dBm, TxRx Rate=(%d), RSSI=%d dBm\n",
+						   j + 1,
+						   priv->hist_data[i].link[j].
+						   txpower,
+						   priv->hist_data[i].link[j].
+						   txrxrate,
+						   priv->hist_data[i].link[j].
+						   rssi);
+				else
+					seq_printf(sfp,
+						   "BLE link[%d]: TxPower=%d dBm, TxRx Rate=(%d), RSSI=%d dBm\n",
+						   j - MAX_BT_LINK + 0x80,
+						   priv->hist_data[i].link[j].
+						   txpower,
+						   priv->hist_data[i].link[j].
+						   txrxrate,
+						   priv->hist_data[i].link[j].
+						   rssi);
+				break;
+			}
+		}
+		seq_printf(sfp, "\n");
+	}
+	LEAVE();
+	return 0;
+}
+
+static int
+bt_histogram_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, bt_histogram_read, PDE_DATA(inode));
+#else
+	return single_open(file, bt_histogram_read, PDE(inode)->data);
+#endif
+}
+
+static const struct file_operations histogram_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = bt_histogram_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+/**
+ *  @brief This function initializes proc entry
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param m_dev    A pointer to struct m_dev
+ *  @param seq      Sequence number
+ *
+ *  @return	BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct proc_dir_entry *entry;
+	int i, j;
+	char hist_entry[50];
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	if (proc_mbt) {
+		priv->dev_proc[seq].proc_entry =
+			proc_mkdir(m_dev->name, proc_mbt);
+		if (!priv->dev_proc[seq].proc_entry) {
+			PRINTM(ERROR, "BT: Could not mkdir %s!\n", m_dev->name);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->dev_proc[seq].hist_entry =
+			proc_mkdir("histogram", priv->dev_proc[seq].proc_entry);
+		if (!priv->dev_proc[seq].hist_entry) {
+			PRINTM(ERROR, "BT: Could not mkdir histogram!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		for (i = 0; i < MAX_ANTENNA_NUM; i++) {
+			priv->hist_proc[i].antenna = i;
+			priv->hist_proc[i].pbt = priv;
+			snprintf(hist_entry, sizeof(hist_entry), "bt-ant%d", i);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			entry = proc_create_data(hist_entry, 0644,
+						 priv->dev_proc[seq].hist_entry,
+						 &histogram_proc_fops,
+						 &priv->hist_proc[i]);
+			if (entry == NULL)
+#else
+			entry = create_proc_entry(hist_entry, 0644,
+						  priv->dev_proc[seq].
+						  hist_entry);
+			if (entry) {
+				entry->data = &priv->hist_proc[i];
+				entry->proc_fops = &histogram_proc_fops;
+			} else
+#endif
+			{
+				PRINTM(MSG,
+				       "Fail to create histogram proc %s\n",
+				       hist_entry);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		priv->dev_proc[seq].pfiles =
+			kmalloc(sizeof(proc_files), GFP_ATOMIC);
+		if (!priv->dev_proc[seq].pfiles) {
+			PRINTM(ERROR,
+			       "BT: Could not alloc memory for pfile!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy((u8 *)priv->dev_proc[seq].pfiles, (u8 *)proc_files,
+		       sizeof(proc_files));
+		priv->dev_proc[seq].num_proc_files = ARRAY_SIZE(proc_files);
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++)
+			priv->dev_proc[seq].pfiles[j].pdata = NULL;
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+			priv->dev_proc[seq].pfiles[j].pdata =
+				kmalloc(priv->dev_proc[seq].pfiles[j].
+					num_items * sizeof(struct item_data),
+					GFP_ATOMIC);
+			if (!priv->dev_proc[seq].pfiles[j].pdata) {
+				PRINTM(ERROR,
+				       "BT: Could not alloc memory for pdata!\n");
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			memcpy((u8 *)priv->dev_proc[seq].pfiles[j].pdata,
+			       (u8 *)proc_files[j].pdata,
+			       priv->dev_proc[seq].pfiles[j].num_items *
+			       sizeof(struct item_data));
+			for (i = 0; i < priv->dev_proc[seq].pfiles[j].num_items;
+			     i++) {
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_DEV)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)&priv->bt_dev;
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_ADAPTER)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)priv->adapter;
+			}
+			priv->dev_proc[seq].pfiles[j].pbt = priv;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			entry = proc_create_data(proc_files[j].name,
+						 S_IFREG | proc_files[j].
+						 fileflag,
+						 priv->dev_proc[seq].proc_entry,
+						 proc_files[j].fops,
+						 &priv->dev_proc[seq].
+						 pfiles[j]);
+			if (entry == NULL)
+#else
+			entry = create_proc_entry(proc_files[j].name,
+						  S_IFREG | proc_files[j].
+						  fileflag,
+						  priv->dev_proc[seq].
+						  proc_entry);
+			if (entry) {
+				entry->data = &priv->dev_proc[seq].pfiles[j];
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
+				entry->owner = THIS_MODULE;
+#endif
+				entry->proc_fops = proc_files[j].fops;
+			} else
+#endif
+				PRINTM(MSG, "BT: Fail to create proc %s\n",
+				       proc_files[j].name);
+		}
+	}
+done:
+	if (ret == BT_STATUS_FAILURE) {
+		if (priv->dev_proc[seq].proc_entry) {
+			remove_proc_entry(m_dev->name, proc_mbt);
+			priv->dev_proc[seq].proc_entry = NULL;
+		}
+		if (priv->dev_proc[seq].pfiles) {
+			for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+				if (priv->dev_proc[seq].pfiles[j].pdata) {
+					kfree(priv->dev_proc[seq].pfiles[j].
+					      pdata);
+					priv->dev_proc[seq].pfiles[j].pdata =
+						NULL;
+				}
+			}
+			kfree(priv->dev_proc[seq].pfiles);
+			priv->dev_proc[seq].pfiles = NULL;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return	N/A
+ */
+void
+bt_proc_remove(bt_private *priv)
+{
+	int j, i;
+	char hist_entry[50];
+	ENTER();
+	PRINTM(INFO, "BT: Remove Proc Interface\n");
+	if (proc_mbt) {
+		for (i = 0; i < MAX_RADIO_FUNC; i++) {
+			if (!priv->dev_proc[i].proc_entry)
+				continue;
+			for (j = 0; j < ARRAY_SIZE(proc_files); j++) {
+				remove_proc_entry(proc_files[j].name,
+						  priv->dev_proc[i].proc_entry);
+			}
+			for (j = 0; j < MAX_ANTENNA_NUM; j++) {
+				snprintf(hist_entry, sizeof(hist_entry),
+					 "bt-ant%d", j);
+				remove_proc_entry(hist_entry,
+						  priv->dev_proc[i].hist_entry);
+			}
+			remove_proc_entry("histogram",
+					  priv->dev_proc[i].proc_entry);
+			remove_proc_entry(priv->bt_dev.m_dev[i].name, proc_mbt);
+			priv->dev_proc[i].proc_entry = NULL;
+
+			if (priv->dev_proc[i].pfiles) {
+				for (j = 0;
+				     j < priv->dev_proc[i].num_proc_files;
+				     j++) {
+					if (priv->dev_proc[i].pfiles[j].pdata) {
+						kfree(priv->dev_proc[i].
+						      pfiles[j].pdata);
+						priv->dev_proc[i].pfiles[j].
+							pdata = NULL;
+					}
+				}
+				kfree(priv->dev_proc[i].pfiles);
+				priv->dev_proc[i].pfiles = NULL;
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function creates proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_root_proc_init(void)
+{
+	PRINTM(INFO, "BT: Create Proc Interface\n");
+	proc_mbt = proc_mkdir("mbt", PROC_DIR);
+	if (!proc_mbt) {
+		PRINTM(ERROR, "BT: Cannot create proc interface\n");
+		return BT_STATUS_FAILURE;
+	}
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS
+ */
+int
+bt_root_proc_remove(void)
+{
+	remove_proc_entry("mbt", PROC_DIR);
+	proc_mbt = NULL;
+	return BT_STATUS_SUCCESS;
+}
diff --git a/bt_sd8997/bt/bt_sdio.h b/bt_sd8997/bt/bt_sdio.h
new file mode 100644
index 0000000..b344e92
--- /dev/null
+++ b/bt_sd8997/bt/bt_sdio.h
@@ -0,0 +1,258 @@
+/** @file bt_sdio.h
+ *  @brief This file contains SDIO (interface) module
+ *  related macros, enum, and structure.
+ *
+ *  Copyright (C) 2007-2017, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_SDIO_H_
+#define _BT_SDIO_H_
+
+#include <linux/irqreturn.h>
+
+/** IRQ return type */
+typedef irqreturn_t IRQ_RET_TYPE;
+/** IRQ return */
+#define IRQ_RET		(return IRQ_HANDLED)
+/** ISR notifier function */
+typedef IRQ_RET_TYPE (*isr_notifier_fn_t) (s32 irq, void *dev_id,
+					   struct pt_regs * reg);
+
+/** SDIO header length */
+#define SDIO_HEADER_LEN			4
+
+/** 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
+/* SD block size can not bigger than 64 due to buf size limit in firmware */
+/** define SD block size for data Tx/Rx */
+#define SD_BLOCK_SIZE			64
+/** define SD block size for firmware download */
+#define SD_BLOCK_SIZE_FW_DL		256
+
+/** Number of blocks for firmware transfer */
+#define FIRMWARE_TRANSFER_NBLOCK	2
+
+/** Firmware ready */
+#define FIRMWARE_READY			0xfedc
+
+/* Bus Interface Control Reg 0x07 */
+/** SD BUS width 1 */
+#define SD_BUS_WIDTH_1			0x00
+/** SD BUS width 4 */
+#define SD_BUS_WIDTH_4			0x02
+/** SD BUS width mask */
+#define SD_BUS_WIDTH_MASK		0x03
+/** Asynchronous interrupt mode */
+#define ASYNC_INT_MODE			0x20
+
+/** magic register */
+#define CARD_MAGIC_REG          0xF0
+/** magic value */
+#define MAGIC_VAL               0x24
+
+/* Host Control Registers */
+/** Host Control Registers : Configuration */
+#define CONFIGURATION_REG		0x00
+/** Host Control Registers : Host without Command 53 finish host*/
+#define HOST_TO_CARD_EVENT		(0x1U << 3)
+/** Host Control Registers : Host terminates Command 53 */
+#define HOST_TERM_CMD53			(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 : Host interrupt RSR */
+#define HOST_INT_RSR_REG		0x04
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR		(0x1U)
+
+/** Host Control Registers : Host interrupt mask */
+#define HOST_INT_MASK_REG		0x08
+
+/** 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)
+/** Enable Host interrupt mask */
+#define HIM_ENABLE			(UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
+/** Disable Host interrupt mask */
+#define	HIM_DISABLE			0xff
+
+/** Host Control Registers : Host interrupt status */
+#define HOST_INTSTATUS_REG		0x0C
+/** Host Control Registers : Upload host interrupt status */
+#define UP_LD_HOST_INT_STATUS		(0x1U)
+/** Host Control Registers : Download host interrupt status */
+#define DN_LD_HOST_INT_STATUS		(0x2U)
+
+/** Host Control Registers : Host Transfer status */
+#define HOST_INT_STATUS_REG		0x58
+/** Host Control Registers : Upload CRC error */
+#define UP_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 : Card to Host Event register */
+#define CARD_STATUS_REG			0x5C
+/** 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 interrupt mask register */
+#define HOST_INTERRUPT_MASK_REG 	0x60
+/** 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 : Card interrupt status register */
+#define CARD_INTERRUPT_STATUS_REG    	0x64
+/** 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 : Card interrupt RSR register */
+#define CARD_INTERRUPT_RSR_REG       	0x68
+/** 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 */
+/** Card Control Registers : Read SQ base address A0 register */
+#define SQ_READ_BASE_ADDRESS_A0_REG  	0xf8
+/** Card Control Registers : Read SQ base address A1 register */
+#define SQ_READ_BASE_ADDRESS_A1_REG  	0xf9
+/** Card Control Registers : Read SQ base address A2 register */
+#define SQ_READ_BASE_ADDRESS_A2_REG  	0x6E
+/** Card Control Registers : Read SQ base address A3 register */
+#define SQ_READ_BASE_ADDRESS_A3_REG  	0x6F
+/** Card Control Registers : Write SQ base address A0 register */
+#define SQ_WRITE_BASE_ADDRESS_A0_REG  	0x70
+/** Card Control Registers : Write SQ base address A1 register */
+#define SQ_WRITE_BASE_ADDRESS_A1_REG  	0x71
+/** Card Control Registers : Write SQ base address A2 register */
+#define SQ_WRITE_BASE_ADDRESS_A2_REG  	0x72
+/** Card Control Registers : Write SQ base address A3 register */
+#define SQ_WRITE_BASE_ADDRESS_A3_REG  	0x73
+
+/** Card Control Registers : Card revision register */
+#define CARD_REVISION_REG            	0xC8
+
+/** Firmware status 0 register (SCRATCH0_0) */
+#define CARD_FW_STATUS0_REG             0xe8
+/** Firmware status 1 register (SCRATCH0_1) */
+#define CARD_FW_STATUS1_REG             0xe9
+/** Rx length register (SCRATCH0_2) */
+#define CARD_RX_LEN_REG                 0xea
+/** Rx unit register (SCRATCH0_3) */
+#define CARD_RX_UNIT_REG                0xeb
+/** 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
+
+/** Card Control Registers : Card OCR 0 register */
+#define CARD_OCR_0_REG			0xD4
+/** Card Control Registers : Card OCR 1 register */
+#define CARD_OCR_1_REG			0xD5
+/** Card Control Registers : Card OCR 3 register */
+#define CARD_OCR_3_REG			0xD6
+/** Card Control Registers : Card config register */
+#define CARD_CONFIG_REG			0xD7
+/** Card Control Registers : Miscellaneous Configuration Register */
+#define CARD_MISC_CFG_REG		0xD8
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT		(0x1U << 4)
+
+/** Card Control Registers : Debug 0 register */
+#define DEBUG_0_REG			0xDC
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0			(0x1U)
+/** Card Control Registers : Debug 1 register */
+#define DEBUG_1_REG			0xDD
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1			(0x1U)
+/** Card Control Registers : Debug 2 register */
+#define DEBUG_2_REG			0xDE
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2			(0x1U)
+/** Card Control Registers : Debug 3 register */
+#define DEBUG_3_REG			0xDF
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3			(0x1U)
+
+/** Host Control Registers : I/O port 0 */
+#define IO_PORT_0_REG			0xE4
+/** Host Control Registers : I/O port 1 */
+#define IO_PORT_1_REG			0xE5
+/** Host Control Registers : I/O port 2 */
+#define IO_PORT_2_REG			0xE6
+
+struct sdio_mmc_card {
+	/** sdio_func structure pointer */
+	struct sdio_func *func;
+	/** bt_private structure pointer */
+	bt_private *priv;
+};
+
+/** DMA alignment value */
+#define DMA_ALIGNMENT	64
+/** 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))
+
+/** This function read cmd52 register */
+int sd_write_reg(bt_private *priv, int reg, u8 val);
+/** This function write cmd52 value to register */
+int sd_read_reg(bt_private *priv, int reg, u8 *data);
+/** This function reads the Cmd52 value in dev structure */
+int sd_read_cmd52_val(bt_private *priv);
+/** This function updates card reg based on the Cmd52 value in dev structure */
+int sd_write_cmd52_val(bt_private *priv, int func, int reg, int val);
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** This function tells lower driver that BT is suspended */
+void bt_is_suspended(bt_private *priv);
+#endif
+#endif
+#endif
+#endif /* _BT_SDIO_H_ */
diff --git a/bt_sd8997/bt/bt_sdiommc.c b/bt_sd8997/bt/bt_sdiommc.c
new file mode 100644
index 0000000..2bc4cdc
--- /dev/null
+++ b/bt_sd8997/bt/bt_sdiommc.c
@@ -0,0 +1,1935 @@
+/** @file bt_sdiommc.c
+ *  @brief This file contains SDIO IF (interface) module
+ *  related functions.
+ *
+ * Copyright (C) 2007-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/mmc/sdio_func.h>
+#include        <linux/mmc/sdio.h>
+#include        <linux/mmc/card.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** define marvell vendor id */
+#define MARVELL_VENDOR_ID 0x02df
+
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD53_RETRY 	3
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD52_RETRY     3
+/** Firmware name */
+static char *fw_name;
+/** fw serial download flag */
+extern int bt_fw_serial;
+/** request firmware nowait */
+int bt_req_fw_nowait;
+static int multi_fn = BIT(2);
+
+#define SD8997_FW_NAME "mrvl/sdsd8997_combo_v4.bin"
+#define SD8997_BT_FW_NAME "mrvl/sd8997_bt_v4.bin"
+#define DEFAULT_FW_NAME "mrvl/sdsd8997_combo_v4.bin"
+#define DEFAULT_BT_FW_NAME "mrvl/sd8997_bt_v4.bin"
+
+/** Function number 2 */
+#define FN2			2
+/** Device ID for SD8997 FN2 */
+#define SD_DEVICE_ID_8997_BT_FN2    0x9142
+
+/** Array of SDIO device ids when multi_fn=0x12 */
+static const struct sdio_device_id bt_ids[] = {
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8997_BT_FN2)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(sdio, bt_ids);
+
+/********************************************************
+		Global Variables
+********************************************************/
+/** unregiser bus driver flag */
+static u8 unregister;
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+extern int mbt_pm_keep_power;
+#endif
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief This function gets rx_unit value
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_get_rx_unit(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_unit_reg = CARD_RX_UNIT_REG;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_unit_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		priv->bt_dev.rx_unit = reg;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads fwstatus registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_read_firmware_status(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 fws0;
+	u8 fws1;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = CARD_FW_STATUS0_REG;
+	u8 card_fw_status1_reg = CARD_FW_STATUS1_REG;
+
+	ENTER();
+
+	fws0 = sdio_readb(card->func, card_fw_status0_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	fws1 = sdio_readb(card->func, card_fw_status1_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	*dat = (((u16) fws1) << 8) | fws0;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function reads rx length
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sd_read_rx_len(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_len_reg = CARD_RX_LEN_REG;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_len_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		*dat = (u16) reg << priv->bt_dev.rx_unit;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables the host interrupts mask
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_enable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = HOST_INT_MASK_REG;
+
+	ENTER();
+
+	sdio_writeb(card->func, mask, host_int_mask_reg, &ret);
+	if (ret) {
+		PRINTM(WARN, "BT: Unable to enable the host interrupt!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function disables the host interrupts mask.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sd_disable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_FAILURE;
+	u8 host_int_mask;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = HOST_INT_MASK_REG;
+
+	ENTER();
+
+	/* Read back the host_int_mask register */
+	host_int_mask = sdio_readb(card->func, host_int_mask_reg, &ret);
+	if (ret)
+		goto done;
+
+	/* Update with the mask and write back to the register */
+	host_int_mask &= ~mask;
+	sdio_writeb(card->func, host_int_mask, host_int_mask_reg, &ret);
+	if (ret < 0) {
+		PRINTM(WARN, "BT: Unable to diable the host interrupt!\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function polls the card status register
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param bits     the bit mask
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_poll_card_status(bt_private *priv, u8 bits)
+{
+	int tries;
+	int rval;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 cs;
+	u8 card_status_reg = CARD_STATUS_REG;
+
+	ENTER();
+
+	for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
+		cs = sdio_readb(card->func, card_status_reg, &rval);
+		if (rval != 0)
+			break;
+		if (rval == 0 && (cs & bits) == bits) {
+			LEAVE();
+			return BT_STATUS_SUCCESS;
+		}
+		udelay(1);
+	}
+	PRINTM(ERROR,
+	       "BT: sdio_poll_card_status failed (%d), tries = %d, cs = 0x%x\n",
+	       rval, tries, cs);
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_cmd52_val(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 func, reg, val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	func = priv->bt_dev.cmd52_func;
+	reg = priv->bt_dev.cmd52_reg;
+	sdio_claim_host(card->func);
+	if (func)
+		val = sdio_readb(card->func, reg, &ret);
+	else
+		val = sdio_f0_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	if (ret) {
+		PRINTM(ERROR, "BT: Cannot read value from func %d reg %d\n",
+		       func, reg);
+	} else {
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param func     Stores func variable
+ *  @param reg      Stores reg variable
+ *  @param val      Stores val variable
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_cmd52_val(bt_private *priv, int func, int reg, int val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	if (val >= 0) {
+		/* Perform actual write only if val is provided */
+		sdio_claim_host(card->func);
+		if (func)
+			sdio_writeb(card->func, val, reg, &ret);
+		else
+			sdio_f0_writeb(card->func, val, reg, &ret);
+		sdio_release_host(card->func);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: Cannot write value (0x%x) to func %d reg %d\n",
+			       val, func, reg);
+			goto done;
+		}
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	/* Save current func and reg for future read */
+	priv->bt_dev.cmd52_func = func;
+	priv->bt_dev.cmd52_reg = reg;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to write
+ *  @param val      value
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_reg(bt_private *priv, int reg, u8 val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, val, reg, &ret);
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to read
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_reg(bt_private *priv, int reg, u8 *data)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	val = sdio_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	*data = val;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function probes the card
+ *
+ *  @param func    A pointer to sdio_func structure.
+ *  @param id      A pointer to structure sdio_device_id
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_probe_card(struct sdio_func *func, const struct sdio_device_id *id)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *card = NULL;
+
+	ENTER();
+
+	PRINTM(INFO, "BT: vendor=0x%x,device=0x%x,class=%d,fn=%d\n", id->vendor,
+	       id->device, id->class, func->num);
+	card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
+	if (!card) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	card->func = func;
+#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_disable_func(func);
+		sdio_release_host(func);
+		PRINTM(FATAL, "BT: sdio_enable_func() failed: ret=%d\n", ret);
+		kfree(card);
+		LEAVE();
+		return -EIO;
+	}
+	sdio_release_host(func);
+	priv = bt_add_card(card);
+	if (!priv) {
+		sdio_claim_host(func);
+		sdio_disable_func(func);
+		sdio_release_host(func);
+		ret = BT_STATUS_FAILURE;
+		kfree(card);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param pollnum  Number of times to poll fw status
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_verify_fw_download(bt_private *priv, int pollnum)
+{
+	int ret = BT_STATUS_FAILURE;
+	u16 firmwarestat = 0;
+	int tries;
+
+	ENTER();
+
+	/* Wait for firmware initialization event */
+	for (tries = 0; tries < pollnum; tries++) {
+		if (sd_read_firmware_status(priv, &firmwarestat) < 0)
+			continue;
+		if (firmwarestat == FIRMWARE_READY) {
+			PRINTM(MSG, "BT FW is active(%d)\n", tries);
+			ret = BT_STATUS_SUCCESS;
+			break;
+		}
+		mdelay(100);
+	}
+	if ((pollnum > 1) && (ret != BT_STATUS_SUCCESS)) {
+		PRINTM(ERROR,
+		       "Fail to poll firmware status: firmwarestat=0x%x\n",
+		       firmwarestat);
+		bt_dump_sdio_regs(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Transfers firmware to card
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @param fw        A Pointer to fw image
+ *  @param fw_len    fw image len
+ *  @return          BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_init_fw_dpc(bt_private *priv, u8 *fw, int fw_len)
+{
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 *firmware = fw;
+	int firmwarelen = fw_len;
+	u8 base0;
+	u8 base1;
+	int ret = BT_STATUS_SUCCESS;
+	int offset;
+	void *tmpfwbuf = NULL;
+	int tmpfwbufsz;
+	u8 *fwbuf;
+	u16 len;
+	int txlen = 0;
+	int tx_blocks = 0;
+	int i = 0;
+	int tries = 0;
+	u8 sq_read_base_address_a0_reg = SQ_READ_BASE_ADDRESS_A0_REG;
+	u8 sq_read_base_address_a1_reg = SQ_READ_BASE_ADDRESS_A1_REG;
+
+	ENTER();
+
+	PRINTM(INFO, "BT: Downloading FW image (%d bytes)\n", firmwarelen);
+
+	tmpfwbufsz = BT_UPLD_SIZE + DMA_ALIGNMENT;
+	tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
+	if (!tmpfwbuf) {
+		PRINTM(ERROR,
+		       "BT: Unable to allocate buffer for firmware. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	/* Ensure aligned firmware buffer */
+	fwbuf = (u8 *)ALIGN_ADDR(tmpfwbuf, DMA_ALIGNMENT);
+
+	/* Perform firmware data transfer */
+	offset = 0;
+	do {
+		/* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits
+		 */
+		ret = sd_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: FW download with helper poll status timeout @ %d\n",
+			       offset);
+			goto done;
+		}
+		/* More data? */
+		if (offset >= firmwarelen)
+			break;
+
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			base0 = sdio_readb(card->func,
+					   sq_read_base_address_a0_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE0 register read failed:"
+				       " base0=0x%04X(%d). Terminating download\n",
+				       base0, base0);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			base1 = sdio_readb(card->func,
+					   sq_read_base_address_a1_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE1 register read failed:"
+				       " base1=0x%04X(%d). Terminating download\n",
+				       base1, base1);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			len = (((u16) base1) << 8) | base0;
+
+			if (len != 0)
+				break;
+			udelay(10);
+		}
+
+		if (len == 0)
+			break;
+		else if (len > BT_UPLD_SIZE) {
+			PRINTM(FATAL,
+			       "BT: FW download failure @ %d, invalid length %d\n",
+			       offset, len);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	/** ignore CRC check before download the first packet */
+		if (offset == 0 && (len & BIT(0)))
+			len &= ~BIT(0);
+		txlen = len;
+
+		if (len & BIT(0)) {
+			i++;
+			if (i >= MAX_CMD53_RETRY) {
+				PRINTM(FATAL,
+				       "BT: FW download failure @ %d, over max retry count\n",
+				       offset);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(ERROR,
+			       "BT: FW CRC error indicated by the helper:"
+			       " len = 0x%04X, txlen = %d\n", len, txlen);
+			len &= ~BIT(0);
+
+			PRINTM(ERROR, "BT: retry: %d, offset %d\n", i, offset);
+			/* Setting this to 0 to resend from same offset */
+			txlen = 0;
+		} else {
+			i = 0;
+
+			/* Set blocksize to transfer - checking for last block */
+			if (firmwarelen - offset < txlen)
+				txlen = firmwarelen - offset;
+
+			PRINTM(INFO, ".");
+
+			tx_blocks =
+				(txlen + SD_BLOCK_SIZE_FW_DL -
+				 1) / SD_BLOCK_SIZE_FW_DL;
+
+			/* Copy payload to buffer */
+			memcpy(fwbuf, &firmware[offset], txlen);
+		}
+
+		/* Send data */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, fwbuf,
+				   tx_blocks * SD_BLOCK_SIZE_FW_DL);
+
+		if (ret < 0) {
+			PRINTM(ERROR,
+			       "BT: FW download, write iomem (%d) failed @ %d\n",
+			       i, offset);
+			sdio_writeb(card->func, 0x04, CONFIGURATION_REG, &ret);
+			if (ret)
+				PRINTM(ERROR, "write ioreg failed (CFG)\n");
+		}
+
+		offset += txlen;
+	} while (TRUE);
+
+	PRINTM(MSG, "BT: FW download over, size %d bytes\n", offset);
+
+	ret = BT_STATUS_SUCCESS;
+done:
+	kfree(tmpfwbuf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *
+ * @param fw_firmware  A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_request_fw_dpc(const struct firmware *fw_firmware, void *context)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = (bt_private *)context;
+	struct sdio_mmc_card *card = NULL;
+	struct m_dev *m_dev_bt = NULL;
+	struct timeval tstamp;
+
+	ENTER();
+
+	m_dev_bt = &priv->bt_dev.m_dev[BT_SEQ];
+
+	if ((priv == NULL) || (priv->adapter == NULL) ||
+	    (priv->bt_dev.card == NULL) || (m_dev_bt == NULL)
+		) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	if (!fw_firmware) {
+		do_gettimeofday(&tstamp);
+		if (tstamp.tv_sec >
+		    (priv->req_fw_time.tv_sec + REQUEST_FW_TIMEOUT)) {
+			PRINTM(ERROR,
+			       "BT: No firmware image found. Skipping download\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		PRINTM(ERROR,
+		       "BT: No firmware image found! Retrying download\n");
+		/* Wait a second here before calling the callback again */
+		os_sched_timeout(1000);
+		sd_download_firmware_w_helper(priv);
+		LEAVE();
+		return ret;
+	}
+
+	priv->firmware = fw_firmware;
+
+	if (BT_STATUS_FAILURE ==
+	    sd_init_fw_dpc(priv, (u8 *)priv->firmware->data,
+			   priv->firmware->size)) {
+		PRINTM(ERROR,
+		       "BT: sd_init_fw_dpc failed (download fw with nowait: %d). Terminating download\n",
+		       bt_req_fw_nowait);
+		sdio_release_host(card->func);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* check if the fimware is downloaded successfully or not */
+	if (sd_verify_fw_download(priv, MAX_FIRMWARE_POLL_TRIES)) {
+		PRINTM(ERROR, "BT: FW failed to be active in time!\n");
+		ret = BT_STATUS_FAILURE;
+		sdio_release_host(card->func);
+		goto done;
+	}
+	sdio_release_host(card->func);
+	sd_enable_host_int(priv);
+	if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+		PRINTM(ERROR,
+		       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	LEAVE();
+	return ret;
+
+done:
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	/* For synchronous download cleanup will be done in add_card */
+	if (!bt_req_fw_nowait)
+		return ret;
+	PRINTM(INFO, "unregister device\n");
+	sbi_unregister_dev(priv);
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+	bt_proc_remove(priv);
+	clean_up_m_devs(priv);
+	bt_free_adapter(priv);
+	bt_priv_put(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware     A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             None
+ **/
+static void
+sd_request_fw_callback(const struct firmware *firmware, void *context)
+{
+	ENTER();
+	sd_request_fw_dpc(firmware, context);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function downloads firmware image to the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sd_download_firmware_w_helper(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	int err;
+	char *cur_fw_name = NULL;
+
+	ENTER();
+
+	cur_fw_name = fw_name;
+	if (fw_name == NULL) {
+		if (!bt_fw_serial || priv->fw_reload || bt_fw_reload)
+			cur_fw_name = DEFAULT_BT_FW_NAME;
+		else
+			cur_fw_name = DEFAULT_FW_NAME;
+	}
+
+	PRINTM(MSG, "BT Request firmware: %s\n", cur_fw_name);
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      sd_request_fw_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#endif
+#endif
+		if (ret < 0)
+			PRINTM(FATAL,
+			       "BT: request_firmware_nowait() failed, error code = %#x\n",
+			       ret);
+	} else {
+		err = request_firmware(&priv->firmware, cur_fw_name,
+				       priv->hotplug_device);
+		if (err < 0) {
+			PRINTM(FATAL,
+			       "BT: request_firmware() failed, error code = %#x\n",
+			       err);
+			ret = BT_STATUS_FAILURE;
+		} else
+			ret = sd_request_fw_dpc(priv->firmware, priv);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads data from the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_card_to_host(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u16 buf_len = 0;
+	int buf_block_len;
+	int blksz;
+	struct sk_buff *skb = NULL;
+	u32 type;
+	u8 *payload = NULL;
+	struct hci_dev *hdev = NULL;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int i = 0;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type == BLUEZ_SPEC)
+		hdev = (struct hci_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer;
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	do {
+		/* Read the length of data to be transferred */
+		ret = sd_read_rx_len(priv, &buf_len);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR, "BT: Read scratch reg failed (%d)\n", i);
+			if (i >= MAX_CMD52_RETRY) {
+				ret = BT_STATUS_FAILURE;
+				goto exit;
+			}
+			udelay(20);
+		}
+	}
+	while (ret == BT_STATUS_FAILURE);
+
+	/* Allocate buffer */
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (buf_len + blksz - 1) / blksz;
+	if (buf_len <= BT_HEADER_LEN ||
+	    (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+		PRINTM(ERROR, "BT: card_to_host, invalid packet length: %d\n",
+		       buf_len);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	skb = bt_skb_alloc(buf_block_len * blksz + DMA_ALIGNMENT, GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		goto exit;
+	}
+	if ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)) {
+		skb_put(skb,
+			DMA_ALIGNMENT -
+			((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+		skb_pull(skb,
+			 DMA_ALIGNMENT -
+			 ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+	}
+
+	payload = skb->data;
+	i = 0;
+	do {
+		ret = sdio_readsb(card->func, payload, priv->bt_dev.ioport,
+				  buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: card_to_host, read iomem (%d) failed: %d\n",
+			       i, ret);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY) {
+				kfree_skb(skb);
+				skb = NULL;
+				goto exit;
+			}
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	/* This is SDIO specific header length: byte[2][1][0], * type: byte[3]
+	   (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
+	buf_len = payload[0];
+	buf_len |= (u16) payload[1] << 8;
+	type = payload[3];
+	PRINTM(DATA, "BT: SDIO Blk Rd %s: len=%d type=%d\n", hdev->name,
+	       buf_len, type);
+	if (buf_len > buf_block_len * blksz) {
+		PRINTM(ERROR,
+		       "BT: Drop invalid rx pkt, len in hdr=%d, cmd53 length=%d\n",
+		       buf_len, buf_block_len * blksz);
+		ret = BT_STATUS_FAILURE;
+		kfree_skb(skb);
+		skb = NULL;
+		goto exit;
+	}
+	DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Rd", payload, buf_len);
+	switch (type) {
+	case HCI_ACLDATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (hdev) {
+			skb->dev = (void *)hdev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+			hci_recv_frame(skb);
+#else
+			hci_recv_frame(hdev, skb);
+#endif
+			hdev->stat.byte_rx += buf_len;
+		}
+		break;
+	case HCI_SCODATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (hdev) {
+			skb->dev = (void *)hdev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+			hci_recv_frame(skb);
+#else
+			hci_recv_frame(hdev, skb);
+#endif
+			hdev->stat.byte_rx += buf_len;
+		}
+		break;
+	case HCI_EVENT_PKT:
+		/** add EVT Demux */
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (BT_STATUS_SUCCESS == check_evtpkt(priv, skb))
+			break;
+		switch (skb->data[0]) {
+		case 0x0E:
+			/** cmd complete */
+			if (hdev) {
+				skb->dev = (void *)hdev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+				hci_recv_frame(skb);
+#else
+				hci_recv_frame(hdev, skb);
+#endif
+				hdev->stat.byte_rx += buf_len;
+			}
+			break;
+		case 0x0F:
+			/** cmd status */
+			/** BT cmd status */
+			if (hdev) {
+				skb->dev = (void *)hdev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+				hci_recv_frame(skb);
+#else
+				hci_recv_frame(hdev, skb);
+#endif
+				hdev->stat.byte_rx += buf_len;
+			}
+			break;
+		case 0xFF:
+			/** Vendor specific pkt */
+			/** BT EVT */
+			if (hdev) {
+				skb->dev = (void *)hdev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+				hci_recv_frame(skb);
+#else
+				hci_recv_frame(hdev, skb);
+#endif
+				hdev->stat.byte_rx += buf_len;
+			}
+			break;
+		default:
+			/** BT EVT */
+			if (hdev) {
+				skb->dev = (void *)hdev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+				hci_recv_frame(skb);
+#else
+				hci_recv_frame(hdev, skb);
+#endif
+				hdev->stat.byte_rx += buf_len;
+			}
+			break;
+		}
+		break;
+	case MRVL_VENDOR_PKT:
+		/* Just think here need to back compatible FM */
+		bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (hdev) {
+			if (BT_STATUS_SUCCESS != bt_process_event(priv, skb)) {
+				skb->dev = (void *)hdev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+				hci_recv_frame(skb);
+#else
+				hci_recv_frame(hdev, skb);
+#endif
+				hdev->stat.byte_rx += buf_len;
+			}
+		}
+
+		break;
+	default:
+		/* Driver specified event and command resp should be handle
+		   here */
+		PRINTM(INFO, "BT: Unknown PKT type:%d\n", type);
+		kfree_skb(skb);
+		skb = NULL;
+		break;
+	}
+exit:
+	if (ret) {
+		if (hdev)
+			hdev->stat.err_rx++;
+		PRINTM(ERROR, "error when recv pkt!\n");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes the card
+ *
+ *  @param func    A pointer to sdio_func structure
+ *  @return        N/A
+ */
+static void
+sd_remove_card(struct sdio_func *func)
+{
+	struct sdio_mmc_card *card;
+
+	ENTER();
+
+	if (func) {
+		card = sdio_get_drvdata(func);
+		if (card) {
+			if (!unregister && card->priv) {
+				PRINTM(INFO, "BT: card removed from sd slot\n");
+				((bt_private *)(card->priv))->adapter->
+					SurpriseRemoved = TRUE;
+			}
+			bt_remove_card(card->priv);
+			kfree(card);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the interrupt.
+ *
+ *  @param func  A pointer to sdio_func structure
+ *  @return      N/A
+ */
+static void
+sd_interrupt(struct sdio_func *func)
+{
+	bt_private *priv;
+	struct m_dev *m_dev = NULL;
+	struct sdio_mmc_card *card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 ireg = 0;
+	u8 host_intstatus_reg = HOST_INTSTATUS_REG;
+
+	ENTER();
+
+	card = sdio_get_drvdata(func);
+	if (!card || !card->priv) {
+		PRINTM(INFO,
+		       "BT: %s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
+		       __func__, func, card);
+		LEAVE();
+		return;
+	}
+	priv = card->priv;
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	ret = sdio_readsb(card->func, priv->adapter->hw_regs, 0, SD_BLOCK_SIZE);
+	if (ret) {
+		PRINTM(ERROR,
+		       "BT: sdio_read_ioreg: cmd53 read int status register failed %d\n",
+		       ret);
+		goto done;
+	}
+	ireg = priv->adapter->hw_regs[host_intstatus_reg];
+	if (ret) {
+		PRINTM(ERROR,
+		       "BT: sdio_read_ioreg: CMD52 read int status register failed %d\n",
+		       ret);
+		goto done;
+	}
+	if (ireg != 0) {
+		/*
+		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+		 * Clear the interrupt status register and re-enable
+		 * the interrupt
+		 */
+		PRINTM(INTR, "BT: INT %s: sdio_ireg = 0x%x\n", m_dev->name,
+		       ireg);
+		priv->adapter->irq_recv = ireg;
+	} else {
+		PRINTM(ERROR, "BT: ERR: ireg=0\n");
+	}
+	OS_INT_DISABLE;
+	priv->adapter->sd_ireg |= ireg;
+	OS_INT_RESTORE;
+	bt_interrupt(m_dev);
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interfaces are present
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @param val    Winner status (0: winner)
+ *  @return       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_check_winner_status(bt_private *priv, u8 *val)
+{
+
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = CARD_FW_STATUS0_REG;
+
+	ENTER();
+	winner = sdio_readb(cardp->func, card_fw_status0_reg, &ret);
+	if (ret != BT_STATUS_SUCCESS) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** @brief This function tells lower driver that BT is suspended
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        None
+ */
+void
+bt_is_suspended(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	priv->adapter->is_suspended = TRUE;
+	sdio_func_suspended(card->func);
+}
+#endif
+
+/** @brief This function handles client driver suspend
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+int
+bt_sdio_suspend(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+	struct hci_dev *hcidev;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is suspended\n",
+		       sdio_func_id(func));
+		return -ENOSYS;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO suspend\n", m_dev->name);
+	hcidev = (struct hci_dev *)m_dev->dev_pointer;
+	hci_suspend_dev(hcidev);
+	skb_queue_purge(&priv->adapter->tx_queue);
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+#ifdef BLE_WAKEUP
+		/** Set BLE Wake up pattern */
+		if (BT_STATUS_SUCCESS != bt_config_ble_wakeup(priv))
+			PRINTM(ERROR, "BT: Set ble wakeup pattern fail!\n");
+#endif
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+			PRINTM(CMD, "BT: HS not actived, suspend fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to suspend!\n");
+			}
+		}
+	}
+
+	priv->adapter->is_suspended = TRUE;
+
+	LEAVE();
+	/* We will keep the power when hs enabled successfully */
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state == HS_ACTIVATED)) {
+#ifdef MMC_PM_SKIP_RESUME_PROBE
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER and "
+		       "MMC_PM_SKIP_RESUME_PROBE\n");
+		return sdio_set_host_pm_flags(func,
+					      MMC_PM_KEEP_POWER |
+					      MMC_PM_SKIP_RESUME_PROBE);
+#else
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER\n");
+		return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+#endif
+	} else {
+		PRINTM(CMD, "BT: suspend without MMC_PM_KEEP_POWER\n");
+		return BT_STATUS_SUCCESS;
+	}
+}
+
+void
+bt_sdio_shutdown(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: shutdown: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is shutdown\n",
+		       sdio_func_id(func));
+		return;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return;
+	}
+
+	priv = cardp->priv;
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+#ifdef BLE_WAKEUP
+		/** Set BLE Wake up pattern */
+		if (BT_STATUS_SUCCESS != bt_config_ble_wakeup(priv))
+			PRINTM(ERROR, "BT: Set ble wakeup pattern fail!\n");
+#endif
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+			PRINTM(CMD, "BT: HS not actived, shutdown fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to shutdown!\n");
+			}
+		}
+	}
+	LEAVE();
+}
+
+/** @brief This function handles client driver resume
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_sdio_resume(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+	struct hci_dev *hcidev;
+
+	ENTER();
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: resume: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+	priv->adapter->is_suspended = FALSE;
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO resume\n", m_dev->name);
+	hcidev = (struct hci_dev *)m_dev->dev_pointer;
+	hci_resume_dev(hcidev);
+	sbi_wakeup_firmware(priv);
+	priv->adapter->hs_state = HS_DEACTIVATED;
+	PRINTM(CMD, "BT:%s: HS DEACTIVATED in Resume!\n", m_dev->name);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+#endif
+#endif
+
+/********************************************************
+		Global Functions
+********************************************************/
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+static const struct dev_pm_ops bt_sdio_pm_ops = {
+	.suspend = bt_sdio_suspend,
+	.resume = bt_sdio_resume,
+};
+#endif
+#endif
+static struct sdio_driver sdio_bt = {
+	.name = "sdio_bt",
+	.id_table = bt_ids,
+	.probe = sd_probe_card,
+	.remove = sd_remove_card,
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+	.drv = {
+		.pm = &bt_sdio_pm_ops,
+		.shutdown = bt_sdio_shutdown,
+		}
+#endif
+#endif
+};
+
+/**
+ *  @brief This function registers the bt module in bus driver.
+ *
+ *  @return	   An int pointer that keeps returned value
+ */
+int *
+sbi_register(void)
+{
+	int *ret;
+
+	ENTER();
+
+	if (sdio_register_driver(&sdio_bt) != 0) {
+		PRINTM(FATAL, "BT: SD Driver Registration Failed\n");
+		LEAVE();
+		return NULL;
+	} else
+		ret = (int *)1;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function de-registers the bt module in bus driver.
+ *
+ *  @return        N/A
+ */
+void
+sbi_unregister(void)
+{
+	ENTER();
+	unregister = TRUE;
+	sdio_unregister_driver(&sdio_bt);
+	LEAVE();
+}
+
+/**
+ *  @brief This function registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_dev(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	u8 chiprev;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	struct sdio_func *func;
+	u8 host_intstatus_reg = HOST_INTSTATUS_REG;
+	u8 host_int_rsr_reg = HOST_INT_RSR_REG;
+	u8 card_misc_cfg_reg = CARD_MISC_CFG_REG;
+	u8 card_revision_reg = CARD_REVISION_REG;
+	u8 io_port_0_reg = IO_PORT_0_REG;
+	u8 io_port_1_reg = IO_PORT_1_REG;
+	u8 io_port_2_reg = IO_PORT_2_REG;
+	u8 card_magic_reg = CARD_MAGIC_REG;
+	u8 magic_val = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: Error: card or function is NULL!\n");
+		goto failed;
+	}
+	func = card->func;
+	priv->hotplug_device = &func->dev;
+
+	/* Initialize the private structure */
+	strncpy(priv->bt_dev.name, "bt_sdio0", sizeof(priv->bt_dev.name));
+	priv->bt_dev.ioport = 0;
+	priv->bt_dev.fn = func->num;
+
+	sdio_claim_host(func);
+	ret = sdio_claim_irq(func, sd_interrupt);
+	if (ret) {
+		PRINTM(FATAL, ": sdio_claim_irq failed: ret=%d\n", ret);
+		goto release_host;
+	}
+	ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
+	if (ret) {
+		PRINTM(FATAL, ": %s: cannot set SDIO block size\n", __func__);
+		goto release_irq;
+	}
+
+	/* read Revision Register to get the chip revision number */
+	chiprev = sdio_readb(func, card_revision_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_REVISION_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->chip_rev = chiprev;
+	PRINTM(INFO, "revision=%#x\n", chiprev);
+
+	magic_val = sdio_readb(func, card_magic_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_MAGIC_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->magic_val = magic_val;
+	PRINTM(INFO, "magic_val=%#x\n", magic_val);
+
+	/*
+	 * Read the HOST_INTSTATUS_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.
+	 */
+	reg = sdio_readb(func, host_intstatus_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+
+	/* Read the IO port */
+	reg = sdio_readb(func, io_port_0_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= reg;
+
+	reg = sdio_readb(func, io_port_1_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 8);
+
+	reg = sdio_readb(func, io_port_2_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 16);
+
+	PRINTM(INFO, ": SDIO FUNC%d IO port: 0x%x\n", priv->bt_dev.fn,
+	       priv->bt_dev.ioport);
+
+#define SDIO_INT_MASK       0x3F
+	/* Set Host interrupt reset to read to clear */
+	reg = sdio_readb(func, host_int_rsr_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	sdio_writeb(func, reg | SDIO_INT_MASK, host_int_rsr_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	/* Set auto re-enable */
+	reg = sdio_readb(func, card_misc_cfg_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	sdio_writeb(func, reg | AUTO_RE_ENABLE_INT, card_misc_cfg_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+
+	sdio_set_drvdata(func, card);
+	sdio_release_host(func);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+release_irq:
+	sdio_release_irq(func);
+release_host:
+	sdio_release_host(func);
+failed:
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function de-registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_unregister_dev(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	if (card && card->func) {
+		sdio_claim_host(card->func);
+		sdio_release_irq(card->func);
+		sdio_disable_func(card->func);
+		sdio_release_host(card->func);
+		sdio_set_drvdata(card->func, NULL);
+	}
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function enables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_enable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sd_enable_host_int_mask(priv, HIM_ENABLE);
+	sd_get_rx_unit(priv);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function disables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sd_disable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sd_disable_host_int_mask(priv, HIM_DISABLE);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param payload A pointer to the data/cmd buffer
+ *  @param nb      Length of data/cmd
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	int ret = BT_STATUS_SUCCESS;
+	int buf_block_len;
+	int blksz;
+	int i = 0;
+	u8 *buf = NULL;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	buf = payload;
+
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (nb + blksz - 1) / blksz;
+	/* Allocate buffer and copy payload */
+	if ((t_ptr)payload & (DMA_ALIGNMENT - 1)) {
+		if (nb > MAX_TX_BUF_SIZE) {
+			PRINTM(ERROR, "BT: Invalid tx packet, size=%d\n", nb);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		}
+		/* Ensure 8-byte aligned CMD buffer */
+		buf = priv->adapter->tx_buf;
+		memcpy(buf, payload, nb);
+	}
+	sdio_claim_host(card->func);
+	do {
+		/* Transfer data to card */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, buf,
+				   buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: host_to_card, write iomem (%d) failed: %d\n",
+			       i, ret);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY)
+				goto exit;
+		} else {
+			PRINTM(DATA, "BT: SDIO Blk Wr %s: len=%d\n",
+			       m_dev->name, nb);
+			DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Wr", payload, nb);
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	priv->bt_dev.tx_dnld_rdy = FALSE;
+exit:
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_download_fw(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	sdio_claim_host(card->func);
+	if (BT_STATUS_SUCCESS == sd_verify_fw_download(priv, 1)) {
+		PRINTM(MSG, "BT: FW already downloaded!\n");
+		sdio_release_host(card->func);
+		sd_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+	/* Check if other interface is downloading */
+	ret = sd_check_winner_status(priv, &winner);
+	if (ret == BT_STATUS_FAILURE) {
+		PRINTM(FATAL, "BT read winner status failed!\n");
+		goto done;
+	}
+	if (winner) {
+		PRINTM(MSG, "BT is not the winner (0x%x). Skip FW download\n",
+		       winner);
+		/* check if the fimware is downloaded successfully or not */
+		if (sd_verify_fw_download(priv, MAX_MULTI_INTERFACE_POLL_TRIES)) {
+			PRINTM(FATAL, "BT: FW failed to be active in time!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		sdio_release_host(card->func);
+		sd_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+
+	do_gettimeofday(&priv->req_fw_time);
+	/* Download the main firmware via the helper firmware */
+	if (sd_download_firmware_w_helper(priv)) {
+		PRINTM(INFO, "BT: FW download failed!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+	goto exit;
+done:
+	sdio_release_host(card->func);
+exit:
+	LEAVE();
+	return ret;
+err_register:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the interrupt status and handle it accordingly.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_get_int_status(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 sdio_ireg = 0;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	OS_INT_DISABLE;
+	sdio_ireg = priv->adapter->sd_ireg;
+	priv->adapter->sd_ireg = 0;
+	OS_INT_RESTORE;
+	sdio_claim_host(card->func);
+	priv->adapter->irq_done = sdio_ireg;
+	if (sdio_ireg & DN_LD_HOST_INT_STATUS) {	/* tx_done INT */
+		if (priv->bt_dev.tx_dnld_rdy) {	/* tx_done already received */
+			PRINTM(INFO,
+			       "BT: warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
+			       priv->bt_dev.tx_dnld_rdy, sdio_ireg);
+		} else {
+			priv->bt_dev.tx_dnld_rdy = TRUE;
+		}
+	}
+	if (sdio_ireg & UP_LD_HOST_INT_STATUS)
+		sd_card_to_host(priv);
+
+	ret = BT_STATUS_SUCCESS;
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function wakeup firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sbi_wakeup_firmware(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
+	sdio_release_host(card->func);
+	PRINTM(CMD, "BT wake up firmware\n");
+
+	LEAVE();
+	return ret;
+}
+
+#define INIT_START_REG  0xF1
+#define INIT_END_REG 0xF6
+
+/** @brief This function dump the SDIO register
+ *
+ *  @param priv     A Pointer to the bt_private structure
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_sdio_regs(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+	char buf[256], *ptr;
+	u8 loop, func, data;
+	unsigned int reg, reg_start, reg_end;
+	u8 loop_num = 2;
+	unsigned int init_reg_start = 0;
+	unsigned int init_reg_end = 0;
+	init_reg_start = INIT_START_REG;
+	init_reg_end = INIT_END_REG;
+
+	if (priv->adapter->ps_state)
+		sbi_wakeup_firmware(priv);
+
+	sdio_claim_host(card->func);
+	for (loop = 0; loop < loop_num; 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 {
+			func = 2;
+			reg_start = 0;
+			reg_end = 0x09;
+		}
+		ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", func, reg_start,
+			       reg_end);
+		for (reg = reg_start; reg <= reg_end;) {
+			if (func == 0)
+				data = sdio_f0_readb(card->func, reg, &ret);
+			else
+				data = sdio_readb(card->func, reg, &ret);
+			if (!ret)
+				ptr += sprintf(ptr, "%02x ", data);
+			else {
+				ptr += sprintf(ptr, "ERR");
+				break;
+			}
+			reg++;
+		}
+		PRINTM(MSG, "%s\n", buf);
+	}
+
+	if (init_reg_start) {
+		memset(buf, 0, sizeof(buf));
+		ptr = buf;
+		ptr += sprintf(ptr, "Init Status Reg (%#x-%#x): ",
+			       init_reg_start, init_reg_end);
+		for (reg = init_reg_start; reg <= init_reg_end;) {
+			data = sdio_readb(card->func, reg, &ret);
+			if (!ret)
+				ptr += sprintf(ptr, "%02x ", data);
+			else {
+				ptr += sprintf(ptr, "ERR");
+				break;
+			}
+			reg++;
+		}
+		PRINTM(MSG, "%s\n", buf);
+	}
+	sdio_release_host(card->func);
+}
+
+module_param(fw_name, charp, 0);
+MODULE_PARM_DESC(fw_name, "Firmware name");
+module_param(bt_req_fw_nowait, int, 0);
+MODULE_PARM_DESC(bt_req_fw_nowait,
+		 "0: Use request_firmware API; 1: Use request_firmware_nowait API");
+module_param(multi_fn, int, 0);
+MODULE_PARM_DESC(multi_fn, "Bit 2: FN2;");
diff --git a/bt_sd8997/bt/hci_wrapper.h b/bt_sd8997/bt/hci_wrapper.h
new file mode 100644
index 0000000..e2942de
--- /dev/null
+++ b/bt_sd8997/bt/hci_wrapper.h
@@ -0,0 +1,162 @@
+/** @file hci_wrapper.h
+ *  @brief This file contains HCI related definitions
+ *
+ *  Copyright (C) 2011-2017, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _HCI_WRAPPER_H_
+#define _HCI_WRAPPER_H_
+
+#include <linux/module.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+/**  Define Seq num */
+#define BT_SEQ      0
+
+/** Define dev type */
+#define BT_TYPE     1
+#define BT_AMP_TYPE 2
+
+/** Define spec type */
+#define BLUEZ_SPEC     1
+#define IANYWHERE_SPEC 2
+#define GENERIC_SPEC   3
+
+/** Define lock/unlock wrapper */
+#define mdev_req_lock(d)		down(&d->req_lock)
+#define mdev_req_unlock(d)		up(&d->req_lock)
+
+/** Length of device name */
+#define DEV_NAME_LEN				32
+
+/** Define struct m_dev */
+struct m_dev {
+	char name[DEV_NAME_LEN];
+	int index;
+	unsigned long flags;
+	spinlock_t lock;
+	struct semaphore req_lock;
+	struct sk_buff_head rx_q;
+	wait_queue_head_t req_wait_q;
+	struct hci_dev_stats stat;
+	struct module *owner;
+	void *dev_pointer;
+	int dev_type;
+	int spec_type;
+	void *driver_data;
+	int read_continue_flag;
+	int wait_rx_complete;
+	int rx_complete_flag;
+	wait_queue_head_t rx_wait_q;
+	spinlock_t rxlock;
+
+	struct sk_buff *evt_skb;
+	struct sk_buff *acl_skb;
+	struct sk_buff *sco_skb;
+
+	int (*open) (struct m_dev * m_dev);
+	int (*close) (struct m_dev * m_dev);
+	int (*flush) (struct m_dev * m_dev);
+	int (*send) (struct m_dev * m_dev, struct sk_buff * skb);
+	void (*destruct) (struct m_dev * m_dev);
+	void (*notify) (struct m_dev * m_dev, unsigned int evt);
+	int (*ioctl) (struct m_dev * m_dev, unsigned int cmd, void *arg);
+	void (*query) (struct m_dev * m_dev, void *arg);
+
+};
+
+/** Define struct mbt_dev */
+struct mbt_dev {
+	/** maybe could add some private member later */
+	char name[DEV_NAME_LEN];
+	unsigned long flags;
+	__u8 type;
+
+	__u16 pkt_type;
+	__u16 esco_type;
+	__u16 link_policy;
+	__u16 link_mode;
+
+	__u32 idle_timeout;
+	__u16 sniff_min_interval;
+	__u16 sniff_max_interval;
+
+	struct sk_buff *reassembly[3];
+
+	atomic_t promisc;
+};
+
+/** This function frees m_dev allocation */
+void free_m_dev(struct m_dev *m_dev);
+
+/**
+ *  @brief This function receives frames
+ *
+ *  @param skb	A pointer to struct sk_buff
+ *  @return	0--success otherwise error code
+ */
+static inline int
+mdev_recv_frame(struct sk_buff *skb)
+{
+	struct m_dev *m_dev = (struct m_dev *)skb->dev;
+	if (!m_dev || (!test_bit(HCI_UP, &m_dev->flags)
+		       && !test_bit(HCI_INIT, &m_dev->flags))) {
+		kfree_skb(skb);
+		return -ENXIO;
+	}
+
+	/* Incomming skb */
+	bt_cb(skb)->incoming = 1;
+
+	/* Time stamp */
+	__net_timestamp(skb);
+
+	/* Queue frame for rx task */
+	skb_queue_tail(&m_dev->rx_q, skb);
+
+	/* Wakeup rx thread */
+	wake_up_interruptible(&m_dev->req_wait_q);
+
+	return 0;
+}
+
+/**
+ *  @brief mbt dev suspend handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_suspend_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+/**
+ *  @brief mbt dev resume handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_resume_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+#endif /* _HCI_WRAPPER_H_ */
diff --git a/bt_sd8997/bt/mbt_char.c b/bt_sd8997/bt/mbt_char.c
new file mode 100644
index 0000000..c0c025f
--- /dev/null
+++ b/bt_sd8997/bt/mbt_char.c
@@ -0,0 +1,774 @@
+/** @file mbt_char.c
+  *
+  * @brief This file contains the char device function calls
+  *
+  * Copyright (C) 2010-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/path.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+
+#include "bt_drv.h"
+#include "mbt_char.h"
+
+static LIST_HEAD(char_dev_list);
+
+static DEFINE_SPINLOCK(char_dev_list_lock);
+
+static int mbtchar_major = MBTCHAR_MAJOR_NUM;
+
+struct kobject *
+chardev_get(struct char_dev *dev)
+{
+	struct kobject *kobj;
+
+	kobj = bt_priv_get(dev->m_dev->driver_data);
+	if (!kobj)
+		return NULL;
+	PRINTM(INFO, "dev get kobj\n");
+	kobj = kobject_get(&dev->kobj);
+	if (!kobj)
+		bt_priv_put(dev->m_dev->driver_data);
+	return kobj;
+}
+
+void
+chardev_put(struct char_dev *dev)
+{
+	if (dev) {
+		struct m_dev *m_dev = dev->m_dev;
+		PRINTM(INFO, "dev put kobj\n");
+		kobject_put(&dev->kobj);
+		if (m_dev)
+			bt_priv_put(m_dev->driver_data);
+	}
+}
+
+/**
+ *	@brief Changes permissions of the dev
+ *
+ *	@param name	pointer to character
+ *	@param mode		mode_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chmod(char *name, mode_t mode)
+{
+	struct path path;
+	struct inode *inode;
+	struct iattr newattrs;
+	int ret;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chmod(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief Changes ownership of the dev
+ *
+ *	@param name	pointer to character
+ *	@param user		uid_t type data
+ *	@param group	gid_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chown(char *name, uid_t user, gid_t group)
+{
+	struct path path;
+	struct inode *inode = NULL;
+	struct iattr newattrs;
+	int ret = 0;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chown(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+	newattrs.ia_valid = ATTR_CTIME;
+	if (user != (uid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_UID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_uid = user;
+#else
+		newattrs.ia_uid = KUIDT_INIT(user);
+#endif
+	}
+	if (group != (gid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_GID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_gid = group;
+#else
+		newattrs.ia_gid = KGIDT_INIT(group);
+#endif
+	}
+	if (!S_ISDIR(inode->i_mode))
+		newattrs.ia_valid |=
+			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief write handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes written
+ */
+ssize_t
+chardev_write(struct file * filp, const char *buf, size_t count, loff_t * f_pos)
+{
+	int nwrite = 0;
+	struct sk_buff *skb;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	if (!test_bit(HCI_UP, &m_dev->flags)) {
+		LEAVE();
+		return -EBUSY;
+	}
+	nwrite = count;
+	skb = bt_skb_alloc(count, GFP_ATOMIC);
+	if (!skb) {
+		PRINTM(ERROR, "mbtchar_write(): fail to alloc skb\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	if (copy_from_user((void *)skb_put(skb, count), buf, count)) {
+		PRINTM(ERROR, "mbtchar_write(): cp_from_user failed\n");
+		kfree_skb(skb);
+		nwrite = -EFAULT;
+		goto exit;
+	}
+
+	skb->dev = (void *)m_dev;
+	bt_cb(skb)->pkt_type = *((unsigned char *)skb->data);
+	skb_pull(skb, 1);
+
+	PRINTM(DATA, "Write: pkt_type: 0x%x, len=%d @%lu\n",
+	       bt_cb(skb)->pkt_type, skb->len, jiffies);
+	DBG_HEXDUMP(DAT_D, "chardev_write", skb->data, skb->len);
+
+	/* Send skb to the hci wrapper layer */
+	if (m_dev->send(m_dev, skb)) {
+		PRINTM(ERROR, "Write: Fail\n");
+		nwrite = 0;
+		/* Send failed */
+		kfree_skb(skb);
+	}
+exit:
+	LEAVE();
+	return nwrite;
+}
+
+/**
+ *	@brief read handler for BT char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes read
+ */
+ssize_t
+chardev_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t ret = 0;
+	struct sk_buff *skb = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	/* Wait for rx data */
+	add_wait_queue(&m_dev->req_wait_q, &wait);
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		skb = skb_dequeue(&m_dev->rx_q);
+		if (skb)
+			break;
+		if (!test_bit(HCI_UP, &m_dev->flags)) {
+			ret = -EBUSY;
+			break;
+		}
+
+		if (filp->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			break;
+		}
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&m_dev->req_wait_q, &wait);
+
+	if (!skb)
+		goto out;
+
+	if (m_dev->read_continue_flag == 0) {
+		/* Put type byte before the data */
+		memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+		PRINTM(DATA, "Read: pkt_type: 0x%x, len=%d @%lu\n",
+		       bt_cb(skb)->pkt_type, skb->len, jiffies);
+	}
+	DBG_HEXDUMP(DAT_D, "chardev_read", skb->data, skb->len);
+	if (skb->len > count) {
+		/* user data length is smaller than the skb length */
+		if (copy_to_user(buf, skb->data, count)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		skb_pull(skb, count);
+		skb_queue_head(&m_dev->rx_q, skb);
+		m_dev->read_continue_flag = 1;
+		wake_up_interruptible(&m_dev->req_wait_q);
+		ret = count;
+		goto out;
+	} else {
+		if (copy_to_user(buf, skb->data, skb->len)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		m_dev->read_continue_flag = 0;
+		ret = skb->len;
+	}
+outf:
+	kfree_skb(skb);
+out:
+	if (m_dev->wait_rx_complete && skb_queue_empty(&m_dev->rx_q)) {
+		m_dev->rx_complete_flag = TRUE;
+		wake_up_interruptible(&m_dev->rx_wait_q);
+	}
+	LEAVE();
+	return ret;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+char_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, void *arg)
+#else
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+char_ioctl(struct file *filp, unsigned int cmd, void *arg)
+#endif
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+	case MBTCHAR_IOCTL_RELEASE:
+		m_dev->close(m_dev);
+		break;
+	case MBTCHAR_IOCTL_QUERY_TYPE:
+		m_dev->query(m_dev, arg);
+		break;
+	default:
+		m_dev->ioctl(m_dev, cmd, arg);
+		break;
+	}
+	LEAVE();
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl(struct inode *inode, struct file *filp,
+	      unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, (void *)arg);
+#else
+	return char_ioctl(filp, cmd, (void *)arg);
+#endif
+}
+
+#ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl_compat(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl_compat(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, compat_ptr(arg));
+#else
+	return char_ioctl(filp, cmd, compat_ptr(arg));
+#endif
+}
+#endif /* CONFIG_COMPAT */
+
+/**
+ *	@brief open handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_open(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = NULL;
+	struct m_dev *m_dev = NULL;
+	struct char_dev *cdev = NULL;
+	struct list_head *p = NULL;
+	ENTER();
+
+	list_for_each(p, &char_dev_list) {
+		cdev = list_entry(p, struct char_dev, list);
+		if (mbtchar_major == MAJOR(inode->i_cdev->dev) &&
+		    cdev->minor == MINOR(inode->i_cdev->dev)) {
+			dev = cdev;
+			break;
+		}
+	}
+	if (!dev) {
+		PRINTM(ERROR, "cannot find dev from inode\n");
+		LEAVE();
+		return -ENXIO;
+	}
+	if (!chardev_get(dev)) {
+		LEAVE();
+		return -ENXIO;
+	}
+	filp->private_data = dev;	/* for other methods */
+	m_dev = dev->m_dev;
+	mdev_req_lock(m_dev);
+	if (test_bit(HCI_UP, &m_dev->flags)) {
+		ret = -EALREADY;
+		goto done;
+	}
+	if (m_dev->open(m_dev)) {
+		ret = -EIO;
+		goto done;
+	}
+	set_bit(HCI_UP, &m_dev->flags);
+
+done:
+	mdev_req_unlock(m_dev);
+	if (ret)
+		chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief release handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_release(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	if (m_dev)
+		ret = dev->m_dev->close(dev->m_dev);
+	filp->private_data = NULL;
+	chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief poll handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param wait		pointer to poll_table structure
+ *	@return			mask
+ */
+static unsigned int
+chardev_poll(struct file *filp, poll_table * wait)
+{
+	unsigned int mask;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+
+	m_dev = dev->m_dev;
+	poll_wait(filp, &m_dev->req_wait_q, wait);
+	mask = POLLOUT | POLLWRNORM;
+	if (skb_peek(&m_dev->rx_q))
+		mask |= POLLIN | POLLRDNORM;
+	if (!test_bit(HCI_UP, &(m_dev->flags)))
+		mask |= POLLHUP;
+	PRINTM(INFO, "poll mask=0x%x\n", mask);
+	LEAVE();
+	return mask;
+}
+
+/* File ops for the Char driver */
+const struct file_operations chardev_fops = {
+	.owner = THIS_MODULE,
+	.read = chardev_read,
+	.write = chardev_write,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	.ioctl = chardev_ioctl,
+#else
+	.unlocked_ioctl = chardev_ioctl,
+#endif
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = chardev_ioctl_compat,
+#endif
+	.open = chardev_open,
+	.release = chardev_release,
+	.poll = chardev_poll,
+};
+
+/**
+ *	@brief This function creates the char dev
+ *
+ *	@param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param mod_name		A pointer to char
+ *  @param dev_name		A pointer to char
+ *	@return				0--success otherwise failure
+ */
+int
+register_char_dev(struct char_dev *dev, struct class *char_class,
+		  char *mod_name, char *dev_name)
+{
+	int ret = 0, dev_num;
+	unsigned long flags;
+	ENTER();
+	/* create the chrdev region */
+	if (mbtchar_major) {
+		dev_num = MKDEV(mbtchar_major, dev->minor);
+		ret = register_chrdev_region(dev_num, 1, mod_name);
+	} else {
+		PRINTM(INFO, "chardev: no major # yet\n");
+		ret = alloc_chrdev_region((dev_t *) & dev_num, dev->minor, 1,
+					  mod_name);
+	}
+
+	if (ret) {
+		PRINTM(ERROR, "chardev: create chrdev_region failed\n");
+		LEAVE();
+		return ret;
+	}
+	if (!mbtchar_major) {
+		/* Store the allocated dev major # */
+		mbtchar_major = MAJOR(dev_num);
+	}
+	dev->cdev = cdev_alloc();
+	dev->cdev->ops = &chardev_fops;
+	dev->cdev->owner = chardev_fops.owner;
+	dev_num = MKDEV(mbtchar_major, dev->minor);
+
+	if (cdev_add(dev->cdev, dev_num, 1)) {
+		PRINTM(ERROR, "chardev: cdev_add failed\n");
+		ret = -EFAULT;
+		goto free_cdev_region;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), NULL, dev_name);
+	}
+#else
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), dev_name);
+	}
+#endif
+	PRINTM(INFO, "register char dev=%s\n", dev_name);
+
+	/** modify later */
+
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_add_tail(&dev->list, &char_dev_list);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+
+	LEAVE();
+	return ret;
+free_cdev_region:
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief This function deletes the char dev
+ *
+ *  @param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param dev_name		A pointer to char
+ *  @return				0--success otherwise failure
+ */
+int
+unregister_char_dev(struct char_dev *dev, struct class *char_class,
+		    char *dev_name)
+{
+	ENTER();
+	device_destroy(char_class, MKDEV(mbtchar_major, dev->minor));
+	cdev_del(dev->cdev);
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	PRINTM(INFO, "unregister char dev=%s\n", dev_name);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param char_class	A pointer to class struct
+ *  @return				N/A
+ */
+void
+chardev_cleanup(struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	do {
+		dev = NULL;
+		list_for_each(p, &char_dev_list) {
+			dev = list_entry(p, struct char_dev, list);
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			unregister_char_dev(dev, char_class, dev->m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	} while (dev);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	class_destroy(char_class);
+	LEAVE();
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param m_dev	A pointer to m_dev struct
+ *  @param char_class	A pointer to class struct
+ *  @return			N/A
+ */
+void
+chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_for_each(p, &char_dev_list) {
+		dev = list_entry(p, struct char_dev, list);
+		if (dev->minor == m_dev->index) {
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			dev->m_dev = NULL;
+			unregister_char_dev(dev, char_class, m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	LEAVE();
+}
diff --git a/bt_sd8997/bt/mbt_char.h b/bt_sd8997/bt/mbt_char.h
new file mode 100644
index 0000000..884d259
--- /dev/null
+++ b/bt_sd8997/bt/mbt_char.h
@@ -0,0 +1,70 @@
+/** @file mbt_char.h
+  *
+  * @brief This file contains mbtchar driver specific defines etc
+  *
+  * Copyright (C) 2010-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+#ifndef __MBT_CHAR_H__
+#define __MBT_CHAR_H__
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+
+/** Define ioctl */
+#define MBTCHAR_IOCTL_RELEASE       _IO('M', 1)
+#define MBTCHAR_IOCTL_QUERY_TYPE    _IO('M', 2)
+#ifdef BLE_WAKEUP
+#define MBTCHAR_IOCTL_BLE_WAKEUP_PARAM _IO('M', 4)
+#endif
+
+#define MBTCHAR_MAJOR_NUM            (0)
+
+/** Interface specific macros */
+#define FMCHAR_MINOR_BASE            (10)
+#define NFCCHAR_MINOR_BASE           (20)
+
+/** Declaration of char_dev struct */
+struct char_dev {
+	struct list_head list;
+	int minor;
+	int dev_type;
+	struct cdev *cdev;
+	struct m_dev *m_dev;
+	struct kobject kobj;
+};
+
+/** Changes permissions of the dev */
+int mbtchar_chmod(char *name, mode_t mode);
+
+/** Changes ownership of the dev */
+int mbtchar_chown(char *name, uid_t user, gid_t group);
+
+/**	This function creates the char dev */
+int register_char_dev(struct char_dev *dev, struct class *char_class,
+		      char *mod_name, char *dev_name);
+
+/**	This function deletes the char dev */
+int unregister_char_dev(struct char_dev *dev, struct class *char_class,
+			char *dev_name);
+
+/**	This function cleans module */
+void chardev_cleanup(struct class *char_class);
+
+/**	This function cleans module */
+void chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class);
+
+#endif /*__MBT_CHAR_H__*/
diff --git a/bt_sd8997/bt_char/bt_drv.h b/bt_sd8997/bt_char/bt_drv.h
new file mode 100644
index 0000000..8d8b659
--- /dev/null
+++ b/bt_sd8997/bt_char/bt_drv.h
@@ -0,0 +1,936 @@
+/** @file bt_drv.h
+ *  @brief This header file contains global constant/enum definitions,
+ *  global variable declaration.
+ *
+ *  Copyright (C) 2007-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_DRV_H_
+#define _BT_DRV_H_
+
+#include <linux/version.h>
+#include <linux/kthread.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+
+#include "hci_wrapper.h"
+
+/** MAX adapter BT driver supported */
+#define MAX_BT_ADAPTER    3
+
+#ifndef BIT
+/** BIT definition */
+#define BIT(x) (1UL << (x))
+#endif
+
+#ifdef MBT_64BIT
+typedef u64 t_ptr;
+#else
+typedef u32 t_ptr;
+#endif
+
+/** max number of adapter supported */
+#define MAX_BT_ADAPTER      3
+/** Define drv_mode bit */
+#define DRV_MODE_BT         BIT(0)
+
+/** Define devFeature bit */
+#define DEV_FEATURE_BT     BIT(0)
+#define DEV_FEATURE_BTAMP     BIT(1)
+#define DEV_FEATURE_BLE     BIT(2)
+
+/** Define maximum number of radio func supported */
+#define MAX_RADIO_FUNC     4
+
+/** MAC address print format */
+#ifndef MACSTR
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+
+/** MAC address print arguments */
+#ifndef MAC2STR
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#endif
+
+/** Debug level : Message */
+#define	DBG_MSG			BIT(0)
+/** Debug level : Fatal */
+#define DBG_FATAL		BIT(1)
+/** Debug level : Error */
+#define DBG_ERROR		BIT(2)
+/** Debug level : Data */
+#define DBG_DATA		BIT(3)
+/** Debug level : Command */
+#define DBG_CMD			BIT(4)
+/** Debug level : Event */
+#define DBG_EVENT		BIT(5)
+/** Debug level : Interrupt */
+#define DBG_INTR		BIT(6)
+
+/** Debug entry : Data dump */
+#define DBG_DAT_D		BIT(16)
+/** Debug entry : Data dump */
+#define DBG_CMD_D		BIT(17)
+
+/** Debug level : Entry */
+#define DBG_ENTRY		BIT(28)
+/** Debug level : Warning */
+#define DBG_WARN		BIT(29)
+/** Debug level : Informative */
+#define DBG_INFO		BIT(30)
+
+#ifdef	DEBUG_LEVEL1
+extern u32 mbt_drvdbg;
+
+#ifdef	DEBUG_LEVEL2
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  \
+	do {if (mbt_drvdbg & DBG_INFO)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...) \
+	do {if (mbt_drvdbg & DBG_WARN)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) \
+	do {if (mbt_drvdbg & DBG_ENTRY) \
+		printk(KERN_DEBUG msg); } while (0)
+#else
+/** Print informative message */
+#define	PRINTM_INFO(msg...)  do {} while (0)
+/** Print warning message */
+#define	PRINTM_WARN(msg...)  do {} while (0)
+/** Print entry message */
+#define	PRINTM_ENTRY(msg...) do {} while (0)
+#endif /* DEBUG_LEVEL2 */
+
+/** Print interrupt message */
+#define	PRINTM_INTR(msg...)  \
+	do {if (mbt_drvdbg & DBG_INTR)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print event message */
+#define	PRINTM_EVENT(msg...) \
+	do {if (mbt_drvdbg & DBG_EVENT) \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print command message */
+#define	PRINTM_CMD(msg...)   \
+	do {if (mbt_drvdbg & DBG_CMD)   \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data message */
+#define	PRINTM_DATA(msg...)  \
+	do {if (mbt_drvdbg & DBG_DATA)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print error message */
+#define	PRINTM_ERROR(msg...) \
+	do {if (mbt_drvdbg & DBG_ERROR) \
+		printk(KERN_ERR msg); } while (0)
+/** Print fatal message */
+#define	PRINTM_FATAL(msg...) \
+	do {if (mbt_drvdbg & DBG_FATAL) \
+		printk(KERN_ERR msg); } while (0)
+/** Print message */
+#define	PRINTM_MSG(msg...)   \
+	do {if (mbt_drvdbg & DBG_MSG)   \
+		printk(KERN_ALERT msg); } while (0)
+
+/** Print data dump message */
+#define	PRINTM_DAT_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_DAT_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+/** Print data dump message */
+#define	PRINTM_CMD_D(msg...)  \
+	do {if (mbt_drvdbg & DBG_CMD_D)  \
+		printk(KERN_DEBUG msg); } while (0)
+
+/** Print message with required level */
+#define	PRINTM(level, msg...) PRINTM_##level(msg)
+
+/** Debug dump buffer length */
+#define DBG_DUMP_BUF_LEN	64
+/** Maximum number of dump per line */
+#define MAX_DUMP_PER_LINE	16
+/** Maximum data dump length */
+#define MAX_DATA_DUMP_LEN	48
+
+/**
+ * @brief Prints buffer data upto provided length
+ *
+ * @param prompt          Char pointer
+ * @param buf			  Buffer
+ * @param len    		  Length
+ *
+ * @return                N/A
+ */
+static inline void
+hexdump(char *prompt, u8 *buf, int len)
+{
+	int i;
+	char dbgdumpbuf[DBG_DUMP_BUF_LEN];
+	char *ptr = dbgdumpbuf;
+
+	printk(KERN_DEBUG "%s: len=%d\n", prompt, len);
+	for (i = 1; i <= len; i++) {
+		ptr += snprintf(ptr, 4, "%02x ", *buf);
+		buf++;
+		if (i % MAX_DUMP_PER_LINE == 0) {
+			*ptr = 0;
+			printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+			ptr = dbgdumpbuf;
+		}
+	}
+	if (len % MAX_DUMP_PER_LINE) {
+		*ptr = 0;
+		printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+	}
+}
+
+/** Debug hexdump of debug data */
+#define DBG_HEXDUMP_DAT_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_DAT_D) \
+		hexdump(x, y, z); } while (0)
+/** Debug hexdump of debug command */
+#define DBG_HEXDUMP_CMD_D(x, y, z) \
+	do {if (mbt_drvdbg & DBG_CMD_D) \
+		hexdump(x, y, z); } while (0)
+
+/** Debug hexdump */
+#define	DBG_HEXDUMP(level, x, y, z)    DBG_HEXDUMP_##level(x, y, z)
+
+/** Mark entry point */
+#define	ENTER()			PRINTM(ENTRY, "Enter: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+/** Mark exit point */
+#define	LEAVE()			PRINTM(ENTRY, "Leave: %s, %s:%i\n", __func__, \
+							__FILE__, __LINE__)
+#else
+/** Do nothing */
+#define	PRINTM(level, msg...) do {} while (0)
+/** Do nothing */
+#define DBG_HEXDUMP(level, x, y, z)    do {} while (0)
+/** Do nothing */
+#define	ENTER()  do {} while (0)
+/** Do nothing */
+#define	LEAVE()  do {} while (0)
+#endif /* DEBUG_LEVEL1 */
+
+/** Bluetooth upload size */
+#define	BT_UPLD_SIZE				2312
+/** Bluetooth status success */
+#define BT_STATUS_SUCCESS			(0)
+/** Bluetooth status pending */
+#define BT_STATUS_PENDING           (1)
+/** Bluetooth status failure */
+#define BT_STATUS_FAILURE			(-1)
+
+#ifndef	TRUE
+/** True value */
+#define TRUE			1
+#endif
+#ifndef	FALSE
+/** False value */
+#define	FALSE			0
+#endif
+
+/** Set thread state */
+#define OS_SET_THREAD_STATE(x)		set_current_state(x)
+/** Time to wait until Host Sleep state change in millisecond */
+#define WAIT_UNTIL_HS_STATE_CHANGED 2000
+/** Time to wait cmd resp in millisecond */
+#define WAIT_UNTIL_CMD_RESP	    5000
+
+/** Sleep until a condition gets true or a timeout elapses */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	interruptible_sleep_on_timeout(&waitq, ((timeout) * HZ / 1000))
+#else
+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
+	wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
+#endif
+
+/** bt thread structure */
+typedef struct {
+	/** Task */
+	struct task_struct *task;
+	/** Queue */
+	wait_queue_head_t waitQ;
+	/** PID */
+	pid_t pid;
+	/** Private structure */
+	void *priv;
+} bt_thread;
+
+/**
+ * @brief Activates bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline void
+bt_activate_thread(bt_thread *thr)
+{
+	/** Initialize the wait queue */
+	init_waitqueue_head(&thr->waitQ);
+
+	/** Record the thread pid */
+	thr->pid = current->pid;
+}
+
+/**
+ * @brief De-activates bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline void
+bt_deactivate_thread(bt_thread *thr)
+{
+	thr->pid = 0;
+	return;
+}
+
+/**
+ * @brief Creates bt thread
+ *
+ * @param btfunc          Function pointer
+ * @param thr			  A pointer to bt_thread structure
+ * @param name    		  Char pointer
+ *
+ * @return                N/A
+ */
+static inline void
+bt_create_thread(int (*btfunc) (void *), bt_thread *thr, char *name)
+{
+	thr->task = kthread_run(btfunc, thr, "%s", name);
+}
+
+/**
+ * @brief Delete bt thread
+ *
+ * @param thr			  A pointer to bt_thread structure
+ *
+ * @return                N/A
+ */
+static inline int
+bt_terminate_thread(bt_thread *thr)
+{
+	/* Check if the thread is active or not */
+	if (!thr->pid)
+		return -1;
+
+	kthread_stop(thr->task);
+	return 0;
+}
+
+/**
+ * @brief  Set scheduled timeout
+ *
+ * @param millisec		 Time unit in ms
+ *
+ * @return                N/A
+ */
+static inline void
+os_sched_timeout(u32 millisec)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	schedule_timeout((millisec * HZ) / 1000);
+}
+
+#ifndef __ATTRIB_ALIGN__
+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
+#endif
+
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__ __attribute__((packed))
+#endif
+
+/** BT histogram command */
+#define BT_CMD_HISTOGRAM            0xEA
+/** max antenna num */
+#define MAX_ANTENNA_NUM             2
+/** BDR 1M */
+#define BDR_RATE_1M					1
+/** EDR 2/3 M */
+#define EDR_RATE_2_3M			    2
+/** BLE 1M */
+#define BLE_RATE_1M                 5
+/** max bt link number */
+#define MAX_BT_LINK                 10
+/** max ble link number */
+#define MAX_BLE_LINK                16
+
+/** BT link state structure */
+typedef struct _bt_link_stat {
+    /** txrx rate 1: BDR_1M, 2:EDR 2/3 M, 3:BLE 1M */
+	u8 txrxrate;
+    /** power: -30 = N = 20 dbm*/
+	s8 txpower;
+    /** rssi: -127 to +20 (For BT), -128 to +127 (For BLE) */
+	s8 rssi;
+} __ATTRIB_PACK__ bt_link_stat;
+
+/** BT histogram data structure */
+typedef struct _bt_histogram_data {
+	/** Antenna */
+	u8 antenna;
+	/** Powerclass */
+	u8 powerclass;
+	/** bt link state structure */
+	bt_link_stat link[MAX_BT_LINK + MAX_BLE_LINK];
+} __ATTRIB_PACK__ bt_histogram_data;
+
+/** BT histogram proc data structure */
+typedef struct _bt_hist_proc_data {
+    /** antenna */
+	u8 antenna;
+	/** Private structure */
+	struct _bt_private *pbt;
+} bt_hist_proc_data;
+
+/** Data structure for the Marvell Bluetooth device */
+typedef struct _bt_dev {
+	/** device name */
+	char name[DEV_NAME_LEN];
+	/** card pointer */
+	void *card;
+	/** IO port */
+	u32 ioport;
+	/** m_dev structure */
+	struct m_dev m_dev[MAX_RADIO_FUNC];
+
+	/** Tx download ready flag */
+	u8 tx_dnld_rdy;
+	/** Function */
+	u8 fn;
+	/** Rx unit */
+	u8 rx_unit;
+	/** Power Save mode : Timeout configuration */
+	u16 idle_timeout;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save command */
+	u8 pscmd;
+	/** Host Sleep mode */
+	u8 hsmode;
+	/** Host Sleep command */
+	u8 hscmd;
+	/** Low byte is gap, high byte is GPIO */
+	u16 gpio_gap;
+	/** Host Sleep configuration command */
+	u8 hscfgcmd;
+	/** Host Send Cmd Flag		 */
+	u8 sendcmdflag;
+	/** opcode for Send Cmd */
+	u16 send_cmd_opcode;
+	/** Device Type			*/
+	u8 devType;
+	/** Device Features    */
+	u8 devFeature;
+	/** cmd52 function */
+	u8 cmd52_func;
+	/** cmd52 register */
+	u8 cmd52_reg;
+	/** cmd52 value */
+	u8 cmd52_val;
+	/** SDIO pull control command */
+	u8 sdio_pull_ctrl;
+	/** Low 2 bytes is pullUp, high 2 bytes for pull-down */
+	u32 sdio_pull_cfg;
+	/** Test mode command */
+	u8 test_mode;
+} bt_dev_t, *pbt_dev_t;
+
+/** Marvell bt adapter structure */
+typedef struct _bt_adapter {
+	/** Chip revision ID */
+	u8 chip_rev;
+    /** magic val */
+	u8 magic_val;
+	/** Surprise removed flag */
+	u8 SurpriseRemoved;
+	/** IRQ number */
+	int irq;
+	/** Interrupt counter */
+	u32 IntCounter;
+	/** Tx packet queue */
+	struct sk_buff_head tx_queue;
+
+	/** Pointer of fw dump file name */
+	char *fwdump_fname;
+	/** Fw dump queue */
+	struct sk_buff_head fwdump_queue;
+	/** Pending Tx packet queue */
+	struct sk_buff_head pending_queue;
+	/** tx lock flag */
+	u8 tx_lock;
+	/** Power Save mode */
+	u8 psmode;
+	/** Power Save state */
+	u8 ps_state;
+	/** Host Sleep state */
+	u8 hs_state;
+	/** hs skip count */
+	u32 hs_skip;
+	/** suspend_fail flag */
+	u8 suspend_fail;
+	/** suspended flag */
+	u8 is_suspended;
+	/** Number of wakeup tries */
+	u8 WakeupTries;
+	/** Host Sleep wait queue */
+	wait_queue_head_t cmd_wait_q __ATTRIB_ALIGN__;
+	/** Host Cmd complet state */
+	u8 cmd_complete;
+	/** last irq recv */
+	u8 irq_recv;
+	/** last irq processed */
+	u8 irq_done;
+	/** sdio int status */
+	u8 sd_ireg;
+     /** buf allocated for transmit */
+	u8 *tx_buffer;
+    /** buf for transmit */
+	u8 *tx_buf;
+    /** buf allocated for read interrupt status */
+	u8 *hw_regs_buf;
+    /** buf for read interrupt status */
+	u8 *hw_regs;
+	/** tx pending */
+	u32 skb_pending;
+/** Version string buffer length */
+#define MAX_VER_STR_LEN         128
+	/** Driver version */
+	u8 drv_ver[MAX_VER_STR_LEN];
+	/** Number of command timeout */
+	u32 num_cmd_timeout;
+} bt_adapter, *pbt_adapter;
+
+/** Length of prov name */
+#define PROC_NAME_LEN				32
+
+/** Item data structure */
+struct item_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** Size */
+	u32 size;
+	/** Address */
+	t_ptr addr;
+	/** Offset */
+	u32 offset;
+	/** Flag */
+	u32 flag;
+};
+
+/** Proc private data structure */
+struct proc_private_data {
+	/** Name */
+	char name[PROC_NAME_LEN];
+	/** File flag */
+	u32 fileflag;
+	/** Buffer size */
+	u32 bufsize;
+	/** Number of items */
+	u32 num_items;
+	/** Item data */
+	struct item_data *pdata;
+	/** Private structure */
+	struct _bt_private *pbt;
+	/** File operations */
+	const struct file_operations *fops;
+};
+
+/** Device proc structure */
+struct device_proc {
+	/** Proc directory entry */
+	struct proc_dir_entry *proc_entry;
+    /** proc entry for hist */
+	struct proc_dir_entry *hist_entry;
+	/** num of proc files */
+	u8 num_proc_files;
+	/** pointer to proc_private_data */
+	struct proc_private_data *pfiles;
+};
+
+/** Private structure for the MV device */
+typedef struct _bt_private {
+	/** Bluetooth device */
+	bt_dev_t bt_dev;
+	/** Adapter */
+	bt_adapter *adapter;
+	/** Firmware helper */
+	const struct firmware *fw_helper;
+	/** Firmware */
+	const struct firmware *firmware;
+	/** Init user configure file */
+	const struct firmware *init_user_cfg;
+	/** Init user configure wait queue token */
+	u16 init_user_conf_wait_flag;
+	/** Init user configure file wait queue */
+	wait_queue_head_t init_user_conf_wait_q __ATTRIB_ALIGN__;
+	/** Firmware request start time */
+	struct timeval req_fw_time;
+	/** Hotplug device */
+	struct device *hotplug_device;
+	/** thread to service interrupts */
+	bt_thread MainThread;
+	 /** proc data */
+	struct device_proc dev_proc[MAX_RADIO_FUNC];
+	/** Driver lock */
+	spinlock_t driver_lock;
+	/** Driver lock flags */
+	ulong driver_flags;
+	/** Driver reference flags */
+	struct kobject kobj;
+	int debug_device_pending;
+	int debug_ocf_ogf[2];
+	u8 fw_reload;
+	/* hist_data_len */
+	u8 hist_data_len;
+    /** hist data */
+	bt_histogram_data hist_data[MAX_ANTENNA_NUM];
+    /** hist proc data */
+	bt_hist_proc_data hist_proc[MAX_ANTENNA_NUM];
+#ifdef BLE_WAKEUP
+	u8 ble_wakeup_buf_size;
+	u8 *ble_wakeup_buf;
+#endif
+} bt_private, *pbt_private;
+
+int bt_get_histogram(bt_private *priv);
+
+/** Disable interrupt */
+#define OS_INT_DISABLE	spin_lock_irqsave(&priv->driver_lock, \
+						priv->driver_flags)
+/** Enable interrupt */
+#define	OS_INT_RESTORE	spin_unlock_irqrestore(&priv->driver_lock, \
+						priv->driver_flags)
+
+#ifndef HCI_BT_AMP
+/** BT_AMP flag for device type */
+#define  HCI_BT_AMP		0x80
+#endif
+
+/** Device type of BT */
+#define DEV_TYPE_BT		0x00
+/** Device type of AMP */
+#define DEV_TYPE_AMP		0x01
+
+/** Marvell vendor packet */
+#define MRVL_VENDOR_PKT			0xFE
+
+/** Bluetooth command : Get FW Version */
+#define BT_CMD_GET_FW_VERSION       0x0F
+/** Bluetooth command : Sleep mode */
+#define BT_CMD_AUTO_SLEEP_MODE		0x23
+/** Bluetooth command : Host Sleep configuration */
+#define BT_CMD_HOST_SLEEP_CONFIG	0x59
+/** Bluetooth command : Host Sleep enable */
+#define BT_CMD_HOST_SLEEP_ENABLE	0x5A
+/** Bluetooth command : Module Configuration request */
+#define BT_CMD_MODULE_CFG_REQ		0x5B
+
+/** Bluetooth command : PMIC Configure */
+#define BT_CMD_PMIC_CONFIGURE           0x7D
+
+/** Bluetooth command : SDIO pull up down configuration request */
+#define BT_CMD_SDIO_PULL_CFG_REQ	0x69
+/** Bluetooth command : Set Evt Filter Command */
+#define BT_CMD_SET_EVT_FILTER		0x05
+/** Bluetooth command : Enable Write Scan Command */
+#define BT_CMD_ENABLE_WRITE_SCAN	0x1A
+/** Bluetooth command : Enable Device under test mode */
+#define BT_CMD_ENABLE_DEVICE_TESTMODE	0x03
+/** Sub Command: Module Bring Up Request */
+#define MODULE_BRINGUP_REQ		0xF1
+/** Sub Command: Module Shut Down Request */
+#define MODULE_SHUTDOWN_REQ		0xF2
+/** Module already up */
+#define MODULE_CFG_RESP_ALREADY_UP      0x0c
+/** Sub Command: Host Interface Control Request */
+#define MODULE_INTERFACE_CTRL_REQ	0xF5
+
+/** Bluetooth event : Power State */
+#define BT_EVENT_POWER_STATE		0x20
+
+/** Bluetooth Power State : Enable */
+#define BT_PS_ENABLE			0x02
+/** Bluetooth Power State : Disable */
+#define BT_PS_DISABLE			0x03
+/** Bluetooth Power State : Sleep */
+#define BT_PS_SLEEP			0x01
+/** Bluetooth Power State : Awake */
+#define BT_PS_AWAKE			0x02
+
+/** Vendor OGF */
+#define VENDOR_OGF				0x3F
+/** OGF for reset */
+#define RESET_OGF		0x03
+/** Bluetooth command : Reset */
+#define BT_CMD_RESET	0x03
+
+/** Host Sleep activated */
+#define HS_ACTIVATED			0x01
+/** Host Sleep deactivated */
+#define HS_DEACTIVATED			0x00
+
+/** Power Save sleep */
+#define PS_SLEEP			0x01
+/** Power Save awake */
+#define PS_AWAKE			0x00
+
+/** bt header length */
+#define BT_HEADER_LEN			4
+
+#ifndef MAX
+/** Return maximum of two */
+#define MAX(a, b)		((a) > (b) ? (a) : (b))
+#endif
+
+/** This is for firmware specific length */
+#define EXTRA_LEN	36
+
+/** Command buffer size for Marvell driver */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+
+/** Bluetooth Rx packet buffer size for Marvell driver */
+#define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \
+	(HCI_MAX_FRAME_SIZE + EXTRA_LEN)
+
+/** Buffer size to allocate */
+#define ALLOC_BUF_SIZE	(((MAX(MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \
+			MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \
+			+ SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
+
+/** Request FW timeout in second */
+#define REQUEST_FW_TIMEOUT		30
+
+/** 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
+
+/** default idle time */
+#define DEFAULT_IDLE_TIME           1000
+
+#define BT_CMD_HEADER_SIZE    3
+
+/** BT command structure */
+typedef struct _BT_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[128];
+} __ATTRIB_PACK__ BT_CMD;
+
+/** BT event structure */
+typedef struct _BT_EVENT {
+	/** Event Counter */
+	u8 EC;
+	/** Length */
+	u8 length;
+	/** Data */
+	u8 data[8];
+} BT_EVENT;
+
+#if defined(SDIO_SUSPEND_RESUME)
+#define DEF_GPIO_GAP        0xffff
+#endif
+
+#ifdef BLE_WAKEUP
+#define BD_ADDR_SIZE 6
+/** Vendor specific event */
+#define VENDOR_SPECIFIC_EVENT     0xff
+/** system suspend event */
+#define HCI_SYSTEM_SUSPEND_EVT    0x80
+/** system suspend */
+#define HCI_SYSTEM_SUSPEND        0x00
+/** system resume */
+#define HCI_SYSTEM_RESUME         0x01
+/** This function enables ble wake up pattern */
+int bt_config_ble_wakeup(bt_private *priv);
+int bt_send_system_event(bt_private *priv, u8 flag);
+#endif
+
+/** This function verify the received event pkt */
+int check_evtpkt(bt_private *priv, struct sk_buff *skb);
+
+/* Prototype of global function */
+/** This function gets the priv reference */
+struct kobject *bt_priv_get(bt_private *priv);
+/** This function release the priv reference */
+void bt_priv_put(bt_private *priv);
+/** This function adds the card */
+bt_private *bt_add_card(void *card);
+/** This function removes the card */
+int bt_remove_card(void *card);
+/** This function handles the interrupt */
+void bt_interrupt(struct m_dev *m_dev);
+
+/** This function creates proc interface directory structure */
+int bt_root_proc_init(void);
+/** This function removes proc interface directory structure */
+int bt_root_proc_remove(void);
+/** This function initializes proc entry */
+int bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq);
+/** This function removes proc interface */
+void bt_proc_remove(bt_private *priv);
+
+/** This function process the received event */
+int bt_process_event(bt_private *priv, struct sk_buff *skb);
+/** This function enables host sleep */
+int bt_enable_hs(bt_private *priv);
+/** This function used to send command to firmware */
+int bt_prepare_command(bt_private *priv);
+/** This function frees the structure of adapter */
+void bt_free_adapter(bt_private *priv);
+/** This function handle the receive packet */
+void bt_recv_frame(bt_private *priv, struct sk_buff *skb);
+
+/** clean up m_devs */
+void clean_up_m_devs(bt_private *priv);
+/** bt driver call this function to register to bus driver */
+int *sbi_register(void);
+/** bt driver call this function to unregister to bus driver */
+void sbi_unregister(void);
+/** bt driver calls this function to register the device  */
+int sbi_register_dev(bt_private *priv);
+/** bt driver calls this function to unregister the device */
+int sbi_unregister_dev(bt_private *priv);
+/** This function initializes firmware */
+int sbi_download_fw(bt_private *priv);
+/** Configures hardware to quit deep sleep state */
+int sbi_wakeup_firmware(bt_private *priv);
+/** Module configuration and register device */
+int sbi_register_conf_dpc(bt_private *priv);
+
+/** This function is used to send the data/cmd to hardware */
+int sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb);
+/** This function reads the current interrupt status register */
+int sbi_get_int_status(bt_private *priv);
+/** This function enables the host interrupts */
+int sbi_enable_host_int(bt_private *priv);
+/** This function disables the host interrupts */
+int sbi_disable_host_int(bt_private *priv);
+
+/** bt fw reload flag */
+extern int bt_fw_reload;
+/** 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
+/** This function reload firmware */
+void bt_request_fw_reload(bt_private *priv, int mode);
+#define MAX_TX_BUF_SIZE     2312
+/** This function downloads firmware image to the card */
+int sd_download_firmware_w_helper(bt_private *priv);
+void bt_dump_sdio_regs(bt_private *priv);
+/* dumps the firmware to /var/ or /data/ */
+void bt_dump_firmware_info_v2(bt_private *priv);
+
+/** 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
+
+/** Bluetooth command : Mac address configuration */
+#define BT_CMD_CONFIG_MAC_ADDR		0x22
+/** Bluetooth command : Write CSU register */
+#define BT_CMD_CSU_WRITE_REG		0x66
+/** Bluetooth command : Load calibrate data */
+#define BT_CMD_LOAD_CONFIG_DATA     0x61
+/** Bluetooth command : Load calibrate ext data */
+#define BT_CMD_LOAD_CONFIG_DATA_EXT     0x60
+
+/** Bluetooth command : BLE deepsleep */
+#define BT_CMD_BLE_DEEP_SLEEP       0x8b
+
+/** BT_BLE command structure */
+typedef struct _BT_BLE_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** deepsleep flag */
+	u8 deepsleep;
+} __ATTRIB_PACK__ BT_BLE_CMD;
+
+/** BT_CSU command structure */
+typedef struct _BT_CSU_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** reg type */
+	u8 type;
+	/** address */
+	u8 offset[4];
+	/** Data */
+	u8 value[2];
+} __ATTRIB_PACK__ BT_CSU_CMD;
+
+/** This function sets mac address */
+int bt_set_mac_address(bt_private *priv, u8 *mac);
+/** This function writes value to CSU registers */
+int bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value);
+/** BT set user defined init data and param */
+int bt_init_config(bt_private *priv, char *cfg_file);
+/** BT PMIC Configure command */
+int bt_pmic_configure(bt_private *priv);
+/** This function load the calibrate data */
+int bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac);
+/** This function load the calibrate ext data */
+int bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len);
+/** BT set user defined calibration data */
+int bt_cal_config(bt_private *priv, char *cfg_file, char *mac);
+/** BT set user defined calibration ext data */
+int bt_cal_config_ext(bt_private *priv, char *cfg_file);
+int bt_init_mac_address(bt_private *priv, char *mac);
+
+int bt_set_independent_reset(bt_private *priv);
+/** Bluetooth command : Independent reset */
+#define BT_CMD_INDEPENDENT_RESET     0x0D
+
+/** BT HCI command structure */
+typedef struct _BT_HCI_CMD {
+	/** OCF OGF */
+	u16 ocf_ogf;
+	/** Length */
+	u8 length;
+	/** cmd type */
+	u8 cmd_type;
+	/** cmd len */
+	u8 cmd_len;
+	/** Data */
+	u8 data[6];
+} __ATTRIB_PACK__ BT_HCI_CMD;
+
+#endif /* _BT_DRV_H_ */
diff --git a/bt_sd8997/bt_char/bt_init.c b/bt_sd8997/bt_char/bt_init.c
new file mode 100644
index 0000000..9d18912
--- /dev/null
+++ b/bt_sd8997/bt_char/bt_init.c
@@ -0,0 +1,751 @@
+/** @file bt_init.c
+  *
+  * @brief This file contains the init functions for BlueTooth
+  * driver.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/string.h>
+#include <linux/firmware.h>
+
+#include "bt_drv.h"
+
+extern int bt_req_fw_nowait;
+
+#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
+			 || ('a' <= (c) && (c) <= 'f') \
+			 || ('A' <= (c) && (c) <= 'F'))
+
+#define isdigit(c)	(('0' <= (c) && (c) <= '9'))
+#define isspace(c)  (c <= ' ' && (c == ' ' || (c <= 13 && c >= 9)))
+/**
+ *  @brief Returns hex value of a give character
+ *
+ *  @param chr	Character to be converted
+ *
+ *  @return	The converted character if chr is a valid hex, else 0
+ */
+static int
+bt_hexval(char chr)
+{
+	ENTER();
+
+	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;
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @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
+ */
+static char *
+bt_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 Returns hex value of a given ascii string
+ *
+ *  @param a	String to be converted
+ *
+ *  @return	hex value
+ */
+static int
+bt_atox(const char *a)
+{
+	int i = 0;
+	ENTER();
+	while (isxdigit(*a))
+		i = i * 16 + bt_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief Converts 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
+ */
+static void
+bt_mac2u8(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;
+	}
+	memcpy(mac_buff, buf, strlen(buf));
+
+	begin = mac_buff;
+	for (i = 0; i < ETH_ALEN; ++i) {
+		end = bt_strsep(&begin, ':', '/');
+		if (end)
+			mac_addr[i] = bt_atox(end);
+	}
+
+	kfree(mac_buff);
+	LEAVE();
+}
+
+/**
+ *  @brief Returns integer value of a given ascii string
+ *
+ *  @param data    Converted data to be returned
+ *  @param a       String to be converted
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_atoi(int *data, char *a)
+{
+	int i, val = 0, len;
+
+	ENTER();
+
+	len = strlen(a);
+	if (!strncmp(a, "0x", 2)) {
+		a = a + 2;
+		len -= 2;
+		*data = bt_atox(a);
+		return BT_STATUS_SUCCESS;
+	}
+	for (i = 0; i < len; i++) {
+		if (isdigit(a[i])) {
+			val = val * 10 + (a[i] - '0');
+		} else {
+			PRINTM(ERROR, "Invalid char %c in string %s\n", a[i],
+			       a);
+			return BT_STATUS_FAILURE;
+		}
+	}
+	*data = val;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief parse cal-data
+ *
+ *  @param src      a pointer to cal-data string
+ *  @param len      len of cal-data
+ *  @param dst      a pointer to return cal-data
+ *  @param dst_size size of dest buffer
+ *
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 *dst_size)
+{
+	const u8 *ptr;
+	u8 *dptr;
+	u32 count = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	ptr = src;
+	dptr = dst;
+
+	while ((ptr - src) < len) {
+		if (*ptr && isspace(*ptr)) {
+			ptr++;
+			continue;
+		}
+
+		if (isxdigit(*ptr)) {
+			if ((dptr - dst) >= *dst_size) {
+				PRINTM(ERROR, "cal_file size too big!!!\n");
+				goto done;
+			}
+			*dptr++ = bt_atox((const char *)ptr);
+			ptr += 2;
+			count++;
+		} else {
+			ptr++;
+		}
+	}
+	if (dptr == dst) {
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	*dst_size = count;
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT get one line data from ASCII format data
+ *
+ *    @param data         Source data
+ *    @param size         Source data length
+ *    @param line_pos     Destination data
+ *    @return             -1 or length of the line
+ */
+int
+parse_cfg_get_line(u8 *data, u32 size, u8 *line_pos)
+{
+	static s32 pos;
+	u8 *src, *dest;
+
+	if (pos >= size) {	/* reach the end */
+		pos = 0;	/* Reset position for rfkill */
+		return -1;
+	}
+	memset(line_pos, 0, MAX_LINE_LEN);
+	src = data + pos;
+	dest = line_pos;
+
+	while (pos < size && *src != '\x0A' && *src != '\0') {
+		if (*src != ' ' && *src != '\t')	/* parse space */
+			*dest++ = *src++;
+		else
+			src++;
+		pos++;
+	}
+	*dest = '\0';
+	/* parse new line */
+	pos++;
+	return strlen((const char *)line_pos);
+}
+
+/**
+ *    @brief BT parse ASCII format data to MAC address
+ *
+ *    @param priv          BT private handle
+ *    @param data          Source data
+ *    @param size          data length
+ *    @return              BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_init_cfg(bt_private *priv, u8 *data, u32 size)
+{
+	u8 *pos;
+	u8 *intf_s, *intf_e;
+	u8 s[MAX_LINE_LEN];	/* 1 line data */
+	u32 line_len;
+	char dev_name[MAX_PARAM_LEN];
+	u8 buf[MAX_PARAM_LEN];
+	u8 bt_addr[MAX_MAC_ADDR_LEN];
+	u8 bt_mac[ETH_ALEN];
+	int setting = 0;
+	u8 type = 0;
+	u16 value = 0;
+	u32 offset = 0;
+	int ret = BT_STATUS_FAILURE;
+
+	memset(dev_name, 0, sizeof(dev_name));
+	memset(bt_addr, 0, sizeof(bt_addr));
+	memset(bt_mac, 0, sizeof(bt_mac));
+
+	while ((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;	/* Need n't process this line */
+
+		/* Process MAC addr */
+		if (strncmp((char *)pos, "mac_addr", 8) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ':');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				if ((intf_e - intf_s) > MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Too long interface name %d\n",
+					       __LINE__);
+					goto done;
+				}
+				strncpy(dev_name, (const char *)intf_s + 1,
+					intf_e - intf_s - 1);
+				dev_name[intf_e - intf_s - 1] = '\0';
+				strncpy((char *)bt_addr,
+					(const char *)intf_e + 1,
+					MAX_MAC_ADDR_LEN - 1);
+				bt_addr[MAX_MAC_ADDR_LEN - 1] = '\0';
+				/* Convert MAC format */
+				bt_mac2u8(bt_mac, (char *)bt_addr);
+				PRINTM(CMD,
+				       "HCI: %s new BT Address " MACSTR "\n",
+				       dev_name, MAC2STR(bt_mac));
+				if (BT_STATUS_SUCCESS !=
+				    bt_set_mac_address(priv, bt_mac)) {
+					PRINTM(FATAL,
+					       "BT: Fail to set mac address\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+		}
+		/* Process REG value */
+		else if (strncmp((char *)pos, "bt_reg", 6) == 0) {
+			intf_s = (u8 *)strchr((const char *)pos, '=');
+			if (intf_s != NULL)
+				intf_e = (u8 *)strchr((const char *)intf_s,
+						      ',');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				/* Copy type */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s + 1,
+					1);
+				buf[1] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					type = (u8)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg type\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			intf_e = (u8 *)strchr((const char *)intf_s, ',');
+			if (intf_e != NULL) {
+				if ((intf_e - intf_s) >= MAX_PARAM_LEN) {
+					PRINTM(ERROR,
+					       "BT: Regsier offset is too long %d\n",
+					       __LINE__);
+					goto done;
+				}
+				/* Copy offset */
+				memset(buf, 0, sizeof(buf));
+				strncpy((char *)buf, (const char *)intf_s,
+					intf_e - intf_s);
+				buf[intf_e - intf_s] = '\0';
+				if (0 == bt_atoi(&setting, (char *)buf))
+					offset = (u32)setting;
+				else {
+					PRINTM(ERROR,
+					       "BT: Fail to parse reg offset\n");
+					goto done;
+				}
+			} else {
+				PRINTM(ERROR,
+				       "BT: Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			if ((strlen((const char *)intf_s) >= MAX_PARAM_LEN)) {
+				PRINTM(ERROR,
+				       "BT: Regsier value is too long %d\n",
+				       __LINE__);
+				goto done;
+			}
+			/* Copy value */
+			memset(buf, 0, sizeof(buf));
+			strncpy((char *)buf, (const char *)intf_s, sizeof(buf));
+			if (0 == bt_atoi(&setting, (char *)buf))
+				value = (u16) setting;
+			else {
+				PRINTM(ERROR, "BT: Fail to parse reg value\n");
+				goto done;
+			}
+
+			PRINTM(CMD,
+			       "BT: Write reg type: %d offset: 0x%x value: 0x%x\n",
+			       type, offset, value);
+			if (BT_STATUS_SUCCESS !=
+			    bt_write_reg(priv, type, offset, value)) {
+				PRINTM(FATAL,
+				       "BT: Write reg failed. type: %d offset: 0x%x value: 0x%x\n",
+				       type, offset, value);
+				goto done;
+			}
+		}
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief BT 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 bt_private structure
+ *
+ * @return          N/A
+ */
+static void
+bt_request_init_user_conf_callback(const struct firmware *firmware,
+				   void *context)
+{
+	bt_private *priv = (bt_private *)context;
+
+	ENTER();
+
+	if (!firmware)
+		PRINTM(ERROR, "BT user init config request firmware failed\n");
+
+	priv->init_user_cfg = firmware;
+	priv->init_user_conf_wait_flag = TRUE;
+	wake_up_interruptible(&priv->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *    @brief BT set user defined init data and param
+ *
+ *    @param priv     BT private handle
+ *    @param cfg_file user cofig file
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_config(bt_private *priv, char *cfg_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if ((request_firmware(&cfg, cfg_file, priv->hotplug_device)) < 0) {
+		PRINTM(FATAL, "BT: request_firmware() %s failed\n", cfg_file);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (cfg)
+		ret = bt_process_init_cfg(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg(bt_private *priv, u8 *data, u32 size, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	u8 cal_data[32];
+	u8 *mac_data = NULL;
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+	u8 *pcal_data = cal_data;
+
+	memset(bt_mac, 0, sizeof(bt_mac));
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (mac != NULL) {
+		/* Convert MAC format */
+		bt_mac2u8(bt_mac, mac);
+		PRINTM(CMD, "HCI: new BT Address " MACSTR "\n",
+		       MAC2STR(bt_mac));
+		mac_data = bt_mac;
+	}
+	if (BT_STATUS_SUCCESS != bt_load_cal_data(priv, pcal_data, mac_data)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT data
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param data    a pointer to cal data
+ *    @param size    cal data size
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_cal_cfg_ext(bt_private *priv, u8 *data, u32 size)
+{
+	u8 cal_data[128];
+	u32 cal_data_len;
+	int ret = BT_STATUS_FAILURE;
+
+	cal_data_len = sizeof(cal_data);
+	if (BT_STATUS_SUCCESS !=
+	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
+		goto done;
+	}
+	if (BT_STATUS_SUCCESS !=
+	    bt_load_cal_data_ext(priv, cal_data, cal_data_len)) {
+		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config(bt_private *priv, char *cal_file, char *mac)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size, mac);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT process calibration EXT file
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param cal_file calibration file name
+ *    @param mac     mac address buf
+ *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_cal_config_ext(bt_private *priv, char *cal_file)
+{
+	const struct firmware *cfg = NULL;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      bt_request_init_user_conf_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cal_file, priv->hotplug_device,
+					      priv,
+					      bt_request_init_user_conf_callback);
+#endif
+#endif
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: bt_cal_config_ext() failed, error code = %#x cal_file=%s\n",
+			       ret, cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->init_user_conf_wait_flag = FALSE;
+		wait_event_interruptible(priv->init_user_conf_wait_q,
+					 priv->init_user_conf_wait_flag);
+		cfg = priv->init_user_cfg;
+	} else {
+		if ((request_firmware(&cfg, cal_file, priv->hotplug_device)) <
+		    0) {
+			PRINTM(FATAL, "BT: request_firmware() %s failed\n",
+			       cal_file);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cfg)
+		ret = bt_process_cal_cfg_ext(priv, (u8 *)cfg->data, cfg->size);
+	else
+		ret = BT_STATUS_FAILURE;
+done:
+	if (cfg)
+		release_firmware(cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief BT init mac address from bt_mac parametre when insmod
+ *
+ *    @param priv    a pointer to bt_private structure
+ *    @param bt_mac  mac address buf
+ *    @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_init_mac_address(bt_private *priv, char *mac)
+{
+	u8 bt_mac[ETH_ALEN];
+	int ret = BT_STATUS_FAILURE;
+
+	ENTER();
+	memset(bt_mac, 0, sizeof(bt_mac));
+	bt_mac2u8(bt_mac, mac);
+	PRINTM(CMD, "HCI: New BT Address " MACSTR "\n", MAC2STR(bt_mac));
+	ret = bt_set_mac_address(priv, bt_mac);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(FATAL,
+		       "BT: Fail to set mac address from insmod parametre.\n");
+
+	LEAVE();
+	return ret;
+}
diff --git a/bt_sd8997/bt_char/bt_main.c b/bt_sd8997/bt_char/bt_main.c
new file mode 100644
index 0000000..1ac0fc2
--- /dev/null
+++ b/bt_sd8997/bt_char/bt_main.c
@@ -0,0 +1,3750 @@
+/** @file bt_main.c
+  *
+  * @brief This file contains the major functions in BlueTooth
+  * driver. It includes init, exit, open, close and main
+  * thread etc..
+  *
+  * Copyright (C) 2007-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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.
+  *
+  */
+/**
+  * @mainpage M-BT Linux Driver
+  *
+  * @section overview_sec Overview
+  *
+  * The M-BT is a Linux reference driver for Marvell Bluetooth chipset.
+  *
+  * @section copyright_sec Copyright
+  *
+  * Copyright (C) 2007-2018, Marvell International Ltd.
+  *
+  */
+#include <linux/module.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
+
+#include <linux/mmc/sdio_func.h>
+
+#include "bt_drv.h"
+#include "mbt_char.h"
+#include "bt_sdio.h"
+
+/** Version */
+#define VERSION "C3X14113"
+
+/** Driver version */
+static char mbt_driver_version[] = "SD8997-%s-" VERSION "-(" "FP" FPNUM ")"
+#ifdef DEBUG_LEVEL2
+	"-dbg"
+#endif
+	" ";
+
+/** Declare and initialize fw_version */
+static char fw_version[32] = "0.0.0.p0";
+
+#define AID_SYSTEM        1000	/* system server */
+
+#define AID_BLUETOOTH     1002	/* bluetooth subsystem */
+
+#define AID_NET_BT_STACK  3008	/* bluetooth stack */
+
+/** Define module name */
+
+#define MODULE_NAME  "bt_fm_nfc"
+
+/** Declaration of chardev class */
+static struct class *chardev_class;
+
+/** Interface specific variables */
+static int mbtchar_minor;
+static int debugchar_minor;
+
+/**
+ * The global variable of a pointer to bt_private
+ * structure variable
+ **/
+bt_private *m_priv[MAX_BT_ADAPTER];
+
+/** Default Driver mode */
+static int drv_mode = (DRV_MODE_BT);
+
+/** BT interface name */
+static char *bt_name;
+/** BT debug interface name */
+static char *debug_name;
+
+/** fw reload flag */
+int bt_fw_reload;
+/** fw serial download flag */
+int bt_fw_serial = 1;
+
+/** Firmware flag */
+static int fw = 1;
+/** default powermode */
+static int psmode = 1;
+/** default BLE deep sleep */
+static int deep_sleep = 1;
+/** Init config file (MAC address, register etc.) */
+static char *init_cfg;
+/** Calibration config file (MAC address, init powe etc.) */
+static char *cal_cfg;
+/** Calibration config file EXT */
+static char *cal_cfg_ext;
+/** Init MAC address */
+static char *bt_mac;
+static int btindrst = -1;
+
+/** Setting mbt_drvdbg value based on DEBUG level */
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define DEFAULT_DEBUG_MASK  (0xffffffff & ~DBG_EVENT)
+#else
+#define DEFAULT_DEBUG_MASK  (DBG_MSG | DBG_FATAL | DBG_ERROR)
+#endif /* DEBUG_LEVEL2 */
+u32 mbt_drvdbg = DEFAULT_DEBUG_MASK;
+#endif
+
+#ifdef CONFIG_OF
+static int dts_enable = 1;
+#endif
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+int mbt_pm_keep_power = 1;
+#endif
+
+static int debug_intf = 1;
+
+static int btpmic = 0;
+
+/** Offset of sequence number in event */
+#define OFFSET_SEQNUM 4
+
+/**
+ *  @brief handle received packet
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *
+ *  @return        N/A
+ */
+void
+bt_recv_frame(bt_private *priv, struct sk_buff *skb)
+{
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		mdev_recv_frame(skb);
+		mdev_bt->stat.byte_rx += skb->len;
+	}
+	return;
+}
+
+/**
+ *  @brief Alloc bt device
+ *
+ *  @return    pointer to structure mbt_dev or NULL
+ */
+struct mbt_dev *
+alloc_mbt_dev(void)
+{
+	struct mbt_dev *mbt_dev;
+	ENTER();
+
+	mbt_dev = kzalloc(sizeof(struct mbt_dev), GFP_KERNEL);
+	if (!mbt_dev) {
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return mbt_dev;
+}
+
+/**
+ *  @brief Alloc debug device
+ *
+ *  @return    pointer to structure debug_level or NULL
+ */
+struct debug_dev *
+alloc_debug_dev(void)
+{
+	struct debug_dev *debug_dev;
+	ENTER();
+
+	debug_dev = kzalloc(sizeof(struct debug_dev), GFP_KERNEL);
+	if (!debug_dev) {
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return debug_dev;
+}
+
+/**
+ *  @brief Frees m_dev
+ *
+ *  @return    N/A
+ */
+void
+free_m_dev(struct m_dev *m_dev)
+{
+	ENTER();
+	kfree(m_dev->dev_pointer);
+	m_dev->dev_pointer = NULL;
+	LEAVE();
+}
+
+/**
+ *  @brief clean up m_devs
+ *
+ *  @return    N/A
+ */
+void
+clean_up_m_devs(bt_private *priv)
+{
+	struct m_dev *m_dev = NULL;
+	int i;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+		PRINTM(MSG, "BT: Delete %s\n", m_dev->name);
+		if (m_dev->spec_type == IANYWHERE_SPEC) {
+			if ((drv_mode & DRV_MODE_BT) && (mbtchar_minor > 0))
+				mbtchar_minor--;
+			m_dev->close(m_dev);
+			for (i = 0; i < 3; i++)
+				kfree_skb(((struct mbt_dev *)
+					   (m_dev->dev_pointer))->
+					  reassembly[i]);
+			/**  unregister m_dev to char_dev */
+			if (chardev_class)
+				chardev_cleanup_one(m_dev, chardev_class);
+			free_m_dev(m_dev);
+		}
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = NULL;
+	}
+	if (priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer) {
+		m_dev = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
+		PRINTM(MSG, "BT: Delete %s\n", m_dev->name);
+		if ((debug_intf) && (debugchar_minor > 0))
+			debugchar_minor--;
+		/** unregister m_dev to char_dev */
+		if (chardev_class)
+			chardev_cleanup_one(m_dev, chardev_class);
+		free_m_dev(m_dev);
+		priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer = NULL;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function verify the received event pkt
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+--------+
+ *  | Event  | Length |  ncmd  |      Opcode     |
+ *  +--------+--------+--------+--------+--------+
+ *  | 1-byte | 1-byte | 1-byte |      2-byte     |
+ *  +--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+check_evtpkt(bt_private *priv, struct sk_buff *skb)
+{
+	struct hci_event_hdr *hdr = (struct hci_event_hdr *)skb->data;
+	struct hci_ev_cmd_complete *ec;
+	u16 opcode, ocf;
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (!priv->bt_dev.sendcmdflag) {
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	if (hdr->evt == HCI_EV_CMD_COMPLETE) {
+		ec = (struct hci_ev_cmd_complete *)
+			(skb->data + HCI_EVENT_HDR_SIZE);
+		opcode = __le16_to_cpu(ec->opcode);
+		ocf = hci_opcode_ocf(opcode);
+		PRINTM(CMD,
+		       "BT: CMD_COMPLTE opcode=0x%x, ocf=0x%x, send_cmd_opcode=0x%x\n",
+		       opcode, ocf, priv->bt_dev.send_cmd_opcode);
+		if (opcode != priv->bt_dev.send_cmd_opcode) {
+			ret = BT_STATUS_FAILURE;
+			goto exit;
+		}
+		switch (ocf) {
+		case BT_CMD_MODULE_CFG_REQ:
+		case BT_CMD_BLE_DEEP_SLEEP:
+		case BT_CMD_CONFIG_MAC_ADDR:
+		case BT_CMD_CSU_WRITE_REG:
+		case BT_CMD_LOAD_CONFIG_DATA:
+		case BT_CMD_LOAD_CONFIG_DATA_EXT:
+		case BT_CMD_AUTO_SLEEP_MODE:
+		case BT_CMD_HOST_SLEEP_CONFIG:
+		case BT_CMD_SDIO_PULL_CFG_REQ:
+		case BT_CMD_SET_EVT_FILTER:
+		case BT_CMD_ENABLE_WRITE_SCAN:
+			// case BT_CMD_ENABLE_DEVICE_TESTMODE:
+		case BT_CMD_RESET:
+		case BT_CMD_PMIC_CONFIGURE:
+		case BT_CMD_INDEPENDENT_RESET:
+			priv->bt_dev.sendcmdflag = FALSE;
+			priv->adapter->cmd_complete = TRUE;
+			wake_up_interruptible(&priv->adapter->cmd_wait_q);
+			break;
+		case BT_CMD_GET_FW_VERSION:
+			{
+				u8 *pos = (skb->data + HCI_EVENT_HDR_SIZE +
+					   sizeof(struct hci_ev_cmd_complete) +
+					   1);
+				snprintf(fw_version, sizeof(fw_version),
+					 "%u.%u.%u.p%u", pos[2], pos[1], pos[0],
+					 pos[3]);
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+				break;
+			}
+		case BT_CMD_HISTOGRAM:
+			{
+				u8 *status =
+					skb->data + HCI_EVENT_HDR_SIZE +
+					sizeof(struct hci_ev_cmd_complete);
+				u8 *pos =
+					(skb->data + HCI_EVENT_HDR_SIZE +
+					 sizeof(struct hci_ev_cmd_complete) +
+					 1);
+				if (*status == 0) {
+					priv->hist_data_len =
+						hdr->plen -
+						sizeof(struct
+						       hci_ev_cmd_complete) - 1;
+					if (priv->hist_data_len >
+					    sizeof(priv->hist_data))
+						priv->hist_data_len =
+							sizeof(priv->hist_data);
+					memcpy(priv->hist_data, pos,
+					       priv->hist_data_len);
+					PRINTM(CMD, "histogram len=%d\n",
+					       priv->hist_data_len);
+				}
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+				break;
+			}
+		case BT_CMD_HOST_SLEEP_ENABLE:
+			priv->bt_dev.sendcmdflag = FALSE;
+			break;
+		default:
+			/** Ignore command not defined but send by driver */
+			if (opcode == priv->bt_dev.send_cmd_opcode) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			} else {
+				ret = BT_STATUS_FAILURE;
+			}
+			break;
+		}
+	}
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+*  @brief This function stores the FW dumps received from events in a file
+*
+*  @param priv    A pointer to bt_private structure
+*  @param skb     A pointer to rx skb
+*
+*  @return        N/A
+*/
+void
+bt_store_firmware_dump(bt_private *priv, u8 *buf, u32 len)
+{
+	struct file *pfile_fwdump = NULL;
+	loff_t pos = 0;
+	u16 seqnum = 0;
+	struct timeval t;
+	u32 sec;
+
+	ENTER();
+
+	seqnum = __le16_to_cpu(*(u16 *) (buf + OFFSET_SEQNUM));
+
+	if (priv->adapter->fwdump_fname && seqnum != 1) {
+		pfile_fwdump =
+			filp_open((const char *)priv->adapter->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		if (IS_ERR(pfile_fwdump)) {
+			PRINTM(MSG, "Cannot create firmware dump file.\n");
+			LEAVE();
+			return;
+		}
+	} else {
+		if (!priv->adapter->fwdump_fname) {
+			gfp_t flag;
+			flag = (in_atomic() ||
+				irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+			priv->adapter->fwdump_fname = kzalloc(64, flag);
+		} else
+			memset(priv->adapter->fwdump_fname, 0, 64);
+
+		do_gettimeofday(&t);
+		sec = (u32)t.tv_sec;
+		sprintf(priv->adapter->fwdump_fname, "%s%u",
+			"/var/log/bt_fwdump_", sec);
+		pfile_fwdump =
+			filp_open(priv->adapter->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		if (IS_ERR(pfile_fwdump)) {
+			sprintf(priv->adapter->fwdump_fname, "%s%u",
+				"/data/bt_fwdump_", sec);
+			pfile_fwdump =
+				filp_open((const char *)priv->adapter->
+					  fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+		}
+	}
+
+	if (IS_ERR(pfile_fwdump)) {
+		PRINTM(MSG, "Cannot create firmware dump file\n");
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile_fwdump, buf, len, &pos);
+#else
+	kernel_write(pfile_fwdump, buf, len, &pos);
+#endif
+	filp_close(pfile_fwdump, NULL);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function process the received event
+ *
+ *  Event format:
+ *  +--------+--------+--------+--------+-----+
+ *  |   EC   | Length |           Data        |
+ *  +--------+--------+--------+--------+-----+
+ *  | 1-byte | 1-byte |          n-byte       |
+ *  +--------+--------+--------+--------+-----+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to rx skb
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_process_event(bt_private *priv, struct sk_buff *skb)
+{
+	int ret = BT_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	BT_EVENT *pevent;
+
+	ENTER();
+	if (!m_dev) {
+		PRINTM(CMD, "BT: bt_process_event without m_dev\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pevent = (BT_EVENT *)skb->data;
+	if (pevent->EC != 0xff) {
+		PRINTM(CMD, "BT: Not Marvell Event=0x%x\n", pevent->EC);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	switch (pevent->data[0]) {
+	case BT_CMD_HISTOGRAM:
+		break;
+	case BT_CMD_AUTO_SLEEP_MODE:
+		if (pevent->data[2] == BT_STATUS_SUCCESS) {
+			if (pevent->data[1] == BT_PS_ENABLE)
+				priv->adapter->psmode = 1;
+			else
+				priv->adapter->psmode = 0;
+			PRINTM(CMD, "BT: PS Mode %s:%s\n", m_dev->name,
+			       (priv->adapter->psmode) ? "Enable" : "Disable");
+
+		} else {
+			PRINTM(CMD, "BT: PS Mode Command Fail %s\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_CONFIG:
+		if (pevent->data[3] == BT_STATUS_SUCCESS) {
+			PRINTM(CMD, "BT: %s: gpio=0x%x, gap=0x%x\n",
+			       m_dev->name, pevent->data[1], pevent->data[2]);
+		} else {
+			PRINTM(CMD, "BT: %s: HSCFG Command Fail\n",
+			       m_dev->name);
+		}
+		break;
+	case BT_CMD_HOST_SLEEP_ENABLE:
+		if (pevent->data[1] == BT_STATUS_SUCCESS) {
+			priv->adapter->hs_state = HS_ACTIVATED;
+			if (priv->adapter->suspend_fail == FALSE) {
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+				bt_is_suspended(priv);
+#endif
+#endif
+#endif
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			}
+			if (priv->adapter->psmode)
+				priv->adapter->ps_state = PS_SLEEP;
+			PRINTM(CMD, "BT: EVENT %s: HS ACTIVATED!\n",
+			       m_dev->name);
+
+		} else {
+			PRINTM(CMD, "BT: %s: HS Enable Fail\n", m_dev->name);
+		}
+		break;
+	case BT_CMD_MODULE_CFG_REQ:
+		if ((priv->bt_dev.sendcmdflag == TRUE) &&
+		    ((pevent->data[1] == MODULE_BRINGUP_REQ)
+		     || (pevent->data[1] == MODULE_SHUTDOWN_REQ))) {
+			if (pevent->data[1] == MODULE_BRINGUP_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2] && (pevent->data[2] !=
+							    MODULE_CFG_RESP_ALREADY_UP))
+				       ? "Bring up Fail" : "Bring up success");
+				priv->bt_dev.devType = pevent->data[3];
+				PRINTM(CMD, "devType:%s\n",
+				       (pevent->data[3] ==
+					DEV_TYPE_AMP) ? "AMP controller" :
+				       "BR/EDR controller");
+				priv->bt_dev.devFeature = pevent->data[4];
+				PRINTM(CMD, "devFeature:  %s,    %s,    %s"
+				       "\n",
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BT) ?
+					"BT Feature" : "No BT Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BTAMP) ?
+					"BTAMP Feature" : "No BTAMP Feature"),
+				       ((pevent->
+					 data[4] & DEV_FEATURE_BLE) ?
+					"BLE Feature" : "No BLE Feature")
+					);
+			}
+			if (pevent->data[1] == MODULE_SHUTDOWN_REQ) {
+				PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+				       (pevent->data[2]) ? "Shut down Fail"
+				       : "Shut down success");
+
+			}
+			if (pevent->data[2]) {
+				priv->bt_dev.sendcmdflag = FALSE;
+				priv->adapter->cmd_complete = TRUE;
+				wake_up_interruptible(&priv->adapter->
+						      cmd_wait_q);
+			}
+		} else {
+			PRINTM(CMD, "BT_CMD_MODULE_CFG_REQ resp for APP\n");
+			ret = BT_STATUS_FAILURE;
+		}
+		break;
+	case BT_EVENT_POWER_STATE:
+		if (pevent->data[1] == BT_PS_SLEEP)
+			priv->adapter->ps_state = PS_SLEEP;
+		PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
+		       (priv->adapter->ps_state) ? "PS_SLEEP" : "PS_AWAKE");
+
+		break;
+	case BT_CMD_SDIO_PULL_CFG_REQ:
+		if (pevent->data[pevent->length - 1] == BT_STATUS_SUCCESS)
+			PRINTM(CMD, "BT: %s: SDIO pull configuration success\n",
+			       m_dev->name);
+
+		else {
+			PRINTM(CMD, "BT: %s: SDIO pull configuration fail\n",
+			       m_dev->name);
+
+		}
+		break;
+	default:
+		PRINTM(CMD, "BT: Unknown Event=%d %s\n", pevent->data[0],
+		       m_dev->name);
+		ret = BT_STATUS_FAILURE;
+		break;
+	}
+exit:
+	if (ret == BT_STATUS_SUCCESS)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function save the dump info to file
+ *
+ *  @param dir_name     directory name
+ *  @param file_name    file_name
+ *  @param buf			buffer
+ *  @param buf_len		buffer length
+ *
+ *  @return   		    0 --success otherwise fail
+ */
+int
+bt_save_dump_info_to_file(char *dir_name, char *file_name, u8 *buf, u32 buf_len)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct file *pfile = NULL;
+	u8 name[64];
+	loff_t pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	if (!dir_name || !file_name || !buf) {
+		PRINTM(ERROR, "Can't save dump info to file\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(name, 0, sizeof(name));
+	sprintf((char *)name, "%s/%s", dir_name, file_name);
+	pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MSG,
+		       "Create file %s error, try to save dump file in /var\n",
+		       name);
+		memset(name, 0, sizeof(name));
+		sprintf((char *)name, "%s/%s", "/var", file_name);
+		pfile = filp_open((const char *)name, O_CREAT | O_RDWR, 0644);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(ERROR, "Create Dump file for %s error\n", name);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MSG, "Dump data %s saved in %s\n", file_name, name);
+
+	pos = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	vfs_write(pfile, (const char __user *)buf, buf_len, &pos);
+	set_fs(fs);
+#else
+	kernel_write(pfile, (const char __user *)buf, buf_len, &pos);
+#endif
+	filp_close(pfile, NULL);
+
+	PRINTM(MSG, "Dump data %s saved in %s successfully\n", file_name, name);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#define DEBUG_HOST_READY		0xEE
+#define DEBUG_FW_DONE			0xFF
+#define DUMP_MAX_POLL_TRIES			200
+
+#define DEBUG_DUMP_CTRL_REG               0xF0
+#define DEBUG_DUMP_START_REG              0xF1
+#define DEBUG_DUMP_END_REG                0xF8
+
+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
+#define MAX_FULL_NAME_LEN               32
+
+/** Memory type mapping structure */
+typedef struct {
+	/** memory name */
+	u8 mem_name[MAX_NAME_LEN];
+	/** memory pointer */
+	u8 *mem_Ptr;
+	/** file structure */
+	struct file *pfile_mem;
+	/** donbe flag */
+	u8 done_flag;
+} memory_type_mapping;
+
+memory_type_mapping bt_mem_type_mapping_tbl[] = {
+	{"ITCM", NULL, NULL, 0xF0},
+	{"DTCM", NULL, NULL, 0xF1},
+	{"SQRAM", NULL, NULL, 0xF2},
+	{"APU", NULL, NULL, 0xF3},
+	{"CIU", NULL, NULL, 0xF4},
+	{"ICU", NULL, NULL, 0xF5},
+	{"MAC", NULL, NULL, 0xF6},
+	{"EXT7", NULL, NULL, 0xF7},
+	{"EXT8", NULL, NULL, 0xF8},
+	{"EXT9", NULL, NULL, 0xF9},
+	{"EXT10", NULL, NULL, 0xFA},
+	{"EXT11", NULL, NULL, 0xFB},
+	{"EXT12", NULL, NULL, 0xFC},
+	{"EXT13", NULL, NULL, 0xFD},
+	{"EXTLAST", NULL, NULL, 0xFE},
+};
+
+typedef enum {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+} rdwr_status;
+
+/**
+ *  @brief This function read/write firmware via cmd52
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+rdwr_status
+bt_cmd52_rdwr_firmware(bt_private *priv, u8 doneflag)
+{
+	int ret = 0;
+	int tries = 0;
+	u8 ctrl_data = 0;
+	u8 dbg_dump_ctrl_reg = 0;
+
+	dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG;
+
+	sdio_writeb(((struct sdio_mmc_card *)priv->bt_dev.card)->func,
+		    DEBUG_HOST_READY, dbg_dump_ctrl_reg, &ret);
+	if (ret) {
+		PRINTM(ERROR, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	for (tries = 0; tries < DUMP_MAX_POLL_TRIES; tries++) {
+		ctrl_data =
+			sdio_readb(((struct sdio_mmc_card *)priv->bt_dev.card)->
+				   func, dbg_dump_ctrl_reg, &ret);
+		if (ret) {
+			PRINTM(ERROR, "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(INFO,
+			       "The ctrl reg was changed, re-try again!\n");
+			sdio_writeb(((struct sdio_mmc_card *)priv->bt_dev.
+				     card)->func, DEBUG_HOST_READY,
+				    dbg_dump_ctrl_reg, &ret);
+			if (ret) {
+				PRINTM(ERROR, "SDIO Write ERR\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		udelay(100);
+	}
+	if (ctrl_data == DEBUG_HOST_READY) {
+		PRINTM(ERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	return RDWR_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_firmware_info_v2(bt_private *priv)
+{
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	u8 *dbg_ptr = NULL;
+	u8 dump_num = 0;
+	u8 idx = 0;
+	u8 doneflag = 0;
+	rdwr_status stat;
+	u8 i = 0;
+	u8 read_reg = 0;
+	u32 memory_size = 0;
+	u8 path_name[64], file_name[32];
+	u8 *end_ptr = NULL;
+	u8 dbg_dump_start_reg = 0;
+	u8 dbg_dump_end_reg = 0;
+
+	if (!priv) {
+		PRINTM(ERROR, "Could not dump firmwware info\n");
+		return;
+	}
+
+	memset(path_name, 0, sizeof(path_name));
+	strcpy((char *)path_name, "/data");
+	PRINTM(MSG, "Create DUMP directory success:dir_name=%s\n", path_name);
+
+	dbg_dump_start_reg = DEBUG_DUMP_START_REG;
+	dbg_dump_end_reg = DEBUG_DUMP_END_REG;
+
+	sbi_wakeup_firmware(priv);
+	sdio_claim_host(((struct sdio_mmc_card *)priv->bt_dev.card)->func);
+	/* start dump fw memory */
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT START ====\n");
+	/* read the number of the memories which will dump */
+	if (RDWR_STATUS_FAILURE == bt_cmd52_rdwr_firmware(priv, doneflag))
+		goto done;
+	reg = dbg_dump_start_reg;
+	dump_num =
+		sdio_readb(((struct sdio_mmc_card *)priv->bt_dev.card)->func,
+			   reg, &ret);
+	if (ret) {
+		PRINTM(MSG, "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 ==
+		    bt_cmd52_rdwr_firmware(priv, doneflag))
+			goto done;
+		memory_size = 0;
+		reg = dbg_dump_start_reg;
+		for (i = 0; i < 4; i++) {
+			read_reg =
+				sdio_readb(((struct sdio_mmc_card *)priv->
+					    bt_dev.card)->func, reg, &ret);
+			if (ret) {
+				PRINTM(MSG, "SDIO READ ERR\n");
+				goto done;
+			}
+			memory_size |= (read_reg << i * 8);
+			reg++;
+		}
+		if (memory_size == 0) {
+			PRINTM(MSG, "Firmware Dump Finished!\n");
+			break;
+		} else {
+			PRINTM(MSG, "%s_SIZE=0x%x\n",
+			       bt_mem_type_mapping_tbl[idx].mem_name,
+			       memory_size);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr =
+				vmalloc(memory_size + 1);
+			if ((ret != BT_STATUS_SUCCESS) ||
+			    !bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+				PRINTM(ERROR,
+				       "Error: vmalloc %s buffer failed!!!\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name);
+				goto done;
+			}
+			dbg_ptr = bt_mem_type_mapping_tbl[idx].mem_Ptr;
+			end_ptr = dbg_ptr + memory_size;
+		}
+		doneflag = bt_mem_type_mapping_tbl[idx].done_flag;
+		PRINTM(MSG, "Start %s output, please wait...\n",
+		       bt_mem_type_mapping_tbl[idx].mem_name);
+		do {
+			stat = bt_cmd52_rdwr_firmware(priv, 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++) {
+				*dbg_ptr =
+					sdio_readb(((struct sdio_mmc_card *)
+						    priv->bt_dev.card)->func,
+						   reg, &ret);
+				if (ret) {
+					PRINTM(MSG, "SDIO READ ERR\n");
+					goto done;
+				}
+				if (dbg_ptr < end_ptr)
+					dbg_ptr++;
+				else
+					PRINTM(MSG,
+					       "pre-allocced buf is not enough\n");
+			}
+			if (RDWR_STATUS_DONE == stat) {
+				PRINTM(MSG, "%s done:"
+				       "size = 0x%x\n",
+				       bt_mem_type_mapping_tbl[idx].mem_name,
+				       (unsigned int)(dbg_ptr -
+						      bt_mem_type_mapping_tbl
+						      [idx].mem_Ptr));
+				memset(file_name, 0, sizeof(file_name));
+				sprintf((char *)file_name, "%s%s", "file_bt_",
+					bt_mem_type_mapping_tbl[idx].mem_name);
+				if (BT_STATUS_SUCCESS !=
+				    bt_save_dump_info_to_file((char *)path_name,
+							      (char *)file_name,
+							      bt_mem_type_mapping_tbl
+							      [idx].mem_Ptr,
+							      memory_size))
+					PRINTM(MSG,
+					       "Can't save dump file %s in %s\n",
+					       file_name, path_name);
+				vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+				bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+				break;
+			}
+		} while (1);
+	}
+	PRINTM(MSG, "==== DEBUG MODE OUTPUT END ====\n");
+	/* end dump fw memory */
+done:
+	sdio_release_host(((struct sdio_mmc_card *)priv->bt_dev.card)->func);
+	for (idx = 0; idx < dump_num; idx++) {
+		if (bt_mem_type_mapping_tbl[idx].mem_Ptr) {
+			vfree(bt_mem_type_mapping_tbl[idx].mem_Ptr);
+			bt_mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+		}
+	}
+	PRINTM(MSG, "==== DEBUG MODE END ====\n");
+	return;
+}
+
+/**
+ *  @brief This function shows debug info for timeout of command sending.
+ *
+ *  @param adapter  A pointer to bt_private
+ *  @param cmd      Timeout command id
+ *
+ *  @return         N/A
+ */
+static void
+bt_cmd_timeout_func(bt_private *priv, u16 cmd)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+
+	adapter->num_cmd_timeout++;
+
+	PRINTM(ERROR, "Version = %s\n", adapter->drv_ver);
+	PRINTM(ERROR, "Timeout Command id = 0x%x\n", cmd);
+	PRINTM(ERROR, "Number of command timeout = %d\n",
+	       adapter->num_cmd_timeout);
+	PRINTM(ERROR, "Interrupt counter = %d\n", adapter->IntCounter);
+	PRINTM(ERROR, "Power Save mode = %d\n", adapter->psmode);
+	PRINTM(ERROR, "Power Save state = %d\n", adapter->ps_state);
+	PRINTM(ERROR, "Host Sleep state = %d\n", adapter->hs_state);
+	PRINTM(ERROR, "hs skip count = %d\n", adapter->hs_skip);
+	PRINTM(ERROR, "suspend_fail flag = %d\n", adapter->suspend_fail);
+	PRINTM(ERROR, "suspended flag = %d\n", adapter->is_suspended);
+	PRINTM(ERROR, "Number of wakeup tries = %d\n", adapter->WakeupTries);
+	PRINTM(ERROR, "Host Cmd complet state = %d\n", adapter->cmd_complete);
+	PRINTM(ERROR, "Last irq recv = %d\n", adapter->irq_recv);
+	PRINTM(ERROR, "Last irq processed = %d\n", adapter->irq_done);
+	PRINTM(ERROR, "tx pending = %d\n", adapter->skb_pending);
+	PRINTM(ERROR, "sdio int status = %d\n", adapter->sd_ireg);
+	bt_dump_sdio_regs(priv);
+	LEAVE();
+}
+
+/**
+ *  @brief This function queue frame
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    N/A
+ */
+static void
+bt_queue_frame(bt_private *priv, struct sk_buff *skb)
+{
+	skb_queue_tail(&priv->adapter->tx_queue, skb);
+}
+
+/**
+ *  @brief This function send reset cmd to firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return	       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_reset_command(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((RESET_OGF << 10) | BT_CMD_RESET);
+	pcmd->length = 0x00;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, 3);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue Reset Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Reset timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_RESET);
+	} else {
+		PRINTM(CMD, "BT: Reset Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends module cfg cmd to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param subcmd  sub command
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_module_cfg_cmd(bt_private *priv, int subcmd)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_MODULE_CFG_REQ);
+	pcmd->length = 1;
+	pcmd->data[0] = subcmd;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "Queue module cfg Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	/*
+	   On some Android platforms certain delay is needed for HCI daemon to
+	   remove this module and close itself gracefully. Otherwise it hangs.
+	   This 10ms delay is a workaround for such platforms as the root cause
+	   has not been found yet. */
+	mdelay(10);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: module_cfg_cmd(%#x): timeout sendcmdflag=%d\n",
+		       subcmd, priv->bt_dev.sendcmdflag);
+		bt_cmd_timeout_func(priv, BT_CMD_MODULE_CFG_REQ);
+	} else {
+		PRINTM(CMD, "BT: module cfg Command done\n");
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function to get histogram
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_get_histogram(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HISTOGRAM);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Histogram cmd(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	priv->hist_data_len = 0;
+	memset(priv->hist_data, 0, sizeof(priv->hist_data));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: histogram timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HISTOGRAM);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables power save mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_ps(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_AUTO_SLEEP_MODE);
+	if (priv->bt_dev.psmode)
+		pcmd->data[0] = BT_PS_ENABLE;
+	else
+		pcmd->data[0] = BT_PS_DISABLE;
+	if (priv->bt_dev.idle_timeout) {
+		pcmd->length = 3;
+		pcmd->data[1] = (u8)(priv->bt_dev.idle_timeout & 0x00ff);
+		pcmd->data[2] = (priv->bt_dev.idle_timeout & 0xff00) >> 8;
+	} else {
+		pcmd->length = 1;
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PSMODE Command(0x%x):%d\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: psmode timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_AUTO_SLEEP_MODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends hscfg command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_hscfg_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_CONFIG);
+	pcmd->length = 2;
+	pcmd->data[0] = (priv->bt_dev.gpio_gap & 0xff00) >> 8;
+	pcmd->data[1] = (u8)(priv->bt_dev.gpio_gap & 0x00ff);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue HSCFG Command(0x%x),gpio=0x%x,gap=0x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[0], pcmd->data[1]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: HSCFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_CONFIG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends sdio pull ctrl command
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_send_sdio_pull_ctrl_cmd(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_SDIO_PULL_CFG_REQ);
+	pcmd->length = 4;
+	pcmd->data[0] = (priv->bt_dev.sdio_pull_cfg & 0x000000ff);
+	pcmd->data[1] = (priv->bt_dev.sdio_pull_cfg & 0x0000ff00) >> 8;
+	pcmd->data[2] = (priv->bt_dev.sdio_pull_cfg & 0x00ff0000) >> 16;
+	pcmd->data[3] = (priv->bt_dev.sdio_pull_cfg & 0xff000000) >> 24;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD,
+	       "Queue SDIO PULL CFG Command(0x%x), PullUp=0x%x%x,PullDown=0x%x%x\n",
+	       __le16_to_cpu(pcmd->ocf_ogf), pcmd->data[1], pcmd->data[0],
+	       pcmd->data[3], pcmd->data[2]);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: SDIO PULL CFG timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SDIO_PULL_CFG_REQ);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends command to configure PMIC
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_pmic_configure(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_PMIC_CONFIGURE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue PMIC Configure Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: PMIC Configure timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_PMIC_CONFIGURE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables host sleep
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_hs(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	priv->adapter->suspend_fail = FALSE;
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_ENABLE);
+	pcmd->length = 0;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	PRINTM(CMD, "Queue hs enable Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->hs_state,
+	     WAIT_UNTIL_HS_STATE_CHANGED)) {
+		PRINTM(MSG, "BT: Enable host sleep timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_HOST_SLEEP_ENABLE);
+	}
+	OS_INT_DISABLE;
+	if ((priv->adapter->hs_state == HS_ACTIVATED) ||
+	    (priv->adapter->is_suspended == TRUE)) {
+		OS_INT_RESTORE;
+		PRINTM(MSG, "BT: suspend success! skip=%d\n",
+		       priv->adapter->hs_skip);
+	} else {
+		priv->adapter->suspend_fail = TRUE;
+		OS_INT_RESTORE;
+		priv->adapter->hs_skip++;
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG,
+		       "BT: suspend skipped! "
+		       "state=%d skip=%d ps_state= %d WakeupTries=%d\n",
+		       priv->adapter->hs_state, priv->adapter->hs_skip,
+		       priv->adapter->ps_state, priv->adapter->WakeupTries);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Set Evt Filter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_evt_filter(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_SET_EVT_FILTER);
+	pcmd->length = 0x03;
+	pcmd->data[0] = 0x02;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Set Evt Filter Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set Evt Filter timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_SET_EVT_FILTER);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Write Scan - Page and Inquiry
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_write_scan(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf = __cpu_to_le16((0x03 << 10) | BT_CMD_ENABLE_WRITE_SCAN);
+	pcmd->length = 0x01;
+	pcmd->data[0] = 0x03;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue Enable Write Scan Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Write Scan timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_WRITE_SCAN);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function Enable Device under test mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_device_under_testmode(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((0x06 << 10) | BT_CMD_ENABLE_DEVICE_TESTMODE);
+	pcmd->length = 0x00;
+	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	PRINTM(CMD, "Queue enable device under testmode Command(0x%x)\n",
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Enable Device under TEST mode timeout\n");
+		bt_cmd_timeout_func(priv, BT_CMD_ENABLE_DEVICE_TESTMODE);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables test mode and send cmd
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_enable_test_mode(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	/** Set Evt Filter Command */
+	ret = bt_set_evt_filter(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Set Evt filter fail\n");
+		goto exit;
+	}
+
+	/** Enable Write Scan Command */
+	ret = bt_enable_write_scan(priv);
+	if (ret != BT_STATUS_SUCCESS) {
+		PRINTM(ERROR, "BT test_mode: Enable Write Scan fail\n");
+		goto exit;
+	}
+
+	/** Enable Device under test mode */
+	ret = bt_enable_device_under_testmode(priv);
+	if (ret != BT_STATUS_SUCCESS)
+		PRINTM(ERROR,
+		       "BT test_mode: Enable device under testmode fail\n");
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+#define DISABLE_RESET  0x0
+#define ENABLE_OUTBAND_RESET 0x1
+#define ENABLE_INBAND_RESET  0x02
+#define DEFAULT_GPIO 0xff
+/**
+ *  @brief This function set GPIO pin
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_independent_reset(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	u8 mode, gpio;
+	BT_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_INDEPENDENT_RESET);
+	mode = btindrst & 0xff;
+	gpio = (btindrst & 0xff00) >> 8;
+	if (mode == ENABLE_OUTBAND_RESET) {
+		pcmd->data[0] = ENABLE_OUTBAND_RESET;
+		if (!gpio)
+			pcmd->data[1] = DEFAULT_GPIO;
+		else
+			pcmd->data[1] = gpio;
+	} else if (mode == ENABLE_INBAND_RESET) {
+		pcmd->data[0] = ENABLE_INBAND_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else if (mode == DISABLE_RESET) {
+		pcmd->data[0] = DISABLE_RESET;
+		pcmd->data[1] = DEFAULT_GPIO;
+	} else {
+		PRINTM(WARN, "Unsupport mode\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	PRINTM(CMD, "BT: independant reset mode=%d gpio=%d\n", mode, gpio);
+	pcmd->length = 2;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Independent reset : timeout!\n");
+		bt_cmd_timeout_func(priv, BT_CMD_INDEPENDENT_RESET);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets ble deepsleep mode
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mode    TRUE/FALSE
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_ble_deepsleep(bt_private *priv, int mode)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_BLE_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_BLE_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_BLE_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_BLE_DEEP_SLEEP);
+	pcmd->length = 1;
+	pcmd->deepsleep = mode;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_BLE_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set BLE deepsleep = %d (0x%x)\n", mode,
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set BLE deepsleep timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_BLE_DEEP_SLEEP);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets FW version
+ *
+ *  @param priv    A pointer to bt_private structure
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_get_fw_version(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_GET_FW_VERSION);
+	pcmd->length = 0x01;
+	pcmd->cmd_type = 0x00;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, 4);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout(priv->adapter->cmd_wait_q,
+					   priv->adapter->cmd_complete,
+					   WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Get FW version: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_GET_FW_VERSION);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets mac address
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_set_mac_address(bt_private *priv, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_HCI_CMD *pcmd;
+	int i = 0;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_HCI_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CONFIG_MAC_ADDR);
+	pcmd->length = 8;
+	pcmd->cmd_type = MRVL_VENDOR_PKT;
+	pcmd->cmd_len = 6;
+	for (i = 0; i < 6; i++)
+		pcmd->data[i] = mac[5 - i];
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_HCI_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set mac addr " MACSTR " (0x%x)\n", MAC2STR(mac),
+	       __le16_to_cpu(pcmd->ocf_ogf));
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(MSG, "BT: Set mac addr: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CONFIG_MAC_ADDR);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data(bt_private *priv, u8 *config_data, u8 *mac)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+	int i = 0;
+	/* u8 config_data[28] = {0x37 0x01 0x1c 0x00 0xFF 0xFF 0xFF 0xFF 0x01
+	   0x7f 0x04 0x02 0x00 0x00 0xBA 0xCE 0xC0 0xC6 0x2D 0x00 0x00 0x00
+	   0x00 0x00 0x00 0x00 0xF0}; */
+
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA);
+	pcmd->length = 0x20;
+	pcmd->data[0] = 0x00;
+	pcmd->data[1] = 0x00;
+	pcmd->data[2] = 0x00;
+	pcmd->data[3] = 0x1C;
+	/* swip cal-data byte */
+	for (i = 4; i < 32; i++)
+		pcmd->data[i] = *(config_data + ((i / 4) * 8 - 1 - i));
+	if (mac != NULL) {
+		pcmd->data[2] = 0x01;	/* skip checksum */
+		for (i = 24; i < 30; i++)
+			pcmd->data[i] = mac[29 - i];
+	}
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate data: ", pcmd->data, 32);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function load the calibrate EXT data
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param config_data     A pointer to calibrate data
+ *  @param mac     A pointer to mac address
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_load_cal_data_ext(bt_private *priv, u8 *config_data, u32 cfg_data_len)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CMD *pcmd;
+
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA_EXT);
+	pcmd->length = cfg_data_len;
+
+	memcpy(pcmd->data, config_data, cfg_data_len);
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+
+	DBG_HEXDUMP(DAT_D, "calirate ext data", pcmd->data, pcmd->length);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Load calibrate ext data: timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_LOAD_CONFIG_DATA_EXT);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function writes value to CSU registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param type    reg type
+ *  @param offset  register address
+ *  @param value   register value to write
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_write_reg(bt_private *priv, u8 type, u32 offset, u16 value)
+{
+	struct sk_buff *skb = NULL;
+	int ret = BT_STATUS_SUCCESS;
+	BT_CSU_CMD *pcmd;
+	ENTER();
+	skb = bt_skb_alloc(sizeof(BT_CSU_CMD), GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "No free skb\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	pcmd = (BT_CSU_CMD *)skb->data;
+	pcmd->ocf_ogf =
+		__cpu_to_le16((VENDOR_OGF << 10) | BT_CMD_CSU_WRITE_REG);
+	pcmd->length = 7;
+	pcmd->type = type;
+	pcmd->offset[0] = (offset & 0x000000ff);
+	pcmd->offset[1] = (offset & 0x0000ff00) >> 8;
+	pcmd->offset[2] = (offset & 0x00ff0000) >> 16;
+	pcmd->offset[3] = (offset & 0xff000000) >> 24;
+	pcmd->value[0] = (value & 0x00ff);
+	pcmd->value[1] = (value & 0xff00) >> 8;
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+	skb_put(skb, sizeof(BT_CSU_CMD));
+	skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+	priv->bt_dev.sendcmdflag = TRUE;
+	priv->bt_dev.send_cmd_opcode = __le16_to_cpu(pcmd->ocf_ogf);
+	priv->adapter->cmd_complete = FALSE;
+	PRINTM(CMD, "BT: Set CSU reg type=%d reg=0x%x value=0x%x\n",
+	       type, offset, value);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	if (!os_wait_interruptible_timeout
+	    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+	     WAIT_UNTIL_CMD_RESP)) {
+		ret = BT_STATUS_FAILURE;
+		PRINTM(ERROR, "BT: Set CSU reg timeout:\n");
+		bt_cmd_timeout_func(priv, BT_CMD_CSU_WRITE_REG);
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function used to restore tx_queue
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        N/A
+ */
+void
+bt_restore_tx_queue(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	while (!skb_queue_empty(&priv->adapter->pending_queue)) {
+		skb = skb_dequeue(&priv->adapter->pending_queue);
+		if (skb)
+			bt_queue_frame(priv, skb);
+	}
+	wake_up_interruptible(&priv->MainThread.waitQ);
+}
+
+/**
+ *  @brief This function used to send command to firmware
+ *
+ *  Command format:
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     OCF OGF     | Length |                Data               |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *  |     2-byte      | 1-byte |               4-byte              |
+ *  +--------+--------+--------+--------+--------+--------+--------+
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_prepare_command(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (priv->bt_dev.hscfgcmd) {
+		priv->bt_dev.hscfgcmd = 0;
+		ret = bt_send_hscfg_cmd(priv);
+	}
+	if (priv->bt_dev.pscmd) {
+		priv->bt_dev.pscmd = 0;
+		ret = bt_enable_ps(priv);
+	}
+	if (priv->bt_dev.sdio_pull_ctrl) {
+		priv->bt_dev.sdio_pull_ctrl = 0;
+		ret = bt_send_sdio_pull_ctrl_cmd(priv);
+	}
+	if (priv->bt_dev.hscmd) {
+		priv->bt_dev.hscmd = 0;
+		if (priv->bt_dev.hsmode)
+			ret = bt_enable_hs(priv);
+		else {
+			ret = sbi_wakeup_firmware(priv);
+			priv->adapter->hs_state = HS_DEACTIVATED;
+		}
+	}
+	if (priv->bt_dev.test_mode) {
+		priv->bt_dev.test_mode = 0;
+		ret = bt_enable_test_mode(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function processes a single packet
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param skb     A pointer to skb which includes TX packet
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+send_single_packet(bt_private *priv, struct sk_buff *skb)
+{
+	int ret;
+	struct sk_buff *new_skb = NULL;
+	ENTER();
+	if (!skb || !skb->data) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	if (!skb->len || ((skb->len + BT_HEADER_LEN) > BT_UPLD_SIZE)) {
+		PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
+		       BT_UPLD_SIZE);
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	if (skb_headroom(skb) < BT_HEADER_LEN) {
+		new_skb = skb_realloc_headroom(skb, BT_HEADER_LEN);
+		if (!new_skb) {
+			PRINTM(ERROR, "TX error: realloc_headroom failed %d\n",
+			       BT_HEADER_LEN);
+			kfree_skb(skb);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		} else {
+			if (new_skb != skb)
+				dev_kfree_skb_any(skb);
+			skb = new_skb;
+		}
+	}
+	/* This is SDIO/PCIE specific header length: byte[3][2][1], * type:
+	   byte[0] (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor)
+	 */
+	skb_push(skb, BT_HEADER_LEN);
+	skb->data[0] = (skb->len & 0x0000ff);
+	skb->data[1] = (skb->len & 0x00ff00) >> 8;
+	skb->data[2] = (skb->len & 0xff0000) >> 16;
+	skb->data[3] = bt_cb(skb)->pkt_type;
+	if (bt_cb(skb)->pkt_type == MRVL_VENDOR_PKT)
+		PRINTM(CMD, "DNLD_CMD: ocf_ogf=0x%x len=%d\n",
+		       __le16_to_cpu(*((u16 *) & skb->data[4])), skb->len);
+	ret = sbi_host_to_card(priv, skb->data, skb->len);
+	if (ret == BT_STATUS_FAILURE)
+		((struct m_dev *)skb->dev)->stat.err_tx++;
+	else
+		((struct m_dev *)skb->dev)->stat.byte_tx += skb->len;
+	if (ret != BT_STATUS_PENDING)
+		kfree_skb(skb);
+	LEAVE();
+	return ret;
+}
+
+#ifdef CONFIG_OF
+/**
+ *  @brief This function read the initial parameter from device tress
+ *
+ *
+ *  @return         N/A
+ */
+static void
+bt_init_from_dev_tree(void)
+{
+	struct device_node *dt_node = NULL;
+	struct property *prop;
+	u32 data;
+	const char *string_data;
+
+	ENTER();
+
+	if (!dts_enable) {
+		PRINTM(CMD, "DTS is disabled!");
+		return;
+	}
+
+	dt_node = of_find_node_by_name(NULL, "sd8xxx-bt");
+	if (!dt_node) {
+		LEAVE();
+		return;
+	}
+	for_each_property_of_node(dt_node, prop) {
+#ifdef DEBUG_LEVEL1
+		if (!strncmp(prop->name, "mbt_drvdbg", strlen("mbt_drvdbg"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(CMD, "mbt_drvdbg=0x%x\n", data);
+				mbt_drvdbg = data;
+			}
+		}
+#endif
+		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(CMD, "init_cfg=%s\n", init_cfg);
+			}
+		} else if (!strncmp
+			   (prop->name, "cal_cfg_ext", strlen("cal_cfg_ext"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg_ext = (char *)string_data;
+				PRINTM(CMD, "cal_cfg_ext=%s\n", cal_cfg_ext);
+			}
+		} else if (!strncmp(prop->name, "cal_cfg", strlen("cal_cfg"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				cal_cfg = (char *)string_data;
+				PRINTM(CMD, "cal_cfg=%s\n", cal_cfg);
+			}
+		} else if (!strncmp(prop->name, "bt_mac", strlen("bt_mac"))) {
+			if (!of_property_read_string
+			    (dt_node, prop->name, &string_data)) {
+				bt_mac = (char *)string_data;
+				PRINTM(CMD, "bt_mac=%s\n", bt_mac);
+			}
+		} else if (!strncmp(prop->name, "btindrst", strlen("btindrst"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btindrst = data;
+				PRINTM(CMD, "btindrst=%d\n", btindrst);
+			}
+		} else if (!strncmp(prop->name, "btpmic", strlen("btpmic"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				btpmic = data;
+				PRINTM(CMD, "btpmic=%d\n", btpmic);
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function initializes the adapter structure
+ *  and set default value to the member of adapter.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+static void
+bt_init_adapter(bt_private *priv)
+{
+	ENTER();
+#ifdef CONFIG_OF
+	bt_init_from_dev_tree();
+#endif
+	skb_queue_head_init(&priv->adapter->tx_queue);
+	skb_queue_head_init(&priv->adapter->fwdump_queue);
+
+	skb_queue_head_init(&priv->adapter->pending_queue);
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+	priv->adapter->fwdump_fname = NULL;
+	init_waitqueue_head(&priv->adapter->cmd_wait_q);
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	ENTER();
+	if (fw == 0) {
+		sbi_enable_host_int(priv);
+		goto done;
+	}
+	sbi_disable_host_int(priv);
+	if (sbi_download_fw(priv)) {
+		PRINTM(ERROR, " FW failed to be download!\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#define FW_POLL_TRIES 100
+#define FW_RESET_REG  0x0EE
+#define FW_RESET_VAL  0x99
+
+/**
+ *  @brief This function reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   FW reload mode
+ *
+ *  @return       0--success, otherwise failure
+ */
+static int
+bt_reload_fw(bt_private *priv, int mode)
+{
+	int ret = 0, tries = 0;
+	u8 value = 1;
+	u32 reset_reg = FW_RESET_REG;
+	u8 reset_val = FW_RESET_VAL;
+
+	ENTER();
+	if ((mode != FW_RELOAD_SDIO_INBAND_RESET) &&
+	    (mode != FW_RELOAD_NO_EMULATION)) {
+		PRINTM(ERROR, "Invalid fw reload mode=%d\n", mode);
+		return -EFAULT;
+	}
+
+    /** flush pending tx_queue */
+	skb_queue_purge(&priv->adapter->tx_queue);
+	if (mode == FW_RELOAD_SDIO_INBAND_RESET) {
+		sbi_disable_host_int(priv);
+	    /** Wake up firmware firstly */
+		sbi_wakeup_firmware(priv);
+
+	/** wait SOC fully wake up */
+		for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_write_reg(priv, reset_reg, 0xba);
+			if (!ret) {
+				ret = sd_read_reg(priv, reset_reg, &value);
+				if (!ret && (value == 0xba)) {
+					PRINTM(MSG, "Fw wake up\n");
+					break;
+				}
+			}
+			udelay(1000);
+		}
+
+		ret = sd_write_reg(priv, reset_reg, reset_val);
+		if (ret) {
+			PRINTM(ERROR, "Failed to write register.\n");
+			goto done;
+		}
+
+	    /** Poll register around 1 ms */
+		for (; tries < FW_POLL_TRIES; ++tries) {
+			ret = sd_read_reg(priv, reset_reg, &value);
+			if (ret) {
+				PRINTM(ERROR, "Failed to read register.\n");
+				goto done;
+			}
+			if (value == 0)
+			    /** FW is ready */
+				break;
+			udelay(1000);
+		}
+		if (value) {
+			PRINTM(ERROR,
+			       "Failed to poll FW reset register %X=0x%x\n",
+			       reset_reg, value);
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	sbi_enable_host_int(priv);
+	/** reload FW */
+	ret = bt_init_fw(priv);
+	if (ret) {
+		PRINTM(ERROR, "Re download firmware failed.\n");
+		ret = -EFAULT;
+	}
+	LEAVE();
+	return ret;
+done:
+	sbi_enable_host_int(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function request to reload firmware
+ *
+ *  @param priv   A pointer to bt_private
+ *  @param mode   fw reload mode.
+ *
+ *  @return         N/A
+ */
+void
+bt_request_fw_reload(bt_private *priv, int mode)
+{
+	ENTER();
+	if (mode == FW_RELOAD_WITH_EMULATION) {
+		bt_fw_reload = FW_RELOAD_WITH_EMULATION;
+		PRINTM(MSG, "BT: FW reload with re-emulation...\n");
+		LEAVE();
+		return;
+	}
+	/** Reload FW */
+	priv->fw_reload = TRUE;
+	if (bt_reload_fw(priv, mode)) {
+		PRINTM(ERROR, "FW reload fail\n");
+		goto done;
+	}
+	priv->fw_reload = FALSE;
+	/** Other operation here? */
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function frees the structure of adapter
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return    N/A
+ */
+void
+bt_free_adapter(bt_private *priv)
+{
+	bt_adapter *adapter = priv->adapter;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	skb_queue_purge(&priv->adapter->fwdump_queue);
+	kfree(adapter->tx_buffer);
+	kfree(adapter->hw_regs_buf);
+	/* Free allocated memory for fwdump filename */
+	if (adapter->fwdump_fname) {
+		kfree(adapter->fwdump_fname);
+		adapter->fwdump_fname = NULL;
+	}
+	/* Free the adapter object itself */
+	kfree(adapter);
+	priv->adapter = NULL;
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the wrapper_dev ioctl
+ *
+ *  @param hev     A pointer to wrapper_dev structure
+ *  @cmd            ioctl cmd
+ *  @arg            argument
+ *  @return    -ENOIOCTLCMD
+ */
+static int
+mdev_ioctl(struct m_dev *m_dev, unsigned int cmd, void *arg)
+{
+	bt_private *priv = NULL;
+	int ret = 0;
+#ifdef BLE_WAKEUP
+	u16 len;
+#endif
+
+	ENTER();
+
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Ioctl for unknown device (m_dev=NULL)\n");
+		ret = -ENODEV;
+		goto done;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "HCI_RUNNING not set, flag=0x%lx\n",
+		       m_dev->flags);
+		ret = -EBUSY;
+		goto done;
+	}
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+#ifdef BLE_WAKEUP
+	case MBTCHAR_IOCTL_BLE_WAKEUP_PARAM:
+		PRINTM(MSG, "BT: Set ble wakeup parameters\n");
+		if (copy_from_user(&len, arg, sizeof(u16))) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Fail to copy ble wakeup params length\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		/** Convert little endian length */
+		len = __le16_to_cpu(len);
+		if (len < 2) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Invalid ble wakeup params len %d\n",
+			       len);
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((len + sizeof(u16)) > priv->ble_wakeup_buf_size) {
+			if (priv->ble_wakeup_buf) {
+				kfree(priv->ble_wakeup_buf);
+				priv->ble_wakeup_buf = NULL;
+				priv->ble_wakeup_buf_size = 0;
+			}
+			priv->ble_wakeup_buf =
+				kzalloc(len + sizeof(u16), GFP_KERNEL);
+			if (!priv->ble_wakeup_buf) {
+				PRINTM(ERROR, "BT_IOCTL: Fail to alloc buffer\t"
+				       "for ble wakeup parameters\n");
+				ret = -ENOMEM;
+				goto done;
+			}
+			priv->ble_wakeup_buf_size = len + sizeof(u16);
+		}
+		if (copy_from_user
+		    (priv->ble_wakeup_buf, arg, len + sizeof(u16))) {
+			PRINTM(ERROR,
+			       "BT_IOCTL: Fail to copy ble wakeup params\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		DBG_HEXDUMP(DAT_D, "BLE_WAKEUP_PARAM:", priv->ble_wakeup_buf,
+			    len + sizeof(u16));
+		break;
+#endif
+	default:
+		break;
+	}
+
+done:
+#ifdef BLE_WAKEUP
+	if (ret && priv->ble_wakeup_buf) {
+		kfree(priv->ble_wakeup_buf);
+		priv->ble_wakeup_buf = NULL;
+		priv->ble_wakeup_buf_size = 0;
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles wrapper device destruct
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    N/A
+ */
+static void
+mdev_destruct(struct m_dev *m_dev)
+{
+	ENTER();
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handles the wrapper device transmit
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return    BT_STATUS_SUCCESS or other error no.
+ */
+static int
+mdev_send_frame(struct m_dev *m_dev, struct sk_buff *skb)
+{
+	bt_private *priv = NULL;
+
+	ENTER();
+	if (!m_dev || !m_dev->driver_data) {
+		PRINTM(ERROR, "Frame for unknown HCI device (m_dev=NULL)\n");
+		LEAVE();
+		return -ENODEV;
+	}
+	priv = (bt_private *)m_dev->driver_data;
+	if (!test_bit(HCI_RUNNING, &m_dev->flags)) {
+		PRINTM(ERROR, "Fail test HCI_RUNNING, flag=0x%lx\n",
+		       m_dev->flags);
+		LEAVE();
+		return -EBUSY;
+	}
+	switch (bt_cb(skb)->pkt_type) {
+	case HCI_COMMAND_PKT:
+		m_dev->stat.cmd_tx++;
+		break;
+	case HCI_ACLDATA_PKT:
+		m_dev->stat.acl_tx++;
+		break;
+	case HCI_SCODATA_PKT:
+		m_dev->stat.sco_tx++;
+		break;
+	}
+
+	if (m_dev->dev_type == DEBUG_TYPE) {
+		/* remember the ogf_ocf */
+		priv->debug_device_pending = 1;
+		priv->debug_ocf_ogf[0] = skb->data[0];
+		priv->debug_ocf_ogf[1] = skb->data[1];
+		PRINTM(CMD, "debug_ocf_ogf[0]=0x%x debug_ocf_ogf[1]=0x%x\n",
+		       priv->debug_ocf_ogf[0], priv->debug_ocf_ogf[1]);
+	}
+
+	if (priv->adapter->tx_lock == TRUE)
+		skb_queue_tail(&priv->adapter->pending_queue, skb);
+	else
+		bt_queue_frame(priv, skb);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function flushes the transmit queue
+ *
+ *  @param m_dev     A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_flush(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	skb_queue_purge(&priv->adapter->tx_queue);
+	skb_queue_purge(&priv->adapter->pending_queue);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function closes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS
+ */
+static int
+mdev_close(struct m_dev *m_dev)
+{
+
+	ENTER();
+	mdev_req_lock(m_dev);
+	if (!test_and_clear_bit(HCI_UP, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+
+	if (m_dev->flush)
+		m_dev->flush(m_dev);
+	/* wait up pending read and unregister char dev */
+	wake_up_interruptible(&m_dev->req_wait_q);
+	/* Drop queues */
+	skb_queue_purge(&m_dev->rx_q);
+	if (!test_and_clear_bit(HCI_RUNNING, &m_dev->flags)) {
+		mdev_req_unlock(m_dev);
+		LEAVE();
+		return 0;
+	}
+	module_put(THIS_MODULE);
+	m_dev->flags = 0;
+	mdev_req_unlock(m_dev);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function opens the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+static int
+mdev_open(struct m_dev *m_dev)
+{
+	ENTER();
+
+	if (try_module_get(THIS_MODULE) == 0)
+		return BT_STATUS_FAILURE;
+
+	set_bit(HCI_RUNNING, &m_dev->flags);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function queries the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @param arg     arguement
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+mdev_query(struct m_dev *m_dev, void *arg)
+{
+	struct mbt_dev *mbt_dev = (struct mbt_dev *)m_dev->dev_pointer;
+
+	ENTER();
+	if (copy_to_user(arg, &mbt_dev->type, sizeof(mbt_dev->type)))
+		PRINTM(ERROR, "IOCTL_QUERY_TYPE: Fail copy to user\n");
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function initializes the wrapper device
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *
+ *  @return    BT_STATUS_SUCCESS  or other
+ */
+void
+init_m_dev(struct m_dev *m_dev)
+{
+	m_dev->dev_pointer = NULL;
+	m_dev->driver_data = NULL;
+	m_dev->dev_type = 0;
+	m_dev->spec_type = 0;
+	skb_queue_head_init(&m_dev->rx_q);
+	init_waitqueue_head(&m_dev->req_wait_q);
+	init_waitqueue_head(&m_dev->rx_wait_q);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+	init_MUTEX(&m_dev->req_lock);
+#else
+	sema_init(&m_dev->req_lock, 1);
+#endif
+	spin_lock_init(&m_dev->rxlock);
+	memset(&m_dev->stat, 0, sizeof(struct hci_dev_stats));
+	m_dev->open = mdev_open;
+	m_dev->close = mdev_close;
+	m_dev->flush = mdev_flush;
+	m_dev->send = mdev_send_frame;
+	m_dev->destruct = mdev_destruct;
+	m_dev->ioctl = mdev_ioctl;
+	m_dev->query = mdev_query;
+	m_dev->owner = THIS_MODULE;
+
+}
+
+/**
+ *  @brief This function handles the major job in bluetooth driver.
+ *  it handles the event generated by firmware, rx data received
+ *  from firmware and tx data sent from kernel.
+ *
+ *  @param data    A pointer to bt_thread structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+static int
+bt_service_main_thread(void *data)
+{
+	bt_thread *thread = data;
+	bt_private *priv = thread->priv;
+	bt_adapter *adapter = priv->adapter;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
+	wait_queue_t wait;
+#else
+	wait_queue_entry_t wait;
+#endif
+	struct sk_buff *skb;
+	ENTER();
+	bt_activate_thread(thread);
+	init_waitqueue_entry(&wait, current);
+	current->flags |= PF_NOFREEZE;
+
+	for (;;) {
+		add_wait_queue(&thread->waitQ, &wait);
+		OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE);
+		if (priv->adapter->WakeupTries ||
+		    ((!priv->adapter->IntCounter) &&
+		     (!priv->bt_dev.tx_dnld_rdy ||
+		      skb_queue_empty(&priv->adapter->tx_queue))
+		     && skb_queue_empty(&priv->adapter->fwdump_queue)
+		    )) {
+			PRINTM(INFO, "Main: Thread sleeping...\n");
+			schedule();
+		}
+		OS_SET_THREAD_STATE(TASK_RUNNING);
+		remove_wait_queue(&thread->waitQ, &wait);
+		if (kthread_should_stop() || adapter->SurpriseRemoved) {
+			PRINTM(INFO, "main-thread: break from main thread: "
+			       "SurpriseRemoved=0x%x\n",
+			       adapter->SurpriseRemoved);
+			break;
+		}
+
+		PRINTM(INFO, "Main: Thread waking up...\n");
+
+		if (priv->adapter->IntCounter) {
+			OS_INT_DISABLE;
+			adapter->IntCounter = 0;
+			OS_INT_RESTORE;
+			sbi_get_int_status(priv);
+		} else if ((priv->adapter->ps_state == PS_SLEEP) &&
+			   !skb_queue_empty(&priv->adapter->tx_queue)) {
+			priv->adapter->WakeupTries++;
+			sbi_wakeup_firmware(priv);
+			continue;
+		}
+		if (priv->adapter->ps_state == PS_SLEEP)
+			continue;
+		if (priv->bt_dev.tx_dnld_rdy == TRUE) {
+			if (!skb_queue_empty(&priv->adapter->tx_queue)) {
+				skb = skb_dequeue(&priv->adapter->tx_queue);
+				if (skb)
+					send_single_packet(priv, skb);
+			}
+		}
+		if (!skb_queue_empty(&priv->adapter->fwdump_queue)) {
+			skb = skb_dequeue(&priv->adapter->fwdump_queue);
+			if (skb) {
+				bt_store_firmware_dump(priv, skb->data,
+						       skb->len);
+				dev_kfree_skb_any(skb);
+			}
+		}
+	}
+	bt_deactivate_thread(thread);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the interrupt. it will change PS
+ *  state if applicable. it will wake up main_thread to handle
+ *  the interrupt event as well.
+ *
+ *  @param m_dev   A pointer to m_dev structure
+ *  @return        N/A
+ */
+void
+bt_interrupt(struct m_dev *m_dev)
+{
+	bt_private *priv = (bt_private *)m_dev->driver_data;
+	ENTER();
+	if (!priv || !priv->adapter) {
+		LEAVE();
+		return;
+	}
+	PRINTM(INTR, "*\n");
+	priv->adapter->ps_state = PS_AWAKE;
+	if (priv->adapter->hs_state == HS_ACTIVATED) {
+		PRINTM(CMD, "BT: %s: HS DEACTIVATED in ISR!\n", m_dev->name);
+		priv->adapter->hs_state = HS_DEACTIVATED;
+	}
+	priv->adapter->WakeupTries = 0;
+	priv->adapter->IntCounter++;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	LEAVE();
+}
+
+/**
+ * @brief  Dynamic release of char dev
+ *
+ * @param kobj          A pointer to kobject structure
+ *
+ * @return                N/A
+ */
+static void
+char_dev_release_dynamic(struct kobject *kobj)
+{
+	struct char_dev *cdev = container_of(kobj, struct char_dev, kobj);
+	ENTER();
+	PRINTM(INFO, "free char_dev\n");
+	kfree(cdev);
+	LEAVE();
+}
+
+static struct kobj_type ktype_char_dev_dynamic = {
+	.release = char_dev_release_dynamic,
+};
+
+/**
+ * @brief  Allocation of char dev
+ *
+ * @param           	N/A
+ *
+ * @return              char_dev
+ */
+static struct char_dev *
+alloc_char_dev(void)
+{
+	struct char_dev *cdev;
+	ENTER();
+	cdev = kzalloc(sizeof(struct char_dev), GFP_KERNEL);
+	if (cdev) {
+		kobject_init(&cdev->kobj, &ktype_char_dev_dynamic);
+		PRINTM(INFO, "alloc char_dev\n");
+	}
+	return cdev;
+}
+
+/**
+ * @brief  Dynamic release of bt private
+ *
+ * @param kobj          A pointer to kobject structure
+ *
+ * @return                N/A
+ */
+static void
+bt_private_dynamic_release(struct kobject *kobj)
+{
+	bt_private *priv = container_of(kobj, bt_private, kobj);
+	ENTER();
+	PRINTM(INFO, "free bt priv\n");
+	kfree(priv);
+	LEAVE();
+}
+
+static struct kobj_type ktype_bt_private_dynamic = {
+	.release = bt_private_dynamic_release,
+};
+
+/**
+ * @brief  Allocation of bt private
+ *
+ * @param           	N/A
+ *
+ * @return              bt_private
+ */
+static bt_private *
+bt_alloc_priv(void)
+{
+	bt_private *priv;
+	ENTER();
+	priv = kzalloc(sizeof(bt_private), GFP_KERNEL);
+	if (priv) {
+		kobject_init(&priv->kobj, &ktype_bt_private_dynamic);
+		PRINTM(INFO, "alloc bt priv\n");
+	}
+	LEAVE();
+	return priv;
+}
+
+/**
+ * @brief  Get bt private structure
+ *
+ * @param priv          A pointer to bt_private structure
+ *
+ * @return              kobject structure
+ */
+struct kobject *
+bt_priv_get(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv get object");
+	return kobject_get(&priv->kobj);
+}
+
+/**
+ * @brief  Get bt private structure
+ *
+ * @param priv          A pointer to bt_private structure
+ *
+ * @return              N/A
+ */
+void
+bt_priv_put(bt_private *priv)
+{
+	PRINTM(INFO, "bt priv put object");
+	kobject_put(&priv->kobj);
+}
+
+/**
+ *  @brief This function send init commands to firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_init_cmd(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = bt_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+	if (ret < 0) {
+		PRINTM(FATAL, "Module cfg command send failed!\n");
+		goto done;
+	}
+	if (btindrst != -1) {
+		ret = bt_set_independent_reset(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Independent reset failed!\n");
+			goto done;
+		}
+	}
+	if (btpmic) {
+		if (BT_STATUS_SUCCESS != bt_pmic_configure(priv)) {
+			PRINTM(FATAL, "BT: PMIC Configure failed \n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	ret = bt_set_ble_deepsleep(priv, deep_sleep ? TRUE : FALSE);
+	if (ret < 0) {
+		PRINTM(FATAL, "%s BLE deepsleep failed!\n",
+		       deep_sleep ? "Enable" : "Disable");
+		goto done;
+	}
+	if (psmode) {
+		priv->bt_dev.psmode = TRUE;
+		priv->bt_dev.idle_timeout = DEFAULT_IDLE_TIME;
+		ret = bt_enable_ps(priv);
+		if (ret < 0) {
+			PRINTM(FATAL, "Enable PS mode failed!\n");
+			goto done;
+		}
+	}
+#if defined(SDIO_SUSPEND_RESUME)
+	priv->bt_dev.gpio_gap = DEF_GPIO_GAP;
+	ret = bt_send_hscfg_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "Send HSCFG failed!\n");
+		goto done;
+	}
+#endif
+	priv->bt_dev.sdio_pull_cfg = 0xffffffff;
+	priv->bt_dev.sdio_pull_ctrl = 0;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reinit firmware after redownload firmware
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @return       BT_STATUS_SUCESS/BT_STATUS_FAILURE
+ */
+int
+bt_reinit_fw(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	priv->adapter->tx_lock = FALSE;
+	priv->adapter->ps_state = PS_AWAKE;
+	priv->adapter->suspend_fail = FALSE;
+	priv->adapter->is_suspended = FALSE;
+	priv->adapter->hs_skip = 0;
+	priv->adapter->num_cmd_timeout = 0;
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+	/* block all the packet from bluez */
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext)
+		priv->adapter->tx_lock = TRUE;
+
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (init_cfg || cal_cfg || bt_mac || cal_cfg_ext) {
+		priv->adapter->tx_lock = FALSE;
+		bt_restore_tx_queue(priv);
+	}
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+done:
+	return ret;
+}
+
+/**
+ *  @brief Module configuration and register device
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @return      BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_conf_dpc(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct mbt_dev *mbt_dev = NULL;
+	struct debug_dev *debug_dev = NULL;
+	int i = 0;
+	struct char_dev *char_dev = NULL;
+	char dev_file[DEV_NAME_LEN + 5];
+	unsigned char dev_type = 0;
+
+	ENTER();
+
+	priv->bt_dev.tx_dnld_rdy = TRUE;
+	if (priv->fw_reload) {
+		bt_reinit_fw(priv);
+		LEAVE();
+		return ret;
+	}
+
+	if (drv_mode & DRV_MODE_BT) {
+		mbt_dev = alloc_mbt_dev();
+		if (!mbt_dev) {
+			PRINTM(FATAL, "Can not allocate mbt dev\n");
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		init_m_dev(&(priv->bt_dev.m_dev[BT_SEQ]));
+		priv->bt_dev.m_dev[BT_SEQ].dev_type = BT_TYPE;
+		priv->bt_dev.m_dev[BT_SEQ].spec_type = IANYWHERE_SPEC;
+		priv->bt_dev.m_dev[BT_SEQ].dev_pointer = (void *)mbt_dev;
+		priv->bt_dev.m_dev[BT_SEQ].driver_data = priv;
+		priv->bt_dev.m_dev[BT_SEQ].read_continue_flag = 0;
+	}
+
+	dev_type = HCI_SDIO;
+
+	if (mbt_dev)
+		mbt_dev->type = dev_type;
+
+	ret = bt_init_cmd(priv);
+	if (ret < 0) {
+		PRINTM(FATAL, "BT init command failed!\n");
+		goto done;
+	}
+
+	if (mbt_dev && priv->bt_dev.devType == DEV_TYPE_AMP) {
+		mbt_dev->type |= HCI_BT_AMP;
+		priv->bt_dev.m_dev[BT_SEQ].dev_type = BT_AMP_TYPE;
+	}
+	/** Process device tree init parameters before register hci device.
+	 *  Since uplayer device has not yet registered, no need to block tx queue.
+	 * */
+	if (init_cfg)
+		if (BT_STATUS_SUCCESS != bt_init_config(priv, init_cfg)) {
+			PRINTM(FATAL,
+			       "BT: Set user init data and param failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	if (cal_cfg) {
+		if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
+			PRINTM(FATAL, "BT: Set cal data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	} else if (bt_mac) {
+		PRINTM(INFO,
+		       "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+		       bt_mac);
+		if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+			PRINTM(FATAL,
+			       "BT: Fail to set mac address from insmod parametre\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (cal_cfg_ext) {
+		if (BT_STATUS_SUCCESS != bt_cal_config_ext(priv, cal_cfg_ext)) {
+			PRINTM(FATAL, "BT: Set cal ext data failed\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Get FW version */
+	bt_get_fw_version(priv);
+	snprintf((char *)priv->adapter->drv_ver, MAX_VER_STR_LEN,
+		 mbt_driver_version, fw_version);
+
+	if (mbt_dev) {
+		/** init mbt_dev */
+		mbt_dev->flags = 0;
+		mbt_dev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
+		mbt_dev->esco_type = (ESCO_HV1);
+		mbt_dev->link_mode = (HCI_LM_ACCEPT);
+
+		mbt_dev->idle_timeout = 0;
+		mbt_dev->sniff_max_interval = 800;
+		mbt_dev->sniff_min_interval = 80;
+		for (i = 0; i < 3; i++)
+			mbt_dev->reassembly[i] = NULL;
+		atomic_set(&mbt_dev->promisc, 0);
+
+		/** alloc char dev node */
+		char_dev = alloc_char_dev();
+		if (!char_dev) {
+			class_destroy(chardev_class);
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		char_dev->minor = MBTCHAR_MINOR_BASE + mbtchar_minor;
+		if (mbt_dev->type & HCI_BT_AMP)
+			char_dev->dev_type = BT_AMP_TYPE;
+		else
+			char_dev->dev_type = BT_TYPE;
+
+		if (bt_name)
+			snprintf(mbt_dev->name, sizeof(mbt_dev->name), "%s%d",
+				 bt_name, mbtchar_minor);
+		else
+			snprintf(mbt_dev->name, sizeof(mbt_dev->name),
+				 "mbtchar%d", mbtchar_minor);
+		snprintf(dev_file, sizeof(dev_file), "/dev/%s", mbt_dev->name);
+		mbtchar_minor++;
+		PRINTM(MSG, "BT: Create %s\n", dev_file);
+
+		/** register m_dev to BT char device */
+		priv->bt_dev.m_dev[BT_SEQ].index = char_dev->minor;
+		char_dev->m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+
+		/** create BT char device node */
+		register_char_dev(char_dev, chardev_class, MODULE_NAME,
+				  mbt_dev->name);
+
+		/** chmod & chown for BT char device */
+		mbtchar_chown(dev_file, AID_SYSTEM, AID_NET_BT_STACK);
+		mbtchar_chmod(dev_file, 0666);
+
+		/** create proc device */
+		snprintf(priv->bt_dev.m_dev[BT_SEQ].name,
+			 sizeof(priv->bt_dev.m_dev[BT_SEQ].name),
+			 mbt_dev->name);
+		bt_proc_init(priv, &(priv->bt_dev.m_dev[BT_SEQ]), BT_SEQ);
+	}
+
+	if ((debug_intf) && ((drv_mode & DRV_MODE_BT)
+	    )) {
+		/** alloc debug_dev */
+		debug_dev = alloc_debug_dev();
+		if (!debug_dev) {
+			PRINTM(FATAL, "Can not allocate debug dev\n");
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+
+		/** init m_dev */
+		init_m_dev(&(priv->bt_dev.m_dev[DEBUG_SEQ]));
+		priv->bt_dev.m_dev[DEBUG_SEQ].dev_type = DEBUG_TYPE;
+		priv->bt_dev.m_dev[DEBUG_SEQ].spec_type = GENERIC_SPEC;
+		priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer = (void *)debug_dev;
+		priv->bt_dev.m_dev[DEBUG_SEQ].driver_data = priv;
+
+		/** create char device for Debug */
+		char_dev = alloc_char_dev();
+		if (!char_dev) {
+			class_destroy(chardev_class);
+			ret = -ENOMEM;
+			goto err_kmalloc;
+		}
+		char_dev->minor = DEBUGCHAR_MINOR_BASE + debugchar_minor;
+		char_dev->dev_type = DEBUG_TYPE;
+		if (debug_name)
+			snprintf(debug_dev->name, sizeof(debug_dev->name),
+				 "%s%d", debug_name, debugchar_minor);
+		else
+			snprintf(debug_dev->name, sizeof(debug_dev->name),
+				 "mdebugchar%d", debugchar_minor);
+		snprintf(dev_file, sizeof(dev_file), "/dev/%s",
+			 debug_dev->name);
+		PRINTM(MSG, "BT: Create %s\n", dev_file);
+		debugchar_minor++;
+
+		/** register char dev */
+		priv->bt_dev.m_dev[DEBUG_SEQ].index = char_dev->minor;
+		char_dev->m_dev = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
+		register_char_dev(char_dev, chardev_class, MODULE_NAME,
+				  debug_dev->name);
+
+		/** chmod for debug char device */
+		mbtchar_chmod(dev_file, 0666);
+
+		/** create proc device */
+		snprintf(priv->bt_dev.m_dev[DEBUG_SEQ].name,
+			 sizeof(priv->bt_dev.m_dev[DEBUG_SEQ].name),
+			 debug_dev->name);
+		bt_proc_init(priv, &(priv->bt_dev.m_dev[DEBUG_SEQ]), DEBUG_SEQ);
+	}
+
+done:
+	LEAVE();
+	return ret;
+err_kmalloc:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function adds the card. it will probe the
+ *  card, allocate the bt_priv and initialize the device.
+ *
+ *  @param card    A pointer to card
+ *  @return        A pointer to bt_private structure
+ */
+
+bt_private *
+bt_add_card(void *card)
+{
+	bt_private *priv = NULL;
+	int index = 0;
+
+	ENTER();
+
+	priv = bt_alloc_priv();
+	if (!priv) {
+		PRINTM(FATAL, "Can not allocate priv\n");
+		LEAVE();
+		return NULL;
+	}
+	/* Save the handle */
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == NULL)
+			break;
+	}
+	if (index < MAX_BT_ADAPTER) {
+		m_priv[index] = priv;
+	} else {
+		PRINTM(ERROR, "Exceeded maximum cards supported!\n");
+		goto err_kmalloc;
+	}
+	/* allocate buffer for bt_adapter */
+	priv->adapter = kzalloc(sizeof(bt_adapter), GFP_KERNEL);
+	if (!priv->adapter) {
+		PRINTM(FATAL, "Allocate buffer for bt_adapter failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buffer =
+		kzalloc(MAX_TX_BUF_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->tx_buffer) {
+		PRINTM(FATAL, "Allocate buffer for transmit\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->tx_buf =
+		(u8 *)ALIGN_ADDR(priv->adapter->tx_buffer, DMA_ALIGNMENT);
+	priv->adapter->hw_regs_buf =
+		kzalloc(SD_BLOCK_SIZE + DMA_ALIGNMENT, GFP_KERNEL);
+	if (!priv->adapter->hw_regs_buf) {
+		PRINTM(FATAL, "Allocate buffer for INT read buf failed!\n");
+		goto err_kmalloc;
+	}
+	priv->adapter->hw_regs =
+		(u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf, DMA_ALIGNMENT);
+	bt_init_adapter(priv);
+
+	PRINTM(INFO, "Starting kthread...\n");
+	priv->MainThread.priv = priv;
+	spin_lock_init(&priv->driver_lock);
+
+	bt_create_thread(bt_service_main_thread, &priv->MainThread,
+			 "bt_main_service");
+
+	/* wait for mainthread to up */
+	while (!priv->MainThread.pid)
+		os_sched_timeout(1);
+
+	/** user config file */
+	init_waitqueue_head(&priv->init_user_conf_wait_q);
+
+	priv->bt_dev.card = card;
+
+	((struct sdio_mmc_card *)card)->priv = priv;
+	priv->adapter->sd_ireg = 0;
+	/*
+	 * Register the device. Fillup the private data structure with
+	 * relevant information from the card and request for the required
+	 * IRQ.
+	 */
+	if (sbi_register_dev(priv) < 0) {
+		PRINTM(FATAL, "Failed to register bt device!\n");
+		goto err_registerdev;
+	}
+	if (bt_init_fw(priv)) {
+		PRINTM(FATAL, "BT Firmware Init Failed\n");
+		goto err_init_fw;
+	}
+	LEAVE();
+	return priv;
+
+err_init_fw:
+	clean_up_m_devs(priv);
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+err_registerdev:
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+err_kmalloc:
+	if (priv->adapter)
+		bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function send hardware remove event
+ *
+ *  @param priv    A pointer to bt_private
+ *  @return        N/A
+ */
+void
+bt_send_hw_remove_event(bt_private *priv)
+{
+	struct sk_buff *skb = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+	ENTER();
+	if (!priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		LEAVE();
+		return;
+	}
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+#define HCI_HARDWARE_ERROR_EVT  0x10
+#define HCI_HARDWARE_REMOVE     0x24
+	skb = bt_skb_alloc(3, GFP_ATOMIC);
+	skb->data[0] = HCI_HARDWARE_ERROR_EVT;
+	skb->data[1] = 1;
+	skb->data[2] = HCI_HARDWARE_REMOVE;
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb_put(skb, 3);
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		PRINTM(MSG, "Send HW ERROR event\n");
+		if (!mdev_recv_frame(skb)) {
+#define RX_WAIT_TIMEOUT				300
+			mdev_bt->wait_rx_complete = TRUE;
+			mdev_bt->rx_complete_flag = FALSE;
+			if (os_wait_interruptible_timeout
+			    (mdev_bt->rx_wait_q, mdev_bt->rx_complete_flag,
+			     RX_WAIT_TIMEOUT))
+				PRINTM(MSG, "BT stack received the event\n");
+			mdev_bt->stat.byte_rx += 3;
+		}
+	}
+	LEAVE();
+	return;
+}
+
+#ifdef BLE_WAKEUP
+/**
+ *  @brief This function used to config BLE wakeup pattern
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        N/A
+ */
+int
+bt_config_ble_wakeup(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	u16 ocf, left_len;
+	u8 len, more_cmd;
+	u8 *pos;
+
+	ENTER();
+
+	if (!priv->ble_wakeup_buf) {
+		PRINTM(ERROR, "BT: no ble wakeup parameters found\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MSG, "Config ble wakeup pattern\n");
+
+	pos = priv->ble_wakeup_buf;
+	left_len = *(u16 *) pos;
+	left_len = __le16_to_cpu(left_len);
+	pos += sizeof(u16);
+
+	while (left_len >= 2) {
+		more_cmd = *pos;
+		len = *(pos + 1);
+		if (((len + 2) > left_len) ||
+		    (!more_cmd && ((len + 2) < left_len))) {
+			PRINTM(ERROR, "Invalid ble parameters\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		skb = bt_skb_alloc(len, GFP_ATOMIC);
+		if (!skb) {
+			PRINTM(ERROR, "BT BLE WAKEUP: fail to alloc skb\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy(skb_put(skb, len), pos + 2, len);
+		bt_cb(skb)->pkt_type = *(u8 *)skb->data;
+		skb_pull(skb, 1);
+		DBG_HEXDUMP(DAT_D, "BLE_WAKEUP_CMD:", skb->data, skb->len);
+		skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
+		skb_queue_head(&priv->adapter->tx_queue, skb);
+		priv->bt_dev.sendcmdflag = TRUE;
+		priv->bt_dev.send_cmd_opcode = *(u16 *) skb->data;
+		ocf = hci_opcode_ocf(priv->bt_dev.send_cmd_opcode);
+		priv->adapter->cmd_complete = FALSE;
+
+		wake_up_interruptible(&priv->MainThread.waitQ);
+		if (!os_wait_interruptible_timeout
+		    (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
+		     WAIT_UNTIL_CMD_RESP)) {
+			ret = BT_STATUS_FAILURE;
+			PRINTM(ERROR,
+			       "BT: Set  Set ble wakeup cmd 0x%x timeout:\n",
+			       priv->bt_dev.send_cmd_opcode);
+			bt_cmd_timeout_func(priv, ocf);
+			goto done;
+		}
+
+		pos += len + 2;
+		left_len -= len + 2;
+	}
+
+done:
+	if (ret != BT_STATUS_SUCCESS) {
+		if (priv->ble_wakeup_buf) {
+			kfree(priv->ble_wakeup_buf);
+			priv->ble_wakeup_buf = NULL;
+			priv->ble_wakeup_buf_size = 0;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function send system suspend event
+ *
+ *  @param priv    A pointer to bt_private
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_send_system_event(bt_private *priv, u8 flag)
+{
+	struct sk_buff *skb = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+
+	ENTER();
+
+	if (!priv->bt_dev.m_dev[BT_SEQ].dev_pointer) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+
+	skb = bt_skb_alloc(4, GFP_ATOMIC);
+	if (!skb) {
+		PRINTM(ERROR, "Fail to allocate sys suspend event skb\n");
+		return BT_STATUS_FAILURE;
+	}
+	skb->data[0] = VENDOR_SPECIFIC_EVENT;
+	skb->data[1] = 2;
+	skb->data[2] = HCI_SYSTEM_SUSPEND_EVT;
+	if (flag)
+		skb->data[3] = HCI_SYSTEM_SUSPEND;
+	else
+		skb->data[3] = HCI_SYSTEM_RESUME;
+
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb_put(skb, 4);
+	if (mbt_dev) {
+		skb->dev = (void *)mdev_bt;
+		PRINTM(MSG, "Send system %s event\n",
+		       flag ? "suspend" : "resume");
+		if (!mdev_recv_frame(skb)) {
+#define RX_WAIT_TIMEOUT                         300
+			mdev_bt->wait_rx_complete = TRUE;
+			mdev_bt->rx_complete_flag = FALSE;
+			if (os_wait_interruptible_timeout(mdev_bt->rx_wait_q,
+							  mdev_bt->
+							  rx_complete_flag,
+							  RX_WAIT_TIMEOUT))
+				PRINTM(MSG, "BT stack received the event\n");
+			mdev_bt->stat.byte_rx += 4;
+		}
+	}
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function removes the card.
+ *
+ *  @param card    A pointer to card
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_remove_card(void *card)
+{
+	bt_private *priv = (bt_private *)card;
+	int index;
+	ENTER();
+	if (!priv) {
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv->adapter->SurpriseRemoved = TRUE;
+
+	bt_send_hw_remove_event(priv);
+#ifdef BLE_WAKEUP
+	if (priv->ble_wakeup_buf) {
+		kfree(priv->ble_wakeup_buf);
+		priv->ble_wakeup_buf = NULL;
+		priv->ble_wakeup_buf_size = 0;
+	}
+#endif
+	wake_up_interruptible(&priv->adapter->cmd_wait_q);
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid) {
+		os_sched_timeout(1);
+		wake_up_interruptible(&priv->MainThread.waitQ);
+	}
+
+	bt_proc_remove(priv);
+	PRINTM(INFO, "Unregister device\n");
+	sbi_unregister_dev(priv);
+	clean_up_m_devs(priv);
+	PRINTM(INFO, "Free Adapter\n");
+	bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function initializes module.
+ *
+ *  @return    BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+bt_init_module(void)
+{
+	int ret = BT_STATUS_SUCCESS;
+	int index;
+	ENTER();
+	PRINTM(MSG, "BT: Loading driver\n");
+	/* Init the bt_private pointer array first */
+	for (index = 0; index < MAX_BT_ADAPTER; index++)
+		m_priv[index] = NULL;
+	bt_root_proc_init();
+
+	/** create char device class */
+	chardev_class = class_create(THIS_MODULE, MODULE_NAME);
+	if (IS_ERR(chardev_class)) {
+		PRINTM(ERROR, "Unable to allocate class\n");
+		bt_root_proc_remove();
+		ret = PTR_ERR(chardev_class);
+		goto done;
+	}
+
+	if (sbi_register() == NULL) {
+		bt_root_proc_remove();
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	if (ret)
+		PRINTM(MSG, "BT: Driver loading failed\n");
+	else
+		PRINTM(MSG, "BT: Driver loaded successfully\n");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function cleans module
+ *
+ *  @return        N/A
+ */
+static void
+bt_exit_module(void)
+{
+	bt_private *priv;
+	int index;
+	ENTER();
+	PRINTM(MSG, "BT: Unloading driver\n");
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		priv = m_priv[index];
+		if (!priv)
+			continue;
+		if (priv && !priv->adapter->SurpriseRemoved) {
+			if (BT_STATUS_SUCCESS == bt_send_reset_command(priv))
+				bt_send_module_cfg_cmd(priv,
+						       MODULE_SHUTDOWN_REQ);
+		}
+		sbi_disable_host_int(priv);
+
+	}
+
+	sbi_unregister();
+
+	bt_root_proc_remove();
+	class_destroy(chardev_class);
+	PRINTM(MSG, "BT: Driver unloaded\n");
+	LEAVE();
+}
+
+module_init(bt_init_module);
+module_exit(bt_exit_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell Bluetooth Driver Ver. " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+module_param(fw, int, 0);
+MODULE_PARM_DESC(fw, "0: Skip firmware download; otherwise: Download firmware");
+module_param(psmode, int, 0);
+MODULE_PARM_DESC(psmode, "1: Enable powermode; 0: Disable powermode");
+module_param(deep_sleep, int, 0);
+MODULE_PARM_DESC(deep_sleep, "1: Enable deep sleep; 0: Disable deep sleep");
+#ifdef CONFIG_OF
+module_param(dts_enable, int, 0);
+MODULE_PARM_DESC(dts_enable, "0: Disable DTS; 1: Enable DTS");
+#endif
+#ifdef	DEBUG_LEVEL1
+module_param(mbt_drvdbg, uint, 0);
+MODULE_PARM_DESC(mbt_drvdbg, "BIT3:DBG_DATA BIT4:DBG_CMD 0xFF:DBG_ALL");
+#endif
+#ifdef SDIO_SUSPEND_RESUME
+module_param(mbt_pm_keep_power, int, 0);
+MODULE_PARM_DESC(mbt_pm_keep_power, "1: PM keep power; 0: PM no power");
+#endif
+module_param(init_cfg, charp, 0);
+MODULE_PARM_DESC(init_cfg, "BT init config file name");
+module_param(cal_cfg, charp, 0);
+MODULE_PARM_DESC(cal_cfg, "BT calibrate file name");
+module_param(cal_cfg_ext, charp, 0);
+MODULE_PARM_DESC(cal_cfg_ext, "BT calibrate ext file name");
+module_param(bt_mac, charp, 0660);
+MODULE_PARM_DESC(bt_mac, "BT init mac address");
+module_param(drv_mode, int, 0);
+MODULE_PARM_DESC(drv_mode, "Bit 0: BT/AMP/BLE;");
+module_param(bt_name, charp, 0);
+MODULE_PARM_DESC(bt_name, "BT interface name");
+module_param(debug_intf, int, 0);
+MODULE_PARM_DESC(debug_intf,
+		 "1: Enable debug interface; 0: Disable debug interface ");
+module_param(debug_name, charp, 0);
+MODULE_PARM_DESC(debug_name, "Debug interface name");
+module_param(bt_fw_reload, int, 0);
+MODULE_PARM_DESC(bt_fw_reload,
+		 "0: disable fw_reload; 1: enable fw reload feature");
+module_param(btindrst, int, 0);
+MODULE_PARM_DESC(btindrst,
+		 "Independent reset configuration; high byte:GPIO pin number;low byte:0x0:disable, 0x1:out-band reset, 0x2:in-band reset.");
+module_param(btpmic, int, 0);
+MODULE_PARM_DESC(btpmic,
+		 "1: Send pmic configure cmd to firmware; 0: No pmic configure cmd sent to firmware (default)");
+module_param(bt_fw_serial, int, 0);
+MODULE_PARM_DESC(bt_fw_serial,
+		 "0: Support parallel download FW; 1: Support serial download FW");
diff --git a/bt_sd8997/bt_char/bt_proc.c b/bt_sd8997/bt_char/bt_proc.c
new file mode 100644
index 0000000..d2fa99a
--- /dev/null
+++ b/bt_sd8997/bt_char/bt_proc.c
@@ -0,0 +1,893 @@
+/** @file bt_proc.c
+  *
+  * @brief This file handle the functions for proc files
+  *
+  * Copyright (C) 2007-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the gpl.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/proc_fs.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** proc diretory root */
+#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
+
+/** Proc mbt directory entry */
+static struct proc_dir_entry *proc_mbt;
+
+#define     CMD52_STR_LEN   50
+static char cmd52_string[CMD52_STR_LEN];
+
+/** proc data structure */
+struct proc_data {
+	/** Read length */
+	int rdlen;
+	/** Read buffer */
+	char *rdbuf;
+	/** Write length */
+	int wrlen;
+	/** Maximum write length */
+	int maxwrlen;
+	/** Write buffer */
+	char *wrbuf;
+	/** Private structure */
+	struct _bt_private *pbt;
+	void (*on_close) (struct inode *, struct file *);
+};
+
+/** Default file permission */
+#define DEFAULT_FILE_PERM  0644
+
+/** Bluetooth device offset */
+#define OFFSET_BT_DEV		0x01
+/** Bluetooth adapter offset */
+#define OFFSET_BT_ADAPTER	0x02
+/** Show integer */
+#define SHOW_INT		0x10
+/** Show hex */
+#define SHOW_HEX		0x20
+/** Show string */
+#define SHOW_STRING		0x40
+
+/** Device size */
+#define item_dev_size(n) (sizeof((bt_dev_t *)0)->n)
+/** Device address */
+#define item_dev_addr(n) ((t_ptr) &((bt_dev_t *)0)->n)
+
+/** Adapter size */
+#define item_adapter_size(n) (sizeof((bt_adapter *)0)->n)
+/** Adapter address */
+#define item_adapter_addr(n) ((t_ptr) &((bt_adapter *)0)->n)
+
+static struct item_data config_items[] = {
+#ifdef	DEBUG_LEVEL1
+	{"drvdbg", sizeof(u32), (t_ptr)&mbt_drvdbg, 0, SHOW_HEX}
+	,
+#endif
+	{"idle_timeout", item_dev_size(idle_timeout), 0,
+	 item_dev_addr(idle_timeout), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"psmode", item_dev_size(psmode), 0, item_dev_addr(psmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"pscmd", item_dev_size(pscmd), 0, item_dev_addr(pscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hsmode", item_dev_size(hsmode), 0, item_dev_addr(hsmode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"hscmd", item_dev_size(hscmd), 0, item_dev_addr(hscmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"gpio_gap", item_dev_size(gpio_gap), 0, item_dev_addr(gpio_gap),
+	 OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"hscfgcmd", item_dev_size(hscfgcmd), 0, item_dev_addr(hscfgcmd),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"sdio_pull_cfg", item_dev_size(sdio_pull_cfg), 0,
+	 item_dev_addr(sdio_pull_cfg), OFFSET_BT_DEV | SHOW_HEX}
+	,
+	{"sdio_pull_ctrl", item_dev_size(sdio_pull_ctrl), 0,
+	 item_dev_addr(sdio_pull_ctrl), OFFSET_BT_DEV | SHOW_INT}
+	,
+	{"test_mode", item_dev_size(test_mode), 0, item_dev_addr(test_mode),
+	 OFFSET_BT_DEV | SHOW_INT}
+	,
+
+};
+
+static struct item_data status_items[] = {
+	{"version", item_adapter_size(drv_ver), 0, item_adapter_addr(drv_ver),
+	 OFFSET_BT_ADAPTER | SHOW_STRING},
+	{"tx_dnld_rdy", item_dev_size(tx_dnld_rdy), 0,
+	 item_dev_addr(tx_dnld_rdy),
+	 OFFSET_BT_DEV | SHOW_INT},
+	{"psmode", item_adapter_size(psmode), 0, item_adapter_addr(psmode),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_state", item_adapter_size(hs_state), 0,
+	 item_adapter_addr(hs_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"hs_skip", item_adapter_size(hs_skip), 0, item_adapter_addr(hs_skip),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"ps_state", item_adapter_size(ps_state), 0,
+	 item_adapter_addr(ps_state),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"WakeupTries", item_adapter_size(WakeupTries), 0,
+	 item_adapter_addr(WakeupTries), OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_recv", item_adapter_size(irq_recv), 0,
+	 item_adapter_addr(irq_recv),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"irq_done", item_adapter_size(irq_done), 0,
+	 item_adapter_addr(irq_done),
+	 OFFSET_BT_ADAPTER | SHOW_INT},
+	{"skb_pending", item_adapter_size(skb_pending), 0,
+	 item_adapter_addr(skb_pending), OFFSET_BT_ADAPTER | SHOW_INT},
+};
+
+static struct item_data debug_items[] = {
+	{"sdcmd52rw", 0, (t_ptr)cmd52_string, 0, SHOW_STRING},
+};
+
+/**
+ *  @brief convert string to number
+ *
+ *  @param s	pointer to numbered string
+ *  @return	converted number from string s
+ */
+int
+string_to_number(char *s)
+{
+	int r = 0;
+	int base = 0;
+	int pn = 1;
+
+	if (strncmp(s, "-", 1) == 0) {
+		pn = -1;
+		s++;
+	}
+	if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
+		base = 16;
+		s += 2;
+	} else
+		base = 10;
+
+	for (s = s; *s != 0; 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 Create cmd52 string
+ *
+ *  @param priv	A pointer to bt_private structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+form_cmd52_string(bt_private *priv)
+{
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	snprintf(cmd52_string, CMD52_STR_LEN - 1, "BT: %d 0x%0x 0x%02X",
+		 priv->bt_dev.cmd52_func, priv->bt_dev.cmd52_reg,
+		 priv->bt_dev.cmd52_val);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/*
+ *  @brief Parse cmd52 string
+ *
+ *  @param buffer  A pointer user buffer
+ *  @param len     Length of 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 __user * buffer, size_t len,
+		   int *func, int *reg, int *val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	char *string = NULL;
+	char *pos = NULL;
+
+	ENTER();
+
+	string = kzalloc(CMD52_STR_LEN, GFP_KERNEL);
+	if (!string) {
+		PRINTM(ERROR, "BT: Can not alloc mem for cmd52 string\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	memcpy(string, buffer + strlen("sdcmd52rw="),
+	       len - strlen("sdcmd52rw="));
+	string = strstrip(string);
+
+	*func = -1;
+	*reg = -1;
+	*val = -1;
+
+	/* Get func */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*func = string_to_number(pos);
+
+	/* Get reg */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*reg = string_to_number(pos);
+
+	/* Get val (optional) */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*val = string_to_number(pos);
+	kfree(string);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handle generic proc file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS
+ */
+static int
+proc_close(struct inode *inode, struct file *file)
+{
+	struct proc_data *pdata = file->private_data;
+	ENTER();
+	if (pdata) {
+		if (pdata->on_close != NULL)
+			pdata->on_close(inode, file);
+		kfree(pdata->rdbuf);
+		kfree(pdata->wrbuf);
+		kfree(pdata);
+	}
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle generic proc file read
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to output buffer
+ *  @param len     number of byte to read
+ *  @param offset  A pointer to offset of file
+ *  @return		number of output data
+ */
+static ssize_t
+proc_read(struct file *file, char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	if ((!pdata->rdbuf) || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->rdlen)
+		return 0;
+	if (len > pdata->rdlen - pos)
+		len = pdata->rdlen - pos;
+	if (copy_to_user(buffer, pdata->rdbuf + pos, len))
+		return -EFAULT;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle generic proc file write
+ *
+ *  @param file    A pointer to file structure
+ *  @param buffer  A pointer to input buffer
+ *  @param len     number of byte to write
+ *  @param offset  A pointer to offset of file
+ *  @return		number of input data
+ */
+static ssize_t
+proc_write(struct file *file,
+	   const char __user * buffer, size_t len, loff_t * offset)
+{
+	loff_t pos = *offset;
+	struct proc_data *pdata = (struct proc_data *)file->private_data;
+	int func = 0, reg = 0, val = 0;
+	int config_data = 0;
+	char *line = NULL;
+
+	if (!pdata->wrbuf || (pos < 0))
+		return -EINVAL;
+	if (pos >= pdata->maxwrlen)
+		return 0;
+	if (len > pdata->maxwrlen - pos)
+		len = pdata->maxwrlen - pos;
+	if (copy_from_user(pdata->wrbuf + pos, buffer, len))
+		return -EFAULT;
+	if (!strncmp(pdata->wrbuf + pos, "fw_reload", strlen("fw_reload"))) {
+		if (!strncmp
+		    (pdata->wrbuf + pos, "fw_reload=", strlen("fw_reload="))) {
+			line = pdata->wrbuf + pos;
+			line += strlen("fw_reload") + 1;
+			config_data = string_to_number(line);
+		} else
+			config_data = FW_RELOAD_SDIO_INBAND_RESET;
+		PRINTM(MSG, "Request fw_reload=%d\n", config_data);
+		bt_request_fw_reload(pdata->pbt, config_data);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "sdcmd52rw=", strlen("sdcmd52rw="))) {
+		parse_cmd52_string(pdata->wrbuf + pos, len, &func, &reg, &val);
+		sd_write_cmd52_val(pdata->pbt, func, reg, val);
+	}
+	if (!strncmp(pdata->wrbuf + pos, "debug_dump", strlen("debug_dump"))) {
+		bt_dump_sdio_regs(pdata->pbt);
+		bt_dump_firmware_info_v2(pdata->pbt);
+	}
+
+	if (pos + len > pdata->wrlen)
+		pdata->wrlen = len + file->f_pos;
+	*offset = pos + len;
+	return len;
+}
+
+/**
+ *  @brief This function handle the generic file close
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return		N/A
+ */
+static void
+proc_on_close(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata = file->private_data;
+	char *line;
+	int i;
+	ENTER();
+	if (!pdata->wrlen)
+		return;
+	line = pdata->wrbuf;
+	while (line[0]) {
+		for (i = 0; i < priv->num_items; i++) {
+			if (!strncmp
+			    (line, priv->pdata[i].name,
+			     strlen(priv->pdata[i].name))) {
+				line += strlen(priv->pdata[i].name) + 1;
+				if (priv->pdata[i].size == 1)
+					*((u8 *)priv->pdata[i].addr) =
+						(u8)string_to_number(line);
+				else if (priv->pdata[i].size == 2)
+					*((u16 *) priv->pdata[i].addr) =
+						(u16) string_to_number(line);
+				else if (priv->pdata[i].size == 4)
+					*((u32 *)priv->pdata[i].addr) =
+						(u32)string_to_number(line);
+			}
+		}
+		while (line[0] && line[0] != '\n')
+			line++;
+		if (line[0])
+			line++;
+	}
+	if (priv->pbt->bt_dev.hscmd || priv->pbt->bt_dev.pscmd
+	    || priv->pbt->bt_dev.sdio_pull_ctrl
+	    || priv->pbt->bt_dev.test_mode || priv->pbt->bt_dev.hscfgcmd) {
+		bt_prepare_command(priv->pbt);
+		wake_up_interruptible(&priv->pbt->MainThread.waitQ);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handle the generic file open
+ *
+ *  @param inode   A pointer to inode structure
+ *  @param file    A pointer to file structure
+ *  @return	BT_STATUS_SUCCESS or other error no.
+ */
+static int
+proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	struct proc_private_data *priv = PDE_DATA(inode);
+#else
+	struct proc_private_data *priv = PDE(inode)->data;
+#endif
+	struct proc_data *pdata;
+	int i;
+	char *p;
+	u32 val = 0;
+	ENTER();
+	priv->pbt->adapter->skb_pending =
+		skb_queue_len(&priv->pbt->adapter->tx_queue);
+	file->private_data = kzalloc(sizeof(struct proc_data), GFP_KERNEL);
+	if (file->private_data == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for proc_data\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	pdata = (struct proc_data *)file->private_data;
+	pdata->pbt = priv->pbt;
+	pdata->rdbuf = kmalloc(priv->bufsize, GFP_KERNEL);
+	if (pdata->rdbuf == NULL) {
+		PRINTM(ERROR, "BT: Can not alloc mem for rdbuf\n");
+		kfree(file->private_data);
+		LEAVE();
+		return -ENOMEM;
+	}
+	if (priv->fileflag == DEFAULT_FILE_PERM) {
+		pdata->wrbuf = kzalloc(priv->bufsize, GFP_KERNEL);
+		if (pdata->wrbuf == NULL) {
+			PRINTM(ERROR, "BT: Can not alloc mem for wrbuf\n");
+			kfree(pdata->rdbuf);
+			kfree(file->private_data);
+			return -ENOMEM;
+		}
+		pdata->maxwrlen = priv->bufsize;
+		pdata->on_close = proc_on_close;
+	}
+	p = pdata->rdbuf;
+	for (i = 0; i < priv->num_items; i++) {
+		if (priv->pdata[i].size == 1)
+			val = *((u8 *)priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 2)
+			val = *((u16 *) priv->pdata[i].addr);
+		else if (priv->pdata[i].size == 4)
+			val = *((u32 *)priv->pdata[i].addr);
+		if (priv->pdata[i].flag & SHOW_INT)
+			p += sprintf(p, "%s=%d\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_HEX)
+			p += sprintf(p, "%s=0x%x\n", priv->pdata[i].name, val);
+		else if (priv->pdata[i].flag & SHOW_STRING) {
+			if (!strncmp
+			    (priv->pdata[i].name, "sdcmd52rw",
+			     strlen("sdcmd52rw"))) {
+				sd_read_cmd52_val(priv->pbt);
+				form_cmd52_string(priv->pbt);
+			}
+			p += sprintf(p, "%s=%s\n", priv->pdata[i].name,
+				     (char *)priv->pdata[i].addr);
+		}
+	}
+	pdata->rdlen = strlen(pdata->rdbuf);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/** Proc read ops */
+static const struct file_operations proc_read_ops = {
+	.read = proc_read,
+	.open = proc_open,
+	.release = proc_close
+};
+
+/** Proc Read-Write ops */
+static const struct file_operations proc_rw_ops = {
+	.read = proc_read,
+	.write = proc_write,
+	.open = proc_open,
+	.release = proc_close
+};
+
+static struct proc_private_data proc_files[] = {
+	{"status", S_IRUGO, 1024,
+	 sizeof(status_items) / sizeof(status_items[0]),
+	 &status_items[0], NULL, &proc_read_ops}
+	,
+	{"config", DEFAULT_FILE_PERM, 512,
+	 sizeof(config_items) / sizeof(config_items[0]), &config_items[0], NULL,
+	 &proc_rw_ops}
+	,
+	{"debug", DEFAULT_FILE_PERM, 512,
+	 sizeof(debug_items) / sizeof(debug_items[0]), &debug_items[0], NULL,
+	 &proc_rw_ops}
+	,
+};
+
+/**
+ *  @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
+bt_histogram_read(struct seq_file *sfp, void *data)
+{
+	bt_hist_proc_data *pdata = (bt_hist_proc_data *) sfp->private;
+	bt_private *priv = (bt_private *)pdata->pbt;
+	u8 ant_num;
+	int i, j;
+
+	ENTER();
+	if (!priv) {
+		LEAVE();
+		return -EFAULT;
+	}
+	bt_get_histogram(priv);
+	ant_num = priv->hist_data_len / sizeof(bt_histogram_data);
+	seq_printf(sfp, "BT histogram:\n");
+	seq_printf(sfp, "antenna: 0=2.4G antenna a,  1=2.4G antenna b\n\n");
+	if (ant_num < 1) {
+		seq_printf(sfp, "no histogram data from FW\n");
+		LEAVE();
+		return 0;
+	}
+	for (i = 0; i < ant_num; i++) {
+		if (pdata->antenna != priv->hist_data[i].antenna)
+			continue;
+		seq_printf(sfp, "antenna %d\n", priv->hist_data[i].antenna);
+		switch (priv->hist_data[i].powerclass) {
+		case 2:
+			seq_printf(sfp, "Power class=1.5\n");
+			break;
+		case 5:
+			seq_printf(sfp, "Power class=2\n");
+			break;
+		case 6:
+			seq_printf(sfp, "Power class=1\n");
+			break;
+		default:
+			seq_printf(sfp, "Power class=%d\n",
+				   priv->hist_data[i].powerclass);
+			break;
+		}
+		for (j = 0; j < (MAX_BT_LINK + MAX_BLE_LINK); j++) {
+			switch (priv->hist_data[i].link[j].txrxrate) {
+			case BDR_RATE_1M:
+				seq_printf(sfp,
+					   "BT link[%d]: TxPower=%d dBm, TxRx Rate=BDR(1 mbps), RSSI=%d dBm\n",
+					   j + 1,
+					   priv->hist_data[i].link[j].txpower,
+					   priv->hist_data[i].link[j].rssi);
+				break;
+			case EDR_RATE_2_3M:
+				seq_printf(sfp,
+					   "BT link[%d]: TxPower=%d dBm, TxRx Rate=EDR(2/3 mbps), RSSI=%d dBm\n",
+					   j + 1,
+					   priv->hist_data[i].link[j].txpower,
+					   priv->hist_data[i].link[j].rssi);
+				break;
+			case BLE_RATE_1M:
+				seq_printf(sfp,
+					   "BLE link[%d]: TxPower=%d dBm, TxRx Rate=BLE(1 mbps), RSSI=%d dBm\n",
+					   j - MAX_BT_LINK + 0x80,
+					   priv->hist_data[i].link[j].txpower,
+					   priv->hist_data[i].link[j].rssi);
+				break;
+			default:
+				if (j < MAX_BT_LINK)
+					seq_printf(sfp,
+						   "BT link[%d]: TxPower=%d dBm, TxRx Rate=(%d), RSSI=%d dBm\n",
+						   j + 1,
+						   priv->hist_data[i].link[j].
+						   txpower,
+						   priv->hist_data[i].link[j].
+						   txrxrate,
+						   priv->hist_data[i].link[j].
+						   rssi);
+				else
+					seq_printf(sfp,
+						   "BLE link[%d]: TxPower=%d dBm, TxRx Rate=(%d), RSSI=%d dBm\n",
+						   j - MAX_BT_LINK + 0x80,
+						   priv->hist_data[i].link[j].
+						   txpower,
+						   priv->hist_data[i].link[j].
+						   txrxrate,
+						   priv->hist_data[i].link[j].
+						   rssi);
+				break;
+			}
+		}
+		seq_printf(sfp, "\n");
+	}
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc open function for histogram
+ *
+ *  @param inode     A pointer to inode structure
+ *  @param file		 A pointer to file structure
+ *
+ *  @return        Number of output data or MLAN_STATUS_FAILURE
+ */
+static int
+bt_histogram_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, bt_histogram_read, PDE_DATA(inode));
+#else
+	return single_open(file, bt_histogram_read, PDE(inode)->data);
+#endif
+}
+
+/** Histogram proc fops */
+static const struct file_operations histogram_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = bt_histogram_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+/**
+ *  @brief This function initializes proc entry
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param m_dev    A pointer to struct m_dev
+ *  @param seq      Sequence number
+ *
+ *  @return	BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_proc_init(bt_private *priv, struct m_dev *m_dev, int seq)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct proc_dir_entry *entry;
+	int i, j;
+	char hist_entry[50];
+	ENTER();
+
+	memset(cmd52_string, 0, CMD52_STR_LEN);
+	if (proc_mbt) {
+		priv->dev_proc[seq].proc_entry =
+			proc_mkdir(m_dev->name, proc_mbt);
+		if (!priv->dev_proc[seq].proc_entry) {
+			PRINTM(ERROR, "BT: Could not mkdir %s!\n", m_dev->name);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		priv->dev_proc[seq].hist_entry =
+			proc_mkdir("histogram", priv->dev_proc[seq].proc_entry);
+		if (!priv->dev_proc[seq].hist_entry) {
+			PRINTM(ERROR, "BT: Could not mkdir histogram!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		for (i = 0; i < MAX_ANTENNA_NUM; i++) {
+			priv->hist_proc[i].antenna = i;
+			priv->hist_proc[i].pbt = priv;
+			snprintf(hist_entry, sizeof(hist_entry), "bt-ant%d", i);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			entry = proc_create_data(hist_entry, 0644,
+						 priv->dev_proc[seq].hist_entry,
+						 &histogram_proc_fops,
+						 &priv->hist_proc[i]);
+			if (entry == NULL)
+#else
+			entry = create_proc_entry(hist_entry, 0644,
+						  priv->dev_proc[seq].
+						  hist_entry);
+			if (entry) {
+				entry->data = &priv->hist_proc[i];
+				entry->proc_fops = &histogram_proc_fops;
+			} else
+#endif
+			{
+				PRINTM(MSG,
+				       "Fail to create histogram proc %s\n",
+				       hist_entry);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		priv->dev_proc[seq].pfiles =
+			kmalloc(sizeof(proc_files), GFP_ATOMIC);
+		if (!priv->dev_proc[seq].pfiles) {
+			PRINTM(ERROR,
+			       "BT: Could not alloc memory for pfile!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy((u8 *)priv->dev_proc[seq].pfiles, (u8 *)proc_files,
+		       sizeof(proc_files));
+		priv->dev_proc[seq].num_proc_files = ARRAY_SIZE(proc_files);
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++)
+			priv->dev_proc[seq].pfiles[j].pdata = NULL;
+		for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+			priv->dev_proc[seq].pfiles[j].pdata =
+				kmalloc(priv->dev_proc[seq].pfiles[j].
+					num_items * sizeof(struct item_data),
+					GFP_ATOMIC);
+			if (!priv->dev_proc[seq].pfiles[j].pdata) {
+				PRINTM(ERROR,
+				       "BT: Could not alloc memory for pdata!\n");
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			memcpy((u8 *)priv->dev_proc[seq].pfiles[j].pdata,
+			       (u8 *)proc_files[j].pdata,
+			       priv->dev_proc[seq].pfiles[j].num_items *
+			       sizeof(struct item_data));
+			for (i = 0; i < priv->dev_proc[seq].pfiles[j].num_items;
+			     i++) {
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_DEV)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)&priv->bt_dev;
+				if (priv->dev_proc[seq].pfiles[j].
+				    pdata[i].flag & OFFSET_BT_ADAPTER)
+					priv->dev_proc[seq].pfiles[j].pdata[i].
+						addr =
+						priv->dev_proc[seq].pfiles[j].
+						pdata[i].offset +
+						(t_ptr)priv->adapter;
+			}
+			priv->dev_proc[seq].pfiles[j].pbt = priv;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			entry = proc_create_data(proc_files[j].name,
+						 S_IFREG | proc_files[j].
+						 fileflag,
+						 priv->dev_proc[seq].proc_entry,
+						 proc_files[j].fops,
+						 &priv->dev_proc[seq].
+						 pfiles[j]);
+			if (entry == NULL)
+#else
+			entry = create_proc_entry(proc_files[j].name,
+						  S_IFREG | proc_files[j].
+						  fileflag,
+						  priv->dev_proc[seq].
+						  proc_entry);
+			if (entry) {
+				entry->data = &priv->dev_proc[seq].pfiles[j];
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
+				entry->owner = THIS_MODULE;
+#endif
+				entry->proc_fops = proc_files[j].fops;
+			} else
+#endif
+				PRINTM(MSG, "BT: Fail to create proc %s\n",
+				       proc_files[j].name);
+		}
+	}
+done:
+	if (ret == BT_STATUS_FAILURE) {
+		if (priv->dev_proc[seq].proc_entry) {
+			remove_proc_entry(m_dev->name, proc_mbt);
+			priv->dev_proc[seq].proc_entry = NULL;
+		}
+		if (priv->dev_proc[seq].pfiles) {
+			for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) {
+				if (priv->dev_proc[seq].pfiles[j].pdata) {
+					kfree(priv->dev_proc[seq].pfiles[j].
+					      pdata);
+					priv->dev_proc[seq].pfiles[j].pdata =
+						NULL;
+				}
+			}
+			kfree(priv->dev_proc[seq].pfiles);
+			priv->dev_proc[seq].pfiles = NULL;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return	N/A
+ */
+void
+bt_proc_remove(bt_private *priv)
+{
+	int j, i;
+	char hist_entry[50];
+	ENTER();
+	PRINTM(INFO, "BT: Remove Proc Interface\n");
+	if (proc_mbt) {
+		for (i = 0; i < MAX_RADIO_FUNC; i++) {
+			if (!priv->dev_proc[i].proc_entry)
+				continue;
+			for (j = 0; j < ARRAY_SIZE(proc_files); j++) {
+				remove_proc_entry(proc_files[j].name,
+						  priv->dev_proc[i].proc_entry);
+			}
+			for (j = 0; j < MAX_ANTENNA_NUM; j++) {
+				snprintf(hist_entry, sizeof(hist_entry),
+					 "bt-ant%d", j);
+				remove_proc_entry(hist_entry,
+						  priv->dev_proc[i].hist_entry);
+			}
+			remove_proc_entry("histogram",
+					  priv->dev_proc[i].proc_entry);
+			remove_proc_entry(priv->bt_dev.m_dev[i].name, proc_mbt);
+			priv->dev_proc[i].proc_entry = NULL;
+
+			if (priv->dev_proc[i].pfiles) {
+				for (j = 0;
+				     j < priv->dev_proc[i].num_proc_files;
+				     j++) {
+					if (priv->dev_proc[i].pfiles[j].pdata) {
+						kfree(priv->dev_proc[i].
+						      pfiles[j].pdata);
+						priv->dev_proc[i].pfiles[j].
+							pdata = NULL;
+					}
+				}
+				kfree(priv->dev_proc[i].pfiles);
+				priv->dev_proc[i].pfiles = NULL;
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function creates proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+bt_root_proc_init(void)
+{
+	PRINTM(INFO, "BT: Create Proc Interface\n");
+	proc_mbt = proc_mkdir("mbt", PROC_DIR);
+	if (!proc_mbt) {
+		PRINTM(ERROR, "BT: Cannot create proc interface\n");
+		return BT_STATUS_FAILURE;
+	}
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function removes proc interface
+ *  directory structure
+ *
+ *  @return		BT_STATUS_SUCCESS
+ */
+int
+bt_root_proc_remove(void)
+{
+	remove_proc_entry("mbt", PROC_DIR);
+	proc_mbt = NULL;
+	return BT_STATUS_SUCCESS;
+}
diff --git a/bt_sd8997/bt_char/bt_sdio.h b/bt_sd8997/bt_char/bt_sdio.h
new file mode 100644
index 0000000..ac3ac01
--- /dev/null
+++ b/bt_sd8997/bt_char/bt_sdio.h
@@ -0,0 +1,258 @@
+/** @file bt_sdio.h
+ *  @brief This file contains SDIO (interface) module
+ *  related macros, enum, and structure.
+ *
+ *  Copyright (C) 2007-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _BT_SDIO_H_
+#define _BT_SDIO_H_
+
+#include <linux/irqreturn.h>
+
+/** IRQ return type */
+typedef irqreturn_t IRQ_RET_TYPE;
+/** IRQ return */
+#define IRQ_RET		(return IRQ_HANDLED)
+/** ISR notifier function */
+typedef IRQ_RET_TYPE (*isr_notifier_fn_t) (s32 irq, void *dev_id,
+					   struct pt_regs * reg);
+
+/** SDIO header length */
+#define SDIO_HEADER_LEN			4
+
+/** 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
+/* SD block size can not bigger than 64 due to buf size limit in firmware */
+/** define SD block size for data Tx/Rx */
+#define SD_BLOCK_SIZE			64
+/** define SD block size for firmware download */
+#define SD_BLOCK_SIZE_FW_DL		256
+
+/** Number of blocks for firmware transfer */
+#define FIRMWARE_TRANSFER_NBLOCK	2
+
+/** Firmware ready */
+#define FIRMWARE_READY			0xfedc
+
+/* Bus Interface Control Reg 0x07 */
+/** SD BUS width 1 */
+#define SD_BUS_WIDTH_1			0x00
+/** SD BUS width 4 */
+#define SD_BUS_WIDTH_4			0x02
+/** SD BUS width mask */
+#define SD_BUS_WIDTH_MASK		0x03
+/** Asynchronous interrupt mode */
+#define ASYNC_INT_MODE			0x20
+
+/** magic register */
+#define CARD_MAGIC_REG          0xF0
+/** magic value */
+#define MAGIC_VAL               0x24
+
+/* Host Control Registers */
+/** Host Control Registers : Configuration */
+#define CONFIGURATION_REG		0x00
+/** Host Control Registers : Host without Command 53 finish host*/
+#define HOST_TO_CARD_EVENT		(0x1U << 3)
+/** Host Control Registers : Host terminates Command 53 */
+#define HOST_TERM_CMD53			(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 : Host interrupt RSR */
+#define HOST_INT_RSR_REG		0x04
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR		(0x1U)
+
+/** Host Control Registers : Host interrupt mask */
+#define HOST_INT_MASK_REG		0x08
+
+/** 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)
+/** Enable Host interrupt mask */
+#define HIM_ENABLE			(UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
+/** Disable Host interrupt mask */
+#define	HIM_DISABLE			0xff
+
+/** Host Control Registers : Host interrupt status */
+#define HOST_INTSTATUS_REG		0x0C
+/** Host Control Registers : Upload host interrupt status */
+#define UP_LD_HOST_INT_STATUS		(0x1U)
+/** Host Control Registers : Download host interrupt status */
+#define DN_LD_HOST_INT_STATUS		(0x2U)
+
+/** Host Control Registers : Host Transfer status */
+#define HOST_INT_STATUS_REG		0x58
+/** Host Control Registers : Upload CRC error */
+#define UP_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 : Card to Host Event register */
+#define CARD_STATUS_REG			0x5C
+/** 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 interrupt mask register */
+#define HOST_INTERRUPT_MASK_REG 	0x60
+/** 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 : Card interrupt status register */
+#define CARD_INTERRUPT_STATUS_REG    	0x64
+/** 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 : Card interrupt RSR register */
+#define CARD_INTERRUPT_RSR_REG       	0x68
+/** 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 */
+/** Card Control Registers : Read SQ base address A0 register */
+#define SQ_READ_BASE_ADDRESS_A0_REG  	0xf8
+/** Card Control Registers : Read SQ base address A1 register */
+#define SQ_READ_BASE_ADDRESS_A1_REG  	0xf9
+/** Card Control Registers : Read SQ base address A2 register */
+#define SQ_READ_BASE_ADDRESS_A2_REG  	0x6E
+/** Card Control Registers : Read SQ base address A3 register */
+#define SQ_READ_BASE_ADDRESS_A3_REG  	0x6F
+/** Card Control Registers : Write SQ base address A0 register */
+#define SQ_WRITE_BASE_ADDRESS_A0_REG  	0x70
+/** Card Control Registers : Write SQ base address A1 register */
+#define SQ_WRITE_BASE_ADDRESS_A1_REG  	0x71
+/** Card Control Registers : Write SQ base address A2 register */
+#define SQ_WRITE_BASE_ADDRESS_A2_REG  	0x72
+/** Card Control Registers : Write SQ base address A3 register */
+#define SQ_WRITE_BASE_ADDRESS_A3_REG  	0x73
+
+/** Card Control Registers : Card revision register */
+#define CARD_REVISION_REG            	0xC8
+
+/** Firmware status 0 register (SCRATCH0_0) */
+#define CARD_FW_STATUS0_REG             0xe8
+/** Firmware status 1 register (SCRATCH0_1) */
+#define CARD_FW_STATUS1_REG             0xe9
+/** Rx length register (SCRATCH0_2) */
+#define CARD_RX_LEN_REG                 0xea
+/** Rx unit register (SCRATCH0_3) */
+#define CARD_RX_UNIT_REG                0xeb
+/** 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
+
+/** Card Control Registers : Card OCR 0 register */
+#define CARD_OCR_0_REG			0xD4
+/** Card Control Registers : Card OCR 1 register */
+#define CARD_OCR_1_REG			0xD5
+/** Card Control Registers : Card OCR 3 register */
+#define CARD_OCR_3_REG			0xD6
+/** Card Control Registers : Card config register */
+#define CARD_CONFIG_REG			0xD7
+/** Card Control Registers : Miscellaneous Configuration Register */
+#define CARD_MISC_CFG_REG		0xD8
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT		(0x1U << 4)
+
+/** Card Control Registers : Debug 0 register */
+#define DEBUG_0_REG			0xDC
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0			(0x1U)
+/** Card Control Registers : Debug 1 register */
+#define DEBUG_1_REG			0xDD
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1			(0x1U)
+/** Card Control Registers : Debug 2 register */
+#define DEBUG_2_REG			0xDE
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2			(0x1U)
+/** Card Control Registers : Debug 3 register */
+#define DEBUG_3_REG			0xDF
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3			(0x1U)
+
+/** Host Control Registers : I/O port 0 */
+#define IO_PORT_0_REG			0xE4
+/** Host Control Registers : I/O port 1 */
+#define IO_PORT_1_REG			0xE5
+/** Host Control Registers : I/O port 2 */
+#define IO_PORT_2_REG			0xE6
+
+struct sdio_mmc_card {
+	/** sdio_func structure pointer */
+	struct sdio_func *func;
+	/** bt_private structure pointer */
+	bt_private *priv;
+};
+
+/** DMA alignment value */
+#define DMA_ALIGNMENT	64
+/** 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))
+
+/** This function read cmd52 register */
+int sd_write_reg(bt_private *priv, int reg, u8 val);
+/** This function write cmd52 value to register */
+int sd_read_reg(bt_private *priv, int reg, u8 *data);
+/** This function reads the Cmd52 value in dev structure */
+int sd_read_cmd52_val(bt_private *priv);
+/** This function updates card reg based on the Cmd52 value in dev structure */
+int sd_write_cmd52_val(bt_private *priv, int func, int reg, int val);
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** This function tells lower driver that BT is suspended */
+void bt_is_suspended(bt_private *priv);
+#endif
+#endif
+#endif
+#endif /* _BT_SDIO_H_ */
diff --git a/bt_sd8997/bt_char/bt_sdiommc.c b/bt_sd8997/bt_char/bt_sdiommc.c
new file mode 100644
index 0000000..9867049
--- /dev/null
+++ b/bt_sd8997/bt_char/bt_sdiommc.c
@@ -0,0 +1,1920 @@
+/** @file bt_sdiommc.c
+ *  @brief This file contains SDIO IF (interface) module
+ *  related functions.
+ *
+ * Copyright (C) 2007-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/mmc/sdio_func.h>
+#include        <linux/mmc/sdio.h>
+#include        <linux/mmc/card.h>
+
+#include "bt_drv.h"
+#include "bt_sdio.h"
+
+/** define marvell vendor id */
+#define MARVELL_VENDOR_ID 0x02df
+
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD53_RETRY 	3
+/** Max retry number of CMD53 read/write */
+#define MAX_CMD52_RETRY     3
+/** Firmware name */
+static char *fw_name;
+/** fw serial download flag */
+extern int bt_fw_serial;
+/** request firmware nowait */
+int bt_req_fw_nowait;
+static int multi_fn = BIT(2);
+
+#define SD8997_FW_NAME "mrvl/sdsd8997_combo_v4.bin"
+#define SD8997_BT_FW_NAME "mrvl/sd8997_bt_v4.bin"
+#define DEFAULT_FW_NAME "mrvl/sdsd8997_combo_v4.bin"
+#define DEFAULT_BT_FW_NAME "mrvl/sd8997_bt_v4.bin"
+
+/** Function number 2 */
+#define FN2			2
+/** Device ID for SD8997 FN2 */
+#define SD_DEVICE_ID_8997_BT_FN2    0x9142
+
+/** Array of SDIO device ids when multi_fn=0x12 */
+static const struct sdio_device_id bt_ids[] = {
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8997_BT_FN2)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(sdio, bt_ids);
+
+/********************************************************
+		Global Variables
+********************************************************/
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+extern int mbt_pm_keep_power;
+#endif
+
+extern bt_private *m_priv[];
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief This function gets rx_unit value
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_get_rx_unit(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_unit_reg = CARD_RX_UNIT_REG;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_unit_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		priv->bt_dev.rx_unit = reg;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads fwstatus registers
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_read_firmware_status(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 fws0;
+	u8 fws1;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = CARD_FW_STATUS0_REG;
+	u8 card_fw_status1_reg = CARD_FW_STATUS1_REG;
+
+	ENTER();
+
+	fws0 = sdio_readb(card->func, card_fw_status0_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	fws1 = sdio_readb(card->func, card_fw_status1_reg, &ret);
+	if (ret < 0) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	*dat = (((u16) fws1) << 8) | fws0;
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function reads rx length
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param dat	   A pointer to keep returned data
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sd_read_rx_len(bt_private *priv, u16 * dat)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_rx_len_reg = CARD_RX_LEN_REG;
+
+	ENTER();
+
+	reg = sdio_readb(card->func, card_rx_len_reg, &ret);
+	if (ret == BT_STATUS_SUCCESS)
+		*dat = (u16) reg << priv->bt_dev.rx_unit;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables the host interrupts mask
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_enable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = HOST_INT_MASK_REG;
+
+	ENTER();
+
+	sdio_writeb(card->func, mask, host_int_mask_reg, &ret);
+	if (ret) {
+		PRINTM(WARN, "BT: Unable to enable the host interrupt!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/** @brief This function disables the host interrupts mask.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param mask	   the interrupt mask
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+static int
+sbi_disable_host_int_mask(bt_private *priv, u8 mask)
+{
+	int ret = BT_STATUS_FAILURE;
+	u8 host_int_mask;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 host_int_mask_reg = HOST_INT_MASK_REG;
+
+	ENTER();
+
+	/* Read back the host_int_mask register */
+	host_int_mask = sdio_readb(card->func, host_int_mask_reg, &ret);
+	if (ret)
+		goto done;
+
+	/* Update with the mask and write back to the register */
+	host_int_mask &= ~mask;
+	sdio_writeb(card->func, host_int_mask, host_int_mask_reg, &ret);
+	if (ret < 0) {
+		PRINTM(WARN, "BT: Unable to diable the host interrupt!\n");
+		goto done;
+	}
+	ret = BT_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function polls the card status register
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param bits     the bit mask
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_poll_card_status(bt_private *priv, u8 bits)
+{
+	int tries;
+	int rval;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 cs;
+	u8 card_status_reg = CARD_STATUS_REG;
+
+	ENTER();
+
+	for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
+		cs = sdio_readb(card->func, card_status_reg, &rval);
+		if (rval != 0)
+			break;
+		if (rval == 0 && (cs & bits) == bits) {
+			LEAVE();
+			return BT_STATUS_SUCCESS;
+		}
+		udelay(1);
+	}
+	PRINTM(ERROR,
+	       "BT: sdio_poll_card_status failed (%d), tries = %d, cs = 0x%x\n",
+	       rval, tries, cs);
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_cmd52_val(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 func, reg, val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	func = priv->bt_dev.cmd52_func;
+	reg = priv->bt_dev.cmd52_reg;
+	sdio_claim_host(card->func);
+	if (func)
+		val = sdio_readb(card->func, reg, &ret);
+	else
+		val = sdio_f0_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	if (ret) {
+		PRINTM(ERROR, "BT: Cannot read value from func %d reg %d\n",
+		       func, reg);
+	} else {
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param func     Stores func variable
+ *  @param reg      Stores reg variable
+ *  @param val      Stores val variable
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_cmd52_val(bt_private *priv, int func, int reg, int val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	ENTER();
+
+	if (val >= 0) {
+		/* Perform actual write only if val is provided */
+		sdio_claim_host(card->func);
+		if (func)
+			sdio_writeb(card->func, val, reg, &ret);
+		else
+			sdio_f0_writeb(card->func, val, reg, &ret);
+		sdio_release_host(card->func);
+		if (ret) {
+			PRINTM(ERROR,
+			       "BT: Cannot write value (0x%x) to func %d reg %d\n",
+			       val, func, reg);
+			goto done;
+		}
+		priv->bt_dev.cmd52_val = val;
+	}
+
+	/* Save current func and reg for future read */
+	priv->bt_dev.cmd52_func = func;
+	priv->bt_dev.cmd52_reg = reg;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to write
+ *  @param val      value
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_write_reg(bt_private *priv, int reg, u8 val)
+{
+	int ret = BT_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, val, reg, &ret);
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads updates the Cmd52 value in dev structure
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param reg      register to read
+ *  @param data		Data
+ *  @return         BT_STATUS_SUCCESS or other error no.
+ */
+int
+sd_read_reg(bt_private *priv, int reg, u8 *data)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 val;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	ENTER();
+	sdio_claim_host(card->func);
+	val = sdio_readb(card->func, reg, &ret);
+	sdio_release_host(card->func);
+	*data = val;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function probes the card
+ *
+ *  @param func    A pointer to sdio_func structure.
+ *  @param id      A pointer to structure sdio_device_id
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_probe_card(struct sdio_func *func, const struct sdio_device_id *id)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *card = NULL;
+
+	ENTER();
+
+	PRINTM(INFO, "BT: vendor=0x%x,device=0x%x,class=%d,fn=%d\n", id->vendor,
+	       id->device, id->class, func->num);
+	card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
+	if (!card) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	card->func = func;
+#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_disable_func(func);
+		sdio_release_host(func);
+		PRINTM(FATAL, "BT: sdio_enable_func() failed: ret=%d\n", ret);
+		kfree(card);
+		LEAVE();
+		return -EIO;
+	}
+	sdio_release_host(func);
+	priv = bt_add_card(card);
+	if (!priv) {
+		sdio_claim_host(func);
+		sdio_disable_func(func);
+		sdio_release_host(func);
+		ret = BT_STATUS_FAILURE;
+		kfree(card);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @param pollnum  Number of times to poll fw status
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_verify_fw_download(bt_private *priv, int pollnum)
+{
+	int ret = BT_STATUS_FAILURE;
+	u16 firmwarestat = 0;
+	int tries;
+
+	ENTER();
+
+	/* Wait for firmware initialization event */
+	for (tries = 0; tries < pollnum; tries++) {
+		if (sd_read_firmware_status(priv, &firmwarestat) < 0)
+			continue;
+		if (firmwarestat == FIRMWARE_READY) {
+			PRINTM(MSG, "BT FW is active(%d)\n", tries);
+			ret = BT_STATUS_SUCCESS;
+			break;
+		}
+		mdelay(100);
+	}
+	if ((pollnum > 1) && (ret != BT_STATUS_SUCCESS)) {
+		PRINTM(ERROR,
+		       "Fail to poll firmware status: firmwarestat=0x%x\n",
+		       firmwarestat);
+		bt_dump_sdio_regs(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Transfers firmware to card
+ *
+ *  @param priv      A Pointer to bt_private structure
+ *  @param fw        A Pointer to fw image
+ *  @param fw_len    fw image len
+ *  @return          BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+static int
+sd_init_fw_dpc(bt_private *priv, u8 *fw, int fw_len)
+{
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 *firmware = fw;
+	int firmwarelen = fw_len;
+	u8 base0;
+	u8 base1;
+	int ret = BT_STATUS_SUCCESS;
+	int offset;
+	void *tmpfwbuf = NULL;
+	int tmpfwbufsz;
+	u8 *fwbuf;
+	u16 len;
+	int txlen = 0;
+	int tx_blocks = 0;
+	int i = 0;
+	int tries = 0;
+#ifdef FW_DOWNLOAD_SPEED
+	u32 tv1, tv2;
+#endif
+	u8 sq_read_base_address_a0_reg = SQ_READ_BASE_ADDRESS_A0_REG;
+	u8 sq_read_base_address_a1_reg = SQ_READ_BASE_ADDRESS_A1_REG;
+
+	ENTER();
+
+	PRINTM(INFO, "BT: Downloading FW image (%d bytes)\n", firmwarelen);
+
+#ifdef FW_DOWNLOAD_SPEED
+	tv1 = get_utimeofday();
+#endif
+
+	tmpfwbufsz = BT_UPLD_SIZE + DMA_ALIGNMENT;
+	tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
+	if (!tmpfwbuf) {
+		PRINTM(ERROR,
+		       "BT: Unable to allocate buffer for firmware. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	/* Ensure aligned firmware buffer */
+	fwbuf = (u8 *)ALIGN_ADDR(tmpfwbuf, DMA_ALIGNMENT);
+
+	/* Perform firmware data transfer */
+	offset = 0;
+	do {
+		/* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits
+		 */
+		ret = sd_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
+		if (ret < 0) {
+			PRINTM(FATAL,
+			       "BT: FW download with helper poll status timeout @ %d\n",
+			       offset);
+			goto done;
+		}
+		/* More data? */
+		if (offset >= firmwarelen)
+			break;
+
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			base0 = sdio_readb(card->func,
+					   sq_read_base_address_a0_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE0 register read failed:"
+				       " base0=0x%04X(%d). Terminating download\n",
+				       base0, base0);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			base1 = sdio_readb(card->func,
+					   sq_read_base_address_a1_reg, &ret);
+			if (ret) {
+				PRINTM(WARN, "Dev BASE1 register read failed:"
+				       " base1=0x%04X(%d). Terminating download\n",
+				       base1, base1);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			len = (((u16) base1) << 8) | base0;
+
+			if (len != 0)
+				break;
+			udelay(10);
+		}
+
+		if (len == 0)
+			break;
+		else if (len > BT_UPLD_SIZE) {
+			PRINTM(FATAL,
+			       "BT: FW download failure @ %d, invalid length %d\n",
+			       offset, len);
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+	/** ignore CRC check before download the first packet */
+		if (offset == 0 && (len & BIT(0)))
+			len &= ~BIT(0);
+		txlen = len;
+
+		if (len & BIT(0)) {
+			i++;
+			if (i >= MAX_CMD53_RETRY) {
+				PRINTM(FATAL,
+				       "BT: FW download failure @ %d, over max retry count\n",
+				       offset);
+				ret = BT_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(ERROR,
+			       "BT: FW CRC error indicated by the helper:"
+			       " len = 0x%04X, txlen = %d\n", len, txlen);
+			len &= ~BIT(0);
+
+			PRINTM(ERROR, "BT: retry: %d, offset %d\n", i, offset);
+			/* Setting this to 0 to resend from same offset */
+			txlen = 0;
+		} else {
+			i = 0;
+
+			/* Set blocksize to transfer - checking for last block */
+			if (firmwarelen - offset < txlen)
+				txlen = firmwarelen - offset;
+
+			PRINTM(INFO, ".");
+
+			tx_blocks =
+				(txlen + SD_BLOCK_SIZE_FW_DL -
+				 1) / SD_BLOCK_SIZE_FW_DL;
+
+			/* Copy payload to buffer */
+			memcpy(fwbuf, &firmware[offset], txlen);
+		}
+
+		/* Send data */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, fwbuf,
+				   tx_blocks * SD_BLOCK_SIZE_FW_DL);
+
+		if (ret < 0) {
+			PRINTM(ERROR,
+			       "BT: FW download, write iomem (%d) failed @ %d\n",
+			       i, offset);
+			sdio_writeb(card->func, 0x04, CONFIGURATION_REG, &ret);
+			if (ret)
+				PRINTM(ERROR, "write ioreg failed (CFG)\n");
+		}
+
+		offset += txlen;
+	} while (TRUE);
+
+	PRINTM(MSG, "BT: FW download over, size %d bytes\n", offset);
+
+	ret = BT_STATUS_SUCCESS;
+done:
+#ifdef FW_DOWNLOAD_SPEED
+	tv2 = get_utimeofday();
+	PRINTM(INFO, "FW: %d.%03d.%03d ", tv1 / 1000000,
+	       (tv1 % 1000000) / 1000, tv1 % 1000);
+	PRINTM(INFO, " -> %d.%03d.%03d ", tv2 / 1000000,
+	       (tv2 % 1000000) / 1000, tv2 % 1000);
+	tv2 -= tv1;
+	PRINTM(INFO, " == %d.%03d.%03d\n", tv2 / 1000000,
+	       (tv2 % 1000000) / 1000, tv2 % 1000);
+#endif
+	kfree(tmpfwbuf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *
+ * @param fw_firmware  A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_request_fw_dpc(const struct firmware *fw_firmware, void *context)
+{
+	int ret = BT_STATUS_SUCCESS;
+	bt_private *priv = (bt_private *)context;
+	struct sdio_mmc_card *card = NULL;
+	struct m_dev *m_dev_bt = NULL;
+	struct timeval tstamp;
+	int index;
+
+	ENTER();
+
+	m_dev_bt = &priv->bt_dev.m_dev[BT_SEQ];
+
+	if ((priv == NULL) || (priv->adapter == NULL) ||
+	    (priv->bt_dev.card == NULL) || (m_dev_bt == NULL)
+		) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+
+	card = (struct sdio_mmc_card *)priv->bt_dev.card;
+
+	if (!fw_firmware) {
+		do_gettimeofday(&tstamp);
+		if (tstamp.tv_sec >
+		    (priv->req_fw_time.tv_sec + REQUEST_FW_TIMEOUT)) {
+			PRINTM(ERROR,
+			       "BT: No firmware image found. Skipping download\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		PRINTM(ERROR,
+		       "BT: No firmware image found! Retrying download\n");
+		/* Wait a second here before calling the callback again */
+		os_sched_timeout(1000);
+		sd_download_firmware_w_helper(priv);
+		LEAVE();
+		return ret;
+	}
+
+	priv->firmware = fw_firmware;
+
+	if (BT_STATUS_FAILURE ==
+	    sd_init_fw_dpc(priv, (u8 *)priv->firmware->data,
+			   priv->firmware->size)) {
+		PRINTM(ERROR,
+		       "BT: sd_init_fw_dpc failed (download fw with nowait: %d). Terminating download\n",
+		       bt_req_fw_nowait);
+		sdio_release_host(card->func);
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* check if the fimware is downloaded successfully or not */
+	if (sd_verify_fw_download(priv, MAX_FIRMWARE_POLL_TRIES)) {
+		PRINTM(ERROR, "BT: FW failed to be active in time!\n");
+		ret = BT_STATUS_FAILURE;
+		sdio_release_host(card->func);
+		goto done;
+	}
+	sdio_release_host(card->func);
+	sbi_enable_host_int(priv);
+	if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+		PRINTM(ERROR,
+		       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+		ret = BT_STATUS_FAILURE;
+		goto done;
+	}
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	LEAVE();
+	return ret;
+
+done:
+	if (fw_firmware) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		if (!bt_req_fw_nowait)
+#endif
+			release_firmware(fw_firmware);
+	}
+	/* For synchronous download cleanup will be done in add_card */
+	if (!bt_req_fw_nowait)
+		return ret;
+	PRINTM(INFO, "unregister device\n");
+	sbi_unregister_dev(priv);
+	((struct sdio_mmc_card *)card)->priv = NULL;
+	/* Stop the thread servicing the interrupts */
+	priv->adapter->SurpriseRemoved = TRUE;
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	while (priv->MainThread.pid)
+		os_sched_timeout(1);
+	bt_proc_remove(priv);
+	clean_up_m_devs(priv);
+	bt_free_adapter(priv);
+	for (index = 0; index < MAX_BT_ADAPTER; index++) {
+		if (m_priv[index] == priv) {
+			m_priv[index] = NULL;
+			break;
+		}
+	}
+	bt_priv_put(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief request_firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware     A pointer to firmware structure
+ * @param context      A Pointer to bt_private structure
+ * @return             None
+ **/
+static void
+sd_request_fw_callback(const struct firmware *firmware, void *context)
+{
+	ENTER();
+	sd_request_fw_dpc(firmware, context);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function downloads firmware image to the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sd_download_firmware_w_helper(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	int err;
+	char *cur_fw_name = NULL;
+
+	ENTER();
+
+	cur_fw_name = fw_name;
+	if (fw_name == NULL) {
+		if (!bt_fw_serial || priv->fw_reload || bt_fw_reload)
+			cur_fw_name = DEFAULT_BT_FW_NAME;
+		else
+			cur_fw_name = DEFAULT_FW_NAME;
+	}
+
+	PRINTM(MSG, "BT Request firmware: %s\n", cur_fw_name);
+	if (bt_req_fw_nowait) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      GFP_KERNEL, priv,
+					      sd_request_fw_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#else
+		ret = request_firmware_nowait(THIS_MODULE,
+					      cur_fw_name, priv->hotplug_device,
+					      priv, sd_request_fw_callback);
+#endif
+#endif
+		if (ret < 0)
+			PRINTM(FATAL,
+			       "BT: request_firmware_nowait() failed, error code = %#x\n",
+			       ret);
+	} else {
+		err = request_firmware(&priv->firmware, cur_fw_name,
+				       priv->hotplug_device);
+		if (err < 0) {
+			PRINTM(FATAL,
+			       "BT: request_firmware() failed, error code = %#x\n",
+			       err);
+			ret = BT_STATUS_FAILURE;
+		} else
+			ret = sd_request_fw_dpc(priv->firmware, priv);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads data from the card.
+ *
+ *  @param priv     A pointer to bt_private structure
+ *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+static int
+sd_card_to_host(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u16 buf_len = 0;
+	int buf_block_len;
+	int blksz;
+	struct sk_buff *skb = NULL;
+	u32 type;
+	u8 *payload = NULL;
+	struct mbt_dev *mbt_dev = NULL;
+	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
+	struct m_dev *mdev_debug = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
+	struct debug_dev *debug_dev =
+		(struct debug_dev *)priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int i = 0;
+
+	ENTER();
+	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
+		mbt_dev =
+			(struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].
+			dev_pointer;
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	do {
+		/* Read the length of data to be transferred */
+		ret = sd_read_rx_len(priv, &buf_len);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR, "BT: Read scratch reg failed (%d)\n", i);
+			if (i >= MAX_CMD52_RETRY) {
+				ret = BT_STATUS_FAILURE;
+				goto exit;
+			}
+			udelay(20);
+		}
+	}
+	while (ret == BT_STATUS_FAILURE);
+
+	/* Allocate buffer */
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (buf_len + blksz - 1) / blksz;
+	if (buf_len <= BT_HEADER_LEN ||
+	    (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+		PRINTM(ERROR, "BT: card_to_host, invalid packet length: %d\n",
+		       buf_len);
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+	skb = bt_skb_alloc(buf_block_len * blksz + DMA_ALIGNMENT, GFP_ATOMIC);
+	if (skb == NULL) {
+		PRINTM(WARN, "BT: No free skb\n");
+		goto exit;
+	}
+	if ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)) {
+		skb_put(skb,
+			DMA_ALIGNMENT -
+			((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+		skb_pull(skb,
+			 DMA_ALIGNMENT -
+			 ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
+	}
+
+	payload = skb->data;
+	i = 0;
+	do {
+		ret = sdio_readsb(card->func, payload, priv->bt_dev.ioport,
+				  buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: card_to_host, read iomem (%d) failed: %d\n",
+			       i, ret);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY) {
+				kfree_skb(skb);
+				skb = NULL;
+				goto exit;
+			}
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	/* This is SDIO specific header length: byte[2][1][0], * type: byte[3]
+	   (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
+	buf_len = payload[0];
+	buf_len |= (u16) payload[1] << 8;
+	type = payload[3];
+	PRINTM(DATA, "BT: SDIO Blk Rd %s: len=%d type=%d\n", mbt_dev->name,
+	       buf_len, type);
+	if (buf_len > buf_block_len * blksz) {
+		PRINTM(ERROR,
+		       "BT: Drop invalid rx pkt, len in hdr=%d, cmd53 length=%d\n",
+		       buf_len, buf_block_len * blksz);
+		ret = BT_STATUS_FAILURE;
+		kfree_skb(skb);
+		skb = NULL;
+		goto exit;
+	}
+	DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Rd", payload, buf_len);
+	switch (type) {
+	case HCI_ACLDATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (*(u16 *) skb->data == 0xffff) {
+			skb_queue_tail(&priv->adapter->fwdump_queue, skb);
+			break;
+		}
+		bt_recv_frame(priv, skb);
+		break;
+	case HCI_SCODATA_PKT:
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		bt_recv_frame(priv, skb);
+		break;
+	case HCI_EVENT_PKT:
+		/** add EVT Demux */
+		bt_cb(skb)->pkt_type = type;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (BT_STATUS_SUCCESS == check_evtpkt(priv, skb))
+			break;
+		switch (skb->data[0]) {
+		case 0x0E:
+			/** cmd complete */
+			if (priv->debug_device_pending) {
+				if (priv->debug_ocf_ogf[0] == skb->data[3] &&
+				    priv->debug_ocf_ogf[1] == skb->data[4]) {
+					priv->debug_device_pending = 0;
+					priv->debug_ocf_ogf[0] = 0;
+					priv->debug_ocf_ogf[1] = 0;
+					/** debug cmd complete */
+					if (debug_dev) {
+						skb->dev = (void *)mdev_debug;
+						mdev_recv_frame(skb);
+						mdev_debug->stat.byte_rx +=
+							buf_len;
+					}
+					break;
+				}
+			}
+			bt_recv_frame(priv, skb);
+			break;
+		case 0x0F:
+			/** cmd status */
+			bt_recv_frame(priv, skb);
+			break;
+		case 0xFF:
+			/** Vendor specific pkt */
+			bt_recv_frame(priv, skb);
+			break;
+		default:
+			bt_recv_frame(priv, skb);
+			break;
+		}
+		break;
+	case MRVL_VENDOR_PKT:
+		/* Just think here need to back compatible FM */
+		bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
+		skb_put(skb, buf_len);
+		skb_pull(skb, BT_HEADER_LEN);
+		if (BT_STATUS_SUCCESS != bt_process_event(priv, skb))
+			bt_recv_frame(priv, skb);
+		break;
+	default:
+		/* Driver specified event and command resp should be handle
+		   here */
+		PRINTM(INFO, "BT: Unknown PKT type:%d\n", type);
+		kfree_skb(skb);
+		skb = NULL;
+		break;
+	}
+exit:
+	if (ret) {
+		if (mbt_dev)
+			mdev_bt->stat.err_rx++;
+		PRINTM(ERROR, "error when recv pkt!\n");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes the card
+ *
+ *  @param func    A pointer to sdio_func structure
+ *  @return        N/A
+ */
+static void
+sd_remove_card(struct sdio_func *func)
+{
+	struct sdio_mmc_card *card;
+
+	ENTER();
+
+	if (func) {
+		card = sdio_get_drvdata(func);
+		if (card) {
+			bt_remove_card(card->priv);
+			kfree(card);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the interrupt.
+ *
+ *  @param func  A pointer to sdio_func structure
+ *  @return      N/A
+ */
+static void
+sd_interrupt(struct sdio_func *func)
+{
+	bt_private *priv;
+	struct m_dev *m_dev = NULL;
+	struct sdio_mmc_card *card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 ireg = 0;
+	u8 host_intstatus_reg = HOST_INTSTATUS_REG;
+
+	ENTER();
+
+	card = sdio_get_drvdata(func);
+	if (!card || !card->priv) {
+		PRINTM(INFO,
+		       "BT: %s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
+		       __func__, func, card);
+		LEAVE();
+		return;
+	}
+	priv = card->priv;
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	ret = sdio_readsb(card->func, priv->adapter->hw_regs, 0, SD_BLOCK_SIZE);
+	if (ret) {
+		PRINTM(ERROR,
+		       "BT: sdio_read_ioreg: cmd53 read int status register failed %d\n",
+		       ret);
+		goto done;
+	}
+	ireg = priv->adapter->hw_regs[host_intstatus_reg];
+	if (ret) {
+		PRINTM(ERROR,
+		       "BT: sdio_read_ioreg: CMD52 read int status register failed %d\n",
+		       ret);
+		goto done;
+	}
+	if (ireg != 0) {
+		/*
+		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+		 * Clear the interrupt status register and re-enable
+		 * the interrupt
+		 */
+		PRINTM(INTR, "BT: INT %s: sdio_ireg = 0x%x\n", m_dev->name,
+		       ireg);
+		priv->adapter->irq_recv = ireg;
+	} else {
+		PRINTM(ERROR, "BT: ERR: ireg=0\n");
+	}
+	OS_INT_DISABLE;
+	priv->adapter->sd_ireg |= ireg;
+	OS_INT_RESTORE;
+	bt_interrupt(m_dev);
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interfaces are present
+ *
+ *  @param priv   A pointer to bt_private structure
+ *  @param val    Winner status (0: winner)
+ *  @return       BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sd_check_winner_status(bt_private *priv, u8 *val)
+{
+
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)priv->bt_dev.card;
+	u8 card_fw_status0_reg = CARD_FW_STATUS0_REG;
+
+	ENTER();
+	winner = sdio_readb(cardp->func, card_fw_status0_reg, &ret);
+	if (ret != BT_STATUS_SUCCESS) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** @brief This function tells lower driver that BT is suspended
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        None
+ */
+void
+bt_is_suspended(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	priv->adapter->is_suspended = TRUE;
+	sdio_func_suspended(card->func);
+}
+#endif
+
+/** @brief This function handles client driver suspend
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS or other error no.
+ */
+int
+bt_sdio_suspend(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is suspended\n",
+		       sdio_func_id(func));
+		return -ENOSYS;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO suspend\n", m_dev->name);
+	mbt_hci_suspend_dev(m_dev);
+	skb_queue_purge(&priv->adapter->tx_queue);
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+#ifdef BLE_WAKEUP
+		/** Set BLE Wake up pattern */
+		if (BT_STATUS_SUCCESS != bt_config_ble_wakeup(priv))
+			PRINTM(ERROR, "BT: Set ble wakeup pattern fail!\n");
+#endif
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+			PRINTM(CMD, "BT: HS not actived, suspend fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to suspend!\n");
+			}
+		}
+	}
+
+	priv->adapter->is_suspended = TRUE;
+
+	LEAVE();
+	/* We will keep the power when hs enabled successfully */
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state == HS_ACTIVATED)) {
+#ifdef MMC_PM_SKIP_RESUME_PROBE
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER and "
+		       "MMC_PM_SKIP_RESUME_PROBE\n");
+		return sdio_set_host_pm_flags(func,
+					      MMC_PM_KEEP_POWER |
+					      MMC_PM_SKIP_RESUME_PROBE);
+#else
+		PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER\n");
+		return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+#endif
+	} else {
+		PRINTM(CMD, "BT: suspend without MMC_PM_KEEP_POWER\n");
+		return BT_STATUS_SUCCESS;
+	}
+}
+
+void
+bt_sdio_shutdown(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+
+	ENTER();
+
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: shutdown: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(ERROR,
+		       "BT: %s: cannot remain alive while host is shutdown\n",
+		       sdio_func_id(func));
+		return;
+	}
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return;
+	}
+
+	priv = cardp->priv;
+
+	if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) {
+#ifdef BLE_WAKEUP
+		/** Set BLE Wake up pattern */
+		if (BT_STATUS_SUCCESS != bt_config_ble_wakeup(priv))
+			PRINTM(ERROR, "BT: Set ble wakeup pattern fail!\n");
+#endif
+
+		if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+			PRINTM(CMD, "BT: HS not actived, shutdown fail!\n");
+			if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) {
+				PRINTM(CMD,
+				       "BT: HS not actived the second time, force to shutdown!\n");
+			}
+		}
+	}
+	LEAVE();
+}
+
+/** @brief This function handles client driver resume
+ *
+ *  @param dev	   A pointer to device structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+bt_sdio_resume(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	bt_private *priv = NULL;
+	struct sdio_mmc_card *cardp;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(CMD, "BT: %s: resume: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->priv) {
+		PRINTM(ERROR, "BT: Card or priv structure is not valid\n");
+		LEAVE();
+		return BT_STATUS_SUCCESS;
+	}
+
+	priv = cardp->priv;
+	priv->adapter->is_suspended = FALSE;
+	m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+	PRINTM(CMD, "BT %s: SDIO resume\n", m_dev->name);
+#ifdef BLE_WAKEUP
+	if (priv->ble_wakeup_buf) {
+		PRINTM(CMD, "BT: Send system resume event\n");
+		bt_send_system_event(priv, FALSE);
+	}
+#endif
+	mbt_hci_resume_dev(m_dev);
+	sbi_wakeup_firmware(priv);
+	priv->adapter->hs_state = HS_DEACTIVATED;
+	PRINTM(CMD, "BT:%s: HS DEACTIVATED in Resume!\n", m_dev->name);
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+#endif
+#endif
+
+/********************************************************
+		Global Functions
+********************************************************/
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+static const struct dev_pm_ops bt_sdio_pm_ops = {
+	.suspend = bt_sdio_suspend,
+	.resume = bt_sdio_resume,
+};
+#endif
+#endif
+static struct sdio_driver sdio_bt = {
+	.name = "sdio_bt",
+	.id_table = bt_ids,
+	.probe = sd_probe_card,
+	.remove = sd_remove_card,
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+	.drv = {
+		.pm = &bt_sdio_pm_ops,
+		.shutdown = bt_sdio_shutdown,
+		}
+#endif
+#endif
+};
+
+/**
+ *  @brief This function registers the bt module in bus driver.
+ *
+ *  @return	   An int pointer that keeps returned value
+ */
+int *
+sbi_register(void)
+{
+	int *ret;
+
+	ENTER();
+
+	if (sdio_register_driver(&sdio_bt) != 0) {
+		PRINTM(FATAL, "BT: SD Driver Registration Failed\n");
+		LEAVE();
+		return NULL;
+	} else
+		ret = (int *)1;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function de-registers the bt module in bus driver.
+ *
+ *  @return        N/A
+ */
+void
+sbi_unregister(void)
+{
+	ENTER();
+	sdio_unregister_driver(&sdio_bt);
+	LEAVE();
+}
+
+/**
+ *  @brief This function registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_register_dev(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 reg;
+	u8 chiprev;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	struct sdio_func *func;
+	u8 host_intstatus_reg = HOST_INTSTATUS_REG;
+	u8 host_int_rsr_reg = HOST_INT_RSR_REG;
+	u8 card_misc_cfg_reg = CARD_MISC_CFG_REG;
+	u8 card_revision_reg = CARD_REVISION_REG;
+	u8 io_port_0_reg = IO_PORT_0_REG;
+	u8 io_port_1_reg = IO_PORT_1_REG;
+	u8 io_port_2_reg = IO_PORT_2_REG;
+	u8 card_magic_reg = CARD_MAGIC_REG;
+	u8 magic_val = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: Error: card or function is NULL!\n");
+		goto failed;
+	}
+	func = card->func;
+	priv->hotplug_device = &func->dev;
+
+	/* Initialize the private structure */
+	strncpy(priv->bt_dev.name, "bt_sdio0", sizeof(priv->bt_dev.name));
+	priv->bt_dev.ioport = 0;
+	priv->bt_dev.fn = func->num;
+
+	sdio_claim_host(func);
+	ret = sdio_claim_irq(func, sd_interrupt);
+	if (ret) {
+		PRINTM(FATAL, ": sdio_claim_irq failed: ret=%d\n", ret);
+		goto release_host;
+	}
+	ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
+	if (ret) {
+		PRINTM(FATAL, ": %s: cannot set SDIO block size\n", __func__);
+		goto release_irq;
+	}
+
+	/* read Revision Register to get the chip revision number */
+	chiprev = sdio_readb(func, card_revision_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_REVISION_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->chip_rev = chiprev;
+	PRINTM(INFO, "revision=%#x\n", chiprev);
+
+	magic_val = sdio_readb(func, card_magic_reg, &ret);
+	if (ret) {
+		PRINTM(FATAL, ": cannot read CARD_MAGIC_REG\n");
+		goto release_irq;
+	}
+	priv->adapter->magic_val = magic_val;
+	PRINTM(INFO, "magic_val=%#x\n", magic_val);
+
+	/*
+	 * Read the HOST_INTSTATUS_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.
+	 */
+	reg = sdio_readb(func, host_intstatus_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+
+	/* Read the IO port */
+	reg = sdio_readb(func, io_port_0_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= reg;
+
+	reg = sdio_readb(func, io_port_1_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 8);
+
+	reg = sdio_readb(func, io_port_2_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	else
+		priv->bt_dev.ioport |= (reg << 16);
+
+	PRINTM(INFO, ": SDIO FUNC%d IO port: 0x%x\n", priv->bt_dev.fn,
+	       priv->bt_dev.ioport);
+
+#define SDIO_INT_MASK       0x3F
+	/* Set Host interrupt reset to read to clear */
+	reg = sdio_readb(func, host_int_rsr_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	sdio_writeb(func, reg | SDIO_INT_MASK, host_int_rsr_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	/* Set auto re-enable */
+	reg = sdio_readb(func, card_misc_cfg_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+	sdio_writeb(func, reg | AUTO_RE_ENABLE_INT, card_misc_cfg_reg, &ret);
+	if (ret < 0)
+		goto release_irq;
+
+	sdio_set_drvdata(func, card);
+	sdio_release_host(func);
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+release_irq:
+	sdio_release_irq(func);
+release_host:
+	sdio_release_host(func);
+failed:
+
+	LEAVE();
+	return BT_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function de-registers the device.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_unregister_dev(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	if (card && card->func) {
+		sdio_claim_host(card->func);
+		sdio_release_irq(card->func);
+		sdio_disable_func(card->func);
+		sdio_release_host(card->func);
+		sdio_set_drvdata(card->func, NULL);
+	}
+
+	LEAVE();
+	return BT_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function enables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_enable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sd_enable_host_int_mask(priv, HIM_ENABLE);
+	sd_get_rx_unit(priv);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function disables the host interrupts.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sbi_disable_host_int(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	ret = sbi_disable_host_int_mask(priv, HIM_DISABLE);
+	sdio_release_host(card->func);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @param payload A pointer to the data/cmd buffer
+ *  @param nb      Length of data/cmd
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_host_to_card(bt_private *priv, u8 *payload, u16 nb)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+#ifdef DEBUG_LEVEL1
+	struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+#endif
+	int ret = BT_STATUS_SUCCESS;
+	int buf_block_len;
+	int blksz;
+	int i = 0;
+	u8 *buf = NULL;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	buf = payload;
+
+	blksz = SD_BLOCK_SIZE;
+	buf_block_len = (nb + blksz - 1) / blksz;
+	/* Allocate buffer and copy payload */
+	if ((t_ptr)payload & (DMA_ALIGNMENT - 1)) {
+		if (nb > MAX_TX_BUF_SIZE) {
+			PRINTM(ERROR, "BT: Invalid tx packet, size=%d\n", nb);
+			LEAVE();
+			return BT_STATUS_FAILURE;
+		}
+		/* Ensure 8-byte aligned CMD buffer */
+		buf = priv->adapter->tx_buf;
+		memcpy(buf, payload, nb);
+	}
+	sdio_claim_host(card->func);
+	do {
+		/* Transfer data to card */
+		ret = sdio_writesb(card->func, priv->bt_dev.ioport, buf,
+				   buf_block_len * blksz);
+		if (ret < 0) {
+			i++;
+			PRINTM(ERROR,
+			       "BT: host_to_card, write iomem (%d) failed: %d\n",
+			       i, ret);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			/* issue abort cmd52 command through F0 */
+			sdio_f0_writeb(card->func, 0x01, SDIO_CCCR_ABORT, &ret);
+#endif
+			sdio_writeb(card->func, HOST_TERM_CMD53,
+				    CONFIGURATION_REG, &ret);
+			udelay(20);
+			ret = BT_STATUS_FAILURE;
+			if (i >= MAX_CMD53_RETRY)
+				goto exit;
+		} else {
+			PRINTM(DATA, "BT: SDIO Blk Wr %s: len=%d\n",
+			       m_dev->name, nb);
+			DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Wr", payload, nb);
+		}
+	} while (ret == BT_STATUS_FAILURE);
+	priv->bt_dev.tx_dnld_rdy = FALSE;
+exit:
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ */
+int
+sbi_download_fw(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+	u8 winner = 0;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		ret = BT_STATUS_FAILURE;
+		goto exit;
+	}
+
+	sdio_claim_host(card->func);
+	if (BT_STATUS_SUCCESS == sd_verify_fw_download(priv, 1)) {
+		PRINTM(MSG, "BT: FW already downloaded!\n");
+		sdio_release_host(card->func);
+		sbi_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+	/* Check if other interface is downloading */
+	ret = sd_check_winner_status(priv, &winner);
+	if (ret == BT_STATUS_FAILURE) {
+		PRINTM(FATAL, "BT read winner status failed!\n");
+		goto done;
+	}
+	if (winner) {
+		PRINTM(MSG, "BT is not the winner (0x%x). Skip FW download\n",
+		       winner);
+		/* check if the fimware is downloaded successfully or not */
+		if (sd_verify_fw_download(priv, MAX_MULTI_INTERFACE_POLL_TRIES)) {
+			PRINTM(FATAL, "BT: FW failed to be active in time!\n");
+			ret = BT_STATUS_FAILURE;
+			goto done;
+		}
+		sdio_release_host(card->func);
+		sbi_enable_host_int(priv);
+		if (BT_STATUS_FAILURE == sbi_register_conf_dpc(priv)) {
+			PRINTM(ERROR,
+			       "BT: sbi_register_conf_dpc failed. Terminating download\n");
+			ret = BT_STATUS_FAILURE;
+			goto err_register;
+		}
+		goto exit;
+	}
+
+	do_gettimeofday(&priv->req_fw_time);
+	/* Download the main firmware via the helper firmware */
+	if (sd_download_firmware_w_helper(priv)) {
+		PRINTM(INFO, "BT: FW download failed!\n");
+		ret = BT_STATUS_FAILURE;
+	}
+	goto exit;
+done:
+	sdio_release_host(card->func);
+exit:
+	LEAVE();
+	return ret;
+err_register:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the interrupt status and handle it accordingly.
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS
+ */
+int
+sbi_get_int_status(bt_private *priv)
+{
+	int ret = BT_STATUS_SUCCESS;
+	u8 sdio_ireg = 0;
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+
+	ENTER();
+
+	OS_INT_DISABLE;
+	sdio_ireg = priv->adapter->sd_ireg;
+	priv->adapter->sd_ireg = 0;
+	OS_INT_RESTORE;
+	sdio_claim_host(card->func);
+	priv->adapter->irq_done = sdio_ireg;
+	if (sdio_ireg & DN_LD_HOST_INT_STATUS) {	/* tx_done INT */
+		if (priv->bt_dev.tx_dnld_rdy) {	/* tx_done already received */
+			PRINTM(INFO,
+			       "BT: warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
+			       priv->bt_dev.tx_dnld_rdy, sdio_ireg);
+		} else {
+			priv->bt_dev.tx_dnld_rdy = TRUE;
+		}
+	}
+	if (sdio_ireg & UP_LD_HOST_INT_STATUS)
+		sd_card_to_host(priv);
+
+	ret = BT_STATUS_SUCCESS;
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function wakeup firmware
+ *
+ *  @param priv    A pointer to bt_private structure
+ *  @return        BT_STATUS_SUCCESS/BT_STATUS_FAILURE or other error no.
+ */
+int
+sbi_wakeup_firmware(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!card || !card->func) {
+		PRINTM(ERROR, "BT: card or function is NULL!\n");
+		LEAVE();
+		return BT_STATUS_FAILURE;
+	}
+	sdio_claim_host(card->func);
+	sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
+	sdio_release_host(card->func);
+	PRINTM(CMD, "BT wake up firmware\n");
+
+	LEAVE();
+	return ret;
+}
+
+#define INIT_START_REG  0xF1
+#define INIT_END_REG 0xF6
+
+/** @brief This function dump the SDIO register
+ *
+ *  @param priv     A Pointer to the bt_private structure
+ *
+ *  @return         N/A
+ */
+void
+bt_dump_sdio_regs(bt_private *priv)
+{
+	struct sdio_mmc_card *card = priv->bt_dev.card;
+	int ret = BT_STATUS_SUCCESS;
+	char buf[256], *ptr;
+	u8 loop, func, data;
+	unsigned int reg, reg_start, reg_end;
+	u8 loop_num = 2;
+	unsigned int init_reg_start = 0;
+	unsigned int init_reg_end = 0;
+	init_reg_start = INIT_START_REG;
+	init_reg_end = INIT_END_REG;
+
+	if (priv->adapter->ps_state)
+		sbi_wakeup_firmware(priv);
+
+	sdio_claim_host(card->func);
+	for (loop = 0; loop < loop_num; 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 {
+			func = 2;
+			reg_start = 0;
+			reg_end = 0x09;
+		}
+		ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", func, reg_start,
+			       reg_end);
+		for (reg = reg_start; reg <= reg_end;) {
+			if (func == 0)
+				data = sdio_f0_readb(card->func, reg, &ret);
+			else
+				data = sdio_readb(card->func, reg, &ret);
+			if (!ret)
+				ptr += sprintf(ptr, "%02x ", data);
+			else {
+				ptr += sprintf(ptr, "ERR");
+				break;
+			}
+			reg++;
+		}
+		PRINTM(MSG, "%s\n", buf);
+	}
+
+	if (init_reg_start) {
+		memset(buf, 0, sizeof(buf));
+		ptr = buf;
+		ptr += sprintf(ptr, "Init Status Reg (%#x-%#x): ",
+			       init_reg_start, init_reg_end);
+		for (reg = init_reg_start; reg <= init_reg_end;) {
+			data = sdio_readb(card->func, reg, &ret);
+			if (!ret)
+				ptr += sprintf(ptr, "%02x ", data);
+			else {
+				ptr += sprintf(ptr, "ERR");
+				break;
+			}
+			reg++;
+		}
+		PRINTM(MSG, "%s\n", buf);
+	}
+	sdio_release_host(card->func);
+}
+
+module_param(fw_name, charp, 0);
+MODULE_PARM_DESC(fw_name, "Firmware name");
+module_param(bt_req_fw_nowait, int, 0);
+MODULE_PARM_DESC(bt_req_fw_nowait,
+		 "0: Use request_firmware API; 1: Use request_firmware_nowait API");
+module_param(multi_fn, int, 0);
+MODULE_PARM_DESC(multi_fn, "Bit 2: FN2;");
diff --git a/bt_sd8997/bt_char/hci_wrapper.h b/bt_sd8997/bt_char/hci_wrapper.h
new file mode 100644
index 0000000..3fe16b6
--- /dev/null
+++ b/bt_sd8997/bt_char/hci_wrapper.h
@@ -0,0 +1,171 @@
+/** @file hci_wrapper.h
+ *  @brief This file contains HCI related definitions
+ *
+ *  Copyright (C) 2011-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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 _HCI_WRAPPER_H_
+#define _HCI_WRAPPER_H_
+
+#include <linux/module.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+/**  Define Seq num */
+#define BT_SEQ      0
+#define DEBUG_SEQ   3
+
+/** Define dev type */
+#define BT_TYPE     1
+#define BT_AMP_TYPE 2
+#define DEBUG_TYPE  5
+
+/** Define spec type */
+#define BLUEZ_SPEC     1
+#define IANYWHERE_SPEC 2
+#define GENERIC_SPEC   3
+
+/** Define lock/unlock wrapper */
+#define mdev_req_lock(d)		down(&d->req_lock)
+#define mdev_req_unlock(d)		up(&d->req_lock)
+
+/** Length of device name */
+#define DEV_NAME_LEN				32
+
+/** Define struct m_dev */
+struct m_dev {
+	char name[DEV_NAME_LEN];
+	int index;
+	unsigned long flags;
+	spinlock_t lock;
+	struct semaphore req_lock;
+	struct sk_buff_head rx_q;
+	wait_queue_head_t req_wait_q;
+	struct hci_dev_stats stat;
+	struct module *owner;
+	void *dev_pointer;
+	int dev_type;
+	int spec_type;
+	void *driver_data;
+	int read_continue_flag;
+	int wait_rx_complete;
+	int rx_complete_flag;
+	wait_queue_head_t rx_wait_q;
+	spinlock_t rxlock;
+	atomic_t extra_cnt;
+
+	struct sk_buff *evt_skb;
+	struct sk_buff *acl_skb;
+	struct sk_buff *sco_skb;
+
+	int (*open) (struct m_dev * m_dev);
+	int (*close) (struct m_dev * m_dev);
+	int (*flush) (struct m_dev * m_dev);
+	int (*send) (struct m_dev * m_dev, struct sk_buff * skb);
+	void (*destruct) (struct m_dev * m_dev);
+	void (*notify) (struct m_dev * m_dev, unsigned int evt);
+	int (*ioctl) (struct m_dev * m_dev, unsigned int cmd, void *arg);
+	void (*query) (struct m_dev * m_dev, void *arg);
+
+};
+
+/** Define struct mbt_dev */
+struct mbt_dev {
+	/** maybe could add some private member later */
+	char name[DEV_NAME_LEN];
+	unsigned long flags;
+	__u8 type;
+
+	__u16 pkt_type;
+	__u16 esco_type;
+	__u16 link_policy;
+	__u16 link_mode;
+
+	__u32 idle_timeout;
+	__u16 sniff_min_interval;
+	__u16 sniff_max_interval;
+
+	struct sk_buff *reassembly[3];
+
+	atomic_t promisc;
+};
+
+struct debug_dev {
+	/** maybe could add some private member later */
+	char name[DEV_NAME_LEN];
+	unsigned long flags;
+};
+
+/** This function frees m_dev allocation */
+void free_m_dev(struct m_dev *m_dev);
+
+/**
+ *  @brief This function receives frames
+ *
+ *  @param skb	A pointer to struct sk_buff
+ *  @return	0--success otherwise error code
+ */
+static inline int
+mdev_recv_frame(struct sk_buff *skb)
+{
+	struct m_dev *m_dev = (struct m_dev *)skb->dev;
+	if (!m_dev || (!test_bit(HCI_UP, &m_dev->flags)
+		       && !test_bit(HCI_INIT, &m_dev->flags))) {
+		kfree_skb(skb);
+		return -ENXIO;
+	}
+
+	/* Incomming skb */
+	bt_cb(skb)->incoming = 1;
+
+	/* Time stamp */
+	__net_timestamp(skb);
+
+	/* Queue frame for rx task */
+	skb_queue_tail(&m_dev->rx_q, skb);
+
+	/* Wakeup rx thread */
+	wake_up_interruptible(&m_dev->req_wait_q);
+
+	return 0;
+}
+
+/**
+ *  @brief mbt dev suspend handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_suspend_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+/**
+ *  @brief mbt dev resume handler
+ *
+ *  @param m_dev   A pointer to struct m_dev
+ *  @return        0
+ */
+static inline int
+mbt_hci_resume_dev(struct m_dev *m_dev)
+{
+	return 0;
+}
+
+#endif /* _HCI_WRAPPER_H_ */
diff --git a/bt_sd8997/bt_char/mbt_char.c b/bt_sd8997/bt_char/mbt_char.c
new file mode 100644
index 0000000..b0c39ac
--- /dev/null
+++ b/bt_sd8997/bt_char/mbt_char.c
@@ -0,0 +1,807 @@
+/** @file mbt_char.c
+  *
+  * @brief This file contains the char device function calls
+  *
+  * Copyright (C) 2010-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include <linux/path.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+
+#include "bt_drv.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+#include <linux/sched/signal.h>
+#endif
+#include "mbt_char.h"
+
+static LIST_HEAD(char_dev_list);
+
+static DEFINE_SPINLOCK(char_dev_list_lock);
+
+static int mbtchar_major = MBTCHAR_MAJOR_NUM;
+
+/**
+ *	@brief  Gets char device structure
+ *
+ *	@param dev		A pointer to char_dev
+ *
+ *	@return			kobject structure
+ */
+struct kobject *
+chardev_get(struct char_dev *dev)
+{
+	struct kobject *kobj;
+
+	kobj = bt_priv_get(dev->m_dev->driver_data);
+	if (!kobj)
+		return NULL;
+	PRINTM(INFO, "dev get kobj\n");
+	kobj = kobject_get(&dev->kobj);
+	if (!kobj)
+		bt_priv_put(dev->m_dev->driver_data);
+	return kobj;
+}
+
+/**
+ *	@brief  Prints char device structure
+ *
+ *	@param dev		A pointer to char_dev
+ *
+ *	@return			N/A
+ */
+void
+chardev_put(struct char_dev *dev)
+{
+	if (dev) {
+		struct m_dev *m_dev = dev->m_dev;
+		PRINTM(INFO, "dev put kobj\n");
+		kobject_put(&dev->kobj);
+		if (m_dev)
+			bt_priv_put(m_dev->driver_data);
+	}
+}
+
+/**
+ *	@brief Changes permissions of the dev
+ *
+ *	@param name	pointer to character
+ *	@param mode		mode_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chmod(char *name, mode_t mode)
+{
+	struct path path;
+	struct inode *inode;
+	struct iattr newattrs;
+	int ret;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chmod(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief Changes ownership of the dev
+ *
+ *	@param name	pointer to character
+ *	@param user		uid_t type data
+ *	@param group	gid_t type data
+ *	@return			0--success otherwise failure
+ */
+int
+mbtchar_chown(char *name, uid_t user, gid_t group)
+{
+	struct path path;
+	struct inode *inode = NULL;
+	struct iattr newattrs;
+	int ret = 0;
+	int retrycount = 0;
+
+	ENTER();
+	do {
+		os_sched_timeout(30);
+		ret = kern_path(name, LOOKUP_FOLLOW, &path);
+		if (++retrycount >= 10) {
+			PRINTM(ERROR,
+			       "mbtchar_chown(): fail to get kern_path\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	} while (ret);
+	inode = path.dentry->d_inode;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_lock(&inode->i_mutex);
+#else
+	inode_lock(inode);
+#endif
+	ret = mnt_want_write(path.mnt);
+	if (ret)
+		goto out_unlock;
+	newattrs.ia_valid = ATTR_CTIME;
+	if (user != (uid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_UID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_uid = user;
+#else
+		newattrs.ia_uid = KUIDT_INIT(user);
+#endif
+	}
+	if (group != (gid_t) (-1)) {
+		newattrs.ia_valid |= ATTR_GID;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+		newattrs.ia_gid = group;
+#else
+		newattrs.ia_gid = KGIDT_INIT(group);
+#endif
+	}
+	if (!S_ISDIR(inode->i_mode))
+		newattrs.ia_valid |=
+			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+	if (inode->i_op->setattr)
+		ret = inode->i_op->setattr(path.dentry, &newattrs);
+	else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		ret = simple_setattr(path.dentry, &newattrs);
+#else
+		ret = inode_setattr(inode, &newattrs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+
+	path_put(&path);
+	LEAVE();
+	return ret;
+out_unlock:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&inode->i_mutex);
+#else
+	inode_unlock(inode);
+#endif
+	mnt_drop_write(path.mnt);
+	path_put(&path);
+	return ret;
+}
+
+/**
+ *	@brief write handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes written
+ */
+ssize_t
+chardev_write(struct file * filp, const char *buf, size_t count, loff_t * f_pos)
+{
+	int nwrite = 0;
+	struct sk_buff *skb;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	if (!test_bit(HCI_UP, &m_dev->flags)) {
+		LEAVE();
+		return -EBUSY;
+	}
+	nwrite = count;
+	skb = bt_skb_alloc(count, GFP_ATOMIC);
+	if (!skb) {
+		PRINTM(ERROR, "mbtchar_write(): fail to alloc skb\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	if (copy_from_user((void *)skb_put(skb, count), buf, count)) {
+		PRINTM(ERROR, "mbtchar_write(): cp_from_user failed\n");
+		kfree_skb(skb);
+		nwrite = -EFAULT;
+		goto exit;
+	}
+
+	skb->dev = (void *)m_dev;
+	bt_cb(skb)->pkt_type = *((unsigned char *)skb->data);
+	skb_pull(skb, 1);
+
+	PRINTM(DATA, "Write: pkt_type: 0x%x, len=%d @%lu\n",
+	       bt_cb(skb)->pkt_type, skb->len, jiffies);
+	DBG_HEXDUMP(DAT_D, "chardev_write", skb->data, skb->len);
+
+	/* Send skb to the hci wrapper layer */
+	if (m_dev->send(m_dev, skb)) {
+		PRINTM(ERROR, "Write: Fail\n");
+		nwrite = 0;
+		/* Send failed */
+		kfree_skb(skb);
+	}
+exit:
+	LEAVE();
+	return nwrite;
+}
+
+/**
+ *	@brief read handler for BT char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param buf		pointer to char buffer
+ *	@param count	size of receive buffer
+ *	@param f_pos	pointer to loff_t type data
+ *	@return			number of bytes read
+ */
+ssize_t
+chardev_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t ret = 0;
+	struct sk_buff *skb = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	/* Wait for rx data */
+	add_wait_queue(&m_dev->req_wait_q, &wait);
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		skb = skb_dequeue(&m_dev->rx_q);
+		if (skb)
+			break;
+		if (!test_bit(HCI_UP, &m_dev->flags)) {
+			ret = -EBUSY;
+			break;
+		}
+
+		if (filp->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			break;
+		}
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&m_dev->req_wait_q, &wait);
+
+	if (!skb)
+		goto out;
+
+	if (m_dev->read_continue_flag == 0) {
+		/* Put type byte before the data */
+		memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+		PRINTM(DATA, "Read: pkt_type: 0x%x, len=%d @%lu\n",
+		       bt_cb(skb)->pkt_type, skb->len, jiffies);
+	}
+	DBG_HEXDUMP(DAT_D, "chardev_read", skb->data, skb->len);
+	if (skb->len > count) {
+		/* user data length is smaller than the skb length */
+		if (copy_to_user(buf, skb->data, count)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		skb_pull(skb, count);
+		skb_queue_head(&m_dev->rx_q, skb);
+		m_dev->read_continue_flag = 1;
+		wake_up_interruptible(&m_dev->req_wait_q);
+		ret = count;
+		goto out;
+	} else {
+		if (copy_to_user(buf, skb->data, skb->len)) {
+			ret = -EFAULT;
+			goto outf;
+		}
+		m_dev->read_continue_flag = 0;
+		ret = skb->len;
+	}
+outf:
+	kfree_skb(skb);
+out:
+	if (m_dev->wait_rx_complete && skb_queue_empty(&m_dev->rx_q)) {
+		m_dev->rx_complete_flag = TRUE;
+		wake_up_interruptible(&m_dev->rx_wait_q);
+	}
+	LEAVE();
+	return ret;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+char_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, void *arg)
+#else
+/**
+ *	@brief ioctl common handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+char_ioctl(struct file *filp, unsigned int cmd, void *arg)
+#endif
+{
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+	PRINTM(INFO, "IOCTL: cmd=%d\n", cmd);
+	switch (cmd) {
+	case MBTCHAR_IOCTL_RELEASE:
+		m_dev->close(m_dev);
+		break;
+	case MBTCHAR_IOCTL_QUERY_TYPE:
+		m_dev->query(m_dev, arg);
+		break;
+	default:
+		m_dev->ioctl(m_dev, cmd, arg);
+		break;
+	}
+	LEAVE();
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl(struct inode *inode, struct file *filp,
+	      unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, (void *)arg);
+#else
+	return char_ioctl(filp, cmd, (void *)arg);
+#endif
+}
+
+#ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_ioctl_compat(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+#else
+/**
+ *	@brief compat ioctl handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param cmd		contains the IOCTL
+ *	@param arg		contains the arguement
+ *	@return			0--success otherwise failure
+ */
+long
+chardev_ioctl_compat(struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	return char_ioctl(inode, filp, cmd, compat_ptr(arg));
+#else
+	return char_ioctl(filp, cmd, compat_ptr(arg));
+#endif
+}
+#endif /* CONFIG_COMPAT */
+
+/**
+ *	@brief open handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_open(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = NULL;
+	struct m_dev *m_dev = NULL;
+	struct char_dev *cdev = NULL;
+	struct list_head *p = NULL;
+	ENTER();
+
+	list_for_each(p, &char_dev_list) {
+		cdev = list_entry(p, struct char_dev, list);
+		if (mbtchar_major == MAJOR(inode->i_cdev->dev) &&
+		    cdev->minor == MINOR(inode->i_cdev->dev)) {
+			dev = cdev;
+			break;
+		}
+	}
+	if (!dev) {
+		PRINTM(ERROR, "cannot find dev from inode\n");
+		LEAVE();
+		return -ENXIO;
+	}
+	if (!chardev_get(dev)) {
+		LEAVE();
+		return -ENXIO;
+	}
+	filp->private_data = dev;	/* for other methods */
+	m_dev = dev->m_dev;
+	mdev_req_lock(m_dev);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)
+	if (test_bit(HCI_UP, &m_dev->flags)) {
+		atomic_inc(&m_dev->extra_cnt);
+		goto done;
+	}
+#endif
+	if (m_dev->open(m_dev)) {
+		ret = -EIO;
+		goto done;
+	}
+	set_bit(HCI_UP, &m_dev->flags);
+
+done:
+	mdev_req_unlock(m_dev);
+	if (ret)
+		chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief release handler for char dev
+ *
+ *	@param inode	pointer to structure inode
+ *	@param filp	pointer to structure file
+ *	@return			0--success otherwise failure
+ */
+int
+chardev_release(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+	m_dev = dev->m_dev;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)
+	if (m_dev && (atomic_dec_if_positive(&m_dev->extra_cnt) >= 0)) {
+		LEAVE();
+		return ret;
+	}
+#endif
+	if (m_dev)
+		ret = dev->m_dev->close(dev->m_dev);
+	filp->private_data = NULL;
+	chardev_put(dev);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief poll handler for char dev
+ *
+ *	@param filp	pointer to structure file
+ *	@param wait		pointer to poll_table structure
+ *	@return			mask
+ */
+static unsigned int
+chardev_poll(struct file *filp, poll_table * wait)
+{
+	unsigned int mask;
+	struct char_dev *dev = (struct char_dev *)filp->private_data;
+	struct m_dev *m_dev = NULL;
+	ENTER();
+	if (!dev || !dev->m_dev) {
+		LEAVE();
+		return -ENXIO;
+	}
+
+	m_dev = dev->m_dev;
+	poll_wait(filp, &m_dev->req_wait_q, wait);
+	mask = POLLOUT | POLLWRNORM;
+	if (skb_peek(&m_dev->rx_q))
+		mask |= POLLIN | POLLRDNORM;
+	if (!test_bit(HCI_UP, &(m_dev->flags)))
+		mask |= POLLHUP;
+	PRINTM(INFO, "poll mask=0x%x\n", mask);
+	LEAVE();
+	return mask;
+}
+
+/* File ops for the Char driver */
+const struct file_operations chardev_fops = {
+	.owner = THIS_MODULE,
+	.read = chardev_read,
+	.write = chardev_write,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	.ioctl = chardev_ioctl,
+#else
+	.unlocked_ioctl = chardev_ioctl,
+#endif
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = chardev_ioctl_compat,
+#endif
+	.open = chardev_open,
+	.release = chardev_release,
+	.poll = chardev_poll,
+};
+
+/**
+ *	@brief This function creates the char dev
+ *
+ *	@param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param mod_name		A pointer to char
+ *  @param dev_name		A pointer to char
+ *	@return				0--success otherwise failure
+ */
+int
+register_char_dev(struct char_dev *dev, struct class *char_class,
+		  char *mod_name, char *dev_name)
+{
+	int ret = 0, dev_num;
+	unsigned long flags;
+	ENTER();
+	/* create the chrdev region */
+	if (mbtchar_major) {
+		dev_num = MKDEV(mbtchar_major, dev->minor);
+		ret = register_chrdev_region(dev_num, 1, mod_name);
+	} else {
+		PRINTM(INFO, "chardev: no major # yet\n");
+		ret = alloc_chrdev_region((dev_t *) & dev_num, dev->minor, 1,
+					  mod_name);
+	}
+
+	if (ret) {
+		PRINTM(ERROR, "chardev: create chrdev_region failed\n");
+		LEAVE();
+		return ret;
+	}
+	if (!mbtchar_major) {
+		/* Store the allocated dev major # */
+		mbtchar_major = MAJOR(dev_num);
+	}
+	dev->cdev = cdev_alloc();
+	dev->cdev->ops = &chardev_fops;
+	dev->cdev->owner = chardev_fops.owner;
+	dev_num = MKDEV(mbtchar_major, dev->minor);
+
+	if (cdev_add(dev->cdev, dev_num, 1)) {
+		PRINTM(ERROR, "chardev: cdev_add failed\n");
+		ret = -EFAULT;
+		goto free_cdev_region;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), NULL, dev_name);
+	}
+	if (dev->dev_type == DEBUG_TYPE) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), NULL, dev_name);
+	}
+#else
+	if ((dev->dev_type == BT_TYPE) || (dev->dev_type == BT_AMP_TYPE)) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), dev_name);
+	}
+	if (dev->dev_type == DEBUG_TYPE) {
+		device_create(char_class, NULL,
+			      MKDEV(mbtchar_major, dev->minor), dev_name);
+	}
+#endif
+	PRINTM(INFO, "register char dev=%s\n", dev_name);
+
+	/** modify later */
+
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_add_tail(&dev->list, &char_dev_list);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+
+	LEAVE();
+	return ret;
+free_cdev_region:
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *	@brief This function deletes the char dev
+ *
+ *  @param dev			A pointer to structure char_dev
+ *  @param char_class	A pointer to class struct
+ *  @param dev_name		A pointer to char
+ *  @return				0--success otherwise failure
+ */
+int
+unregister_char_dev(struct char_dev *dev, struct class *char_class,
+		    char *dev_name)
+{
+	ENTER();
+	device_destroy(char_class, MKDEV(mbtchar_major, dev->minor));
+	cdev_del(dev->cdev);
+	unregister_chrdev_region(MKDEV(mbtchar_major, dev->minor), 1);
+	PRINTM(INFO, "unregister char dev=%s\n", dev_name);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param char_class	A pointer to class struct
+ *  @return				N/A
+ */
+void
+chardev_cleanup(struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	do {
+		dev = NULL;
+		list_for_each(p, &char_dev_list) {
+			dev = list_entry(p, struct char_dev, list);
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			unregister_char_dev(dev, char_class, dev->m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	} while (dev);
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	class_destroy(char_class);
+	LEAVE();
+}
+
+/**
+ *	@brief This function cleans module
+ *
+ *  @param m_dev	A pointer to m_dev struct
+ *  @param char_class	A pointer to class struct
+ *  @return			N/A
+ */
+void
+chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class)
+{
+	unsigned long flags;
+	struct list_head *p = NULL;
+	struct char_dev *dev = NULL;
+	ENTER();
+	spin_lock_irqsave(&char_dev_list_lock, flags);
+	list_for_each(p, &char_dev_list) {
+		dev = list_entry(p, struct char_dev, list);
+		if (dev->minor == m_dev->index) {
+			list_del(p);
+			spin_unlock_irqrestore(&char_dev_list_lock, flags);
+			dev->m_dev = NULL;
+			unregister_char_dev(dev, char_class, m_dev->name);
+			kobject_put(&dev->kobj);
+			spin_lock_irqsave(&char_dev_list_lock, flags);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&char_dev_list_lock, flags);
+	LEAVE();
+}
diff --git a/bt_sd8997/bt_char/mbt_char.h b/bt_sd8997/bt_char/mbt_char.h
new file mode 100644
index 0000000..9997a38
--- /dev/null
+++ b/bt_sd8997/bt_char/mbt_char.h
@@ -0,0 +1,72 @@
+/** @file mbt_char.h
+  *
+  * @brief This file contains mbtchar driver specific defines etc
+  *
+  * Copyright (C) 2010-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+#ifndef __MBT_CHAR_H__
+#define __MBT_CHAR_H__
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+
+/** Define ioctl */
+#define MBTCHAR_IOCTL_RELEASE       _IO('M', 1)
+#define MBTCHAR_IOCTL_QUERY_TYPE    _IO('M', 2)
+#ifdef BLE_WAKEUP
+#define MBTCHAR_IOCTL_BLE_WAKEUP_PARAM _IO('M', 4)
+#endif
+
+#define MBTCHAR_MAJOR_NUM            (0)
+
+/** Interface specific macros */
+#define MBTCHAR_MINOR_BASE           (0)
+#define FMCHAR_MINOR_BASE            (10)
+#define NFCCHAR_MINOR_BASE           (20)
+#define DEBUGCHAR_MINOR_BASE         (30)
+
+/** Declaration of char_dev struct */
+struct char_dev {
+	struct list_head list;
+	int minor;
+	int dev_type;
+	struct cdev *cdev;
+	struct m_dev *m_dev;
+	struct kobject kobj;
+};
+
+/** Changes permissions of the dev */
+int mbtchar_chmod(char *name, mode_t mode);
+
+/** Changes ownership of the dev */
+int mbtchar_chown(char *name, uid_t user, gid_t group);
+
+/**	This function creates the char dev */
+int register_char_dev(struct char_dev *dev, struct class *char_class,
+		      char *mod_name, char *dev_name);
+
+/**	This function deletes the char dev */
+int unregister_char_dev(struct char_dev *dev, struct class *char_class,
+			char *dev_name);
+
+/**	This function cleans module */
+void chardev_cleanup(struct class *char_class);
+
+/**	This function cleans module */
+void chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class);
+
+#endif /*__MBT_CHAR_H__*/
diff --git a/wlan_sd8897/Makefile b/wlan_sd8897/Makefile
new file mode 100644
index 0000000..f64c670
--- /dev/null
+++ b/wlan_sd8897/Makefile
@@ -0,0 +1,596 @@
+# File: Makefile
+#
+# Copyright (C) 2008-2018, Marvell International Ltd.
+#
+# This software file (the "File") is distributed by Marvell International
+# Ltd. under the terms of the GNU General Public License Version 2, June 1991
+# (the "License").  You may use, redistribute and/or modify this File in
+# accordance with the terms and conditions of the License, a copy of which
+# is available by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# A copy of the GPL is available in file gpl-2.0.txt accompanying in this
+# deliverables.
+#
+# 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.
+
+COMPATDIR=/lib/modules/$(KERNELVERSION_X86)/build/compat-wireless-3.2-rc1-1/include
+CC=		$(CROSS_COMPILE)gcc -I$(COMPATDIR)
+LD=		$(CROSS_COMPILE)ld
+BACKUP=		/root/backup
+YMD=		`date +%Y%m%d%H%M`
+
+ifneq ($(COMPAT_VERSION_CODE),)
+DRV_DIR ?= $(shell pwd)
+export DRV_DIR
+COMPAT_VERSION=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$1}')
+COMPAT_PATCHLEVEL=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$2}')
+COMPAT_SUBLEVEL=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$3}')
+DECL_HEADER_FILE=$(DRV_DIR)/mlinux/moal_main.h
+$(shell sed -i 's/COMPAT_VERSION_CODE KERNEL_VERSION.*/COMPAT_VERSION_CODE KERNEL_VERSION(\
+		$(COMPAT_VERSION), $(COMPAT_PATCHLEVEL), $(COMPAT_SUBLEVEL))/g' $(DECL_HEADER_FILE))
+endif
+
+#############################################################################
+# Configuration Options
+#############################################################################
+
+# Debug Option
+# DEBUG LEVEL n/1/2:
+# n: NO DEBUG
+# 1: Only PRINTM(MMSG,...), PRINTM(MFATAL,...), ...
+# 2: All PRINTM()
+CONFIG_DEBUG=1
+
+# Proc debug file
+CONFIG_PROC_DEBUG=y
+
+# 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 WIFIDISPLAY support
+CONFIG_WIFI_DISPLAY_SUPPORT=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
+
+# Enable SDIO multi-port Tx aggregation
+CONFIG_SDIO_MULTI_PORT_TX_AGGR=y
+
+# Enable SDIO multi-port Rx aggregation
+CONFIG_SDIO_MULTI_PORT_RX_AGGR=y
+
+# SDIO suspend/resume
+CONFIG_SDIO_SUSPEND_RESUME=y
+
+# DFS testing support
+CONFIG_DFS_TESTING_SUPPORT=y
+
+# Multi-channel support
+CONFIG_MULTI_CHAN_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 += -I$(srctree)/drivers/soc/berlin/modules/wlan_sd8897/mlan
+ccflags-y += -DLINUX
+
+
+
+ARCH ?= arm
+KERNELDIR ?= /usr/src/arm/linux-4.1.43-bg4ct
+CROSS_COMPILE ?= /usr/local/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
+
+LD += -S
+
+BINDIR = ../bin_sd8897
+APPDIR= $(shell if test -d "mapp"; then echo mapp; fi)
+
+#############################################################################
+# Compiler Flags
+#############################################################################
+
+	ccflags-y += -I$(KERNELDIR)/include
+
+	ccflags-y += -DFPNUM='"68"'
+
+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_PROC_DEBUG),y)
+	ccflags-y += -DPROC_DEBUG
+	export CONFIG_PROC_DEBUG
+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_WIFI_DISPLAY_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_WIFI_DISPLAY_SUPPORT=n
+CONFIG_UAP_WEXT=n
+CONFIG_UAP_CFG80211=n
+endif
+
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	ccflags-y += -DWIFI_DIRECT_SUPPORT
+endif
+ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y)
+	ccflags-y += -DWIFI_DISPLAY_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
+
+ifeq ($(CONFIG_SDIO_MULTI_PORT_TX_AGGR),y)
+	ccflags-y += -DSDIO_MULTI_PORT_TX_AGGR
+endif
+
+ifeq ($(CONFIG_SDIO_MULTI_PORT_RX_AGGR),y)
+	ccflags-y += -DSDIO_MULTI_PORT_RX_AGGR
+endif
+
+ifeq ($(CONFIG_SDIO_SUSPEND_RESUME),y)
+	ccflags-y += -DSDIO_SUSPEND_RESUME
+endif
+
+ifeq ($(CONFIG_MULTI_CHAN_SUPPORT),y)
+	ccflags-y += -DMULTI_CHAN_SUPPORT
+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
+
+# 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
+
+#############################################################################
+# 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_UAP_CFG80211=y
+else
+ifeq ($(CPTCFG_CFG80211),m)
+	CONFIG_UAP_CFG80211=y
+else
+	CONFIG_UAP_CFG80211=n
+endif
+endif
+endif
+
+ifneq ($(CONFIG_STA_SUPPORT),y)
+	CONFIG_WIFI_DIRECT_SUPPORT=n
+	CONFIG_WIFI_DISPLAY_SUPPORT=n
+	CONFIG_STA_WEXT=n
+	CONFIG_STA_CFG80211=n
+endif
+
+ifneq ($(CONFIG_UAP_SUPPORT),y)
+	CONFIG_WIFI_DIRECT_SUPPORT=n
+	CONFIG_WIFI_DISPLAY_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
+
+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
+MLANOBJS += mlan/mlan_sdio.o
+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_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_cfgvendor.o
+MOALOBJS += mlinux/moal_sta_cfg80211.o
+endif
+ifeq ($(CONFIG_UAP_CFG80211),y)
+MOALOBJS += mlinux/moal_cfg80211.o
+MOALOBJS += mlinux/moal_cfgvendor.o
+MOALOBJS += mlinux/moal_uap_cfg80211.o
+endif
+
+ifdef CONFIG_PROC_FS
+MOALOBJS += mlinux/moal_proc.o
+ifeq ($(CONFIG_PROC_DEBUG),y)
+MOALOBJS += mlinux/moal_debug.o
+endif
+endif
+
+
+
+
+ifeq ($(CONFIG_MULTI_INTERFACE),y)
+obj-m := mlan_sdio.o
+mlan_sdio-objs := $(MLANOBJS)
+else
+obj-m := mlan.o
+mlan-objs := $(MLANOBJS)
+endif
+
+obj-m := 8897mlan.o
+8897mlan-objs := $(MLANOBJS)
+MOALOBJS += mlinux/moal_sdio_mmc.o
+obj-m += sd8897.o
+sd8897-objs := $(MOALOBJS)
+
+# Otherwise we were called directly from the command line; invoke the kernel build system.
+else
+
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) modules
+
+endif
+
+###############################################################
+
+export		CC LD ccflags-y KERNELDIR
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+.PHONY: mapp/mlanconfig mapp/mlan2040coex mapp/mlanevent mapp/uaputl mapp/mlanutl clean distclean
+else
+.PHONY: mapp/mlanconfig mapp/mlanevent mapp/mlan2040coex mapp/mlanutl clean distclean
+endif
+else
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+.PHONY: mapp/mlanevent mapp/uaputl clean distclean
+endif
+endif
+	@echo "Finished Making Marvell Wlan Linux Driver"
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+mapp/mlanconfig:
+	$(MAKE) -C $@
+mapp/mlanutl:
+	$(MAKE) -C $@
+mapp/mlan2040coex:
+	$(MAKE) -C $@
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+mapp/uaputl:
+	$(MAKE) -C $@
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+mapp/wifidirectutl:
+	$(MAKE) -C $@
+endif
+mapp/mlanevent:
+	$(MAKE) -C $@
+
+echo:
+
+build:		echo default
+
+	@if [ ! -d $(BINDIR) ]; then \
+		mkdir $(BINDIR); \
+	fi
+
+ifeq ($(CONFIG_MULTI_INTERFACE),y)
+	cp -f mlan_sdio.$(MODEXT) $(BINDIR)/mlan_sdio$(DBG).$(MODEXT)
+else
+	cp -f mlan.$(MODEXT) $(BINDIR)/mlan$(DBG).$(MODEXT)
+endif
+	cp -f sd8xxx.$(MODEXT) $(BINDIR)/sd8897$(DBG).$(MODEXT)
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	cp -f README $(BINDIR)
+	cp -f README_MLAN $(BINDIR)
+	cp -f README_RBC $(BINDIR)
+ifeq ($(CONFIG_OPENWRT_SUPPORT),y)
+	cp -f README_OPENWRT $(BINDIR)
+endif
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/mlanconfig $@ INSTALLDIR=$(BINDIR)
+	$(MAKE) -C mapp/mlanutl $@ INSTALLDIR=$(BINDIR)
+	$(MAKE) -C mapp/mlan2040coex $@ INSTALLDIR=$(BINDIR)
+endif
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	cp -f README_UAP $(BINDIR)
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/uaputl $@ INSTALLDIR=$(BINDIR)
+endif
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	cp -f README_WIFIDIRECT $(BINDIR)
+	cp -rpf script/wifidirect $(BINDIR)
+ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y)
+	cp -rpf script/wifidisplay $(BINDIR)
+endif
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/wifidirectutl $@ INSTALLDIR=$(BINDIR)
+endif
+endif
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/mlanevent $@ 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),)
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	$(MAKE) -C mapp/mlanconfig $@
+	$(MAKE) -C mapp/mlanutl $@
+	$(MAKE) -C mapp/mlan2040coex $@
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	$(MAKE) -C mapp/uaputl $@
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	$(MAKE) -C mapp/wifidirectutl $@
+endif
+	$(MAKE) -C mapp/mlanevent $@
+endif
+
+install: default
+
+	cp -f mlan.$(MODEXT) $(INSTALLDIR)/mlan$(DBG).$(MODEXT)
+	cp -f ../io/sdio/$(PLATFORM)/sdio.$(MODEXT) $(INSTALLDIR)
+	cp -f sd8xxx.$(MODEXT) $(INSTALLDIR)/sd8897$(DBG).$(MODEXT)
+	echo "sd8897 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),)
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	$(MAKE) -C mapp/mlanconfig $@
+	$(MAKE) -C mapp/mlanutl $@
+	$(MAKE) -C mapp/mlan2040coex $@
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	$(MAKE) -C mapp/uaputl $@
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	$(MAKE) -C mapp/wifidirectutl $@
+endif
+	$(MAKE) -C mapp/mlanevent $@
+endif
+
+# End of file
diff --git a/wlan_sd8897/README b/wlan_sd8897/README
new file mode 100644
index 0000000..73e44e0
--- /dev/null
+++ b/wlan_sd8897/README
@@ -0,0 +1,2365 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2008-2018, Marvell International Ltd.
+ All Rights Reserved
+
+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 up to 4.15.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy firmware image sd8786_uapsta.bin | sd8787_uapsta.bin | ... to
+	   /lib/firmware/mrvl/ directory, create the directory if it doesn't exist.
+	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
+		The default drv_mode is 7.
+			Bit 4 :  NAN
+
+		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 2)
+		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)
+		nan_name: Name of the NAN interface (default: "nan")
+		max_nan_bss: Number of NAN interfaces (default 1)
+	   For example, to install SD8787 driver,
+		insmod mlan.ko
+		insmod sd8787.ko [drv_mode=3] [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in STA only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=1 [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in uAP only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=2 [fw_name=mrvl/sd8787_uapsta.bin]
+
+	   To switch mode between STA only, uAP only and uAPSTA etc. in run time,
+		echo drv_mode=1 > /proc/mwlan/config		// STA mode
+		echo drv_mode=2 > /proc/mwlan/config		// uAP mode
+		echo drv_mode=3 > /proc/mwlan/config		// STA+uAP mode
+		echo drv_mode=7 > /proc/mwlan/config		// STA+uAP+WIFIDIRECT mode
+	c) Uninstall WLAN driver,
+		ifconfig mlanX down
+		ifconfig uapX down
+		rmmod sd8xxx
+		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>
+	  p2p_enh=0|1 <Disable enhanced P2P (default) | Enable enhanced P2P>
+	  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)>
+	  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>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf
+	  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
+	cfg80211_drcs=1|0 <Enable DRCS support (default) | Disable DRCS support>
+	  reg_alpha2=<Regulatory alpha2 (default NULL)>
+	  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>
+	  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
+      indrstcfg=<2-byte IR configuration>
+      gpio pin (high byte): GPIO pin no to be used as trigger for out band reset
+        (0xFF: default pin configuration)
+      ir_mode (low byte) : independent reset mode
+        (0: disable, 1: enable out band, 2: enable in band)
+      For example, to enable out band reset via gpio_pin 14
+       indrstcfg=0x0e01
+      To enable out band reset via default gpio_pin
+       indrstcfg=0xff01
+      To enable in band reset and disable out band reset
+       indrstcfg=0x02
+
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sd8xxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+
+	The following info are provided in /proc/net/mwlan/mlanX/info,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX/info.
+
+	driver_name = "wlan"
+	driver_version = <chip id, firmware version and driver version>
+	interface_name = "mlanX"
+	bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown"
+	media_state = "Disconnected" | "Connected"
+	mac_address = <6-byte adapter MAC address>
+	multicase_count = <multicast address count>
+	essid = <current SSID>
+	bssid = <current BSSID>
+	channel = <current channel>
+	region_code = <current region code>
+	multicast_address[n] = <multicast address>
+	num_tx_bytes = <number of bytes sent to device>
+	num_rx_bytes = <number of bytes received from device and sent to kernel>
+	num_tx_pkts = <number of packets sent to device>
+	num_rx_pkts = <number of packets received from device and sent to kernel>
+	num_tx_pkts_dropped = <number of Tx packets dropped by driver>
+	num_rx_pkts_dropped = <number of Rx packets dropped by driver>
+	num_tx_pkts_err = <number of Tx packets failed to send to device>
+	num_rx_pkts_err = <number of Rx packets failed to receive from device>
+	carrier "on" | "off"
+	tx queue "stopped" | "started"
+
+	The following debug info are provided in /proc/net/mwlan/mlanX/debug,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX/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>
+	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>
+	sleep_pd = <sleep period in milliseconds>
+	qos_cfg = <WMM QoS info>
+	tx_lock_flag = <0/1, Tx lock flag>
+	port_open = <0/1, port open flag>
+	scan_processing = <0/1, scan processing flag>
+	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>
+	num_evt_disassoc = <number of disassociated events received from device>
+	num_evt_link_lost = <number of link lost events received from device>
+	num_cmd_deauth = <number of deauthenticate commands sent to device>
+	num_cmd_assoc_ok = <number of associate commands with success return>
+	num_cmd_assoc_fail = <number of associate commands with failure return>
+	cmd_sent = <0/1, send command resources available/sending command to device>
+	data_sent = <0/1, send data resources available/sending data to device>
+	mp_rd_bitmap = <SDIO multi-port read bitmap>
+	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>
+	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>
+	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>
+	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/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/config      # read func 0 address 4
+		cat /proc/mwlan/config                          # display the register value
+		echo "sdcmd52rw= 1 3 0xf" > /proc/mwlan/config  # write 0xf to func 1 address 3
+
+	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 IWPRIV COMMAND
+
+NAME
+	This manual describes the usage of private commands used in Marvell MLAN
+	Linux Driver.
+
+	To use parameters as hex format, a '0x' must precede it for the parameters to
+	be parsed properly.
+
+SYNOPSIS
+	iwpriv <mlanX> <command> [sub-command] ...
+
+	iwpriv mlanX version
+	iwpriv mlanX verext
+	iwpriv mlanX getsignal [m] [n]
+	iwpriv mlanX antcfg [m] [n]
+	iwpriv mlanX regioncode [n]
+	iwpriv mlanX cfpcode [m] [n]
+	iwpriv mlanX wwscfg [m]
+	iwpriv mlanX esuppmode
+	iwpriv mlanX passphrase <ssid/psk/passphrase>
+	iwpriv mlanX httxcfg [<m>] [<n>]
+	iwpriv mlanX htcapinfo [<m>] [<n>]
+	iwpriv mlanX addbapara <m> <n> <o> <p> <q>
+	iwpriv mlanX aggrpriotbl <n>
+	iwpriv mlanX addbareject <n>
+	iwpriv mlanX txbufcfg
+	iwpriv mlanX amsduaggrctrl <n>
+	iwpriv mlanX httxbfcap [cap]
+	iwpriv mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData]"
+	iwpriv mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+	iwpriv mlanX deepsleep [n] [m]
+	iwpriv mlanX hscfg [condition [[GPIO# [gap]]]]
+	iwpriv mlanX hssetpara condition [GPIO# [gap]]
+	iwpriv mlanX deauth [n]
+	iwpriv mlanX radioctrl
+	iwpriv mlanX reassoctrl [n]
+	iwpriv mlanX adhocaes
+	iwpriv mlanX bandcfg [l] [m] [n] [o]
+	iwpriv mlanX getlog
+	iwpriv mlanX 11dcfg
+	iwpriv mlanX 11dclrtbl
+	iwpriv mlanX wmmcfg [n]
+	iwpriv mlanX hotspotcfg [n]
+	iwpriv mlanX txpowercfg [<RateIndex> [<MinPwr> [<MaxPwr> <step>]]]
+	iwpriv mlanX qoscfg
+	iwpriv mlanX getdatarate
+	iwpriv mlanX txratecfg [n]
+	iwpriv mlanX bcninterval [n]
+	iwpriv mlanX sysclock [clk1] [clk2] [clk3] [clk4]
+	iwpriv mlanX drvdbg [n]
+	iwpriv mlanX mgmtframectrl
+	iwpriv mlanX warmreset
+	iwpriv mlanX regrdwr <type> <offset> [value]
+	iwpriv mlanX rdeeprom <offset> <length>
+	iwpriv mlanX memrdwr <address> [value]
+	iwpriv mlanX inactivityto <n> <m> <l> [k]
+	iwpriv mlanX sdioclock <n>
+	iwpriv mlanX sdcmd52rw <FN no.> <address> [data]
+	iwpriv mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+	iwpriv mlanX sleeppd [n]
+	iwpriv mlanX pscfg [k] [d] [l] ...
+        iwpriv mlanX fwwakeupmethod [n] [g]
+	iwpriv mlanX getkey
+	iwpriv mlanX associate "<bssid> <ssid>"
+	iwpriv mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+	iwpriv mlanX netmon [<act> [<filter> <band> <chan> [offset]]]
+	iwpriv mlanX authtype [n]
+	iwpriv mlanX powercons [n]
+	iwpriv mlanX htstreamcfg [n]
+	iwpriv mlanX ipaddr ["<op>;<ipaddr>"]
+	iwpriv mlanX macctrl [n]
+	iwpriv mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+	iwpriv mlanX thermal
+    iwpriv mlanX indrstcfg <ir_mode> [gpio_pin]
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell 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.
+
+version
+	This is used to get the current version of the driver and the firmware.
+
+verext
+	Retrieve and display an extended version string from the firmware
+
+	Usage:
+		iwpriv mlanX verext [#]
+
+	where [#] is an optional argument to retrieve a specific version string,
+	omission of the argument retrieves the 0 indexed string.
+
+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:
+		iwpriv mlan0 getsignal 1        : Get the RSSI info (beacon last, beacon
+		                                  average, data last and data average)
+		iwpriv mlan0 getsignal 3 4      : Get the NF of data average
+		iwpriv mlan0 getsignal 2 1      : Get the SNR of beacon last
+		iwpriv 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
+
+antcfg
+	This command is used to set/get the mode of Tx/Rx path.
+
+	where value of m is:
+		Bit 0   -- Tx Path A
+		Bit 1   -- Tx Path B
+		Bit 0-1 -- Tx Path A+B
+
+	where value of n is:
+		Bit 0   -- Rx Path A
+		Bit 1   -- Rx Path B
+		Bit 0-1 -- Rx Path A+B
+	The Tx path setting (m) is used if Rx path (n) is not provided.
+
+	Examples:
+		iwpriv mlan0 antcfg             : Get Tx and Rx path
+		iwpriv mlan0 antcfg 3           : Set Tx and Rx path to A+B
+		iwpriv mlan0 antcfg 1 3         : Set Tx path to A and Rx path to A+B
+
+regioncode
+	This command is used to set/get the region code in the station.
+	Note: This command should be issued at beginning before band/channel selection
+	and association.
+
+	where value is 'region code' for various regions like
+	USA FCC, Canada IC, Europe ETSI, Japan ...
+	The special code (0xff) is used for Japan to support channel 1-14 in B/G/N mode.
+
+	Examples:
+		iwpriv mlan0 regioncode         : Get region code
+		iwpriv mlan0 regioncode 0x10    : Set region code to USA (0x10)
+
+	Note : in some case regioncode will be 0 after updated countycode or 80211d
+		i.e. mlanutl mlanX countrycode  (CA, JP, CN, DE, ES AT, BR, RU)
+		or uaputl.exe sys_cfg_80211d state 1 country (CA, JP, CN, DE, ES AT, BR, RU)
+		Please use cfp instead of it.
+
+cfpcode
+	This command is used to set/get the Channel-Frequency-Power table codes.
+	The region table can be selected through region code.
+	The current configuration is returned if no parameter provided.
+
+	where the parameters are,
+		[m]: code of the CFP table for 2.4GHz (0: unchanged)
+		[n]: code of the CFP table for 5GHz (0 or not provided: unchanged)
+
+	Examples:
+		iwpriv mlan0 cfpcode            : Get current configuration
+		iwpriv mlan0 cfpcode 0x30       : Set 2.4GHz CFP table code 0x30 (EU),
+		                                  keep 5GHz table unchanged
+		iwpriv mlan0 cfpcode 0x10 5     : Set 2.4GHz CFP table code 0x10 (USA)
+		                                  and 5GHz table code 5
+
+wwscfg
+	This command is used to set/get the WWS (World Wide Safe) mode.
+
+	where value of m is:
+		0       -- Disable WWS mode (default)
+		1       -- Enable WWS mode
+
+	Examples:
+		iwpriv mlan0 wwscfg             : Get WWS mode
+		iwpriv mlan0 wwscfg 1           : Enable WWS mode
+		iwpriv mlan0 wwscfg 0           : Disable WWS mode
+
+esuppmode
+	This command is used to get the current RSN mode and active pairwise/group
+    cipher for WPA/WPA2 mode.
+	Note: This command is available only when STA is connected.
+
+	These are bits settings used to indicate each RSN mode.
+		Bit 0    : No RSN
+		Bit 1-2  : RFU
+		Bit 3    : WPA
+		Bit 4    : WPA-NONE
+		Bit 5    : WPA2
+		Bit 6    : AES
+		Bit 7-15 : RFU
+
+	These are bits settings used to indicate each pairwise and group cipher.
+		Bit 0    : RFU
+		Bit 1    : RFU
+		Bit 2    : TKIP
+		Bit 3    : AES
+		Bit 2-7  : RFU
+
+	Example:
+		iwpriv mlan0 esuppmode          : Get RSN mode and pairwise/group cipher
+		8 4 4
+		(The current RSN mode is WPA, active pairwise cipher is TKIP and
+		 active group cipher is TKIP.)
+
+passphrase
+	This command is used to set/get passphrase for WPA-PSK/WPA2-PSK mode.
+
+	Where <n>
+		ASCII string for ssid/passphrase/psk.
+
+	1) "0;<ssid=valid ssid>" - This will get the passphrase, AKMP
+	   for specified ssid, if none specified then it will get all.
+
+	Example:
+		iwpriv mlan0 passphrase "0;ssid=marvell"
+
+	2) "1;<psk=64 byte hexpsk>;<passphrase=1-63 byte passphare>
+	   <ssid=valid ssid>" - Passphrase and psk cannot be provided for the same SSID.
+	   This command takes only one SSID at a time, If ssid= is present 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 ';' or '/' has to be used in an SSID then a '/' should be preceded
+	   to ';' or '/' as a escape.
+
+	Examples:
+		iwpriv mlan0 passphrase "1;ssid=mrvlAP;passphrase=abcdefgd"
+		iwpriv mlan0 passphrase "1;ssid=mrvl AP;psk=<64 bytes hexpsk>"
+
+		If user wants to input the ssid as "mrvl; AP" then command has to be
+		iwpriv mlan0 passphrase "1;ssid=mrvl/; AP;passphrase=abcdefgh"
+
+		If user wants to input the ssid as "//;" then command has to be
+		iwpriv mlan0 passphrase "1;ssid=/////;;passphrase=abcdefgh"
+
+	3) "2;<ssid=valid ssid>" - This will clear the passphrase
+	   for specified ssid, if none specified then it will clear all.
+
+	Examples:
+		iwpriv mlan0 passphrase "2;ssid=marvell"
+		iwpriv mlan0 passphrase "2"     : Clear all profiles and disable embedded supplicant
+
+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
+
+	Examples:
+		iwpriv mlanX httxcfg
+		This will display HT Tx configuration.
+		If the configurations for 2.4G and 5G are 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.
+
+		iwpriv mlanX httxcfg 0x62
+		This will enable 20/40 and Short GI but will disable Green field for 2.4G and 5G band.
+
+		iwpriv 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 24: Short GI in 40 Mhz enable/disable
+		Bit 23: Short GI in 20 Mhz 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
+
+	Examples:
+		iwpriv 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.
+
+		iwpriv mlanX htcapinfo 0x1820000
+		This will enable Short GI, Channel BW to 20/40 and disable Green field support for 2.4G and 5G band.
+
+		iwpriv 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).
+
+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:
+	iwpriv mlanX addbapara - This command will get the current addba params
+	iwpriv 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.
+
+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:
+	iwpriv 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
+	iwpriv 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.
+	iwpriv 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.
+
+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:
+	iwpriv 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.
+
+	iwpriv 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]
+
+	iwpriv 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.
+
+txbufcfg
+	This command can be used to get current buffer size.
+
+	eg:
+	iwpriv mlanX txbufcfg 	  - This will display the current buffer size.
+
+	Note:- The actual tx buf size will depends on AP's capability and max transmit buffer size.
+
+amsduaggrctrl
+	This command could be used to enable/disable a feature where firmware gives feedback to driver
+	regarding the optimal AMSDU buffer size to use with the current rate. Firmware will use the
+	current rate to decide the buffer size we could transmit. The max buffer size will still be
+	limited by buffer size provided in txbufcfg. (i.e. if the txbufcfg is 4K, then we could only transmit
+	4K/2K AMSDU packets, if the txbufcfg is 8K then we could transmit 8k/4k/2k based on current rate)
+
+	If enabled AMSDU buffer size at various rates will be as follows
+
+	1.	Legacy B/G rate.
+		No AMSDU aggregation.
+
+	2.	BW20 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 3, 2:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 1, 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 4, 3:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	3.	BW40 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4, 3, 2, 1:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5, 4, 3:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	where <n> is 0/1 (for disable/enable)
+
+	eg:
+	iwpriv mlanx amsduaggrctrl 1 - Enable this feature
+	iwpriv mlanx amsduaggrctrl 0 - Disable this feature
+	iwpriv mlanx amsduaggrctrl - This will get the enable/disable flag
+	and the current AMSDU buffer size). The AMSDU buffer size returned is only
+	valid after association as before association there is no rate info.
+
+	Note:- This command to enable/disable could be given anytime (before/after
+			association). This feature is enabled by default by the driver during
+			initialization.
+
+httxbfcap
+	This command is used to set/get the TX beamforming capabilities.
+
+	Usage:
+		iwpriv mlanX httxbfcap [cap]
+
+	where the parameters are,
+		cap: TX beamforming capabilities
+			 Bit 0    : Implicit TX BF receiving capable
+			 Bit 1    : RX staggered sounding capable
+			 Bit 2    : TX staggered sounding capable
+			 Bit 3    : RX NDP capable
+			 Bit 4    : TX NDP capable
+			 Bit 5    : Implicit TX BF capable
+			 Bit 6-7  : Calibration
+			         0: - not supported
+			         1: - STA can respond to a calibration request using
+			              the CSI Report, but cannot initiate calibration
+			         2: - reserved
+			         3: - STA can both initiate and respond to a calibration request
+			 Bit 8    : Explicit CSI TX BF capable
+			 Bit 9    : Explicit non-compressed steering capable
+			 Bit 10   : Explicit compressed steering capable
+			 Bit 11-12: Explicit TX BF CSI feedback
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 13-14: Explicit non-compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 15-16: Explicit compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 17-18: Minimal grouping
+			         0: - no grouping (STA supports groups of 1)
+			         1: - groups of 1, 2
+			         2: - groups of 1, 4
+			         3: - groups of 1, 2, 4
+			 Bit 19-20: CSI number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 21-22: Non-compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 23-24: Compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 25-26: CSI max number of rows beamformer supported
+			         0: - single row of CSI
+			         1: - 2 rows of CSI
+			         2: - 3 rows of CSI
+			         3: - 4 rows of CSI
+			 Bit 27-28: Channel estimation capability
+			         0: - 1 space time stream
+			         1: - 2 space time streams
+			         2: - 3 space time streams
+			         3: - 4 space time streams
+			 Bit 29-31: Reserved
+
+	Examples:
+		iwpriv mlan0 httxbfcap             : Get the current TX BF capabilities
+		iwpriv mlan0 httxbfcap 0x0000001F  : Set the TX BF capabilities of the
+		                                     Implicit TX BF receiving capable,
+		                                     RX staggered sounding capable,
+		                                     TX staggered sounding capable,
+		                                     RX NDP capable and TX NDP capable
+
+httxbfcfg
+	This command is used to configure the TX beamforming options.
+	Note: Any new subcommand should be inserted in the second
+		argument and each argument of the sub command should be
+		separated by semicolon. For global configuration, the
+		arguments should be separated by space.
+
+	Usage:
+		iwpriv mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData]"
+
+	where the parameters are,
+		action: TX beamforming action
+			0: Control global parameters for beamforming
+		        1: Performs NDP Sounding for PEER
+		        2: TX BF interval in milliseconds
+		        3: Enable/Disable beamforming/sounding for a particular peer
+		        4: TX BF SNR Threshold for peer
+		        .. <for new subcommand>
+		GlobalData: Global parameter arguments.
+		    It contains beamforming enable, sounding enable, FB type, snr_threshold
+		    sounding interval, Beamformig mode values seperated by space.
+		    Syntax:
+			iwpriv mlanX httxbfcfg <action>;<beamforming enable> <sounding enable> <FB type>
+			                       <snr_threshold>  <sounding interval> <Beamforming mode>
+		tsData: Trigger sounding for PEER specific arguments,
+		        it contains PEER MAC and status
+		interval: TX BF interval in milliseconds
+		txPeerData: Enable/Disable beamforming/sounding for the indicated peer,
+		          it contains PEER MAC, sounding, beamfoming options and FB type;
+		snrData: TX BF SNR Threshold for peer, it contains PEER MAC and SNR
+
+	Examples:
+		iwpriv mlan0 httxbfcfg "0"                          : Get current global configuration parameter
+		iwpriv mlan0 httxbfcfg "2;00:50:43:20:BF:64"        : Get the TX BF periodicity for a given peer
+		iwpriv mlan0 httxbfcfg "3"                          : Get the list of MAC addresses that have
+		                                                      beamforming and/or sounding enabled
+		iwpriv mlan0 httxbfcfg "4"                          : Get the list of PEER MAC, SNR tuples
+		                                                      programmed into the firmware.
+		iwpriv mlan0 httxbfcfg "0;0 0 3 10 500 5"           : Disable beamforming, sounding, set FB type
+		                                                      to 3, snr threshold to 10, sounding interval
+		                                                      to 500 ms and beamforming mode to 5
+		iwpriv mlan0 httxbfcfg "1;00:50:43:20:BF:64"        : Perform NDP Trigger sounding to peer
+		                                                      00:50:43:20:BF:64
+		iwpriv mlan0 httxbfcfg "2;00:50:43:20:BF:64;500"    : Set TX BF periodicity for peer 00:50:43:20:BF:64
+		                                                      to 500 milliseconds
+		iwpriv mlan0 httxbfcfg "3;00:50:43:20:BF:43;1;0;3"  : Enable beamforming, disable sounding and set
+		                                                      FB type to 3 for peer 00:50:43:20:BF:43
+		iwpriv mlan0 httxbfcfg "4;00:50:43:20:BF:24;43"     : Set TX BF SNR threshold to peer
+		                                                      00:50:43:20:BF:24 with SNR 43
+
+mgmtframectrl
+	This command is used to get/set mask for the management frames which needs to be forwarded to application layer.
+
+	Usage:
+		iwpriv mlanX mgmtframectrl [m]
+
+	where the parameter [m] is the bit mask of management frame reception.
+		Following are the bit definitions.
+		Bit 0 : Association Request
+		Bit 1 : Association Response
+		Bit 2 : Re-Association Request
+		Bit 3 : Re-Association Response
+		Bit 4 : Probe Request
+		Bit 5 : Probe Response
+		Bit 8 : Beacon Frames
+
+	Examples:
+		iwpriv mlan0 mgmtframectrl         : Get the current Mgmt Frame forwarding mask
+		iwpriv mlan0 mgmtframectrl 0x0020  : Bit 5 is set, Forward probe response
+											 frames to application layer
+
+mpactrl
+	This command is used to set/get the Tx, Rx SDIO aggregation parameters.
+	Note: The parameters can be set only in disconnected state.
+
+	Usage:
+		iwpriv mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+
+	where the parameter are:
+		[tx_ena]: Enable/disable (1/0) Tx MP-A
+		[rx_ena]: Enable/disable (1/0) Rx MP-A
+		[tx_size]: Size of Tx MP-A buffer
+		[rx_size]: Size of Rx MP-A buffer
+		[tx_ports]: Max ports (1-16) for Tx MP-A
+		[rx_ports]: Max ports (1-16) for Rx MP-A
+	default values are 1 1 16384 32768 16 16
+	The MP-A may be disabled by default at build time if the MMC driver byte mode patch
+	is not available in kernel.
+
+	Examples:
+		iwpriv mlan0 mpactrl       : Get MP aggregation parameters
+		iwpriv mlan0 mpactrl 0 0
+		                           : Disable MP aggregation for Tx, Rx respectively
+		iwpriv mlan0 mpactrl 1 1 8192 8192 8 8
+		                           : Enable MP aggregation for Tx, Rx
+		                           : Set Tx, Rx buffer size to 8192 bytes
+		                           : Set maximum Tx, Rx ports to 8
+
+deepsleep
+	This command is used to set/get auto deep sleep mode.
+
+	Usage:
+		iwpriv mlanX deepsleep [n] [m]
+
+	where the parameters are:
+		[n]: Enable/disable auto deep sleep mode (1/0)
+		[m]: Idle time in milliseconds after which firmware will put the device
+		     in deep sleep mode. Default value is 100 ms.
+
+	Examples:
+		iwpriv mlan0 deepsleep          : Display auto deep sleep mode
+		iwpriv mlan0 deepsleep 1        : Enable auto deep sleep mode, idle time unchanged
+		iwpriv mlan0 deepsleep 0        : Disable auto deep sleep mode
+		iwpriv mlan0 deepsleep 1 500    : Enable auto deep sleep mode with idle time 500 ms
+        Note:
+            Deepsleep must be disabled before changing idle time.
+
+hscfg
+	This command is used to configure the host sleep parameters.
+
+	Usage:
+		iwpriv mlanX hscfg [condition [[GPIO# [gap]]]]
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap) parameters for set. If no parameter provided,
+	get is performed.
+
+	where Condition is:
+		bit 0 = 1   -- broadcast data
+		bit 1 = 1   -- unicast data
+		bit 2 = 1   -- mac event
+		bit 3 = 1   -- multicast data
+		bit 6 = 1  --  Wakeup when mgmt frame received.
+		bit 7 = 1  --  Reserved
+		bit 8 = 1  --  Disable non maskable data wakeup.
+
+	The host sleep mode will be canceled if condition is set to -1. The default is 0x7.
+
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+	GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead).
+	The default is 0xff.
+
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff
+	for special setting (host acknowledge required) when GPIO is used to wakeup host.
+	The default is 200.
+
+	The host sleep set except for cancellation will be blocked if host sleep is
+	already activated.
+
+	Examples:
+		iwpriv mlan0 hscfg              : Get current host sleep mode
+		iwpriv mlan0 hscfg -1           : Cancel host sleep mode
+		iwpriv mlan0 hscfg 3            : Broadcast and unicast data
+		                                  Use GPIO and gap set previously
+		iwpriv mlan0 hscfg 2 3          : Unicast data
+		                                  Use GPIO 3 and gap set previously
+		iwpriv mlan0 hscfg 2 1 0xa0     : Unicast data
+		                                  Use GPIO 1 and gap 160 ms
+		iwpriv mlan0 hscfg 2 0xff       : Unicast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap set previously
+		iwpriv mlan0 hscfg 4 3 0xff     : MAC event
+		                                  Use GPIO 3
+		                                  Special host sleep mode
+		iwpriv mlan0 hscfg 1 0xff 0xff  : Broadcast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap 255ms
+
+hssetpara
+	This command is used to set host sleep parameters.
+
+	Usage:
+		iwpriv mlanX hssetpara Condition [GPIO# [gap]]
+
+	Note:
+	1) The usages of parameters are the same as "hscfg" command.
+	2) The parameters will be saved in the driver and be used when host suspends.
+
+deauth
+	This command is used to send a de-authentication to an arbitrary AP.
+	If [n] is omitted, the driver will deauth the associated AP.
+	If in ad-hoc mode this command is used to stop beacon transmission
+	from the station and go into idle state.
+
+	When <n> is supplied as a MAC address, the driver will deauth the
+	  specified AP.  If the AP address matches the driver's associated AP,
+	  the driver will disconnect. Otherwise, the driver remains connected.
+
+radioctrl
+	This command is used to turn on/off the radio.
+	Note: The radio can be disabled only in disconnected state.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 radioctrl 1        : Turn the radio on
+		iwpriv mlan0 radioctrl          : Get radio status
+
+reassoctrl
+	This command is used to turn on/off re-association in driver.
+
+	Usage:
+		iwpriv mlanX reassoctrl [n]
+
+	Where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 reassoctrl         : Get re-association status
+		iwpriv mlan0 reassoctrl 1       : Turn re-association on
+
+adhocaes
+	This command is used to set/get the AES key, when the station is in ad-hoc mode.
+	Note: This command is only available in disconnected state.
+
+	where value can be any 16 byte value.
+
+	Examples:
+		iwpriv mlan0 adhocaes           : Get ad-hoc aes key
+		iwpriv mlan0 adhocaes "1;12345678901234567890123456789012"
+		                                : Set ad-hoc aes key
+		iwpriv mlan0 adhocaes 2         : Clear ad-hoc aes key
+
+bandcfg
+	This command is used to set/get infra/ad-hoc band.
+	Note: This command is only available in disconnected state.
+
+	Usage:
+		iwpriv mlanX bandcfg [l] [m] [n] [o]
+
+	where the parameters:
+		[l]: Infrastructure band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+
+			 bit 5: AC 2.4G
+			 bit 6: AC 5G
+		[m]: Ad-hoc start band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+			 bit 5: AC 2.4G
+			 bit 6: AC 5G
+		[n]: Ad-hoc start channel
+		[o]: 0 - Bandwidth 20Mhz
+		     1 - HT Bandwidth 40Mhz above
+		     3 - HT Bandwidth 40Mhz below
+			 4 - VHT Bandwidth 80Mhz
+	Examples:
+		iwpriv mlan0 bandcfg            : Get infra/ad-hoc band and ad-hoc
+		                                  start channel configurations
+		iwpriv mlan0 bandcfg 1          : Set infra band to B only
+		iwpriv mlan0 bandcfg 3 2 6      : Set infra band to B/G, ad-hoc start band
+		                                  to G and ad-hoc start channel to 6
+		iwpriv mlan0 bandcfg 7 11 6 1   : Set infra band to B/G/A, ad-hoc start band
+		                                  to B/G/GN, ad-hoc start channel to 6 and
+		                                  secondary channel to above
+
+getlog
+	This command is used to get the statistics available in the station.
+
+11dcfg
+	This command is used to control 11D. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 11dcfg 1           : Enable 11D
+		iwpriv mlan0 11dcfg             : Get 11D status
+
+11dclrtbl
+	This command is used to clear the 11D channel table.
+
+	Usage:
+		iwpriv mlanX 11dclrtbl
+
+wmmcfg
+	This command is used to control WMM. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 wmmcfg 1           : Enable WMM
+		iwpriv mlan0 wmmcfg             : Get WMM status
+
+hotspotcfg
+	This command is used to get/set the HotSpot configuration.
+
+	WHere
+		<n> - Configuration bitset
+	This is a bitmap and should be used as following
+		Bit 31-10: Reserved set to 0
+		Bit 9: TDLS support indication enable/disable
+		Bit 8: Interworking indication enable/disable
+		Bit 7-1: Reserved set to 0
+		Bit 0: HotSpot feature enable/disable
+
+txpowercfg
+	This command is used to get/set the Tx power configuration.
+
+	Where
+		<RateIndex> - Data rate index
+			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
+			12	MCS0 (BW20)
+			13	MCS1 (BW20)
+			14	MCS2 (BW20)
+			15	MCS3 (BW20)
+			16	MCS4 (BW20)
+			17	MCS5 (BW20)
+			18	MCS6 (BW20)
+			19	MCS7 (BW20)
+			20	MCS8 (BW20)
+			21	MCS9 (BW20)
+			22	MCS10 (BW20)
+			23	MCS11 (BW20)
+			24	MCS12 (BW20)
+			25	MCS13 (BW20)
+			26	MCS14 (BW20)
+			27	MCS15 (BW20)
+			140	MCS0 (BW40)
+			141	MCS1 (BW40)
+			142	MCS2 (BW40)
+			143	MCS3 (BW40)
+			144	MCS4 (BW40)
+			145	MCS5 (BW40)
+			146	MCS6 (BW40)
+			147	MCS7 (BW40)
+  			148	MCS0 (BW40)
+			149	MCS1 (BW40)
+			150	MCS2 (BW40)
+			151	MCS3 (BW40)
+			152	MCS4 (BW40)
+			153	MCS5 (BW40)
+			154	MCS6 (BW40)
+			155	MCS7 (BW40)
+			0xff	Default
+		<MinPwr> - Minimum power level in dBm
+		<MaxPwr> - Maximum power level in dBm
+		<step>   - Power step
+
+	Note: Firmware may adjust the setting if over limit, final value can be
+	      verified using get command.
+
+	Examples:
+		iwpriv mlan0 txpowercfg 0xff        : Default power configuration
+		iwpriv mlan0 txpowercfg 11 12       : Set power level 12 dBm to data rate 54 Mbps
+		iwpriv mlan0 txpowercfg 7 11 16 1   : Set power level 11 dBm to 16 dBm with
+		                                      step 1 to data rate 18 Mbps
+		iwpriv mlan0 txpowercfg             : Get current configuration
+		mlan0     txpowercfg:2  3  13  18  2  1  1  13  18  2  0  0  13  18  2
+		10  11  13  15  2  8  9  13  16  2  6  7  13  17  2  4  5  13  17  2
+		17  19  13  15  2  15  16  13  16  2  13  14  13  17  2  12  12  13  17  2
+		145  147  13  14  1  143  144  13  14  1  141  142  13  14  1  140  140  13  14  1
+
+		 2 -> First rate index is 5.5 Mbps.
+		 3 -> Last rate index is 11 Mbps.
+		13 -> Min Tx power value is 13 dBm.
+		18 -> Max Tx power value is 18 dBm.
+		 2 -> Power adjustment step value is 2.
+
+		Similarly
+		17 -> First rate index is MCS5 (BW20).
+		19 -> Last rate index is MCS7 (BW20).
+		13 -> Min Tx power value is 13 dBm.
+		15 -> Max Tx power value is 15 dBm.
+		 2 -> Power adjustment step value is 2.
+
+		so on...
+
+qoscfg
+	This command sets WMM IE QOS info when an argument is given, and gets current WMM
+	IE QOS info when no argument is given.
+
+	Examples:
+		iwpriv mlan0 qoscfg 0x0f        : Set WMM IE QOS info to 0x0f
+		iwpriv mlan0 qoscfg             : Get WMM IE QOS info
+
+getdatarate
+	This command is used to get the data rate (index) being used in last Tx
+	packet and last Rx packet.
+
+bcninterval
+	This command is used to set/get the beacon interval in ad-hoc mode.
+	The valid beacon interval is between 20 - 1000, default beacon
+	interval is 100.
+
+	Where <n>
+		Beacon interval in TU (Time Unit: 1024 us).
+
+	Examples:
+		iwpriv mlan0 bcninterval 200    : Set ad-hoc beacon interval to 200
+		iwpriv mlan0 bcninterval        : Get ad-hoc beacon interval
+
+sysclock
+	This command is used to set/get system clocks in MHz.
+	The current system clock, configurable system clocks and all of the
+	supported system clocks will be returned if no parameter provided.
+
+	Examples:
+		iwpriv mlan0 sysclock           : Get system clocks
+		80 80 128 128 128 5 11 16 20 22 32 40 44 64 80 106 128 160 ...
+		(The current system clock is 80 MHz.
+		 The configurable system clocks of non-security, security, non-security
+		 A-MPDU and security A-MPDU are 80 MHz, 128 MHz, 128 MHz and 128 MHz.
+		 The supported system clocks are 5 MHz, 11 MHz, ..., 160 MHz, 182 MHz,
+		 213 MHz, 256 MHz, 320 Mhz, 366 MHz , ... . the Max system clocks is different
+		 for different chips, you could use this command to get the supported system clock)
+
+		iwpriv mlanX sysclock 80        : Set system clock in non-security mode
+		                                  to 80 MHz, no change for others
+		iwpriv mlanX sysclock 0 0 128   : Set system clock in non-security A-MPDU
+		                                  mode to 128 MHz, no changes for others
+
+drvdbg
+	This command is used to set/get the bit masks of driver debug message control.
+
+	Usage:
+		iwpriv 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:
+		iwpriv mlan0 drvdbg             : Get the current driver debug masks
+		iwpriv mlan0 drvdbg 0           : Disable all the debug messages
+		iwpriv mlan0 drvdbg 7           : Enable MMSG, MFATAL and MERROR messages
+		iwpriv mlan0 drvdbg 0x20037     : Enable MMSG, MFATAL, MEEROR,
+		                                  MCMND, MEVENT and MCMD_D messages
+		iwpriv mlan0 drvdbg -1          : Enable all the debug messages
+
+warmreset
+	This command is used for warm reset of the interface.
+
+	Usage:
+		iwpriv mlanX warmreset
+
+regrdwr
+	This command is used to read/write the adapter register.
+
+	Usage:
+		iwpriv mlanX regrdwr <type> <offset> [value]
+
+	where the parameters are,
+		<type>:     1:MAC/SOC, 2:BBP, 3:RF, 5:CAU
+		<offset>:   offset of register
+		[value]:    value to be written
+	Note: If highest bit of a 32-bit value needs to be set, use negative input.
+	The calculation is -(0xffffffff - value + 1). Range from -0x80000000 to -1.
+
+	Examples:
+		iwpriv mlan0 regrdwr 1 0xa060       : Read the MAC register
+		iwpriv mlan0 regrdwr 1 0xa060 0x12  : Write the MAC register
+		iwpriv mlan0 regrdwr 1 0xa794 -0x80000000
+		                                    : Write 0x80000000 to MAC register
+		iwpriv mlan0 regrdwr 1 0xa794 -0x00000001
+		                                    : Write 0xffffffff to MAC register
+
+rdeeprom
+	This command is used to read the EEPROM contents of the card.
+
+	Usage:
+		iwpriv mlanX rdeeprom <offset> <length>
+
+	where the parameters are,
+		<offset>:   multiples of 4
+		<length>:   4-20, multiples of 4
+
+	Example:
+		iwpriv mlan0 rdeeprom 0 20      : Read 20 bytes of EEPROM data from offset 0
+
+memrdwr
+	This command is used to read/write the adapter memory.
+
+	Usage:
+		iwpriv mlanX memrdwr <address> [value]
+
+	where the parameters are,
+		<address>:  memory address
+		[value]:    value to be written
+	Note: If highest bit of a 32-bit address/value needs to be set, use negitive input.
+	The calculation is -(0xffffffff - address/value + 1). Range from -0x80000000 to -1.
+
+	Examples:
+		iwpriv mlan0 memrdwr 0x4cf70    : Read memory address 0x4cf70
+		iwpriv mlan0 memrdwr -0x80000000
+		                                : Read memory address 0x80000000
+		iwpriv mlan0 memrdwr -0x7fff6000 -0x40000000
+		                                : Write 0xc0000000 to memory address 0x8000a000
+
+inactivityto
+	This command is used to set/get the inactivity timeout value, which specifies
+	when WLAN device is put to sleep.
+
+	Usage:
+		iwpriv mlanX inactivityto <n> <m> <l> [k]
+
+	where the parameter are:
+		<n>: timeout unit in microseconds.
+		<m>: Inactivity timeout for unicast data.
+		<l>: Inactivity timeout for multicast data.
+		[k]: Inactivity timeout for new Rx traffic after PS notification to AP.
+
+	Examples:
+		iwpriv mlan0 inactivityto           : Get the timeout value
+		iwpriv mlan0 inactivityto 1000 2 3  : Set timeout unit to 1000 us (1 ms),
+		                                      inactivity timeout for unicast data is 2 ms,
+		                                      inactivity timeout for multicast data is 3 ms
+
+sdioclock
+	Turn On(1) or Off(0) the SDIO clock.
+
+	Usage:
+		iwpriv mlanX sdioclock 1 (on)
+		iwpriv mlanX sdioclock 0 (off)
+		iwpriv mlanX sdioclock (get the current clock state)
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		iwpriv mlanX sdcmd52rw <function number> <register address> [value]
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+	Examples:
+		iwpriv mlan0 sdcmd52rw 1 3
+		iwpriv mlan0 sdcmd52rw 1 1 0x3f
+
+scancfg
+	This command is used to set/get scan configuration parameters.
+
+	Usage:
+		iwpriv mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+
+	where the parameters:
+		[t]: Scan Type (0: Unchanged, 1: Active, 2: Passive, default Active)
+		[m]: Scan Mode (0: Unchanged, 1: BSS, 2: IBSS, 3: Any, default Any)
+		[p]: Scan Probes (0: Unchanged, 1-4: Number of probes per channel, default 4)
+		[s]: Specific Scan Time (0: Unchanged, n: Value in ms, default 110 ms, max 500 ms)
+		[a]: Active Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 500 ms)
+		[b]: Passive Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 2000 ms)
+		[ext]: Extended scan (0: Legacy scan, 1: Extended scan)
+
+	No change if the parameter is 0 or the parameter is not provided.
+
+	Examples:
+		iwpriv mlan0 scancfg            : Get all the current scan configuration settings
+		iwpriv mlan0 scancfg 1 3        : Set scan type to active and scan mode to any,
+		                                  all the other scan configurations are unchanged
+		iwpriv mlan0 scancfg 0 1 2 200  : Set scan mode to BSS, number of probes to 2 and
+		                                  specific scan time to 200 ms, all the other scan
+		                                  configurations are unchanged
+
+sleeppd
+	This command is used to configure the sleep period of the WLAN device.
+
+	Usage:
+		iwpriv mlanX sleeppd [<period>]
+
+	Where the parameter is:
+		period: sleep period in milliseconds. Range 10~60. 0 for disable.
+
+	Examples:
+		iwpriv mlan0 sleeppd            : Get sleep period configuration
+		iwpriv mlan0 sleeppd 10         : Set sleep period to 10 ms
+
+pscfg
+	This command is used to set/get PS configuration parameters.
+
+	Usage:
+		iwpriv mlanX pscfg [k] [d] [l] ...
+
+	Where the parameters:
+		[k]: Keep alive null packet interval (0: Unchanged, -1: Disable, n: Interval in seconds)
+		[d]: DTIM interval (    0: Unchanged,
+		                      1-5: Value,
+		                    65534: DTIM will be ignored, listen interval will be used,
+		                    65533: Closest DTIM to the listen interval period will be used )
+		[l]: Local listen interval (     0: Unchanged,
+		                                -1: Disable,
+		                              1-49: Value in beacon intervals,
+		                             >= 50: Value in TUs )
+		[a]: Ad-hoc awake period (0: Unchanged, 1-31: Beacon interval, 255: Firmware
+		                          will go to sleep after beacon send out)
+		[b]: Beacon miss timeout (0: Unchanged, 1-50: Value in milliseconds, 65535: Disable)
+		[p]: Delay to PS (0-65535: Value in milliseconds, default 1000ms)
+		[m]: PS mode (0: Unchanged, 1: Auto mode, 2: PS-Poll mode, 3: PS Null mode)
+	No change if parameters are not provided.
+
+	Examples:
+		iwpriv mlan0 pscfg              : Get all the current PS configuration settings
+		iwpriv mlan0 pscfg 3 4          : Set PS keep alive null packet interval to 3 seconds
+		                                  and DTIM interval to 4, all the other configurations
+		                                  are unchanged
+		iwpriv mlan0 pscfg 0 0xfffe 10 0 20
+		                                : Disable DTIM interval, set local listen interval to
+		                                  10 beacon intervals and beacon miss interval to 20,
+		                                  all the other configurations are unchanged
+		iwpriv mlan0 pscfg 0 0 0 0 0 50 : Set delay to PS to 50 ms, keep the others unchanged
+
+fwwakeupmethod
+	This command is used to set/get the firmware wakeup method.
+
+	where value is:
+	        [n]:
+		1	-- Firmware wakeup through the interface command interrupt
+			    -- (default setting for SDIO/PCIe/USB)
+		2	-- Firmware wakeup through the GPIO pin
+		[g]:If firware wakeup throug GPIO pin, [g] is GPIO pin number
+
+	Examples:
+		iwpriv mlan0 fwwakeupmethod     : Get current firmware wakeup method
+		iwpriv mlan0 fwwakeupmethod 1    : Set firmware wakeup method to Interface mode
+		iwpriv mlan0 fwwakeupmethod 2 5  : Set firmware wakeup method to GPIO mode, GPIO_pin=5
+
+getkey
+	This command is used to get PTK/GTK
+
+	iwpriv mlanX getkey
+associate
+	Request an association to a given SSID/BSSID pair. This the only accurate
+	way to pick a specific AP and ESS for an association. The entry must
+	already exist in the scan table for the association to be attempted.
+
+	iwpriv mlanX associate "xx:xx:xx:xx:xx:xx SSID"
+
+sleepparams
+	This command is used to set the sleepclock configurations
+
+	Usage:
+		iwpriv mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+
+	where:
+		p1 is Sleep clock error in ppm (0-65535)
+		p2 is Wakeup offset in usec (0-65535)
+		p3 is Clock stabilization time in usec (0-65535)
+		p4 is Control periodic calibration (0-2)
+		p5 is Control the use of external sleep clock (0-2)
+		p6 is reserved for debug (0-65535)
+
+	Examples:
+		iwpriv mlan0 sleepparams                      : Get current sleepclock configuration
+		iwpriv mlan0 sleepparams 10 1000 2000 1 0 128 : Set sleepclock configuration
+
+netmon
+	This command is used to set/get sniffer mode configuration.
+	Note: The channel and band config is optional. If not specified, or if
+	any STA/uAP/STA+uAP connection is active, sniffer activity will be started
+	on the current config set in the FW.
+	'rtap' monitor interface will be created on enabling sniffer activity and
+	should be made 'up' for capturing in a sniffer app.
+
+	Usage:
+		iwpriv <interface> netmon [<act> [<filter>]]
+		iwpriv <interface> netmon [<act> [<filter>] [<band> <chan> [offset]]]
+
+	Where the parameters are:
+		<interface> : mlanX, uapX
+		<act>    : (1/0) enable/disable sniffer activity
+		<filter> : network monitor filer flag
+		    bit 0: (1/0) enable/disable management frame
+		    bit 1: (1/0) enable/disable control frame
+		    bit 2: (1/0) enable/disable data frame
+			bit 3: (1/0) enable/disable frames destined to active connection only
+			bit 4: (1/0) enable/disable decrypted unicast data/mgmt frames
+		<band>   : 802.11 band
+		    bit 0: B
+		    bit 1: G
+		    bit 2: A
+		    bit 3: GN
+		    bit 4: AN
+			 bit 5: AC 2.4G
+			 bit 6: AC 5G
+		<chan>   : channel to monitor
+		[offset] : secondary channel bandwidth
+			0 - Bandwidth 20Mhz
+			1 - HT Bandwidth 40Mhz sec channel above
+			3 - HT Bandwidth 40Mhz sec channel below
+			4 - VHT Bandwidth 80Mhz
+
+	Examples:
+		iwpriv mlan0 netmon             : Get the current sniffer mode configuration
+		iwpriv mlan0 netmon 0           : Disable network monitor activity
+		iwpriv uap0 netmon 1 7          : Enable sniffer activity on current channel set in FW,
+											set filter data, control, management frame.
+		iwpriv mlan0 netmon 1 4 11 6    : Enable sniffer activity in absence of active connection,
+											set filter data frame, band B/G/GN and channel 6
+		iwpriv mlan0 netmon 1 7 20 64 1 : Enable sniffer activity in absence of active connection,
+											set filter management, control and data frame, band A/AN,
+											channel 64 and secondary channel above
+		iwpriv uap0 netmon 1 0x0c        : Enable sniffer activity, set filter data frames
+											destined to the active uAP connection only
+
+		iwpriv mlan0 netmon 1 0x1d       : Enable sniffer activity, set filter decrypted data and
+											management frames destined to the active STA connection
+											only
+
+authtype
+	This command is used to set/get authentication type.
+
+	Usage:
+		iwpriv mlanX authtype [n]
+
+	where <n>
+		0: 802.11 open system authentication
+		1: 802.11 shared key authentication
+		255: allow open system or shared key authentication (default)
+
+	Examples:
+		iwpriv mlan0 authtype 0         : use open system authentication
+		iwpriv mlan0 authtype 1         : use shared key authentication
+		iwpriv mlan0 authtype 255       : allow open system or shared key authentication
+		iwpriv mlan0 authtype           : get current setting
+
+powercons
+	This command is used to set the local transmit power constraint.
+	Value is in dbm unit. This command is only used for ad-hoc start.
+
+	Usage:
+		iwpriv mlanX powercons [n]
+
+	Examples:
+		iwpriv mlanX powercons          : get the current setting
+		iwpriv mlanX powercons 12       : set local power constraint to 12 dbm
+
+htstreamcfg
+	This command is used to set/get HT stream configuration.
+	The setting only takes effect in next association.
+
+	Usage:
+		iwpriv mlanX htstreamcfg [n]
+
+	where <n>
+		0x11: HT stream 1x1 mode
+		0x22: HT stream 2x2 mode
+
+	Examples:
+		iwpriv mlan0 htstreamcfg        : Get current setting
+		iwpriv mlan0 htstreamcfg 0x11   : Set HT stream 1x1 mode
+		iwpriv mlan0 htstreamcfg 0x22   : Set HT stream 2x2 mode
+
+ipaddr
+	This command is used to set/get IP address.
+
+	Usage:
+		iwpriv mlanX ipaddr ["<op>;<ipaddr>"]
+
+	where <op>
+		0: Remove the IP address
+		bit 0: Set IP address for broadcast ARP filter, which will be auto enabled
+		       in next host sleep configuration
+		bit 1: Set IP address for auto broadcast ARP response
+
+	Examples:
+		iwpriv mlan0 ipaddr                 : Get current settings
+		iwpriv mlan0 ipaddr "0"             : Remove IP address
+		iwpriv mlan0 ipaddr "1;192.168.0.5" : Set IP address for ARP filter
+		iwpriv mlan0 ipaddr "3;192.168.0.6" : Set IP address for ARP filter
+		                                    : and auto ARP response
+
+macctrl
+	This command is used to set/get MAC control.
+	It's recommended to read the current setting first to avoid override issue.
+
+	Usage:
+		iwpriv mlanX macctrl [n]
+
+	where <n>
+		bit 0:  Rx enabled
+		bit 1:  Tx enabled
+		bit 3:  WEP enabled
+		bit 4:  EthernetII enabled
+		bit 7:  Promiscuous enabled
+		bit 8:  All multicast enabled
+		bit 9:  RTS/CTS enabled (0: CTS to self)
+		bit 11: Force 11n protection disabled
+		bit 12: Ad-hoc g protection disabled
+		...
+
+	Examples:
+		iwpriv mlan0 macctrl            : Get current MAC control
+		iwpriv mlan0 macctrl 0x13       : Set Tx/Rx on and EthernetII on
+		iwpriv mlan0 macctrl 0x813      : Set Tx/Rx on and EthernetII on
+		                                : Disable force 11n protection
+
+dfstesting
+	This command is used to set/get settings for DFS testing.
+
+	Usage:
+	    iwpriv mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+
+	where <user_cac_pd> is user-configured Channel Availability Check in msec
+                        0 = disable, use default period (60000)
+                        1-65535 = enable with that period
+	where <user_nop_pd> is user-configured Non-Occupancy Period in sec
+                        0 = disable, use default period (1800)
+                        1-65535 = enable with that period
+	where <no_chan_change> is enable/disable no channel change on radar
+                           0 = disable, 1 = enable (overrides below)
+	where <fixed_chan_num> is user-configured channel to change to on radar
+                           0 = disable, 1-255 = enable with that channel
+                           (channel validity for region, etc. is not checked)
+                           (only takes effect if no_chan_change = 0)
+
+	Examples:
+		iwpriv mlan0 dfstesting             : Get current dfstesting settings
+		iwpriv mlan0 dfstesting 2000 0 0 0  : user_cac=2sec, others disabled/default
+		iwpriv mlan0 dfstesting 0 0 1 0     : only no_chan_change enabled
+		iwpriv mlan0 dfstesting 0 120 0 64  : user_nop=2min, force chan 64 on radar
+
+thermal
+	This command is used to get the current thermal reading.
+
+	Examples:
+		iwpriv mlan0 thermal            : Get thermal reading
+
+indrstcfg
+    This command is used to set/get settings for independent reset mode
+
+    Usage:
+        iwpriv mlanX indrstcfg <ir_mode> [gpio_pin]
+
+    where <ir_mode>  is independent reset mode
+                     0 = disable independent reset
+                     1 = enable out band and disable in band
+                     2 = enable in band and disable out band
+    where <gpio_pin> is user-configured gpio pin number to be used for oob mode
+                     0xFF = use FW default gpio assignment
+                     0-15 = gpio pin number
+
+    Examples:
+        iwpriv mlan0 indrstcfg              : Get current settings
+        iwpriv mlan0 indrstcfg 1 14         : Enable oob_mode with gpio pin 14
+        iwpriv mlan0 indrstcfg 1 0xff       : Enable oob_mode with default gpio pin
+        iwpriv mlan0 indrstcfg 0            : Disable ir_mode
+        iwpriv mlan0 indrstcfg 2            : Enable in band reset mode
+
+
+===============================================================================
+		U S E R  M A N U A L  F O R  M L A N C O N F I G
+
+NAME
+mlanconfig - configure the additional parameters available for the Marvell mdriver.
+
+SYNOPSIS
+mlanconfig -v
+mlanconfig <mlanX> <command> [parameters] ...
+
+mlanconfig mlanX hostcmd <bg_scan.conf> bgscfg
+mlanconfig mlanX hostcmd <requesttpc.conf> requesttpc
+mlanconfig mlanX hostcmd <crypto_test.conf> crypto_test
+mlanconfig mlanX hostcmd <subevent.conf> subevent_get
+mlanconfig mlanX hostcmd <subevent.conf> subevent_set
+mlanconfig mlanX hostcmd <auto_tx.conf> auto_tx_get
+mlanconfig mlanX hostcmd <auto_tx.conf> nat_keep_alive
+mlanconfig mlanX hostcmd <auto_tx.conf> auto_tx_unreg
+mlanconfig mlanX hostcmd <txrate_cfg.conf> txrate_cfg_get
+mlanconfig mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bg
+mlanconfig mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bgn
+mlanconfig mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_cfg_get
+mlanconfig mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_2g_cfg_set
+mlanconfig mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_5g_cfg_set
+mlanconfig mlanX hostcmd <pad_cfg.conf> pad_cfg_get
+mlanconfig mlanX hostcmd <pad_cfg.conf> pad_cfg_set
+mlanconfig mlanX hostcmd <11n_2040coex.conf> 2040coex
+mlanconfig mlanX hostcmd <robust_btc.conf> mode_get
+mlanconfig mlanX hostcmd <robust_btc.conf> mode_timeshare
+mlanconfig mlanX hostcmd <robust_btc.conf> mode_spatial
+mlanconfig mlanX hostcmd <robust_btc.conf> generictime
+mlanconfig mlanX hostcmd <robust_btc.conf> a2dptime
+mlanconfig mlanX hostcmd <robust_btc.conf> inquirytim
+mlanconfig mlanX hostcmd <robust_btc.conf> ap_generictime
+mlanconfig mlanX hostcmd <robust_btc.conf> ap_a2dptime
+mlanconfig mlanX hostcmd <robust_btc.conf> ap_inquirytime
+mlanconfig mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_get
+mlanconfig mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_set
+mlanconfig mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_disable
+mlanconfig mlanX arpfilter <arpfilter.conf>
+mlanconfig mlanX mefcfg <mef.conf>
+mlanconfig mlanX cfgdata <register type> <conf file>
+mlanconfig mlanX sdcmd52rw <FN no.> <address> [data]
+mlanconfig mlanX sdcmd53rw <FN no.> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+mlanconfig mlanX setuserscan [ARGS]
+mlanconfig mlanX getscantable [ARGS]
+mlanconfig mlanX addts <filename.conf> <section# of tspec> <timeout in ms>
+mlanconfig mlanX delts <filename.conf> <section# of tspec>
+mlanconfig mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+mlanconfig mlanX qconfig get [Queue Id: 0-3]
+mlanconfig mlanX qconfig def [Queue Id: 0-3]
+mlanconfig mlanX qstats on  [Queue Id: 0-3]
+mlanconfig mlanX qstats off [Queue Id: 0-3]
+mlanconfig mlanX qstats get [Queue Id: 0-3]
+mlanconfig mlanX qstatus
+mlanconfig mlanX ts_status
+mlanconfig mlanX regrdwr <type> <offset> [value]
+mlanconfig mlanX memrdwr <address> [value]
+mlanconfig mlanX customie <index> <mask> <IE buffer>
+mlanconfig mlanX tdls_config <0/1>
+mlanconfig mlanX tdls_setinfo <tdls.conf>
+mlanconfig mlanX tdls_setup <tdls.conf>
+mlanconfig mlanX tdls_discovery <tdls.conf>
+mlanconfig mlanX tdls_teardown <tdls.conf>
+mlanconfig mlanX tdls_powermode <tdls.conf>
+mlanconfig mlanX tdls_channel_switch <tdls.conf>
+mlanconfig mlanX tdls_stop_channel_switch <tdls.conf>
+mlanconfig mlanX tdls_cs_params <tdls.conf>
+mlanconfig mlanX tdls_disable_cs <0/1>
+mlanconfig mlanX tdls_link_status
+mlanconfig mlanX tdls_debug "wrong_bss" <0/1>
+mlanconfig mlanX tdls_debug "setup_existing_link" <0/1>
+mlanconfig mlanX tdls_debug "fail_setup_confirm" <0/1>
+mlanconfig mlanX tdls_debug "setup_with_prohibited" <0/1>
+mlanconfig mlanX tdls_debug "higher_lower_mac" <0/1>
+mlanconfig mlanX tdls_debug "ignore_key_expiry" <0/1>
+mlanconfig mlanX tdls_debug "allow_weak_security" <0/1>
+mlanconfig mlanX tdls_debug "stop_rx" <0/1>
+mlanconfig mlanX tdls_debug "cs_im_return" <0/1>
+mlanconfig mlanX mgmtframetx <mgmt_frame.conf>
+
+
+DESCRIPTION
+
+Those commands are used in Marvell specific application called mlanconfig.
+
+===========
+-v
+	This command is used to display the version of mlanconfig utility.
+	Usage:
+		mlanconfig -v
+
+hostcmd bgscfg
+	This command is used to configure the various parameters for PPS/UAPSD
+	or normal background scan.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/bg_scan.conf bgscfg
+
+hostcmd requesttpc
+	This command is used to request 802.11H TPC info.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/requesttpc.conf requesttpc
+
+hostcmd crypto_test
+	This command is used to test the encryption/decryption API of the firmware.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/crypto_test.conf crypto_test
+
+hostcmd subevent_get
+hostcmd subevent_set
+	This command is used to get/set the configurations for event descriptor
+	interface command.
+	subsvent_get: get subscribed event parameters
+	subsvent_set: set subscribed event parameters
+
+	Usage:
+		mlanconfig mlanX hostcmd config/subevent.conf subevent_get
+		mlanconfig mlanX hostcmd config/subevent.conf subevent_set
+
+hostcmd auto_tx_get
+hostcmd nat_keep_alive
+hostcmd auto_tx_unreg
+	This command is used to configures the Frame Auto Transmission parameters.
+	auto_tx_get: get auto_tx parameters
+	nat_keep_alive: register to firmware for sending NAT Keep Alive packet
+	auto_tx_unreg: unregister to firmware auto_tx
+
+	Usage:
+		mlanconfig mlanX hostcmd config/auto_tx.conf auto_tx_get
+		mlanconfig mlanX hostcmd config/auto_tx.conf nat_keep_alive
+		mlanconfig mlanX hostcmd config/auto_tx.conf auto_tx_unreg
+
+hostcmd txrate_cfg_get
+hostcmd txrate_cfg_set_bg
+hostcmd txrate_cfg_set_bgn
+	This command is used to set/get the transmit data rate.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_get
+		mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bg
+		mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bgn
+
+hostcmd txpwrlimit_cfg_get
+hostcmd txpwrlimit_2g_cfg_set
+hostcmd txpwrlimit_5g_cfg_set
+	This command is used to set/get the configuration data of Tx power limitation.
+	Note: The configuration set should be issued when STA is disconnected.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get
+		mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set
+		mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set
+
+hostcmd pad_cfg_get
+hostcmd pad_cfg_set
+	This command is used to set/get the configuration data for PAD OR.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/pad_cfg.conf pad_cfg_get
+		mlanconfig mlanX hostcmd config/pad_cfg.conf pad_cfg_set
+
+hostcmd 2040coex
+	This command is used to send the 11n 20/40 Coex command to firmware.
+	Firmware will send 11n 20/40 Coex management action frame to AP.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/11n_2040coex.conf 2040coex
+
+hostcmd mode_get
+hostcmd mode_timeshare
+hostcmd mode_spatial
+	This command is used to get/set Robust BT Coex.
+	mode_get:       get the current mode
+	mode_timeshare: set Robust BT Coex to timeshare mode  (default on 1x1 chips)
+	mode_spatial:   set Robust BT Coex to spatial mode    (only for, and default on 2x2 chips)
+
+	Usage:
+		mlanconfig mlanX hostcmd config/robust_btc.conf mode_get
+		mlanconfig mlanX hostcmd config/robust_btc.conf mode_timeshare
+		mlanconfig mlanX hostcmd config/robust_btc.conf mode_spatial
+
+hostcmd generictime
+hostcmd a2dptime
+hostcmd inquirytime
+hostcmd ap_generictime
+hostcmd ap_a2dptime
+hostcmd ap_inquirytime
+        This command is used to configure the time slice of COEX (only works in timeshare mode)
+        generictime:       configure the Bttime and Wlantime in Station Generic case
+        a2dptime:          configure the Bttime and Wlantime in Station A2DP case
+        inquirytime:       configure the Bttime and Wlantime in Station Inquiry case
+        ap_generictime:    configure the Bttime and Wlantime in Ap Generic case
+        ap_a2dptime:       configure the Bttime and Wlantime in Ap A2DP case
+        ap_inquirytime:    configure the Bttime and Wlantime in Ap Inquiry case
+
+    Usage:
+                mlanutl mlanX hostcmd config/robust_btc.conf generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf inquirytim
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime
+
+hostcmd sdio_pulldown_get
+hostcmd sdio_pulldown_set
+hostcmd sdio_pulldown_disable
+	This command is used to set/get the settings of pulling up and
+	pulling down of SDIO lines.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_get
+		mlanconfig mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_set
+		mlanconfig mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_disable
+
+arpfilter
+	This command is used to configure the ARP filtering parameters.
+
+	Usage:
+		mlanconfig mlanX arpfilter config/arpfilter.conf
+
+mefcfg
+	This command is used to set MEF settings.
+
+	Usage:
+		mlanconfig mlanX mefcfg config/mef.conf
+
+cfgdata
+	This command is used to set/get the configuration data to/from firmware.
+
+	Usage:
+		mlanconfig mlanX cfgdata <type> <.conf file name>
+		This command is used to set the cfg data in the .conf file to firmware.
+
+		mlanconfig mlanX cfgdata <type>
+		This command is used to get the cfg data from firmware and display
+		on to the console.
+
+	Where the value of <type> field is:
+		2   -- Cal data download and <.conf file name> is cal_data.conf
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanconfig mlanX sdcmd52rw <function number> <register address> [value]
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+    Examples:
+		mlanconfig mlan0 sdcmd52rw 1 3
+		mlanconfig mlan0 sdcmd52rw 1 1 0x3f
+
+sdcmd53rw
+	This command is used to issue a CMD53 read/write data in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanconfig mlanX sdcmd53rw <func> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+
+	where the parameters are,
+		<func>:     function number (0/1/2/..)
+		<address>:  data address
+		<mode>:     byte mode/block mode (0/1)
+		<blksize>:  block size (32/64/../512, NA for byte mode)
+		<blknum>:   block number or byte number
+		<data1> ... <dataN>:  data for write
+
+	Note: The total data length is block size * block number for block mode
+	or byte number for byte mode. The max data length is 2000-byte.
+	For write the data pattern will be duplicated to data buffer.
+
+	Examples:
+		mlanconfig mlan0 sdcmd53rw 0 0x8000 1 0x40 2
+		mlanconfig mlan0 sdcmd53rw 1 0x10000 0 1 5 0x0a 0x0b 0x0c 0x0d 0x0e
+
+setuserscan
+	Initiate a customized scan and retrieve the results
+
+	Usage:
+		mlanconfig mlanX setuserscan [ARGS]
+
+	Where [ARGS]:
+	  ssid="[SSID]"            specify a SSID filter for the scan
+	  chan=[chan#][band][mode] where band is [a,b,g,n] and mode is
+	                           blank for active or 'p' for passive
+	  bssid=xx:xx:xx:xx:xx:xx  specify a BSSID filter for the scan
+	  wc="[WILDCARD SSID]"     specify a UNIX pattern matching filter (using *
+	                           and ?) for SSIDs found in a broadcast probe
+	  keep=[0 or 1]            keep the previous scan results (1), discard (0)
+	  dur=[scan time]          time to scan for each channel in milliseconds
+	  gap=[time gap]           Time gap between two scans in milliseconds
+	  probes=[#]               number of probe requests to send on each chan
+	                           for each broadcast probe required and each SSID
+	                           specific probe required (1-4)
+	  type=[1,2,3]             BSS type: 1 (Infra), 2(Adhoc), 3(Any)
+
+	Any combination of the above arguments can be supplied on the command line.
+	If the chan token is absent, a full channel scan will be completed by driver.
+	If the dur or probes tokens are absent, the driver default setting will be
+	used. The bssid and ssid fields, if blank, will produce an unfiltered scan.
+	It's allowed to input multiple ssid/wc entries, the max entry number is 10.
+	The type field will default to 3 (Any) and the keep field will default to 0
+	(Discard).
+
+	Examples:
+	1) Perform an active scan on channels 1, 6, and 11 in the 'g' band:
+		setuserscan chan=1g,6g,11g
+
+	2) Perform a passive scan on channel 11 for 20 ms:
+		setuserscan chan=11gp dur=20
+
+	3) Perform an active scan on channels 1, 6, and 11; and a passive scan on
+	   channel 36 in the 'a' band:
+		setuserscan chan=1g,6g,11g,36ap
+
+	4) Perform an active scan on channel 6 and 36 for specific SSID:
+		setuserscan chan=6g,36a ssid=TestAP1 ssid=TestAP2
+
+	5) Scan all available channels (B/G/N, A bands) for a specific BSSID, keep
+	   the current scan table intact, update existing or append new scan data:
+		setuserscan bssid=00:50:43:20:12:82 keep=1
+
+	6) Scan channel 6, for all infrastructure networks, sending two probe
+	   requests.  Keep the previous scan table intact. Update any duplicate
+	   BSSID/SSID matches with the new scan data:
+		setuserscan chan=6g type=1 probes=2 keep=1
+
+	7) Scan channel 1 and 6, for all networks matching the Mrvl*AP
+	   or AP*Mrvl? patterns and for MrvlTst SSID.  Generate 3 broadcast
+	   probes for the patterns and 3 SSID specific probes for MrvlTst on
+	   both channel 1 and channel 6.
+		setuserscan chan=1g,6g probes=3 wc="Mrvl*AP" wc="AP*Mrvl?" ssid="MrvlTst"
+
+	8) Scan all the channels for specified band.
+		setuserscan chan=0g
+
+	9) Scan channel 1 and 6, send 3 probe requests, scan each channel for 40 ms
+	   with time gap of 50ms between 2 scans
+		setuserscan chan=1g,6g probes=3 dur=40 gap=50
+
+	All entries in the scan table (not just the new scan data when keep=1)
+	will be displayed upon completion by use of the getscantable ioctl.
+
+getscantable
+	Display the current contents of the driver scan table
+
+	Usage:
+		mlanconfig mlanX getscantable
+		mlanconfig mlanX getscantable [#]
+		mlanconfig mlanX getscantable tsf
+		mlanconfig mlanX getscantable help
+
+	1) Without argument, the entire scantable is displayed.
+	2) Specifying a # will display detailed information about a specific scan
+	   table entry.  '0' displays driver cached information regarding the
+	   current association (if any).
+	3) The tsf argument will display the entire scan table with the recorded
+	   TSF timestamp for the entry.
+	4) The help argument will display the legend for the capability field.
+
+addts
+	Send an ADDTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in an ADDTS request to the associated AP.
+
+	Return the execution status of the command as well as the ADDTS response
+	  from the AP if any.
+
+	Usage:
+		mlanconfig mlanX addts <filename.conf> <section# of tspec> <timeout(ms)>
+
+delts
+	Send a DELTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in a DELTS request to the associated AP.
+
+	Return the execution status of the command.  There is no response to a
+	  DELTS from the AP.
+
+	Usage:
+		mlanconfig mlanX delts <filename.conf> <section# of tspec>
+
+qconfig
+	Send a WMM AC Queue configuration command to get/set/default params
+
+	Configure or get the parameters of a WMM AC queue. The command takes
+	  an optional Queue Id as a last parameter.  Without the queue id, all
+	  queues will be acted upon.
+
+	Usage:
+		mlanconfig mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+		mlanconfig mlanX qconfig get [Queue Id: 0-3]
+		mlanconfig mlanX qconfig def [Queue Id: 0-3]
+
+qstats
+	Turn on/off or retrieve and clear the queue statistics for an AC
+
+	Turn the queue statistics collection on/off for a given AC or retrieve the
+	  current accumulated stats and clear them from the firmware. The command
+	  takes an optional Queue Id as a last parameter. Without the queue id,
+	  all queues will be acted upon.
+
+	Usage:
+		mlanconfig mlanX qstats on  [Queue Id: 0-3]
+		mlanconfig mlanX qstats off [Queue Id: 0-3]
+		mlanconfig mlanX qstats get [Queue Id: 0-3]
+
+qstatus
+	This command retrieves the current status of the WMM queues. If WMM
+	  is enabled then it displays the information for each AC in a table.
+
+	Usage:
+		mlanconfig mlanX qstatus
+
+ts_status
+	This command queries the FW for the status of TSIDs 0 through 7
+	  configured via call admission control and displays the results in a
+	  table.
+
+	Usage:
+		mlanconfig mlanX ts_status
+
+regrdwr
+	This command is used to read/write the adapter register.
+
+	Usage:
+		mlanconfig mlanX regrdwr <type> <offset> [value]
+
+	where the parameters are,
+		<type>:     1:MAC/SOC, 2:BBP, 3:RF, 5:CAU
+		<offset>:   offset of register
+		[value]:    value to be written
+
+	Examples:
+		mlanconfig mlan0 regrdwr 1 0xa060   : Read the MAC register
+		mlanconfig mlan0 regrdwr 1 0xa794 0x80000000
+		                                    : Write 0x80000000 to MAC register
+
+memrdwr
+	This command is used to read/write the adapter memory.
+
+	Usage:
+		mlanconfig mlanX memrdwr <address> [value]
+
+	where the parameters are,
+		<address>:  memory address
+		[value]:    value to be written
+
+	Examples:
+		mlanconfig mlan0 memrdwr 0x80000000  : Read memory address 0x80000000
+		mlanconfig mlan0 memrdwr 0x80000000 0xffffffff
+		                                     : Write 0xffffffff to memory address 0x80000000
+
+customie
+	This command is used to set or get custom IEs for management frames.
+
+	Usage : customie [INDEX] [MASK] [IEBuffer]
+        empty - Get all IE settings
+        INDEX:  0 - Get/Set IE index 0 setting
+                1 - Get/Set IE index 1 setting
+                2 - Get/Set IE index 2 setting
+               MAX IE Index depends on device memory.
+
+               -1 - Append/Delete IE automatically
+                    Delete will delete the IE from the matching IE buffer
+                    Append will append the IE to the buffer with the same mask
+        MASK :  Management subtype mask value as per bit definitions
+             :  Bit 0 - Association request
+             :  Bit 1 - Association response
+             :  Bit 2 - Reassociation request
+             :  Bit 3 - Reassociation response
+             :  Bit 4 - Probe request
+             :  Bit 5 - Probe response
+             :  Bit 8 - Beacon
+        MASK :  MASK = 0 to clear the mask and the IE buffer
+        IEBuffer :  IE Buffer in hex (max 256 bytes)
+                    The Buffer should not be space separated.
+
+	Example:
+	 ./mlanconfig mlan0 customie
+		Get IE buffer, subtype mask settings for all indices.
+
+	./mlanconfig mlan0 customie 1
+		Get IE buffer and subtype mask for the Index = 1.
+
+	./mlanconfig mlan0 customie 2 0
+		Clear IE buffer and mask value for Index = 2.
+
+	./mlanconfig mlan0 customie 3 0x101 0xdd051234567890
+		Set IE buffer and mask value for Index = 3.
+
+	./mlanconfig mlan0 customie -1 0x101 0xdd051234567890
+		Append the specified IEBuffer at index with mask value of 0x101.
+
+	./mlanconfig mlan0 customie -1 0 0xdd051234567890
+		Delete the specified IEBuffer from all the IEs.
+
+	./mlanconfig mlan0 customie 2 0 0xdd051234567890
+		Delete the specified IEBuffer from the IEs at index 2.
+
+tdls_config
+	This command is used to enable/disable TDLS on device.
+
+	Usage : tdls_config <0/1>
+		1: Enable TDLS
+		0: Disable TDLS
+tdls_setinfo
+	This command is used for setting the capabilities of the TDLS station.
+
+        Usage : tdls_setinfo <tdls.conf>
+		Set capabilities of TDLS station.
+tdls_setup
+	This command is used to send TDLS setup request.
+
+	Usage: tdls_setup <tdls.conf>
+                Send TDLS setup request.
+tdls_discovery
+	This command is used to request TDLS discovery.
+
+	Usage : tdls_discovery <tdls.conf>
+        	Request TDLS discovery.
+tdls_teardown
+	This command is used to send TDLS teardown request.
+
+	Usage : tdls_teardown <tdls.conf>
+		Request teardown of TDLS link.
+tdls_powermode
+	This command is used to send TDLS powermode request.
+
+	Usage : tdls_powermode <tdls.conf>
+		Send TDLS powermode (either 0:Active, 1:PowerSave) command.
+tdls_channel_switch
+	This command is used to send TDLS channel switch request.
+
+	Usage : tdls_channel_switch <tdls.conf>
+		Send TDLS channel switch command.
+tdls_stop_channel_switch
+	This command is used to send stop TDLS channel switch request.
+
+	Usage : tdls_stop_channel_switch <tdls.conf>
+		Send stop TDLS channel switch command.
+tdls_cs_params
+	This command is used to set TDLS channel switch params
+
+	Usage : tdls_cs_params <tdls.conf>
+		Set TDLS channel switch params.
+tdls_disable_cs
+	This command is used to disable TDLS channel switch
+
+	Usage : tdls_disable_cs <0/1>
+		Disable TDLS channel switch.
+tdls_link_status [peer_mac_address]
+	This command is used to get link information about TDLS links or
+    a TDLS link correponding to peer mac address.
+
+	Usage : tdls_link_status
+		Send TDLS command to get current link status.
+tdls_debug
+	This command is used for FW debug functionality and tests.
+
+mgmtframetx
+	This command is used to send mgmt frame
+
+	Usage:
+		mlanconfig mlanX mgmtframetx <mgmt_frame.conf>
+
+
+===============================================================================
+		U S E R  M A N U A L  F O R  M L A N 2 0 4 0 C O E X
+
+NAME
+mlan2040coex - This application handles the 11n 20/40 coexistence operation for
+               the Marvell mdriver
+
+SYNOPSIS
+mlan2040coex [-d <n>] [-i <intfname>] [hvB]
+	-d = Device number (n)
+	-i = Interface name (intfname)
+	-h = Help
+	-v = Version
+	-B = Run the process in background
+Note: If device number (n) is not present, then 0 assumed.
+      If intfname is not present, then mlan0 assumed.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANEVENT
+
+NAME
+mlanevent.exe
+
+This tool can be used to listen for and obtain events from the driver
+through the netlink layer.
+
+----------------
+Supported events
+----------------
+STA_DEAUTH
+STA_ASSOC
+BSS_START
+BSS_IDLE
+BSS_ACTIVE
+
+-----------------
+Details of events
+-----------------
+
+STA_DEAUTH
+----------
+    For this event, the following information is shown:
+        + Deauthenticated STA MAC address.
+        + Reason for deauthentication.
+
+STA_ASSOC
+----------
+    For this event, the following information is shown:
+        + STA MAC address.
+
+BSS_START
+----------
+    For this event, the following information is shown:
+        + AP MAC address.
+
+BSS_IDLE
+----------
+    For this event, there is no associated information.
+
+BSS_ACTIVE
+----------
+    For this event, there is no associated information.
+
+===============================================================================
diff --git a/wlan_sd8897/README_MLAN b/wlan_sd8897/README_MLAN
new file mode 100644
index 0000000..47c1d62
--- /dev/null
+++ b/wlan_sd8897/README_MLAN
@@ -0,0 +1,3637 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2008-2018, Marvell International Ltd.
+ All Rights Reserved
+
+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 up to 4.15.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy firmware image sd8787_uapsta.bin | sd8797_uapsta.bin | ... to
+	   /lib/firmware/mrvl/ directory, create the directory if it doesn't exist.
+	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
+		The default drv_mode is 7.
+			Bit 4 :  NAN
+
+		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 2)
+		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)
+		nan_name: Name of the NAN interface (default: "nan")
+		max_nan_bss: Number of NAN interfaces (default 1)
+	   For example, to install SD8787 driver,
+		insmod mlan.ko
+		insmod sd8787.ko [drv_mode=3] [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in STA only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=1 [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in uAP only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=2 [fw_name=mrvl/sd8787_uapsta.bin]
+
+	   To switch mode between STA only, uAP only and uAPSTA etc. in run time,
+		echo drv_mode=1 > /proc/mwlan/config		// STA mode
+		echo drv_mode=2 > /proc/mwlan/config		// uAP mode
+		echo drv_mode=3 > /proc/mwlan/config		// STA+uAP mode
+		echo drv_mode=7 > /proc/mwlan/config		// STA+uAP+WIFIDIRECT mode
+	c) Uninstall WLAN driver,
+		ifconfig mlanX down
+		ifconfig uapX down
+		rmmod sd8xxx
+		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>
+	  p2p_enh=0|1 <Disable enhanced P2P (default) | Enable enhanced P2P>
+	  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)>
+	  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>
+	  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>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf
+          Note: Loading driver with 8887 must include correct cal_data_cfg parameter.
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf
+	  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
+	  cfg80211_drcs=1|0 <Enable DRCS support (default) | Disable DRCS support>
+	  reg_alpha2=<Regulatory alpha2 (default NULL)>
+	  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>
+	  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
+	  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.>
+      napi=0|1 <disable napi | enable napi>
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sd8xxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+
+	The following info are provided in /proc/net/mwlan/mlanX|uapX|wfdX/info,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX|uapX|wfdX/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/mlanX|uapX|wfdX/debug,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX|uapX|wfdX/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>
+	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>
+	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>
+	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/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/config      # read func 0 address 4
+		cat /proc/mwlan/config                          # display the register value
+		echo "sdcmd52rw= 1 3 0xf" > /proc/mwlan/config  # write 0xf to func 1 address 3
+
+	Issue debug_dump command through proc.
+	Usage:
+		echo "debug_dump" > /proc/mwlan/config
+
+	Examples:
+		echo "debug_dump" > /proc/mwlan/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 sd8xxx.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/config   trigger inband firmware reset and reload firmware
+       echo "fw_reload=2" > /proc/mwlan/config   trigger firmware reload
+       echo "fw_reload=3" > /proc/mwlan/config   set firmware reload flag in driver.
+
+    (Note: This feature will be supported on Robin3 and KF2.
+           For CAC-A2, it only work with the board which supports parallel fw download)
+
+
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANUTL
+
+NAME
+    mlanutl - configure the additional parameters available for Marvell mdriver.
+
+SYNOPSIS
+    mlanutl -v
+    mlanutl <mlanX|uapX|wfdx> <command> [parameters] ...
+
+	mlanutl mlanX 11dcfg
+	mlanutl mlanX 11dclrtbl
+	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 addts <filename.conf> <section# of tspec> <timeout in ms>
+	mlanutl mlanX adhocaes
+	mlanutl mlanX aggrpriotbl [<m0> <n0> <m1> <n1> ... <m7> <n7>]
+	mlanutl uapX aggrpriotbl [<m0> <n0> <m1> <n1> ... <m7> <n7>]
+	mlanutl mlanX amsduaggrctrl <n>
+	mlanutl mlanX antcfg [m] [n]
+	mlanutl mlanX arpfilter <arpfilter.conf>
+	mlanutl mlanX assocessid <"[essid]">
+	mlanutl mlanX assocessid_bssid <"[bssid] [essid]">
+	mlanutl mlanX associate "<bssid> <ssid>"
+	mlanutl mlanX authtype [n]
+	mlanutl mlanX autotdls [n]
+        mlanutl mlanX tdls_idle_time [n]
+        mlanutl uapX dfs_offload [n]
+	mlanutl mlanX bandcfg [l] [m] [n] [o]
+	mlanutl mlanX bcninterval [n]
+	mlanutl wfdX bssrole [l]
+	mlanutl mlanX cfgdata <register type> [<conf file>]
+	mlanutl mlanX cfpcode [m] [n]
+	mlanutl mlanX changraph [<load | anpi | anpiload> <loops>]
+	mlanutl mlanX coex_rx_winsize [m]
+	mlanutl mlanX countrycode [l]
+
+	mlanutl	mlanX cfpinfo
+	mlanutl uapX cfpinfo
+
+	mlanutl	mlanX acs [<chX> <chY> ... <chZ>]
+	mlanutl	uapX acs [<chX> <chY> ... <chZ>]
+
+	mlanutl mlanX customie [[[<index>] <mask>] <IEBuffer>]
+	mlanutl mlanX deauth [l]
+	mlanutl uapX deauth [l]
+	mlanutl mlanX deepsleep [l] [m]
+	mlanutl mlanX delba <l> [<m> <n>]
+	mlanutl uapX delba <l> [<m> <n>]
+	mlanutl mlanX delts <filename.conf> <section# of tspec>
+	mlanutl mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+	mlanutl mlanX drvdbg [n]
+	mlanutl mlanX esuppmode [l] [m] [n]
+	mlanutl mlanX extcapcfg [<ext_cap>]
+	mlanutl mlanX fwmacaddr [mac_addr]
+	mlanutl mlanX getdatarate
+	mlanutl uapX getdatarate
+	mlanutl mlanX getkey
+	mlanutl mlanX getlog
+	mlanutl mlanX getscantable [ARGS]
+	mlanutl mlanX getsignal [m] [n]
+	mlanutl mlanX signalextcfg [m]
+	mlanutl mlanX getsignalextv2 [m]
+	mlanutl mlanX getsignalext [m]
+        mlanutl mlanX dyn_bw [n]
+	mlanutl uapX getstalist
+	mlanutl uapX channel_switch <switch mode> <oper class> <new channel> <switch count> <bandwidth>
+	mlanutl mlanX hostcmd <11n_2040coex.conf> 2040coex
+	mlanutl mlanX hostcmd <auto_tx.conf> auto_tx_get
+	mlanutl mlanX hostcmd <auto_tx.conf> auto_tx_unreg
+	mlanutl mlanX hostcmd <bg_scan.conf> bgscfg
+
+	mlanutl mlanX hostcmd <pkt_coalescing.conf> coalesce_cfg
+	mlanutl mlanX hostcmd <ed_mac_ctrl.conf> ed_mac_ctrl
+	mlanutl mlanX hostcmd <crypto_test.conf> crypto_test
+	mlanutl mlanX hostcmd <auto_tx.conf> nat_keep_alive
+	mlanutl mlanX hostcmd <pad_cfg.conf> pad_cfg_get
+	mlanutl mlanX hostcmd <pad_cfg.conf> pad_cfg_set
+	mlanutl mlanX hostcmd <requesttpc.conf> requesttpc
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_get
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_timeshare
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_spatial
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_none
+	mlanutl mlanX hostcmd <robust_btc.conf> gpio_cfg
+	mlanutl mlanX hostcmd <robust_btc.conf> generictime
+	mlanutl mlanX hostcmd <robust_btc.conf> a2dptime
+	mlanutl mlanX hostcmd <robust_btc.conf> inquirytim
+	mlanutl mlanX hostcmd <robust_btc.conf> ap_generictime
+	mlanutl mlanX hostcmd <robust_btc.conf> ap_a2dptime
+	mlanutl mlanX hostcmd <robust_btc.conf> ap_inquirytime
+	mlanutl mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_disable
+	mlanutl mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_get
+	mlanutl mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_set
+	mlanutl mlanX hostcmd <subevent.conf> subevent_get
+	mlanutl mlanX hostcmd <subevent.conf> subevent_set
+	mlanutl mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_2g_cfg_set
+	mlanutl mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_5g_cfg_set
+	mlanutl mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_cfg_get
+	mlanutl mlanX hostcmd <txrate_cfg.conf> txrate_cfg_get
+	mlanutl mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bg
+	mlanutl mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bgn
+	mlanutl mlanX hostcmd <conf> generate_raw <raw_data_file>
+	mlanutl mlanX hostcmd <fwdump.conf> fwdump
+
+	mlanutl mlanX hotspotcfg [<bitmap>]
+	mlanutl mlanX hscfg [condition [[GPIO# [gap]]]] [ind_GPIO# [level]]
+	mlanutl mlanX hssetpara condition [GPIO# [gap]] [ind_GPIO# [level]]
+	mlanutl mlanX mgmtfilter <mgmtfilter.conf>
+	mlanutl mlanX auto_arp [n]
+	mlanutl mlanX htcapinfo [<m>] [<n>]
+	mlanutl mlanX htstreamcfg [n]
+	mlanutl mlanX httxbfcap [cap]
+	mlanutl mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData]"
+	mlanutl mlanX httxcfg [<m>] [<n>]
+	mlanutl mlanX inactivityto <n> <m> <l> [k]
+	mlanutl mlanX ipaddr ["<op>;<ipaddr>"]
+	mlanutl mlanX linkstats
+	mlanutl mlanX listeninterval [l]
+	mlanutl mlanX macctrl [n]
+	mlanutl uapX macctrl [n]
+	mlanutl mlanX mefcfg <mef.conf>
+	mlanutl mlanX memrdwr <address> [value]
+	mlanutl mlanX miracastcfg [l] [m] [n]
+	mlanutl mlanX mgmtframectrl [<mask>]
+	mlanutl uapX mgmtframectrl [<mask>]
+	mlanutl mlanX mgmtframetx <mgmt_frame.conf>
+	mlanutl mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+	mlanutl mlanX netmon [<act> [<filter> <band> <chan> [offset]]]
+	mlanutl mlanX offchannel [<l> <m> <n>]
+	mlanutl mlanX otpuserdata <l>
+	mlanutl mlanX passphrase [l]
+	mlanutl mlanX pb_bypass [data_1, data_2, ... data_n]
+	mlanutl mlanX pmfcfg <mfpc> <mfpr>
+	mlanutl mlanX port_ctrl [n]
+	mlanutl mlanX powercons [n]
+	mlanutl mlanX pscfg [k] [d] [l] ...
+	mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p]
+	mlanutl mlanX psmode [l]
+        mlanutl <interface> robustcoex <gpiocfg> [Enable/Disable] [gpionum] [gpiopolarity]
+        mlanutl <interface> keep_connect [Enable/Disable]
+	mlanutl mlanX qconfig def [Queue Id: 0-3]
+	mlanutl mlanX qconfig get [Queue Id: 0-3]
+	mlanutl mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+	mlanutl mlanX qoscfg
+	mlanutl mlanX qstatus
+	mlanutl mlanX radioctrl [n]
+	mlanutl mlanX rdeeprom <offset> <length>
+	mlanutl mlanX reassoctrl [n]
+	mlanutl mlanX regioncode [n]
+	mlanutl mlanX regrdwr <type> <offset> [value]
+	mlanutl mlanX rejectaddbareq [conditions]
+	mlanutl uapX rejectaddbareq [conditions]
+	mlanutl mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+	mlanutl mlanX sdcmd52rw <FN no.> <address> [data]
+	mlanutl mlanX sdcmd53rw <FN no.> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+	mlanutl mlanX sdioclock <n>
+	mlanutl mlanX setuserscan [ARGS]
+	mlanutl mlanX cancelscan
+	mlanutl mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+	mlanutl mlanX sleeppd [n]
+	mlanutl mlanX sysclock [clk1] [clk2] [clk3] [clk4]
+	mlanutl mlanX tcpackenh [l]
+	mlanutl mlanX tdls_channel_switch <tdls.conf>
+	mlanutl mlanX tdls_config <0/1>
+	mlanutl mlanX tdls_cs_params <tdls.conf>
+	mlanutl mlanX tdls_debug "allow_weak_security" <0/1>
+	mlanutl mlanX tdls_debug "cs_im_return" <0/1>
+	mlanutl mlanX tdls_debug "fail_setup_confirm" <0/1>
+	mlanutl mlanX tdls_debug "higher_lower_mac" <0/1>
+	mlanutl mlanX tdls_debug "ignore_key_expiry" <0/1>
+	mlanutl mlanX tdls_debug "setup_existing_link" <0/1>
+	mlanutl mlanX tdls_debug "setup_with_prohibited" <0/1>
+	mlanutl mlanX tdls_debug "stop_rx" <0/1>
+	mlanutl mlanX tdls_debug "wrong_bss" <0/1>
+	mlanutl mlanX tdls_disable_cs <0/1>
+	mlanutl mlanX tdls_discovery <tdls.conf>
+	mlanutl mlanX tdls_link_status
+	mlanutl mlanX tdls_powermode <tdls.conf>
+	mlanutl mlanX tdls_setinfo <tdls.conf>
+	mlanutl mlanX tdls_setup <tdls.conf>
+	mlanutl mlanX tdls_stop_channel_switch <tdls.conf>
+	mlanutl mlanX tdls_teardown <tdls.conf>
+	mlanutl mlanX thermal
+	mlanutl mlanX ts_status
+	mlanutl mlanX tsf
+	mlanutl mlanX txaggrctrl [m]
+	mlanutl mlanX txbufcfg
+	mlanutl mlanX txratecfg [l] [m] [n]
+	mlanutl uapX txratecfg [l] [m] [n]
+    mlanutl mlanX verext
+    mlanutl mlanX version
+	mlanutl mlanX vhtcfg <j> <k> [l] [m] [n] [o]
+	mlanutl uapX vhtcfg <j> <k> [l] [m] [n] [o]
+	mlanutl mlanX wakeupreason
+	mlanutl uapX wakeupreason
+	mlanutl mlanX warmreset
+	mlanutl mlanX wpssession [n]
+	mlanutl mlanX wmmcfg [n]
+	mlanutl mlanX wmmparamcfg [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+				[AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+				[AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+				[AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+	mlanutl mlanX wwscfg [m]
+	mlanutl mlanX mc_cfg [n]
+	mlanutl mlanX mc_policy [n]
+	mlanutl mlanX mc_cfg_ext [c] [s] [u] [m] <a> <b> <d> <e>
+	mlanutl p2pX cfg_noa [h] [i] [j] [k] [l]
+	mlanutl p2pX cfg_opp_ps [m] [n]
+        mlanutl mlanX get_sensor_temp
+        mlanutl <inteface> indrstcfg <ir_mode> [gpio_pin]
+
+        mlanutl <interface> fwwakeupmethod <method> <GPIO_pin>
+
+        mlanutl uapX ctrldeauth <n>
+
+        mlanutl mlanX/uapX bootsleep <1/0>
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell 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.
+
+11dcfg
+	This command is used to control 11D. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 11dcfg 1           : Enable 11D
+		mlanutl mlan0 11dcfg             : Get 11D status
+
+11dclrtbl
+	This command is used to clear the 11D channel table.
+
+	Usage:
+		mlanutl mlanX 11dclrtbl
+
+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.
+
+addts
+	Send an ADDTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in an ADDTS request to the associated AP.
+
+	Return the execution status of the command as well as the ADDTS response
+	  from the AP if any.
+
+	Usage:
+		mlanutl mlanX addts <filename.conf> <section# of tspec> <timeout(ms)>
+
+adhocaes
+	This command is used to set/get the AES key, when the station is in ad-hoc mode.
+	Note: This command is only available in disconnected state.
+
+	where value can be any 16 byte value.
+
+	Examples:
+		mlanutl mlan0 adhocaes           : Get ad-hoc aes key
+		mlanutl mlan0 adhocaes "1;12345678901234567890123456789012"
+		                                : Set ad-hoc aes key
+		mlanutl mlan0 adhocaes 2         : Clear ad-hoc aes key
+
+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.
+
+amsduaggrctrl
+	This command could be used to enable/disable a feature where firmware gives feedback to driver
+	regarding the optimal AMSDU buffer size to use with the current rate. Firmware will use the
+	current rate to decide the buffer size we could transmit. The max buffer size will still be
+	limited by buffer size provided in txbufcfg. (i.e. if the txbufcfg is 4K, then we could only transmit
+	4K/2K AMSDU packets, if the txbufcfg is 8K then we could transmit 8k/4k/2k based on current rate)
+
+	If enabled AMSDU buffer size at various rates will be as follows
+
+	1.	Legacy B/G rate.
+		No AMSDU aggregation.
+
+	2.	BW20 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 3, 2:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 1, 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 4, 3:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	3.	BW40 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4, 3, 2, 1:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5, 4, 3:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	where <n> is 0/1 (for disable/enable)
+
+	eg:
+	mlanutl mlan0 amsduaggrctrl 1 - Enable this feature
+	mlanutl mlan0 amsduaggrctrl 0 - Disable this feature
+	mlanutl mlan0 amsduaggrctrl - This will get the enable/disable flag
+	and the current AMSDU buffer size). The AMSDU buffer size returned is only
+	valid after association as before association there is no rate info.
+
+	Note:- This command to enable/disable could be given anytime (before/after
+			association). This feature is enabled by default by the driver during
+			initialization.
+
+antcfg
+	This command is used to set/get the mode of Tx/Rx path.
+
+    For chip which support STREAM_2X2
+	where value of m is:
+		Bit 0   -- Tx Path A or Tx/Rx Path A if [n] is not provided
+		Bit 1   -- Tx Path B or Tx/Rx Path B if [n] is not provided
+		Bit 0-1 -- Tx Path A+B or Tx/Rx Path A+B if [n] is not provided
+	where value of n is:
+		Bit 0   -- Rx Path A
+		Bit 1   -- Rx Path B
+		Bit 0-1 -- Rx Path A+B
+	The Tx path setting (m) is used for both Tx and Rx if Rx path (n) is not provided.
+
+	Examples:
+		mlanutl mlan0 antcfg             : Get Tx and Rx path
+		mlanutl mlan0 antcfg 3           : Set Tx and Rx path to A+B
+		mlanutl mlan0 antcfg 1 3         : Set Tx path to A and Rx path to A+B
+
+    For chip which support SAD
+    	where value of m is:
+		Bit 0   -- Tx/Rx antenna 1
+		Bit 1   -- Tx/Rx antenna 2
+		...
+		0xFFFF  -- Tx/Rx antenna diversity
+
+        where value of n is:
+                SAD evaluate time interval, only be provided when m = 0xFFFF, default value is 6s(0x1770)
+
+	Examples:
+		mlanutl mlan0 antcfg               : Get Tx/Rx antenna mode
+		mlanutl mlan0 antcfg 1             : Set Tx/Rx antenna 1
+		mlanutl mlan0 antcfg 0xFFFF        : Set Tx/Rx antenna diversity
+		mlanutl mlan0 antcfg 0xFFFF 0x1770 : Set antenna evaluate time interval to 6s
+
+arpfilter
+	This command is used to configure the ARP filtering parameters.
+
+	Usage:
+		mlanutl mlanX arpfilter <arpfilter.conf>
+
+	Where the parameter is:
+		arpfilter.conf : The configuration file specifying ARP filtering parameters.
+
+	Example:
+		mlanutl mlan0 arpfilter config/arpfilter.conf
+
+assocessid
+	This command is used to assoc essid with asynced mode,
+	and driver will auto retry if driver auto assoc enabled.
+
+	Usage:
+		mlanutl mlanX assocessid <"[essid]">
+
+	Where
+	<"[essid]"> is the essid which need to be associated with asynced mode.
+
+	Examples:
+		mlanutl mlan0 assocessid "Marvell Micro AP"    : Associate to the ESSID "Marvell Micro AP"
+
+assocessid_bssid
+	This command is used to assoc AP by ssid/bssid pair with asynced mode,
+	and driver will auto retry if driver auto assoc enabled.
+
+	Usage:
+		mlanutl mlanX assocessid_bssid <"[bssid] [essid]">
+
+	Where
+	<"[bssid]"> is the bssid which need to be associated with asynced mode.
+	<"[essid]"> is the essid which need to be associated with asynced mode.
+
+	Examples:
+		mlanutl mlan0 assocessid_bssid "xx:xx:xx:xx:xx:xx Marvell Micro AP"   : Associate to the AP which ssid = "Marvell Micro AP", bssid = "xx:xx:xx:xx:xx:xx"
+
+associate
+	Request an association to a given SSID/BSSID pair. This the only accurate
+	way to pick a specific AP and ESS for an association. The entry must
+	already exist in the scan table for the association to be attempted.
+
+	mlanutl mlanX associate "xx:xx:xx:xx:xx:xx SSID"
+
+authtype
+	This command is used to set/get authentication type.
+
+	Usage:
+		mlanutl mlanX authtype [n]
+
+	where <n>
+		0: 802.11 open system authentication
+		1: 802.11 shared key authentication
+		255: allow open system or shared key authentication (default)
+
+	Examples:
+		mlanutl mlan0 authtype 0         : use open system authentication
+		mlanutl mlan0 authtype 1         : use shared key authentication
+		mlanutl mlan0 authtype 255       : allow open system or shared key authentication
+		mlanutl mlan0 authtype           : get current setting
+
+autotdls
+	This command is used to enable/disable auto TDLS.
+
+	Usage:
+		mlanutl mlanX autotdls [n]
+
+	where <n>
+		0: Disable auto tdls
+		1: Enable auto tdls
+
+	Examples:
+		mlanutl mlan0 autotdls 1         : enable auto TDLS
+		mlanutl mlan0 autotdls 0         : disable auto TDLS
+		mlanutl mlan0 autotdls           : get current setting
+
+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
+
+tdls_idle_time
+	This command is used to set/get TDLS idle timeout. The valid value is between 0-0xffff. When set to 0, the tdls_idle_time will use default value(60).
+
+	Usage:
+		mlanutl mlanX tdls_idle_time [n]
+
+	where <n>
+		TDLS idle timeout value
+
+	Examples:
+		mlanutl mlan0 tdls_idle_time 30        : set tdls_idle_time value to 30
+		mlanutl mlan0 tdls_idle_time 0         : use default tdls_idle_time value(60)
+		mlanutl mlan0 tdls_idle_time           : get current setting
+
+dfs_offload
+	This command is used to enable/disable DFS offload. The valid value is 0/1.
+	Note: The parameters can be set only in disconnected state.
+
+	Usage:
+		mlanutl uapX dfs_offload [n]
+
+	where <n>
+		Enable/disable
+
+	Examples:
+		mlanutl uap0 dfs_offload 1         : enable DFS offload
+		mlanutl uap0 dfs_offload 0         : disable DFS offload
+
+bandcfg
+	This command is used to set/get infra/ad-hoc band.
+	Note: This command is only available in disconnected state.
+
+	Usage:
+		mlanutl mlanX bandcfg [l] [m] [n] [o]
+
+	where the parameters:
+		[l]: Infrastructure band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+
+		     bit 5: AC 2.4G
+		     bit 6: AC 5G
+		[m]: Ad-hoc start band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+		     bit 5: AC 2.4G
+		     bit 6: AC 5G
+		[n]: Ad-hoc start channel
+		[o]: 0 - Bandwidth 20Mhz
+		     1 - HT Bandwidth 40Mhz above
+		     3 - HT Bandwidth 40Mhz below
+			 4 - VHT Bandwidth 80Mhz
+	Examples:
+		mlanutl mlan0 bandcfg            : Get infra/ad-hoc band and ad-hoc
+		                                  start channel configurations
+		mlanutl mlan0 bandcfg 1          : Set infra band to B only
+		mlanutl mlan0 bandcfg 3 2 6      : Set infra band to B/G, ad-hoc start band
+		                                  to G and ad-hoc start channel to 6
+		mlanutl mlan0 bandcfg 7 11 6 1   : Set infra band to B/G/A, ad-hoc start band
+		                                  to B/G/GN, ad-hoc start channel to 6 and
+		                                  secondary channel to above
+
+bcninterval
+	This command is used to set/get the beacon interval in ad-hoc mode.
+	The valid beacon interval is between 20 - 1000, default beacon
+	interval is 100.
+
+	Where <n>
+		Beacon interval in TU (Time Unit: 1024 us).
+
+	Examples:
+		mlanutl mlan0 bcninterval 200    : Set ad-hoc beacon interval to 200
+		mlanutl mlan0 bcninterval        : Get ad-hoc beacon interval
+
+bssrole
+	This command is used to set/get the BSS role.
+
+	Where
+	[l] is <bss_role>
+	<bss_role> - This parameter specifies the BSS role to set.
+		0       : STA
+		1       : uAP
+
+	Examples:
+		mlanutl wfd0 bssrole                 : Get the current BSS role
+		mlanutl wfd0 bssrole 1               : Set the current BSS role to uAP
+
+cfgdata
+	This command is used to set/get the configuration data to/from firmware.
+
+	Usage:
+		mlanutl mlanX cfgdata <type> [<.conf file name>]
+
+	Where the parameters are:
+		type :
+		        2 -- CAL data download and <.conf file name> is cal_data.conf
+		.conf file name : The configuration file used to set/get the configuration data.
+
+	Examples:
+		mlanutl mlan0 cfgdata 2
+			: This command is used to get and display the CAL data from firmware.
+
+cfpcode
+	This command is used to set/get the Channel-Frequency-Power table codes.
+	The region table can be selected through region code.
+	The current configuration is returned if no parameter provided.
+
+	where the parameters are,
+		[m]: code of the CFP table for 2.4GHz (0: unchanged)
+		[n]: code of the CFP table for 5GHz (0 or not provided: unchanged)
+
+	Examples:
+		mlanutl mlan0 cfpcode            : Get current configuration
+		mlanutl mlan0 cfpcode 0x30       : Set 2.4GHz CFP table code 0x30 (EU),
+		                                  keep 5GHz table unchanged
+		mlanutl mlan0 cfpcode 0x10 5     : Set 2.4GHz CFP table code 0x10 (USA)
+		                                  and 5GHz table code 5
+
+changraph
+	Displays 2-dimensional graph, plotting channel number along x-axis and
+	anpi or channel-load along y-axis, depending on whether it is an anpi graph
+	or a channel load graph.
+
+	Usage:
+		mlanutl mlanX changraph [<load | anpi | anpiload> <loops>]
+		where:
+			load:       Only channel vs channel-load graph is displayed
+			anpi:       Only channel vs Average Noise Power Indicator(ANPI)
+						graph is displayed
+			anpiload:   Both the graphs for anpi and for the load are displayed
+			loops:      This is used to calculate the number of times
+						the graph [load or anpi or both] will be printed
+
+coex_rx_winsize
+	This command is used to set/get control to coex RX window size
+
+	where value of m is:
+		0       -- Disable COEX RX winsize (default)
+		1       -- Enable COEX RX winsize
+
+	Examples:
+		mlanutl mlan0 coex_rx_winsize             : Get COEX RX winsize
+		mlanutl mlan0 coex_rx_winsize 1           : Enable COEX RX winsize
+
+countrycode
+	This command is used to set and get the country code.
+
+	Where
+	[l] is Country code
+
+	Examples:
+		mlanutl mlan0 countrycode            : Get current countrycode
+		mlanutl mlan0 countrycode CN         : Set countrycode as China (CN)
+
+cfpinfo
+	This command is used to get region, country, environment codes,
+	channel and power table information from the FW.
+
+	Examples:
+		mlanutl mlan0 cfpinfo		     : Display cfp tables
+		mlanutl uap0 cfpinfo
+
+acs
+	This command is used to issue acs scan, then FW will
+	report the best channel and channel statistics.
+	User could specify channels or not. If channel is not
+	specified, acs scan will be on all supported channels.
+
+	Examples:
+		mlanutl mlan0 acs		     : ACS scan on all supported channels
+		mlanutl uap0 acs		     : ACS scan on all supported channels
+		mlanutl mlan0 acs 5 6 7 8	     : ACS scan on 5 6 7 8 channels
+		mlanutl uap0 acs 1 2 3		     : ACS scan on 1 2 3 channels
+
+customie
+	This command is used to set or get custom IEs for management frames.
+
+	Usage:
+		mlanutl mlanX customie [[[<index>] <mask>] <IEBuffer>]
+
+	Where the parameter is:
+		empty - Get all IE settings
+		<index> :   0 - Get/Set IE index 0 setting
+		            1 - Get/Set IE index 1 setting
+		            2 - Get/Set IE index 2 setting
+		           MAX IE Index depends on device memory.
+		           -1 - Append/Delete IE automatically
+		                Delete will delete the IE from the matching IE buffer
+		                Append will append the IE to the buffer with the same mask
+		<mask>      :  Management subtype mask value as per bit definitions
+		            :  Bit 0 - Association request
+		            :  Bit 1 - Association response
+		            :  Bit 2 - Reassociation request
+		            :  Bit 3 - Reassociation response
+		            :  Bit 4 - Probe request
+		            :  Bit 5 - Probe response
+		            :  Bit 8 - Beacon
+		<mask>      :  mask = 0 to clear the mask and the IE buffer
+		<IEBuffer>  :  IE Buffer in hex (max 256 bytes)
+		               The Buffer should not be space separated.
+
+	Examples:
+		mlanutl mlan0 customie
+			: Get IE buffer, subtype mask settings for all indices.
+
+		mlanutl mlan0 customie 1
+			: Get IE buffer and subtype mask for the Index = 1.
+
+		mlanutl mlan0 customie 2 0
+			: Clear IE buffer and mask value for Index = 2.
+
+		mlanutl mlan0 customie 3 0x101 0xdd051234567890
+			: Set IE buffer and mask value for Index = 3.
+
+		mlanutl mlan0 customie -1 0x101 0xdd051234567890
+			: Append the specified IEBuffer at index with mask value of 0x101.
+
+		mlanutl mlan0 customie -1 0 0xdd051234567890
+			: Delete the specified IEBuffer from all the IEs.
+
+		mlanutl mlan0 customie 2 0 0xdd051234567890
+			: Delete the specified IEBuffer from the IEs at index 2.
+
+deauth
+	This command is used to send a de-authentication to an arbitrary AP.
+	If [l] is omitted, the driver will deauth the associated AP.
+	If in ad-hoc mode this command is used to stop beacon transmission
+	from the station and go into idle state.
+
+	When <l> is supplied as a MAC address, the driver will deauth the
+	  specified AP.  If the AP address matches the driver's associated AP,
+	  the driver will disconnect. Otherwise, the driver remains connected.
+
+	When this command is executed on AP interface, it is used to send
+	a de-authentication to associated station.
+
+deepsleep
+	This command is used to set/get auto deep sleep mode.
+
+	Usage:
+		mlanutl mlanX deepsleep [l] [m]
+
+	where the parameters are:
+		[l]: Enable/disable auto deep sleep mode (1/0)
+		[m]: Idle time in milliseconds after which firmware will put the device
+		     in deep sleep mode. Default value is 100 ms.
+
+	Examples:
+		mlanutl mlan0 deepsleep          : Display auto deep sleep mode
+		mlanutl mlan0 deepsleep 1        : Enable auto deep sleep mode, idle time unchanged
+		mlanutl mlan0 deepsleep 0        : Disable auto deep sleep mode
+		mlanutl mlan0 deepsleep 1 500    : Enable auto deep sleep mode with idle time 500 ms
+        Note:
+            Deepsleep must be disabled before changing idle time.
+
+delba
+	This command is used to delete either all Tx BA or all Rx BA or a specific BA stream
+	based on direction, TID and peer address.
+
+	where <l> [<m> <n>]
+		<l> - This is the direction of BA stream, Tx (bit 0), Rx (bit 1).
+		<m> - This is the TID (0-7, 0xff for all) of BA stream.
+		<n> - This is the peer MAC addres of BA stream.
+
+	eg:
+	mlanutl mlanX delba 2 - This command will delete all the Rx BA streams.
+	mlanutl mlanX delba 3 - This command will delete all the Tx and Rx BA streams.
+	mlanutl mlanX delba 1 0 - This command will delete all the Tx streams with TID 0.
+	mlanutl mlanX delba 2 0xff "00:11:22:33:44:55" - This command will delete all the Rx BA streams
+		with specified peer MAC address
+	mlanutl mlanX delba 1 3 "00:11:22:33:44:55" - This command will delete the Tx BA stream with
+		TID 3 and specified peer MAC address.
+
+delts
+	Send a DELTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in a DELTS request to the associated AP.
+
+	Return the execution status of the command.  There is no response to a
+	  DELTS from the AP.
+
+	Usage:
+		mlanutl mlanX delts <filename.conf> <section# of tspec>
+
+dfstesting
+	This command is used to set/get settings for DFS testing.
+
+	Usage:
+	    mlanutl mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+
+	where <user_cac_pd> is user-configured Channel Availability Check in msec
+                        0 = disable, use default period (60000)
+                        1-65535 = enable with that period
+	where <user_nop_pd> is user-configured Non-Occupancy Period in sec
+                        0 = disable, use default period (1800)
+                        1-65535 = enable with that period
+	where <no_chan_change> is enable/disable no channel change on radar
+                           0 = disable, 1 = enable (overrides below)
+	where <fixed_chan_num> is user-configured channel to change to on radar
+                           0 = disable, 1-255 = enable with that channel
+                           (channel validity for region, etc. is not checked)
+                           (only takes effect if no_chan_change = 0)
+
+	Examples:
+		mlanutl mlan0 dfstesting             : Get current dfstesting settings
+		mlanutl mlan0 dfstesting 2000 0 0 0  : user_cac=2sec, others disabled/default
+		mlanutl mlan0 dfstesting 0 0 1 0     : only no_chan_change enabled
+		mlanutl mlan0 dfstesting 0 120 0 64  : user_nop=2min, force chan 64 on radar
+
+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
+
+esuppmode
+	This command is used to set/get the e-supplicant mode configurations/status.
+
+	Note: The configurations can be set only before association.
+	      For get, the configurations will be returned before association
+	      and the current status will be returned after association.
+
+	Where
+	[l] is <rsn_mode>
+	<rsn_mode> - This parameter specifies the RSN mode configuration
+		Bit 0    : No RSN
+		Bit 1-2  : RFU
+		Bit 3    : WPA
+		Bit 4    : WPA-NONE
+		Bit 5    : WPA2
+		Bit 6-15 : RFU
+	[m] is <pairwise_cipher>
+	<pairwise_cipher> - This parameter specifies the pairwise cipher
+		Bit 0    : RFU
+		Bit 1    : RFU
+		Bit 2    : TKIP
+		Bit 3    : AES
+		Bit 4-7  : RFU
+	[n] is <group_cipher>
+	<group_cipher> - This parameter specifies the group cipher
+		Bit 0    : RFU
+		Bit 1    : RFU
+		Bit 2    : TKIP
+		Bit 3    : AES
+		Bit 4-7  : RFU
+	Note that: the RFU bits cannot be SET.
+
+	Examples:
+		mlanutl mlan0 esuppmode          : Get RSN mode and pairwise/group cipher
+		mlanutl mlan0 esuppmode 8 4 4    : Set RSN mode yo WPA, active pairwise and
+		                                   group ciphers to TKIP
+
+extcapcfg
+	This command is used to set/get extended capabilities.
+
+	Usage:
+		mlanutl mlanX extcapcfg [<ext_cap>]
+
+	where <ext_cap> :  Extended capabilities in hex (max 9 bytes)
+		               The Buffer should not be space separated.
+
+	Examples:
+		mlanutl mlan0 extcapcfg 0x0000008020	: Set TDLS support and Interworking bits.
+
+fwmacaddr
+	This command is used to set/get FW side MAC address but host side address will remain as earlier.
+
+	Usage:
+		mlanutl mlanX fwmacaddr [mac_addr]
+
+	where <mac_addr> is desired MAC address
+
+	Examples:
+		mlanutl mlan0 fwmacaddr                        : Get current FW MAC address
+		mlanutl mlan0 fwmacaddr 00:50:43:20:bc:44      : Set FW side MAC address
+
+getdatarate
+	This command is used to get the data rate being used in last Tx
+	packet and last Rx packet.
+
+getkey
+	This command is used to get PTK/GTK
+
+	mlanutl mlanX getkey
+
+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
+
+getscantable
+	Display the current contents of the driver scan table
+
+	Usage:
+		mlanutl mlanX getscantable
+		mlanutl mlanX getscantable [#]
+		mlanutl mlanX getscantable tsf
+		mlanutl mlanX getscantable ch
+		mlanutl mlanX getscantable help
+
+	1) Without argument, the entire scantable is displayed in terms of channel (ch), signal strength (ss), BSS id (bssid), capability (cap), and SSID,
+		where each column in the capability is described as follows:
+		column 1 indicates the IBSS capability: A (Adhoc), I (Infra)
+		column 2 indicates the encryption capability: P (WEP), W (WPA), 2 (WPA2)
+		column 3 indicates the 11D capability: D (11D)
+		column 4 indicates the WMM capability: W (WMM), C (CAC)
+		column 5 indicates the 11K capability: K (11K)
+		column 6 indicates the 11R capability: R (11R)
+		column 7 indicates the WPS capability: S (WPS)
+		column 8 indicates the 11N/11AC capability: N (11N), A (11AC)
+
+	2) Specifying a # will display detailed information about a specific scan
+	   table entry.  '0' displays driver cached information regarding the
+	   current association (if any).
+	3) The tsf argument will display the entire scan table with the recorded
+	   TSF timestamp for the entry.
+	4) The ch argument will display the entire scan table sorted by channel
+	   number in the ascending order. If this argument is not specified,
+           scan table is sorted by signal strength in the descending order.
+	6) The help argument will display the legend for the capability field.
+
+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.
+
+	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.
+
+	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
+
+getstalist
+    This command is used to get list of associated stations to the AP.
+
+    Example:
+        mlanutl uap0 getstalist
+
+channel_switch <switch mode> <oper class> <new channel> <switch count> <bandwidth>
+    This command is used to do channel switch according to spec.
+
+    Where the paramters are:
+        switch mode : 0 -- no need to block traffic, 1 -- need block traffic
+        oper class  : operating class according to IEEE std802.11 spec, when 0 is used, only CSA IE will be used
+        new channel : the channel will switch to
+        switch count: channel switch time to send ECSA ie
+        bandwidth   : channel width switch to(optional),only for 5G channels.
+                      Support value 1 -- 40M above, 3 -- 40M below, 4 -- 80M, 5 -- 160M
+
+    Example:
+        mlanutl uap0 channel_switch 1 115 36 10      :switch to channel 36, oper class 115
+        mlanutl uap0 channel_switch 1 81 6 10        :switch to channel 6, oper class 81
+        mlanutl uap0 channel_switch 1 0 6 10         :switch to channel 6
+        mlanutl uap0 channel_switch 1 0 36 10 1      :switch to channel 36, bandwidth 40MHz above
+
+hostcmd 2040coex
+	This command is used to send the 11n 20/40 Coex command to firmware.
+	Firmware will send 11n 20/40 Coex management action frame to AP.
+
+	Usage:
+		mlanutl mlanX hostcmd config/11n_2040coex.conf 2040coex
+
+hostcmd auto_tx_get
+hostcmd auto_tx_unreg
+	This command is used to configures the Frame Auto Transmission parameters.
+	auto_tx_get: get auto_tx parameters
+	auto_tx_unreg: unregister to firmware auto_tx
+
+	Usage:
+		mlanutl mlanX hostcmd config/auto_tx.conf auto_tx_get
+		mlanutl mlanX hostcmd config/auto_tx.conf auto_tx_unreg
+
+hostcmd bgscfg
+	This command is used to configure the various parameters for PPS/UAPSD
+	or normal background scan.
+
+	Usage:
+		mlanutl mlanX hostcmd config/bg_scan.conf bgscfg
+
+hostcmd <pkt_coalescing.conf> coalesce_cfg
+	This command is used to set/clear rules to filter and buffer
+	broadcast/multicast packet which reduce unwanted patcket or interrupt to
+	host.
+
+	Usage:
+		mlanutl mlanX hostcmd <pkt_coalescing.conf> coalesce_cfg
+
+hostcmd <ed_mac_ctrl.conf> ed_mac_ctrl
+	This command is used to control ED MAC.
+
+	Usage:
+		mlanutl mlanX hostcmd <ed_mac_ctrl.conf> ed_mac_ctrl
+
+hostcmd crypto_test
+	This command is used to test the encryption/decryption API of the firmware.
+
+	Usage:
+		mlanutl mlanX hostcmd config/crypto_test.conf crypto_test
+
+hostcmd nat_keep_alive
+	This command is used to configures the Frame Auto Transmission parameters.
+	nat_keep_alive: register to firmware for sending NAT Keep Alive packet
+
+	Usage:
+		mlanutl mlanX hostcmd config/auto_tx.conf nat_keep_alive
+
+hostcmd pad_cfg_get
+hostcmd pad_cfg_set
+	This command is used to set/get the configuration data for PAD OR.
+
+	Usage:
+		mlanutl mlanX hostcmd config/pad_cfg.conf pad_cfg_get
+		mlanutl mlanX hostcmd config/pad_cfg.conf pad_cfg_set
+
+hostcmd requesttpc
+	This command is used to request 802.11H TPC info.
+
+	Usage:
+		mlanutl mlanX hostcmd config/requesttpc.conf requesttpc
+
+hostcmd mode_get
+hostcmd mode_timeshare
+hostcmd mode_spatial
+hostcmd mode_none
+	This command is used to get/set Robust BT Coex.
+	mode_get:       get the current mode
+	mode_timeshare: set Robust BT Coex to timeshare mode  (default on 1x1 chips)
+	mode_spatial:   set Robust BT Coex to spatial mode    (only for, and default on 2x2 chips)
+	mode_none:      set Robust BT Coex to mode none       (only for, and default on 2x2_3Antenna chips)
+
+	Usage:
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_get
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_timeshare
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_spatial
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_none
+
+hostcmd gpio_cfg
+	This command is used to enable/disable GPIO cfg.
+	gpio_cfg:       enable/disable GPIO cfg for external bt request  (default is enable with High Polarity)
+
+	Usage:
+		mlanutl mlanX hostcmd config/robust_btc.conf gpio_cfg
+
+hostcmd generictime
+hostcmd a2dptime
+hostcmd inquirytime
+hostcmd ap_generictime
+hostcmd ap_a2dptime
+hostcmd ap_inquirytime
+        This command is used to configure the time slice of COEX (only works in timeshare mode)
+        generictime:       configure the Bttime and Wlantime in Station Generic case
+        a2dptime:          configure the Bttime and Wlantime in Station A2DP case
+        inquirytime:       configure the Bttime and Wlantime in Station Inquiry case
+        ap_generictime:    configure the Bttime and Wlantime in Ap Generic case
+        ap_a2dptime:       configure the Bttime and Wlantime in Ap A2DP case
+        ap_inquirytime:    configure the Bttime and Wlantime in Ap Inquiry case
+
+    Usage:
+                mlanutl mlanX hostcmd config/robust_btc.conf generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf inquirytim
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime
+
+hostcmd sdio_pulldown_get
+hostcmd sdio_pulldown_set
+hostcmd sdio_pulldown_disable
+	This command is used to set/get the settings of pulling up and
+	pulling down of SDIO lines.
+
+	Usage:
+		mlanutl mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_get
+		mlanutl mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_set
+		mlanutl mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_disable
+
+hostcmd subevent_get
+hostcmd subevent_set
+	This command is used to get/set the configurations for event descriptor
+	interface command.
+	subsvent_get: get subscribed event parameters
+	subsvent_set: set subscribed event parameters
+
+	Usage:
+		mlanutl mlanX hostcmd config/subevent.conf subevent_get
+		mlanutl mlanX hostcmd config/subevent.conf subevent_set
+
+hostcmd txpwrlimit_2g_cfg_set
+hostcmd txpwrlimit_5g_cfg_set
+hostcmd txpwrlimit_cfg_get
+	This command is used to set/get the configuration data of Tx power limitation.
+	Note: The configuration set should be issued when STA is disconnected.
+
+	Usage:
+		mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get
+		mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set
+		mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set
+
+hostcmd txrate_cfg_get
+hostcmd txrate_cfg_set_bg
+hostcmd txrate_cfg_set_bgn
+	This command is used to set/get the transmit data rate.
+
+	Usage:
+		mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_get
+		mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bg
+		mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bgn
+
+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>
+
+hostcmd fwdump
+	This command is used to trigger firmware dump
+
+	Usage:
+		mlanutl mlanX hostcmd <fwdump.conf> fwdump
+
+hotspotcfg
+	This command is used to get/set the HotSpot configuration.
+
+	Usage:
+		mlanutl mlanX hotspotcfg [<bitmap>]
+
+	Where the parameter is:
+		<bitmap> : configuration bitset
+			 : Bit 31-10 - Reserved set to 0
+			 : Bit 9 - TDLS support indication enable/disable
+			 : Bit 8 - Interworking indication enable/disable
+			 : Bit 7-1 - Reserved set to 0
+			 : Bit 0 - HotSpot feature enable/disable
+
+	Examples:
+		mlanutl mlan0 hotspotcfg        : Get present remote address mode
+		mlanutl mlan0 hotspotcfg 0x301  : Turn on HotSpot2.0 and enable TDLS support and interworking indication
+		mlanutl mlan0 hotspotcfg 0      : Turn off HotSpot2.0 and disable TDLS support and interworking indication
+
+hscfg
+	This command is used to configure the host sleep parameters.
+
+	Usage:
+		mlanutl mlanX hscfg [condition [[GPIO# [gap]]]] (optional)[type ind_GPIO# [level]] (optional)[type event_force_ignore event_use_ext_gap ext_gap [gpio_wave]]
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap). If more than three parameters, it can set different or multiple features indicating by type(this is optional):
+
+	If type=1, it will set indication gpio and its level. And the parameter format will be (condition, GPIO#,gap and type,ind_GPIO#) or
+	(condition, GPIO#, gap, type, ind_GPIO# and level).
+
+	If type=2, it will set extend hscfg wakup method. And the parameter format will be (condition, GPIO#, gap, type, force_ignore,
+	use_ext_gap, ext_gap [gpio_wave]). gpio_wave parameter is optional and default value is 0(falling edge). Each bit of
+	event_force_ignore and event_use_ext_gap will be defined to one same event, and set one same event(same bit) in those two
+	parameters is not allowed. Set bit(s) in event_force_ignore means the event(s) will be forced ignore in firmware silently.
+	Set bit(s) in event_use_ext_gap mean the event(s) will use extend gap to inform host. Not set means not handle.
+
+	If type=3, it will set hs_wakeup_interval.
+
+        If no parameter provided, get is performed.
+
+	The usages of parameters for "hscfg" are the same as that for "hssetpara" command.
+
+hssetpara
+	This command is used to set host sleep parameters.
+
+	Usage:
+		mlanutl mlanX hssetpara condition [GPIO# [gap]] (optional)[type ind_GPIO# [level]] (optional)[type event_force_ignore event_use_ext_gap ext_gap [gpio_wave]] (optional)[type hs_wakeup_interval]
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap).If more than three parameters, it can set different or multiple features indicating by type and
+        the detailed usage is the same as hscfg above.
+
+	where Condition is:
+		bit 0 = 1   -- broadcast data
+		bit 1 = 1   -- unicast data
+		bit 2 = 1   -- mac event
+		bit 3 = 1   -- multicast data
+		bit 6 = 1  --  Wakeup when mgmt frame received.
+		Bit 31 = 1  --  Don't wakeup when IPV6 packet received.
+
+	The host sleep mode will be canceled if condition is set to -1. The default is 0x7.
+
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+	GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead).
+	The default is 0xff.
+
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff
+	for special setting (host acknowledge required) when GPIO is used to wakeup host.
+	The default is 200.
+
+	The host sleep set except for cancellation will be blocked if host sleep is
+	already activated.
+
+	where ind_GPIO# is the pin number of GPIO used to indicate wakeup source. The level on
+	this GPIO will indicate normal wakeup source or abnormal wakeup source.
+
+	where level is used to set level(0/1) on ind_GPIO# pin for indication normal wakeup source.
+	The opposite level will indicate abnormal wakeup source. The default value is 0.
+
+	where event_force_ignore is a bitmap,each bit represent one wakeup reason event. Set the bit means this
+	wakeup reason should be force ignored in firmware. Reset the bit means do not handle this reason.
+
+	where event_use_ext_gap is a bitmap, each bit represent one wakeup reason event. Set the bit means this
+	wakeup reason should use ext_gap to indicate host. Reset the bit means do not handle this reason.
+
+	where event_force_ignore and event_use_ext_gap have the same wakeup reason event definition of each bit:
+		bit 0  = 1     --Disconnect
+		bit 1  = 1     --GTK/iGTK rekey failure
+		bit 2  = 1     --Eapol
+		other bits     --Reserved
+	They should not set both for one same wakeup reason.
+
+	where ext_gap is the extend gap based on third parameter Gap. Only valid when use_ext_gap is used.
+	The total gap is (Gap + (x+1)*ext_gap). x means the bit number(start from 0) of this reason in use_ext_gap.
+
+	where gpio_wave is used to set GPIO wave level for hscfg extend. 0 means falling edge, 1 means rising edge.
+	This parameter is optional and default value is 0.
+
+	where hs_wakeup_interval is used to set host sleep wakeup interval and the type must set to 3 to indicate
+	this feature. And the value will round to the nearest multiple dtim*beacon_interval in fw. The unit is milliseconds.
+
+	Examples:
+		mlanutl mlan0 hssetpara -1           : Cancel host sleep mode
+		mlanutl mlan0 hssetpara 3            : Broadcast and unicast data
+		                                       Use GPIO and gap set previously
+		mlanutl mlan0 hssetpara 2 3          : Unicast data
+		                                       Use GPIO 3 and gap set previously
+		mlanutl mlan0 hssetpara 2 1 0xa0     : Unicast data
+		                                       Use GPIO 1 and gap 160 ms
+		mlanutl mlan0 hssetpara 2 0xff       : Unicast data
+		                                       Use interface (e.g. SDIO)
+		                                       Use gap set previously
+		mlanutl mlan0 hssetpara 4 3 0xff     : MAC event
+		                                       Use GPIO 3
+		                                       Special host sleep mode
+		mlanutl mlan0 hssetpara 1 0xff 0xff  : Broadcast data
+
+		mlanutl mlan0 hssetpara 2 1 0xa0 1 5 1 : Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=1 to set indication GPIO feature
+                                                       Use GPIO 5 to indicate wakeup source
+                                                       High level on GPIO 5 means this is a normal wakeup
+		mlanutl mlan0 hssetpara 2 1 0xa0 1 5   : Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=1 to set indication GPIO feature
+                                                       Use GPIO 5 to indicate wakeup source
+                                                       Use level set previously.
+
+		mlanutl mlan0 hssetpara 2 1 0xa0 2 0 0x1 10 1: Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=2 to set extend hscfg feature
+                                                       Force_ignore not used
+                                                       Disconnect will use extend gap to indicate host
+                                                       Use gap 170.
+                                                       Rising edge
+		mlanutl mlan0 hssetpara 2 1 0xa0 2 0x1 0 0 0: Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=2 to set extend hscfg feature
+                                                       Falling edge
+                                                       Force ignore Disconnect
+                                                       Extend gap not used
+                                                       Not used.
+                                                       Falling edge
+		mlanutl mlan0 hssetpara 2 1 0xa0 3 400:  Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=3 to set hs_wakeup_interval feature
+                                                       hs_wakeup_interval set to 400ms
+
+	Note: The parameters will be saved in the driver and be used when host suspends.
+              The ind_GPIO# and level parameters only work with specific board and firmware.
+
+mgmtfilter
+        This command is used to set management frame to wake up host when host suspend.
+
+        Usage:
+                mlanutl mlanX mgmtfilter <mgmtfilter.conf>
+
+        where <mgmtfilter.conf>
+                This conf file will set management frame catagory, action and frame mask.
+
+        Examples:
+                mlanutl mlan0 mgmtfilter mgmtfilter.conf
+
+auto_arp
+        This command is used to enable/disable auto arp response in host sleep mode.
+        No argument is used to get.
+
+        where value of n is:
+                0   -- Disable
+                1   -- Enable
+
+        Examples:
+                mlanutl mlan0 auto_arp 0           : Disable auto arp response from FW
+                mlanutl mlan0 auto_arp             : Get auto arp configuration status
+
+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).
+
+htstreamcfg
+	This command is used to set/get HT stream configuration.
+	The setting only takes effect in next association.
+
+	Usage:
+		mlanutl mlanX htstreamcfg [n]
+
+	where <n>
+		0x11: HT stream 1x1 mode
+		0x22: HT stream 2x2 mode
+
+	Examples:
+		mlanutl mlan0 htstreamcfg        : Get current setting
+		mlanutl mlan0 htstreamcfg 0x11   : Set HT stream 1x1 mode
+		mlanutl mlan0 htstreamcfg 0x22   : Set HT stream 2x2 mode
+
+httxbfcap
+	This command is used to set/get the TX beamforming capabilities.
+
+	Usage:
+		mlanutl mlanX httxbfcap [cap]
+
+	where the parameters are,
+		cap: TX beamforming capabilities
+			 Bit 0    : Implicit TX BF receiving capable
+			 Bit 1    : RX staggered sounding capable
+			 Bit 2    : TX staggered sounding capable
+			 Bit 3    : RX NDP capable
+			 Bit 4    : TX NDP capable
+			 Bit 5    : Implicit TX BF capable
+			 Bit 6-7  : Calibration
+			         0: - not supported
+			         1: - STA can respond to a calibration request using
+			              the CSI Report, but cannot initiate calibration
+			         2: - reserved
+			         3: - STA can both initiate and respond to a calibration request
+			 Bit 8    : Explicit CSI TX BF capable
+			 Bit 9    : Explicit non-compressed steering capable
+			 Bit 10   : Explicit compressed steering capable
+			 Bit 11-12: Explicit TX BF CSI feedback
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 13-14: Explicit non-compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 15-16: Explicit compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 17-18: Minimal grouping
+			         0: - no grouping (STA supports groups of 1)
+			         1: - groups of 1, 2
+			         2: - groups of 1, 4
+			         3: - groups of 1, 2, 4
+			 Bit 19-20: CSI number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 21-22: Non-compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 23-24: Compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 25-26: CSI max number of rows beamformer supported
+			         0: - single row of CSI
+			         1: - 2 rows of CSI
+			         2: - 3 rows of CSI
+			         3: - 4 rows of CSI
+			 Bit 27-28: Channel estimation capability
+			         0: - 1 space time stream
+			         1: - 2 space time streams
+			         2: - 3 space time streams
+			         3: - 4 space time streams
+			 Bit 29-31: Reserved
+
+	Examples:
+		mlanutl mlan0 httxbfcap             : Get the current TX BF capabilities
+		mlanutl mlan0 httxbfcap 0x0000001F  : Set the TX BF capabilities of the
+		                                     Implicit TX BF receiving capable,
+		                                     RX staggered sounding capable,
+		                                     TX staggered sounding capable,
+		                                     RX NDP capable and TX NDP capable
+
+httxbfcfg
+	This command is used to configure the TX beamforming options.
+	Note: Any new subcommand should be inserted in the second
+		argument and each argument of the sub command should be
+		separated by semicolon. For global configuration, the
+		arguments should be separated by space.
+
+	Usage:
+		mlanutl mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData/txSounding]"
+
+	where the parameters are,
+		action: TX beamforming action
+			0: Control global parameters for beamforming
+		        1: Performs NDP Sounding for PEER
+		        2: TX BF interval in milliseconds
+		        3: Enable/Disable beamforming/sounding for a particular peer
+		        4: TX BF SNR Threshold for peer
+		        .. <for new subcommand>
+		GlobalData: Global parameter arguments.
+		    It contains beamforming enable, sounding enable, FB type, snr_threshold
+		    sounding interval, Beamformig mode values seperated by space.
+		    Syntax:
+			mlanutl mlanX httxbfcfg <action>;<beamforming enable> <sounding enable> <FB type>
+			                       <snr_threshold>  <sounding interval> <Beamforming mode>
+		tsData: Trigger sounding for PEER specific arguments,
+		        it contains PEER MAC and status
+		interval: TX BF interval in milliseconds
+		txPeerData: Enable/Disable beamforming/sounding for the indicated peer,
+		          it contains PEER MAC, sounding, beamfoming options and FB type;
+		snrData: TX BF SNR Threshold for peer, it contains PEER MAC and SNR
+
+	Examples:
+		mlanutl mlan0 httxbfcfg "0"                          : Get current global configuration parameter
+		mlanutl mlan0 httxbfcfg "2;00:50:43:20:BF:64"        : Get the TX BF periodicity for a given peer
+		mlanutl mlan0 httxbfcfg "3"                          : Get the list of MAC addresses that have
+		                                                      beamforming and/or sounding enabled
+		mlanutl mlan0 httxbfcfg "4"                          : Get the list of PEER MAC, SNR tuples
+		                                                      programmed into the firmware.
+		mlanutl mlan0 httxbfcfg "0;0 0 3 10 500 5"           : Disable beamforming, sounding, set FB type
+		                                                      to 3, snr threshold to 10, sounding interval
+		                                                      to 500 ms and beamforming mode to 5
+		mlanutl mlan0 httxbfcfg "1;00:50:43:20:BF:64"        : Perform NDP Trigger sounding to peer
+		                                                      00:50:43:20:BF:64
+		mlanutl mlan0 httxbfcfg "2;00:50:43:20:BF:64;500"    : Set TX BF periodicity for peer 00:50:43:20:BF:64
+		                                                      to 500 milliseconds
+		mlanutl mlan0 httxbfcfg "3;00:50:43:20:BF:43;1;0;3"  : Enable beamforming, disable sounding and set
+		                                                      FB type to 3 for peer 00:50:43:20:BF:43
+		mlanutl mlan0 httxbfcfg "4;00:50:43:20:BF:24;43"     : Set TX BF SNR threshold to peer
+		                                                      00:50:43:20:BF:24 with SNR 43
+
+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-10: Reserved set to 0
+        Bit 9-8: Rx STBC set to 0x01
+        BIT9 BIT8  Description
+         0    0     No spatial streams
+         0    1     One spatial streams supported
+         1    0     Reserved
+         1    1     Reserved
+		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.
+
+inactivityto
+	This command is used to set/get the inactivity timeout value, which specifies
+	when WLAN device is put to sleep.
+
+	Usage:
+		mlanutl mlanX inactivityto <n> <m> <l> [k]
+
+	where the parameter are:
+		<n>: timeout unit in microseconds.
+		<m>: Inactivity timeout for unicast data.
+		<l>: Inactivity timeout for multicast data.
+		[k]: Inactivity timeout for new Rx traffic after PS notification to AP.
+
+	Examples:
+		mlanutl mlan0 inactivityto           : Get the timeout value
+		mlanutl mlan0 inactivityto 1000 2 3  : Set timeout unit to 1000 us (1 ms),
+		                                      inactivity timeout for unicast data is 2 ms,
+		                                      inactivity timeout for multicast data is 3 ms
+
+ipaddr
+	This command is used to set/get IP address.
+
+	Usage:
+		mlanutl mlanX ipaddr ["<op>;<ipaddr>"]
+
+	where <op>
+		0: Remove the IP address
+		bit 0: Set IP address for broadcast ARP filter, which will be auto enabled
+		       in next host sleep configuration
+		bit 1: Set IP address for auto broadcast ARP response
+
+	Examples:
+		mlanutl mlan0 ipaddr                 : Get current settings
+		mlanutl mlan0 ipaddr "0"             : Remove IP address
+		mlanutl mlan0 ipaddr "1;192.168.0.5" : Set IP address for ARP filter
+		mlanutl mlan0 ipaddr "3;192.168.0.6" : Set IP address for ARP filter
+		                                     : and auto ARP response
+
+linkstats
+	This command is used to get the link statistics from the firmware.
+
+	Usage:
+		mlanutl mlanX linkstats
+
+listeninterval
+	This command is used to set/get listen interval in assoc request.
+
+	Usage:
+		mlanutl mlanX listeninterval [l]
+
+	where the parameter:
+		[l]: Value of listen interval [Default 10]
+
+	Examples:
+		mlanutl mlan0 listeninterval     : Display Listen interval
+		mlanutl mlan0 listeninterval 1   : Set Listen interval to 1.
+
+macctrl
+	This command is used to set/get MAC control.
+	It's recommended to read the current setting first to avoid override issue.
+
+	Usage:
+		mlanutl mlanX macctrl [n]
+
+	where <n>
+		bit 0:  Rx enabled
+		bit 1:  Directed Filter enabled
+		bit 2:  LoopBack enabled
+		bit 3:  WEP enabled
+		bit 4:  EthernetII enabled
+		bit 5:  MultiCast enabled
+		bit 6:  BroadCast enabled
+		bit 7:  Promiscuous enabled
+		bit 8:  All MultiCast enabled
+		bit 9:  RTS/CTS enabled (0: CTS to self)
+		bit 10: Enforce Protection enabled
+		bit 11: Force 11N Protection enabled
+		bit 12: Rx 802.11 Packets enabled
+		bit 13: Ad-hoc g Protection enabled
+		bit 14: Reserved
+		bit 15: WEP Type
+		bit 16: BandWidth Indication in RTS enabled
+		bit 17: Dynamic BandWidth Indication Mode in RTS enabled
+		bit 18-31: Reserved
+
+	Examples:
+		mlanutl mlan0 macctrl           : Get current MAC control
+		mlanutl mlan0 macctrl 0x13      : Set Rx enabled and Directed Filter enabled and EthernetII enabled
+		mlanutl mlan0 macctrl 0x813     : Set Rx enabled and Directed Filter enabled and EthernetII enabled
+		                                  Force 11N Protection enabled
+
+mefcfg
+	This command is used to set MEF settings.
+
+	Usage:
+		mlanutl mlanX mefcfg <mef.conf>
+
+	Where the parameter is:
+		mef.conf : The configuration file specifying the MEF settings.
+
+	Example:
+		mlanutl mlan0 mefcfg config/mef.conf
+
+memrdwr
+	This command is used to read/write the adapter memory.
+
+	Usage:
+		mlanutl mlanX memrdwr <address> [value]
+
+	where the parameters are,
+		<address>:  memory address
+		[value]:    value to be written
+
+	Examples:
+		mlanutl mlan0 memrdwr 0x4cf70    : Read memory address 0x4cf70
+		mlanutl mlan0 memrdwr 0x80000000 0xffffffff
+		                                 : Write 0xffffffff to memory address 0x80000000
+
+miracastcfg
+	This command is used to set/get the miracast configuration.
+
+	Usage:
+	mlanutl mlanX miracastcfg [l] [m] [n]
+
+	where the parameters are,
+		[l]:    miracast mode
+				0: Disable
+				1: Source
+				2: Sink
+		[m]:    scan time per channel, in ms
+		[n]:    gap during two scans, in ms
+
+	Examples:
+		mlanutl mlan0 miracastcfg           : Get miracast configuration
+		mlanutl mlan0 miracastcfg 0         : Disable miracast configuration
+		mlanutl mlan0 miracastcfg 1 20 40   : Set miracast mode as source, with scan time
+	                                          20ms per channel and gap during two scans 40ms
+
+mgmtframectrl
+	This command is used to set/get registered frame type to passthrough.
+
+	Usage:
+		mlanutl mlanX mgmtframectrl [<mask>]
+		mlanutl uapX mgmtframectrl [<mask>]
+
+	Where the parameter is:
+		<mask>  : the bit mask of management frame reception.
+			: Bit 0 - Association Request
+			: Bit 1 - Association Response
+			: Bit 2 - Re-Association Request
+			: Bit 3 - Re-Association Response
+			: Bit 4 - Probe Request
+			: Bit 5 - Probe Response
+			: Bit 8 - Beacon Frames
+
+	Examples:
+		mlanutl mlan0 mgmtframectrl        : Get present mask
+		mlanutl mlan0 mgmtframectrl 0x0020 : Bit 5 is set, Forward probe response frames to application layer
+
+mgmtframetx
+	This command is used to send management frame.
+
+	Usage:
+		mlanutl mlanX mgmtframetx <mgmt_frame.conf>
+
+	Where the parameter is:
+		mgmt_frame.conf : The configuration file contains the management frame.
+
+	Examples:
+		mlanutl mlan0 mgmtframetx config/mgmt_frame.conf
+
+mpactrl
+	This command is used to set/get the Tx, Rx SDIO aggregation parameters.
+	Note: The parameters can be set only in disconnected state.
+
+	Usage:
+		mlanutl mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+
+	where the parameter are:
+		[tx_ena]: Enable/disable (1/0) Tx MP-A
+		[rx_ena]: Enable/disable (1/0) Rx MP-A
+		[tx_size]: Size of Tx MP-A buffer
+		[rx_size]: Size of Rx MP-A buffer
+		[tx_ports]: Max ports (1-16) for Tx MP-A
+		[rx_ports]: Max ports (1-16) for Rx MP-A
+	default values are 1 1 16384 32768 16 16
+	The MP-A may be disabled by default at build time if the MMC driver byte mode patch
+	is not available in kernel.
+
+	Examples:
+		mlanutl mlan0 mpactrl       : Get MP aggregation parameters
+		mlanutl mlan0 mpactrl 0 0
+		                           : Disable MP aggregation for Tx, Rx respectively
+		mlanutl mlan0 mpactrl 1 1 8192 8192 8 8
+		                           : Enable MP aggregation for Tx, Rx
+		                           : Set Tx, Rx buffer size to 8192 bytes
+		                           : Set maximum Tx, Rx ports to 8
+
+netmon
+    This command is used to set/get sniffer mode configuration.
+    Note: The channel and band config is optional. If not specified, or if
+    any STA/uAP/STA+uAP connection is active, sniffer activity will be started
+    on the current config set in the FW.
+    'rtap' monitor interface will be created on enabling sniffer activity and
+    should be made 'up' for capturing in a sniffer app.
+
+    Usage:
+        mlanutl <interface> netmon [<act> [<filter>]]
+        mlanutl mlanX netmon [<act> [<filter>] [<band> <chan> [offset]]]
+
+    Where the parameters are:
+        <interface> : mlanX, uapX
+        <act>	: (0) disable sniffer activity
+                : (1) enable sniffer activity
+
+        <filter> : network monitor fitler flag
+            bit 0: (1/0) enable/disable management frame
+            bit 1: (1/0) enable/disable control frame
+            bit 2: (1/0) enable/disable data frame
+            bit 3: (1/0) enable/disable frames destined to active connection only
+            bit 4: (1/0) enable/disable decrypted unicast data/mgmt frames
+
+        <band>   : 802.11 band
+            bit 0: B
+            bit 1: G
+            bit 2: A
+            bit 3: GN
+            bit 4: AN
+            bit 5: AC 2.4G
+            bit 6: AC 5G
+        <chan>   : channel to monitor
+
+        [offset] : secondary channel bandwidth
+            0 - Bandwidth 20Mhz
+            1 - HT Bandwidth 40Mhz sec channel above
+            3 - HT Bandwidth 40Mhz sec channel below
+            4 - VHT Bandwidth 80Mhz
+
+	Examples:
+        mlanutl mlan0 netmon             : Get the current sniffer mode configuration
+        mlanutl mlan0 netmon 0           : Disable network monitor activity
+        mlanutl uap0 netmon 1 7			 : Enable sniffer activity on current channel set in FW,
+                                           set filter data, control, management frame.
+        mlanutl mlan0 netmon 1 4 11 6    : Enable sniffer activity in absence of active connection,
+                                           set filter data frame, band B/G/GN and channel 6
+        mlanutl mlan0 netmon 1 7 20 64 1 : Enable sniffer activity in absence of active connection
+                                           set filter management, control and data frame, band A/AN,
+                                           channel 64 and secondary channel above
+        mlanutl uap0 netmon 1 0x0c	      : Enable sniffer activity, set filter data frames
+                                            destined to the active uAP connection only
+
+        mlanutl mlan0 netmon 1 0x1d       : Enable sniffer activity, set filter decrypted data and
+                                            management frames destined to the active STA connection
+                                            only
+
+offchannel
+	This command is used to set/cancel the offchannel configuration.
+	Note: This command only can be used when cfg80211 is enabled during load time.
+
+	Usage:
+		mlanutl mlanX offchannel [<l> <m> <n>]
+
+	where
+		<l>
+			0 : Cancel the offchannel configuration
+			1 : Set the offchannel configuration
+		<m>
+			The channel to configure
+		<n>
+			The duration for which to configure
+
+	Examples:
+		mlanutl mlan0 offchannel           : Get current offchannel status.
+		mlanutl mlan0 offchannel 0         : Cancel the offchannel configuration.
+		mlanutl mlan0 offchannel 1 3 5     : Configure channel 3 for 5 milliseconds.
+		mlanutl mlan0 offchannel 1 36 5000 : Configure channel 36 for 5000 milliseconds.
+
+otpuserdata
+	This command is used to get the OTP user data.
+
+	Where
+	<l> is <user_data_length>
+	<user_data_length> - This parameter specifies the length of OTP user data to be read
+
+	Examples:
+		mlanutl mlan0 otpuserdata 10         : Get the 10-byte OTP user data
+
+passphrase
+	This command is used to set/get passphrase for WPA-PSK/WPA2-PSK mode.
+
+	Where <l>
+		ASCII string for ssid/passphrase/psk.
+
+	1) "0;<ssid=valid ssid>" - This will get the passphrase, AKMP
+	   for specified ssid, if none specified then it will get all.
+
+	Example:
+		mlanutl mlan0 passphrase "0;ssid=marvell"
+
+	2) "1;<psk=64 byte hexpsk>;<passphrase=1-63 byte passphare>
+	   <ssid=valid ssid>" - Passphrase and psk cannot be provided for the same SSID.
+	   This command takes only one SSID at a time, If ssid= is present 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 ';' or '/' has to be used in an SSID then a '/' should be preceded
+	   to ';' or '/' as a escape.
+
+	Examples:
+		mlanutl mlan0 passphrase "1;ssid=mrvlAP;passphrase=abcdefgd"
+		mlanutl mlan0 passphrase "1;ssid=mrvl AP;psk=<64 bytes hexpsk>"
+
+		If user wants to input the ssid as "mrvl; AP" then command has to be
+		mlanutl mlan0 passphrase "1;ssid=mrvl/; AP;passphrase=abcdefgh"
+
+		If user wants to input the ssid as "//;" then command has to be
+		mlanutl mlan0 passphrase "1;ssid=/////;;passphrase=abcdefgh"
+
+	3) "2;<ssid=valid ssid>" - This will clear the passphrase
+	   for specified ssid, if none specified then it will clear all.
+
+	Examples:
+		mlanutl mlan0 passphrase "2;ssid=marvell"
+		mlanutl mlan0 passphrase "2"     : Clear all profiles and disable embedded supplicant
+
+pb_bypass
+	This command is used to get the By-passed TX packet from upper layer.
+
+	Usage:
+
+	mlanutl mlanX pb_bypass [data_1, data_2, ... data_n]
+
+	where value of data_1, data_2, ... data_n isBypass TX Data
+
+pmfcfg
+	This command is used to set/get management frame protection parameters.
+
+	Usage:
+		mlanutl mlanX pmfcfg <m> <n>
+
+	where
+		<m>: Management Frame Protection Capable (MFPC)
+			1: Management Frame Protection Capable
+			0: Management Frame Protection not Capable
+		<n>: Management Frame Protection Required (MFPR)
+			1: Management Frame Protection Required
+			0: Management Frame Protection Optional
+		Default setting is PMF not capable.
+		m = 0, n = 1 is an invalid combination
+
+        Examples:
+                mlanutl mlan0 pmfcfg            : Get PMF parameters
+                mlanutl mlan0 pmfcfg 1 0        : Set MFPC and make MFPR optional
+
+port_ctrl
+	This command is used to Set/Get Port Control mode. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 port_ctrl 1           : Enable Port Control mode
+		mlanutl mlan0 port_ctrl             : Get Port Control mode status
+
+powercons
+	This command is used to set the local transmit power constraint.
+	Value is in dbm unit. This command is only used for ad-hoc start.
+
+	Usage:
+		mlanutl mlanX powercons [n]
+
+	Examples:
+		mlanutl mlanX powercons          : get the current setting
+		mlanutl mlanX powercons 12       : set local power constraint to 12 dbm
+
+pscfg
+	This command is used to set/get PS configuration parameters.
+
+	Usage:
+		mlanutl mlanX pscfg [k] [d] [l] ...
+
+	Where the parameters:
+		[k]: Keep alive null packet interval (0: Unchanged, -1: Disable, n: Interval in seconds)
+		[d]: DTIM interval (    0: Unchanged,
+		                      1-5: Value,
+		                    65534: DTIM will be ignored, listen interval will be used,
+		                    65533: Closest DTIM to the listen interval period will be used )
+		[l]: Local listen interval (     0: Unchanged,
+		                                -1: Disable,
+		                              1-49: Value in beacon intervals,
+		                             >= 50: Value in TUs )
+		[a]: Ad-hoc awake period (0: Unchanged, 1-31: Beacon interval, 255: Firmware
+		                          will go to sleep after beacon send out)
+		[b]: Beacon miss timeout (0: Unchanged, 1-50: Value in milliseconds, 65535: Disable)
+		[p]: Delay to PS (0-65535: Value in milliseconds, default 1000ms)
+		[m]: PS mode (0: Unchanged, 1: Auto mode, 2: PS-Poll mode, 3: PS Null mode)
+	No change if parameters are not provided.
+
+	Examples:
+		mlanutl mlan0 pscfg              : Get all the current PS configuration settings
+		mlanutl mlan0 pscfg 3 4          : Set PS keep alive null packet interval to 3 seconds
+		                                   and DTIM interval to 4, all the other configurations
+		                                   are unchanged
+		mlanutl mlan0 pscfg 0 0xfffe 10 0 20
+		                                : Disable DTIM interval, set local listen interval to
+		                                  10 beacon intervals and beacon miss interval to 20,
+		                                  all the other configurations are unchanged
+		mlanutl mlan0 pscfg 0 0 0 0 0 50 : Set delay to PS to 50 ms, keep the others unchanged
+
+bcntimeoutcfg
+	This command is used to set Beacon timeout parameters.
+
+	Usage:
+		mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p]
+
+	Where the parameters:
+		[l]: Beacon miss timeout period Rx window (in ms)
+		[m]: Beacon miss timeout period (unit in beacon interval)
+		[o]: Beacon reacquire timeout period Rx window (unit in beacon interval)
+		[p]: Beacon reacquire timeout period (unit in beacon interval)
+		Please note that it would be better [m]+[p] not exceed 64.
+	Examples:
+		mlanutl mlan0 bcntimeoutcfg 10 30 2 30    : Set beacon timeout configure to
+		                                            Beacon miss timeout period Rx window      : 10 (ms)
+		                                            Beacon miss timeout period                : 30 (Beacon Interval)
+		                                            Beacon reacquire timeout period Rx window : 2  (Beacon Interval)
+		                                            Beacon reacquire timeout period           : 30 (Beacon Interval)
+
+psmode
+	This command is used to set/get the IEEE PS mode configuration.
+
+	Usage:
+		mlanutl mlanX psmode [l]
+
+	where the parameter:
+		[l]
+			0 : Disable IEEE PS mode
+			1 : Enable IEEE PS mode
+			<none>: Get IEEE PS mode
+
+	Examples:
+		mlanutl mlan0 psmode   : Get IEEE PS mode.
+		mlanutl mlan0 psmode 1 : Enable IEEE PS mode.
+
+qconfig
+	Send a WMM AC Queue configuration command to get/set/default params
+
+	Configure or get the parameters of a WMM AC queue. The command takes
+	an optional Queue Id as a last parameter.  Without the queue id, all
+	queues will be acted upon.
+
+	Usage:
+		mlanutl mlanX qconfig def [Queue Id: 0-3]
+		mlanutl mlanX qconfig get [Queue Id: 0-3]
+		mlanutl mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+
+qoscfg
+	This command sets WMM IE QOS info when an argument is given, and gets current WMM
+	IE QOS info when no argument is given.
+
+	Examples:
+		mlanutl mlanX qoscfg 0x0f        : Set WMM IE QOS info to 0x0f
+		mlanutl mlanX qoscfg             : Get WMM IE QOS info
+
+qstatus
+	This command retrieves the current status of the WMM queues. If WMM
+	  is enabled then it displays the information for each AC in a table.
+
+	Usage:
+		mlanutl mlanX qstatus
+
+radioctrl
+	This command is used to turn on/off the radio.
+	Note: The radio can be disabled only in disconnected state.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 radioctrl 1        : Turn the radio on
+		mlanutl mlan0 radioctrl          : Get radio status
+
+rdeeprom
+	This command is used to read the EEPROM contents of the card.
+
+	Usage:
+		mlanutl mlanX rdeeprom <offset> <length>
+
+	where the parameters are,
+		<offset>:   multiples of 4
+		<length>:   4-20, multiples of 4
+
+	Example:
+		mlanutl mlan0 rdeeprom 0 20      : Read 20 bytes of EEPROM data from offset 0
+
+reassoctrl
+	This command is used to turn on/off re-association in driver.
+
+	Usage:
+		mlanutl mlanX reassoctrl [n]
+
+	Where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 reassoctrl         : Get re-association status
+		mlanutl mlan0 reassoctrl 1       : Turn re-association on
+
+regioncode
+	This command is used to set/get the region code in the station.
+	Note: This command should be issued at beginning before band/channel selection
+	and association.
+
+	where value is 'region code' for various regions like
+	USA FCC, Canada IC, Europe ETSI, Japan ...
+	The special code (0xff) is used for Japan to support channel 1-14 in B/G/N mode.
+
+	Examples:
+		mlanutl mlan0 regioncode         : Get region code
+		mlanutl mlan0 regioncode 0x10    : Set region code to USA (0x10)
+	Note : in some case regioncode will be 0 after updated countycode or 80211d
+		i.e. mlanutl mlanX countrycode  (CA, JP, CN, DE, ES AT, BR, RU)
+		or uaputl.exe sys_cfg_80211d state 1 country (CA, JP, CN, DE, ES AT, BR, RU)
+		Please use cfp instead of it.
+
+regrdwr
+	This command is used to read/write the adapter register.
+
+	Usage:
+		mlanutl mlanX regrdwr <type> <offset> [value]
+
+	where the parameters are,
+		<type>:     1:MAC/SOC, 2:BBP, 3:RF, 5:CAU, 6:PSU
+		<offset>:   offset of register
+		[value]:    value to be written
+		Note:
+		BBP reg (type 2) 0xXZZZ:
+		X: 0=BBUD, 8=BBUA.
+		ZZZ: offset (0-0xFFF).
+		RF reg (type 3) 0xXYZZ:
+                 X   = Path ID (0-1)
+           	 Y   = Page Number (0-6) in selected Path
+           	 ZZ  = Register offset in selected path/page
+
+	Examples:
+		mlanutl mlan0 regrdwr 1 0xa060   : Read the MAC register
+		mlanutl mlan0 regrdwr 1 0xa794 0x80000000
+		                                 : Write 0x80000000 to MAC register
+
+rejectaddbareq
+	This command is used to set/get the conditions of rejecting addba request.
+
+	Usage:
+		mlanutl mlanX rejectaddbareq [conditions]
+		mlanutl uapX rejectaddbareq [conditions]
+
+	Where conditions are:
+		bit 0 = 1   -- reject the addba request when host sleep activated
+		others      -- reserved
+
+	Examples:
+		mlanutl mlan0 rejectaddbareq      : Get the reject addba request conditions
+		mlanutl mlan0 rejectaddbareq 0x1  : Reject the addba request
+		                                    when host sleep activated
+		mlanutl uap0 rejectaddbareq 0x1   : Reject the addba request
+		                                    when host sleep activated
+
+scancfg
+	This command is used to set/get scan configuration parameters.
+
+	Usage:
+		mlanutl mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+
+	where the parameters:
+		[t]: Scan Type (0: Unchanged, 1: Active, 2: Passive, default Active)
+		[m]: Scan Mode (0: Unchanged, 1: BSS, 2: IBSS, 3: Any, default Any)
+		[p]: Scan Probes (0: Unchanged, 1-4: Number of probes per channel, default 4)
+		[s]: Specific Scan Time (0: Unchanged, n: Value in ms, default 110 ms, max 500 ms)
+		[a]: Active Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 500 ms)
+		[b]: Passive Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 2000 ms)
+		[ext]: Extended scan (0: Legacy scan, 1: Extended scan)
+	No change if the parameter is 0 or the parameter is not provided.
+
+	Examples:
+		mlanutl mlan0 scancfg            : Get all the current scan configuration settings
+		mlanutl mlan0 scancfg 1 3        : Set scan type to active and scan mode to any,
+		                                   all the other scan configurations are unchanged
+		mlanutl mlan0 scancfg 0 1 2 200  : Set scan mode to BSS, number of probes to 2 and
+		                                   specific scan time to 200 ms, all the other scan
+		                                   configurations are unchanged
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanutl mlanX sdcmd52rw <function number> <register address> [value]
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+	Examples:
+		mlanutl mlan0 sdcmd52rw 1 3      : Read SDIO function 1 register 3
+		mlanutl mlan0 sdcmd52rw 1 1 0x3f : Write 0x3f to SDIO function 1 register 1
+
+sdcmd53rw
+	This command is used to issue a CMD53 read/write data in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanutl mlanX sdcmd53rw <func> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+
+	where the parameters are,
+		<func>:     function number (0/1/2/..)
+		<address>:  data address
+		<mode>:     byte mode/block mode (0/1)
+		<blksize>:  block size (32/64/../512, NA for byte mode)
+		<blknum>:   block number or byte number
+		<data1> ... <dataN>:  data for write
+
+	Note: The total data length is block size * block number for block mode
+	or byte number for byte mode. The max data length is 2000-byte.
+	For write the data pattern will be duplicated to data buffer.
+
+	Examples:
+		mlanutl mlan0 sdcmd53rw 0 0x8000 1 0x40 2
+		mlanutl mlan0 sdcmd53rw 1 0x10000 0 1 5 0x0a 0x0b 0x0c 0x0d 0x0e
+
+sdioclock
+	Turn On(1) or Off(0) the SDIO clock.
+
+	Usage:
+		mlanutl mlanX sdioclock 1 (on)
+		mlanutl mlanX sdioclock 0 (off)
+		mlanutl mlanX sdioclock (get the current clock state)
+
+setuserscan
+	Initiate a customized scan and retrieve the results
+
+	Usage:
+		mlanutl mlanX setuserscan [ARGS]
+
+	Where [ARGS]:
+	  ssid="[SSID]"            specify a SSID filter for the scan
+	  chan=[chan#][band][mode] where band is [a,b,g,n] and mode is
+	                           blank for unchange, or 'c' for active or 'p' for passive
+	  bssid=xx:xx:xx:xx:xx:xx  specify a BSSID filter for the scan
+	  wc="[WILDCARD SSID]"     specify a UNIX pattern matching filter (using *
+	                           and ?) for SSIDs found in a broadcast probe
+	  keep=[0 or 1]            keep the previous scan results (1), discard (0)
+	  dur=[scan time]          time to scan for each channel in milliseconds
+	  gap=[gap time]           Time gap between two scans in milliseconds
+	  probes=[#]               number of probe requests to send on each chan
+	                           for each broadcast probe required and each SSID
+	                           specific probe required (1-4)
+	  bss_type=[1,2,3]         BSS type: 1 (Infra), 2(Adhoc), 3(Any)
+          sort_by_ch               Sort by channel number in ascending order.
+                                   Default mode: Sort by Signal Strength in descending order.
+
+	Any combination of the above arguments can be supplied on the command line.
+	If the chan token is absent, a full channel scan will be completed by driver.
+	If the dur or probes tokens are absent, the driver default setting will be
+	used. The bssid and ssid fields, if blank, will produce an unfiltered scan.
+	It's allowed to input multiple ssid/wc entries, the max entry number is 10.
+	The type field will default to 3 (Any) and the keep field will default to 0
+	(Discard).
+
+	Examples:
+	1) Perform an active scan on channels 1, 6, and 11 in the 'g' band:
+		setuserscan chan=1g,6g,11g
+
+	2) Perform a passive scan on channel 11 for 20 ms:
+		setuserscan chan=11gp dur=20
+
+	3) Perform an active scan on channels 1, 6, and 11; and a passive scan on
+	   channel 36 in the 'a' band:
+		setuserscan chan=1g,6g,11g,36ap
+
+	4) Perform an active scan on channel 6 and 36 for specific SSID:
+		setuserscan chan=6g,36a ssid=TestAP1 ssid=TestAP2
+
+	5) Scan all available channels (B/G/N, A bands) for a specific BSSID, keep
+	   the current scan table intact, update existing or append new scan data:
+		setuserscan bssid=00:50:43:20:12:82 keep=1
+
+	6) Scan channel 6, for all infrastructure networks, sending two probe
+	   requests.  Keep the previous scan table intact. Update any duplicate
+	   BSSID/SSID matches with the new scan data:
+		setuserscan chan=6g bss_type=1 probes=2 keep=1
+
+	7) Scan channel 1 and 6, for all networks matching the Mrvl*AP
+	   or AP*Mrvl? patterns and for MrvlTst SSID.  Generate 3 broadcast
+	   probes for the patterns and 3 SSID specific probes for MrvlTst on
+	   both channel 1 and channel 6.
+		setuserscan chan=1g,6g probes=3 wc="Mrvl*AP" wc="AP*Mrvl?" ssid="MrvlTst"
+
+	8) Scan all the channels for specified band.
+		setuserscan chan=0g
+
+	9) Scan channel 1 and 6, send 3 probe requests, scan each channel for 40 ms
+	   with time gap of 50ms between 2 scans
+		setuserscan chan=1g,6g probes=3 dur=40 gap=50
+
+	All entries in the scan table (not just the new scan data when keep=1)
+	will be displayed upon completion by use of the getscantable ioctl.
+cancelscan
+	This command is used to cancel scan
+	Usage:
+		mlanutl mlanX cancelscan
+sleepparams
+	This command is used to set the sleepclock configurations
+
+	Usage:
+		mlanutl mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+
+	where:
+		p1 is Sleep clock error in ppm (0-65535)
+		p2 is Wakeup offset in usec (0-65535)
+		p3 is Clock stabilization time in usec (0-65535)
+		p4 is Control periodic calibration (0-2)
+		p5 is Control the use of external sleep clock (0-2)
+		p6 is reserved for debug (0-65535)
+
+	Examples:
+		mlanutl mlan0 sleepparams                      : Get current sleepclock configuration
+		mlanutl mlan0 sleepparams 10 1000 2000 1 0 128 : Set sleepclock configuration
+
+sleeppd
+	This command is used to configure the sleep period of the WLAN device.
+
+	Usage:
+		mlanutl mlanX sleeppd [<period>]
+
+	Where the parameter is:
+		period: sleep period in milliseconds. Range 10~60. 0 for disable.
+
+	Examples:
+		mlanutl mlan0 sleeppd            : Get sleep period configuration
+		mlanutl mlan0 sleeppd 10         : Set sleep period to 10 ms
+
+sysclock
+	This command is used to set/get system clocks in MHz.
+	The current system clock, configurable system clocks and all of the
+	supported system clocks will be returned if no parameter provided.
+
+	Examples:
+		mlanutl mlan0 sysclock           : Get system clocks
+		80 80 128 128 128 5 11 16 20 22 32 40 44 64 80 106 128 160 ...
+		(The current system clock is 80 MHz.
+		 The configurable system clocks of non-security, security, non-security
+		 A-MPDU and security A-MPDU are 80 MHz, 128 MHz, 128 MHz and 128 MHz.
+		 The supported system clocks are 5 MHz, 11 MHz, ..., 160 MHz, 182 MHz,
+		 213 MHz, 256 MHz, 320 Mhz, 366 MHz , ... . the Max system clocks is different
+		 for different chips, you could use this command to get the supported system clock)
+
+		mlanutl mlanX sysclock 80        : Set system clock in non-security mode
+		                                  to 80 MHz, no change for others
+		mlanutl mlanX sysclock 0 0 128   : Set system clock in non-security A-MPDU
+		                                  mode to 128 MHz, no changes for others
+
+host_tdls_config
+	This command is used to support channel switch and uapsd for host based tdls
+
+	Usage:
+		mlanutl mlanX host_tdls_config <host_tdls.conf>
+
+
+	Where the parameter is:
+		host_tdls.conf: The configuration file specifying to enable/disable uapsd/cs and related parameters.
+
+	Examples:
+		mlanutl mlan0 host_tdls_config config/host_tdls.conf
+			: enable or disable uapsd/cs, config the channel related ie, based on the configuration file.
+tdls_channel_switch
+	This command is used to send TDLS channel switch request.
+
+	Usage:
+		mlanutl mlanX tdls_channel_switch <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending TDLS channel switch command.
+
+	Examples:
+		mlanutl mlan0 tdls_channel_switch config/tdls.conf
+			: Send TDLS channel switch command, based on the configuration file.
+
+tdls_config
+	This command is used to enable/disable TDLS on device.
+
+	Usage:
+		mlanutl mlanX tdls_config <0/1>
+
+	Where the parameter is:
+		0: Enable TDLS.
+		1: Disable TDLS.
+
+	Examples:
+		mlanutl mlan0 tdls_config 0      : Disable TDLS
+		mlanutl mlan0 tdls_config 1      : Enable TDLS
+
+tdls_cs_params
+	This command is used to set TDLS channel switch params
+
+	Usage:
+		mlanutl mlanX tdls_cs_params <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file specifying the TDLS channel switch params.
+
+	Examples:
+		mlanutl mlan0 tdls_cs_params config/tdls.conf
+			: Set TDLS channel switch params, based on the configuration file.
+
+tdls_debug
+	This command is used for FW debug functionality and tests.
+
+tdls_disable_cs
+	This command is used to disable TDLS channel switch
+
+	Usage:
+		mlanutl mlanX tdls_disable_cs <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file to disable TDLS channel switch.
+
+	Examples:
+		mlanutl mlan0 tdls_disable_cs config/tdls.conf
+			: Disable TDLS channel switch, based on the configuration file.
+
+tdls_discovery
+	This command is used to request TDLS discovery.
+
+	Usage:
+		mlanutl mlanX tdls_discovery <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file to request TDLS discovery.
+
+	Examples:
+		mlanutl mlan0 tdls_discovery config/tdls.conf
+			: Request TDLS discovery based on the configuration file.
+
+tdls_link_status [peer_mac_address]
+	This command is used to get link information about TDLS links or
+    a TDLS link correponding to peer mac address.
+
+	Usage:
+		mlanutl mlanX tdls_link_status <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file to send TDLS command to get current link status.
+
+	Examples:
+		mlanutl mlan0 tdls_link_status config/tdls.conf
+			: Send TDLS command to get current link status based on the configuration file.
+
+tdls_powermode
+	This command is used to send TDLS powermode request.
+
+	Usage:
+		mlanutl mlanX tdls_powermode <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending TDLS powermode command.
+
+	Examples:
+		mlanutl mlan0 tdls_powermode config/tdls.conf
+			: Send TDLS powermode (either 0:Active, 1:PowerSave) command, based on the configuration file.
+
+tdls_setinfo
+	This command is used for setting the capabilities of the TDLS station.
+
+	Usage:
+		mlanutl mlanX tdls_setinfo <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file specifying the capabilities of the TDLS station.
+
+	Examples:
+		mlanutl mlan0 tdls_setinfo config/tdls.conf
+			: Set capabilities of the TDLS station, based on the configuration file.
+
+tdls_setup
+	This command is used to send TDLS setup request.
+
+	Usage:
+		mlanutl mlanX tdls_setup <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending TDLS setup request.
+
+	Examples:
+		mlanutl mlan0 tdls_setup config/tdls.conf
+			: Send TDLS setup request, based on the configuration file.
+
+tdls_stop_channel_switch
+	This command is used to send stop TDLS channel switch request.
+
+	Usage:
+		mlanutl mlanX tdls_stop_channel_switch <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending stop TDLS channel switch command.
+
+	Examples:
+		mlanutl mlan0 tdls_stop_channel_switch config/tdls.conf
+			: Send stop TDLS channel switch command, based on the configuration file.
+
+tdls_teardown
+	This command is used to send TDLS teardown request.
+
+	Usage:
+		mlanutl mlanX tdls_teardown <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for requesting teardown of TDLS link.
+
+	Examples:
+		mlanutl mlan0 tdls_teardown config/tdls.conf
+			: Request teardown of TDLS link, based on the configuration file.
+
+thermal
+	This command is used to get the current thermal reading.
+
+	Examples:
+		mlanutl mlan0 thermal            : Get thermal reading
+
+ts_status
+	This command queries the FW for the status of TSIDs 0 through 7
+	  configured via call admission control and displays the results in a
+	  table.
+
+	Usage:
+		mlanutl mlanX ts_status
+
+tsf
+	Get the TSF timer value for the station. Station maintains a TSF timer with
+	modulus 2^64 counting in increments of microseconds.
+
+	Usage:
+		mlanutl mlanX tsf
+
+txaggrctrl
+	This command is used to enable/disable TX AMPDU on infra link when TDLS link is established
+
+	Usage:
+		mlanutl mlanX txaggrctrl [m]
+
+	Where:
+		[m]: 1 to enable TX AMPDU on infra link; 0 to disable TX AMPDU on infra link
+
+	Examples:
+		mlanutl mlan0 txaggrctrl	: Get current TX AMPDU status on infra link
+		mlanutl mlan0 txaggrctrl 0	: Disable TX AMPDU on infra link
+		mlanutl mlan0 txaggrctrl 1	: Enable TX AMPDU on infra link
+
+	Note:
+		The set command only works when TDLS link is established.
+
+txbufcfg
+	This command can be used to get current buffer size.
+
+	eg:
+	mlanutl mlanX txbufcfg 	  - This will display the current buffer size.
+
+	Note:- The actual tx buf size will depends on AP's capability and max transmit buffer size.
+
+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.
+
+	Where
+	[l] is <format>
+	<format> - This parameter specifies the data rate format used in this command
+		0:    LG
+		1:    HT
+		2:    VHT
+		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
+	[n] is <nss>
+	<nss> - This parameter specifies the NSS. It is valid only for VHT
+	If <format> is 2 (VHT),
+		1	NSS1
+		2	NSS2
+
+	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 0xff     : Disable fixed rate and uses auto rate
+
+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.
+
+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.
+
+opermodecfg
+	This command is used to set and get 11ac Operating Mode Notification configuration.
+
+	where <m> is <bw>
+	<bw> - This is the channel width setting for the opermodecfg
+		1: 20MHz
+		2: 40MHz
+		3: 80MHz
+		4: 160MHz or 80+80MHz
+
+	where <n> is <nss>
+	<nss> - This parameter specifies the nss that the STA can receive.
+		1: NSS1
+		2: NSS2
+		3: NSS3
+		4: NSS4
+		5: NSS5
+		6: NSS6
+		7: NSS7
+		8: NSS8
+
+wakeupreason
+	This command is used to get the host sleep wakeup reason.
+
+	Usage:
+		mlanutl mlanX wakeupreason
+		mlanutl uapX wakeupreason
+	Examples:
+		mlanutl mlan0 wakeupreason        : Get the host sleep wakeup reason
+		mlanutl uap0 wakeupreason         : Get the host sleep wakeup reason
+		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
+		8:  Control frame matched
+		9:  Management frame matched
+		Others: reserved. (0)
+
+warmreset
+	This command is used for warm reset of the interface.
+
+	Usage:
+		mlanutl mlanX warmreset
+
+wpssession
+	This command is used to control wps session. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 wpssession 1           : Enable wpssession
+		mlanutl mlan0 wpssession             : Get wpssession status
+
+wmmcfg
+	This command is used to control WMM. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 wmmcfg 1           : Enable WMM
+		mlanutl mlan0 wmmcfg             : Get WMM status
+
+wmmparamcfg
+	This command is used to configure WMM paramameters.
+
+	Usage:
+		mlanutl mlanX wmmparamcfg [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+                                          [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+                                          [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+                                          [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+
+	The supported option are:
+           AC_BE: 0
+           AC_BK: 1
+           AC_VI: 2
+           AC_V0: 3
+           AIFSN: AIFSN value
+           ECW_MAX: ECW max
+           ECW_MIN: ECW min
+           TX_OP: TXOP Limit
+           empty - Get current WMM parameters
+
+        Example:
+        mlanutl mlanX wmmparamcfg 0 3 10 4 0
+           Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        mlanutl mlanX wmmparamcfg 1 7 10 4 0
+           Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        mlanutl mlanX wmmparamcfg 2 2 4 3 94
+           Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+
+        mlanutl mlanX wmmparamcfg 3 2 3 2 47
+           Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        mlanutl mlanX wmmparamcfg
+            Get current WMM parameters
+
+        mlanutl mlanX wmmparamcfg 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+wwscfg
+	This command is used to set/get the WWS (World Wide Safe) mode.
+
+	where value of m is:
+		0       -- Disable WWS mode (default)
+		1       -- Enable WWS mode
+
+	Examples:
+		mlanutl mlan0 wwscfg             : Get WWS mode
+		mlanutl mlan0 wwscfg 1           : Enable WWS mode
+		mlanutl mlan0 wwscfg 0           : Disable WWS mode
+
+mc_cfg
+	This command is used to set/get the channel time.
+
+	Usage:
+		mlanutl mlanX mc_cfg [n]
+
+	where <n> :  Channel time in microseconds.
+
+	Examples:
+		mlanutl mlanX mc_cfg			: Get Channel time and buffer weight.
+		mlanutl mlanX mc_cfg 10000		: Set Channel time to 10000us.
+
+mc_policy
+        This command is used to set/get the multi-channel policy.
+	Note: This is a device specific command. Hence, setting on one interface is
+		reflected on all other interfaces.
+
+        Usage:
+                mlanutl mlanX mc_policy [n]
+
+        where <n> :  Multi-channel policy
+
+        Examples:
+                mlanutl mlanX mc_policy			: Get multi-channel policy setting.
+                mlanutl mlanX mc_policy 1		: Set multi-channel policy to 1.
+                mlanutl mlanX mc_policy 0		: Disable multi-channel policy
+
+mc_cfg_ext
+    This command is used to set/get the drcs parameters.
+
+    Usage:
+        mlanutl mlanX mc_cfg_ext [c] [s] [u] [m] <a> <b> <d> <e>
+
+    where:
+    channel index0:
+        [c] :  chantime(in TU)
+        [s] :  switchtime(in TU)
+        [u] :  undozetime(in TU)
+        [m] :  mode :0x0 --- PM1(default)
+                     0x1 --- Null2Self
+    channel index1:
+        <a> :  chantime(in TU)
+        <b> :  switchtime(in TU)
+        <d> :  undozetime(in TU)
+        <e> :  mode :0x0 --- PM1(default)
+                     0x1 --- Null2Self
+    Note:
+        channel index0: the first channel
+        channel index1: the second channel
+        undozetime should be less than other channel's switchtime
+        If want to set two channels the same parameters, just ignore the last four parameters and
+        use [c] [s] [u] [m] to set.
+    Examples:
+        mlanutl mlanX mc_cfg_ext                        : Get the drcs parameters for two channels.
+        mlanutl mlanX mc_cfg_ext 15 10 5 0              : Set two channels:channeltime 15TU, switchtime 10TU, undozetime 5TU, mode PM1
+        mlanutl mlanX mc_cfg_ext 15 10 5 0 25 15 9 0    : Set channel index0: channeltime 17TU, switchtime 10TU, undozetime 5TU, mode PM1;
+                                                        set channel index1: channeltime 25TU, switchtime 15TU, undozetime 9TU, mode PM1.
+
+cfg_noa
+	This is used to get/set P2P NoA (Notice of Absence) parameters only for P2P GO.
+
+	Usage:
+		mlanutl p2pX cfg_noa [h] [i] [j] [k] [l]
+
+	where:
+		[h] : noa_enable : 1/0 Set to 1 to enable NoA, 0 to disable NoA.
+		[i] : index      : 0 - 255 Identifies an instance of NoA timing.
+		[j] : count      : 1 - 255 Indicates the number of absence intervals.
+				   255 means a continuous schedule.
+		[k] : duration   : Indicates the maximum duration in units of microseconds
+				   that P2P GO can remain absent following the start of
+				   a NoA interval.
+		[l] : interval   : Indicates the length of the NoA interval in units of
+				   microseconds.
+
+        Examples:
+                mlanutl p2pX cfg_noa						: Get noa configuration.
+                mlanutl p2pX cfg_noa 1 1 255 50 100			: Set noa configuration.
+
+cfg_opp_ps
+	This is used to get/set P2P OPP-PS parameters only for P2P GO.
+
+	Usage:
+		mlanutl p2pX cfg_opp_ps [m] [n]
+
+	where:
+		[m] : ps_enable  : 1/0 Set to 1 to indicate P2P GO is using opportunistic
+				   power save. Set to 0 if opportunistic power save is disabled.
+		[n] : ct_window  : A period of time in TU after a TBTT during which P2P GO
+				   is present. 0 indicates that there shall be no
+				   CTWindow (Client Traffic Window).
+
+        Examples:
+                mlanutl p2pX cfg_opp_ps					: Get noa configuration.
+                mlanutl p2pX cfg_opp_ps 1 7				: Set noa configuration.
+
+rxpktcoal_cfg
+	This is used to get/set RX packet coalescing paramters
+	Usage:
+		mlanutl mlanX rxpktcoal_cfg [m] [n]
+
+	where:
+        [m]: pkt_threshold: count after which packets would be sent to host. Valid values 1-7
+        [n]: delay: timeout in ms after which packets would be sent to host. Valid values 1-4
+        Coalescing is disabled if both or either of packet_thershold and delay is zero
+
+        RX packet coalescing parameters can be changed only when device is in
+        idle state i.e. all interfaces are disconnected.
+
+get_sensor_temp
+        This command is used to get SOC temperature
+        Usage:
+                mlanutl mlanX get_sensor_temp
+
+indrstcfg
+    This command is used to set/ get independent reset mode configuration
+
+    Usage :
+            mlanutl <interface> indrstcfg <ir_mode> [gpio_pin]
+
+            interface : mlanX, uapX
+            ir_mode   : 0 -- Disable
+                        1 -- Enable out band reset, disable in band
+                        2 -- Enable in band, disable out band
+            gpio_pin  : 255 -- Default pin for reset
+                        any other number for changing the gpio for reset.
+
+   Example :
+            mlanutl mlan0 indrstcfg 1 255   : Set default pin on interface mlan0 as reset pin
+            mlanutl mlan0 indrstcfg 0       : Disable the gpio 17 as reset pin on interface mlan0
+            mlanutl mlan0 indrstcfg         : Get the status and the pin used for reset pin
+            mlanutl mlan0 indrstcfg 2       : Enable in band reset mode
+
+    This command is used to set FW wakeup method and GPIO pin
+    Usage :
+            mlanutl <interface> fwwakeupmethod <method> <GPIO_pin>
+            interface : mlanX
+            method:
+                        1       -- Firmware wakeup through the interface command interrupt
+                                -- (default setting for SDIO/PCIe/USB)
+                        2       -- Firmware wakeup through the GPIO pin
+            GPIO_pin:  If firware wakeup throug GPIO pin, [g] is GPIO pin number
+    Example :
+            mlanutl mlan0 fwwakeupmethod     : Get current wakeup method
+            mlanutl mlan0 fwwakeupmethod 1   : Set wakeup method is interface method
+            mlanutl mlan0 fwwakeupmethod 2 5 : Set wakeup method is GPIO method and GPIO pin is 5.
+
+robustcoex
+    This command is used to set robust coex.
+
+    Usage :
+            mlanutl <interface> robustcoex <gpiocfg> [Enable/Disable] [gpionum] [gpiopolarity]
+            Enable/Disable : 0 -- Disable ; 1 -- Enable
+            gpionum : Number of gpio
+            gpiopolarity : polarity of gpio
+
+    Example :
+            mlanutl mlan0 robustcoex gpiocfg 1 4 1 : Enable robustcoex gpio, set gpionum to 4 and gpiopolarity to 1
+            mlanutl mlan0 robustcoex gpiocfg 0     : Disable robustcoex gpio
+
+keep_connect
+    This command is used to refuse disconnect
+
+    Usage :
+            mlanutl <interface> keep_connect [Enable/Disable]
+            Enable/Disable : 0 -- Disable ; 1 -- Enable
+
+    Example :
+            mlanutl mlan0 keep_connect 1 : Enable keep connect
+            mlanutl mlan0 keep_connect 0 : Disable keep connect
+ctrldeauth
+    This command is used to set/get firmware ctrldeauth setting
+    Usage :
+            mlanutl uapX ctrldeauth <n>
+
+    Where value of n is :
+            0 -- Firmware will use default behavior
+            1 -- Firmware will not send deauth packet when uap move to another channel.
+
+    Example :
+            mlanutl uap0 ctrldeauth   : Get current setting
+            mlanutl uap0 ctrldeauth   : Firmware will not send deauth packet when uap move to different channel.
+
+bootsleep
+    This command is used to set and get boot sleep configure.
+
+    Usage :
+            mlanutl mlanX/uapX bootsleep <enable>
+            <enable> :  enable boot sleep
+                     :  0 - disable boot sleep
+                     :  1 - enable boot sleep
+
+    Example :
+            mlanutl mlan0/uap0 bootsleep 1       : Enable boot sleep
+            mlanutl mlan0/uap0 bootsleep         : Get boot sleep configure
+
+
+===============================================================================
diff --git a/wlan_sd8897/README_OPENWRT b/wlan_sd8897/README_OPENWRT
new file mode 100644
index 0000000..90a6722
--- /dev/null
+++ b/wlan_sd8897/README_OPENWRT
@@ -0,0 +1,356 @@
+=================================================================================
+        U S E R  M A N U A L  F O R  OpenWrt
+
+This section describes detailed steps to add Marvell Wireless NIC (sdio/usb/pcie)
+driver to OpenWrt build system.
+
+Add marvell driver (sdio/usb/pcie) to OpenWrt build system.
+
+1. Go to the openwrt source code folder
+2. make menuconfig
+	choose x86 platform
+	other general openwrt configurations please refer to:
+	https://wiki.openwrt.org/doc/howto/build
+3. After make menuconfig
+	make sure that following configurations are set in .config
+	CONFIG_PACKAGE_hostapd=y
+	CONFIG_PACKAGE_hostapd-common=y
+	CONFIG_PACKAGE_kmod-cfg80211=y
+4. Go to the openwrt source code folder and Compile openwrt BSP
+	make V=s [-j[number]]
+5. After the first time compiling, openwrt/dl folder will be created
+   , related packages will be downloaded during compiling, so you need
+   network access as long as you need to compile openwrt BSP.
+6. Go to the openwrt source code folder: openwrt/dl/
+7. Find compat-wireless-xxxx-xx-xx.tar.bz2, and uncompress the package
+8. Go to compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/
+9. Modify compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/Kconfig
+
+	source "drivers/net/wireless/marvell/libertas/Kconfig"
+	source "drivers/net/wireless/marvell/libertas_tf/Kconfig"
+	source "drivers/net/wireless/marvell/mwifiex/Kconfig"
+	+source "drivers/net/wireless/marvell/mrvl-pcie/Kconfig"
+	+source "drivers/net/wireless/marvell/mrvl-sd8xxx/Kconfig"
+	+source "drivers/net/wireless/marvell/mrvl-usb/Kconfig"
+
+10. Modify compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/Makefile
+
+	obj-$(CPTCFG_LIBERTAS_THINFIRM)	+= libertas_tf/
+	obj-$(CPTCFG_MWIFIEX)	+= mwifiex/
+	+obj-$(CPTCFG_MRVL_PCIE)  += mrvl-pcie/
+	+obj-$(CPTCFG_MRVL_SD8XXX) += mrvl-sd8xxx/
+	+obj-$(CPTCFG_MRVL_USB) += mrvl-usb/
+
+11. Go to compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/
+12. mkdir (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)
+13. copy (pcie/sdio/usb)/wlan_src/* to (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)
+14. Go to mrvl-pcie/mrvl-sd8xxx/mrvl-usb
+15. Add new Kconfig:
+	mrvl-pcie/Kconfig
+
+	+config MRVL_PCIE
+	+	tristate "Marvell Wireless Driver for PCIE 8997"
+	+	depends on m
+	+	depends on PCI
+	+	depends on CFG80211
+	+	depends on WIRELESS_EXT
+	+	---help---
+	+	  This adds support for wireless adapters based on Marvell
+	+	  pcie 8997 chipsets with PCIe interface.
+	+
+	+	  If you choose to build it as a module, it will be called
+	+	  pcie8xxx.
+
+	mrvl-sd8xxx/Kconfig
+
+	+config MRVL_SD8XXX
+	+	tristate "Marvell sdio 802.11n/802.11ac Wireless cards"
+	+	depends on m
+	+	depends on MMC
+	+	depends on CFG80211
+	+	depends on WIRELESS_EXT
+	+	---help---
+	+	  A driver for Marvell sdio 802.11n/802.11ac Wireless cards.
+
+	mrvl-usb/Kconfig
+
+	+config MRVL_USB
+	+	tristate "Marvell sdio 802.11n/802.11ac Wireless cards"
+	+	depends on m
+	+	depends on USB
+	+	depends on CFG80211
+	+	depends on WIRELESS_EXT
+	+	---help---
+	+	A driver for Marvell sdio 802.11n/802.11ac Wireless cards.
+
+16. Open moal_main.h under (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlinux/
+
+	find #define COMPAT_VERSION_CODE KERNEL_VERSION_CODE(x, x, x)
+	modify (x, x, x) to the kernel version code of backports/compat-wireless package
+
+	backported kernel version code could be found in
+	compat-wireless-xxxx-xx-xx/version as following
+
+	'BACKPORTED_KERNEL_VERSION="v4.4-rc5-1913-gc8fdf68"'
+	v4.4 means KERNEL_VERSION(4, 4, 0)
+
+17. Modify (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/Makefile
+
+	# OpenWrt support
+	-CONFIG_OPENWRT_SUPPORT=n
+	+CONFIG_OPENWRT_SUPPORT=y
+
+	...
+
+	#############################################################################
+	# Select Platform Tools
+	#############################################################################
+
+	MODEXT = ko
+	-ccflags-y += -I$(M)/mlan
+	+ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan
+	ccflags-y += -DLINUX
+
+
+	ifeq ($(CONFIG_EMBEDDED_SUPP_AUTH), y)
+	-ccflags-y += -I$(M)/mlan/esa
+	-ccflags-y += -I$(M)/mlan/esa/common
+	+ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan/esa
+	+ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan/esa/common
+	endif
+
+18. compress compat-wireless-xxxx-xx-xx to its original .tar.bz2 format
+19. Go to the openwrt source code folder: openwrt/package/kernel/mac80211/
+20. Modify openwrt/package/kernel/mac80211/Makefile.
+
+	PKG_DRIVERS = \
+		adm8211 \
+		ath ath5k ath9k ath9k-common ath9k-htc ath10k \
+		b43 b43legacy \
+		carl9170 \
+		hermes hermes-pci hermes-pcmcia hermes-plx\
+		iwl-legacy iwl3945 iwl4965 iwlwifi \
+		lib80211 \
+		libipw ipw2100 ipw2200 \
+		libertas-sdio libertas-usb libertas-spi \
+		mac80211-hwsim \
+		mt7601u \
+		mwl8k mwifiex-pcie \
+		+mrvl-pcie \
+		+mrvl-sd8xxx \
+		+mrvl-usb \
+		p54-common p54-pci p54-spi p54-usb \
+		rt2x00-lib rt2x00-pci rt2x00-usb \
+		rt2400-pci rt2500-pci rt2500-usb \
+
+	...
+
+	+define KernelPackage/mrvl-pcie
+	+  $(call KernelPackage/mac80211/Default)
+	+  TITLE:=Marvell pcie wireless driver
+	+  URL:=http://wireless.kernel.org/en/users/Drivers/mwifiex
+	+  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT
+	+  FILES:= \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/mlan.ko \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/pcie8xxx.ko
+	+  AUTOLOAD:=$(call AutoProbe,mrvl-pcie)
+	+endef
+
+	+define KernelPackage/mrvl-pcie/description
+	+ Kernel modules for Marvell pcie 802.11n/802.11ac PCIe Wireless cards
+	+endef
+
+	+define KernelPackage/mrvl-sd8xxx
+	+  $(call KernelPackage/mac80211/Default)
+	+  DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT
+	+  TITLE:=Marvell sdio Wireless Driver
+	+  FILES:= \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/mlan.ko \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/sd8xxx.ko
+	+  AUTOLOAD:=$(call AutoProbe, mrvl-sd8xxx)
+	+endef
+
+	+define KernelPackage/mrvl-sd8xxx/description
+	+ Kernel modules for Marvell sdio 802.11n/802.11ac Wireless cards
+	+endef
+
+	+define KernelPackage/mrvl-usb
+	+  $(call KernelPackage/mac80211/Default)
+	+  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
+	+  TITLE:=Marvell usb Wireless Driver
+	+  FILES:= \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/mlan.ko \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/usb8xxx.ko
+	+  AUTOLOAD:=$(call AutoProbe, mrvl-usb)
+	+endef
+
+	+define KernelPackage/mrvl-usb/description
+	+ Kernel modules for Marvell usb 802.11n/802.11ac Wireless cards
+	+endef
+
+	...
+
+	config-$(call config_package,mwl8k) += MWL8K
+	config-$(call config_package,mwifiex-pcie) += MWIFIEX MWIFIEX_PCIE
+	+config-$(call config_package,mrvl-pcie) += MRVL_PCIE
+	+config-$(call config_package,mrvl-sd8xxx) += MRVL_SD8XXX
+	+config-$(call config_package,mrvl-usb) += MRVL_USB
+	config-$(call config_package,rtl8180) += RTL8180
+	config-$(call config_package,rtl8187) += RTL8187
+
+	...
+
+	$(eval $(call KernelPackage,mwl8k))
+	$(eval $(call KernelPackage,mwifiex-pcie))
+	+$(eval $(call KernelPackage,mrvl-pcie))
+	+$(eval $(call KernelPackage,mrvl-sd8xxx))
+	+$(eval $(call KernelPackage,mrvl-usb))
+	$(eval $(call KernelPackage,p54-common))
+
+OpenWrt configuration
+21. Go to OpenWrt srouce code folder
+22. Make menuconfig
+
+   select one of the newly added marvell driver
+	│-> Kernel modules
+	│	-> Wireless Drivers
+	|		->mrvl-pcie
+	|		->mrvl-sd8xxx
+	|		->mrvl-usb
+
+23. Other general configurations, please refer to the https://wiki.openwrt.org/doc/howto/build
+24. after menucofig make soure that following configurations are seletect
+
+	CONFIG_PACKAGE_hostapd=y
+	CONFIG_PACKAGE_hostapd-common=y
+	CONFIG_PACKAGE_kmod-cfg80211=y
+
+	Go to openwrt folder and re-build openwrt BSP
+	make V=s [-j[number]]
+
+	After openwrt BSP is successfully build, kernel modules could be found
+	both in the build folder and the running OS once openwrt is boot up.
+	kernel modules will be written to u-disk while openwrt img is burned to u-disk.
+
+	kernel modules in openwrt build dir:
+	openwrt/build_dir/target-x86_64_uClibc-0.9.33.2/linux-x86_64/compat-wireless-2016-01-10/
+	ipkg-x86_64/kmod-mrvl-(usb/sd8xxx/pcie)/lib/modules/3.18.45/
+
+	kernel modules in openwrt running OS:
+	/lib/modules/xx.xx.xx/
+
+25. To support SDIO card in OpenWrt x86 platforma
+	Add following kernel configurations for OpenWrt
+	Go to OpenWrt source code foler
+
+	make kernel_menuconfig
+
+	Device Drivers---->
+		--- MMC/SD/SDIO card support
+                  [ ]   MMC debugging
+                  [ ]   MMC host clock gating
+                  *** MMC/SD/SDIO Card Drivers ***
+                  < >   MMC block device driver
+                  < >   SDIO UART/GPS class support
+                  < >   MMC host test driver
+                  *** MMC/SD/SDIO Host Controller Drivers ***
+                  <*>   Secure Digital Host Controller Interface support
+                  <*>   SDHCI support on PCI bus
+                  [ ]     Ricoh MMC Controller Disabler
+                  < >   SDHCI platform and OF driver helper
+                  < >   Winbond W83L51xD SD/MMC Card Interface support
+                  < >   TI Flash Media MMC/SD Interface support
+                  < >   ENE CB710 MMC/SD Interface support
+                  < >   VIA SD/MMC Card Reader Driver
+                  < >   Renesas USDHI6ROL0 SD/SDIO Host Controller support
+
+	Compile OpenWrt using Make V=s, then write openwrt img to u-disk and boot up
+
+26. Bring up marvell wireless NIC on OpenWrt system
+
+	copy pcie/sdio/usb firmware to /lib/firmware/mrvl folder
+	On OpenWrt running OS
+	scp usrname@<target_pc ip address>:/path/firmware.bin /lib/firmware/mrvl
+
+	Another way is to add firmware binary to OpenWrt source code
+
+27. load marvell pcie/sdio/usb driver modules
+
+    End with Marvell Wirelss NIC card bring up on OpenWrt
+
+=======================================================================================================
+If firmware is copied to OpenWrt via scp, following steps could be ignored.
+28. Add firmware binary in OpenWrt
+	Copy pcie/usb/sdio firmware to folder:
+	openwrt/build_dir/target-x86_64_uClibc-0.9.33.2/linux-firmware-52442afee9907bc32a058f22bb3295d040677c26/mrvl/
+29. Go to penwrt/package/firmware/linux-firmware
+	Modify marvell.mk as following
+
+	+Package/mrvl-pcie-firmware = $(call Package/firmware-default,Marvell PCIE8997 firmware)
+	+define Package/mrvl-pcie-firmware/install
+	+	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+	+	$(INSTALL_DATA) \
+	+		$(PKG_BUILD_DIR)/mrvl/pcieusb8997_combo_v4.bin \
+	+		$(1)/lib/firmware/mrvl/
+	+endef
+	+$(eval $(call BuildPackage,mrvl-pcie-firmware))
+
+	+Package/mrvl-sd8xxx-firmware = $(call Package/firmware-default,Marvell SDIO8997 firmware)
+	+define Package/mrvl-sd8xxx-firmware/install
+	+	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+	+	$(INSTALL_DATA) \
+	+		$(PKG_BUILD_DIR)/mrvl/sdsd8997_combo_v4.bin \
+	+		$(1)/lib/firmware/mrvl/
+	+endef
+	+$(eval $(call BuildPackage,mrvl-sd8xxx-firmware))
+
+	+Package/mrvl-usb-firmware = $(call Package/firmware-default,Marvell SDIO8997 firmware)
+	+define Package/mrvl-usb-firmware/install
+	+	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+	+	$(INSTALL_DATA) \
+	+		$(PKG_BUILD_DIR)/mrvl/usbusb8997_combo_v4.bin \
+	+		$(1)/lib/firmware/mrvl/
+	+endef
+	+$(eval $(call BuildPackage,mrvl-usb-firmware))
+
+30. re-modify openwrt/package/kernel/mac80211/Makefile
+
+	for PCIE
+	+  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT +mrvl-pcie-firmware
+	for SDIO
+	+  DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT +mrvl-sd8xxx-firmware
+	for USB
+	+  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT +mrvl-usb-firmware
+31. Go to step 25.
+=======================================================================================================
+To support SDIO, USB and PCIE in one OpenWrt BSP
+if no need to support multi bus types in one BSP, ignore the following steps
+32. Re-modify Modify openwrt/package/kernel/mac80211/Makefile.
+	for PCIE
+        +       $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/mlan-pcie.ko \
+	for SDIO
+	+       $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/mlan-sdio.ko \
+	for USB
+	+       $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/mlan-usb.ko \
+33. Re-modify (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/Makefile
+	for PCIE
+
+	-obj-m := mlan.o
+	-mlan-objs := $(MLANOBJS)
+	+obj-m := mlan-pcie.o
+	+mlan-pcie-objs := $(MLANOBJS)
+
+	for SDIO
+
+	-obj-m := mlan.o
+	-mlan-objs := $(MLANOBJS)
+	+obj-m := mlan-sdio.o
+	+mlan-sdio-objs := $(MLANOBJS)
+
+	for USB
+
+	-obj-m := mlan.o
+	-mlan-objs := $(MLANOBJS)
+	+obj-m := mlan-usb.o
+	+mlan-usb-objs := $(MLANOBJS)
+34. Go to step 25.
diff --git a/wlan_sd8897/README_RBC b/wlan_sd8897/README_RBC
new file mode 100644
index 0000000..c849287
--- /dev/null
+++ b/wlan_sd8897/README_RBC
@@ -0,0 +1,103 @@
+===============================================================================
+            U S E R  M A N U A L for Robust BT-WLAN coex (RBC)
+
+ Copyright (C) 2014-2018, Marvell International Ltd.
+ All Rights Reserved
+===============================================================================
+
+###############################
+
+# Abbreviations and acronyms
+
+###############################
+RBC - Robust BT-WLAN co-existence
+TMD - Time Distribute
+SMPS - Spatial Multiplexing Power Save
+
+###############################
+
+# Default RBC modes:
+
+###############################
+1.  For systems where BT and WLAN have seperate antennas, RBC mode is
+    automatically disabled in FW after detecting this from FEM cal data. e.g.
+    For 1x1 Dual-Ant system and 2x2 3-Ant system RBC mode is disabled.
+2.  For systems where BT and WLAN share an antenna, RBC mode is automatically
+    enabled in FW after detecting this from FEM cal data.
+    Default modes:
+    1x1 single antenna system: TMD RBC
+    2x2 2-antenna system: 1x1 SMPS RBC
+
+
+#################################
+
+# 2x2 2-antenna system RBC modes
+
+#################################
+There are three mutually exclusive RBC modes for a 2x2 system.
+The default RBC mode is 1x1 SMPS RBC. The required RBC mode must be
+configured before starting uAP or associating in-STA. The mode cannot be
+changed dynamically when any of these connections is active. The modes are
+described below:
+1.  1x1 SMPS RBC mode: WLAN switches to 1x1 FEM when BT is turned on. Also,
+    in-STA goes to SMPS mode w.r.t. ext-AP. When BT is turned off, WLAN
+    switches back to 2x2 FEM setting and in-STA moves out of SMPS.
+    uAP starts bss with only 1-stream even BT is off because it cannot
+    dynamically move between 1-stream and 2-stream rates like in-STA. To start
+    uAP with 2-stream, RBC mode has to be disabled.
+2.  1x2 SMPS RBC mode: Similar as 1x1 SMPS RBC mode. WLAN switches to 1x2 FEM
+    when BT is turned on. In this mode, it is expected that when BT is not
+    actively transmitting, WLAN can receive on both the antennas to enhance
+    the range. Note that 1-stream rates are used for receive and transmit.
+3.  2x2 TMD RBC mode: WLAN uses 2x2 antenna setting and timeshares the antenna
+    with BT.
+
+###############################
+
+# RBC mode select:
+
+###############################
+
+User can use robust_btc.conf and hostcmd to select different RBC mode:
+
+hostcmd mode_get
+hostcmd mode_timeshare
+hostcmd mode_spatial
+    This command is used to get/set Robust BT Coex.
+    mode_get:       get the current mode
+    mode_timeshare: set Robust BT Coex to timeshare mode  (default on 1x1 chips)
+    mode_spatial:   set Robust BT Coex to spatial mode    (only for, and default on 2x2 chips)
+
+    Usage:
+        mlanconfig mlanX hostcmd config/robust_btc.conf mode_get
+        mlanconfig mlanX hostcmd config/robust_btc.conf mode_timeshare
+        mlanconfig mlanX hostcmd config/robust_btc.conf mode_spatial
+
+hostcmd gpio_cfg
+    This command is used to enable/disable GPIO cfg.
+    gpio_cfg: enable/disable GPIO cfg for external bt request  (default is enable with High Polarity)
+
+    Usage:
+        mlanconfig mlanX hostcmd config/robust_btc.conf gpio_cfg
+
+hostcmd generictime
+hostcmd a2dptime
+hostcmd inquirytime
+hostcmd ap_generictime
+hostcmd ap_a2dptime
+hostcmd ap_inquirytime
+        This command is used to configure the time slice of COEX (only works in timeshare mode)
+        generictime:       configure the Bttime and Wlantime in Station Generic case
+        a2dptime:          configure the Bttime and Wlantime in Station A2DP case
+        inquirytime:       configure the Bttime and Wlantime in Station Inquiry case
+        ap_generictime:    configure the Bttime and Wlantime in Ap Generic case
+        ap_a2dptime:       configure the Bttime and Wlantime in Ap A2DP case
+        ap_inquirytime:    configure the Bttime and Wlantime in Ap Inquiry case
+
+    Usage:
+                mlanutl mlanX hostcmd config/robust_btc.conf generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf inquirytim
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime
diff --git a/wlan_sd8897/README_UAP b/wlan_sd8897/README_UAP
new file mode 100644
index 0000000..b05fe8a
--- /dev/null
+++ b/wlan_sd8897/README_UAP
@@ -0,0 +1,2715 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2009-2018, Marvell International Ltd.
+ All Rights Reserved
+
+1) FOR DRIVER BUILD
+
+	Goto source code directory wlan_src.
+		make [clean] build
+	The driver binaries can be found in ../bin_xxxx directory.
+	The driver code supports Linux kernel up to 4.14.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy sd8786_uapsta.bin | sd8787_uapsta.bin | ... to /lib/firmware/mrvl/ directory,
+	   create the directory if it doesn't exist.
+	b) Install uAP 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
+		The default drv_mode is 7.
+			Bit 4 :  NAN
+
+		max_uap_bss: Maximum number of uAP BSS (default 1, max 2)
+		uap_name: Name of the uAP interface (default: "uap")
+	   For example, to install SD8787 driver,
+	   To load driver in uAP only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=2 [fw_name=mrvl/sd8787_uapsta.bin]
+	   To switch mode between STA only, uAP only and uAPSTA in run time,
+		echo drv_mode=1 > /proc/mwlan/config		// STA mode
+		echo drv_mode=2 > /proc/mwlan/config		// uAP mode
+		echo drv_mode=3 > /proc/mwlan/config		// uAPSTA mode
+	c) Uninstall uAP driver,
+		ifconfig uapX down
+		rmmod sd8xxx
+		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)>
+	  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>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf
+	  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
+	  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>
+	  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
+
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sd8xxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+	The following info are provided in /proc/mwlan/uapX/info.
+
+	driver_name = "uap"
+	driver_version = <driver version>
+	InterfaceName= "uapX"
+	State= "Disconnected" | "Connected"
+	MACAddress= <6-byte adapter MAC address>
+	MCCount= <multicast address count>
+	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>
+	num_tx_timeout =  <number of tx timeout>
+	carrier "on" | "off"
+	tx queue "stopped" | "started"
+
+	The following debug info are provided in /proc/mwlan/uapX/debug.
+
+	drvdbg = <bit masks of driver debug message control>
+		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,...)
+	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>
+	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>
+	num_bridge_pkts = <number of bridged packets>
+	num_drop_pkts = <number of dropped packets>
+	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>
+	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>
+	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>
+	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>
+	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>
+
+	Example:
+		echo "drvdbg=0x7" > /proc/mwlan/uapX/debug	#enable MMSG,MFATAL,MERROR messages
+
+	Use dmesg or cat /var/log/debug to check driver debug messages.
+
+	To log driver debug messages to file,
+	a) Edit /etc/rsyslog.conf, add one line "*.debug		/var/log/debug"
+	b) touch /var/log/debug (if the file doesn't exist)
+	c) service rsyslog restart
+
+4) SOFT_RESET command
+   This command is used to perform a "soft reset" on the module.
+   The FW code will disable hardware and jump to boot code.
+   Host software will then need to re-download firmware if required.
+
+   Usage:
+	echo "soft_reset=1" > /proc/mwlan/config
+
+===============================================================================
+
+		U S E R  M A N U A L  F O R  UAPUTL
+
+NAME
+uaputl.exe [options] <command> [command parameters]]
+
+Options:
+	--help 	Display help
+	-v    	Display version
+	-i <interface>
+	-d <debug_level=0|1|2>
+
+Example:
+	./uaputl.exe --help
+		"display help for uaputl"
+
+	./uaputl.exe sys_config --help
+		"display help for sys_config command"
+
+This tool can be used to set/get uAP's settings. To change AP settings, you might
+need to issue "bss_stop" command to stop AP before making change and issue "bss_start"
+command to restart the AP after making change.
+
+------------------
+Supported Commands
+------------------
+version
+debug_level
+sys_config [CONFIG_FILE_NAME]
+bss_config [CONFIG_FILE_NAME]
+sys_info
+sys_reset
+bss_start
+bss_stop
+sta_list
+sta_deauth <STA_MAC_ADDRESS>
+sta_deauth_ext <STA_MAC_ADDRESS> <REASON_CODE>
+radioctrl [0|1]
+txratecfg [l] [m] [n]
+antcfg [m] [n]
+pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE]
+mic_err <STA_MAC_ADDRESS>
+key_material <MAC_ADDRESS> <KEY> [KEY_ID]
+sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]
+coex_config [CONFIG_FILE_NAME]
+hscfg [condition [[GPIO# [gap]]]]
+hssetpara condition [[GPIO# [gap]]]
+sys_cfg_wmm  [qosinfo=<qosinfo>]
+             [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+             [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+             [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+             [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+sys_cfg_ap_wmm [0]
+               [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+               [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+               [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+               [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_MAP]
+addbapara [timeout txwinsize rxwinsize txamsdu rxamsdu]
+aggrpriotbl <m0> <n0> <m1> <n1> ... <m7> <n7>
+addbareject <m0> <m1> ... <m7>
+httxbfcfg <ACTION> [ACT_DATA]
+httxcfg [<m>] [<n>]
+htstreamcfg [n]
+deepsleep [MODE] [IDLE_TIME]
+sdcmd52rw <FN no.> <address> [data]
+hostcmd <txpwrlimit_cfg.conf> txpwrlimit_cfg_get
+hostcmd <txpwrlimit_cfg.conf> txpwrlimit_2g_cfg_set
+hostcmd <txpwrlimit_cfg.conf> txpwrlimit_5g_cfg_set
+tx_data_pause [ENABLE][TX_BUF_CNT]
+vhtcfg <j> <k> [l] [m] [n] [o]
+dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+cscount [<channel_switch_count>]
+mgmtframectrl [MASK]
+
+-------------------------------------------------------------------
+The following commands can be issued individually for debug purpose
+-------------------------------------------------------------------
+sys_cfg_ap_mac_address [AP_MAC_ADDRESS]
+sys_cfg_ssid [SSID]
+sys_cfg_beacon_period [BEACON_PERIOD]
+sys_cfg_dtim_period [DTIM_PERIOD]
+sys_cfg_channel [CHANNEL] [MODE]
+sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]
+sys_cfg_scan_channels [CHANNEL[.BAND]]
+sys_cfg_rates [RATES]
+sys_cfg_rates_ext [rates RATES] [mbrate RATE]
+sys_cfg_tx_power [TX_POWER]
+sys_cfg_bcast_ssid_ctl [0|1|2]
+sys_cfg_preamble_ctl
+sys_cfg_bss_status
+sys_cfg_rts_threshold [RTS_THRESHOLD]
+sys_cfg_frag_threshold [FRAG_THRESHOLD]
+sys_cfg_rsn_replay_prot [1|0]
+sys_cfg_tx_beacon_rate [TX_BEACON_RATE]
+sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]
+sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]
+sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]
+sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]
+sys_cfg_auth [AUTH_MODE]
+sys_cfg_protocol [PROTOCOL] [AKM_SUITE]
+sys_cfg_pmf [MFPC] [MFPR]
+sys_cfg_wep_key [INDEX ISDEFAULT KEY]
+sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]
+sys_cfg_pwk_cipher [<PROTOCOL>] [PAIRWISE_CIPHER]
+sys_cfg_gwk_cipher [GROUP_CIPHER]
+sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]
+sys_cfg_wpa_passphrase [PASSPHRASE]
+sys_cfg_max_sta_num [STA_NUM]
+sys_cfg_retry_limit [RETRY_LIMIT]
+sys_cfg_sticky_tim_config [ENABLE] [<DURATION> <STICKY_BIT_MASK>]
+sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]
+sys_cfg_2040_coex [ENABLE]
+sys_cfg_eapol_pwk_hsk [<TIMEOUT> <RETRIES>]
+sys_cfg_eapol_gwk_hsk [<TIMEOUT> <RETRIES>]
+sta_filter_table <FILTERMODE> <MACADDRESS_LIST>
+regrdwr <TYPE> <OFFSET> [value]
+memaccess <ADDR> [value]
+rdeeprom <offset> <byteCount>
+cfg_data <type> [*.conf]
+sys_cfg_80211d [state STATE] [country COUNTRY]
+uap_stats
+sys_cfg_tdls_ext_cap [CONFIG_FILE]
+sys_cfg_restrict_client_mode [<ENABLE> [MODE_CONFIG]]
+
+-------------------
+Details of Commands
+-------------------
+
+version
+-------
+    "./uaputl.exe -v"
+
+    This command prints the uAP utility version information.
+
+debug_level
+-----------
+    "./uaputl.exe -d <debug_level>"
+
+    The supported debug_level are:
+        0     - no debug
+        1     - enable MSG_DEBUG
+        2     - enable all the debug
+    This command use to control the debug level of uaputl.exe.
+
+    Example:
+	./uaputl.exe -d 2 sys_config
+		Enable all the debug in uaputl.exe
+
+sys_config
+----------
+    "./uaputl.exe sys_config [CONFIG_FILE]"
+    This command is used to set or get the current settings of the Micro AP.
+
+    The supported options are:
+        CONFIG_FILE is file contain all the Micro AP settings.
+        empty - Get current Micro AP settings
+
+    Example:
+	./uaputl.exe sys_config
+		Get current settings of the Micro AP.
+
+	./uaputl.exe sys_config config/uaputl.conf
+		Load Micro AP's settings from uaputl.conf file and set.
+
+bss_config
+----------
+    "./uaputl.exe bss_config [CONFIG_FILE]"
+    This command is used to set or get the current settings of the BSS.
+
+    The supported options are:
+        CONFIG_FILE is file contain all the BSS settings.
+        empty - Get current BSS settings
+
+    Example:
+	./uaputl.exe bss_config
+		Get current settings of the BSS.
+
+	./uaputl.exe bss_config config/uaputl.conf
+		Load BSS settings from uaputl.conf file and set.
+
+sys_info
+--------
+    "./uaputl.exe sys_info"
+
+    This command returns system information such as firmware version number
+    and HW information.
+
+sys_reset
+---------
+    "./uaputl.exe sys_reset"
+
+    This command is used to reset the Micro AP back to its initial state.
+    For example, this can be used to recover from a serious error, or before
+    creating a new BSS.
+
+    This command has the following effects:
+        1. The WLAN hardware MAC is reset.
+        2. All MIB variables are initialized to their respective default
+           values.
+        3. The firmware internal variables are reset to their respective
+           default values.
+        4. The firmware state machines are reset to their respective initial
+           states.
+
+bss_start
+---------
+    "./uaputl.exe bss_start"
+
+    This command starts the BSS.
+    There is no error for redundant bss_start command.
+
+bss_stop
+--------
+    "./uaputl.exe bss_stop"
+
+    This command stops the BSS. The command causes the firmware to:
+        1. Deauthenticate all associated client stations.
+        2. Turn off the radio (hence stopping beaconing).
+    There is no error for redundant bss_stop command.
+
+sta_list
+--------
+    "./uaputl.exe sta_list"
+
+    This command returns the list of client stations that are currently
+    associated with the AP.
+
+    The output is formatted as shown below, for each STA:
+    "STA <STA_NUM> information:
+     ==========================
+     MAC Address: <STA MAC address>
+     Power mfg status: active|power save
+     Rssi:  <RSSI_VALUE>"
+
+sta_deauth
+----------
+    "./uaputl.exe sta_deauth <STA_MAC_ADDRESS>"
+
+    This command is used to de-authentciate a client station for any reason.
+
+radioctrl
+----------
+    "./uaputl.exe radioctrl [0|1]"
+
+    This command is used to set or get the radio settings.
+    The supported options are:
+        1     - Turn radio on
+        0     - Turn radio off
+        empty - Get current radio setting
+
+txratecfg
+----------
+    "./uaputl.exe txratecfg [l] [m] [n]"
+
+    This command is used to set/get the transmit data rate.
+
+    Where
+        [l] is <format>
+        <format> - This parameter specifies the data rate format used in this command
+            0:    LG
+            1:    HT
+            2:    VHT
+            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
+            32   MCS32
+        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
+        [n] is <nss>
+        <nss> - This parameter specifies the NSS. It is valid only for VHT
+        If <format> is 2 (VHT),
+            1    NSS1
+            2    NSS2
+
+    Examples:
+        ./uaputl.exe txratecfg 0 3        : Set fixed Tx rate to 11 Mbps
+        ./uaputl.exe txratecfg 0 11       : Set fixed Tx rate to 54 Mbps
+        ./uaputl.exe txratecfg 1 3        : Set fixed Tx rate to MCS3
+        ./uaputl.exe txratecfg 2 3 2    : Set fixed Tx rate to MCS3 for NSS2
+        ./uaputl.exe txratecfg 0xff     : Disable fixed rate and uses auto rate
+        ./uaputl.exe txratecfg          : Read the current data rate setting
+
+antcfg
+----------
+    "./uaputl.exe antcfg [m] [n]"
+
+    This command is used to set/get the transmit and receive antenna.
+    where value of m is:
+        Bit 0   -- Tx Path A
+        Bit 1   -- Tx Path B
+        Bit 0-1 -- Tx Path A+B
+
+    where value of n is:
+        Bit 0   -- Rx Path A
+        Bit 1   -- Rx Path B
+        Bit 0-1 -- Rx Path A+B
+    The Tx path setting (m) is used if Rx path (n) is not provided.
+
+    Examples:
+        ./uaputl.exe antcfg             : Get Tx and Rx path
+        ./uaputl.exe antcfg 3           : Set Tx and Rx path to A+B
+        ./uaputl.exe antcfg 2 3         : Set Tx path to B and Rx path to A+B
+
+sys_cfg_ap_mac_address
+----------------------
+    "./uaputl.exe sys_cfg_ap_mac_address [AP_MAC_ADDRESS]"
+
+    This command is used to set or get the AP MAC address.
+
+    If no arguments are given, this command returns the current AP MAC
+    address.
+    Otherwise, this MAC address becomes the BSSID of the infrastructure
+    network created by the AP.
+
+    Example:
+	./uaputl.exe sys_cfg_ap_mac_address 00:50:43:20:aa:bb
+		Set AP MAC address to 00:50:43:20:aa:bb
+
+	./uaputl.exe sys_cfg_ap_mac_address
+		Get AP MAC address"
+
+sys_cfg_ssid
+------------
+    "./uaputl.exe sys_cfg_ssid [SSID]"
+
+    This command is used to set or get the AP SSID.
+
+    If no arguments are given, this command returns the current AP SSID.
+    While setting, the maximum length of the SSID can be 32 characters.
+
+    Example:
+	./uaputl.exe sys_cfg_ssid microap
+		Set AP ssid to "microap"
+
+	./uaputl.exe sys_cfg_ssid
+		Get AP ssid
+
+sys_cfg_beacon_period
+---------------------
+    "./uaputl.exe sys_cfg_beacon_period [BEACON_PERIOD]"
+
+    This command is used to set or get the AP beacon period.
+
+    If no arguments are given, this command returns the current AP beacon
+    period.
+
+    Beacon period is represented in milliseconds.
+
+    Example:
+	./uaputl.exe sys_cfg_beacon_period 100
+		Set AP beacon period to 100 TU
+
+	./uaputl.exe sys_cfg_beacon_period
+		Get AP beacon period
+
+sys_cfg_dtim_period
+-------------------
+    "./uaputl.exe sys_cfg_dtim_period [DTIM_PERIOD]
+
+    This command is used to set or get the AP DTIM period.
+
+    If no arguments are given, this command returns the current AP DTIM
+    period.
+
+    Example:
+	./uaputl.exe sys_cfg_dtim_period 3
+		Set AP DTIM period to 3
+
+	./uaputl.exe sys_cfg_dtim_period
+		Get AP DTIM period
+
+sys_cfg_scan_channels
+---------------------
+    "./uaputl.exe sys_cfg_scan_channels [CHANNEL[.BAND]]"
+
+    This command is used to set or get the AP's scan channel list.
+
+    If no arguments are given, this command returns the scan channel list.
+    If BAND is 0, channel is set in 2.4 GHz band and if BAND is 1, channel is set to 5GHz.
+    Channels from only one of the bands should be specified.
+    Each CHANNEL.BAND pair must be separated by a space. BAND parameter is optional.
+
+    Example:
+	./uaputl.exe sys_cfg_scan_channels 1 11 6
+		Set AP scan channel list to 1 11 6
+
+	./uaputl.exe sys_cfg_scan_channels 11.0 6.0
+		Set AP scan channel list to 11 6
+
+	./uaputl.exe sys_cfg_scan_channels
+		Get AP scan channel list
+
+        ./uaputl.exe sys_cfg_scan_channels 8.1 16.1 34
+                Set AP scan channel list to 8 16 and 34 in 5GHz band.
+
+sys_cfg_channel
+---------------
+    "./uaputl.exe sys_cfg_channel [CHANNEL] [MODE]"
+
+    This command is used to set or get the AP radio channel.
+
+    If no arguments are given, this command returns the current AP radio
+    channel.
+
+    MODE: band config mode.
+          Bit 0:  automatic channel selection (ACS) enable/disable
+          Bit 1:  secondary channel is above primary channel enable/disable(only allow for channel 1-7)
+          Bit 2:  secondary channel is below primary channel enable/disable(only allow for channel 5-11)
+          For 'a' band channel:
+          Bit 1:  secondary channel is above primary channel enable/disable
+          Bit 2:  secondary channel is below primary channel enable/disable
+          Only following pairs of channels are valid for secondary channel setting in 5GHz band.
+          36, 40
+          44, 48
+          52, 56
+          60, 64
+          100, 104
+          108, 112
+          116, 120
+          124, 128
+          132, 136
+          149, 153
+          157, 161
+
+    Example:
+        ./uaputl.exe sys_cfg_channel 6
+                Set AP radio channel to 6, and no secondary channel.
+
+        ./uaputl.exe sys_cfg_channel 11 0
+                Set AP radio channel to 11 with Manual Channel Select.
+
+        ./uaputl.exe sys_cfg_channel 0 1
+                Set AP to ACS.
+
+        ./uaputl.exe sys_cfg_channel
+                Get AP radio channel
+
+        ./uaputl.exe sys_cfg_channel 6 2
+                Set AP primary radio channel to 6, and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel 6 4
+                Set AP primary radio channel to 6, and secondary channel is below
+        ./uaputl.exe sys_cfg_channel 0 3
+                Set AP to ACS mode, and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel 0 5
+                Set AP to ACS mode, and secondary channel is below.
+        ./uaputl.exe sys_cfg_channel 36 2
+                Set AP primary radio channel to 36, and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel 40 4
+                Set AP primary radio channel to 40, and secondary channel is below.
+
+sys_cfg_channel_ext
+---------------
+    "./uaputl.exe sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]"
+
+    This command is used to set or get the AP radio channel.
+
+    If no arguments are given, this command returns the current AP radio
+    channel.
+
+    BAND: 0 : 2.4GHz operation
+          1 : 5GHz operation
+    MODE: band config mode.
+          Bit 0:  automatic channel selection (ACS) enable/disable
+          Bit 1:  secondary channel is above primary channel enable/disable(only allow for channel 1-7)
+          Bit 2:  secondary channel is below primary channel enable/disable(only allow for channel 5-11)
+          For 'a' band channel:
+          Bit 1:  secondary channel is above primary channel enable/disable
+          Bit 2:  secondary channel is below primary channel enable/disable
+          Only following pairs of channels are valid for secondary channel setting in 5GHz band.
+          36, 40
+          44, 48
+          52, 56
+          60, 64
+          100, 104
+          108, 112
+          116, 120
+          124, 128
+          132, 136
+          149, 153
+          157, 161
+
+    Example:
+        ./uaputl.exe sys_cfg_channel_ext 6
+Set AP radio channel to 6, and no secondary channel.
+
+        ./uaputl.exe sys_cfg_channel_ext 11 0 0
+                Set AP radio channel to 11 in 2.4GHz band with Manual Channel Select.
+
+        ./uaputl.exe sys_cfg_channel_ext 0 0 1
+                Set AP to ACS mode and 2.4GHz band.
+
+        ./uaputl.exe sys_cfg_channel_ext 8 0
+                Set AP to channel 8 and 2.4GHz band.
+
+        ./uaputl.exe sys_cfg_channel_ext 8 1
+                Set AP to channel 8 and 5GHz band.
+
+        ./uaputl.exe sys_cfg_channel_ext 36 1
+                Set AP to channel 36 and 5GHZ band.
+
+        ./uaputl.exe sys_cfg_channel_ext
+                Get AP radio channel, band and mode.
+
+        ./uaputl.exe sys_cfg_channel_ext 6 0 2
+                Set AP primary radio channel to 6, band to 2.4GHz and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel_ext 6 0 4
+                Set AP primary radio channel to 6, band to 2.4GHz and secondary channel is below
+        ./uaputl.exe sys_cfg_channel_ext 0 0 3
+                Set AP to ACS mode, band to 2.4GHz and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel_ext 0 0 5
+                Set AP to ACS mode, band to 2.4GHz and secondary channel is below.
+        ./uaputl.exe sys_cfg_channel_ext 36 1 2
+                Set AP primary radio channel to 36, band to 5GHz and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel_ext 40 1 4
+                Set AP primary radio channel to 40, band to 5GHz and secondary channel is below.
+
+sys_cfg_rates
+-------------
+    "./uaputl.exe sys_cfg_rates [RATES]"
+
+    If 'Rate' provided, a 'set' is performed else a 'get' is performed
+    RATES is provided as a set of data rates, in unit of 500 kilobits
+    A rate with MSB bit is basic rate, i.e 0x82 is basic rate.
+
+    'set' will not allowed after bss start.
+
+    Valid rates: 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
+    Non-Basic rates: 0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+    Basic rates: 0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc
+
+    Each rate must be separated by a space.
+
+    Example:
+    ./uaputl.exe sys_cfg_rates 0x82 0x84 0x96 0x0c 0x12 0x18
+    ./uaputl.exe sys_cfg_rates
+
+sys_cfg_rates_ext
+-----------------
+    "./uaputl.exe sys_cfg_rates_ext [rates RATES] [mbrate RATE]"
+
+    If 'Rate' provided, a 'set' is performed else a 'get' is performed.
+    RATES is provided as a set of data rates, in unit of 500 kilobits
+    A rate with MSB bit is basic rate, i.e 0x82 is basic rate.
+    If only operational rates is provided, MCBC rate and unicast rate will be set to auto.
+
+    Valid rates: 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
+    Non-Basic rates: 0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+    Basic rates: 0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc
+    Rates 2, 4, 11 and 22 (in units of 500 Kbps) must be present in either of
+    basic or non-basic rates. If OFDM rates are enabled then 12, 24 and 48 (in
+    units of 500 Kbps) must be present in either basic or non-basic rates.
+
+    Each rate must be separated by a space.
+
+    rates followed by RATES for setting operational rates.
+    mbrate followed by RATE for setting multicast and broadcast rate.
+
+    operational rates only allow to set before bss start.
+
+    Example:
+    ./uaputl.exe sys_cfg_rates_ext rates 0x82 0x04 11 0x96 12 24 48 mbrate 0x16
+        Set AP operation rates to 0x82,0x04,11,0x96,12,24,48, multicast rate to 0x16
+    ./uaputl.exe sys_cfg_rates_ext rates 0x82 0x04 11 0x96 12 24 48
+		Set AP operation rates to 0x82,0x04,11,0x96,12,24,48.
+
+sys_cfg_tx_power
+----------------
+    "./uaputl.exe sys_cfg_tx_power [TX_POWER]"
+
+    This command is used to set or get the AP Tx power.
+
+    If no arguments are given, this command returns the current AP Tx power.
+
+    Tx power level is represented in dBm.
+
+    Example:
+	./uaputl.exe sys_cfg_tx_power 13
+		Set AP Tx power to 13 dBm
+
+	./uaputl.exe sys_cfg_tx_power
+		Get AP Tx power
+
+sys_cfg_bcast_ssid_ctl
+----------------------
+    "./uaputl.exe sys_cfg_bcast_ssid_ctl [0|1|2]"
+
+    This command is used to set or get the SSID broadcast feature setting.
+
+    The supported options are:
+        0     - Disable SSID broadcast, send empty SSID (length=0) in beacon.
+        1     - Enable SSID broadcast
+        2     - Disable SSID broadcast, clear SSID (ACSII 0) in beacon, but keep the original length
+        empty - Get current SSID broadcast setting
+
+    When broadcast SSID is enabled, the AP responds to probe requests from
+    client stations that contain null SSID.
+
+    When broadcast SSID is disabled (sys_cfg_bcast_ssid_ctl = 0/2), the AP:
+        1. Does not respond to probe requests that contain null SSID.
+        2. when sys_cfg_bcast_ssid_ctl = 0, generates beacons that contain null SSID (length=0).
+        3. when sys_cfg_bcast_ssid_ctl = 2, clear SSID (ACSII 0) in beacon and keep the original length
+
+   Example:
+        ./uaputl.exe sys_cfg_bcast_ssid_ctl 0
+                Disable SSID broadcast, send empty SSID (length=0) in beacon.
+
+	./uaputl.exe sys_cfg_bcast_ssid_ctl 1
+		Enable SSID broadcast
+
+        ./uaputl.exe sys_cfg_bcast_ssid_ctl 2
+                Disable SSID broadcast, clear SSID (ACSII 0) in beacon, but keep the original length
+
+	./uaputl.exe sys_cfg_bcast_ssid_ctl
+		Get SSID broadcast setting
+
+sys_cfg_preamble_ctl
+--------------------
+    "./uaputl.exe sys_cfg_preamble_ctl"
+
+    This command is used to get type of preamble.
+
+    Example:
+	./uaputl.exe sys_cfg_preamble_ctl
+		Get AP preamble setting
+
+sys_cfg_bss_status
+--------------------
+    "./uaputl.exe sys_cfg_bss_status"
+
+    This command is used to get current BSS status.
+
+    Example:
+	./uaputl.exe sys_cfg_bss_status
+		Get current BSS status
+
+sys_cfg_rts_threshold
+---------------------
+    "./uaputl.exe sys_cfg_rts_threshold [RTS_THRESHOLD]"
+
+    This command is used to set or get the RTS threshold value.
+
+    If no arguments are given, this command returns the current RTS threshold
+    value.
+
+    Example:
+	./uaputl.exe sys_cfg_rts_threshold 2347
+		Set AP RTS threshold to 2347
+
+	./uaputl.exe sys_cfg_rts_threshold
+		Get AP RTS threshold
+
+sys_cfg_frag_threshold
+----------------------
+    "./uaputl.exe sys_cfg_frag_threshold [FRAG_THRESHOLD]"
+
+    This command is used to set or get the Fragmentation threshold value.
+
+    If no arguments are given, this command returns the current Fragmentation threshold
+    value.
+
+    Example:
+	./uaputl.exe sys_cfg_frag_threshold 2346
+		Set AP Fragmentation threshold to 2346
+
+	./uaputl.exe sys_cfg_frag_threshold
+		Get AP Fragmentation threshold
+
+    Note: Please use aggrpriotbl command to disable the AMPDU/AMSDU aggregation when frag_threshold is set.
+
+sys_cfg_rsn_replay_prot
+-----------------------
+    "./uaputl.exe sys_cfg_rsn_replay_prot [1|0]"
+
+    This command is used to enable or disable RSN replay protection.
+
+    The supported options are:
+        0     - Disable RSN replay protection
+        1     - Enable RSN replay protection
+        empty - Get current RSN replay protection setting
+
+   Example:
+	./uaputl.exe sys_cfg_rsn_replay_prot 1
+		Enable RSN replay protection
+
+	./uaputl.exe sys_cfg_rsn_replay_prot
+		Get RSN replay protection setting
+
+sys_cfg_tx_beacon_rate
+--------------------
+    "./uaputl.exe sys_cfg_tx_beacon_rate [TX_BEACON_RATE]"
+
+    This command is used to set or get the Tx beacon rate settings.
+
+    The supported options are:
+        0     - Auto rate
+        >0    - Set specified beacon rate
+        empty - Get current beacon rate
+
+    Tx beacon rate is represented in units of 500 kbps. While setting Tx beacon
+    rates, only zero or rates currently configured are allowed.
+
+	Following is the list of supported rates in units of 500 Kbps:
+	    2,    4,    11,   22,   12,   18,   24,   36,   48,   72,   96,   108
+	    0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+
+    Example:
+	./uaputl.exe sys_cfg_tx_beacon_rate 0x04
+		Set AP Tx beacon rate to 2 M
+
+   	./uaputl.exe sys_cfg_tx_beacon_rate 4
+		Set AP Tx data beacon to 2 M
+
+	./uaputl.exe sys_cfg_tx_beacon_rate
+		Get AP Tx beacon rate
+
+sys_cfg_mcbc_data_rate
+----------------------
+    "./uaputl.exe sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]"
+
+    This command is used to set or get the MCBC data rate to use for multicast
+    or broadcast packet transmission.
+
+    The supported options are:
+        0     - Auto rate
+        >0    - Set specified MCBC data rate
+        empty - Get current MCBC data rate
+
+    MCBC data rate is represented in units of 500 kbps. While setting MCBC data
+    rates, only zero or one of rates currently configured as basic rates are allowed.
+
+    For example:  If current basic rates is "0x82 0x84 0x8b 0x96", then the allowed
+                  values for MCBC data rate will be "0x2 0x4 0xb 0x16".
+
+    Example:
+	./uaputl.exe sys_cfg_mcbc_data_rate 22
+		Set AP MCBC data rate to 11 M
+
+   	./uaputl.exe sys_cfg_mcbc_data_rate 0
+		Set AP MCBC data rate to auto
+
+	./uaputl.exe sys_cfg_mcbc_data_rate
+		Get AP MCBC data rate
+
+sys_cfg_pkt_fwd_ctl
+-------------------
+    "./uaputl.exe sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]"
+
+    This command is used to set or get the packet forwarding control
+    settings.
+
+    where PKT_FWD_CTRL is:
+        bit 0 -- Packet forwarding handled by Host (0) or Firmware (1)
+        bit 1 -- Intra-BSS broadcast packets are allowed (0) or denied (1)
+        bit 2 -- Intra-BSS unicast packets are allowed (0) or denied (1)
+        bit 3 -- Inter-BSS unicast packets are allowed (0) or denied (1)
+        empty - Get current packet forwarding setting
+
+    Example:
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 1
+		Set AP packet forwarding control in firmware to allow all packets
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 6
+		Set AP packet forwarding control in Host, only allow Inter-BSS unicast packets forwarding.
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 8
+		Set AP packet forwarding control in Host, only allow Intra-BSS packets forwarding.
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 0
+		Set AP packet forwarding control in Host, allow Intra-BSS packets and
+	            Inter-BSS unicast packets forwarding.
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl
+		Get AP packet forwarding control
+
+sys_cfg_sta_ageout_timer
+------------------------
+    "./uaputl.exe sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]"
+
+    This command is used to set or get the STA ageout value.
+
+    Value of 0 will mean that stations will never be aged out.
+
+    Minimum value for this is 100. Maximum allowed setting should be 864000.
+
+    If no arguments are given, this command returns the current STA ageout
+    value.
+
+    Ageout timer value is represented in units of 100 ms.
+
+    Example:
+	./uaputl.exe sys_cfg_sta_ageout_timer 1800
+		Set AP STA ageout time to 180000 ms
+
+	./uaputl.exe sys_cfg_sta_ageout_timer
+		Get AP STA ageout time
+
+sys_cfg_ps_sta_ageout_timer
+---------------------------
+	"./uaputl.exe sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]"
+
+	This command is used to set or get the PS STA ageout value.
+
+	Value of 0 will mean that stations will never be aged out.
+
+	Minimum value for this is 100. Maximum allowed setting should be 864000.
+
+	If no arguments are given, this command returns the current	PS STA ageout
+	value.
+
+	Ageout timer value is represented in units of 100 ms.
+
+	Example:
+	./uaputl.exe sys_cfg_ps_sta_ageout_timer 1800
+		Set AP PS STA ageout time to 180000 ms
+
+	./uaputl.exe sys_cfg_ps_sta_ageout_timer
+		Get AP PS STA ageout time
+
+sys_cfg_auth
+------------
+    "./uaputl.exe sys_cfg_auth [AUTHMODE]"
+
+    This command is used to set or get the AP authentication mode.
+
+    The supported options are:
+        AUTHMODE :     0 - Open authentication
+                       1 - Shared key authentication
+                       255 - Auto (Open and Shared key) authentication
+    empty - Get current authentication mode
+
+    Example:
+	./uaputl.exe sys_cfg_auth 0
+		Set AP authentication mode to Open.
+
+	./uaputl.exe sys_cfg_auth
+		Get AP authentication mode.
+
+sys_cfg_protocol
+----------------
+    "./uaputl.exe sys_cfg_protocol [PROTOCOL] [AKM_SUITE]"
+
+    This command is used to set or get the encryption protocol.
+
+    The supported options are:
+	PROTOCOL:
+			1		 No RSN
+			2		WEP Static
+			8		  WPA
+			32		  WPA2
+			40		 WPA, WPA2 Mixed Mode
+    empty - Get current encryption protocol
+
+    AKM_SUITE:
+            bit 0   KEY_MGMT_EAP
+            bit 1   KEY_MGMT_PSK
+            bit 2   KEY_MGMT_NONE
+            bit 8   KEY_MGMT_PSK_SHA256
+
+    Example:
+	./uaputl.exe sys_cfg_protocol 2
+		Set AP encryption protocol to static WEP.
+
+	./uaputl.exe sys_cfg_protocol
+		Get AP encryption protocol.
+
+    ./uaputl.exe sys_cfg_protocol 32 0x102
+        Set AP encryption protocol to WPA2 and AKM SUITE to PSK and PSK SHA256
+
+    ./uaputl.exe sys_cfg_protocol 40 0x100
+        Set AP encryption protocol to WPA+WPA2 and AKM SUITE to PSK SHA256
+
+sys_cfg_pmf
+-----------
+    "./uaputl.exe sys_cfg_pmf [MFPC] [MFPR]"
+
+    This command is used to set or get the PMF settings.
+
+    The supported options are:
+        MFPC:       0 - Mgmt frame protection not capable
+                    1 - Mgmt frame protection capable
+
+        MFPR:       0 - Mgmt frame protection not required
+                    1 - Mgmt frame protection required
+                    x - don't care if MFPC = 0
+
+    Example:
+    ./uaputl.exe sys_cfg_pmf 1 1
+        Set AP's PMF params to Mgmt frames protection capable and required.
+
+    ./uaputl.exe sys_cfg_pmf
+        Get AP's PMF params settings.
+
+sys_cfg_wep_key
+---------------
+    "./uaputl.exe sys_cfg_wep_key [INDEX ISDEFAULT Key_0]
+                                  [INDEX ISDEFAULT Key_1]
+                                  [INDEX ISDEFAULT Key_2]
+                                  [INDEX ISDEFAULT Key_3]
+                                  [INDEX]"
+
+    This command is used to set or get the WEP key settings.
+
+    The supported options are:
+        INDEX:       0 - KeyIndex is 0
+                     1 - KeyIndex is 1
+                     2 - KeyIndex is 2
+                     3 - KeyIndex is 3
+	ISDEFAULT:   0: KeyIndex is not the default
+		     1: KeyIndex is the default transmit key
+
+        KEY_* :      Key value.
+        empty - Get current WEP key settings for all the keys
+        INDEX - Only INDEX will get the key setting for the particular
+                KeyIndex.
+
+    Example:
+	./uaputl.exe sys_cfg_wep_key 0 1 55555
+		Set AP's default transmit key to "55555", key index is 0.
+
+    ./uaputl.exe sys_cfg_wep_key 0 1 12345678901234567890123456
+        Set AP's default transmit key to "12345678901234567890123456", key index is 0.
+
+	./uaputl.exe sys_cfg_wep_key
+		Get AP all the WEP keys settings.
+
+	./uaputl.exe sys_cfg_wep_key 1
+		Get WEP key setting for the KeyIndex = 1.
+
+sys_cfg_cipher
+--------------
+    "./uaputl.exe sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]"
+
+    This command is used to set or get the key types for the pairwise and group key.
+
+    The supported options are:
+	PAIRWISE_CIPHER:
+			0		  None
+			4		  TKIP
+			8		 AES CCMP
+			12		 AES CCMP + TKIP
+        GROUP_CIPHER:
+			0		  None
+			4		  TKIP
+			8		 AES CCMP
+    	empty - Get current key types
+
+	Valid combinations of [PAIRWISE_CIPHER GROUP_CIPHER] are:
+		[0 0], [4 4], [8 8], [12 4].
+
+    Example:
+	./uaputl.exe sys_cfg_cipher 4 4
+		Set AP's pairwise and group key's type to TKIP.
+
+	./uaputl.exe sys_cfg_cipher
+		Get AP's key types for the pairwise and group key.
+
+sys_cfg_pwk_cipher
+------------------
+    "./uaputl.exe sys_cfg_pwk_cipher [<PROTOCOL>] [PAIRWISE_CIPHER]"
+
+    This command is used to set or get protocol and corresponding pairwise cipher settings.
+
+    The supported options are:
+        PROTOCOL:
+                        0                None
+                        8                 WPA
+                        32                WPA2
+        PAIRWISE_CIPHER:
+                        0                 None
+                        4                 TKIP
+                        8                AES CCMP
+                        12               AES CCMP + TKIP
+        WPA/TKIP cipher cannot be used when uAP operates in 802.11n mode.
+        If only PROTOCOL is provided, pairwise cipher for that protocol is displayed.
+        empty - Get protocol and corresponding pairwise cipher settings.
+
+    Example:
+        ./uaputl.exe sys_cfg_pwk_cipher 8 4
+                Set AP's pairwise cipher to TKIP for WPA protocol.
+
+        ./uaputl.exe sys_cfg_pwk_cipher 32
+                Get AP's pairwise cipher for WPA2 protocol.
+
+        ./uaputl.exe sys_cfg_pwk_cipher
+                Get AP's protocol and corresponding pairwise cipher settings.
+
+sys_cfg_gwk_cipher
+------------------
+    "./uaputl.exe sys_cfg_gwk_cipher [GROUP_CIPHER]"
+
+    This command is used to set or get group cipher.
+
+    The supported options are:
+        GROUP_CIPHER:
+                        0                 None
+                        4                 TKIP
+                        8                AES CCMP
+        empty - Get group cipher settings.
+
+    Example:
+        ./uaputl.exe sys_cfg_gwk_cipher 8
+                Set AP's group cipher to AES CCMP.
+
+        ./uaputl.exe sys_cfg_gwk_cipher
+                Get AP's group cipher settings.
+
+sys_cfg_group_rekey_timer
+-------------------------
+    "./uaputl.exe sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]"
+
+    This command is used to set or get the AP group re-key time interval, in seconds.
+
+    The supported options are:
+        GROUP_REKEY_TIMER is represented in seconds. This is only applicable
+        		 if the protocol is WPA or WPA2. Value of 0 will disable group re-key.
+
+        empty - Get current group rekey timer
+
+    Example:
+	./uaputl.exe sys_cfg_group_rekey_timer 1800
+		Set AP's group re-key time interval to 1800 s
+
+	./uaputl.exe sys_cfg_group_rekey_timer
+		Get AP's group re-key time interval.
+
+sys_cfg_wpa_passphrase
+----------------------
+    "./uaputl.exe sys_cfg_wpa_passphrase [PASSPHRASE]"
+
+    This command is used to set or get the WPA or WPA2 passphrase.
+
+    If no arguments are given, this command returns the current WPA or WPA2
+    passphrase.
+    While setting, the maximum length of the passphrase can be 64 characters.
+
+    Example:
+	./uaputl.exe sys_cfg_wpa_passphrase 1234567890
+		Set AP's WPA or WPA2 passphrase to "1234567890"
+
+	./uaputl.exe sys_cfg_wpa_passphrase
+		Get AP's WPA or WPA2 passphrase.
+
+sys_cfg_max_sta_num
+-------------------
+    "./uaputl.exe sys_cfg_max_sta_num [STA_NUM]"
+
+    This command is used to set or get the maximum number of stations allowed to connect to uAP.
+
+    If no arguments are given, this command returns the configured maximum number of stations
+		allowed to connect to uAP and maximum number of stations supported.
+
+    Example:
+	./uaputl.exe sys_cfg_max_sta_num 2
+		Set AP's maximum station number to 2
+
+	./uaputl.exe sys_cfg_max_sta_num
+		Get AP's maximum station number configured and maximum station number supported.
+
+sys_cfg_retry_limit
+-------------------
+    "./uaputl.exe sys_cfg_retry_limit [RETRY_LIMIT]"
+
+    This command is used to set or get the retry limit to use for packet transmissions.
+
+    The maximum retry_limit allowed is 14.
+
+    If no arguments are given, this command returns the current retry limit value.
+
+    Example:
+	./uaputl.exe sys_cfg_retry_limit 2
+		Set AP's retry limit value to 2
+
+	./uaputl.exe sys_cfg_retry_limit
+		Get AP's retry limit value
+
+sys_cfg_sticky_tim_config
+-------------------------
+    "./uaputl.exe sys_cfg_sticky_tim_config [ENABLE] [<DURATION> <STICKY_BIT_MASK>]"
+
+    This command is used to set or get sticky TIM configuration.
+
+    ENABLE is used to enable or disable sticky TIM feature.
+    Following are the valid values of ENABLE
+    0- disable SticktyTIM
+    1- enable StickyTIM  (Both DURATION in beacons and STICKY_BIT_MASK must be provided)
+    2- enable StickyTIM  (enable sticky TIM without changing previous values of
+       DURATION and STICKY_BIT_MASK)
+
+    When bit 0 of STICKY_BIT_MASK is set, TIM bit is made sticky and when
+    cleared, normal TIM bit updates resume.
+    When bit 1 of STICKY_BIT_MASK is set, MoreData bit is made sticky and when
+    cleared, normal MoreData bit updates resume.
+    STICKY_BIT_MASK = 0 is NOT a valid configuration value.
+
+    If no argument is given, this command returns current sticky TIM configuration.
+
+    Example:
+    ./uaputl.exe sys_cfg_sticky_tim_config
+                Get sticky TIM configuration.
+
+    ./uaputl.exe sys_cfg_sticky_tim_config 0
+                Disable sticky TIM feature.
+
+    ./uaputl.exe sys_cfg_sticky_tim_config 1 30 1
+                Enable sticky TIM feature with DURATION of 30 beacons and
+                STICKY_BIT_MASK set to 1.
+
+sys_cfg_sticky_tim_sta_mac_addr
+-------------------------------
+    "./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]"
+
+    This command is used to set or get sticky TIM control parameter for associated station.
+
+    CONTROL when set to 1, sticky TIM bit for that station is activated.
+    When set to 0, sticky TIM bit for that station is deactivated.
+
+    If no argument is given, it returns sticky TIM configuration for all associated stations.
+    If only STA_MAC_ADDRESS is provided, it returns sticky TIM configartion for that station.
+
+    Example:
+    ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr
+            Get sticky TIM configuration for all associated stations.
+
+    ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr 00:50:43:20:11:22
+            Get control parameter for station 00:50:43:20:11:22.
+
+    ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr 1 00:50:43:20:11:22
+            Set control parameter for station with MAC address 00:50:43:20:11:22 to 1.
+
+    Note:TIM bit for an associated STA is made sticky only if both below mentioned
+         conditions are satisfied
+         1.Enable = 1 or 2 in most recently received sys_cfg_sticky_tim_config command, and
+         2.Control = 1 in most recently received sys_cfg_sticky_tim_sta_mac_addr
+           with this station MAC address.
+
+sys_cfg_2040_coex
+-------------------------------
+    "./uaputl.exe sys_cfg_2040_coex [ENABLE]"
+
+    This command is used to set or get 20/40 BSS coexistence configuration.
+
+    ENABLE when set to 0, disables 20/40 coex.
+    When set to 1, enables 20/40 coex.
+
+    If no argument is given, it returns 20/40 BSS coex configuration.
+
+    Example:
+    ./uaputl.exe sys_cfg_2040_coex
+            Get 20/40 BSS coexistence configuration.
+
+    ./uaputl.exe sys_cfg_2040_coex 0
+            Disable 20/40 BSS coexistence.
+
+    ./uaputl.exe sys_cfg_2040_coex 1
+            Enable 20/40 BSS coexistence.
+
+    Note:20/40 BSS coex configuration can be set only before starting BSS.
+
+sys_cfg_eapol_pwk_hsk
+---------------------
+    "./uaputl.exe sys_cfg_eapol_pwk_hsk [<TIMEOUT> <RETRIES>]"
+
+	This command is used to set or get pairwise handshake update timeout and
+	number of retries.
+
+	Both TIMEOUT and number of RETRIES should be provided for a 'set'.
+
+	If no arguments are given, this command returns timeout value and number
+	of
+	retries for pairwise key.
+
+	Example:
+	./uaputl.exe sys_cfg_eapol_pwk_hsk 50 2
+		Set AP's pairwise key timeout to 50ms and number of retries to 2.
+
+	./uaputl.exe sys_cfg_eapol_pwk_hsk
+		Get AP's pairwise key timeout and number of retries.
+
+sys_cfg_eapol_gwk_hsk
+---------------------
+	"./uaputl.exe sys_cfg_eapol_gwk_hsk [<TIMEOUT> <RETRIES>]"
+
+	This command is used to set or get groupwise handshake update timeout and
+	number of retries.
+
+	Both TIMEOUT and number of RETRIES should be provided for a	'set'.
+
+	If no arguments are given, this command returns timeout	value and number
+	of retries for groupwise key.
+
+	Example:
+	./uaputl.exe sys_cfg_eapol_gwk_hsk 50 2
+	Set AP's groupwise key timeout to 50ms and number of retries to 2.
+
+	./uaputl.exe sys_cfg_eapol_gwk_hsk
+	Get AP's groupwise key timeout and number of retries.
+
+sta_filter_table
+----------------
+    "./uaputl.exe sta_filter_table <FILTERMODE> [<MACADDRESS_LIST>]"
+
+    This command is used to get or set the client station MAC address
+    filter table.
+
+    The supported options are:
+    FILTERMODE : 0 - Disable filter table
+                 1 - Allow mac address specified in the allowed list
+                 2 - Block MAC addresses specified in the  banned list
+    MACADDRESS_LIST is the list of MAC addresses to be acted upon. Each
+    MAC address must be separated with a space. Maximum of 16 MAC addresses
+    are supported.
+
+    empty - Get current client station MAC address filter table.
+
+    Example:
+	./uaputl.exe sta_filter_table 0
+		Disable filter table
+
+	./uaputl.exe sta_filter_table 1 00:50:43:20:aa:bb
+		Set AP's filter mode to allow, only MAC address "00:50:43:ab:bb" will be allowed.
+
+	./uaputl.exe sta_filter_table
+		Get AP's filter table settings.
+
+regrdwr
+-------
+     "./uaputl.exe regrdwr <TYPE> <OFFSET> [value]"
+
+     These commands are used to read the MAC, BBP and RF registers from the card.
+     TYPE can take 3 values, 1 - read/write MAC register
+                             2 - read/write BBP register
+                             3 - read/write RF  register
+
+     OFFSET specifies the offset location that is to be read.
+     This parameter can be specified either in decimal or in hexadecimal (by preceding the number with a "0x").
+
+     value if specified, then that value will be written to that offset in the specified register. Value should be
+     specified in hexadecimal.
+
+     Example:
+	./uaputl.exe regrdwr 1 0xa123
+		read MAC register 0xa123
+
+	./uaputl.exe regrdwr 1 0xa123 0xaa
+		write 0xaa to MAC register 0xa123
+
+        ./uaputl.exe regrdwr 2 0x0123
+		read BBP register 0x0123
+
+	./uaputl.exe regrdwr 2 0x0123 0xaa
+		write 0xaa to BBP register 0x0123
+
+        ./uaputl.exe regrdwr 3 0x0123
+		read RF register 0x0123
+
+	./uaputl.exe regrdwr 3 0x0123 0xaa
+		write 0xaa to RF register 0x0123
+
+memaccess
+---------
+ 	"./uaputl.exe memaccess <ADDR> [value]"
+	This commands is used to read/write to a memory address
+
+	ADDR specifies the address of the location that is to be read/write
+	This parameter can be specified either in decimal or in hexadecimal (by preceding the number with a "0x").
+
+	value if specified, then that value will be written to that address in the specified register.
+
+	Example:
+		./uaputl.exe memaccess 0xc00153e4
+			read contents of memory location 0xc00153e4
+
+
+		./uaputl.exe memaccess 0xc00153e4 0xaabbccdd
+			write value 0xaabbccdd to  memory location 0xc00153e4
+
+rdeeprom
+--------
+    "./uaputl.exe rdeeprom <offset> <bytecount>"
+
+    This command is used to read bytes from offset location on
+    EEPROM
+
+    offset: 0,4,8,..., multiple of 4
+    bytecount: 4-20, multiple of 4
+
+   	Example:
+    ./uaputl.exe rdeeprom 200 12
+        read 12 bytes from offset 200 ON EEPROM
+
+cfg_data
+--------
+ 	"./uaputl.exe cfg_data <type> [*.conf]"
+
+    This command is used to set/get the configuration data to/from the firmware.
+
+    type: 2 -- cal data
+
+   	Example:
+        ./uaputl.exe cfg_data 2 cal_data.conf
+            read cal_data from cal_data.conf and download to firmware.
+        ./uaputl.exe cfg_data 2
+            read cal_data from firmware
+
+sys_cfg_80211d
+--------------
+    "./uaputl.exe sys_cfg_80211d [state STATE] [country COUNTRY]"
+    This command is used to set/get 802.11D specific parameters.
+    If no parameters are provided, this command returns state, country and
+    domain information.
+
+    Allowed values for state are 0 for disable and 1 for enable.
+    COUNTRY is a two letter string input (derived from ISO 3166 code;
+    http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
+    )
+
+    Countries are mapped with specific domain in file "80211d_domain.conf". In
+    order to set customize band setting, user can modify 80211d_domain.conf
+    file.
+
+    Example:
+    ./uaputl.exe sys_cfg_80211d state 0
+        To-disable
+
+    ./uaputl.exe sys_cfg_80211d state 1
+        To-enable
+
+    ./uaputl.exe sys_cfg_80211d country IN
+        for using country as INDIA
+
+    ./uaputl.exe sys_cfg_80211d state 1 country US
+        for enabling and setting country in single command.
+
+uap_stats
+---------
+    "./uaputl.exe uap_stats"
+    This command is used to get uAP statistics.
+
+    Example:
+    ./uaputl.exe uap_stats
+
+pscfg
+---------
+    "./uaputl.exe pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE]
+
+    This command is used to set or get the AP's power mode and power save params.
+
+    The supported options are:
+        MODE :     0 - disable power mode
+                   2 - enable inactivity based power save mode
+
+        PS PARAMS:
+            CTRL:  0 - disable protection frame Tx before PS
+                   1 - enable protection frame Tx before PS
+            INACTTO: Inactivity timeout in microseconds, default value is 200000 us
+            MIN_SLEEP: Minimum sleep duration in microseconds, default value 17000 us
+            MAX_SLEEP: Maximum sleep duration in microseconds, default value 17000 us
+			The value of MIN_SLEEP should be >= 5000 us.
+			The value of MAX_SLEEP should be <= beacon interval(when ctrl: 0).
+			The value of MAX_SLEEP should be <= 32000 us(when ctrl: 1).
+
+            MIN_AWAKE: Minimum awake duration in microseconds, default value is 2000 us
+            MAX_AWAKE: Maximum awake duration in microseconds, default value is 2000 us
+			The value of MIN_AWAKE should be >= 2000 us.
+            MIN_AWAKE,MAX_AWAKE only valid when MODE is set to inactivity based power save mode.
+
+
+	empty - Get current power mode and power save params.
+
+    Example:
+	./uaputl.exe pscfg 0
+		Disable AP's power mode.
+
+   	./uaputl.exe pscfg 2
+		Enable inactivity based power save mode.
+
+   	./uaputl.exe pscfg 2 1 400000 20000 20000 10000 10000
+		Enable inactivity based power save mode, enable protection, set inactivity timeout 400000 us
+        set minimum sleep duration to 20000 us, maximum sleep duration to 20000 us
+        and set minimum awake duration to 10000us, maximum awake duration to 10000 us
+
+	./uaputl.exe pscfg
+		Get current AP's power mode and power save params.
+
+hscfg
+-----
+    ./uaputl.exe hscfg [condition [[GPIO# [gap]]]]
+	This command is used to configure the host sleep parameters.
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap) parameters for set. If no parameter provided,
+	get is performed.
+
+	where Condition is:
+		bit 0 = 1   -- broadcast data
+		bit 1 = 1   -- unicast data
+		bit 2 = 1   -- mac event
+		bit 3 = 1   -- multicast data
+		bit 6 = 1  --  Wakeup when mgmt frame received.
+
+	The host sleep mode will be cancelled if condition is set to 0xffff.
+	The default is 0x7.
+
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+	GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead).
+	The default is 0xff.
+
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff
+	for special setting (host acknowledge required) when GPIO is used to wakeup host.
+	The default is 200.
+
+	Examples:
+		./uaputl.exe hscfg              : Get current host sleep mode
+		./uaputl.exe hscfg 0xffff       : Cancel host sleep mode
+		./uaputl.exe hscfg 3            : Broadcast and unicast data
+		                                  Use GPIO and gap set previously
+		./uaputl.exe hscfg 2 3          : Unicast data
+		                                  Use GPIO 3 and gap set previously
+		./uaputl.exe hscfg 2 1 0xa0     : Unicast data
+		                                  Use GPIO 1 and gap 160 ms
+		./uaputl.exe hscfg 2 0xff       : Unicast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap set previously
+		./uaputl.exe hscfg 4 3 0xff     : MAC event
+		                                  Use GPIO 3
+		                                  Special host sleep mode
+		./uaputl.exe hscfg 1 0xff 0xff  : Broadcast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap 255ms
+
+hssetpara
+---------
+    ./uaputl.exe hssetpara condition [[GPIO# [gap]]]
+    This command is used to configure the host sleep parameters.
+
+    Note:
+    1) The usages of parameters are the same as "hscfg" command.
+    2) The parameters will be saved in the driver and be used when host suspends.
+
+sta_deauth_ext
+--------------
+    "./uaputl.exe sta_deauth_ext <STA_MAC_ADDRESS><REASON_CODE>"
+
+    This command is used to de-authenticate a client station with specific reason code.
+
+    Example:
+        ./uaputl.exe sta_deauth_ext 00:50:43:20:34:58  4
+            deauth station 00:50:43:20:34:58 with IEEE reason code 4 (Disassociated due to inactivity)
+
+mic_err
+-------
+    "./uaputl.exe mic_err <STA_MAC_ADDRESS>"
+
+    This command is used to report station mic error.
+
+    Example:
+        ./uaputl.exe mic_err 00:50:43:20:34:58
+            report mic err for station 00:50:43:20:34:58
+
+key_material
+------------
+    "./uaputl.exe key_material <MAC_ADDRESS> <KEY> [KEY_ID]"
+
+    This command is used to set key. Get operation is not supported.
+
+        MAC_ADDRESS: station mac address while setting station unicast key
+                     ff:ff:ff:ff:ff:ff while setting multicast key
+
+        KEY: hex string, allowed length should be 32 or 64.
+        KEY_ID: default value is 0.
+
+    Example:
+        ./uaputl.exe key_material ff:ff:ff:ff:ff:ff 12345678901234567890123456789012 1
+            set group key, key value is "12345678901234567890123456789012", key id is 1
+
+        ./uaputl.exe key_material 00:50:43:20:34:58 1234567890123456789012345678901234567890123456789012345678901234
+            set station 00:50:43:20:34:58 unicast key,
+            key value is "1234567890123456789012345678901234567890123456789012345678901234"
+
+sys_cfg_custom_ie
+-----------------
+    "./uaputl.exe sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]"
+
+    This command is used to set or get custom IEs for management frames.
+
+    The supported options are:
+        INDEX:       0 - IE Index is 0
+                     1 - IE Index is 1
+                     2 - IE Index is 2
+                     MAX IE Index depends on device memory.
+
+               	    -1 - Append/Delete IE automatically
+                         Delete will delete the IE from the matching IE buffer
+                         Append will append the IE to the buffer with the same mask
+        MASK :       Management subtype mask value as per bit definitions
+	                   :  Bit 0 - Association request.
+	                   :  Bit 1 - Association response.
+	                   :  Bit 2 - Reassociation request.
+	                   :  Bit 3 - Reassociation response.
+	                   :  Bit 4 - Probe request.
+	                   :  Bit 5 - Probe response.
+	                   :  Bit 8 - Beacon.
+        MASK :       MASK = 0 to clear the mask and the IE buffer
+
+        IEBuffer:    IE buffer to set in hexadecimal bytes.
+	                  The Buffer should not be space separated.
+	                  ( Maximum length = 256 bytes )
+        empty - Get IE buffer, subtype mask settings for all the indices [0-3].
+        INDEX - Only INDEX will get the IE buffer configured for the particular
+                Index.
+
+    Example:
+	./uaputl.exe sys_cfg_custom_ie
+		Get IE buffer, subtype mask settings for all indices.
+
+	./uaputl.exe sys_cfg_custom_ie 1
+		Get IE buffer and subtype mask WEP key setting for the Index = 1.
+
+	./uaputl.exe sys_cfg_custom_ie 2 0
+		Clear IE buffer and mask value for Index = 2.
+
+	./uaputl.exe sys_cfg_custom_ie 3 0x101 0xdd051234567890
+		Set IE buffer and mask value for Index = 3.
+
+	./uaputl.exe sys_cfg_custom_ie -1 0x101 0xdd051234567890
+		Append the specified IEBuffer at index with mask value of 0x101
+
+	./uaputl.exe sys_cfg_custom_ie -1 0 0xdd051234567890
+		Delete the specified IEBuffer from all the IEs.
+
+	./uaputl.exe sys_cfg_custom_ie 2 0 0xdd051234567890
+		Delete the specified IEBuffer from the IEs at index 2.
+
+coex_config
+-----------
+    "./uaputl.exe coex_config [CONFIG_FILE]"
+    This command is used to set or get the BT coex configuration settings.
+
+    The supported options are:
+        CONFIG_FILE is file contain all the BT coex settings.
+        empty - Get current BT coex settings
+
+    Example:
+	./uaputl.exe coex_config
+		Get current BT coex settings.
+
+	./uaputl.exe coex_config uapcoex.conf
+		Load BT coex configuration settings from uapcoex.conf file and set.
+
+sys_cfg_wmm
+-----------
+    "./uaputl.exe sys_cfg_wmm [qosinfo=<qosinfo>]
+                              [0]
+                              [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+                              [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+                              [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+                              [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]"
+
+    This command can be used set/get beacon WMM parameters
+
+    The supported option are:
+        qosinfo: qos information. User can set only MSB. Valid values are 0x80 and 0x00.
+        Lower 4 bits are managed by FW. Hence, value read for qosinfo may have
+        lower 4 bits non-zero.
+
+        AC_BE: 0
+        AC_BK: 1
+        AC_VI: 2
+        AC_V0: 3
+        AIFSN: AIFSN value
+        ECW_MAX: ECW max
+        ECW_MIN: ECW min
+        TX_OP: TXOP Limit
+        empty - Get current WMM parameters
+        When all the parameter are 0, wmm will be disabled.
+
+        Example:
+        ./uaputl.exe sys_cfg_wmm 0 3 10 4 0
+           Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_wmm 1 7 10 4 0
+           Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_wmm 2 2 4 3 94
+           Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+
+        ./uaputl.exe sys_cfg_wmm 3 2 3 2 47
+           Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_wmm
+            Get current wmm parameters
+
+        ./uaputl.exe sys_cfg_wmm 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_wmm qosinfo=0x80 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Enable wmm PS mode.
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_wmm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        ./uaputl.exe sys_cfg_wmm 0
+            Disable wmm
+
+sys_cfg_ap_wmm
+-----------
+    "./uaputl.exe sys_cfg_ap wmm [0]
+                                 [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+                                 [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+                                 [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+                                 [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]"
+
+    This command can be used set/get AP WMM parameters
+
+    The supported option are:
+        AC_BE: 0
+        AC_BK: 1
+        AC_VI: 2
+        AC_V0: 3
+        AIFSN: AIFSN value
+        ECW_MAX: ECW max
+        ECW_MIN: ECW min
+        TX_OP: TXOP Limit
+        empty - Get current AP WMM parameters
+        When all the parameter are 0, AP wmm will be disabled.
+
+        Example:
+        ./uaputl.exe sys_cfg_ap_wmm 0 3 10 4 0
+           Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_ap_wmm 1 7 10 4 0
+           Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_ap_wmm 2 2 4 3 94
+           Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+
+        ./uaputl.exe sys_cfg_ap_wmm 3 2 3 2 47
+           Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_ap_wmm
+            Get current AP wmm parameters
+
+        ./uaputl.exe sys_cfg_ap_wmm 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_ap_wmm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        ./uaputl.exe sys_cfg_ap_wmm 0
+            Disable AP wmm
+
+addbapara
+---------
+    "./uaputl.exe addbapara [timeout txwinsize rxwinsize txamsdu rxamsdu]"
+	This command can be used to update the default ADDBA parameters.
+
+	The supported options are:
+	    timeout - This is the block ack timeout for ADDBA request.
+		    0 : Disable (recommended for throughput test)
+		    1 - 65535 : Block Ack Timeout in TU
+	    txwinsize - Buffer size for ADDBA request. (32 is default value)
+	    rxwinsize - Buffer size for ADDBA response. (16 is default value)
+	    txamsdu - amsdu support for ADDBA request. (1 is default value)
+		    0 : Disable amsdu in ADDBA request.
+		    1 - Enable amsdu in ADDBA request.
+	    rxamsdu - amsdu support for ADDBA response. (1 is default value)
+		    0 : Disable amsdu in ADDBA response.
+		    1 - Enable amsdu in ADDBA response.
+        empty - Get current ADDBA parameters.
+
+	Current window size limit for Tx as well as Rx is 1023.
+
+	Example:
+	./uaputl.exe addbapara
+        Get the current addba params
+	./uaputl.exe addbaparam 1000 64 8 0 0
+        This will change the ADDBA timeout to (1000 * 1024) us,	txwinsize to 64 and rxwinsize to 8
+        and disable AMSDU in ADDBA request/response.
+
+	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 txamdsdu/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.
+
+sys_cfg_11n
+-----------
+    "./uaputl.exe sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_CAP]"
+    This command can be used set/get 802.11n parameters.
+
+    The supported option are:
+        ENABLE: 0 - disable 802.11n in uap
+                1 - enable 802.11n in uap
+		Note: If 802.11n is disabled, 802.11ac MUST be disabled at the same time
+        HTCAP: HT Capabilities info (default value is 0x111c)
+               Bit 15-13: Reserved set to 0
+               Bit 12: DSS/CCK mode in 40MHz enable/disable
+               Bit 11-10: Reserved set to 0
+               Bit 9-8: Reserved set to 0x01
+               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
+        AMPDU: A-MPDU Parameter (default value is 0x03)
+               Bit 7-5: Reserved set to 0
+               Bit 4-2: Minimum MPDU Start spacing
+                        Set to 0 for no restriction
+                        Set to 1 for 1/4 us
+                        Set to 2 for 1/2 us
+                        Set to 3 for 1 us
+                        Set to 4 for 2 us
+                        Set to 5 for 4 us
+                        Set to 6 for 8 us
+                        Set to 7 for 16 us
+               Bit 1-0: Max A-MPDU length
+        TXBFCAP: TX Beamforming capabilities
+               Bit 0    : Implicit TX BF receiving capable
+               Bit 1    : RX staggered sounding capable
+               Bit 2    : TX staggered sounding capable
+               Bit 3    : RX NDP capable
+               Bit 4    : TX NDP capable
+               Bit 5    : Implicit TX BF capable
+               Bit 6-7  : Calibration
+                       0: - not supported
+                       1: - STA can respond to a calibration request using
+                            the CSI Report, but cannot initiate calibration
+                       2: - reserved
+                       3: - STA can both initiate and respond to a calibration request
+               Bit 8    : Explicit CSI TX BF capable
+               Bit 9    : Explicit non-compressed steering capable
+               Bit 10   : Explicit compressed steering capable
+               Bit 11-12: Explicit TX BF CSI feedback
+                       0: - not supported
+                       1: - delayed feedback
+                       2: - immediate feedback
+                       3: - delayed and immediate feedback
+               Bit 13-14: Explicit non-compressed BF feedback capable
+                       0: - not supported
+                       1: - delayed feedback
+                       2: - immediate feedback
+                       3: - delayed and immediate feedback
+               Bit 15-16: Explicit compressed BF feedback capable
+                       0: - not supported
+                       1: - delayed feedback
+                       2: - immediate feedback
+                       3: - delayed and immediate feedback
+               Bit 17-18: Minimal grouping
+                       0: - no grouping (STA supports groups of 1)
+                       1: - groups of 1, 2
+                       2: - groups of 1, 4
+                       3: - groups of 1, 2, 4
+               Bit 19-20: CSI number of beamformer antennas supported
+                       0: - single TX antenna sounding
+                       1: - 2 TX antenna sounding
+                       2: - 3 TX antenna sounding
+                       3: - 4 TX antenna sounding
+               Bit 21-22: Non-compressed steering number of beamformer antennas supported
+                       0: - single TX antenna sounding
+                       1: - 2 TX antenna sounding
+                       2: - 3 TX antenna sounding
+                       3: - 4 TX antenna sounding
+               Bit 23-24: Compressed steering number of beamformer antennas supported
+                       0: - single TX antenna sounding
+                       1: - 2 TX antenna sounding
+                       2: - 3 TX antenna sounding
+                       3: - 4 TX antenna sounding
+               Bit 25-26: CSI max number of rows beamformer supported
+                       0: - single row of CSI
+                       1: - 2 rows of CSI
+                       2: - 3 rows of CSI
+                       3: - 4 rows of CSI
+               Bit 27-28: Channel estimation capability
+                       0: - 1 space time stream
+                       1: - 2 space time streams
+                       2: - 3 space time streams
+                       3: - 4 space time streams
+               Bit 29-31: Reserved
+        HT_MCS_MAP: MCS rate bitmap
+               Bit 0-7   : MCS_SET_0
+               Bit 15-8  : MCS_SET_1
+        empty - Get current 802.11n parameters.
+
+        Example:
+        ./uaputl.exe sys_cfg_11n 1 0x117e 3
+            enable 802.11n, and set HT Capabilities info to 0x117e, and A-MPDU Parameter to 0x03
+        ./uaputl.exe sys_cfg_11n 1 0x117e 3 0xFFFFFFFF
+            enable 802.11n, and set HT Capabilities info to 0x117e, A-MPDU
+            Parameter to 0x03 and TX Beamforming capabilities to 0xFFFFFFFF
+        ./uaputl.exe sys_cfg_11n 1 0x117e 3 0xFFFFFFFF 0x00100023
+            enable 802.11n, and set HT Capabilities info to 0x117e, A-MPDU
+            Parameter to 0x03, TX Beamforming capabilities to 0xFFFFFFFF and
+            MCS rate bitmap to 0x00100023.
+        ./uaputl.exe sys_cfg_11n 0
+            disable 802.11n in uap
+        ./uaputl.exe sys_cfg_11n
+            Get current 802.11n parameters
+
+aggrpriotbl
+-----------
+        "./uaputl.exe aggrpriotbl <m0> <n0> <m1> <n1> ... <m7> <n7>"
+        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)
+
+        The supported option are:
+            <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.
+
+        empty - Get current priority table for AMPDU/AMSDU traffic.
+
+        Example:
+        ./uaputl.exe 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
+
+	    ./uaputl.exe 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.
+
+	    ./uaputl.exe 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 issued in disconnected state.
+
+addbareject
+-----------
+        "./uaputl.exe addbareject <m0> <m1> ... <m7>"
+        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.
+
+        The supported option are:
+            <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.
+        empty - Get current addbareject table for all the TIDs.
+
+        Example:
+        ./uaputl.exe addbareject
+            This command will get the current table.
+	        [0 0 0 0 0 0 1 1]. ADDBA would be accepted for all TIDs except for TID [6,7].
+	        This is the default state.
+
+        ./uaputl.exe 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]
+
+	    ./uaputl.exe 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 issued in disconnected state.
+
+sys_cfg_tdls_ext_cap
+--------------------
+
+    "./uaputl.exe sys_cfg_tdls_ext_cap [CONFIG_FILE]"
+
+    This command is used to set/get TDLS extended capability settings.
+
+    If CONFIG_FILE is provided, a SET is performed , else a GET is performed.
+
+    Examples:
+        ./uaputl.exe sys_cfg_tdls_ext_cap config/tdls_ext_cap.conf
+        Set TDLS extended capability parameters in the config file.
+        ./uaputl.exe sys_cfg_tdls_ext_cap
+        Get TDLS extended capability parameters.
+
+httxbfcfg
+---------
+	"./uaputl.exe httxbfcfg <ACTION> [ACT_DATA]"
+
+	This command is used to configure the TX beamforming options.
+
+	The supported options are:
+		ACTION: 0 - Control global parameters for beamforming
+                1 - Performs NDP Sounding for PEER
+		        2 - TX BF interval in milliseconds
+		        3 - Enable/Disable beamforming/sounding for the indicated peer.
+		        4 - TX BF SNR Threshold for peer
+		ACT_DATA: Specific data for the above actions
+                  For ACTION 0 - Beamforming enable/disable, sounding enable/disable,
+                                 FB type, snr_threshold, sounding interval, Beamformig mode
+		          For ACTION 1 - PEER MAC and status
+		          For ACTION 2 - TX BF interval
+		          For ACTION 3 - PEER MAC
+		          For ACTION 4 - PEER MAC and SNR
+		          empty - Get action specific settings
+
+	Examples:
+		./uaputl.exe httxbfcfg 0                          : Get current global configuration parameter
+		./uaputl.exe httxbfcfg 2 00:50:43:20:BF:64        : Get the TX BF periodicity for a given peer
+		./uaputl.exe httxbfcfg 3                          : Get the list of MAC addresses that have
+		                                                      beamforming and/or sounding enabled
+		./uaputl.exe httxbfcfg 4                          : Get the list of PEER MAC, SNR tuples
+		                                                      programmed into the firmware.
+		./uaputl.exe httxbfcfg 0 0 0 3 10 500 5           : Disable beamforming, sounding, set FB type
+		                                                      to 3, snr threshold to 10, sounding interval
+		                                                      to 500 ms and beamforming mode to 5
+		./uaputl.exe httxbfcfg 1 00:50:43:20:BF:64        : Perform NDP Trigger sounding to peer
+		                                                      00:50:43:20:BF:64
+		./uaputl.exe httxbfcfg 2 00:50:43:20:BF:64 500    : Set TX BF periodicity for peer 00:50:43:20:BF:64
+		                                                      to 500 milliseconds
+		./uaputl.exe httxbfcfg 3 00:50:43:20:BF:43 1 0 3  : Enable beamforming, disable sounding and set
+		                                                      FB type to 3 for peer 00:50:43:20:BF:43
+		./uaputl.exe httxbfcfg 4 00:50:43:20:BF:24 43     : Set TX BF SNR threshold to peer
+
+
+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-10: Reserved set to 0
+        Bit 9-8: Rx STBC set to 0x01
+        BIT9 BIT8  Description
+        0    0     No spatial streams
+        0    1     One spatial streams supported
+        1    0     Reserved
+        1    1     Reserved
+		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:
+		./uaputl.exe -i uapX httxcfg
+		This will display HT Tx configuration for 2.4G and 5G band.
+
+		./uaputl.exe -i uapX httxcfg 0x62
+		This will enable 20/40 and Short GI but will disable Green field for 2.4G and 5G band.
+
+		./uaputl.exe -i uapX 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.
+
+htstreamcfg
+	This command is used to set/get HT stream configuration.
+	The setting only takes effect in next association.
+
+	Usage:
+		./uaputl.exe -i uapX htstreamcfg [n]
+
+	where <n>
+		0x11: HT stream 1x1 mode
+		0x22: HT stream 2x2 mode
+
+	Examples:
+		./uaputl.exe -i uapX htstreamcfg        : Get current setting
+		./uaputl.exe -i uapX htstreamcfg 0x11   : Set HT stream 1x1 mode
+		./uaputl.exe -i uapX htstreamcfg 0x22   : Set HT stream 2x2 mode
+
+deepsleep
+---------
+    "./uaputl.exe deepsleep [MODE] [IDLE_TIME]"
+    This command is used to set/get auto deep sleep mode.
+
+    The supported option are:
+        [MODE]: Enable/disable auto deep sleep mode (1/0)
+        [IDLE_TIME]: Idle time in milliseconds after which firmware will put the device
+                    in deep sleep mode. Default value is 100 ms.
+        empty - Get current deep sleep mode.
+
+    Example:
+    ./uaputl.exe deepsleep          : Display auto deep sleep mode
+    ./uaputl.exe deepsleep 1        : Enable auto deep sleep mode, idle time unchanged
+    ./uaputl.exe deepsleep 0        : Disable auto deep sleep mode
+    ./uaputl.exe deepsleep 1 500    : Enable auto deep sleep mode with idle time 500 ms
+
+    Note:
+            Deepsleep must be disabled before changing idle time.
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+    "./uaputl.exe sdcmd52rw <function number> <register address> [value]"
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+	Examples:
+    ./uaputl.exe sdcmd52rw 1 3          : Issue cmd52 to read function 1, register 3.
+    ./uaputl.exe sdcmd52rw 1 1 0x3f     : Issue cmd52 to write function 1, register 1
+                                          with value 0x3f.
+
+txpwrlimit_cfg_get
+txpwrlimit_2g_cfg_set
+txpwrlimit_5g_cfg_set
+------------------
+    This command is used to set/get the configuration data of Tx power limitation.
+    Note: The configuration set should be issued when no STA is connected.
+
+    Examples:
+        ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get
+        ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set
+        ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set
+
+rxpktcoal_cfg
+-------------
+   "./uaputl.exe rxpktcoal_cfg [PKT-THRESHOLD] [TIMEOUT]"
+
+	This is used to get/set RX packet coalescing paramters
+
+    The supported option are:
+        [PKT-THRESHOLD]: count after which packets would be sent to host. Valid values 1-7
+        [TIMEOUT]: timeout in ms after which packets would be sent to host. Valid values 1-4
+        Coalescing is disabled if both or either of packet_thershold and delay is zero
+
+        RX packet coalescing parameters can be changed only when device is in
+        idle state i.e. all interfaces are disconnected.
+
+    Example:
+    ./uaputl.exe rxpktcoal_cfg      : Display RX packet coalescing settings
+    ./uaputl.exe rxpktcoal_cfg 5 1  : Enable RX packet coalescing: packet count 5, delay 1.
+    ./uaputl.exe rxpktcoal_cfg 0 0  : Disable RX packet coalescing.
+
+tx_data_pause
+-------------
+  "./uaputl.exe tx_data_pause [ENABLE][TX_BUF_CNT]"
+
+    This command is used to set/get tx data pause settings.
+
+    The supported option are:
+        [ENABLE]: Enable/disable pause tx events from firmware to host.
+        [TX_BUF_CNT]: Max number of TX buffers allowed for all PS clients
+        empty - Get current tx data pause settings
+
+    Example:
+    ./uaputl.exe tx_data_pause      : Display tx data pause settings
+    ./uaputl.exe tx_data_pause 1    : Enable pause tx event, max tx buffer number unchanged.
+    ./uaputl.exe tx_data_pause 0    : Disable pasue tx event, max tx buffer number unchanged.
+    ./uaputl.exe tx_data_pause 1 15 : Enable pause tx event, with max tx buffer number 15.
+
+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
+		3: configuration of VHT capabilities (uAP only)
+	Note: For the UAP, only 3 is supported for txrx.
+
+	where [l] is <bwcfg>
+	<bwcfg> - This parameter specifies the bandwidth (BW) configuration
+		  applied to the vhtcfg.
+	If <txrx> is 3 (For uAP),
+		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.
+
+	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.
+
+	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:
+		./uaputl.exe -i uapX vhtcfg 2 3            : Get current VHT configuration in 5GHz for the uAP.
+		./uaputl.exe -i uapX 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.
+		./uaputl.exe -i uapX 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.
+
+dfstesting
+----------
+  "./uaputl.exe dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]"
+
+    This command is used to set/get DFS testing settings.
+
+    The supported option are:
+        <user_cac_pd>: user-configured Channel Availability Check in msec
+                       0 = disable, use default period (60000)
+                       1-65535 = enable with that period
+        <user_nop_pd>: user-configured Non-Occupancy Period in sec
+                       0 = disable, use default period (1800)
+                       1-65535 = enable with that period
+        <no_chan_change>: enable/disable no channel change on radar
+                          0 = disable, 1 = enable (overrides below)
+        <fixed_chan_num>: user-configured channel to change to on radar
+                          0 = disable, 1-255 = enable with that channel
+                          (channel validity for region, etc. is not checked)
+                          (only takes effect if no_chan_change = 0)
+
+    Example:
+    ./uaputl.exe dfstesting             : Get current dfstesting settings
+    ./uaputl.exe dfstesting 2000 0 0 0  : user_cac=2sec, others disabled/default
+    ./uaputl.exe dfstesting 0 0 1 0     : only no_chan_change enabled
+    ./uaputl.exe dfstesting 0 120 0 64  : user_nop=2min, force chan 64 on radar
+
+cscount
+---------------
+
+  "./uaputl.exe cscount [<channel_switch_count>]"
+
+    This command is used to configure the number of beacons AP sends with channel switch IE, before channel change due to
+    radar detection. If not configured, <channel_switch_count> is set to 5 by default.
+
+    The supported options are:
+        <channel_switch_count>: user configured channel switch count
+                                5-20 = configure with that value
+
+   Example:
+   ./uaputl.exe cscount         : Get user configured channel switch count value
+   ./uaputl.exe cscount 10      : Set channel switch count to 10
+
+
+mgmtframectrl
+-------------
+  "./uaputl.exe mgmtframectrl [MASK]"
+
+    This command is used to set/get management frame control mask.
+
+    where the parameter [MASK] is the bit mask of management frame reception.
+        Following are the bit definitions.
+        Bit 0 : Association Request
+        Bit 1 : Association Response
+        Bit 2 : Re-Association Request
+        Bit 3 : Re-Association Response
+        Bit 4 : Probe Request
+        Bit 5 : Probe Response
+        Bit 8 : Beacon Frames
+
+    Example:
+    ./uaputl.exe mgmtframectrl 0x101
+    Set management frame control mask to 0x101.
+
+restrict_client_mode
+--------------------
+	"./uaputl.exe restrict_client_mode [<ENABLE> [MODE_CONFIG]]"
+
+	This command is used to set/get the mode in which the ex-Stations can connect to the uAP.
+	If no arguments are given, this command returns the current configuration.
+	By default this feature will be disabled.
+	[ENABLE]:
+		1: Enable the feature.
+		0: Disable the feature.
+	[MODE_CONFIG]: config mode.
+		Bit 0:	B only Mode.
+		Bit 1:	A only Mode.
+		Bit 2:	G only Mode.
+		Bit 3:	N only Mode.
+		Bit 4:	AC only Mode.
+
+	Example:
+	./uaputl.exe restrict_client_mode 1 0x8.
+	Only N mode clients will be able to connect. Association will fail for other clients.
+
+	./uaputl.exe restrict_client_mode 0.
+	This feature is disabled.
+
+	Note:
+	The set operation should be performed before bss is started.
+	User should make sure that the mode advertized by uAP in beacons
+	(i.e. combination of supported/extended rates IE and capability IEs)
+	is superset of the mode allowed for ex-STA associations using this TLV.
+
+uap_oper_ctrl
+-------------
+	"./uaputl.exe uap_oper_ctrl [control] [chanopt] [bandcfg] [channel]"
+
+	This command is used to set/get uAP operation control when in-STA disconnected with ext-AP.
+	If no arguments are given, this command returns the current configuration.
+
+	The supported options are:
+		<control> : 0  default, do nothing
+				   2  uAP stops and restart automatically
+		<chanopt> Specify which channel should be used when uap restarts automatically
+				   1: uap restarts on default 2.4G/channel 6
+				   2: uap restart on band/channel configured by driver previously
+				   3: uap restart on band/channel configured by parameter bandcfg/channel
+		<bandcfg> This parameter specifies the bandwidth when chanopt is 3
+				   0: 20Mhz
+				   2: 40Mhz
+				   3: 80Mhz
+		<channel> This parameter specifies the channel will be used when chanopt is 3
+
+		Example:
+		./uaputl.exe uap_oper_ctrl  2 1
+		uap stops and restart automatically when in-STA disconnects with ext-AP,
+		and restart on default 2.4G/channel 6.
+
+		./uaputl.exe uap_oper_ctrl  2 2
+		uap stops and restart automatically when in-STA disconnects with ext-AP,
+		and restart on band/channel configured by driver previously.
+
+		./uaputl.exe uap_oper_ctrl  2 3 2 36
+		uap stops and restart automatically when in-STA disconnects with ext-AP,
+		and restart on channel 36, bandwidth 40.
+
+		./uaputl.exe uap_oper_ctrl  0
+		when in-STA disconnects with ext-AP, uap will stay on current operation channel.
+
+		./uaputl.exe uap_oper_ctrl
+		Get current uap operation control setting.
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANEVENT
+
+NAME
+mlanevent.exe
+
+This tool can be used to listen for and obtain events from the uAP driver
+through the netlink layer.
+
+----------------
+Supported events
+----------------
+STA_DEAUTH
+STA_ASSOC
+BSS_START
+BSS_IDLE
+BSS_ACTIVE
+
+-----------------
+Details of events
+-----------------
+
+STA_DEAUTH
+----------
+    For this event, the following information is shown:
+        + Deauthenticated STA MAC address.
+        + Reason for deauthentication.
+
+STA_ASSOC
+---------
+    For this event, the following information is shown:
+        + STA MAC address.
+
+BSS_START
+---------
+    For this event, the following information is shown:
+        + AP MAC address.
+
+BSS_IDLE
+--------
+    For this event, there is no associated information.
+
+BSS_ACTIVE
+----------
+    For this event, there is no associated information.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  IWPRIV
+
+NAME
+	This manual describes the usage of private commands used in Marvell MLAN
+	Linux UAP Driver.
+
+	To use parameters as hex format, a '0x' must precede it for the parameters to
+	be parsed properly.
+
+SYNOPSIS
+	iwpriv <uapX> <command> [sub-command] ...
+
+	iwpriv uapX version
+	iwpriv uapX verext
+	iwpriv uapX start
+	iwpriv uapX stop
+	iwpriv uapX bssstart
+	iwpriv uapX bssstop
+	iwpriv uapX fwreload <path>
+	iwpriv uapX apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,[SEC,][KEY,]
+	                   [CHANNEL,][PREAMBLE,][MAX_SCB,][END]"
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell MLAN
+	card via the Linux device driver.
+
+	The uapX parameter specifies the network device that is to be used to
+	perform this command on. It could be uap0, uap1 etc.
+
+version
+	This is used to get the current version of the driver and the firmware.
+
+verext
+	Retrieve and display an extended version string from the firmware
+
+	Usage:
+		iwpriv uapX verext [#]
+
+	where [#] is an optional argument to retrieve a specific version string,
+	omission of the argument retrieves the 0 indexed string.
+
+start
+	Start the uAP driver.
+
+	Usage:
+		iwpriv uapX start
+
+stop
+	Stop the uAP driver.
+
+	Usage:
+		iwpriv uapX stop
+
+bssstart
+	Start the AP mode, so that uAP will start transmitting beacon.
+
+	Usage:
+		iwpriv uapX bssstart
+
+bssstop
+	Stop the AP mode and disconnect all stations. uAP will stop
+	transmitting beacon as well.
+
+	Usage:
+		iwpriv uapX bssstop
+
+fwreload
+	Reload the firmware. Here string "FW_PATH=" in the path
+	argument is mandatory part.
+
+	Usage:
+		iwpriv uapX fwreload <path>
+
+apcfg
+	This command is used to set the AP configurations. Here string
+	"ASCII_CMD=AP_CFG" is minimum requirement in the ASCII string.
+	Note: BSS will be stopped then restarted if BSS is already started
+	when the command is received.
+
+	Usage:
+		iwpriv uapX apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,[SEC=sec,]
+			[KEY=key,][CHANNEL=channel,][MAX_SCB=max_scb,][END]"
+
+	Where the parameters are:
+		SSID:       Set SSID to be used in beacon and probe response
+		[SEC]:      Security modes - open, wep128, wpa-psk or wpa2-psk
+		            11n will be auto disabled in wep128 and wpa-psk mode
+		[KEY]:      Encrypted key for wep128, wpa-psk or wpa2-psk, minimum 8 chars
+		[CHANNEL]:  Channel to be selected
+		[MAX_SCB]:  Maximum STA number
+		[END]:      Optional termination in ASCII string
+
+	Examples:
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP"
+                                        : Set AP SSID to "TEST_uAP"
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,SEC=open"
+                                        : Set AP SSID to "TEST_uAP" and
+                                          security mode is disabled
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,SEC=WPA2-PSK,KEY=ecbe5facdbfe234a"
+                                        : Set AP SSID to "TEST_uAP" and security mode
+                                          to WPA2-SPK and encrypted key ecbe5facdbfe234a
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,CHANNEL=8"
+                                        : Set AP SSID to "TEST_uAP" and
+                                          set the AP channel to 8
+
+===============================================================================
diff --git a/wlan_sd8897/README_WIFIDIRECT b/wlan_sd8897/README_WIFIDIRECT
new file mode 100644
index 0000000..b56602a
--- /dev/null
+++ b/wlan_sd8897/README_WIFIDIRECT
@@ -0,0 +1,448 @@
+
+===============================================================================
+
+        S E T U P  I N S T R U C T I O N S F O R  *WifiDirect*
+
+Driver,FW release:
+
+1. Make sure, bg_scan.conf,uaputl.conf has SSID starting with "DIRECT-"
+2. Download uAP configuration and BG scan configuration.
+3. This version of wifidirectutl breaks the backward compatibility and will work
+with following releases -
+    8797 >= 14.xx.16.p15
+         >= 14.xx.11.p138
+    8766 >= 14.xx.11.p138
+    8787 >= 14.xx.9.p89
+
+    However, In case one needs to run the utility in backward compatibility mode
+    he can do so by running following command before running the utility -
+
+    # export WIFIDIR_USE_FIXED_IE_INDICES=1
+
+    To disable backward comaptibility mode run following command -
+
+    # export WIFIDIR_USE_FIXED_IE_INDICES=0
+
+WPSWIFIDIRECT release:
+
+1. Modify the wifidirect.conf file to specify the correct HW addresses of
+   devices. The DUT mac address and peer mac address needs to be correctly
+   entered.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  WIFIDIRECTUTL
+
+NAME
+	wifidirectutl
+
+This tool can be used to configure WifiDirect parameters.
+
+------------------
+Supported Commands
+------------------
+wifidirect_mode [MODE]
+wifidirect_config [*.conf]
+wifidirect_params_config [*.conf]
+wifidirect_action_frame <*.conf> | [<PeerAddr> <Category> <OuiSubtype> <DialogToken>]
+wifidirect_discovery_request <*.conf>
+wifidirect_discovery_response <*.conf>
+
+wifidirect_cfg_discovery_period [<MinDiscPeriod> <MaxDiscPeriod>]
+wifidirect_cfg_intent [IntentValue]
+wifidirect_cfg_capability [<DeviceCapability> <GroupCapability>]
+wifidirect_cfg_noa <enable|disable> <index> [<counttype> <duration> <interval>]
+wifidirect_cfg_opp_ps <enable|disable> [<CTWindow>]
+wifidirect_cfg_invitation_list [mac_addr]
+wifidirect_cfg_listen_channel [ListenChannel]
+wifidirect_cfg_op_channel [OperatingChannel]
+wifidirect_cfg_persistent_group_record [index] [role]
+           [<groupbss> <deviceId> <ssid> <psk>] [peermac1] [peermac2]
+wifidirect_cfg_persistent_group_invoke [index] | <cancel>
+wifidirect_cfg_presence_req_params [<type> <duration> <interval>]
+wifidirect_cfg_ext_listen_time [<duration> <interval>]
+wifidirect_cfg_provisioning_params [<action> <configMethods> <devicePassword>]
+wifidirect_cfg_wps_params [<action>]
+
+wifidirect_mode [mode]
+----------
+    "./wifidirectutl <iface> wifidirect_mode [mode]"
+
+    This command is used to setup various modes for wifidirect device.
+    The mode 2 can be used only when wifidirect is started using mode 1.
+    The mode 3 should not be used for uAP.
+
+    The supported options are:
+        mode :     0 - stop wifidirect mode
+                   1 - start wifidirect mode
+                   2 - start wifidirect group owner mode
+                   3 - start wifidirect client mode
+                   4 - start wifidirect find phase
+                   5 - stop wifidirect find phase
+        empty - Get current wifidirect mode
+
+    Example:
+        ./wifidirectutl <iface> wifidirect_mode 0
+                Stop wifidirect mode.
+
+        ./wifidirectutl <iface> wifidirect_mode 1
+                Start wifidirect mode.
+
+        ./wifidirectutl <iface> wifidirect_mode
+                Get current WIFIDIRECT start/stop mode.
+
+wifidirect_config
+----------
+    "./wifidirectutl <iface> wifidirect_config [*.conf]"
+
+    This command is used to set/get the wifidirect configuration.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_config wifidirect.conf
+            Read configuration from wifidirect.conf and apply it.
+        ./wifidirectutl <iface> wifidirect_config
+            Read existing wifidirect configuration and display it.
+
+wifidirect_params_config
+----------
+    "./wifidirectutl <iface> wifidirect_params_config [*.conf]"
+
+    This command is used to set/get the wifidirect parameters configuration.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_params_config wifidirect.conf
+            Read parameter configuration from wifidirect.conf and apply it.
+        ./wifidirectutl <iface> wifidirect_params_config
+            Read existing wifidirect parameters's configuration and display it.
+
+wifidirect_action_frame
+----------
+    "./wifidirectutl <iface> wifidirect_action_frame <*.conf> | <PeerAddr> <Category> <OUISubtype> <DialogToken>"
+
+    This command is used to send action frames as specified in config file or on command line.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_action_frame wifidirect.conf
+            Read action_frame from wifidirect.conf and send to peer.
+        ./wifidirectutl <iface> wifidirect_action_frame <PeerAddr> <Category> <OUISubtype> <DialogToken>
+            Read action frame parameters from command line and send to peer.
+
+wifidirect_discovery_request
+----------
+    "./wifidirectutl <iface> wifidirect_discovery_request <*.conf>"
+
+    This command is used to send wifidirect discovery request packet.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_discovery_request wifidirect.conf
+            Read discovery packet from wifidirect.conf and send to peer.
+
+wifidirect_discovery_response
+----------
+    "./wifidirectutl <iface> wifidirect_discovery_response <*.conf>"
+
+    This command is used to send wifidirect discovery response packet.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_discovery_response wifidirect.conf
+            Read discovery packet from wifidirect.conf and send to peer.
+
+wifidirect_cfg_discovery_period
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_discovery_period [<MinDiscPeriod> <MaxDiscPeriod>]"
+
+	This command is used to set or get minimum and maximum discovery period.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_discovery_period 10 20
+		Set minimum discovery interval to 10 and maximum discovery
+		interval to	20.
+
+		./wifidirectutl <iface> wifidirect_cfg_discovery_period
+		Get minimum and maximum discovery interval.
+
+wifidirect_cfg_intent
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_intent [IntentValue]"
+
+	This command is used to set or get intent value.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_intent 12
+		Set intent value to 12.
+
+		./wifidirectutl <iface> wifidirect_cfg_intent
+		Get Group Owner Intent.
+
+wifidirect_cfg_capability
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_capability [<DeviceCapability> <GroupCapability>]"
+
+	This command is used to set or get device capability and group capability.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_capability 10 20
+		Set Device capability to 10 and group capability to 20
+
+		./wifidirectutl <iface> wifidirect_cfg_capability
+		Get Device capability and group capability.
+
+wifidirect_cfg_noa
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_noa <enable|disable> <index> [<counttype> <duration> <interval>]"
+
+	This command is used to set or get NoA parameters like count_type, duration and
+	interval in ms when NoA is enabled. Valid value of index is [0, 1].
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_noa enable 0 10 50 100
+		Enable NoA and set count to 10, duration to 50ms and interval to 100 ms
+            for index 0.
+
+		./wifidirectutl <iface> wifidirect_cfg_noa disable 1
+		Disable NoA at index 1.
+
+		./wifidirectutl <iface> wifidirect_cfg_noa
+		Get NoA settings.
+
+wifidirect_cfg_opp_ps
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_opp_ps <enable|disable> [<CTWindow>]"
+
+	This command is used to set or get Opportunistic power save and CT window.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_opp_ps enable 50
+		Set OppPS and CTwindow value to 50.
+
+		./wifidirectutl <iface> wifidirect_cfg_opp_ps disable
+		Disable OppPS.
+
+		./wifidirectutl <iface> wifidirect_cfg_opp_ps
+		Get OppPS and CT window.
+
+wifidirect_cfg_invitation_list
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_invitation_list [mac_addr]"
+
+	This command is used to set or get invitation list of peers.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_invitation_list 00:50:43:20:23:34
+		Set 00:50:43:20:23:34 in invitation list of peers.
+
+		./wifidirectutl <iface> wifidirect_cfg_invitation_list
+		Get Invitation list of peers.
+
+wifidirect_cfg_listen_channel
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_listen_channel [ListenChannel]"
+
+	This command is used to set or get Listen channel.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_listen_channel 11
+		Set Listen channel to 11.
+
+		./wifidirectutl <iface> wifidirect_cfg_listen_channel
+		Get Listen channel.
+
+wifidirect_cfg_op_channel
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_op_channel [OperatingChannel]"
+
+		This command is used to set or get Operating channel.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_op_channel 11
+		Set Operating channel to 11.
+
+		./wifidirectutl <iface> wifidirect_cfg_op_channel
+		Get Operating channel.
+
+wifidirect_cfg_persistent_group_record
+----------
+		"./wifidirectutl <iface> [index] [role]
+                 [<groupbss> <deviceId> <ssid> <psk>] [peermac1] [peermac2]"
+
+		This command is used to set or get the persistent group record
+        maintained in the device. Valid index is from 0 to 3. The role should be
+        0 for client, 1 for group-owner.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record 0 1
+        00:50:43:12:24:36 00:50:43:13:26:39 "DIRECT-" "1234567890"
+        00:50:43:20:c2:d0
+		Set persistent group record with index 0, role as group owner, bssId and
+        device Id, ssid="DIRECT-", passphrase="1234567890", and peer mac address.
+        The passphrase get converted to PSK.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record 1 1
+        00:50:43:12:24:36 00:50:43:13:26:39 "DIRECT-" "1234567890"
+        0x1234567890123456789012345678901234567890123456789012345678901234
+		Set persistent group record with index 1, role as group owner, bssId and
+        device Id, ssid="DIRECT-", passphrase="1234567890", and peer mac address.
+        The passphrase get converted to PSK.
+        PSK is specified with "0x" prefix and 32 bytes (64 characters).
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record 1
+		Get persistent group record with index 1.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record
+		Get persistent group record for all indices.
+
+wifidirect_cfg_persistent_group_invoke
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_persistent_group_invoke [index] | <cancel>"
+
+		This command is used to invoke a particular persistent group record
+        from the list. Valid index is from 0 to 3.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_invoke 2
+		Invoke persistent group record with index 1.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_invoke cancel
+		Cancel invokation of persistent groups.
+
+wifidirect_cfg_presence_req_params
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_presence_req_params [<type> <duration> <interval>]"
+
+		This command is used to set/get presence request parameters. Type should
+        be 1 for preferred values and 2 for acceptable values.
+
+		./wifidirectutl <iface> wifidirect_cfg_presence_req_params 1 50 100
+		Set duration to 50ms and interval to 100ms.
+
+		./wifidirectutl <iface> wifidirect_cfg_presence_req_params
+		Get presence request parameters.
+
+wifidirect_cfg_ext_listen_time
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_ext_listen_time [<duration> <interval>]"
+
+		This command is used to set/get extended listen timing parameters.
+
+		./wifidirectutl <iface> wifidirect_cfg_ext_listen_time 1200 1300
+		Set availability period to 1200ms and availability interval to 1300 ms.
+
+		./wifidirectutl <iface> wifidirect_cfg_ext_listen_time
+		Get extended listen timing parameters.
+
+wifidirect_cfg_provisioning_params
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_provisioning_params [<action> <configMethod> <devicePassword>]"
+
+		This command is used to set/get provisioning protocol parameters. Action should
+        be 1 for request parameters and 2 for response parameters.
+
+		./wifidirectutl <iface> wifidirect_cfg_provisioning_params 1 0x80 0x04
+		Set config method to 0x86 and device password to 0x04.
+
+		./wifidirectutl <iface> wifidirect_cfg_provisioning_params
+		Get Provision protocol parameters.
+
+wifidirect_cfg_wps_params
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_wps_params [<action>]"
+
+		This command is used to set WPS action. action can be "pin" (pin entered),
+        "pbc"(button pressed) or "none".
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_wps_params pin
+		Indicates pin operation
+
+		./wifidirectutl <iface> wifidirect_cfg_wps_params none
+		Indicates no operation
+
+===============================================================================
+        U S E R  M A N U A L  F O R  WIFIDISPLAY
+
+wifidisplay_mode
+-----------
+            "./wifidirectutl <iface> wifidisplay_mode [<action>]"
+            This command is used to enable or disable wifi-display. The possible values are either 1 or 0.
+		Example:
+		./wifidirectutl <iface> wifidisplay_mode 1
+		Indicates enable wifi_display
+
+		./wifidirectutl <iface> wifidisplay_mode 0
+		Indicates disable wifi_display
+
+wifidisplay_config
+-----------
+            "./wifidirectutl <iface> wifidisplay_config [*.conf]"
+
+            This command is used to set/get the wifidisplay configuration.
+
+             Example:
+             ./wifidirectutl <iface> wifidisplay_config wifidisplay.conf
+             Read configuration from wifidisplay.conf and apply it.
+             ./wifidirectutl <iface> wifidisplay_config
+             Read existing wifidisplay configuration and display it.
+
+wifidisplay_update_devinfo
+----------
+            "./wifidirectutl <iface> wifidisplay_update_devinfo [value]"
+
+            This command is used to set the device information of wifidisplay device information subelement.
+            This command will overwrite the new device information with user defined value.
+
+             Example:
+             ./wifidirectutl <iface> wifidisplay_update_devinfo 10
+             Update device information programmed with new value 10 by overwritting existing value.
+
+wifidisplay_discovery_request
+----------
+            "./wifidirectutl <iface> wifidisplay_discovery_request [*.config]"
+
+            This command is used to send wifi display service discovery request.
+
+            Example:
+            ./wifidirectutl <iface> wifidisplay_discovery_request wifidisplay.conf
+            Read discovery packet from wifidisplay.conf and send to peer.
+
+wifidisplay_discovery_response
+----------
+           "./wifidirectutl <iface> wifidisplay_discovery_response <*.conf>"
+
+           This command is used to send wifidisplay discovery response packet.
+
+           Example:
+           ./wifidirectutl <iface> wifidisplay_discovery_response wifidisplay.conf
+           Read discovery packet from wifidisplay.conf and send to peer.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANEVENT
+
+NAME
+mlanevent.exe
+
+This tool can be used to listen for and obtain events from the driver
+through the netlink layer. This is only used for display/debugging purpose.
+
+----------------
+Supported events
+----------------
+WIFIDIRECT_GENERIC_EVENT
+WIFIDIRECT_SERVICE_DISCOVERY
+
+-----------------
+Details of events
+-----------------
+
+WIFIDIRECT_GENERIC_EVENT
+-----------------
+    For this event, the following information is shown:
+        + Event length.
+        + Event Type indicating Negociation, Invitation, Discoverability,
+		Provision discovery related Request or Response.
+        + Event SubType indicating Client or Group owner role.
+        + Peer MAC address.
+        + Associated WIFIDIRECT IE elements.
+
+WIFIDIRECT_SERVICE_DISCOVERY
+---------------------
+    For this event, the following information is shown:
+        + Peer MAC address.
+        + Service discovery packet details.
diff --git a/wlan_sd8897/gpl-2.0.txt b/wlan_sd8897/gpl-2.0.txt
new file mode 100644
index 0000000..2c62266
--- /dev/null
+++ b/wlan_sd8897/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_sd8897/mapp/mlan2040coex/Makefile b/wlan_sd8897/mapp/mlan2040coex/Makefile
new file mode 100644
index 0000000..0d94daf
--- /dev/null
+++ b/wlan_sd8897/mapp/mlan2040coex/Makefile
@@ -0,0 +1,48 @@
+#
+# File : mlan2040coex/Makefile
+#
+# Copyright (C) 2009-2017, Marvell International Ltd. All Rights Reserved
+
+# Path to the top directory of the mlandriver distribution
+PATH_TO_TOP = ../..
+
+# Determine how we should copy things to the install directory
+ABSPATH := $(filter /%, $(INSTALLDIR))
+RELPATH := $(filter-out /%, $(INSTALLDIR))
+INSTALLPATH := $(ABSPATH)
+ifeq ($(strip $(INSTALLPATH)),)
+INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH)
+endif
+
+# Override CFLAGS for application sources, remove __ kernel namespace defines
+CFLAGS := $(filter-out -D__%, $(ccflags-y))
+# remove KERNEL include dir
+CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS))
+
+#
+# List of application executables to create
+#
+libobjs:= mlan2040coex.o mlan2040misc.o
+exectarget=mlan2040coex
+TARGETS := $(exectarget)
+
+#
+# Make target rules
+#
+
+# All rule compiles list of TARGETS using builtin program target from src rule
+all :
+$(exectarget): $(libobjs)
+	$(CC) $(CFLAGS) $(libobjs) -o $(exectarget)
+
+# Update any needed TARGETS and then copy to the install path
+build install: $(TARGETS)
+	@cp -f $(exectarget) $(INSTALLPATH)
+
+clean:
+	@rm -f $(exectarget)
+	@rm -f *.o
+
+distclean: clean
+	@rm -f *~ core
+	@rm -f tags
diff --git a/wlan_sd8897/mapp/mlan2040coex/mlan2040coex.c b/wlan_sd8897/mapp/mlan2040coex/mlan2040coex.c
new file mode 100644
index 0000000..aa2703b
--- /dev/null
+++ b/wlan_sd8897/mapp/mlan2040coex/mlan2040coex.c
@@ -0,0 +1,1323 @@
+/** @file  mlan2040coex.c
+  *
+  * @brief 11n 20/40 MHz Coex application
+  *
+  * Copyright (C) 2009-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     06/24/2009: initial version
+************************************************************************/
+
+#include    <stdio.h>
+#include    <ctype.h>
+#include    <unistd.h>
+#include    <string.h>
+#include    <signal.h>
+#include    <fcntl.h>
+#include    <stdlib.h>
+#include    <errno.h>
+#include    <sys/socket.h>
+#include    <sys/ioctl.h>
+#include    <linux/if.h>
+#include    <linux/wireless.h>
+#include    <linux/netlink.h>
+#include    <linux/rtnetlink.h>
+#ifdef ANDROID
+#include    <net/if_ether.h>
+#else
+#include    <net/ethernet.h>
+#endif
+#include    "mlan2040coex.h"
+#include    "mlan2040misc.h"
+
+/** coex application's version number */
+#define COEX_VER "M2.0"
+
+/** Initial number of total private ioctl calls */
+#define IW_INIT_PRIV_NUM    128
+/** Maximum number of total private ioctl calls supported */
+#define IW_MAX_PRIV_NUM     1024
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+static char *usage[] = {
+	"Usage: ",
+	"	mlan2040coex [-i <intfname>] [-hvB] ",
+	"	-h = help",
+	"	-v = version",
+	"	-B = run the process in background.",
+	"	(if intfname not present then mlan0 assumed)"
+};
+
+t_s32 sockfd = 0;  /**< socket descriptor */
+char dev_name[IFNAMSIZ + 1];   /**< device name */
+
+/** Flag: is 2040coex command required */
+int coex_cmd_req_flag = FALSE;
+/** Flag: is associated */
+int assoc_flag = FALSE;
+/** Flag: is HT AP */
+int is_ht_ap = FALSE;
+/** terminate flag */
+int terminate_flag = FALSE;
+
+/********************************************************
+		Global Variables
+********************************************************/
+/** OBSS scan parameter of associated AP */
+OBSSScanParam_t cur_obss_scan_param;
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief Prepare command buffer
+ *  @param buffer   Command buffer to be filled
+ *  @param cmd      Command id
+ *  @param num      Number of arguments
+ *  @param args     Arguments list
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static int
+prepare_buffer(t_u8 *buffer, char *cmd, t_u32 num, char *args[])
+{
+	t_u8 *pos = NULL;
+	unsigned int i = 0;
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	/* Flag it for our use */
+	pos = buffer;
+	strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL));
+	pos += (strlen(CMD_MARVELL));
+
+	/* Insert command */
+	strncpy((char *)pos, (char *)cmd, strlen(cmd));
+	pos += (strlen(cmd));
+
+	/* Insert arguments */
+	for (i = 0; i < num; i++) {
+		strncpy((char *)pos, args[i], strlen(args[i]));
+		pos += strlen(args[i]);
+		if (i < (num - 1)) {
+			strncpy((char *)pos, " ", strlen(" "));
+			pos += 1;
+		}
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process OBSS scan table
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_scantable(void)
+{
+	char ssid[MRVDRV_MAX_SSID_LENGTH + 1] = { 0 };
+	unsigned int scan_start;
+	int idx, i = 0, j, already_listed, ssid_len = 0, ssid_idx;
+
+	t_u8 *pcurrent;
+	t_u8 *pnext;
+	IEEEtypes_ElementId_e *pelement_id;
+	t_u8 *pelement_len, ht_cap_present, intol_bit_is_set;
+	int ret = MLAN_STATUS_SUCCESS;
+	t_s32 bss_info_len = 0;
+	t_u32 fixed_field_length = 0;
+
+	IEEEtypes_CapInfo_t cap_info;
+	t_u8 tsf[8];
+	t_u16 beacon_interval;
+	IEEEtypes_HTCap_t *pht_cap;
+
+	wlan_ioctl_get_scan_table_info *prsp_info;
+	wlan_get_scan_table_fixed fixed_fields;
+
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Start preparing the buffer */
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	memset(&cap_info, 0x00, sizeof(cap_info));
+	memset(leg_ap_chan_list, 0, sizeof(leg_ap_chan_list));
+	num_leg_ap_chan = 0;
+
+	scan_start = 1;
+
+	do {
+		/* buffer = CMD_MARVELL + <cmd_string> */
+		prepare_buffer(buffer, "getscantable", 0, NULL);
+		prsp_info =
+			(wlan_ioctl_get_scan_table_info *)(buffer +
+							   strlen(CMD_MARVELL) +
+							   strlen
+							   ("getscantable"));
+
+		prsp_info->scan_number = scan_start;
+
+		/* Perform IOCTL */
+		memset(&ifr, 0, sizeof(struct ifreq));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+		ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+		if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+			if (errno == EAGAIN) {
+				ret = -EAGAIN;
+			} else {
+				perror("mlan2040coex");
+				fprintf(stderr,
+					"mlan2040coex: getscantable fail\n");
+				ret = MLAN_STATUS_FAILURE;
+			}
+			goto done;
+		}
+
+		prsp_info = (wlan_ioctl_get_scan_table_info *)buffer;
+		pcurrent = 0;
+		pnext = prsp_info->scan_table_entry_buf;
+
+		if (scan_start == 1) {
+			printf("----------------------------------------------\n");
+		}
+
+		for (idx = 0; (unsigned int)idx < prsp_info->scan_number; idx++) {
+
+			/*
+			 * Set pcurrent to pnext in case pad bytes are at the end
+			 * of the last IE we processed.
+			 */
+			pcurrent = pnext;
+
+			memcpy((t_u8 *)&fixed_field_length,
+			       (t_u8 *)pcurrent, sizeof(fixed_field_length));
+			pcurrent += sizeof(fixed_field_length);
+
+			memcpy((t_u8 *)&bss_info_len,
+			       (t_u8 *)pcurrent, sizeof(bss_info_len));
+			pcurrent += sizeof(bss_info_len);
+
+			memcpy((t_u8 *)&fixed_fields,
+			       (t_u8 *)pcurrent, sizeof(fixed_fields));
+			pcurrent += fixed_field_length;
+
+			pnext = pcurrent + bss_info_len;
+
+			if (bss_info_len >= (sizeof(tsf)
+					     + sizeof(beacon_interval) +
+					     sizeof(cap_info))) {
+				pcurrent +=
+					(sizeof(tsf) + sizeof(beacon_interval) +
+					 sizeof(cap_info));
+				bss_info_len -=
+					(sizeof(tsf) + sizeof(beacon_interval) +
+					 sizeof(cap_info));
+			}
+			ht_cap_present = FALSE;
+			intol_bit_is_set = FALSE;
+			memset(ssid, 0, MRVDRV_MAX_SSID_LENGTH + 1);
+			ssid_len = 0;
+			while (bss_info_len >= 2) {
+				pelement_id = (IEEEtypes_ElementId_e *)pcurrent;
+				pelement_len = pcurrent + 1;
+				pcurrent += 2;
+
+				switch (*pelement_id) {
+				case SSID:
+					if (*pelement_len &&
+					    *pelement_len <=
+					    MRVDRV_MAX_SSID_LENGTH) {
+						memcpy(ssid, pcurrent,
+						       *pelement_len);
+						ssid_len = *pelement_len;
+					}
+					break;
+
+				case HT_CAPABILITY:
+					pht_cap =
+						(IEEEtypes_HTCap_t *)
+						pelement_id;
+					ht_cap_present = TRUE;
+					if (IS_INTOL_BIT_SET
+					    (le16_to_cpu
+					     (pht_cap->ht_cap.ht_cap_info))) {
+						intol_bit_is_set = TRUE;
+					}
+					break;
+				default:
+					break;
+				}
+				pcurrent += *pelement_len;
+				bss_info_len -= (2 + *pelement_len);
+			}
+			if (!ht_cap_present || intol_bit_is_set) {
+				printf("%s AP found on channel number: %-3d ",
+				       intol_bit_is_set ? "40 MHZ intolerant" :
+				       "Legacy", fixed_fields.channel);
+				if (ssid_len) {
+					printf("SSID: ");
+					/* Print out the ssid or the hex values if non-printable */
+					for (ssid_idx = 0; ssid_idx < ssid_len;
+					     ssid_idx++) {
+						if (isprint(ssid[ssid_idx])) {
+							printf("%c",
+							       ssid[ssid_idx]);
+						} else {
+							printf("\\%02x",
+							       ssid[ssid_idx]);
+						}
+					}
+				}
+				printf("\n");
+
+				/* Verify that the channel is already listed or not */
+				already_listed = FALSE;
+				for (j = 0; j < i; j++) {
+					if (leg_ap_chan_list[j].chan_num ==
+					    fixed_fields.channel) {
+						already_listed = TRUE;
+						if (intol_bit_is_set)
+							leg_ap_chan_list[j].
+								is_intol_set =
+								intol_bit_is_set;
+						break;
+					}
+				}
+				if (!already_listed) {
+					/* add the channel in list */
+					leg_ap_chan_list[i].chan_num =
+						fixed_fields.channel;
+					leg_ap_chan_list[i].is_intol_set =
+						intol_bit_is_set;
+					i++;
+					coex_cmd_req_flag = TRUE;
+					num_leg_ap_chan++;
+				}
+			}
+		}
+		scan_start += prsp_info->scan_number;
+
+	} while (prsp_info->scan_number);
+
+done:
+	if (cmd)
+		free(cmd);
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/** BSS Mode any (both infra and adhoc) */
+#define BSS_MODE_ANY 3
+
+/** current scan config parameters */
+#define SCAN_CFG_PARAMS 7
+
+/** Active : 1 , Passive : 2 */
+#define SCAN_TYPE_ACTIVE 1
+
+/**
+ *  @brief Issue get scan type command
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+get_scan_cfg(int *scan_param)
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	/* Start preparing the buffer */
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* buffer = CMD_MARVELL + <cmd_string> */
+	prepare_buffer(buffer, "scancfg", 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlan2040coex");
+		fprintf(stderr, "mlan2040coex: get_scan_cfg fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	scan_param = (int *)(buffer);
+done:
+	if (cmd)
+		free(cmd);
+	if (buffer)
+		free(buffer);
+
+	return ret;
+}
+
+/**
+ *  @brief Issue OBSS scan command
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_setuserscan(void)
+{
+	wlan_ioctl_user_scan_cfg scan_req;
+	int scan_cfg[SCAN_CFG_PARAMS];
+	t_u8 *buffer = NULL, *pos = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int status = 0;
+
+	memset(&scan_req, 0x00, sizeof(scan_req));
+	memset(scan_cfg, 0x00, SCAN_CFG_PARAMS);
+	coex_cmd_req_flag = FALSE;
+
+	if (get_scan_cfg(scan_cfg) != MLAN_STATUS_SUCCESS) {
+		printf("mlan2040coex: scancfg ioctl failure");
+		return -EFAULT;
+	}
+
+	if (scan_cfg[0] == SCAN_TYPE_ACTIVE)
+		scan_req.chan_list[0].scan_time =
+			(t_u32)le16_to_cpu(cur_obss_scan_param.
+					   obss_scan_active_dwell);
+	else
+		scan_req.chan_list[0].scan_time =
+			(t_u32)le16_to_cpu(cur_obss_scan_param.
+					   obss_scan_passive_total);
+	scan_req.bss_mode = (scan_cfg[1]) ? scan_cfg[1] : BSS_MODE_ANY;
+
+	/* Start preparing the buffer */
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* buffer = CMD_MARVELL + <cmd_string> */
+	prepare_buffer(buffer, "setuserscan", 0, NULL);
+	pos = buffer + strlen(CMD_MARVELL) + strlen("setuserscan");
+
+	/* buffer = buffer + 'scan_req' */
+	memcpy(pos, &scan_req, sizeof(wlan_ioctl_user_scan_cfg));
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlan2040coex");
+		fprintf(stderr, "mlan2040coex: setuserscan fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+    /** process scan results */
+	do {
+		status = process_scantable();
+	} while (status == -EAGAIN);
+
+	if (cmd)
+		free(cmd);
+	if (buffer)
+		free(buffer);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Display usage
+ *
+ *  @return       NA
+ */
+static t_void
+display_usage(t_void)
+{
+	t_u32 i;
+	for (i = 0; i < NELEMENTS(usage); i++)
+		fprintf(stderr, "%s\n", usage[i]);
+}
+
+/**
+ *  @brief              get connection status
+ *
+ *  @param data         Pointer to the output buffer holding connection status
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+int
+get_connstatus(int *data)
+{
+	struct ether_addr apaddr;
+	struct ether_addr etherzero = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* buffer = CMD_MARVELL + <cmd_string> */
+	prepare_buffer(buffer, "getwap", 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlan2040coex");
+		fprintf(stderr, "mlan2040coex: getwap fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(&apaddr, 0, sizeof(struct ether_addr));
+	memcpy(&apaddr, (struct ether_addr *)(buffer),
+	       sizeof(struct ether_addr));
+
+	if (!memcmp(&apaddr, &etherzero, sizeof(struct ether_addr))) {
+		/* not associated */
+		*data = FALSE;
+	} else {
+		/* associated */
+		*data = TRUE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Print connect and disconnect event related information
+ *
+ *  @param buffer   Pointer to received event buffer
+ *  @param size     Length of the received event
+ *
+ *  @return         N/A
+ */
+void
+print_event_drv_connected(t_u8 *buffer, t_u16 size)
+{
+	struct ether_addr *wap;
+	struct ether_addr etherzero = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
+	char buf[32];
+
+	wap = (struct ether_addr *)(buffer + strlen(CUS_EVT_AP_CONNECTED));
+
+	if (!memcmp(wap, &etherzero, sizeof(struct ether_addr))) {
+		printf("---< Disconnected from AP >---\n");
+		memset(&cur_obss_scan_param, 0, sizeof(cur_obss_scan_param));
+		assoc_flag = FALSE;
+		is_ht_ap = FALSE;
+	} else {
+		memset(buf, 0, sizeof(buf));
+		snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X",
+			 wap->ether_addr_octet[0],
+			 wap->ether_addr_octet[1],
+			 wap->ether_addr_octet[2],
+			 wap->ether_addr_octet[3],
+			 wap->ether_addr_octet[4], wap->ether_addr_octet[5]);
+		printf("---< Connected to AP: %s >---\n", buf);
+	/** set TRUE, if connected */
+		assoc_flag = TRUE;
+	}
+}
+
+/**
+ *  @brief Parse and print received event information
+ *
+ *  @param event    Pointer to received event
+ *  @param size     Length of the received event
+ *  @param evt_conn     A pointer to a output buffer. It sets TRUE when it gets
+ *  					the event CUS_EVT_OBSS_SCAN_PARAM, otherwise FALSE
+ *  @param if_name  The interface name
+ *
+ *  @return         N/A
+ */
+void
+print_event(event_header *event, t_u16 size, int *evt_conn, char *if_name)
+{
+	if (!strncmp
+	    (CUS_EVT_AP_CONNECTED, (char *)event,
+	     strlen(CUS_EVT_AP_CONNECTED))) {
+		if (strlen(if_name))
+			printf("EVENT for interface %s\n", if_name);
+		print_event_drv_connected((t_u8 *)event, size);
+		return;
+	}
+	if (!strncmp
+	    (CUS_EVT_OBSS_SCAN_PARAM, (char *)event,
+	     strlen(CUS_EVT_OBSS_SCAN_PARAM))) {
+		if (strlen(if_name))
+			printf("EVENT for interface %s\n", if_name);
+		printf("---< %s >---\n", CUS_EVT_OBSS_SCAN_PARAM);
+		memset(&cur_obss_scan_param, 0, sizeof(cur_obss_scan_param));
+		memcpy(&cur_obss_scan_param,
+		       ((t_u8 *)event + strlen(CUS_EVT_OBSS_SCAN_PARAM) + 1),
+		       sizeof(cur_obss_scan_param));
+	/** set TRUE, since it is an HT AP */
+		is_ht_ap = TRUE;
+		*evt_conn = TRUE;
+		return;
+	}
+	if (!strncmp
+	    (CUS_EVT_BW_CHANGED, (char *)event, strlen(CUS_EVT_BW_CHANGED))) {
+		if (strlen(if_name))
+			printf("EVENT for interface %s\n", if_name);
+		printf("---< %s >---\n", CUS_EVT_BW_CHANGED);
+		return;
+	}
+}
+
+/**
+ *  @brief              This function parses for NETLINK events
+ *
+ *  @param nlh          Pointer to Netlink message header
+ *  @param bytes_read   Number of bytes to be read
+ *  @param evt_conn     A pointer to a output buffer. It sets TRUE when it gets
+ *  					the event CUS_EVT_OBSS_SCAN_PARAM, otherwise FALSE
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static int
+drv_nlevt_handler(struct nlmsghdr *nlh, int bytes_read, int *evt_conn)
+{
+	int len, plen;
+	t_u8 *buffer = NULL;
+	t_u32 event_id = 0;
+	event_header *event = NULL;
+	char if_name[IFNAMSIZ + 1];
+
+	/* Initialize receive buffer */
+	buffer = (t_u8 *)malloc(NL_MAX_PAYLOAD);
+	if (!buffer) {
+		printf("ERR: Could not alloc buffer\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	memset(buffer, 0, NL_MAX_PAYLOAD);
+
+	*evt_conn = FALSE;
+	while ((unsigned int)bytes_read >= NLMSG_HDRLEN) {
+		len = nlh->nlmsg_len;	/* Length of message including header */
+		plen = len - NLMSG_HDRLEN;
+		if (len > bytes_read || plen < 0) {
+			/* malformed netlink message */
+			return MLAN_STATUS_FAILURE;
+		}
+		if ((unsigned int)len > NLMSG_SPACE(NL_MAX_PAYLOAD)) {
+			printf("ERR:Buffer overflow!\n");
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(buffer, 0, NL_MAX_PAYLOAD);
+		memcpy(buffer, NLMSG_DATA(nlh), plen);
+
+		if (NLMSG_OK(nlh, len)) {
+			memcpy(&event_id, buffer, sizeof(event_id));
+
+			if (((event_id & 0xFF000000) == 0x80000000) ||
+			    ((event_id & 0xFF000000) == 0)) {
+				event = (event_header *)buffer;
+			} else {
+				memset(if_name, 0, IFNAMSIZ + 1);
+				memcpy(if_name, buffer, IFNAMSIZ);
+				event = (event_header *)(buffer + IFNAMSIZ);
+			}
+		}
+
+		print_event(event, bytes_read, evt_conn, if_name);
+		len = NLMSG_ALIGN(len);
+		bytes_read -= len;
+		nlh = (struct nlmsghdr *)((char *)nlh + len);
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/** Maximum event message length */
+#define MAX_MSG_LENGTH	1024
+
+/**
+ *  @brief Configure and read event data from netlink socket
+ *
+ *  @param nl_sk        Netlink socket handler
+ *  @param msg          Pointer to message header
+ *  @param ptv          Pointer to struct timeval
+ *
+ *  @return             Number of bytes read or MLAN_STATUS_FAILURE
+ */
+int
+read_event(int nl_sk, struct msghdr *msg, struct timeval *ptv)
+{
+	int count = -1;
+	int ret = MLAN_STATUS_FAILURE;
+	fd_set rfds;
+
+	/* Setup read fds and initialize event buffers */
+	FD_ZERO(&rfds);
+	FD_SET(nl_sk, &rfds);
+
+	/* Wait for reply */
+	ret = select(nl_sk + 1, &rfds, NULL, NULL, ptv);
+
+	if (ret == MLAN_STATUS_FAILURE) {
+		/* Error */
+		terminate_flag++;
+		ptv->tv_sec = DEFAULT_SCAN_INTERVAL;
+		ptv->tv_usec = 0;
+		goto done;
+	} else if (!ret) {
+		if (assoc_flag && is_ht_ap) {
+	    /** Issue OBSS scan */
+			process_setuserscan();
+	    /** Invoke 2040coex command, if any legacy AP found or
+             *  any AP has 40MHz intolarent bit set */
+			if (coex_cmd_req_flag)
+				invoke_coex_command();
+		}
+		if (assoc_flag && is_ht_ap) {
+			/* Timeout. Try again after BSS channel width triger scan
+			   interval when the STA is connected with a HT AP */
+			ptv->tv_sec =
+				(t_u32)le16_to_cpu(cur_obss_scan_param.
+						   bss_chan_width_trigger_scan_int);
+		} else {
+			/* Timeout. Try again after default duration when the STA is
+			   not connected with a HT AP */
+			ptv->tv_sec = DEFAULT_SCAN_INTERVAL;
+		}
+		ptv->tv_usec = 0;
+		goto done;
+	}
+
+	if (!FD_ISSET(nl_sk, &rfds)) {
+		/* Unexpected error. Try again */
+		ptv->tv_sec = DEFAULT_SCAN_INTERVAL;
+		ptv->tv_usec = 0;
+		goto done;
+	}
+	/* Success */
+	count = recvmsg(nl_sk, msg, 0);
+
+done:
+	return count;
+}
+
+/** Maximum event message length */
+#define MAX_MSG_LENGTH	1024
+/**
+ *  @brief Run the application
+ *
+ *  @param nl_sk    Netlink socket
+ *
+ *  @return         N/A
+ */
+void
+run_app(int nl_sk)
+{
+	struct timeval tv;
+	int bytes_read, evt_conn;
+	struct msghdr msg;
+	struct sockaddr_nl dest_addr;
+	struct nlmsghdr *nlh;
+	struct iovec iov;
+
+    /** Get connection status */
+	if (get_connstatus(&assoc_flag) == MLAN_STATUS_FAILURE)
+		return;
+
+	/* Initialize timeout value */
+	tv.tv_sec = DEFAULT_SCAN_INTERVAL;
+	tv.tv_usec = 0;
+
+	/* Initialize netlink header */
+	nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(NL_MAX_PAYLOAD));
+	if (!nlh) {
+		printf("ERR: Could not allocate space for netlink header\n");
+		goto done;
+	}
+	memset(nlh, 0, NLMSG_SPACE(NL_MAX_PAYLOAD));
+	/* Fill the netlink message header */
+	nlh->nlmsg_len = NLMSG_SPACE(NL_MAX_PAYLOAD);
+	nlh->nlmsg_pid = getpid();	/* self pid */
+	nlh->nlmsg_flags = 0;
+
+	/* Initialize I/O vector */
+	memset(&iov, 0, sizeof(struct iovec));
+	iov.iov_base = (void *)nlh;
+	iov.iov_len = nlh->nlmsg_len;
+
+	/* Set destination address */
+	memset(&dest_addr, 0, sizeof(struct sockaddr_nl));
+	dest_addr.nl_family = AF_NETLINK;
+	dest_addr.nl_pid = 0;	/* Kernel */
+	dest_addr.nl_groups = NL_MULTICAST_GROUP;
+
+	/* Initialize message header */
+	memset(&msg, 0, sizeof(struct msghdr));
+	msg.msg_name = (void *)&dest_addr;
+	msg.msg_namelen = sizeof(dest_addr);
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+
+	while (!terminate_flag) {
+		/* event buffer is received for all the interfaces */
+		bytes_read = read_event(nl_sk, &msg, &tv);
+		/* handle only NETLINK events here */
+		drv_nlevt_handler((struct nlmsghdr *)nlh, bytes_read,
+				  &evt_conn);
+		if (assoc_flag && is_ht_ap) {
+	    /** If the event is connected with an HT AP then issue OBSS scan immediately */
+			if (evt_conn) {
+		/** Issue OBSS scan */
+				process_setuserscan();
+		/** Invoke 2040coex command, if any legacy AP found or
+                 *  any AP has 40MHz intolarent bit set */
+				if (coex_cmd_req_flag)
+					invoke_coex_command();
+			}
+			tv.tv_sec =
+				(t_u32)le16_to_cpu(cur_obss_scan_param.
+						   bss_chan_width_trigger_scan_int);
+		} else {
+			tv.tv_sec = DEFAULT_SCAN_INTERVAL;
+		}
+		tv.tv_usec = 0;
+	}
+
+done:
+	if (nl_sk > 0)
+		close(nl_sk);
+	if (nlh)
+		free(nlh);
+	return;
+}
+
+/**
+ *  @brief Determine the netlink number
+ *
+ *  @return         Netlink number to use
+ */
+static int
+get_netlink_num(int dev_index)
+{
+	FILE *fp = NULL;
+	int netlink_num = NETLINK_MARVELL;
+	char str[64];
+	char *srch = "netlink_num";
+	char filename[64];
+
+	if (dev_index == 0) {
+		strcpy(filename, "/proc/mwlan/config");
+	} else if (dev_index > 0) {
+		sprintf(filename, "/proc/mwlan/config%d", dev_index);
+	}
+	/* Try to open /proc/mwlan/config$ */
+	fp = fopen(filename, "r");
+
+	if (fp) {
+		while (!feof(fp)) {
+			fgets(str, sizeof(str), fp);
+			if (strncmp(str, srch, strlen(srch)) == 0) {
+				netlink_num = atoi(str + strlen(srch) + 1);
+				break;
+			}
+		}
+		fclose(fp);
+	} else {
+		return -1;
+	}
+
+	printf("Netlink number = %d\n", netlink_num);
+	return netlink_num;
+}
+
+/**
+ *  @brief opens netlink socket to receive NETLINK events
+ *  @return  socket id --success, otherwise--MLAN_STATUS_FAILURE
+ */
+int
+open_netlink(int dev_index)
+{
+	int sk = -1;
+	struct sockaddr_nl src_addr;
+	int netlink_num = 0;
+
+	netlink_num = get_netlink_num(dev_index);
+	if (netlink_num < 0) {
+		printf("ERR:Could not get netlink socket. Invalid device number.\n");
+		return sk;
+	}
+
+	/* Open netlink socket */
+	sk = socket(PF_NETLINK, SOCK_RAW, netlink_num);
+	if (sk < 0) {
+		printf("ERR:Could not open netlink socket.\n");
+		return sk;
+	}
+
+	/* Set source address */
+	memset(&src_addr, 0, sizeof(src_addr));
+	src_addr.nl_family = AF_NETLINK;
+	src_addr.nl_pid = getpid();
+	src_addr.nl_groups = NL_MULTICAST_GROUP;
+
+	/* Bind socket with source address */
+	if (bind(sk, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0) {
+		printf("ERR:Could not bind socket!\n");
+		close(sk);
+		return -1;
+	}
+	return sk;
+}
+
+/**
+ *  @brief Terminate signal handler
+ *  @param signal   Signal to handle
+ *  @return         NA
+ */
+static t_void
+terminate_handler(int signal)
+{
+	printf("Stopping application.\n");
+#if DEBUG
+	printf("Process ID of process killed = %d\n", getpid());
+#endif
+	terminate_flag = TRUE;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Process host command
+ *  @param hostcmd_idx  Host command index
+ *  @param chan_list    A pointer to a channel list
+ *  @param chan_num     Number of channels in the channel list
+ *  @param reg_class    Regulatory class of the channels
+ *  @param is_intol_ap_present Flag:is there any 40 MHz intolerant AP is present or not
+ *
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_host_cmd(int hostcmd_idx, t_u8 *chan_list, t_u8 chan_num,
+		 t_u8 reg_class, t_u8 is_intol_ap_present)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, "hostcmd", 0, NULL);
+	switch (hostcmd_idx) {
+	case CMD_2040COEX:
+		prepare_coex_cmd_buff(buffer + strlen(CMD_MARVELL) +
+				      strlen("hostcmd"), chan_list, chan_num,
+				      reg_class, is_intol_ap_present);
+		break;
+	default:
+		break;
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlan2040coex");
+		fprintf(stderr, "mlan2040coex: hostcmd fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	ret = process_host_cmd_resp("hostcmd", buffer);
+
+done:
+	if (cmd)
+		free(cmd);
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Check the STA is 40 MHz intolerant or not
+ *  @param intol	Flag: TRUE when the STA is 40 MHz intolerant, otherwise FALSE
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+is_intolerant_sta(int *intol)
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int htcap_info, ret = MLAN_STATUS_SUCCESS;
+
+	*intol = FALSE;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* buffer = CMD_MARVELL + <cmd_string> */
+	prepare_buffer(buffer, "htcapinfo", 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlan2040coex");
+		fprintf(stderr, "mlan2040coex: htcapinfo fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	htcap_info = *((int *)(buffer));
+
+	if (htcap_info & MBIT(8))
+		*intol = TRUE;
+
+done:
+	if (cmd)
+		free(cmd);
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief get region code
+ *  @param reg_code	Pointer to region code
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+get_region_code(int *reg_code)
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* buffer = CMD_MARVELL + <cmd_string> */
+	prepare_buffer(buffer, "regioncode", 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlan2040coex");
+		fprintf(stderr, "mlan2040coex: regioncode fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memcpy(reg_code, buffer, sizeof(int));
+done:
+	if (cmd)
+		free(cmd);
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/** No option */
+#define NO_OPTION -1
+
+/**
+ *  @brief Entry function for coex
+ *  @param argc		number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+main(int argc, char *argv[])
+{
+	char ifname[IFNAMSIZ + 1] = "mlan0";
+	int c, daemonize = FALSE;
+	t_s32 nl_sk;
+		  /**< netlink socket descriptor to receive an event */
+	int dev_index = 0;	     /** initialise with -1 to open multiple NETLINK Sockets */
+
+	char temp[2];
+	int arg_count = 0;
+	int ifname_given = FALSE;
+
+	for (;;) {
+		c = getopt(argc, argv, "Bhi:vd:");
+		/* check if all command-line options have been parsed */
+		if (c == NO_OPTION)
+			break;
+
+		switch (c) {
+		case 'B':
+			daemonize = TRUE;
+			break;
+		case 'h':
+			display_usage();
+			return MLAN_STATUS_SUCCESS;
+		case 'v':
+			fprintf(stdout,
+				"Marvell 20/40coex application version %s\n",
+				COEX_VER);
+			return MLAN_STATUS_SUCCESS;
+		case 'i':
+			ifname_given = TRUE;
+			if (strlen(optarg) < IFNAMSIZ)
+				strncpy(ifname, optarg, IFNAMSIZ - 1);
+			else {
+				fprintf(stdout, "Interface name too long\n");
+				display_usage();
+				return MLAN_STATUS_SUCCESS;
+			}
+			arg_count += 1;
+			break;
+		case 'd':
+			strncpy(temp, optarg, strlen(optarg));
+			if (isdigit(temp[0]))
+				dev_index = atoi(temp);
+			arg_count += 1;
+			break;
+		default:
+			fprintf(stdout, "Invalid argument\n");
+			display_usage();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	if (!ifname_given) {
+		sprintf(ifname, "mlan%d", dev_index);
+	}
+
+	if (optind < argc) {
+		fputs("Too many arguments.\n", stderr);
+		display_usage();
+		goto done;
+	}
+
+	strncpy(dev_name, ifname, IFNAMSIZ - 1);
+
+	/* create a socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		fprintf(stderr, "mlan2040coex: Cannot open socket.\n");
+		goto done;
+	}
+
+	/* create netlink sockets and bind them with app side addr */
+	nl_sk = open_netlink(dev_index);
+
+	if (nl_sk < 0) {
+		fprintf(stderr, "mlan2040coex: Cannot open netlink socket.\n");
+		goto done;
+	}
+
+	signal(SIGHUP, terminate_handler);	/* catch hangup signal */
+	signal(SIGTERM, terminate_handler);	/* catch kill signal */
+	signal(SIGINT, terminate_handler);	/* catch kill signal */
+	signal(SIGALRM, terminate_handler);	/* catch kill signal */
+
+    /** Make the process background-process */
+	if (daemonize) {
+		if (daemon(0, 0))
+			fprintf(stderr, "mlan2040coex: Cannot start daemon\n");
+	}
+
+    /** run the application */
+	run_app(nl_sk);
+
+done:
+	if (sockfd > 0)
+		close(sockfd);
+	if (nl_sk > 0)
+		close(nl_sk);
+
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/wlan_sd8897/mapp/mlan2040coex/mlan2040coex.h b/wlan_sd8897/mapp/mlan2040coex/mlan2040coex.h
new file mode 100644
index 0000000..01339d8
--- /dev/null
+++ b/wlan_sd8897/mapp/mlan2040coex/mlan2040coex.h
@@ -0,0 +1,233 @@
+/** @file  mlan2040coex.h
+  *
+  * @brief This file contains definitions for application
+  *
+  * Copyright (C) 2009-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     06/24/2009: initial version
+************************************************************************/
+#ifndef _COEX_H_
+#define _COEX_H_
+
+/** Marvell private command identifier */
+#define CMD_MARVELL "MRVL_CMD"
+
+/** IOCTL number */
+#define MLAN_ETH_PRIV       (SIOCDEVPRIVATE + 14)
+
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#undef BIG_ENDIAN_SUPPORT
+#endif
+
+/** 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) ))
+
+/** Convert to correct endian format */
+#ifdef 	BIG_ENDIAN_SUPPORT
+/** CPU to little-endian convert for 16-bit */
+#define 	cpu_to_le16(x)	swap_byte_16(x)
+/** CPU to little-endian convert for 32-bit */
+#define		cpu_to_le32(x)  swap_byte_32(x)
+/** CPU to little-endian convert for 64-bit */
+#define     cpu_to_le64(x)  swap_byte_64(x)
+/** Little-endian to CPU convert for 16-bit */
+#define 	le16_to_cpu(x)	swap_byte_16(x)
+/** Little-endian to CPU convert for 32-bit */
+#define		le32_to_cpu(x)  swap_byte_32(x)
+/** Little-endian to CPU convert for 64-bit */
+#define     le64_to_cpu(x)  swap_byte_64(x)
+#else
+/** Do nothing */
+#define		cpu_to_le16(x)	(x)
+/** Do nothing */
+#define		cpu_to_le32(x)  (x)
+/** Do nothing */
+#define		cpu_to_le64(x)  (x)
+/** Do nothing */
+#define 	le16_to_cpu(x)	(x)
+/** Do nothing */
+#define 	le32_to_cpu(x)	(x)
+/** Do nothing */
+#define 	le64_to_cpu(x)	(x)
+#endif
+
+#ifdef __GNUC__
+/** Structure packing begins */
+#define PACK_START
+/** Structure packeing end */
+#define PACK_END  __attribute__ ((packed))
+#else
+/** Structure packing begins */
+#define PACK_START   __packed
+/** Structure packeing end */
+#define PACK_END
+#endif
+
+/** Character, 1 byte */
+typedef signed char t_s8;
+/** Unsigned character, 1 byte */
+typedef unsigned char t_u8;
+
+/** Short integer */
+typedef signed short t_s16;
+/** Unsigned short integer */
+typedef unsigned short t_u16;
+
+/** Integer */
+typedef signed int t_s32;
+/** Unsigned integer */
+typedef unsigned int t_u32;
+
+/** Long long integer */
+typedef signed long long t_s64;
+/** Unsigned long long integer */
+typedef unsigned long long t_u64;
+
+/** Void pointer (4-bytes) */
+typedef void t_void;
+
+#ifdef FALSE
+#undef FALSE
+#endif
+
+#ifdef TRUE
+#undef TRUE
+#endif
+
+#ifndef MIN
+/** Find minimum value */
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+/** Type definition: boolean */
+typedef enum { FALSE, TRUE } boolean;
+
+/** Find number of elements */
+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
+/** Success */
+#define MLAN_STATUS_SUCCESS         (0)
+/** Failure */
+#define MLAN_STATUS_FAILURE         (-1)
+
+/** Enumeration for host-command index */
+enum COMMANDS {
+	CMD_2040COEX = 1,
+};
+/** Maximum number of channels that can be sent in a setuserscan ioctl */
+#define WLAN_IOCTL_USER_SCAN_CHAN_MAX  50
+
+#ifndef ETH_ALEN
+/** MAC address length */
+#define ETH_ALEN    6
+#endif
+
+/** Netlink protocol number */
+#define NETLINK_MARVELL         (MAX_LINKS - 1)
+/** Netlink maximum payload size */
+#define NL_MAX_PAYLOAD          1024
+/** Netlink multicast group number */
+#define NL_MULTICAST_GROUP      RTMGRP_LINK
+/** Default wait time in seconds for events */
+#define UAP_RECV_WAIT_DEFAULT   10
+#ifndef NLMSG_HDRLEN
+/** NL message header length */
+#define NLMSG_HDRLEN            ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#endif
+
+/** Event header */
+typedef PACK_START struct _event_header {
+    /** Event ID */
+	t_u32 event_id;
+    /** Event data */
+	t_u8 event_data[0];
+} PACK_END event_header;
+
+/** Event ID length */
+#define EVENT_ID_LEN    4
+
+/** Custom events definitions */
+/** 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 events definitions end */
+
+/** Structure defination of chan_intol_t*/
+typedef struct _chan_intol_t {
+    /** Channel numer */
+	t_u8 chan_num;
+    /** Flag: Is any 40MHz intolerant AP found in this channel */
+	t_u8 is_intol_set;
+} chan_intol_t;
+
+/** Private command structure */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+struct eth_priv_cmd {
+    /** Command buffer pointer */
+	t_u64 buf;
+    /** buffer updated by driver */
+	int used_len;
+    /** buffer sent by application */
+	int total_len;
+} __ATTRIB_PACK__;
+#else
+struct eth_priv_cmd {
+    /** Command buffer */
+	t_u8 *buf;
+    /** Used length */
+	int used_len;
+    /** Total length */
+	int total_len;
+};
+#endif
+
+/** Legacy APs channel list */
+chan_intol_t leg_ap_chan_list[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
+/** Total number of channel present in Legacy APs channel list */
+t_u8 num_leg_ap_chan;
+int get_region_code(int *reg_code);
+int process_host_cmd(int cmd, t_u8 *chan_list, t_u8 chan_num, t_u8 reg_class,
+		     t_u8 is_intol_ap_present);
+int is_intolerant_sta(int *intol);
+
+#endif /* _COEX_H_ */
diff --git a/wlan_sd8897/mapp/mlan2040coex/mlan2040misc.c b/wlan_sd8897/mapp/mlan2040coex/mlan2040misc.c
new file mode 100644
index 0000000..004e09b
--- /dev/null
+++ b/wlan_sd8897/mapp/mlan2040coex/mlan2040misc.c
@@ -0,0 +1,280 @@
+/** @file  mlan2040misc.c
+  *
+  * @brief This file contains helper functions for coex application
+  *
+  * Copyright (C) 2009-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     06/24/2009: initial version
+************************************************************************/
+#include    <stdio.h>
+#include    <ctype.h>
+#include    <string.h>
+#include    <stdlib.h>
+#include    "mlan2040coex.h"
+#include    "mlan2040misc.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+/** Regulatory class and Channel mapping for various regions */
+static class_chan_t us_class_chan_t[] = {
+	{32, {1, 2, 3, 4, 5, 6, 7}, 7},
+	{33, {5, 6, 7, 8, 9, 10, 11}, 7}
+};
+
+static class_chan_t europe_class_chan_t[] = {
+	{11, {1, 2, 3, 4, 5, 6, 7, 8, 9}, 9},
+	{12, {5, 6, 7, 8, 9, 10, 11, 12, 13}, 9}
+};
+
+static class_chan_t japan_class_chan_t[] = {
+	{56, {1, 2, 3, 4, 5, 6, 7, 8, 9}, 9},
+	{57, {5, 6, 7, 8, 9, 10, 11, 12, 13}, 9},
+	{58, {14}, 1}
+};
+
+/** Region-code(Regulatory domain) and Class-channel table mapping */
+static region_class_chan_t region_class_chan_table[] = {
+	{0x10, us_class_chan_t, sizeof(us_class_chan_t) / sizeof(class_chan_t)}	/* US */
+	,
+	{0x20, us_class_chan_t, sizeof(us_class_chan_t) / sizeof(class_chan_t)}	/* CANADA */
+	,
+	{0x30, europe_class_chan_t, sizeof(europe_class_chan_t) / sizeof(class_chan_t)}	/* EUROPE */
+	,
+	{0x32, europe_class_chan_t, sizeof(europe_class_chan_t) / sizeof(class_chan_t)}	/* FRANCE */
+	,
+	{0x40, japan_class_chan_t, sizeof(japan_class_chan_t) / sizeof(class_chan_t)}	/* JAPAN */
+	,
+	{0x41, japan_class_chan_t, sizeof(japan_class_chan_t) / sizeof(class_chan_t)}	/* JAPAN */
+	,
+	{0x50, europe_class_chan_t, sizeof(europe_class_chan_t) / sizeof(class_chan_t)}	/* CHINA */
+};
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief  This function prepares the channel list for a particular
+ *  		regulatory class from channel number for legacy AP
+ *  @param cur_class_chan_table  A pointer to the class_chan_t
+ *  @param num_entry             Number of entry in cur_class_chan_table table
+ *  @param chan_list             A pointer to the output channel list
+ *  @param chan_num	             total number of channel in output channel list
+ *  @param reg_domain            regulatory domain
+ *  @param reg_class             regulatory class
+ *  @param is_intol_ap_present   It sets TRUE when 40MHz intolerant AP is found
+ *  						     otherwise FALSE
+ *  @return      	  None
+ */
+static void
+get_channels_for_specified_reg_class(class_chan_t *cur_class_chan_table,
+				     int num_entry, t_u8 *chan_list,
+				     t_u8 *chan_num, t_u8 reg_domain,
+				     t_u8 reg_class, t_u8 *is_intol_ap_present)
+{
+	int i, j, k, idx = 0;
+
+	*is_intol_ap_present = FALSE;
+
+	/* For each regulatory class */
+	for (i = 0; i < num_entry; i++) {
+		if (cur_class_chan_table[i].reg_class == reg_class) {
+			/* For each channel of the regulatory class */
+			for (j = 0; j < cur_class_chan_table[i].total_chan; j++) {
+				for (k = 0; k < num_leg_ap_chan; k++) {
+
+					if (cur_class_chan_table[i].
+					    channels[j] ==
+					    leg_ap_chan_list[k].chan_num) {
+						*(chan_list + idx) =
+							leg_ap_chan_list[k].
+							chan_num;
+						idx++;
+						if (leg_ap_chan_list[k].
+						    is_intol_set)
+							*is_intol_ap_present =
+								TRUE;
+					}
+				}
+			}
+			break;
+		}
+	}
+	/* update the total number of channel */
+	*chan_num = idx--;
+	return;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Prepare 2040 coex command buffer
+ *  @param buf		   A pointer to the command buffer
+ *  @param chan_list   Channel list
+ *  @param num_of_chan Number of channel present in channel list
+ *  @param reg_class   Regulatory class
+ *  @param is_intol_ap_present   Flag: is any 40 MHz intolerant AP
+ *  				   is present in these chaanel set
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+void
+prepare_coex_cmd_buff(t_u8 *buf, t_u8 *chan_list, t_u8 num_of_chan,
+		      t_u8 reg_class, t_u8 is_intol_ap_present)
+{
+	HostCmd_DS_GEN *hostcmd;
+	MrvlIETypes_2040COEX_t *coex_ie = NULL;
+	MrvlIETypes_2040BssIntolerantChannelReport_t *bss_intol_ie = NULL;
+	t_u8 *pos = NULL;
+	int intol;
+
+	hostcmd = (HostCmd_DS_GEN *)(buf + sizeof(t_u32));
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_11N_2040COEX);
+	hostcmd->size = S_DS_GEN;
+	pos = buf + sizeof(t_u32) + S_DS_GEN;
+	{
+		coex_ie = (MrvlIETypes_2040COEX_t *)pos;
+		coex_ie->header.element_id = TLV_ID_2040COEX;
+		coex_ie->header.len = sizeof(coex_ie->coex_elem);
+		/* Check STA is 40 MHz intolerant or not */
+		is_intolerant_sta(&intol);
+		if (intol)
+			coex_ie->coex_elem |= MBIT(1);
+
+		if (is_intol_ap_present)
+			coex_ie->coex_elem |= MBIT(2);
+		pos += sizeof(MrvlIETypes_2040COEX_t);
+		hostcmd->size += sizeof(MrvlIETypes_2040COEX_t);
+	}
+	{
+		bss_intol_ie =
+			(MrvlIETypes_2040BssIntolerantChannelReport_t *)pos;
+		bss_intol_ie->header.element_id =
+			TLV_ID_2040BSS_INTOL_CHAN_REPORT;
+		hostcmd->size +=
+			sizeof(MrvlIETypes_2040BssIntolerantChannelReport_t) -
+			sizeof(bss_intol_ie->chan_num);
+		bss_intol_ie->reg_class = reg_class;
+		memcpy(bss_intol_ie->chan_num, chan_list, num_of_chan);
+		bss_intol_ie->header.len =
+			sizeof(bss_intol_ie->reg_class) + num_of_chan;
+		hostcmd->size += num_of_chan;
+	}
+	hostcmd->size = cpu_to_le16(hostcmd->size);
+	return;
+}
+
+/**
+ *  @brief Invoke multiple 2040Coex commands for multiple regulatory classes
+ *
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+invoke_coex_command(void)
+{
+	int cur_reg_domain;
+	t_u8 chan_list[MAX_CHAN], is_intol_ap_present;
+	t_u8 num_of_chan;
+	int i, num_entry, ret = MLAN_STATUS_SUCCESS;
+	class_chan_t *cur_class_chan_table = NULL;
+
+    /** get region code */
+	ret = get_region_code(&cur_reg_domain);
+	if (ret != MLAN_STATUS_SUCCESS)
+		return ret;
+    /** Find region_class_chan_table for this region */
+	for (i = 0;
+	     (unsigned int)i <
+	     (sizeof(region_class_chan_table) / sizeof(region_class_chan_t));
+	     i++) {
+		if (region_class_chan_table[i].reg_domain == cur_reg_domain) {
+			cur_class_chan_table =
+				region_class_chan_table[i].class_chan_list;
+			num_entry =
+				region_class_chan_table[i].num_class_chan_entry;
+			break;
+		}
+	}
+	if (cur_class_chan_table == NULL) {
+		printf("No region_class_chan table found for this region\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	for (i = 0; i < num_entry; i++) {
+	/** Get channels for the specified regulatory class */
+		get_channels_for_specified_reg_class(cur_class_chan_table,
+						     num_entry, chan_list,
+						     &num_of_chan,
+						     cur_reg_domain,
+						     cur_class_chan_table[i].
+						     reg_class,
+						     &is_intol_ap_present);
+
+	/** If any channel found for this regulatory class, then invoke the 2040coex command */
+		if (num_of_chan > 0) {
+			ret = process_host_cmd(CMD_2040COEX, chan_list,
+					       num_of_chan,
+					       cur_class_chan_table[i].
+					       reg_class, is_intol_ap_present);
+			if (ret)
+				break;
+		}
+	}
+	return ret;
+}
+
+/**
+ *  @brief Process host_cmd response
+ *
+ *  @param cmd_name	The command string
+ *  @param buf		A pointer to the response buffer
+ *
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_host_cmd_resp(char *cmd_name, t_u8 *buf)
+{
+	t_u32 hostcmd_size = 0;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	buf += strlen(CMD_MARVELL) + strlen(cmd_name);
+	memcpy((t_u8 *)&hostcmd_size, buf, sizeof(t_u32));
+	buf += sizeof(t_u32);
+
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	hostcmd->command = le16_to_cpu(hostcmd->command);
+	hostcmd->size = le16_to_cpu(hostcmd->size);
+
+	hostcmd->command &= ~HostCmd_RET_BIT;
+	if (!le16_to_cpu(hostcmd->result)) {
+		switch (hostcmd->command) {
+		}
+	} else {
+		printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+		ret = MLAN_STATUS_FAILURE;
+	}
+	return ret;
+}
diff --git a/wlan_sd8897/mapp/mlan2040coex/mlan2040misc.h b/wlan_sd8897/mapp/mlan2040coex/mlan2040misc.h
new file mode 100644
index 0000000..d264913
--- /dev/null
+++ b/wlan_sd8897/mapp/mlan2040coex/mlan2040misc.h
@@ -0,0 +1,443 @@
+/** @file  mlan2040misc.h
+  *
+  * @brief This file contains command definitions for application
+  *
+  * Copyright (C) 2009-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     06/24/2009: initial version
+************************************************************************/
+#ifndef _COEX_MISC_H_
+#define _COEX_MISC_H_
+
+/** MLAN MAC Address Length */
+#define MLAN_MAC_ADDR_LENGTH     (6)
+/** Size of command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+
+/** 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
+/** TLV Id for 2040Coex IE */
+#define TLV_ID_2040COEX                    0x48
+/** TLV Id for 2040BSS intolarent channel report IE */
+#define TLV_ID_2040BSS_INTOL_CHAN_REPORT   0x49
+/** Host-command for 2040coex command */
+#define HostCmd_CMD_11N_2040COEX           0x00e9
+/** Maximum scan response buffer size */
+#define SCAN_RESP_BUF_SIZE 2000
+
+/** Maximum length of SSID */
+#define MRVDRV_MAX_SSID_LENGTH          32
+
+/** Length of ethernet address */
+#ifndef ETH_ALEN
+#define ETH_ALEN            6
+#endif
+/** Maximum length of SSID list */
+#define MRVDRV_MAX_SSID_LIST_LENGTH         10
+/** Default scan interval in second*/
+#define DEFAULT_SCAN_INTERVAL 300
+
+/** BIT value */
+#define MBIT(x)    (((t_u32)1) << (x))
+
+/** Check intolerent bit set */
+#define IS_INTOL_BIT_SET(cap_info) (cap_info & MBIT(14))
+
+/** Check OBSS non-HT STAs present bit set */
+#define IS_NON_HT_STA_PRESENT(ht_info) (ht_info.field3 & MBIT(4))
+
+/** IEEE Type definitions  */
+typedef 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,
+	HT_CAPABILITY = 45,
+	HT_OPERATION = 61,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	EXT_CAPABILITY = 127,
+	ERP_INFO = 42,
+	EXTENDED_SUPPORTED_RATES = 50,
+	VENDOR_SPECIFIC_221 = 221,
+	WMM_IE = VENDOR_SPECIFIC_221,
+	RSN_IE = 48,
+} __attribute__ ((packed))
+     IEEEtypes_ElementId_e;
+
+/** HT Capabilities Data */
+     typedef struct _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;
+    /** Reserved set to 0 */
+	     t_u16 reserved;
+     } __attribute__ ((packed))
+     HTCap_t, *pHTCap_t;
+
+/** HT Information Data */
+     typedef struct _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];
+    /** Reserved set to 0 */
+	     t_u16 reserved;
+     } __attribute__ ((packed))
+     HTInfo_t, *pHTInfo_t;
+
+/** 20/40 BSS Coexistence Data */
+     typedef struct _BSSCo2040_t {
+    /** 20/40 BSS Coexistence value */
+	     t_u8 bss_co_2040_value;
+    /** Reserve field */
+	     t_u8 reserved[3];
+     } __attribute__ ((packed))
+     BSSCo2040_t, *pBSSCo2040_t;
+
+/** Extended Capabilities Data */
+     typedef struct _ExtCap_t {
+    /** Extended Capabilities value */
+	     t_u8 ext_cap_value;
+    /** Reserved field */
+	     t_u8 reserved[3];
+     } __attribute__ ((packed))
+     ExtCap_t, *pExtCap_t;
+
+/** Overlapping BSS Scan Parameters Data */
+     typedef struct _OverlapBSSScanParam_t {
+    /** OBSS Scan Passive Dwell */
+	     t_u16 obss_scan_passive_dwell;
+    /** OBSS Scan Active Dwell */
+	     t_u16 obss_scan_active_dwell;
+    /** BSS Channel Width Trigger Scan Interval */
+	     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;
+     } __attribute__ ((packed))
+     OBSSScanParam_t, *pOBSSScanParam_t;
+
+/** IEEEtypes_CapInfo_t structure*/
+     typedef 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;
+     } __attribute__ ((packed))
+     IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+
+     typedef struct {
+	     t_u8 chan_number;
+		       /**< Channel Number to scan */
+	     t_u8 radio_type;
+		       /**< Radio type: 'B/G' Band = 0, 'A' Band = 1 */
+	     t_u8 scan_type;
+		       /**< Scan type: Active = 1, Passive = 2 */
+	     t_u8 reserved;
+		      /**< Reserved */
+	     t_u32 scan_time;
+		       /**< Scan duration in milliseconds; if 0 default used */
+     } __attribute__ ((packed))
+     wlan_ioctl_user_scan_chan;
+
+     typedef struct {
+	     char ssid[MRVDRV_MAX_SSID_LENGTH + 1];
+					    /**< SSID */
+	     t_u8 max_len;		       /**< Maximum length of SSID */
+     } __attribute__ ((packed))
+     wlan_ioctl_user_scan_ssid;
+
+     typedef struct {
+
+    /** Flag set to keep the previous scan table intact */
+	     t_u8 keep_previous_scan;	/* Do not erase the existing scan results */
+
+    /** BSS mode to be sent in the firmware command */
+	     t_u8 bss_mode;
+
+    /** Configure the number of probe requests for active chan scans */
+	     t_u8 num_probes;
+
+    /** Reserved */
+	     t_u8 reserved;
+
+    /** BSSID filter sent in the firmware command to limit the results */
+	     t_u8 specific_bssid[ETH_ALEN];
+    /** SSID filter list used in the to limit the scan results */
+	     wlan_ioctl_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH];
+
+    /** Variable number (fixed maximum) of channels to scan up */
+	     wlan_ioctl_user_scan_chan chan_list[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
+
+     } __attribute__ ((packed))
+     wlan_ioctl_user_scan_cfg;
+
+/** IEEE IE header */
+     typedef struct _IEEEtypes_Header_t {
+    /** Element ID */
+	     t_u8 element_id;
+    /** Length */
+	     t_u8 len;
+     } __attribute__ ((packed))
+     IEEEtypes_Header_t, *pIEEEtypes_Header_t;
+
+/** HT Capabilities IE */
+     typedef struct _IEEEtypes_HTCap_t {
+    /** Generic IE header */
+	     IEEEtypes_Header_t ieee_hdr;
+    /** HTCap struct */
+	     HTCap_t ht_cap;
+     } __attribute__ ((packed))
+     IEEEtypes_HTCap_t, *pIEEEtypes_HTCap_t;
+
+/** HT Information IE */
+     typedef struct _IEEEtypes_HTInfo_t {
+    /** Generic IE header */
+	     IEEEtypes_Header_t ieee_hdr;
+    /** HTInfo struct */
+	     HTInfo_t ht_info;
+     } __attribute__ ((packed))
+     IEEEtypes_HTInfo_t, *pIEEEtypes_HTInfo_t;
+
+/** 20/40 BSS Coexistence IE */
+     typedef struct _IEEEtypes_2040BSSCo_t {
+    /** Generic IE header */
+	     IEEEtypes_Header_t ieee_hdr;
+    /** BSSCo2040_t struct */
+	     BSSCo2040_t bss_co_2040;
+     } __attribute__ ((packed))
+     IEEEtypes_2040BSSCo_t, *pIEEEtypes_2040BSSCo_t;
+
+/** Extended Capabilities IE */
+     typedef struct _IEEEtypes_ExtCap_t {
+    /** Generic IE header */
+	     IEEEtypes_Header_t ieee_hdr;
+    /** ExtCap_t struct */
+	     ExtCap_t ext_cap;
+     } __attribute__ ((packed))
+     IEEEtypes_ExtCap_t, *pIEEEtypes_ExtCap_t;
+
+/** Overlapping BSS Scan Parameters IE */
+     typedef struct _IEEEtypes_OverlapBSSScanParam_t {
+    /** Generic IE header */
+	     IEEEtypes_Header_t ieee_hdr;
+    /** OBSSScanParam_t struct */
+	     OBSSScanParam_t obss_scan_param;
+     } __attribute__ ((packed))
+     IEEEtypes_OverlapBSSScanParam_t, *pIEEEtypes_OverlapBSSScanParam_t;
+
+     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;
+    /** TSF value from the firmware at packet reception */
+	     t_u64 network_tsf;
+     } wlan_get_scan_table_fixed;
+
+/**
+ *  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 starting at bssInfoBuffer
+     */
+	     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[1]; */
+     } wlan_ioctl_get_scan_table_entry;
+
+/**
+ *  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;
+
+/* Define general hostcmd data structure */
+/** HostCmd_DS_GEN */
+     typedef struct _HostCmd_DS_GEN {
+    /** Command */
+	     t_u16 command;
+    /** Size */
+	     t_u16 size;
+    /** Sequence number */
+	     t_u16 seq_num;
+    /** Result */
+	     t_u16 result;
+     } __attribute__ ((packed))
+     HostCmd_DS_GEN;
+
+/** Size of HostCmd_DS_GEN */
+#define S_DS_GEN    sizeof(HostCmd_DS_GEN)
+
+/** TLV related data structures*/
+/** MrvlIEtypesHeader_t */
+     typedef struct _MrvlIEtypesHeader {
+    /** Header type */
+	     t_u16 type;
+    /** Header length */
+	     t_u16 len;
+     } __attribute__ ((packed))
+     MrvlIEtypesHeader_t;
+
+/** _MrvlIETypes_2040BssIntolerantChannelReport_t */
+     typedef struct _MrvlIETypes_2040BssIntolerantChannelReport_t {
+    /** Header */
+	     IEEEtypes_Header_t header;
+    /** regulatory class */
+	     t_u8 reg_class;
+    /** channel numbers for legacy AP */
+	     t_u8 chan_num[1];
+     } __attribute__ ((packed))
+     MrvlIETypes_2040BssIntolerantChannelReport_t;
+
+/** MrvlIETypes_2040COEX_t */
+     typedef struct _MrvlIETypes_2040COEX_t {
+    /** Header */
+	     IEEEtypes_Header_t header;
+    /** 2040 coex element */
+	     t_u8 coex_elem;
+     } __attribute__ ((packed))
+     MrvlIETypes_2040COEX_t;
+
+     typedef struct _HostCmd_DS_CMD_11N_2040COEX {
+	/** 2040 coex element */
+	     MrvlIETypes_2040COEX_t coex;
+	/** 2040 BSS intolerant channel report*/
+	     MrvlIETypes_2040BssIntolerantChannelReport_t chan_intol_report;
+     } __attribute__ ((packed))
+     HostCmd_DS_CMD_11N_2040COEX;
+
+/** Maximum number of channel per regulatory class */
+#define MAX_CHAN 20
+     typedef struct _class_chan_t {
+	/** Regulatory class */
+	     t_u8 reg_class;
+	/** Channel numbers */
+	     t_u8 channels[MAX_CHAN];
+	/** Total number of channels */
+	     t_u8 total_chan;
+     } class_chan_t;
+
+     typedef struct _region_class_chan_t {
+    /** Regulatory domain */
+	     int reg_domain;
+    /** Channel numbers */
+	     class_chan_t *class_chan_list;
+    /** Number of class channel table entry */
+	     int num_class_chan_entry;
+     } region_class_chan_t;
+
+     int process_host_cmd_resp(char *cmd_name, t_u8 *buf);
+     void prepare_coex_cmd_buff(t_u8 *buf, t_u8 *chan_list, t_u8 num_of_chan,
+				t_u8 reg_class, t_u8 is_intol_ap_present);
+     int invoke_coex_command(void);
+
+#endif /* _COEX_MISC_H_ */
diff --git a/wlan_sd8897/mapp/mlanconfig/Makefile b/wlan_sd8897/mapp/mlanconfig/Makefile
new file mode 100644
index 0000000..ba6794a
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/Makefile
@@ -0,0 +1,48 @@
+#
+# File : mlanconfig/Makefile
+#
+# Copyright (C) 2008-2017, Marvell International Ltd. All Rights Reserved
+
+# Path to the top directory of the mlandriver distribution
+PATH_TO_TOP = ../..
+
+# Determine how we should copy things to the install directory
+ABSPATH := $(filter /%, $(INSTALLDIR))
+RELPATH := $(filter-out /%, $(INSTALLDIR))
+INSTALLPATH := $(ABSPATH)
+ifeq ($(strip $(INSTALLPATH)),)
+INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH)
+endif
+
+# Override CFLAGS for application sources, remove __ kernel namespace defines
+CFLAGS := $(filter-out -D__%, $(ccflags-y))
+# remove KERNEL include dir
+CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS))
+
+#
+# List of application executables to create
+#
+libobjs:= mlanconfig.o mlanhostcmd.o mlanmisc.o
+exectarget=mlanconfig
+TARGETS := $(exectarget)
+
+#
+# Make target rules
+#
+
+# All rule compiles list of TARGETS using builtin program target from src rule
+all :
+$(exectarget): $(libobjs)
+	$(CC) $(CFLAGS) $(libobjs) -o $(exectarget)
+
+# Update any needed TARGETS and then copy to the install path
+build install: $(TARGETS)
+	@cp -rf config $(INSTALLPATH)
+
+clean:
+	@rm -f $(exectarget)
+	@rm -f *.o
+
+distclean: clean
+	@rm -f *~ core
+	@rm -f tags
diff --git a/wlan_sd8897/mapp/mlanconfig/config/11n_2040coex.conf b/wlan_sd8897/mapp/mlanconfig/config/11n_2040coex.conf
new file mode 100644
index 0000000..1e8cda7
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/11n_2040coex.conf
@@ -0,0 +1,21 @@
+#	File : 11n_2040coex.conf
+
+######################### 20/40 Coex command ##################
+2040coex={
+    CmdCode=0x00e9  # do NOT change this line
+
+    2040CoexTlvType:1=0x48
+    2040CoexTlvLen:1={
+        2040CoexElement:1=0x04
+    }
+
+    2040BssIntlChanTlvType:1=0x49
+    2040BssIntlChanTlvLen:1={
+        RegulatoryDomain:1=32   # USA: 32 (1-7), 33 (5-11)
+        ChannelNum:1=1
+        ChannelNum:1=2
+        #  ...
+    }
+}
+
+##################################################################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/arpfilter.conf b/wlan_sd8897/mapp/mlanconfig/config/arpfilter.conf
new file mode 100644
index 0000000..a50b089
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/arpfilter.conf
@@ -0,0 +1,29 @@
+#	File : arpfilter.conf
+
+######################### Host Sleep ARP/IP filtering command ##################
+# add arp filter
+# firmware supports 8 entries of ARP_FILTER. Each entry has 8 bytes.
+# must not exceed 8x8+4=68 bytes
+
+arpfilter={
+   TlvType:2=0x0115
+   TlvLength:2={
+      AddrType:2=3              # multicast
+      EthType:2=0xffff          # Any
+      Ipv4Addr:4=0xffffffff     # Any
+      AddrType:2=1              # broadcast
+      EthType:2=0x0608          # ARP: 0x0806
+      Ipv4Addr:4=0x6200a8c0     # 192.168.0.98
+      AddrType:2=2              # unicast
+      EthType:2=0xffff          # Any
+      Ipv4Addr:4=0xffffffff     # Any
+    }
+}
+
+# remove arp filter
+#arpfilter={
+#	TlvType:2=0x0115
+#	TlvLength:2={
+#	}
+#}
+######################### Host Sleep ARP/IP filtering command ##################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/auto_tx.conf b/wlan_sd8897/mapp/mlanconfig/config/auto_tx.conf
new file mode 100644
index 0000000..6c35540
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/auto_tx.conf
@@ -0,0 +1,54 @@
+#	File : auto_tx.conf
+
+######################### Auto-TX command ##################
+auto_tx_get={
+	CmdCode=0x0082	# do NOT change this line
+
+	Action:2=0		# GET
+}
+
+auto_tx_unreg={
+	CmdCode=0x0082	# do NOT change this line
+
+	Action:2=1		# SET
+}
+
+nat_keep_alive={
+	CmdCode=0x0082	# do NOT change this line
+
+	Action:2=1		# SET
+
+	AutoTxTlvType:2=0x0118
+	AutoTxTlvLength:2={		# 58 = 6 + 52 (FrameLen)
+		Interval:2=2		# 1 - 3600 seconds
+		Priority:1=7		# Priority, ignored if non-WMM
+		Reserved:1=0
+		FrameLength:2={		# 52 = 6 (DA) + 6 (SA) + 2 + 38 (Length)
+			DestMacAddr:6='0x00,0x40,0xf4,0xbf,0x24,0xee'
+			SrcMacAddr:6='0x00,0x00,0x00,0x00,0x00,0x00'
+			Length:2='0x00,38'	# 38 = 8 (SNAP hdr) + 29 (IP) + 1 (padding)
+			DSAP:1=0xaa			# SNAP header
+			SSAP:1=0xaa
+			Ctrl:1=0x03
+			SNAP_OUI:3='0x00,0x00,0x00'
+			SNAP_PID:2='0x08,0x00'		# IP Packet
+			IPv4:1=0x45
+			IP_TOS:1=0x00
+			IP_LEN:2='0x00,29'		# IP hdr 20 + payload 9 = 29
+			IP_ID:2=0xefbe
+			IP_Flag_FragOffset:2=0x0000
+			IP_TTL:1=128
+			IP_Prot:1=17		  		# UDP protocol
+			IPhdr_cksum:2=0xc5f9		# may need re-calculation if changed
+			IPsrcAddr:4='192,168,0,201'	# 192.168.0.201
+			IPdstAddr:4='192,168,0,1'	# 192.168.0.1
+			UDPsrcPort:2='0x11,0x94'	# 4500
+			UDPdstPort:2='0x11,0x94'	# 4500
+			UDPlength:2='0x00,9'		# UDP hdr 8 + payload 1 = 9
+			UDPcksum:2=0x985b			# may need re-calculation if changed
+			UDPpayload:1=0xff
+			padding:1=0					# MAC Padding for 32bit alignment, set to 0
+		}
+	}
+}
+######################### Auto-TX command ##################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/bg_scan.conf b/wlan_sd8897/mapp/mlanconfig/config/bg_scan.conf
new file mode 100644
index 0000000..e174936
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/bg_scan.conf
@@ -0,0 +1,157 @@
+#	File : bg_scan.conf
+
+######################### BG Scan Configuration command ##################
+########### Sample configuration for Get BG Scan Configuration #####################
+#bgscfg={
+#	CmdCode=0x006b          # do NOT change this line
+#	Action:1=0              # 0- Get, 1- Set
+#	ConfigType:1=0          # 0- normal BG Scan config, 1-PPS or UAPSD BG Scan config
+#	Enable:1=1              # 0- Disable, 1-Enable
+#	BssType:1=0             # 1 - Infrastructure,2 - IBSS,3 - Any
+#	ChannelsPerScan:1=0     # Number of Channel to scan at one scan; maximum 14
+#	Reserved1:3=0
+#	ScanInterval:4=0        # Interval between consecutive scan (in milliseconds)
+#	Reserved2:4=0
+#	ReportConditions:4=0    # bit0  - SSID match
+	                        # bit1  - SNR above SNR threshold
+	                        # bit2  - RSSI above RSSI threshold
+	                        # bit31 - All channels scanned at least once
+#	Reserved3:2=0
+#}
+
+########### SET BG Scan Configuration #####################
+bgscfg={
+	CmdCode=0x006b          # do NOT change this line
+	Action:1=1              # 0- Get, 1- Set
+	ConfigType:1=0          # 0- normal BG Scan config, 1-PPS or UAPSD BG Scan config
+	Enable:1=1              # 0- Disable, 1-Enable
+	BssType:1=3             # 1 - Infrastructure,2 - IBSS,3 - Any
+	ChannelsPerScan:1=14    # Number of Channel to scan at one scan; maximum 14
+	Reserved1:3=0
+	ScanInterval:4=1000     # Interval between consecutive scan (in milliseconds)
+	Reserved2:4=0
+	ReportConditions:4=1  	# bit0  - SSID match
+	                      	# bit1  - SNR above SNR threshold
+	                      	# bit2  - RSSI above RSSI threshold
+	                      	# bit31 - All channels scanned at least once
+	Reserved3:2=0
+
+	# SSID parameter set:
+	#
+	# MaxSSIDLen entries:
+	#
+	# 1. MaxSSIDLen:1=0x00      - to denote match AP name exactly,
+	#                             generate SSID specific probes
+	# 2. MaxSSIDLen:1=maxlen    - to denote AP name will be use to base match the
+	#                             SSID and SSID's max length is 'maxlen',
+	#                             do not generate SSID specific probes
+	# 3. MaxSSIDLen:1=wildcard match char ('*' or '?')
+	#                           - to denote wildcard AP name will be use to match the SSID
+	# 4. MaxSSIDLen:1=0xff      - to denote unix pattern matching
+	#
+	# SSID entries:
+	#
+	# SSID="AP_NAME"            - to mention the SSID to match
+
+	# SSID Examples:
+	#
+	#
+	# Match SSID name "MarvellAP" exactly, generate SSID specific probes
+	#
+	SSIDHeaderType:2=0x0112
+	SSIDHeaderLen:2={
+		MaxSSIDLen:1=0x00
+		SSID:9="MarvellAP"
+	}
+
+	#
+	# MarvellAP will be use to base match the SSID and SSID's max length is 12
+	#
+#	SSIDHeaderType:2=0x0112
+#	SSIDHeaderLen:2={
+#		MaxSSIDLen:1=0x0c
+#		SSID:9="MarvellAP"
+#	}
+
+	#
+	# Match "MarvellAP*" where '*' is a single char
+	#
+#	SSIDHeaderType:2=0x0112
+#	SSIDHeaderLen:2={
+#		MaxSSIDLen:1='*'
+#		SSID:10="MarvellAP*"
+#	}
+
+	#
+	# Match "Mar?ell*" with unix pattern matching
+	#
+#	SSIDHeaderType:2=0x0112
+#	SSIDHeaderLen:2={
+#		MaxSSIDLen:1=0xff     # For unix pattern matching
+#		SSID:8="Mar?ell*"
+#	}
+
+	# Number Probe requests to be sent for broadcast and
+	# for each SSID specific scan required.
+	#
+	# If any SSID in the list has a non-zero modifier (wildcard match char,
+	# unix pattern match, maxlen), "Numprobes" of broadcast probe requests
+	# will be transmitted once per channel and the results matched against
+	# all entries.
+	#
+	# Set to 0 to use global scan probes setting
+	#
+	ProbeHeaderType:2=0x0102
+	ProbeHeaderLen:2={
+		NumProbes:2=2
+	}
+
+	# ChannelList contains the channels to scan
+	# The ChannelList should be specified in the form of
+	#
+	#     RadioType, ChanNumber, ScanType, MinScanTime, ScanTime;
+	#
+	# RadioType - 0 [B/G Band], 1 [A Band]
+	# ScanType  - 2 [Active],   3 [Passive]
+	#
+
+	ChannHeaderType:2=0x0101
+	ChannHeaderLen:2={
+		Chan1_RadioType:1=0
+		Chan1_ChanNumber:1=10
+		Chan1_ScanType:1=2
+		Chan1_MinScanTime:2=10
+		Chan1_ScanTime:2=100
+
+		Chan2_RadioType:1=0
+		Chan2_ChanNumber:1=6
+		Chan2_ScanType:1=3
+		Chan2_MinScanTime:2=10
+		Chan2_ScanTime:2=100
+	}
+
+	# SNR threshold used when ReportConditions bit1 is set
+	SNRHeaderType:2=0x0105
+	SNRHeaderLen:2={
+		SNRValue:1=40 	#SNR Thereshold Value
+		SNRFreq:1=0
+	}
+
+	# RSSI threshold used when ReportConditions bit2 is set
+	#
+	# Threshold is absolute value and match value would
+	#   therefore be less than or equal to trigger a report
+	RSSIHeaderType:2=0x0104
+	RSSIHeaderLen:2={
+		RSSIValue:1=50 	#RSSI Thereshold Value
+		RSSIFreq:1=0
+	}
+
+	# StartLaterValue: 0 - BGScan start immediately
+	# 1 - BGScan will start later after "Scan Interval"
+	StartLaterHeaderType:2=0x011e
+	StartLaterHeaderLen:2={
+		StartLaterValue:2=0
+	}
+}
+######################### BG Scan Configuration command ##################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/bg_scan_wifidirect.conf b/wlan_sd8897/mapp/mlanconfig/config/bg_scan_wifidirect.conf
new file mode 100644
index 0000000..f480a9c
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/bg_scan_wifidirect.conf
@@ -0,0 +1,88 @@
+#	File : bg_scan_wifidirect.conf
+
+######################### BG Scan Configuration command ##################
+########### SET BG Scan Configuration #####################
+bgscfg={
+	CmdCode=0x006b          # do NOT change this line
+	Action:1=1              # 0- Get, 1- Set
+	ConfigType:1=0          # 0- normal BG Scan config, 1-PPS or UAPSD BG Scan config
+	Enable:1=1              # 0- Disable, 1-Enable
+	BssType:1=3             # 1 - Infrastructure,2 - IBSS,3 - Any
+	ChannelsPerScan:1=3     # Number of Channel to scan at one scan; maximum 14
+	Reserved1:3=0
+	ScanInterval:4=1000     # Interval between consecutive scan (in milliseconds)
+	StoreCondition:4=1      # 1 - SSID match (bit 0)
+	                        # 2 - SSID match AND SNR above SNR threshold (bit 1)
+	ReportConditions:4=1  	# 1 - SSID match (bit 0)
+	                        # 2 - SSID match AND SNR above SNR threshold (bit 1)
+	Reserved3:2=0
+
+	# SSID parameter set:
+	#
+	SSIDHeaderType:2=0x0112
+	SSIDHeaderLen:2={
+		MaxSSIDLen:1=0x00
+		SSID:7="DIRECT-"
+	}
+
+	# Number Probe requests to be sent for broadcast and
+	# for each SSID specific scan required.
+	#
+	# If any SSID in the list has a non-zero modifier (wildcard match char,
+	# unix pattern match, maxlen), "Numprobes" of broadcast probe requests
+	# will be transmitted once per channel and the results matched against
+	# all entries.
+	#
+	# Set to 0 to use global scan probes setting
+	#
+	ProbeHeaderType:2=0x0102
+	ProbeHeaderLen:2={
+		NumProbes:2=2
+	}
+
+	# ChannelList contains the channels to scan
+	# The ChannelList should be specified in the form of
+	#
+	#     RadioType, ChanNumber, ScanType, MinScanTime, ScanTime;
+	#
+	# RadioType - 0 [B/G Band], 1 [A Band]
+	# ScanType  - 2 [Active],   3 [Passive]
+	#
+
+	ChannHeaderType:2=0x0101
+	ChannHeaderLen:2={
+		Chan1_RadioType:1=0
+		Chan1_ChanNumber:1=1
+		Chan1_ScanType:1=2
+		Chan1_MinScanTime:2=10
+		Chan1_ScanTime:2=100
+
+		Chan2_RadioType:1=0
+		Chan2_ChanNumber:1=6
+		Chan2_ScanType:1=2
+		Chan2_MinScanTime:2=10
+		Chan2_ScanTime:2=100
+
+		Chan3_RadioType:1=0
+		Chan3_ChanNumber:1=11
+		Chan3_ScanType:1=2
+		Chan3_MinScanTime:2=10
+		Chan3_ScanTime:2=100
+	}
+
+	# SNR threshold to match, when StoreCondition
+	#     or ReportConditions been set to 2
+	SNRHeaderType:2=0x0105
+	SNRHeaderLen:2={
+		SNRValue:1=40 	#SNR Thereshold Value
+		SNRFreq:1=0
+	}
+
+	# StartLaterValue: 0 - BGScan start immediately
+	# 1 - BGScan will start later after "Scan Interval"
+	StartLaterHeaderType:2=0x011e
+	StartLaterHeaderLen:2={
+		StartLaterValue:2=0
+	}
+}
+######################### BG Scan Configuration command ##################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/cal_data.conf b/wlan_sd8897/mapp/mlanconfig/config/cal_data.conf
new file mode 100644
index 0000000..e37f674
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/cal_data.conf
@@ -0,0 +1,42 @@
+01 00 0c 00 58 02
+00 40 68 0c 00 00 00 40 00 00 00 00 00 11 00 00
+00 11 00 10 00 00 00 00 00 00 00 00 00 00 00 00
+10 12 00 10 10 86 40 89 01 03 02 00 01 02 05 00
+01 03 05 00 17 17 00 05 00 00 00 00 00 00 00 00
+00 30 1f 11 00 00 00 70 00 00 00 00 13 00 1e 01
+00 1e 5e 15 29 5e 15 13 5c 1d 0d 0b 1d 0d 0b 29
+0d 0b 29 5c 0b 29 5c 1d 00 5c 1d 0d 00 00 00 00
+00 5c c0 0e 00 00 00 cc 00 5f 00 00 07 01 04 00
+00 00 0e 0d 00 00 00 00 00 00 00 00 00 00 00 ff
+00 00 00 01 00 00 00 00 00 00 00 ff 00 00 00 01
+00 00 00 00 00 00 00 ff 00 00 00 01 00 00 00 00
+00 00 00 ff 00 00 00 01 00 00 00 00 06 3c 06 3d
+00 00 00 00 00 00 00 00 00 00 00 00
+00 5c dc 25 00 00 01 28 00 6f 00 00 07 01 04 00
+00 00 0e 0d 00 00 00 00 00 00 00 00 00 08 00 07
+00 00 00 09 00 00 00 00 00 08 00 07 00 00 00 09
+00 00 00 00 00 08 00 07 00 00 00 09 00 00 00 00
+00 08 00 07 00 00 00 09 00 00 00 00 06 3c 06 3d
+00 00 00 00 00 00 00 00 00 00 00 00
+00 14 9f 1f 00 00 01 3c 03 00 00 00 00 f1 0a f1
+00 fb 0d fb
+00 20 dd 28 00 00 01 5c 08 86 00 88 ff 06 b1 05
+24 24 3c 42 00 00 24 18 a4 24 bc bc 3d 00 a0 8f
+00 14 00 2a 00 00 01 70 00 00 30 00 01 05 1b 00
+00 00 00 01
+00 74 2c 10 00 00 01 e4 00 00 00 00 09 6a 09 b0
+0b 12 00 6c 04 0a 00 6c 03 03 00 6c 03 03 00 6c
+3f ff ff 00 3f ff ff 01 3f ff ff 02 3f ff ff 03
+15 00 00 04 17 00 00 05 19 00 00 06 1b 00 00 07
+1d 00 00 08 1f 00 00 09 21 00 00 0a 23 00 00 0b
+25 00 00 0c 28 00 00 0d 2a 00 00 0e 2d 00 00 0f
+2f 00 00 10 32 00 00 11 34 00 00 12 3f ff ff 13
+3f ff ff 14
+00 74 84 10 ff ff ff ff 01 00 00 00 09 b0 09 ba
+0a 0f 00 6c 04 09 00 6c 03 03 00 6c 03 03 00 6c
+3f ff ff 00 3f ff ff 01 3f ff ff 02 3f ff ff 03
+15 00 00 04 17 00 00 05 1a 00 00 06 1c 00 00 07
+1f 00 00 08 21 00 00 09 23 00 00 0a 26 00 00 0b
+2a 00 00 0c 2d 00 00 0d 31 00 00 0e 34 00 00 0f
+3f ff ff 10 3f ff ff 11 3f ff ff 12 3f ff ff 13
+3f ff ff 14
diff --git a/wlan_sd8897/mapp/mlanconfig/config/crypto_test.conf b/wlan_sd8897/mapp/mlanconfig/config/crypto_test.conf
new file mode 100644
index 0000000..9b911d2
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/crypto_test.conf
@@ -0,0 +1,57 @@
+#	File : crypto_test.conf
+
+######################### crypto_test command configuration ##################
+
+crypto_test={
+	CmdCode=0x0078          # do NOT change this line
+	#EncDec: 0-Decrypt, 1-Encrypt
+	EncDec:2=0
+	#Algorithm: 1-RC4, 2-AES, 3-AES_KEY_WRAP
+	Algorithm:2=1
+	#KeyIVLength: Length of KeyIV (bytes)
+	KeyIVLength:2=8
+	#KeyIV: Key IV
+	KeyIV:32='0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11'
+	#KeyLength: Length of Key (bytes)
+	KeyLength:2=16
+	#Key: Key
+	Key:32='0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22'
+	#DataType: DataType
+	DataType:2=0x0111
+	#DataLength: Data Length
+	DataLength:2={
+		#Data: Data
+		Data:8='0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33'
+	}
+}
+
+#####Sample crypto_test command configuration for AES-CCM algorithm #########
+
+#crypto_test={
+#	CmdCode=0x0078          # do NOT change this line
+#	#EncDec: 0-Decrypt, 1-Encrypt
+#	EncDec:2=1
+#	#Algorithm: 4-AES-CCM
+#	Algorithm:2=4
+#	#KeyLength: Length of Key (bytes)
+#	KeyLength:2=16
+#	#Key: Key
+#	Key:32='0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22'
+#	#NonceLength: Length of Nonce (bytes)
+#	NonceLength:2=10
+#	#Nonce: Nonce
+#	Nonce:14='0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11'
+#	#AADLength: Length of AAD (bytes)
+#	AADLength:2=12
+#	#AAD: AAD
+#	AAD:32='0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33'
+#	#DataType: DataType
+#	DataType:2=0x0111
+#	#DataLength: Data Length
+#	DataLength:2={
+#		#Data: Data
+#		Data:8='0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33'
+#	}
+#}
+
+######################### End of crypto_test configuration command ##################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/cwmode.conf b/wlan_sd8897/mapp/mlanconfig/config/cwmode.conf
new file mode 100644
index 0000000..1f245a2
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/cwmode.conf
@@ -0,0 +1,51 @@
+#CW_MODE settings configuration
+#
+CW_MODE={
+#Mode of operation 0: Disable current Tx Mode, 1: Continuous Tx Packet, 2: Continuous Wave/Tone
+Mode=1
+#Channel number
+Channel=6
+#channel Info
+#bit [3:0] - channel offset 0: no secondary channel, 1: secondary channel above, 2: reserved, 3: secondary channel below
+#bit [4:7] - channel band   0: 2.4G, 1: 5G, 2: 4G, 3: reserved
+Chaninfo=0x00
+#Tx power for Cont Tx in dbm
+TxPower=12
+# Packet Length for Cont Tx
+# legacy rates: upto 2312, HT/VHT rates: upto 8K
+PktLength=2048
+#RateInfo for Cont Tx
+RateInfo=0x0000
+#rateInfo = 0x0732 :  format = VHT, Bandwidth = 80MHz, datarate/MCS index = MCS7
+#rateInfo = 0x0000 :  format = legacy, Bandwidth = 20MHz, datarate/MCS index = 1Mbps
+#rateInfo = 0x0521 :  format = HT, Bandwidth = 40MHz, datarate/MCS index = MCS5
+#rateInfo = 0x4521 :  format = HT, Bandwidth = 40MHz, datarate/MCS index = MCS5, NSS = 1
+#rateInfo = 0x8921 :  format = HT, Bandwidth = 40MHz, datarate/MCS index = MCS9, NSS = 2
+#bit [1:0]  - Format 0: legacy, 1: 11n (HT), 2: 11ac (VHT)
+#bit 2      - STBC (Not used for Cont Tx test)
+#bit 3      - Beamforming (Not used for Cont Tx test)
+#bit [5:4]  - Bandwidth 0: 20MHz, 2: 40MHz, 3: 80MHz
+#bit [7:6]  - reserved
+#bit [13:8] - index : data rate or MCS
+#bit [15:14]- NSS (Used for 2x2 chips). Used in FW only for 2x2 chips.
+#<index> can take following values.
+#If <format> is 0 (LG),  #If <format> is 1 (HT)   #If <format> is 2 (VHT)
+#                            NSS = 1                 NSS = 1 or 2
+#    0   1 Mbps              0   MCS0                0   MCS0
+#    1   2 Mbps              1   MCS1                1   MCS1
+#    2   5.5 Mbps            2   MCS2                2   MCS2
+#    3   11 Mbps             3   MCS3                3   MCS3
+#    5   6 Mbps              4   MCS4                4   MCS4
+#    6   9 Mbps              5   MCS5                5   MCS5
+#    7   12 Mbps             6   MCS6                6   MCS6
+#    8   18 Mbps             7   MCS7                7   MCS7
+#                           Used only for NSS = 2
+#    9   24 Mbps             8   MCS8
+#    10  36 Mbps             9   MCS9
+#    11  48 Mbps            10   MCS10
+#    12  54 Mbps            11   MCS11
+#                           12   MCS12
+#                           13   MCS13
+#                           14   MCS14
+#                           15   MCS15
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/config/ed_mac_ctrl.conf b/wlan_sd8897/mapp/mlanconfig/config/ed_mac_ctrl.conf
new file mode 100644
index 0000000..ae0f750
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/ed_mac_ctrl.conf
@@ -0,0 +1,74 @@
+#       File : ed_mac_ctrl.conf
+#
+#   ./mlanutl mlan0 hostcmd config/ed_mac_ctrl.conf ed_mac_ctrl
+#
+#   ed_mac_ctrl_v2 should be used for KF/CAC
+#   ./mlanutl mlan0 hostcmd config/ed_mac_ctrl.conf ed_mac_ctrl_v2
+#
+#   ed_mac_ctrl_v3 should be used for KF2/RB3/CA2
+#   ./mlanutl mlan0 hostcmd config/ed_mac_ctrl.conf ed_mac_ctrl_v3
+#
+## Set ED MAC control
+ed_mac_ctrl={
+        CmdCode=0x0124          # do NOT change this line
+        Enable:2=0x0            # 0       - disable, use default
+                                # 1       - enable
+
+        Offset:2=0x0            # 0       - no offset
+                                # 0xffff  - offset set to -1
+                                # 0x1     - offset set to 1
+}
+
+ed_mac_ctrl_v2={
+        CmdCode=0x0130                  #Command code, do NOT change this tile
+        ed_ctrl_2g.enable:2=0x00        #0      - disable, all other parameters are ignored in 2.4G band
+                                        #1      - enable
+                                        #0xff   - use default OR value
+        ed_ctrl_2g.offset:2=0x0         #offset - value rabge: -128~127
+        ed_ctrl_2g.on_period:2=0x12     #time in millisecond to keep ED control enabled in 2.4g
+        ed_ctrl_2g.off_period:2=0x0     #time in milliseconf to keep ED control disabled in 2.4g
+        ed_ctrl_2g.bitmap:2=0x1         #Factors that affect 2.4G band ED control behavior
+                                        #Bit0: 0=If IEEE power save mode is on, disable EDCtrl2g
+                                        #      1=Neglect IEEE power save mode
+                                        #Bit8: 0=If IEEE power save mode is on EDCtrl2g is 1,
+                                        #        always keep EDCtrl2g enabled as if EDOffPeriod2g is 0
+                                        #      1=Neglect IEEE power save mode
+
+        ed_ctrl_5g.enable:2=0x0         #0      - disable, all other parameters are ignored in 2.4G band
+                                        #1      - enable
+                                        #0xff   - use default OR value
+        ed_ctrl_5g.offset:2=0x0         #offset - value rabge: -128~127
+        ed_ctrl_5g.on_period:2=0x12     #time in millisecond to keep ED control enabled in 5g
+        ed_ctrl_5g.off_period:2=0x0     #time in milliseconf to keep ED control disabled in 5g
+        ed_ctrl_5g.bitmap:2=0x1         #Factors that affect 5G band ED control behavior
+                                        #Bit0: 0=If IEEE power save mode is on, disable EDCtrl5g
+                                        #      1=Neglect IEEE power save mode
+                                        #Bit8: 0=If IEEE power save mode is on EDCtrl5g is 1,
+                                        #        always keep EDCtrl2g enabled as if EDOffPeriod5g is 0
+                                        #      1=Neglect IEEE power save mode
+}
+
+ed_mac_ctrl_v3={
+        CmdCode=0x0130                  #Command code, do NOT change this tile
+        ed_ctrl_2g.enable:2=0x01        #0      - disable EDMAC feature in 2.4G band
+                                        #1      - enable
+        ed_ctrl_2g.offset:2=0x0         #offset - value range: -128~127
+					                    #this offset will be added to the EDMAC thresholds
+					                    #effective_thr = default_thr + offset
+        ed_ctrl_5g.enable:2=0x01        #0      - disable EDMAC feature in 5G band
+                                        #1      - enable
+        ed_ctrl_5g.offset:2=0x0         #offset - value range: -128~127
+					                    #this offset will be added to the EDMAC thresholds
+					                    #effective_thr = default_thr + offset
+        ed_ctrl_txq_lock:4=0xFF         #Bitmap to control which queues to lock when ED busy is high
+                                        #The bitmap controls the following Tx when ED is high:
+                                        #Bit23 - PS queue
+                                        #Bit22 - CF queue
+                                        #Bit21 - MC queue
+                                        #Bit20 - TS queue
+                                        #Bit10 - Beacon TBTT
+                                        #Bit9 - BWQ
+                                        #Bit8 - CMQ
+                                        #Bit7:0 - TCQ7:0
+					                    #Respective Tx is blocked when the bit is set.
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/config/host_tdls.conf b/wlan_sd8897/mapp/mlanconfig/config/host_tdls.conf
new file mode 100644
index 0000000..3316d79
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/host_tdls.conf
@@ -0,0 +1,22 @@
+#	File : host_tdls.conf
+
+######################### HOST TDLS commands configuration ##################
+# starts with a command name with parameters embedded inside
+
+host_tdls_config={
+    uapsd_support=1  # 1: suport uapsd, 0: uapsd not support
+    cs_support=1     # 1: support channel switch, 0: don't support channel switch
+    SupportedChannels={
+        FirstChannelNo=1
+        NumberofSubBandChannels=11
+        # multiple instances of First Channel No, Number of SubBand Channels
+    }
+    SupportedRegulatoryClasses={
+        CurrentRegulatoryClass=1
+        NumofRegulatoryClasses=15
+        ListOfRegulatoryClasses=1,2,3,4,12,22,23,24,25,27,28,29,30,32,33
+    }
+
+}
+
+######################### HOST TDLS commands configuration ##################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/init_cfg.conf b/wlan_sd8897/mapp/mlanconfig/config/init_cfg.conf
new file mode 100644
index 0000000..d37cc4d
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/init_cfg.conf
@@ -0,0 +1,11 @@
+#	File : init_cfg.conf
+
+# MAC address (interface: address)
+mac_addr=mlan0: 00:50:43:20:12:34
+mac_addr=uap0: 00:50:43:20:12:35
+mac_addr=wfd0: 00:50:43:20:12:36
+
+# Register (type, offset, value)
+# type 1:MAC/SOC, 2:BBP, 3:RF, 5:CAU
+wlan_reg=1,0xA794,0x55FF55FF
+
diff --git a/wlan_sd8897/mapp/mlanconfig/config/mef.conf b/wlan_sd8897/mapp/mlanconfig/config/mef.conf
new file mode 100644
index 0000000..37d19a4
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/mef.conf
@@ -0,0 +1,167 @@
+#	File : mef.conf
+
+######################### MEF Configuration command ##################
+mefcfg={
+	#Criteria: bit0-broadcast, bit1-unicast, bit3-multicast
+	Criteria=2 		# Unicast frames are received during hostsleepmode
+	NumEntries=1		# Number of activated MEF entries
+	#mef_entry_0: example filters to match TCP destination port 80 send by 192.168.0.88 pkt or magic pkt.
+	mef_entry_0={
+		#mode: bit0--hostsleep mode, bit1--non hostsleep mode
+		mode=1		# HostSleep mode
+		#action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host
+		action=3	# Allow and Wake host
+		filter_num=3    # Number of filter
+		#RPN only support "&&" and "||" operator,space can not be removed between operator.
+		RPN=Filter_0 && Filter_1 || Filter_2
+		#Byte comparison filter's type is 0x41,Decimal comparison filter's type is 0x42,
+		#Bit comparison filter's type is  0x43
+		#Filter_0 is decimal comparison filter, it always with type=0x42
+		#Decimal filter always has type, pattern, offset, numbyte 4 field
+                #Filter_0 will match rx pkt with TCP destination port 80
+		Filter_0={
+			type=0x42	# decimal comparison filter
+			pattern=80	# 80 is the decimal constant to be compared
+			offset=44	# 44 is the byte offset of the field in RX pkt to be compare
+			numbyte=2       # 2 is the number of bytes of the field
+		}
+		#Filter_1 is Byte comparison filter, it always with type=0x41
+		#Byte filter always has type, byte, repeat, offset 4 filed
+		#Filter_1 will match rx pkt send by IP address 192.168.0.88
+		Filter_1={
+			type=0x41          	# Byte comparison filter
+			repeat=1                # 1 copies of 'c0:a8:00:58'
+			byte=c0:a8:00:58	# 'c0:a8:00:58' is the byte sequence constant with each byte
+						# in hex format, with ':' as delimiter between two byte.
+			offset=34               # 34 is the byte offset of the equal length field of rx'd pkt.
+		}
+		#Filter_2 is Magic packet, it will looking for 16 contiguous copies of '00:50:43:20:01:02' from
+		# the rx pkt's offset 14
+		Filter_2={
+			type=0x41		# Byte comparison filter
+			repeat=16               # 16 copies of '00:50:43:20:01:02'
+			byte=00:50:43:20:01:02  # '00:50:43:20:01:02' is the byte sequence constant
+			offset=14		# 14 is the byte offset of the equal length field of rx'd pkt.
+		}
+	}
+}
+
+
+#--------------------------examples for MEF filters--------------------------------
+#	example: filters to match ARP packet with protocol addr 192.168.0.104
+#	mef_entry_0={
+#		mode=1			# HostSleep mode
+#		action=3		# Allow and Wake host
+#		filter_num=3		# Number of filter
+#		RPN=Filter_0 && Filter_1 && Filter_2
+#		#Filter_0 looking for rx pkt with DA is broadcast address
+#		Filter_0={
+#			type=0x41
+#			repeat=6
+#			byte=ff
+#			offset=0
+#		}
+#		#Filter_1 looking for rx pkt with EtherType is 0x0806(ARP)
+#		Filter_1={
+#			type=0x41
+#			repeat=1
+#			byte=08:06
+#			offset=20
+#		}
+#		#Filter_2 looking for rx pkt with ARP target protocol addr 192.168.0.104
+#		Filter_2={
+#			type=0x41
+#			repeat=1
+#			byte=c0:a8:00:68
+#			offset=46
+#		}
+#	}
+#-------------------------------------------------------------------------------------
+#	example: filter to check if the destination MAC address is unicast pkt
+#	mef_entry_0={
+#		mode=1			# HostSleep mode
+#		action=3		# Allow and Wake host
+#		filter_num=3		# Number of filter
+#		RPN=Filter_0
+#		#Filter_0 is Bit comparison filter, it always with type=0x43
+#		#Byte filter always has type, byte, mask, offset 4 filed
+#		#"byte" is the byte sequence constant with each byte in hex format, with ':' as delimiter between two byte
+#		#"mask" is also with each byte in hex format, with ':' as delimiter between two byte
+#		#"byte" should has the same length as "mask"
+#		#Filter_0 will check if the destination MAC address is unicast pkt
+#		Filter_0={
+#			type=0x43	#Bit comparison filter
+#			byte=00		#00 is the 1-byte sequence constant
+#			offset=0        #0 is the byte offset of the rx pkt
+#			mask=01		#1 is the 1-byte mask
+#		}
+#	}
+#--------------------------------------------------------------------------------------------------
+#	example: Disable MEF filters
+#	mefcfg={
+#		#Criteria: bit0-broadcast, bit1-unicast, bit3-multicast
+#		Criteria=2 		# Unicast frames are received during hostsleepmode
+#		NumEntries=0		# Number of activated MEF entries
+#	}
+#--------------------------------------------------------------------------------------------------
+#	example: Test MEF filters
+#       mefcfg={
+#		Criteria=1
+#		NumEntries=1
+#		mef_entry_0={
+#			mode=4         # Test Mode
+#			action=16      # Invoke Test
+#			filter_num=0
+#		}
+#	}
+#-----------------------------------------------------------------------------------------------------
+#	example: Test MEF filters
+#       mefcfg={
+#		Criteria=1
+#		NumEntries=1
+#		mef_entry_0={
+#			mode=4
+#			action=0
+#			filter_num=1
+#			RPN=Filter_0
+#			Filter_0={
+#				type=0x44		# test filter
+#				repeat=2                # 2 copies of 'BE:EF'
+#				byte=BE:EF		# 'BE:EF' is the byte sequence constant
+#				offset=18		# 18 is the byte offset of the equal length field of rx'd pkt.
+#				dest=00:50:43:20:5a:82  # '00:50:43:20:5a:82' is the byte sequence constant
+#			}
+#		}
+#	}
+#----------------------------------------------------------------------------------------------------
+#example: Filter broadcast/ipv4 multicast/ipv6 multicast packets in non hostsleep mode
+#mefcfg={
+#	Criteria=9		# broadcast and multicast frames
+#	NumEntries=1	# Number of activated MEF entries
+#	mef_entry_0={
+#		mode=2		# non HostSleep mode
+#		action=0	# discard and not wake host
+#		filter_num=3    # Number of filter
+#		RPN=Filter_0 || Filter_1 || Filter_2
+#		Filter_0={              # IPV4 multicast
+#			type=0x41	        # byte comparison filter
+#			byte=01:00:5e		# 01:00:5e is the byte constant to be compared
+#			offset=0	        # 0 is the byte offset of the equal length field of rx'd pkt.
+#			repeat=1		    #
+#		}
+#		Filter_1={              # broadcast packet check
+#			type=0x41          	# Byte comparison filter
+#			repeat=6            # 6 copies of 'ff', means broadcast
+#			byte=ff			    # 'ff'(0xff) is the byte sequence constant with each byte
+#						        # in hex format, with ':' as delimiter between two byte.
+#			offset=0            # 0 is the byte offset of the equal length field of rx'd pkt.
+#		}
+#		Filter_2={              # IPV6 multicast
+#			type=0x41	        # byte comparison filter
+#			byte=33:33		    # 33:33 is the byte constant to be compared
+#			offset=0	        # 0 is the byte offset of the equal length field of rx'd pkt.
+#			repeat=1		    #
+#		}
+#	}
+#}
+#------------------------------------------------------------------------------------------------------
diff --git a/wlan_sd8897/mapp/mlanconfig/config/mef_mdns.conf b/wlan_sd8897/mapp/mlanconfig/config/mef_mdns.conf
new file mode 100644
index 0000000..568ca6f
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/mef_mdns.conf
@@ -0,0 +1,204 @@
+#	File : mef_mdns.conf
+
+######################### MEF Configuration command ##################
+mefcfg={
+	#Criteria: bit0-broadcast, bit1-unicast, bit3-multicast
+	Criteria=8 		# Multicast frames are received during hostsleepmode
+	NumEntries=2		# Number of activated MEF entries
+	#mef_entry_0: example filters to match WS-Discovery pkt for IPv4.
+	mef_entry_0={
+		#mode: bit0--hostsleep mode, bit1--non hostsleep mode
+		mode=1		# HostSleep mode
+		#action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host
+		action=3	# Allow and Wake host
+		filter_num=4    # Number of filter
+		#RPN only support "&&" and "||" operator,space can not be removed between operator.
+		RPN=Filter_0 && Filter_1 && Filter_2 && Filter_3
+		#Filter_0 will match IPv4 protocol packet
+		Filter_0={
+			type=0x41
+			repeat=1
+			byte=08:00
+			offset=20
+		}
+		#Filter_1 will match dest multicast IPv4 address 224.0.0.251
+		Filter_1={
+			type=0x41
+			repeat=1
+			byte=e0:00:00:fb
+			offset=38
+		}
+		#Filter_2 will match UDP packet
+		Filter_2={
+			type=0x42
+			pattern=17
+			offset=31
+			numbyte=1
+		}
+		#Filter_3 will match UDP port 5353
+		Filter_3={
+			type=0x42
+			pattern=5353
+			offset=44
+			numbyte=2
+		}
+	}
+	#mef_entry_1: example filters to match WS-Discovery pkt for IPv6.
+	mef_entry_1={
+		#mode: bit0--hostsleep mode, bit1--non hostsleep mode
+		mode=1		# HostSleep mode
+		#action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host
+		action=3	# Allow and Wake host
+		filter_num=4    # Number of filter
+		#RPN only support "&&" and "||" operator,space can not be removed between operator.
+		RPN=Filter_0 && Filter_1 && Filter_2 && Filter_3
+		#Filter_0 will match IPv4 protocol packet
+		Filter_0={
+			type=0x41
+			repeat=1
+			byte=86:dd
+			offset=20
+		}
+		#Filter_1 will match dest multicast IPv6 address FF02::FB
+		Filter_1={
+			type=0x41
+			repeat=1
+			byte=ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:fb
+			offset=46
+		}
+		#Filter_2 will match UDP packet
+		Filter_2={
+			type=0x42
+			pattern=17
+			offset=28
+			numbyte=1
+		}
+		#Filter_3 will match UDP port 5353
+		Filter_3={
+			type=0x42
+			pattern=5353
+			offset=64
+			numbyte=2
+		}
+	}
+}
+
+
+#--------------------------examples for MEF filters--------------------------------
+#	example: filters to match ARP packet with protocol addr 192.168.0.104
+#	mef_entry_0={
+#		mode=1			# HostSleep mode
+#		action=3		# Allow and Wake host
+#		filter_num=3		# Number of filter
+#		RPN=Filter_0 && Filter_1 && Filter_2
+#		#Filter_0 looking for rx pkt with DA is broadcast address
+#		Filter_0={
+#			type=0x41
+#			repeat=6
+#			byte=ff
+#			offset=0
+#		}
+#		#Filter_1 looking for rx pkt with EtherType is 0x0806(ARP)
+#		Filter_1={
+#			type=0x41
+#			repeat=1
+#			byte=08:06
+#			offset=20
+#		}
+#		#Filter_2 looking for rx pkt with ARP target protocol addr 192.168.0.104
+#		Filter_2={
+#			type=0x41
+#			repeat=1
+#			byte=c0:a8:00:68
+#			offset=46
+#		}
+#	}
+#-------------------------------------------------------------------------------------
+#	example: filter to check if the destination MAC address is unicast pkt
+#	mef_entry_0={
+#		mode=1			# HostSleep mode
+#		action=3		# Allow and Wake host
+#		filter_num=3		# Number of filter
+#		RPN=Filter_0
+#		#Filter_0 is Bit comparison filter, it always with type=0x43
+#		#Byte filter always has type, byte, mask, offset 4 filed
+#		#"byte" is the byte sequence constant with each byte in hex format, with ':' as delimiter between two byte
+#		#"mask" is also with each byte in hex format, with ':' as delimiter between two byte
+#		#"byte" should has the same length as "mask"
+#		#Filter_0 will check if the destination MAC address is unicast pkt
+#		Filter_0={
+#			type=0x43	#Bit comparison filter
+#			byte=00		#00 is the 1-byte sequence constant
+#			offset=0        #0 is the byte offset of the rx pkt
+#			mask=01		#1 is the 1-byte mask
+#		}
+#	}
+#--------------------------------------------------------------------------------------------------
+#	example: Disable MEF filters
+#	mefcfg={
+#		#Criteria: bit0-broadcast, bit1-unicast, bit3-multicast
+#		Criteria=2 		# Unicast frames are received during hostsleepmode
+#		NumEntries=0		# Number of activated MEF entries
+#	}
+#--------------------------------------------------------------------------------------------------
+#	example: Test MEF filters
+#       mefcfg={
+#		Criteria=1
+#		NumEntries=1
+#		mef_entry_0={
+#			mode=4         # Test Mode
+#			action=16      # Invoke Test
+#			filter_num=0
+#		}
+#	}
+#-----------------------------------------------------------------------------------------------------
+#	example: Test MEF filters
+#       mefcfg={
+#		Criteria=1
+#		NumEntries=1
+#		mef_entry_0={
+#			mode=4
+#			action=0
+#			filter_num=1
+#			RPN=Filter_0
+#			Filter_0={
+#				type=0x44		# test filter
+#				repeat=2                # 2 copies of 'BE:EF'
+#				byte=BE:EF		# 'BE:EF' is the byte sequence constant
+#				offset=18		# 18 is the byte offset of the equal length field of rx'd pkt.
+#				dest=00:50:43:20:5a:82  # '00:50:43:20:5a:82' is the byte sequence constant
+#			}
+#		}
+#	}
+#----------------------------------------------------------------------------------------------------
+#example: Filter broadcast/ipv4 multicast/ipv6 multicast packets in non hostsleep mode
+#mefcfg={
+#	Criteria=9		# broadcast and multicast frames
+#	NumEntries=1	# Number of activated MEF entries
+#	mef_entry_0={
+#		mode=2		# non HostSleep mode
+#		action=0	# discard and not wake host
+#		filter_num=3    # Number of filter
+#		RPN=Filter_0 || Filter_1 || Filter_2
+#		Filter_0={              # IPV4 multicast
+#			type=0x41	        # byte comparison filter
+#			byte=01:00:5e		# 01:00:5e is the byte constant to be compared
+#			offset=0	        # 0 is the byte offset of the equal length field of rx'd pkt.
+#			repeat=1		    #
+#		}
+#		Filter_1={              # broadcast packet check
+#			type=0x41          	# Byte comparison filter
+#			repeat=6            # 6 copies of 'ff', means broadcast
+#			byte=ff			    # 'ff'(0xff) is the byte sequence constant with each byte
+#						        # in hex format, with ':' as delimiter between two byte.
+#			offset=0            # 0 is the byte offset of the equal length field of rx'd pkt.
+#		}
+#		Filter_2={              # IPV6 multicast
+#			type=0x41	        # byte comparison filter
+#			byte=33:33		    # 33:33 is the byte constant to be compared
+#			offset=0	        # 0 is the byte offset of the equal length field of rx'd pkt.
+#			repeat=1		    #
+#		}
+#	}
+#}
+#------------------------------------------------------------------------------------------------------
diff --git a/wlan_sd8897/mapp/mlanconfig/config/mef_ws_discovery.conf b/wlan_sd8897/mapp/mlanconfig/config/mef_ws_discovery.conf
new file mode 100644
index 0000000..518a240
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/mef_ws_discovery.conf
@@ -0,0 +1,204 @@
+#	File : mef_ws_discovery.conf
+
+######################### MEF Configuration command ##################
+mefcfg={
+	#Criteria: bit0-broadcast, bit1-unicast, bit3-multicast
+	Criteria=8 		# Multicast frames are received during hostsleepmode
+	NumEntries=2		# Number of activated MEF entries
+	#mef_entry_0: example filters to match WS-Discovery pkt for IPv4.
+	mef_entry_0={
+		#mode: bit0--hostsleep mode, bit1--non hostsleep mode
+		mode=1		# HostSleep mode
+		#action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host
+		action=3	# Allow and Wake host
+		filter_num=4    # Number of filter
+		#RPN only support "&&" and "||" operator,space can not be removed between operator.
+		RPN=Filter_0 && Filter_1 && Filter_2 && Filter_3
+		#Filter_0 will match IPv4 protocol packet
+		Filter_0={
+			type=0x41
+			repeat=1
+			byte=08:00
+			offset=20
+		}
+		#Filter_1 will match dest multicast IPv4 address 239.255.255.250
+		Filter_1={
+			type=0x41
+			repeat=1
+			byte=ef:ff:ff:fa
+			offset=38
+		}
+		#Filter_2 will match UDP packet
+		Filter_2={
+			type=0x42
+			pattern=17
+			offset=31
+			numbyte=1
+		}
+		#Filter_3 will match UDP port 3702
+		Filter_3={
+			type=0x42
+			pattern=3702
+			offset=44
+			numbyte=2
+		}
+	}
+	#mef_entry_1: example filters to match WS-Discovery pkt for IPv6.
+	mef_entry_1={
+		#mode: bit0--hostsleep mode, bit1--non hostsleep mode
+		mode=1		# HostSleep mode
+		#action: 0--discard and not wake host, 1--discard and wake host 3--allow and wake host
+		action=3	# Allow and Wake host
+		filter_num=4    # Number of filter
+		#RPN only support "&&" and "||" operator,space can not be removed between operator.
+		RPN=Filter_0 && Filter_1 && Filter_2 && Filter_3
+		#Filter_0 will match IPv4 protocol packet
+		Filter_0={
+			type=0x41
+			repeat=1
+			byte=86:dd
+			offset=20
+		}
+		#Filter_1 will match dest multicast IPv6 address FF02::C
+		Filter_1={
+			type=0x41
+			repeat=1
+			byte=ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:0c
+			offset=46
+		}
+		#Filter_2 will match UDP packet
+		Filter_2={
+			type=0x42
+			pattern=17
+			offset=28
+			numbyte=1
+		}
+		#Filter_3 will match UDP port 3702
+		Filter_3={
+			type=0x42
+			pattern=3702
+			offset=64
+			numbyte=2
+		}
+	}
+}
+
+
+#--------------------------examples for MEF filters--------------------------------
+#	example: filters to match ARP packet with protocol addr 192.168.0.104
+#	mef_entry_0={
+#		mode=1			# HostSleep mode
+#		action=3		# Allow and Wake host
+#		filter_num=3		# Number of filter
+#		RPN=Filter_0 && Filter_1 && Filter_2
+#		#Filter_0 looking for rx pkt with DA is broadcast address
+#		Filter_0={
+#			type=0x41
+#			repeat=6
+#			byte=ff
+#			offset=0
+#		}
+#		#Filter_1 looking for rx pkt with EtherType is 0x0806(ARP)
+#		Filter_1={
+#			type=0x41
+#			repeat=1
+#			byte=08:06
+#			offset=20
+#		}
+#		#Filter_2 looking for rx pkt with ARP target protocol addr 192.168.0.104
+#		Filter_2={
+#			type=0x41
+#			repeat=1
+#			byte=c0:a8:00:68
+#			offset=46
+#		}
+#	}
+#-------------------------------------------------------------------------------------
+#	example: filter to check if the destination MAC address is unicast pkt
+#	mef_entry_0={
+#		mode=1			# HostSleep mode
+#		action=3		# Allow and Wake host
+#		filter_num=3		# Number of filter
+#		RPN=Filter_0
+#		#Filter_0 is Bit comparison filter, it always with type=0x43
+#		#Byte filter always has type, byte, mask, offset 4 filed
+#		#"byte" is the byte sequence constant with each byte in hex format, with ':' as delimiter between two byte
+#		#"mask" is also with each byte in hex format, with ':' as delimiter between two byte
+#		#"byte" should has the same length as "mask"
+#		#Filter_0 will check if the destination MAC address is unicast pkt
+#		Filter_0={
+#			type=0x43	#Bit comparison filter
+#			byte=00		#00 is the 1-byte sequence constant
+#			offset=0        #0 is the byte offset of the rx pkt
+#			mask=01		#1 is the 1-byte mask
+#		}
+#	}
+#--------------------------------------------------------------------------------------------------
+#	example: Disable MEF filters
+#	mefcfg={
+#		#Criteria: bit0-broadcast, bit1-unicast, bit3-multicast
+#		Criteria=2 		# Unicast frames are received during hostsleepmode
+#		NumEntries=0		# Number of activated MEF entries
+#	}
+#--------------------------------------------------------------------------------------------------
+#	example: Test MEF filters
+#       mefcfg={
+#		Criteria=1
+#		NumEntries=1
+#		mef_entry_0={
+#			mode=4         # Test Mode
+#			action=16      # Invoke Test
+#			filter_num=0
+#		}
+#	}
+#-----------------------------------------------------------------------------------------------------
+#	example: Test MEF filters
+#       mefcfg={
+#		Criteria=1
+#		NumEntries=1
+#		mef_entry_0={
+#			mode=4
+#			action=0
+#			filter_num=1
+#			RPN=Filter_0
+#			Filter_0={
+#				type=0x44		# test filter
+#				repeat=2                # 2 copies of 'BE:EF'
+#				byte=BE:EF		# 'BE:EF' is the byte sequence constant
+#				offset=18		# 18 is the byte offset of the equal length field of rx'd pkt.
+#				dest=00:50:43:20:5a:82  # '00:50:43:20:5a:82' is the byte sequence constant
+#			}
+#		}
+#	}
+#----------------------------------------------------------------------------------------------------
+#example: Filter broadcast/ipv4 multicast/ipv6 multicast packets in non hostsleep mode
+#mefcfg={
+#	Criteria=9		# broadcast and multicast frames
+#	NumEntries=1	# Number of activated MEF entries
+#	mef_entry_0={
+#		mode=2		# non HostSleep mode
+#		action=0	# discard and not wake host
+#		filter_num=3    # Number of filter
+#		RPN=Filter_0 || Filter_1 || Filter_2
+#		Filter_0={              # IPV4 multicast
+#			type=0x41	        # byte comparison filter
+#			byte=01:00:5e		# 01:00:5e is the byte constant to be compared
+#			offset=0	        # 0 is the byte offset of the equal length field of rx'd pkt.
+#			repeat=1		    #
+#		}
+#		Filter_1={              # broadcast packet check
+#			type=0x41          	# Byte comparison filter
+#			repeat=6            # 6 copies of 'ff', means broadcast
+#			byte=ff			    # 'ff'(0xff) is the byte sequence constant with each byte
+#						        # in hex format, with ':' as delimiter between two byte.
+#			offset=0            # 0 is the byte offset of the equal length field of rx'd pkt.
+#		}
+#		Filter_2={              # IPV6 multicast
+#			type=0x41	        # byte comparison filter
+#			byte=33:33		    # 33:33 is the byte constant to be compared
+#			offset=0	        # 0 is the byte offset of the equal length field of rx'd pkt.
+#			repeat=1		    #
+#		}
+#	}
+#}
+#------------------------------------------------------------------------------------------------------
diff --git a/wlan_sd8897/mapp/mlanconfig/config/mem.conf b/wlan_sd8897/mapp/mlanconfig/config/mem.conf
new file mode 100644
index 0000000..cf649c9
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/mem.conf
@@ -0,0 +1,17 @@
+#File : memory/register update
+# memory/register update file
+mem_set={
+	CmdCode=0x0086	#do NOT change this line
+	Action:2=1	# 1 - SET
+	Rsrvd:2=0
+	Addr:4=0x8000a584	# memory/register address
+	Value:4=0x16161669 #Value
+}
+
+mem_get={
+	CmdCode=0x0086	#do NOT change this line
+	Action:2=0	# 1 - SET
+	Rsrvd:2=0
+	Addr:4=0x8000a584	# memory/register address
+	Result:4=0
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/config/mgmt_frame.conf b/wlan_sd8897/mapp/mlanconfig/config/mgmt_frame.conf
new file mode 100644
index 0000000..22b19b1
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/mgmt_frame.conf
@@ -0,0 +1,30 @@
+# Format of the packet data to be sent.
+# Update the TxControl value for TxPD, else zero is sent.
+# all packet data is written under "Data" block
+
+PktType=0x00          # should be zero for MGMT frames
+PktSubType=0x05
+                      # Assoc Request       0
+                      # Assoc Response       1
+                      # Re-Assoc Request     2
+                      # Re-Assoc Response    3
+                      # Probe Request        4
+                      # Probe Response       5
+                      # Beacon               8
+                      # Atim                 9
+                      # Dis-assoc            10
+                      # Auth                 11
+                      # Deauth               12
+                      # Action Frame         13
+
+FromDS=0
+ToDS=0
+
+Addr1=00:50:43:27:B0:41   # Destination address
+Addr2=00:50:43:21:0F:84   # Source address
+Addr3=00:50:43:21:0F:84   # BSSID
+
+Data=0x01,0x01,0x00,0x0c,0x00,0x58,0x02,0x40
+
+SeqNum=0
+FragNum=0
diff --git a/wlan_sd8897/mapp/mlanconfig/config/mgmtfilter.conf b/wlan_sd8897/mapp/mlanconfig/config/mgmtfilter.conf
new file mode 100644
index 0000000..8ee0298
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/mgmtfilter.conf
@@ -0,0 +1,15 @@
+##############management frame filter to wake up host ###########
+##### support two entries currently ######
+mgmtfilter={
+	entry_num=1
+	entry_0={
+		action=1      # discard and wakeup host
+		type=0x1      # p2p frames
+		frame_mask=0x7 # Go neg req & rsp & cfm frame
+	}
+#	entry_1={
+#		action=0      # discard and not wakeup host
+#		type=0xff     # management frames
+#		frame_mask=0x3  # assoc req & rsp frame
+#	}
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/config/or_data.conf b/wlan_sd8897/mapp/mlanconfig/config/or_data.conf
new file mode 100644
index 0000000..99154f5
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/or_data.conf
@@ -0,0 +1,7 @@
+ 07 01 03 3A 80 00 3A 00 ff ff 00 17 03 00 07 03
+ 09 00 0e 10 16 02 19 25 1a 04 1c ff 32 5e 33 15
+ 35 29 36 17 4b 74 4c 64 4d 3b 50 27 61 d6 62 98
+ 6b ae 6f 5b 77 f2 79 ff 7f 2d
+ 07 01 12 16 c0 00 ff ff ff ff 00 05 03 10 32 5c
+ 33 1a 6b a2 7f 20
+
diff --git a/wlan_sd8897/mapp/mlanconfig/config/pad_cfg.conf b/wlan_sd8897/mapp/mlanconfig/config/pad_cfg.conf
new file mode 100644
index 0000000..80e2788
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/pad_cfg.conf
@@ -0,0 +1,11 @@
+#       File : pad_cfg.conf
+
+## Get CFG data for PAD OR
+pad_cfg_get={
+        CmdCode=0x008f          # do NOT change this line
+        Action:2=0              # 0 - GET
+        Type:2=5                # 5 - optimized pad reg
+        CfgLen:2={
+        }
+}
+
diff --git a/wlan_sd8897/mapp/mlanconfig/config/requesttpc.conf b/wlan_sd8897/mapp/mlanconfig/config/requesttpc.conf
new file mode 100644
index 0000000..690c30d
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/requesttpc.conf
@@ -0,0 +1,15 @@
+#	File : requesttpc.conf
+
+######################### requesttpc command configuration ##################
+
+requesttpc={
+	CmdCode=0x0060  # do NOT change this line
+	#DestMac: Destination STA address
+	DestMac:6='0x02,0x04,0x0e,0x06,0x01,0x12'
+	#RateIndex: IEEE Rate index to send request
+	RateIndex:1=22
+	#Timeout: Response timeout in ms
+	Timeout:2=10
+}
+
+######################### End of requesttpc command configuration ##################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/robust_btc.conf b/wlan_sd8897/mapp/mlanconfig/config/robust_btc.conf
new file mode 100644
index 0000000..7d5cb9b
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/robust_btc.conf
@@ -0,0 +1,189 @@
+#	File : robust_btc.conf
+
+######################### Robust Coex command ###############
+mode_get={
+    CmdCode=0x00e0		# do NOT change this line
+    Action:2=0			# GET
+    RSVD:2=0
+
+    # Robust Coex Mode TLV
+    RobustCoexTlvType:2=0x0160
+    RobustCoexTlvLength:2={
+        Enable:1=0x00	# Read-back Coex mode(s)
+        Reserved:3=0
+    }
+}
+
+mode_timeshare={
+    CmdCode=0x00e0		# do NOT change this line
+    Action:2=1			# SET
+    RSVD:2=0
+
+    # Robust Coex Mode TLV
+    RobustCoexTlvType:2=0x0160
+    RobustCoexTlvLength:2={
+        # All the modes below are mutually exclusive of each other;
+        Enable:1=0x01       # Bit0: Enable 2x2 or 1x1 Time Distribute(TMD)
+                            #  Robust Coex(RBC) mode, when uAP bss start,
+                            #  uAP TMD RBC scheme is enabled,
+                            #  STA TMD RBC scheme is disabled.
+        Reserved:3=0
+    }
+}
+
+mode_spatial={
+    CmdCode=0x00e0		# do NOT change this line
+    Action:2=1			# SET
+    RSVD:2=0
+
+    # Robust Coex Mode TLV
+    RobustCoexTlvType:2=0x0160
+    RobustCoexTlvLength:2={
+        # All the modes below are mutually exclusive of each other;
+        Enable:1=0x82       # Bit1: Enable 1x1 SMPS Spatial RBC Mode, e.g. 0x02
+                            # Bit7: Enable uAP+STA SMPS RBC Mode,
+                            #  when uAP bss start, uAP SMPS RBC scheme enable,
+                            #  must combined with BIT1 or BIT2, e.g. 0x82, 0x84.
+        Reserved:3=0
+    }
+}
+
+mode_none={
+    CmdCode=0x00e0		# do NOT change this line
+    Action:2=1			# SET
+    RSVD:2=0
+
+    # Robust Coex Mode TLV
+    RobustCoexTlvType:2=0x0160
+    RobustCoexTlvLength:2={
+        Enable:1=0          # Concurrent Coex mode. Used for chips which has
+                            # separate antenna for BT
+        Reserved:3=0
+    }
+}
+
+mode_2={
+    CmdCode=0x00e0          # do NOT change this line
+    Action:2=1              # SET
+    RSVD:2=0
+
+    # Robust Coex Mode TLV
+    RobustCoexTlvType:2=0x0160
+    RobustCoexTlvLength:2={
+        Enable:1=0x20          # Concurrent Coex mode with Tx power control and Rx De-sense.
+                               # Used for chips which has separate antenna for BT
+        Reserved:3=0
+    }
+}
+
+gpio_cfg={
+    CmdCode=0x00e0          # do NOT change this line
+    Action:2=1              # SET
+    RSVD:2=0
+
+    # Robust Coex Mode TLV
+    RobustCoexTlvType:2=0x021B
+    RobustCoexTlvLength:2={
+        Enable:1=0x1        # enable GPIO cfg for external bt request
+        gpionum:1=4         # gpio 4
+        gpiopolarity:1=1    # Polarity High
+    }
+}
+
+#In Station generic case
+#BT time is set as BTTime
+#Wlan time is set as Wlan Time
+generictime={
+    CmdCode=0x00e0
+    Action:2=1
+    RSVD:2=0
+    RobustCoexTlvType:2=0x0390
+    RobustCoexTlvLength:2={
+        Enable:2=0x01
+        BtTime:2=10000           #(10ms) BTTime must be less than 65535
+        WlanTime:2=40000         #(40ms) WlanTime must be less than 65535
+     }
+}
+
+#In Station A2DP case
+#BT time is set as BTTime
+#Wlan time is set as Wlan Time
+a2dptime={
+    CmdCode=0x00e0
+    Action:2=1
+    RSVD:2=0
+    RobustCoexTlvType:2=0x0391
+    RobustCoexTlvLength:2={
+        Enable:2=0x01
+        BtTime:2=10000           #(10ms)   BTTime must be less than 65535
+        WlanTime:2=39500         #(39.5ms) WlanTime must be less than 65535
+     }
+}
+
+#In Station inquiry case
+#BT time is set as BTTime
+#Wlan time is set as Wlan Time
+inquirytime={
+    CmdCode=0x00e0
+    Action:2=1
+    RSVD:2=0
+    RobustCoexTlvType:2=0x0392
+    RobustCoexTlvLength:2={
+        Enable:2=0x01
+        BtTime:2=21215           #(21.215ms) BTTime must be less than 65535
+        WlanTime:2=11000         #(11ms)     WlanTime must be less than 65535
+     }
+}
+
+#In Ap generic case
+#BT time is BTTimeBusy when BT has traffic
+#BT time is BTTimeIdle when BT is idle
+#Wlan time is WlanTimeBusy when Wlan has traffic
+#Wlan time is WlanTimeIdle when Wlan is idle
+ap_generictime={
+    CmdCode=0x00e0
+    Action:2=1
+    RSVD:2=0
+    RobustCoexTlvType:2=0x0393
+    RobustCoexTlvLength:2={
+       Enable:2=0x01
+       BtTime_MAX:2=23000         #(23ms)   BTTime(BT Busy) must be less than 28767
+       BtTime_MIN:2=6500          #(6.5ms)  BTTime(BT Idle) must be less than 28767
+       WlanTime_MAX:2=18000       #(18ms)   WlanTime(Wlan Busy) must be less than 32767
+       WlanTime_MIN:2=5750        #(5.75ms) WlanTime(Wlan Idle) must be less than 32767
+    }
+}
+
+#In Ap A2DP case
+#BT time is change from BTTimeMax to BTTimeMin
+#Wlan time is change from WlanTimeMax to WlanTimeMin
+ap_a2dptime={
+    CmdCode=0x00e0
+    Action:2=1
+    RSVD:2=0
+    RobustCoexTlvType:2=0x0394
+    RobustCoexTlvLength:2={
+        Enable:2=0x01
+        BtTimebusy:2=23000           #(23ms)   Maximum BTTime must be less than 32767
+        BtTimeidle:2=6500            #(6.5ms)  Minimum BTTime must be less than 32767
+        WlanTimebusy:2=18000         #(18ms)   Maximum WlanTime must be less than 32767
+        WlanTimeidle:2=5750          #(5.75ms) Minimum WlanTime must be less than 32767
+        }
+}
+
+#In Ap inquiry case
+#BT time is set as BTTime
+#Wlan time is set as Wlan Time
+ap_inquirytime={
+    CmdCode=0x00e0
+    Action:2=1
+    RSVD:2=0
+    RobustCoexTlvType:2=0x0395
+    RobustCoexTlvLength:2={
+        Enable:2=0x01
+        BtTime:2=28750               #(28.75ms) BTTime must less than 32767
+        WlanTime:2=20000             #(20ms)    WlanTime must be less than 32767
+        }
+}
+
+######################### Robust Coex command ###############
diff --git a/wlan_sd8897/mapp/mlanconfig/config/sdio_pulldown.conf b/wlan_sd8897/mapp/mlanconfig/config/sdio_pulldown.conf
new file mode 100644
index 0000000..745978b
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/sdio_pulldown.conf
@@ -0,0 +1,27 @@
+#	File : sdio_pulldown.conf
+
+######################### SDIO Pulldown command ###############
+sdio_pulldown_get={
+	CmdCode=0x0093		# do NOT change this line
+
+	Action:2=0			# GET
+	PullUpDelay:2=0
+	PullDownDelay:2=0
+}
+
+sdio_pulldown_set={
+	CmdCode=0x0093		# do NOT change this line
+
+	Action:2=1			# SET
+	PullUpDelay:2=0
+	PullDownDelay:2=0
+}
+
+sdio_pulldown_disable={
+	CmdCode=0x0093		# do NOT change this line
+
+	Action:2=1			# SET
+	PullUpDelay:2=0xffff
+	PullDownDelay:2=0xffff
+}
+######################### SDIO Pulldown command ###############
diff --git a/wlan_sd8897/mapp/mlanconfig/config/small_debug.conf b/wlan_sd8897/mapp/mlanconfig/config/small_debug.conf
new file mode 100644
index 0000000..1457426
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/small_debug.conf
@@ -0,0 +1,62 @@
+#	File : small_debug.conf
+
+######################### DBG Config command ###############
+small_debug_enable={
+    CmdCode=0x008b      # do NOT change this line
+
+    Dst:1=0x06          # dbgs_cfg_t
+    Air_Chan:1=0x00
+    RSVD:1=0
+    Num_Entries:1=0x81  # one entry global enable
+
+    # dbgs_t
+    En_Mask:2=0x0000    # en_mask_id
+    BaseId:2=0x0000     # base_id
+}
+
+small_debug_disable={
+    CmdCode=0x008b      # do NOT change this line
+
+    Dst:1=0x00
+    Air_Chan:1=0x00
+    RSVD:1=0
+    Num_Entries:1=0x00
+}
+
+######################### DBG Get Trace Memory ###############
+# Disable Air and Host destinations to disable dbgs_drain
+# Enable only the Power save ID - Host interface is a course enable - not on specific event
+trace_enable={
+    CmdCode=0x008b      # do NOT change this line
+
+    Dst:1=0x00          # dbgs_cfg_t - don't drain debug
+    Air_Chan:1=0x00
+    RSVD:1=0
+    Num_Entries:1=0x02  # 2 entry
+
+    # dbgs_t
+    En_Mask:2=0x5fff    # en_mask_id - enable single ID=0x80
+    BaseId:2=0x0020     # base_id
+    En_Mask:2=0x5fff    # en_mask_id - enable single ID=0x80
+    BaseId:2=0x0021     # base_id
+}
+
+get_trace={
+    CmdCode=0x008c      # do NOT change this line
+
+    startAddress:4=0x02 # read trace memeory - not a generic memory read
+    len:2=0x0000        # First read=0 - for next reads use the returned next start
+}
+
+trace_disable={
+    CmdCode=0x008b      # do NOT change this line
+
+    Dst:1=0x00          # dbgs_cfg_t - don't drain debug
+    Air_Chan:1=0x00
+    RSVD:1=0
+    Num_Entries:1=0x01  # one entry
+
+    # dbgs_t
+    En_Mask:2=0x0000    # en_mask_id
+    BaseId:2=0x0000     # base_id
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/config/smc.conf b/wlan_sd8897/mapp/mlanconfig/config/smc.conf
new file mode 100644
index 0000000..9bead4c
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/smc.conf
@@ -0,0 +1,124 @@
+#	File : smc.conf
+
+smc_get={
+	CmdCode=0x012d	#do not change this
+
+	Action:2=0	# GET
+}
+
+smc_set={
+	CmdCode=0x012d	#do not change this
+
+	Action:2=1	# SET
+
+# SSID
+	SSIDHeaderType:2=0x0000
+	SSIDHeaderLen:2={
+		SSID:10="Marvell_SMC_1"
+	}
+
+# Beacon Period.
+# This should be smaller than than MinScanTime.
+	BeaconHeaderType:2=0x012c
+	BeaconHeaderLen:2={
+		beaconPeriod:2=30
+	}
+
+# Channel list.
+# ChanNumber, MinScanTime and ScanTime are mandatory.
+# MinScanTime is minimum dwelling time for ChanNumber channel.
+# ScanTime is maximum dwelling time for ChanNumber channel.
+	ChannHeaderType:2=0x0101
+	ChannHeaderLen:2={
+
+# Following four line define one channel.
+# Please add similar four lines with different channel number for new channel.
+		Chan1_RadioType:1=0
+		Chan1_ChanNumber:1=1
+		Chan1_ScanType:1=2
+		Chan1_MinScanTime:2=40
+		Chan1_ScanTime:2=200
+
+		Chan2_RadioType:1=0
+		Chan2_ChanNumber:1=6
+		Chan2_ScanType:1=3
+		Chan2_MinScanTime:2=40
+		Chan2_ScanTime:2=200
+
+		Chan3_RadioType:1=0
+		Chan3_ChanNumber:1=9
+		Chan3_ScanType:1=2
+		Chan3_MinScanTime:2=40
+		Chan3_ScanTime:2=100
+
+		Chan2_RadioType:1=0
+		Chan2_ChanNumber:1=11
+		Chan2_ScanType:1=3
+		Chan2_MinScanTime:2=40
+		Chan2_ScanTime:2=200
+	}
+
+#Custom IE
+#Currently max size of custom IE supported is 50 bytes.
+#
+#	CustomHeaderType:2=0x010a
+#	CustomHeaderLen:2={
+#		start:1=0xdd
+#		start:1=0x10
+#		start:1=0x00
+#		start:1=0x01
+#		start:1=0x02
+#		start:1=0x03
+#		start:1=0x04
+#		start:1=0x05
+#		start:1=0x06
+#		start:1=0x07
+#		start:1=0x08
+#		start:1=0x09
+#		start:1=0x0a
+#		start:1=0x0b
+#		start:1=0x0c
+#		start:1=0x0d
+#		start:1=0x0e
+#		start:1=0x0f
+#	}
+
+#Multicast mac filtering address
+#All the multicast packets from starting mac address to ending mac address would
+#be captured and sent to the host.
+	MACHeaderType:2=0x01cc
+	MACHeaderLen:2={
+#Staring Multicast mac address
+		start:1=0x01
+		start:1=0x00
+		start:1=0x5e
+		start:1=0x00
+		start:1=0x00
+		start:1=0x01
+
+#Ending Multicast mac address
+		end:1=0x01
+		end:1=0x00
+		end:1=0x5e
+		end:1=0x7f
+		end:1=0xff
+		end:1=0xff
+
+#FilterType
+# 1 for RX AP frames
+# 2 for RX STA frames
+# 3 for both
+		Filter:2=0x3
+	}
+
+}
+smc_start={
+	CmdCode=0x012d	#do not change this
+
+	Action:2=2	# START
+}
+smc_stop={
+	CmdCode=0x012d	#do not change this
+
+	Action:2=3	# STOP
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/config/subevent.conf b/wlan_sd8897/mapp/mlanconfig/config/subevent.conf
new file mode 100644
index 0000000..ac7f333
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/subevent.conf
@@ -0,0 +1,103 @@
+#	File : subevent.conf
+
+######################### Subscribe Events command ##################
+subevent_get={
+	CmdCode=0x0075	# do NOT change this line
+
+	Action:2=0		# GET
+	Events:2=0
+}
+
+subevent_set={
+	CmdCode=0x0075	# do NOT change this line
+
+	Action:2=1		# SET
+	Events:2=0xbc8  # bit0     - Beacon RSSI_LOW
+	                # bit1     - Beacon SNR_LOW
+	                # bit2     - FAILED_COUNT
+	                # bit3     - Beacon Missed
+	                # bit4     - Beacon RSSI_HIGH
+	                # bit5     - Beacon SNR_HIGH
+	                # bit6     - Data RSSI_LOW
+	                # bit7     - Data SNR_LOW
+	                # bit8     - Data RSSI_HIGH
+	                # bit9     - Data SNR_HIGH
+	                # bit10    - LINK_QUALITY
+	                # bit11    - PRE_BCN_LOST
+	                # bit12-15 - Reserved
+
+	LowRssiTlvType:2=0x0104
+	LowRssiTlvLength:2={
+		Threshold:1=70
+		ReportingFreq:1=0
+	}
+
+	LowSnrTlvType:2=0x0105
+	LowSnrTlvLength:2={
+		Threshold:1=56
+		ReportingFreq:1=0
+	}
+
+	FailedCountTlvType:2=0x0106
+	FailedCountTlvLength:2={
+		Threshold:1=5
+		ReportingFreq:1=0
+	}
+
+	BeaconMissTlvType:2=0x0107
+	BeaconMissTlvLength:2={
+		BeaconMissed:1=60
+		Reserved:1=0
+	}
+
+	HighRssiTlvType:2=0x0116
+	HighRssiTlvLength:2={
+		Threshold:1=40
+		ReportingFreq:1=0
+	}
+
+	HighSnrTlvType:2=0x0117
+	HighSnrTlvLength:2={
+		Threshold:1=86
+		ReportingFreq:1=0
+	}
+
+	DataLowRssiTlvType:2=0x0126
+	DataLowRssiTlvLength:2={
+		Threshold:1=10
+		ReportingFreq:1=0
+	}
+
+	DataLowSnrTlvType:2=0x0127
+	DataLowSnrTlvLength:2={
+		Threshold:1=66
+		ReportingFreq:1=0
+	}
+
+	DataHighRssiTlvType:2=0x0128
+	DataHighRssiTlvLength:2={
+		Threshold:1=50
+		ReportingFreq:1=0
+	}
+
+	DataHighSnrTlvType:2=0x0129
+	DataHighSnrTlvLength:2={
+		Threshold:1=96
+		ReportingFreq:1=1
+	}
+	LinkQualityTlvType:2=0x0124
+	LinkQualityTlvType:2={
+		LinkSNRThreshold:2=0x0056
+		LinkSNRFrequency:2=0x0003
+		MinRateVal:2=0x0014
+		MinRateFreq:2=0x0003
+		TxLatencyVal:4=0x00C8
+		TxLatencyThreshold:4=0x0003
+	}
+	PreBcnLostTlvType:2=0x0149
+	PreBcnLostTlvLength:2={
+		PreBeaconCnt:1=30
+		Reserved:1=0
+	}
+}
+######################### Subscribe Events command ##################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/tdls.conf b/wlan_sd8897/mapp/mlanconfig/config/tdls.conf
new file mode 100644
index 0000000..d7369cf
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/tdls.conf
@@ -0,0 +1,118 @@
+#	File : tdls.conf
+
+######################### TDLS commands configuration ##################
+# starts with a command name with parameters embedded inside
+
+tdls_setinfo={
+    CapInfo=0x2421
+    Rate=0x02,0x04,0x0b,0x16,0x0C,0x12,0x18,0x24,0x30,0x48,0x60,0x6c
+    QosInfo=0x0F # 1 byte qos capability field. Valid values 0x00 or 0x0F
+                 # For AMPDU over direct link, this should be 0x00
+    ExtendCapabilities=0x00,0x00,0x00,0x50,0x20 # Enable Peer U-APSD(Bit28), TDLS channel switch(Bit30), TDLS(Bit37)
+    HTCapability={
+        HTCapabilityInfo=0x62 # 2 byte HT capability field.
+        AMPDUParam=0x3
+        SupportedMCSSet=0xFF,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+        HTExtCapability=0x00
+        TxBfCapability=0x00
+        AntennaSel=0x00
+    }
+    HTInformation={
+        PrimaryChannel=1
+        Field2=0x0
+        Field3=0x5
+        Field4=0x0
+        BasicMCSSet=0xFF,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+        # 16 elements as per the structure.
+    }
+    2040BSSCoex=0x01 # 1 byte 2040 Coex field.
+    VHTCapability={
+        VHTCapabilityInfo=0x33C00000 # 4 byte VHT capability field.
+	RxMCSMap=0xFFFC
+	RxMaxRate=0x0000   #bit 29-31 reserved
+	TxMCSMap=0xFFFC
+	TxMaxRate=0x0000  #bit 61-63 reserved
+    }
+    VHTOper={
+	ChanWidth=0x01;
+	ChanCF1=0x01;
+	ChanCF2=0x01;
+	BasicMCSMap=0xFF, 0XFF;    #Basic MCS set map, each 2 bits stands for a Nss
+    }
+#   Uncomment the RSNInfo while testing open-secure network.
+    RSNInfo={
+        GroupCipherSuite=0x00,0x0F,0xAC,0x07
+        PairwiseCipherCount=1
+        PairwiseCipherSuite=0x00,0x0F,0xAC,0x04 # CCMP
+        #PairwiseCipherSuite=0x00,0x0F,0xAC,0x02 # TKIP multiple Pairwise Cipher Suite if count > 1.
+        AKMSuiteCount=1
+        AKMSuite=0x00,0x0F,0xAC,0x07 # multiple AKM Suite if count > 1.
+        #AKMSuite=0x00,0x0F,0xAC,0x07 # multiple AKM Suite if count > 1.
+        RSNCapability=0x200   # Enable PeerKey
+        PMKIDCount=0
+    }
+    SupportedChannels={
+        FirstChannelNo=1
+        NumberofSubBandChannels=11
+        # multiple instances of First Channel No, Number of SubBand Channels
+    }
+    SupportedRegulatoryClasses={
+        CurrentRegulatoryClass=1
+        NumofRegulatoryClasses=15
+        ListOfRegulatoryClasses=1,2,3,4,12,22,23,24,25,27,28,29,30,32,33
+    }
+
+#    CountryInfo={
+#        CountryString="US"         # 3 byte country string
+#        FirstChannel=1
+#        NumberofChannels=11
+#        TxPower=30
+#        # multiple instances of First Channel, Number of Channels, Tx Power
+#    }
+}
+
+tdls_discovery={
+   PeerMAC=00:50:43:27:B0:41        # MAC address of Peer
+}
+
+tdls_setup={
+   PeerMAC=00:50:43:27:B0:41        # MAC address of Peer
+   WaitTimems=3000                  # Time in milliseconds to wait
+                                    # for setup response from peer
+   KeyLifetime=301                   # Lifetime of security key in seconds.
+}
+
+tdls_teardown={
+   PeerMAC=00:50:43:27:B0:41        # MAC address of Peer
+   ReasonCode=26                    # Tear down reason code
+}
+
+tdls_channel_switch={
+   PeerMAC=00:50:43:27:B0:41        # MAC address of Peer
+   Band=0                           # Band
+   PrimaryChannel=6                 # Primary channel no for channel switching
+   SecondaryChannelOffset=0         # Secondary channel offset
+   Periodicity=1                    # Channel switch periodicity
+   ChannelSwitchTime=10              # Channel switch time in ms.
+   ChannelSwitchTimeout=14          # Channel switch timeout in ms
+   RegulatoryClass=12               # Target regulatory class
+}
+
+tdls_cs_params={
+   UnitTime=2                       # Unit time, multiples of 10 ms
+   ThresholdOtherLink=10            # Threshold for other link
+   ThresholdDirectLink=1           # Threshold for direct link
+}
+
+
+tdls_stop_channel_switch={
+   PeerMAC=00:50:43:27:B0:41        # MAC address of Peer
+}
+
+tdls_powermode={
+   PeerMAC=00:50:43:27:B0:41        # MAC address of Peer
+   PowerMode=1                      # 0: Active, 1 : Power Save
+}
+
+
+######################### TDLS commands configuration ##################
diff --git a/wlan_sd8897/mapp/mlanconfig/config/tspecs.conf b/wlan_sd8897/mapp/mlanconfig/config/tspecs.conf
new file mode 100644
index 0000000..86c1ac6
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/tspecs.conf
@@ -0,0 +1,100 @@
+# TSPEC contents for TID=0, UserPriority = 6
+[tspec0]
+# Element ID
+dd
+# Length
+3d
+# OUI
+00 50 f2
+# OUI Type
+02
+# OUI SubType
+02
+# Version
+01
+# TSInfo
+e0 34 00
+# Nominal MSDU Size
+d0 80
+# Maximum MSDU Size
+d0 00
+# Min Service Interval
+20 4e 00 00
+# Max Service Interval
+20 4e 00 00
+# Inactivity Interval
+80 96 98 00
+# Suspension Interval
+ff ff ff ff
+# Service Start Time
+00 00 00 00
+# Minimum Data Rate
+00 45 01 00
+# Mean Data Rate
+00 45 01 00
+# Peak Data Rate
+00 45 01 00
+# Max Burst Size
+00 00 00 00
+# Delay Bound
+00 00 00 00
+# Min PHY Rate
+00 1b b7 00
+# Surplus Bandwidth Allowance
+00 30
+# Medium Time
+00 00
+# Extra Data Bytes
+[/tspec0]
+
+
+# TSPEC contents for TID=1, UserPriority = 4
+[tspec1]
+# Element ID
+dd
+# Length
+3d
+# OUI
+00 50 f2
+# OUI Type
+02
+# OUI SubType
+02
+# Version
+01
+# TSInfo
+e3 20 00
+# Nominal MSDU Size
+96 00
+# Maximum MSDU Size
+dc 05
+# Min Service Interval
+00 00 00 00
+# Max Service Interval
+00 00 00 00
+# Inactivity Interval
+00 00 00 00
+# Suspension Interval
+ff ff ff ff
+# Service Start Time
+00 00 00 00
+# Minimum Data Rate
+a0 00 00 00
+# Mean Data Rate
+a0 00 00 00
+# Peak Data Rate
+a0 00 00 00
+# Max Burst Size
+00 00 00 00
+# Delay Bound
+00 00 00 00
+# Min PHY Rate
+80 8d 5b 00
+# Surplus Bandwidth Allowance
+00 30
+# Medium Time
+00 00
+# Extra Data Bytes
+dd 04 00 50 43 ff
+[/tspec1]
+
diff --git a/wlan_sd8897/mapp/mlanconfig/config/turbo_mode.conf b/wlan_sd8897/mapp/mlanconfig/config/turbo_mode.conf
new file mode 100644
index 0000000..8a92f2f
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/turbo_mode.conf
@@ -0,0 +1,9 @@
+#File : turbo_mode.conf
+## WMM turbo mode config command
+turbo_mode_set={
+    CmdCode=0x0016          # do NOT change this line
+    Action:2=1              # 1 - SET
+    OID:2=0x27              # OID_WMM_TURBO_MODE
+    Size:2=128
+    Value:128=5             # 1 -- Enable turbo_mode_1; 2 -- Enable turbo_mode_2; otherwise, disable turbo_mode
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/config/txpwrlimit_cfg.conf b/wlan_sd8897/mapp/mlanconfig/config/txpwrlimit_cfg.conf
new file mode 100644
index 0000000..2192fd5
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/txpwrlimit_cfg.conf
@@ -0,0 +1,610 @@
+#       File : txpwrlimit_cfg.conf
+## Get CFG data for Tx power limitation
+txpwrlimit_2g_cfg_get={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=0              # 0 - GET
+        SubBand:2=0x00          # 0x00 2G subband  (2.4G: channel 1-14)
+                                # 0x10 5G subband0 (5G: channel 36,40,44,48,
+                                #                               52,56,60,64)
+                                # 0x11 5G subband1 (5G: channel 100,104,108,112,
+                                #                               116,120,124,128,
+                                #                               132,136,140,144)
+                                # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172)
+                                # 0x13 5G subband3 (5G: channel 183,184,185,187,188,
+                                #                               189, 192,196;
+                                #                   5G: channel 7,8,11,12,16,34)
+}
+
+
+txpwrlimit_5g_cfg_get_sub0={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=0              # 0 - GET
+        SubBand:2=0x10          # 0x00 2G subband  (2.4G: channel 1-14)
+                                # 0x10 5G subband0 (5G: channel 36,40,44,48,
+                                #                               52,56,60,64)
+                                # 0x11 5G subband1 (5G: channel 100,104,108,112,
+                                #                               116,120,124,128,
+                                #                               132,136,140,144)
+                                # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172)
+                                # 0x13 5G subband3 (5G: channel 183,184,185,187,188,
+                                #                               189, 192,196;
+                                #                   5G: channel 7,8,11,12,16,34)
+}
+
+
+txpwrlimit_5g_cfg_get_sub1={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=0              # 0 - GET
+        SubBand:2=0x11          # 0x00 2G subband  (2.4G: channel 1-14)
+                                # 0x10 5G subband0 (5G: channel 36,40,44,48,
+                                #                               52,56,60,64)
+                                # 0x11 5G subband1 (5G: channel 100,104,108,112,
+                                #                               116,120,124,128,
+                                #                               132,136,140,144)
+                                # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172)
+                                # 0x13 5G subband3 (5G: channel 183,184,185,187,188,
+                                #                               189, 192,196;
+                                #                   5G: channel 7,8,11,12,16,34)
+}
+
+
+txpwrlimit_5g_cfg_get_sub2={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=0              # 0 - GET
+        SubBand:2=0x12          # 0x00 2G subband  (2.4G: channel 1-14)
+                                # 0x10 5G subband0 (5G: channel 36,40,44,48,
+                                #                               52,56,60,64)
+                                # 0x11 5G subband1 (5G: channel 100,104,108,112,
+                                #                               116,120,124,128,
+                                #                               132,136,140,144)
+                                # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172)
+                                # 0x13 5G subband3 (5G: channel 183,184,185,187,188,
+                                #                               189, 192,196;
+                                #                   5G: channel 7,8,11,12,16,34)
+}
+
+
+txpwrlimit_5g_cfg_get_sub3={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=0              # 0 - GET
+        SubBand:2=0x13          # 0x00 2G subband  (2.4G: channel 1-14)
+                                # 0x10 5G subband0 (5G: channel 36,40,44,48,
+                                #                               52,56,60,64)
+                                # 0x11 5G subband1 (5G: channel 100,104,108,112,
+                                #                               116,120,124,128,
+                                #                               132,136,140,144)
+                                # 0x12 5G subband2 (5G: channel 149,153,157,161,165,172)
+                                # 0x13 5G subband3 (5G: channel 183,184,185,187,188,
+                                #                               189, 192,196;
+                                #                   5G: channel 7,8,11,12,16,34)
+}
+
+## Set CFG data for Tx power limitation
+##
+## TLVStartFreq: Starting Frequency of the band for this channel
+##                 2407, 2414 or 2400 for 2.4 GHz
+##                 5000
+##                 4000
+## TLVChanWidth: Channel Width
+##                 20
+## TLVChanNum  : Channel Number
+## TLVPwr[]    : ModulationGroup
+##                 0: CCK (1,2,5.5,11 Mbps)
+##                 1: OFDM (6,9,12,18 Mbps)
+##                 2: OFDM (24,36 Mbps)
+##                 3: OFDM (48,54 Mbps)
+##                 4: HT20 (MCS0,1,2)
+##                 5: HT20 (MCS3,4)
+##                 6: HT20 (MCS5,6,7)
+##                 7: HT40 (MCS0,1,2)
+##                 8: HT40 (MCS3,4)
+##                 9: HT40 (MCS5,6,7)
+##                 10: HT2_20 (MCS8,9,10)
+##                 11: HT2_20 (MCS11,12)
+##                 12: HT2_20 (MCS13,14,15)
+##                 13: HT2_40 (MCS8,9,10)
+##                 14: HT2_40 (MCS11,12)
+##                 15: HT2_40 (MCS13,14,15)
+##                 16: VHT_QAM256 (MCS8)
+##                 17: VHT_40_QAM256 (MCS8,9)
+##                 18: VHT_80_PSK (MCS0,1,2)
+##                 19: VHT_80_QAM16 (MCS3,4)
+##                 20: VHT_80_QAM64 (MCS5,6,7)
+##                 21: VHT_80_QAM256 (MCS8,9)
+##                 22: VHT2_20_QAM256 (MCS8,9)
+##                 23: VHT2_40_QAM256 (MCS8,9)
+##                 24: VHT2_80_PSK (MCS0, 1, 2)
+##                 25: VHT2_80_QAM16 (MCS3,4)
+##                 26: VHT2_80_QAM64 (MCS5,6,7)
+##                 27: VHT2_80_QAM256 (MCS8,9)
+##               Power Limit in dBm
+##
+## Note: For KF, add VHT 20/40/80 1SS/2SS mod group.
+
+## 2G subband0 Tx power limit CFG
+txpwrlimit_2g_cfg_set={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=1              # 1 - SET
+        SubBand:2=0             # do NOT use this member in set cmd
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=1
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=2
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=3
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=4
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=5
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=6
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=7
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=8
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=9
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=10
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=11
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=12
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=13
+            TLVPwr:32='0,17,1,15,2,15,3,13,4,15,5,15,6,13,7,15,8,15,9,13,10,15,11,15,12,15,13,15,14,15,15,15'
+        }
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=2407
+            TLVChanWidth:1=20
+            TLVChanNum:1=14
+            TLVPwr:32='0,12,1,12,2,12,3,12,4,12,5,12,6,12,7,12,8,12,9,12,10,12,11,12,12,12,13,12,14,12,15,12'
+        }
+}
+
+
+## 5G subband1 Tx power limit CFG
+txpwrlimit_5g_cfg_set_sub0={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=1              # 1 - SET
+        SubBand:2=0             # do NOT use this member in set cmd
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=36
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=40
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=44
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=48
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=52
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=56
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=60
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=64
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+}
+
+## 5G subband2 Tx power limit CFG
+txpwrlimit_5g_cfg_set_sub1={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=1              # 1 - SET
+        SubBand:2=0             # do NOT use this member in set cmd
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=100
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=104
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=108
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=112
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=116
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=120
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=124
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=128
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=132
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=136
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=140
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=144
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+}
+
+
+## 5G subband3 Tx power limit CFG
+txpwrlimit_5g_cfg_set_sub2={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=1              # 1 - SET
+        SubBand:2=0             # do NOT use this member in set cmd
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=149
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=153
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=157
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=161
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=165
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+}
+
+
+## 5G subband4 Tx power limit CFG
+txpwrlimit_5g_cfg_set_sub3={
+        CmdCode=0x00fb          # do NOT change this line
+        Action:2=1              # 1 - SET
+        SubBand:2=0             # do NOT use this in set cmd
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=4000
+            TLVChanWidth:1=20
+            TLVChanNum:1=183
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=4000
+            TLVChanWidth:1=20
+            TLVChanNum:1=184
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=4000
+            TLVChanWidth:1=20
+            TLVChanNum:1=185
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=4000
+            TLVChanWidth:1=20
+            TLVChanNum:1=187
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=4000
+            TLVChanWidth:1=20
+            TLVChanNum:1=188
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=4000
+            TLVChanWidth:1=20
+            TLVChanNum:1=189
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=4000
+            TLVChanWidth:1=20
+            TLVChanNum:1=192
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=4000
+            TLVChanWidth:1=20
+            TLVChanNum:1=196
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=7
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=8
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=11
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=12
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=16
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+
+
+        ChanTRPC.TlvType:2=0x0189
+        ChanTRPC.TlvLength:2={
+            TLVStartFreq:2=5000
+            TLVChanWidth:1=20
+            TLVChanNum:1=34
+            TLVPwr:56='0,17,1,15,2,15,3,11,4,15,5,15,6,11,7,15,8,15,9,11,10,15,11,15,12,14,13,15,14,15,15,14,16,11,17,11,18,13,19,13,20,10,21,10,22,11,23,11,24,13,25,13,26,12,27,10'
+        }
+}
+
diff --git a/wlan_sd8897/mapp/mlanconfig/config/txrate_cfg.conf b/wlan_sd8897/mapp/mlanconfig/config/txrate_cfg.conf
new file mode 100644
index 0000000..4d2f789
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/config/txrate_cfg.conf
@@ -0,0 +1,171 @@
+#	File : txrate_cfg.conf
+
+## Tx Rate Configuration command
+txrate_cfg_get={
+	CmdCode=0x00d6		# do NOT change this line
+        Action:2=0              # 0 - GET
+        Index:2=0               # do NOT change this line
+
+	TxRateScope.TlvType:2=0x0153
+	TxRateScope.TlvLength:2={
+	}
+}
+
+txrate_cfg_set_bg={
+	CmdCode=0x00d6		# do NOT change this line
+
+	Action:2=1		# 1 - SET
+	Index:2=0		# do NOT change this line
+
+	TxRateScope.TlvType:2=0x0153
+	TxRateScope.TlvLength:2={
+                      ################# TXRATE SCOPE ######################
+
+                                # The following table shows the bitmap of the rates:
+                                # (bit 0 is the least significant bit)
+                                #       Bit     Data rate
+                                #       0       1 Mbps
+                                #       1       2 Mbps
+                                #       2       5.5 Mbps
+                                #       3       11 Mbps
+                                #       4       Reserved
+                HRDSSS.RateScope:2=0x0000
+
+                                # The following table shows the bitmap of the rates:
+                                # (bit 0 is the least significant bit)
+                                #       Bit     Data rate
+                                #       0       6 Mbps
+                                #       1       9 Mbps
+                                #       2       12 Mbps
+                                #       3       18 Mbps
+                                #       4       24 Mbps
+                                #       5       36 Mbps
+                                #       6       48 Mbps
+                                #       7       54 Mbps
+                OFDM.RateScope:2=0x0080
+
+                                # The following table shows the bitmap of the rates:
+                                # (bit 0 is the least significant bit)
+                                #       Bit     Data rate
+                                #       0       MCS0
+                                #       1       MCS1
+                                #       2       MCS2
+                                #       3       MCS3
+                                #       4       MCS4
+                                #       5       MCS5
+                                #       6       MCS6
+                                #       7       MCS7
+                                #       32      MCS32
+                HT.RateScopeDword0:4=0x00000000
+                HT.RateScopeDword1:4=0x00000000
+                HT.RateScopeDword2:4=0x00000000
+                HT.RateScopeDword3:4=0x00000000
+	}
+
+        TxRateDrop.TlvType:2=0x0151
+        TxRateDrop.TlvLength:2={
+                RateDrop.Mode:4=0x00000001
+        }
+}
+
+txrate_cfg_set_bgn={
+	CmdCode=0x00d6		# do NOT change this line
+
+	Action:2=1		# 1 - SET
+	Index:2=0		# do NOT change this line
+
+	TxRateScope.TlvType:2=0x0153
+	TxRateScope.TlvLength:2={
+                      ################# TXRATE SCOPE ######################
+
+                                # The following table shows the bitmap of the rates:
+                                # (bit 0 is the least significant bit)
+                                #       Bit     Data rate
+                                #       0       1 Mbps
+                                #       1       2 Mbps
+                                #       2       5.5 Mbps
+                                #       3       11 Mbps
+                                #       4       Reserved
+                HRDSSS.RateScope:2=0x0000
+
+                                # The following table shows the bitmap of the rates:
+                                # (bit 0 is the least significant bit)
+                                #       Bit     Data rate
+                                #       0       6 Mbps
+                                #       1       9 Mbps
+                                #       2       12 Mbps
+                                #       3       18 Mbps
+                                #       4       24 Mbps
+                                #       5       36 Mbps
+                                #       6       48 Mbps
+                                #       7       54 Mbps
+                OFDM.RateScope:2=0x0000
+
+                                # The following table shows the bitmap of the rates:
+                                # (bit 0 is the least significant bit)
+                                #       Bit     Data rate
+                                #       0       MCS0
+                                #       1       MCS1
+                                #       2       MCS2
+                                #       3       MCS3
+                                #       4       MCS4
+                                #       5       MCS5
+                                #       6       MCS6
+                                #       7       MCS7
+                                #       32      MCS32
+                HT.RateScopeDword0:4=0x00000080
+                HT.RateScopeDword1:4=0x00000000
+                HT.RateScopeDword2:4=0x00000000
+                HT.RateScopeDword3:4=0x00000000
+	}
+
+        TxRateDrop.TlvType:2=0x0151
+        TxRateDrop.TlvLength:2={
+                RateDrop.Mode:4=0x00000001
+        }
+}
+
+########supported BasicRate setting###########
+basic_rate_get={
+    CmdCode=0x00d6    # do NOT change this line
+        Action:2=0    # 0 - GET
+         Index:2=0    # do NOT change this line
+
+    TlvType:2=0x21a
+    TlvLength:2={
+    }
+}
+
+basic_rate_set={
+    CmdCode=0x00d6 # do NOT change this line
+
+    Action:2=1     # 1 - SET
+    Index:2=0      # do NOT change this line
+
+    TlvType:2=0x21a
+    TlvLength:2={
+    BasicRateSupport:2=0x000f  #defalt value
+
+       # The following table shows the bitmap of the rates:
+       # (bit 0 is the least significant bit)
+       #       Bit     BasicRateSupport
+       #       0       DBPSK1Mbps
+       #       1       DQPSK2Mbps
+       #       2       CCK5_5Mbps
+       #       3       CCK11Mbps
+       #       4       Not used.
+       #       5       OFDM6Mbps
+       #       6       OFDM9Mbps
+       #       7       OFDM12Mbps
+       #       8       OFDM18Mbps
+       #       9       OFDM24Mbps
+       #      10       OFDM36Mbps
+       #      11       OFDM48Mbps
+       #      12       OFDM54Mbps
+       #     13-15     Reserved
+       #note: value0x0 represents no setting value
+       #For example:
+       #BasicRateSupport:2=0x3 set supported BasicRate to DBPSK1Mbps, DQPSK2Mbps
+       #BasicRateSupport:2=0x180 set supported BasicRate to OFDM18Mbps, OFDM12Mbps
+    }
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/mlanconfig.c b/wlan_sd8897/mapp/mlanconfig/mlanconfig.c
new file mode 100644
index 0000000..b876af1
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/mlanconfig.c
@@ -0,0 +1,4842 @@
+/** @file  mlanconfig.c
+  *
+  * @brief Program to configure addition parameters into the mlandriver
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     11/26/2008: initial version
+     03/10/2009:  add setuserscan, getscantable etc. commands
+     08/11/2009:  add addts, regclass, setra, scanagent etc. commands
+************************************************************************/
+
+#include    "mlanconfig.h"
+#include    "mlanhostcmd.h"
+#include    "mlanmisc.h"
+
+/** mlanconfig version number */
+#define MLANCONFIG_VER "M2.0"
+
+/** Initial number of total private ioctl calls */
+#define IW_INIT_PRIV_NUM    128
+/** Maximum number of total private ioctl calls supported */
+#define IW_MAX_PRIV_NUM     1024
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/** Private ioctl commands */
+enum COMMANDS {
+	CMD_HOSTCMD,
+	CMD_MEFCFG,
+	CMD_ARPFILTER,
+	CMD_CFG_DATA,
+	CMD_CMD52RW,
+	CMD_CMD53RW,
+	CMD_GET_SCAN_RSP,
+	CMD_SET_USER_SCAN,
+	CMD_ADD_TS,
+	CMD_DEL_TS,
+	CMD_QCONFIG,
+	CMD_QSTATS,
+	CMD_TS_STATUS,
+	CMD_WMM_QSTATUS,
+	CMD_REGRW,
+	CMD_MEMRW,
+	CMD_STA_CUSTOM_IE,
+	CMD_STA_MGMT_FRAME_TX,
+	CMD_TDLS_CONF,
+	CMD_TDLS_INFO,
+	CMD_TDLS_DISCOVERY,
+	CMD_TDLS_SETUP,
+	CMD_TDLS_TEARDOWN,
+	CMD_TDLS_POWERMODE,
+	CMD_TDLS_LINK_STATUS,
+	CMD_TDLS_DEBUG,
+	CMD_TDLS_CHANNEL_SWITCH,
+	CMD_TDLS_STOP_CHAN_SWITCH,
+	CMD_TDLS_CS_PARAMS,
+	CMD_TDLS_CS_DISABLE,
+};
+
+static t_s8 *commands[] = {
+	"hostcmd",
+	"mefcfg",
+	"arpfilter",
+	"cfgdata",
+	"sdcmd52rw",
+	"sdcmd53rw",
+	"getscantable",
+	"setuserscan",
+	"addts",
+	"delts",
+	"qconfig",
+	"qstats",
+	"ts_status",
+	"qstatus",
+	"regrdwr",
+	"memrdwr",
+	"customie",
+	"mgmtframetx",
+	"tdls_config",
+	"tdls_setinfo",
+	"tdls_discovery",
+	"tdls_setup",
+	"tdls_teardown",
+	"tdls_powermode",
+	"tdls_link_status",
+	"tdls_debug",
+	"tdls_channel_switch",
+	"tdls_stop_channel_switch",
+	"tdls_cs_params",
+	"tdls_disable_cs",
+};
+
+static t_s8 *usage[] = {
+	"Usage: ",
+	"   mlanconfig -v  (version)",
+	"   mlanconfig <mlanX> <cmd> [...]",
+	"   where",
+	"   mlanX : wireless network interface",
+	"   cmd : hostcmd",
+	"     : mefcfg",
+	"     : customie",
+	"     : mgmtframetx",
+	"     : arpfilter",
+	"     : tdls_config",
+	"     : tdls_setinfo",
+	"     : tdls_discovery",
+	"     : tdls_setup",
+	"     : tdls_teardown",
+	"     : tdls_powermode",
+	"     : tdls_link_status",
+	"     : tdls_debug",
+	"     : tdls_channel_switch",
+	"     : tdls_stop_channel_switch",
+	"     : tdls_cs_params",
+	"     : tdls_disable_cs",
+	"     : cfgdata",
+	"     : sdcmd52rw, sdcmd53rw",
+	"     : getscantable, setuserscan",
+	"     : addts, delts, qconfig, qstats, ts_status, qstatus",
+	"     : regrdwr, memrdwr",
+	"     : additional parameter for hostcmd",
+	"     :   <filename> <cmd>",
+	" 	  : additional parameters for mefcfg are:",
+	"     :   <filename>",
+	"      : additional parameters for customie are:",
+	"      :  <index> <mask> <IE buffer>",
+	"      : additional parameters for mgmtframetx are:",
+	"      : <pkt file>",
+	"     : additional parameter for arpfilter",
+	"     :   <filename>",
+	"     : additional parameter for tdls_setinfo",
+	"     :   <filename>",
+	"     : additional parameter for tdls_discovery",
+	"     :   <filename>",
+	"     : additional parameter for tdls_setup",
+	"     :   <filename>",
+	"     : additional parameter for tdls_teardown",
+	"     :   <filename>",
+	"     : additional parameter for tdls_powermode",
+	"     :   <filename>",
+	"     : additional parameter for tdls_debug <parameters>",
+	"     : additional parameter for tdls_channel_switch",
+	"     :   <filename>",
+	"     : additional parameter for tdls_stop_channel_switch",
+	"     :   <filename>",
+	"     : additional parameter for tdls_cs_params",
+	"     :   <filename>",
+	"     : additional parameter for cfgdata",
+	"     :   <type> <filename>",
+	"     : additional parameter for sdcmd52rw",
+	"     :   <function> <reg addr.> <data>",
+	"     : additional parameter for sdcmd53rw",
+	"     :   <func> <addr> <mode> <blksiz> <blknum> <data1> ... ...<dataN> ",
+	"     : additional parameter for addts",
+	"     :   <filename.conf> <section# of tspec> <timeout in ms>",
+	"     : additional parameter for delts",
+	"     :   <filename.conf> <section# of tspec>",
+	"     : additional parameter for qconfig",
+	"     :   <[set msdu <lifetime in TUs> [Queue Id: 0-3]]",
+	"     :    [get [Queue Id: 0-3]] [def [Queue Id: 0-3]]>",
+	"     : additional parameter for qstats",
+	"     :   <[get [User Priority: 0-7]]>",
+	"     : additional parameter for regrdwr",
+	"     :   <type> <offset> [value]",
+	"     : additional parameter for memrdwr",
+	"     :   <address> [value]",
+};
+
+t_s32 sockfd;  /**< socket */
+t_s8 dev_name[IFNAMSIZ + 1];	/**< device name */
+static struct iw_priv_args *priv_args = NULL;	   /**< private args */
+static int we_version_compiled = 0;
+				  /**< version compiled */
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *    @brief isdigit for String.
+ *
+ *    @param x            Char string
+ *    @return             MLAN_STATUS_FAILURE for non-digit.
+ *                        MLAN_STATUS_SUCCESS for digit
+ */
+static int
+ISDIGIT(t_s8 *x)
+{
+	unsigned int i;
+	for (i = 0; i < strlen(x); i++)
+		if (isdigit(x[i]) == 0)
+			return MLAN_STATUS_FAILURE;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * Check of decimal or hex string
+ * @param   num string
+ */
+#define IS_HEX_OR_DIGIT(num) \
+    (strncasecmp("0x", (num), 2)?ISDIGIT((num)):ishexstring((num)))
+
+/**
+ *  @brief Get private info.
+ *
+ *  @param ifname   A pointer to net name
+ *  @return 	    MLAN_STATUS_SUCCESS--success, otherwise --fail
+ */
+static int
+get_private_info(const t_s8 *ifname)
+{
+	/* This function sends the SIOCGIWPRIV command, which is
+	 * handled by the kernel and gets the total number of
+	 * private ioctl's available in the host driver.
+	 */
+	struct iwreq iwr;
+	int s, ret = MLAN_STATUS_SUCCESS;
+	struct iw_priv_args *ppriv = NULL;
+	struct iw_priv_args *new_priv;
+	int result = 0;
+	size_t size = IW_INIT_PRIV_NUM;
+
+	s = socket(PF_INET, SOCK_DGRAM, 0);
+	if (s < 0) {
+		perror("socket[PF_INET,SOCK_DGRAM]");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, ifname, IFNAMSIZ - 1);
+
+	do {
+		/* (Re)allocate the buffer */
+		new_priv = realloc(ppriv, size * sizeof(ppriv[0]));
+		if (new_priv == NULL) {
+			printf("Error: Buffer allocation failed\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		ppriv = new_priv;
+
+		iwr.u.data.pointer = (caddr_t) ppriv;
+		iwr.u.data.length = size;
+		iwr.u.data.flags = 0;
+
+		if (ioctl(s, SIOCGIWPRIV, &iwr) < 0) {
+			result = errno;
+			ret = MLAN_STATUS_FAILURE;
+			if (result == E2BIG) {
+				/* We need a bigger buffer. Check if kernel gave us any hints. */
+				if (iwr.u.data.length > size) {
+					/* Kernel provided required size */
+					size = iwr.u.data.length;
+				} else {
+					/* No hint from kernel, double the buffer size */
+					size *= 2;
+				}
+			} else {
+				/* ioctl error */
+				perror("ioctl[SIOCGIWPRIV]");
+				break;
+			}
+		} else {
+			/* Success. Return the number of private ioctls */
+			priv_args = ppriv;
+			ret = iwr.u.data.length;
+			break;
+		}
+	} while (size <= IW_MAX_PRIV_NUM);
+
+	if ((ret == MLAN_STATUS_FAILURE) && (ppriv))
+		free(ppriv);
+
+	close(s);
+
+	return ret;
+}
+
+/**
+ *  @brief Get Sub command ioctl number
+ *
+ *  @param i        command index
+ *  @param priv_cnt     Total number of private ioctls availabe in driver
+ *  @param ioctl_val    A pointer to return ioctl number
+ *  @param subioctl_val A pointer to return sub-ioctl number
+ *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static int
+marvell_get_subioctl_no(t_s32 i,
+			t_s32 priv_cnt, int *ioctl_val, int *subioctl_val)
+{
+	t_s32 j;
+
+	if (priv_args[i].cmd >= SIOCDEVPRIVATE) {
+		*ioctl_val = priv_args[i].cmd;
+		*subioctl_val = 0;
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	j = -1;
+
+	/* Find the matching *real* ioctl */
+
+	while ((++j < priv_cnt)
+	       && ((priv_args[j].name[0] != '\0') ||
+		   (priv_args[j].set_args != priv_args[i].set_args) ||
+		   (priv_args[j].get_args != priv_args[i].get_args))) {
+	}
+
+	/* If not found... */
+	if (j == priv_cnt) {
+		printf("%s: Invalid private ioctl definition for: 0x%x\n",
+		       dev_name, priv_args[i].cmd);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Save ioctl numbers */
+	*ioctl_val = priv_args[j].cmd;
+	*subioctl_val = priv_args[i].cmd;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get ioctl number
+ *
+ *  @param ifname   	A pointer to net name
+ *  @param priv_cmd	A pointer to priv command buffer
+ *  @param ioctl_val    A pointer to return ioctl number
+ *  @param subioctl_val A pointer to return sub-ioctl number
+ *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static int
+marvell_get_ioctl_no(const t_s8 *ifname,
+		     const t_s8 *priv_cmd, int *ioctl_val, int *subioctl_val)
+{
+	t_s32 i;
+	t_s32 priv_cnt;
+	int ret = MLAN_STATUS_FAILURE;
+
+	priv_cnt = get_private_info(ifname);
+
+	/* Are there any private ioctls? */
+	if (priv_cnt <= 0 || priv_cnt > IW_MAX_PRIV_NUM) {
+		/* Could skip this message ? */
+		printf("%-8.8s  no private ioctls.\n", ifname);
+	} else {
+		for (i = 0; i < priv_cnt; i++) {
+			if (priv_args[i].name[0] &&
+			    !strcmp(priv_args[i].name, priv_cmd)) {
+				ret = marvell_get_subioctl_no(i, priv_cnt,
+							      ioctl_val,
+							      subioctl_val);
+				break;
+			}
+		}
+	}
+
+	if (priv_args) {
+		free(priv_args);
+		priv_args = NULL;
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief Retrieve the ioctl and sub-ioctl numbers for the given ioctl string
+ *
+ *  @param ioctl_name   Private IOCTL string name
+ *  @param ioctl_val    A pointer to return ioctl number
+ *  @param subioctl_val A pointer to return sub-ioctl number
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+int
+get_priv_ioctl(char *ioctl_name, int *ioctl_val, int *subioctl_val)
+{
+	int retval;
+
+	retval = marvell_get_ioctl_no(dev_name,
+				      ioctl_name, ioctl_val, subioctl_val);
+
+	return retval;
+}
+
+/**
+ *  @brief Process host_cmd
+ *  @param argc		number of arguments
+ *  @param argv		A pointer to arguments array
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_host_cmd(int argc, char *argv[])
+{
+	t_s8 cmdname[256];
+	t_u8 *buf;
+	HostCmd_DS_GEN *hostcmd;
+	struct iwreq iwr;
+	int ret = MLAN_STATUS_SUCCESS;
+	int ioctl_val, subioctl_val;
+	FILE *fp = NULL;
+
+	if (get_priv_ioctl("hostcmd",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	if (argc < 5) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanconfig mlanX hostcmd <hostcmd.conf> <cmdname>\n");
+		exit(1);
+	}
+
+	if ((fp = fopen(argv[3], "r")) == NULL) {
+		fprintf(stderr, "Cannot open file %s\n", argv[3]);
+		exit(1);
+	}
+
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (buf == NULL) {
+		printf("Error: allocate memory for hostcmd failed\n");
+		fclose(fp);
+		return -ENOMEM;
+	}
+	snprintf(cmdname, sizeof(cmdname), "%s", argv[4]);
+	ret = prepare_host_cmd_buffer(fp, cmdname, buf);
+	fclose(fp);
+
+	if (ret == MLAN_STATUS_FAILURE)
+		goto _exit_;
+
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = (t_u8 *)hostcmd;
+	iwr.u.data.length = le16_to_cpu(hostcmd->size);
+
+	iwr.u.data.flags = 0;
+	if (ioctl(sockfd, ioctl_val, &iwr)) {
+		fprintf(stderr,
+			"mlanconfig: MLANHOSTCMD is not supported by %s\n",
+			dev_name);
+		ret = MLAN_STATUS_FAILURE;
+		goto _exit_;
+	}
+	ret = process_host_cmd_resp(buf);
+
+_exit_:
+	if (buf)
+		free(buf);
+
+	return ret;
+}
+
+/**
+ *  @brief  get range
+ *
+ *  @return	MLAN_STATUS_SUCCESS--success, otherwise --fail
+ */
+static int
+get_range(t_void)
+{
+	struct iw_range *range;
+	struct iwreq iwr;
+	size_t buf_len;
+
+	buf_len = sizeof(struct iw_range) + 500;
+	range = malloc(buf_len);
+	if (range == NULL) {
+		printf("Error: allocate memory for iw_range failed\n");
+		return -ENOMEM;
+	}
+	memset(range, 0, buf_len);
+	memset(&iwr, 0, sizeof(struct iwreq));
+	iwr.u.data.pointer = (caddr_t) range;
+	iwr.u.data.length = buf_len;
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+
+	if ((ioctl(sockfd, SIOCGIWRANGE, &iwr)) < 0) {
+		printf("Get Range Results Failed\n");
+		free(range);
+		return MLAN_STATUS_FAILURE;
+	}
+	we_version_compiled = range->we_version_compiled;
+	printf("Driver build with Wireless Extension %d\n",
+	       range->we_version_compiled);
+	free(range);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Display usage
+ *
+ *  @return       NA
+ */
+static t_void
+display_usage(t_void)
+{
+	t_u32 i;
+	for (i = 0; i < NELEMENTS(usage); i++)
+		fprintf(stderr, "%s\n", usage[i]);
+}
+
+/**
+ *  @brief Find command
+ *
+ *  @param maxcmds  max command number
+ *  @param cmds     A pointer to commands buffer
+ *  @param cmd      A pointer to command buffer
+ *  @return         index of command or MLAN_STATUS_FAILURE
+ */
+static int
+findcommand(t_s32 maxcmds, t_s8 *cmds[], t_s8 *cmd)
+{
+	t_s32 i;
+
+	for (i = 0; i < maxcmds; i++) {
+		if (!strcasecmp(cmds[i], cmd)) {
+			return i;
+		}
+	}
+
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Process arpfilter
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_arpfilter(int argc, char *argv[])
+{
+	t_u8 *buf;
+	struct iwreq iwr;
+	t_u16 length = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+	FILE *fp = NULL;
+	int ioctl_val, subioctl_val;
+
+	if (get_priv_ioctl("arpfilter",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	if (argc < 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanconfig mlanX arpfilter <arpfilter.conf>\n");
+		exit(1);
+	}
+
+	if ((fp = fopen(argv[3], "r")) == NULL) {
+		fprintf(stderr, "Cannot open file %s\n", argv[3]);
+		return MLAN_STATUS_FAILURE;
+	}
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (buf == NULL) {
+		printf("Error: allocate memory for arpfilter failed\n");
+		fclose(fp);
+		return -ENOMEM;
+	}
+	ret = prepare_arp_filter_buffer(fp, buf, &length);
+	fclose(fp);
+
+	if (ret == MLAN_STATUS_FAILURE)
+		goto _exit_;
+
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = buf;
+	iwr.u.data.length = length;
+	iwr.u.data.flags = 0;
+	if (ioctl(sockfd, ioctl_val, &iwr)) {
+		fprintf(stderr,
+			"mlanconfig: arpfilter command is not supported by %s\n",
+			dev_name);
+		ret = MLAN_STATUS_FAILURE;
+		goto _exit_;
+	}
+
+_exit_:
+	if (buf)
+		free(buf);
+
+	return ret;
+}
+
+/**
+ *  @brief Process cfgdata
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_cfg_data(int argc, char *argv[])
+{
+	t_u8 *buf;
+	HostCmd_DS_GEN *hostcmd;
+	struct iwreq iwr;
+	int ret = MLAN_STATUS_SUCCESS;
+	int ioctl_val, subioctl_val;
+	FILE *fp = NULL;
+
+	if (get_priv_ioctl("hostcmd",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	if (argc < 4 || argc > 5) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanconfig mlanX cfgdata <register type> <filename>\n");
+		exit(1);
+	}
+
+	if (argc == 5) {
+		if ((fp = fopen(argv[4], "r")) == NULL) {
+			fprintf(stderr, "Cannot open file %s\n", argv[3]);
+			exit(1);
+		}
+	}
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (buf == NULL) {
+		printf("Error: allocate memory for hostcmd failed\n");
+		if (argc == 5)
+			fclose(fp);
+		return -ENOMEM;
+	}
+	ret = prepare_cfg_data_buffer(argc, argv, fp, buf);
+	if (argc == 5)
+		fclose(fp);
+
+	if (ret == MLAN_STATUS_FAILURE)
+		goto _exit_;
+
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = (t_u8 *)hostcmd;
+	iwr.u.data.length = le16_to_cpu(hostcmd->size);
+
+	iwr.u.data.flags = 0;
+	if (ioctl(sockfd, ioctl_val, &iwr)) {
+		fprintf(stderr,
+			"mlanconfig: MLANHOSTCMD is not supported by %s\n",
+			dev_name);
+		ret = MLAN_STATUS_FAILURE;
+		goto _exit_;
+	}
+	ret = process_host_cmd_resp(buf);
+
+_exit_:
+	if (buf)
+		free(buf);
+
+	return ret;
+}
+
+/**
+ *  @brief read current command
+ *  @param ptr      A pointer to data
+ *  @param curCmd   A pointer to the buf which will hold current command
+ *  @return         NULL or the pointer to the left command buf
+ */
+static t_s8 *
+readCurCmd(t_s8 *ptr, t_s8 *curCmd)
+{
+	t_s32 i = 0;
+#define MAX_CMD_SIZE 64	/**< Max command size */
+
+	while (*ptr != ']' && i < (MAX_CMD_SIZE - 1))
+		curCmd[i++] = *(++ptr);
+
+	if (*ptr != ']')
+		return NULL;
+
+	curCmd[i - 1] = '\0';
+
+	return ++ptr;
+}
+
+/**
+ *  @brief parse command and hex data
+ *  @param fp       A pointer to FILE stream
+ *  @param dst      A pointer to the dest buf
+ *  @param cmd      A pointer to command buf for search
+ *  @return         Length of hex data or MLAN_STATUS_FAILURE
+ */
+static int
+fparse_for_cmd_and_hex(FILE * fp, t_u8 *dst, t_u8 *cmd)
+{
+	t_s8 *ptr;
+	t_u8 *dptr;
+	t_s8 buf[256], curCmd[64];
+	t_s32 isCurCmd = 0;
+
+	dptr = dst;
+	while (fgets(buf, sizeof(buf), fp)) {
+		ptr = buf;
+
+		while (*ptr) {
+			/* skip leading spaces */
+			while (*ptr && isspace(*ptr))
+				ptr++;
+
+			/* skip blank lines and lines beginning with '#' */
+			if (*ptr == '\0' || *ptr == '#')
+				break;
+
+			if (*ptr == '[' && *(ptr + 1) != '/') {
+				if (!(ptr = readCurCmd(ptr, curCmd)))
+					return MLAN_STATUS_FAILURE;
+
+				if (strcasecmp(curCmd, (char *)cmd))	/* Not equal */
+					isCurCmd = 0;
+				else
+					isCurCmd = 1;
+			}
+
+			/* Ignore the rest if it is not correct cmd */
+			if (!isCurCmd)
+				break;
+
+			if (*ptr == '[' && *(ptr + 1) == '/')
+				return (dptr - dst);
+
+			if (isxdigit(*ptr)) {
+				ptr = convert2hex(ptr, dptr++);
+			} else {
+				/* Invalid character on data line */
+				ptr++;
+			}
+		}
+	}
+
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Send an ADDTS command to the associated AP
+ *
+ *  Process a given conf file for a specific TSPEC data block.  Send the
+ *    TSPEC along with any other IEs to the driver/firmware for transmission
+ *    in an ADDTS request to the associated AP.
+ *
+ *  Return the execution status of the command as well as the ADDTS response
+ *    from the AP if any.
+ *
+ *  mlanconfig mlanX addts <filename.conf> <section# of tspec> <timeout in ms>
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_addts(int argc, char *argv[])
+{
+	int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+	wlan_ioctl_wmm_addts_req_t addtsReq;
+
+	FILE *fp = NULL;
+	char filename[48];
+	char config_id[20];
+
+	memset(&addtsReq, 0x00, sizeof(addtsReq));
+	memset(filename, 0x00, sizeof(filename));
+
+	if (get_priv_ioctl("addts",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	if (argc != 6) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return -EINVAL;
+	}
+
+	strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3])));
+	if ((fp = fopen(filename, "r")) == NULL) {
+		perror("fopen");
+		fprintf(stderr, "Cannot open file %s\n", argv[3]);
+		return -EFAULT;;
+	}
+
+	snprintf(config_id, sizeof(config_id), "tspec%d", atoi(argv[4]));
+
+	addtsReq.ieDataLen = fparse_for_cmd_and_hex(fp,
+						    addtsReq.ieData,
+						    (t_u8 *)config_id);
+
+	if (addtsReq.ieDataLen > 0) {
+		printf("Found %d bytes in the %s section of conf file %s\n",
+		       (int)addtsReq.ieDataLen, config_id, filename);
+	} else {
+		fprintf(stderr, "section %s not found in %s\n",
+			config_id, filename);
+		if (fp)
+			fclose(fp);
+		return -EFAULT;
+	}
+
+	addtsReq.timeout_ms = atoi(argv[5]);
+
+	printf("Cmd Input:\n");
+	hexdump(config_id, addtsReq.ieData, addtsReq.ieDataLen, ' ');
+
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.flags = subioctl_val;
+	iwr.u.data.pointer = (caddr_t) & addtsReq;
+	iwr.u.data.length = (sizeof(addtsReq)
+			     - sizeof(addtsReq.ieData)
+			     + addtsReq.ieDataLen);
+
+	if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+		perror("mlanconfig: addts ioctl");
+		if (fp)
+			fclose(fp);
+		return -EFAULT;
+	}
+
+	printf("Cmd Output:\n");
+	printf("ADDTS Command Result = %d\n", addtsReq.commandResult);
+	printf("ADDTS IEEE Status    = %d\n", addtsReq.ieeeStatusCode);
+	hexdump(config_id, addtsReq.ieData, addtsReq.ieDataLen, ' ');
+
+	if (fp)
+		fclose(fp);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Send a DELTS command to the associated AP
+ *
+ *  Process a given conf file for a specific TSPEC data block.  Send the
+ *    TSPEC along with any other IEs to the driver/firmware for transmission
+ *    in a DELTS request to the associated AP.
+ *
+ *  Return the execution status of the command.  There is no response to a
+ *    DELTS from the AP.
+ *
+ *  mlanconfig mlanX delts <filename.conf> <section# of tspec>
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_delts(int argc, char *argv[])
+{
+	int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+	wlan_ioctl_wmm_delts_req_t deltsReq;
+
+	FILE *fp = NULL;
+	char filename[48];
+	char config_id[20];
+
+	memset(&deltsReq, 0x00, sizeof(deltsReq));
+	memset(filename, 0x00, sizeof(filename));
+
+	if (get_priv_ioctl("delts",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	if (argc != 5) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return -EINVAL;
+	}
+
+	strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3])));
+	if ((fp = fopen(filename, "r")) == NULL) {
+		perror("fopen");
+		fprintf(stderr, "Cannot open file %s\n", argv[3]);
+		return -EFAULT;
+	}
+
+	snprintf(config_id, sizeof(config_id), "tspec%d", atoi(argv[4]));
+
+	deltsReq.ieDataLen = fparse_for_cmd_and_hex(fp,
+						    deltsReq.ieData,
+						    (t_u8 *)config_id);
+
+	if (deltsReq.ieDataLen > 0) {
+		printf("Found %d bytes in the %s section of conf file %s\n",
+		       (int)deltsReq.ieDataLen, config_id, filename);
+	} else {
+		fprintf(stderr, "section %s not found in %s\n",
+			config_id, filename);
+		if (fp)
+			fclose(fp);
+		return -EFAULT;
+	}
+
+	printf("Cmd Input:\n");
+	hexdump(config_id, deltsReq.ieData, deltsReq.ieDataLen, ' ');
+
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.flags = subioctl_val;
+	iwr.u.data.pointer = (caddr_t) & deltsReq;
+	iwr.u.data.length = (sizeof(deltsReq)
+			     - sizeof(deltsReq.ieData)
+			     + deltsReq.ieDataLen);
+
+	if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+		perror("mlanconfig: delts ioctl");
+		if (fp)
+			fclose(fp);
+		return -EFAULT;
+	}
+
+	printf("Cmd Output:\n");
+	printf("DELTS Command Result = %d\n", deltsReq.commandResult);
+	if (fp)
+		fclose(fp);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Send a WMM AC Queue configuration command to get/set/default params
+ *
+ *  Configure or get the parameters of a WMM AC queue. The command takes
+ *    an optional Queue Id as a last parameter.  Without the queue id, all
+ *    queues will be acted upon.
+ *
+ *  mlanconfig mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+ *  mlanconfig mlanX qconfig get [Queue Id: 0-3]
+ *  mlanconfig mlanX qconfig def [Queue Id: 0-3]
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_qconfig(int argc, char *argv[])
+{
+	int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+	wlan_ioctl_wmm_queue_config_t queue_config_cmd;
+	mlan_wmm_ac_e ac_idx;
+	mlan_wmm_ac_e ac_idx_start;
+	mlan_wmm_ac_e ac_idx_stop;
+
+	const char *ac_str_tbl[] = { "BK", "BE", "VI", "VO" };
+
+	if (argc < 4) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return -EINVAL;
+	}
+
+	if (get_priv_ioctl("qconfig",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	memset(&queue_config_cmd, 0x00, sizeof(queue_config_cmd));
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = (caddr_t) & queue_config_cmd;
+	iwr.u.data.length = sizeof(queue_config_cmd);
+	iwr.u.data.flags = subioctl_val;
+
+	if (strcmp(argv[3], "get") == 0) {
+		/*    3     4    5   */
+		/* qconfig get [qid] */
+		if (argc == 4) {
+			ac_idx_start = WMM_AC_BK;
+			ac_idx_stop = WMM_AC_VO;
+		} else if (argc == 5) {
+			if (atoi(argv[4]) < WMM_AC_BK ||
+			    atoi(argv[4]) > WMM_AC_VO) {
+				fprintf(stderr, "ERROR: Invalid Queue ID!\n");
+				return -EINVAL;
+			}
+			ac_idx_start = atoi(argv[4]);
+			ac_idx_stop = ac_idx_start;
+		} else {
+			fprintf(stderr, "Invalid number of parameters!\n");
+			return -EINVAL;
+		}
+		queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_GET;
+
+		for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) {
+			queue_config_cmd.accessCategory = ac_idx;
+			if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+				perror("qconfig ioctl");
+			} else {
+				printf("qconfig %s(%d): MSDU Lifetime GET = 0x%04x (%d)\n", ac_str_tbl[ac_idx], ac_idx, queue_config_cmd.msduLifetimeExpiry, queue_config_cmd.msduLifetimeExpiry);
+			}
+		}
+	} else if (strcmp(argv[3], "set") == 0) {
+		if ((argc >= 5) && strcmp(argv[4], "msdu") == 0) {
+			/*    3     4    5     6      7   */
+			/* qconfig set msdu <value> [qid] */
+			if (argc == 6) {
+				ac_idx_start = WMM_AC_BK;
+				ac_idx_stop = WMM_AC_VO;
+			} else if (argc == 7) {
+				if (atoi(argv[6]) < WMM_AC_BK ||
+				    atoi(argv[6]) > WMM_AC_VO) {
+					fprintf(stderr,
+						"ERROR: Invalid Queue ID!\n");
+					return -EINVAL;
+				}
+				ac_idx_start = atoi(argv[6]);
+				ac_idx_stop = ac_idx_start;
+			} else {
+				fprintf(stderr,
+					"Invalid number of parameters!\n");
+				return -EINVAL;
+			}
+			queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_SET;
+			queue_config_cmd.msduLifetimeExpiry = atoi(argv[5]);
+
+			for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop;
+			     ac_idx++) {
+				queue_config_cmd.accessCategory = ac_idx;
+				if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+					perror("qconfig ioctl");
+				} else {
+					printf("qconfig %s(%d): MSDU Lifetime SET = 0x%04x (%d)\n", ac_str_tbl[ac_idx], ac_idx, queue_config_cmd.msduLifetimeExpiry, queue_config_cmd.msduLifetimeExpiry);
+				}
+			}
+		} else {
+			/* Only MSDU Lifetime provisioning accepted for now */
+			fprintf(stderr, "Invalid set parameter: s/b [msdu]\n");
+			return -EINVAL;
+		}
+	} else if (strncmp(argv[3], "def", strlen("def")) == 0) {
+		/*    3     4    5   */
+		/* qconfig def [qid] */
+		if (argc == 4) {
+			ac_idx_start = WMM_AC_BK;
+			ac_idx_stop = WMM_AC_VO;
+		} else if (argc == 5) {
+			if (atoi(argv[4]) < WMM_AC_BK ||
+			    atoi(argv[4]) > WMM_AC_VO) {
+				fprintf(stderr, "ERROR: Invalid Queue ID!\n");
+				return -EINVAL;
+			}
+			ac_idx_start = atoi(argv[4]);
+			ac_idx_stop = ac_idx_start;
+		} else {
+			fprintf(stderr, "Invalid number of parameters!\n");
+			return -EINVAL;
+		}
+		queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_DEFAULT;
+
+		for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) {
+			queue_config_cmd.accessCategory = ac_idx;
+			if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+				perror("qconfig ioctl");
+			} else {
+				printf("qconfig %s(%d): MSDU Lifetime DEFAULT = 0x%04x (%d)\n", ac_str_tbl[ac_idx], ac_idx, queue_config_cmd.msduLifetimeExpiry, queue_config_cmd.msduLifetimeExpiry);
+			}
+		}
+	} else {
+		fprintf(stderr,
+			"Invalid qconfig command; s/b [set, get, default]\n");
+		return -EINVAL;
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Turn on/off or retrieve and clear the queue statistics for a UP
+ *
+ *  Turn the statistics collection on/off for a given UP or retrieve the
+ *    current accumulated stats and clear them from the firmware.  The command
+ *    takes an optional Queue Id as a last parameter.  Without the queue id,
+ *    all queues will be acted upon.
+ *
+ *  mlanconfig mlanX qstats get [User Priority: 0-7]
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_qstats(int argc, char *argv[])
+{
+	int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+	wlan_ioctl_wmm_queue_stats_t queue_stats_cmd;
+	t_u8 up_idx;
+	t_u8 up_idx_start;
+	t_u8 up_idx_stop;
+	t_u16 usedTime[MAX_USER_PRIORITIES];
+	t_u16 policedTime[MAX_USER_PRIORITIES];
+
+	const char *ac_str_tbl[] = { "BE", "BK", "BK", "BE",
+		"VI", "VI", "VO", "VO"
+	};
+
+	if (argc < 3) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return -EINVAL;
+	}
+
+	if (get_priv_ioctl("qstats",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	printf("\n");
+
+	memset(usedTime, 0x00, sizeof(usedTime));
+	memset(policedTime, 0x00, sizeof(policedTime));
+	memset(&queue_stats_cmd, 0x00, sizeof(queue_stats_cmd));
+
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = (caddr_t) & queue_stats_cmd;
+	iwr.u.data.length = sizeof(queue_stats_cmd);
+	iwr.u.data.flags = subioctl_val;
+
+	if ((argc > 3) && strcmp(argv[3], "on") == 0) {
+		if (argc == 4) {
+			up_idx_start = 0;
+			up_idx_stop = 7;
+		} else if (argc == 5) {
+			if (atoi(argv[4]) < 0 || atoi(argv[4]) > 7) {
+				fprintf(stderr,
+					"ERROR: Invalid User Priority!\n");
+				return -EINVAL;
+			}
+			up_idx_start = atoi(argv[4]);
+			up_idx_stop = up_idx_start;
+		} else {
+			fprintf(stderr, "Invalid number of parameters!\n");
+			return -EINVAL;
+		}
+		queue_stats_cmd.action = WMM_STATS_ACTION_START;
+		for (up_idx = up_idx_start; up_idx <= up_idx_stop; up_idx++) {
+			queue_stats_cmd.userPriority = up_idx;
+			if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+				perror("qstats ioctl");
+			} else {
+				printf("qstats UP%d, %s turned on\n",
+				       up_idx, ac_str_tbl[up_idx]);
+			}
+		}
+	} else if ((argc > 3) && strcmp(argv[3], "off") == 0) {
+		if (argc == 4) {
+			up_idx_start = 0;
+			up_idx_stop = 7;
+		} else if (argc == 5) {
+			if (atoi(argv[4]) < 0 || atoi(argv[4]) > 7) {
+				fprintf(stderr,
+					"ERROR: Invalid User Priority!\n");
+				return -EINVAL;
+			}
+			up_idx_start = atoi(argv[4]);
+			up_idx_stop = up_idx_start;
+		} else {
+			fprintf(stderr, "Invalid number of parameters!\n");
+			return -EINVAL;
+		}
+		queue_stats_cmd.action = WMM_STATS_ACTION_STOP;
+		for (up_idx = up_idx_start; up_idx <= up_idx_stop; up_idx++) {
+			queue_stats_cmd.userPriority = up_idx;
+			if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+				perror("qstats ioctl");
+			} else {
+				printf("qstats UP%d, %s turned off\n",
+				       up_idx, ac_str_tbl[up_idx]);
+			}
+		}
+	} else if ((argc >= 3) &&
+		   ((argc == 3) ? 1 : (strcmp(argv[3], "get") == 0))) {
+		/* If the user types: "mlanconfig mlanX qstats" without get argument.
+		 *   The mlanconfig application invokes "get" option for all UPs
+		 */
+		if ((argc == 4) || (argc == 3)) {
+			up_idx_start = 0;
+			up_idx_stop = 7;
+		} else if (argc == 5) {
+			if (atoi(argv[4]) < 0 || atoi(argv[4]) > 7) {
+				fprintf(stderr,
+					"ERROR: Invalid User Priority!\n");
+				return -EINVAL;
+			}
+			up_idx_start = atoi(argv[4]);
+			up_idx_stop = up_idx_start;
+		} else {
+			fprintf(stderr, "Invalid number of parameters!\n");
+			return -EINVAL;
+		}
+		printf("%s %6s %5s %8s %8s %6s %6s %6s %6s %6s %6s\n",
+		       "AC-UP", "Count", "Loss", "TxDly", "QDly",
+		       "<=5", "<=10", "<=20", "<=30", "<=50", ">50");
+		printf("----------------------------------"
+		       "---------------------------------------------\n");
+		queue_stats_cmd.action = WMM_STATS_ACTION_GET_CLR;
+
+		for (up_idx = up_idx_start; up_idx <= up_idx_stop; up_idx++) {
+			queue_stats_cmd.userPriority = up_idx;
+			if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+				perror("qstats ioctl");
+			} else {
+				printf(" %s-%d %6u %5u %8u %8u %6u %6u %6u %6u %6u %6u\n", ac_str_tbl[up_idx], up_idx, queue_stats_cmd.pktCount, queue_stats_cmd.pktLoss, (unsigned int)queue_stats_cmd.avgTxDelay, (unsigned int)queue_stats_cmd.avgQueueDelay, queue_stats_cmd.delayHistogram[0], queue_stats_cmd.delayHistogram[1], queue_stats_cmd.delayHistogram[2], queue_stats_cmd.delayHistogram[3], (queue_stats_cmd.delayHistogram[4] + queue_stats_cmd.delayHistogram[5]), queue_stats_cmd.delayHistogram[6]);
+
+				usedTime[up_idx] = queue_stats_cmd.usedTime;
+				policedTime[up_idx] =
+					queue_stats_cmd.policedTime;
+			}
+		}
+
+		printf("----------------------------------"
+		       "---------------------------------------------\n");
+		printf("\nAC-UP      UsedTime      PolicedTime\n");
+		printf("------------------------------------\n");
+
+		for (up_idx = up_idx_start; up_idx <= up_idx_stop; up_idx++) {
+			printf(" %s-%d        %6u           %6u\n",
+			       ac_str_tbl[up_idx],
+			       up_idx,
+			       (unsigned int)usedTime[up_idx],
+			       (unsigned int)policedTime[up_idx]);
+		}
+	} else {
+		fprintf(stderr, "Invalid qstats command;\n");
+		return -EINVAL;
+	}
+	printf("\n");
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get the current status of the WMM Queues
+ *
+ *  Command: mlanconfig mlanX qstatus
+ *
+ *  Retrieve the following information for each AC if wmm is enabled:
+ *        - WMM IE ACM Required
+ *        - Firmware Flow Required
+ *        - Firmware Flow Established
+ *        - Firmware Queue Enabled
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_wmm_qstatus(int argc, char *argv[])
+{
+	int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+	wlan_ioctl_wmm_queue_status_t qstatus;
+	mlan_wmm_ac_e acVal;
+
+	if (get_priv_ioctl("qstatus",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	memset(&qstatus, 0x00, sizeof(qstatus));
+
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.flags = subioctl_val;
+	iwr.u.data.pointer = (caddr_t) & qstatus;
+	iwr.u.data.length = (sizeof(qstatus));
+
+	if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+		perror("mlanconfig: qstatus ioctl");
+		return -EFAULT;
+	}
+
+	for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) {
+		switch (acVal) {
+		case WMM_AC_BK:
+			printf("BK: ");
+			break;
+		case WMM_AC_BE:
+			printf("BE: ");
+			break;
+		case WMM_AC_VI:
+			printf("VI: ");
+			break;
+		case WMM_AC_VO:
+			printf("VO: ");
+			break;
+		default:
+			printf("??: ");
+		}
+
+		printf("ACM[%c], FlowReq[%c], FlowCreated[%c], Enabled[%c],"
+		       " DE[%c], TE[%c]\n",
+		       (qstatus.acStatus[acVal].wmmAcm ? 'X' : ' '),
+		       (qstatus.acStatus[acVal].flowRequired ? 'X' : ' '),
+		       (qstatus.acStatus[acVal].flowCreated ? 'X' : ' '),
+		       (qstatus.acStatus[acVal].disabled ? ' ' : 'X'),
+		       (qstatus.acStatus[acVal].deliveryEnabled ? 'X' : ' '),
+		       (qstatus.acStatus[acVal].triggerEnabled ? 'X' : ' '));
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get the current status of the WMM Traffic Streams
+ *
+ *  Command: mlanconfig mlanX ts_status
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_wmm_ts_status(int argc, char *argv[])
+{
+	int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+	wlan_ioctl_wmm_ts_status_t ts_status;
+	int tid;
+
+	const char *ac_str_tbl[] = { "BK", "BE", "VI", "VO" };
+
+	if (get_priv_ioctl("ts_status",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	printf("\nTID   Valid    AC   UP   PSB   FlowDir  MediumTime\n");
+	printf("---------------------------------------------------\n");
+
+	for (tid = 0; tid <= 7; tid++) {
+		memset(&ts_status, 0x00, sizeof(ts_status));
+		ts_status.tid = tid;
+
+		strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+		iwr.u.data.flags = subioctl_val;
+		iwr.u.data.pointer = (caddr_t) & ts_status;
+		iwr.u.data.length = (sizeof(ts_status));
+
+		if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+			perror("mlanconfig: ts_status ioctl");
+			return -EFAULT;
+		}
+
+		printf(" %02d     %3s    %2s    %u     %c    ",
+		       ts_status.tid,
+		       (ts_status.valid ? "Yes" : "No"),
+		       (ts_status.
+			valid ? ac_str_tbl[ts_status.accessCategory] : "--"),
+		       ts_status.userPriority, (ts_status.psb ? 'U' : 'L'));
+
+		if ((ts_status.flowDir & 0x03) == 0) {
+			printf("%s", " ---- ");
+		} else {
+			printf("%2s%4s",
+			       (ts_status.flowDir & 0x01 ? "Up" : ""),
+			       (ts_status.flowDir & 0x02 ? "Down" : ""));
+		}
+
+		printf("%12u\n", ts_status.mediumTime);
+	}
+
+	printf("\n");
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Provides interface to perform read/write operations on regsiter
+ *
+ *  Command: mlanconfig mlanX regrdwr <type> <offset> [value]
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_regrdwr(int argc, char *argv[])
+{
+	struct iwreq iwr;
+	int ioctl_val, subioctl_val;
+	t_u32 type, offset, value;
+	t_u8 buf[100];
+	HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	/* Check arguments */
+	if ((argc < 5) || (argc > 6)) {
+		printf("Parameters for regrdwr: <type> <offset> [value]\n");
+		return -EINVAL;
+	}
+
+	if (get_priv_ioctl("hostcmd",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	type = a2hex_or_atoi(argv[3]);
+	offset = a2hex_or_atoi(argv[4]);
+	if (argc > 5)
+		value = a2hex_or_atoi(argv[5]);
+	if ((ret = prepare_hostcmd_regrdwr(type, offset,
+					   (argc > 5) ? &value : NULL, buf))) {
+		return ret;
+	}
+
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = buf;
+	iwr.u.data.length = le16_to_cpu(hostcmd->size);
+	iwr.u.data.flags = 0;
+
+	if (ioctl(sockfd, ioctl_val, &iwr)) {
+		fprintf(stderr,
+			"mlanconfig: MLANHOSTCMD is not supported by %s\n",
+			dev_name);
+		return MLAN_STATUS_FAILURE;
+	}
+	ret = process_host_cmd_resp(buf);
+
+	return ret;
+}
+
+/**
+ *  @brief Provides interface to perform read/write the adapter memory
+ *
+ *  Command: mlanconfig mlanX memrdwr <address> [value]
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_memrdwr(int argc, char *argv[])
+{
+	struct iwreq iwr;
+	int ioctl_val, subioctl_val;
+	t_u32 address, value;
+	t_u8 buf[100] = { 0 };
+	HostCmd_DS_MEM *pmem;
+	HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	pmem = (HostCmd_DS_MEM *)(buf + S_DS_GEN);
+
+	/* Check arguments */
+	if ((argc < 4) || (argc > 5)) {
+		printf("Parameters for memrdwr: <address> [value]\n");
+		return -EINVAL;
+	}
+
+	if (get_priv_ioctl("hostcmd",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	address = a2hex_or_atoi(argv[3]);
+	pmem->addr = cpu_to_le32(address);
+	if (argc > 4) {
+		pmem->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+		value = a2hex_or_atoi(argv[4]);
+		pmem->value = cpu_to_le32(value);
+	} else {
+		pmem->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+		pmem->value = 0;
+	}
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_MEM_ACCESS);
+	hostcmd->size = cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_MEM));
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = buf;
+	iwr.u.data.length = le16_to_cpu(hostcmd->size);
+	iwr.u.data.flags = 0;
+
+	if (ioctl(sockfd, ioctl_val, &iwr)) {
+		fprintf(stderr,
+			"mlanconfig: MLANHOSTCMD is not supported by %s\n",
+			dev_name);
+		return MLAN_STATUS_FAILURE;
+	}
+	ret = process_host_cmd_resp(buf);
+
+	return ret;
+}
+
+/** custom IE, auto mask value */
+#define	CUSTOM_IE_AUTO_MASK	0xffff
+
+/**
+ * @brief Show usage information for the customie
+ * command
+ *
+ * $return         N/A
+ **/
+void
+print_custom_ie_usage(void)
+{
+	printf("\nUsage : customie [INDEX] [MASK] [IEBuffer]");
+	printf("\n         empty - Get all IE settings\n");
+	printf("\n         INDEX:  0 - Get/Set IE index 0 setting");
+	printf("\n                 1 - Get/Set IE index 1 setting");
+	printf("\n                 2 - Get/Set IE index 2 setting");
+	printf("\n                 3 - Get/Set IE index 3 setting");
+	printf("\n                 .                             ");
+	printf("\n                 .                             ");
+	printf("\n                 .                             ");
+	printf("\n                -1 - Append/Delete IE automatically");
+	printf("\n                     Delete will delete the IE from the matching IE buffer");
+	printf("\n                     Append will append the IE to the buffer with the same mask");
+	printf("\n         MASK :  Management subtype mask value as per bit defintions");
+	printf("\n              :  Bit 0 - Association request.");
+	printf("\n              :  Bit 1 - Association response.");
+	printf("\n              :  Bit 2 - Reassociation request.");
+	printf("\n              :  Bit 3 - Reassociation response.");
+	printf("\n              :  Bit 4 - Probe request.");
+	printf("\n              :  Bit 5 - Probe response.");
+	printf("\n              :  Bit 8 - Beacon.");
+	printf("\n         MASK :  MASK = 0 to clear the mask and the IE buffer");
+	printf("\n         IEBuffer :  IE Buffer in hex (max 256 bytes)\n\n");
+	return;
+}
+
+/**
+ * @brief Converts a string to hex value
+ *
+ * @param str      A pointer to the string
+ * @param raw      A pointer to the raw data buffer
+ * @return         Number of bytes read
+ **/
+int
+string2raw(char *str, unsigned char *raw)
+{
+	int len = (strlen(str) + 1) / 2;
+
+	do {
+		if (!isxdigit(*str)) {
+			return -1;
+		}
+		*str = toupper(*str);
+		*raw = CHAR2INT(*str) << 4;
+		++str;
+		*str = toupper(*str);
+		if (*str == '\0')
+			break;
+		*raw |= CHAR2INT(*str);
+		++raw;
+	} while (*++str != '\0');
+	return len;
+}
+
+/**
+ * @brief Creates a hostcmd request for custom IE settings
+ * and sends to the driver
+ *
+ * Usage: "customie [INDEX] [MASK] [IEBuffer]"
+ *
+ * Options: INDEX :      0 - Get/Delete IE index 0 setting
+ *                       1 - Get/Delete IE index 1 setting
+ *                       2 - Get/Delete IE index 2 setting
+ *                       3 - Get/Delete IE index 3 setting
+ *                       .
+ *                       .
+ *                       .
+ *                      -1 - Append IE at the IE buffer with same MASK
+ *          MASK  :      Management subtype mask value
+ *          IEBuffer:    IE Buffer in hex
+ *   					       empty - Get all IE settings
+ *
+ * @param argc     Number of arguments
+ * @param argv     Pointer to the arguments
+ * @return         N/A
+ **/
+static int
+process_custom_ie(int argc, char *argv[])
+{
+	tlvbuf_custom_ie *tlv = NULL;
+	tlvbuf_max_mgmt_ie *max_mgmt_ie_tlv = NULL;
+	custom_ie *ie_ptr = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 buf_len = 0;
+	t_u16 mgmt_subtype_mask = 0;
+	int ie_buf_len = 0, ie_len = 0, i = 0;
+	struct ifreq ifr;
+
+	/* mlanconfig mlan0 customie idx flag buf */
+	if (argc > 6) {
+		printf("ERR:Too many arguments.\n");
+		print_custom_ie_usage();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Error checks and initialize the command length */
+	if (argc > 3) {
+		if (((IS_HEX_OR_DIGIT(argv[3]) == MLAN_STATUS_FAILURE) &&
+		     (atoi(argv[3]) != -1)) || (atoi(argv[3]) < -1)) {
+			printf("ERR:Illegal index %s\n", argv[3]);
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	switch (argc) {
+	case 3:
+		buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+		break;
+	case 4:
+		if (atoi(argv[3]) < 0) {
+			printf("ERR:Illegal index %s. Must be either greater than or equal to 0 for Get Operation \n", argv[3]);
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+		break;
+	case 5:
+		if (MLAN_STATUS_FAILURE == ishexstring(argv[4]) ||
+		    A2HEXDECIMAL(argv[4]) != 0) {
+			printf("ERR: Mask value should be 0 to clear IEBuffers.\n");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (atoi(argv[3]) == -1) {
+			printf("ERR: You must provide buffer for automatic deletion.\n");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie);
+		break;
+	case 6:
+		/* This is to check negative numbers and special symbols */
+		if (MLAN_STATUS_FAILURE == IS_HEX_OR_DIGIT(argv[4])) {
+			printf("ERR:Mask value must be 0 or hex digits\n");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		/* If above check is passed and mask is not hex, then it must be 0 */
+		if ((ISDIGIT(argv[4]) == MLAN_STATUS_SUCCESS) && atoi(argv[4])) {
+			printf("ERR:Mask value must be 0 or hex digits\n ");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (MLAN_STATUS_FAILURE == ishexstring(argv[5])) {
+			printf("ERR:Only hex digits are allowed\n");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		ie_buf_len = strlen(argv[5]);
+		if (!strncasecmp("0x", argv[5], 2)) {
+			ie_len = (ie_buf_len - 2 + 1) / 2;
+			argv[5] += 2;
+		} else
+			ie_len = (ie_buf_len + 1) / 2;
+		if (ie_len > MAX_IE_BUFFER_LEN) {
+			printf("ERR:Incorrect IE length %d\n", ie_buf_len);
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		mgmt_subtype_mask = (t_u16)A2HEXDECIMAL(argv[4]);
+		buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie) + ie_len;
+		break;
+	}
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+	tlv = (tlvbuf_custom_ie *)buffer;
+	tlv->tag = MRVL_MGMT_IE_LIST_TLV_ID;
+	if (argc == 3 || argc == 4) {
+		if (argc == 3)
+			tlv->length = 0;
+		else {
+			tlv->length = sizeof(t_u16);
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			ie_ptr->ie_index = (t_u16)(atoi(argv[3]));
+		}
+	} else {
+		/* Locate headers */
+		ie_ptr = (custom_ie *)(tlv->ie_data);
+		/* Set TLV fields */
+		tlv->length = sizeof(custom_ie) + ie_len;
+		ie_ptr->ie_index = atoi(argv[3]);
+		ie_ptr->mgmt_subtype_mask = mgmt_subtype_mask;
+		ie_ptr->ie_length = ie_len;
+		if (argc == 6)
+			string2raw(argv[5], ie_ptr->ie_buffer);
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)buffer;
+	/* Perform ioctl */
+	if (ioctl(sockfd, CUSTOM_IE_CFG, &ifr)) {
+		perror("ioctl[CUSTOM_IE_CFG]");
+		printf("ERR:Command sending failed!\n");
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Print response */
+	if (argc > 4) {
+		printf("custom IE setting successful\n");
+	} else {
+		printf("Querying custom IE successful\n");
+		tlv = (tlvbuf_custom_ie *)buffer;
+		ie_len = tlv->length;
+		ie_ptr = (custom_ie *)(tlv->ie_data);
+		while ((unsigned int)ie_len >= sizeof(custom_ie)) {
+			printf("Index [%d]\n", ie_ptr->ie_index);
+			if (ie_ptr->ie_length)
+				printf("Management Subtype Mask = 0x%02x\n",
+				       (ie_ptr->mgmt_subtype_mask) == 0 ?
+				       CUSTOM_IE_AUTO_MASK :
+				       (ie_ptr->mgmt_subtype_mask));
+			else
+				printf("Management Subtype Mask = 0x%02x\n",
+				       (ie_ptr->mgmt_subtype_mask));
+			hexdump("IE Buffer", (void *)ie_ptr->ie_buffer,
+				ie_ptr->ie_length, ' ');
+			ie_len -= sizeof(custom_ie) + ie_ptr->ie_length;
+			ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+					       sizeof(custom_ie) +
+					       ie_ptr->ie_length);
+		}
+	}
+	max_mgmt_ie_tlv =
+		(tlvbuf_max_mgmt_ie *)(buffer + sizeof(tlvbuf_custom_ie) +
+				       tlv->length);
+	if (max_mgmt_ie_tlv) {
+		if (max_mgmt_ie_tlv->tag == MRVL_MAX_MGMT_IE_TLV_ID) {
+			for (i = 0; i < max_mgmt_ie_tlv->count; i++) {
+				printf("buf%d_size = %d\n", i,
+				       max_mgmt_ie_tlv->info[i].buf_size);
+				printf("number of buffers = %d\n",
+				       max_mgmt_ie_tlv->info[i].buf_count);
+				printf("\n");
+			}
+		}
+	}
+	if (buffer)
+		free(buffer);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Get one line from the File
+ *
+ *  @param fp       File handler
+ *  @param str	    Storage location for data.
+ *  @param size 	Maximum number of characters to read.
+ *  @param lineno	A pointer to return current line number
+ *  @return         returns string or NULL
+ */
+char *
+mlan_config_get_line(FILE * fp, t_s8 *str, t_s32 size, int *lineno)
+{
+	char *start, *end;
+	int out, next_line;
+
+	if (!fp || !str)
+		return NULL;
+
+	do {
+read_line:
+		if (!fgets(str, size, fp))
+			break;
+		start = str;
+		start[size - 1] = '\0';
+		end = start + strlen(str);
+		(*lineno)++;
+
+		out = 1;
+		while (out && (start < end)) {
+			next_line = 0;
+			/* Remove empty lines and lines starting with # */
+			switch (start[0]) {
+			case ' ':	/* White space */
+			case '\t':	/* Tab */
+				start++;
+				break;
+			case '#':
+			case '\n':
+			case '\0':
+				next_line = 1;
+				break;
+			case '\r':
+				if (start[1] == '\n')
+					next_line = 1;
+				else
+					start++;
+				break;
+			default:
+				out = 0;
+				break;
+			}
+			if (next_line)
+				goto read_line;
+		}
+
+		/* Remove # comments unless they are within a double quoted
+		 * string. Remove trailing white space. */
+		if ((end = strstr(start, "\""))) {
+			if (!(end = strstr(end + 1, "\"")))
+				end = start;
+		} else
+			end = start;
+
+		if ((end = strstr(end + 1, "#")))
+			*end-- = '\0';
+		else
+			end = start + strlen(start) - 1;
+
+		out = 1;
+		while (out && (start < end)) {
+			switch (*end) {
+			case ' ':	/* White space */
+			case '\t':	/* Tab */
+			case '\n':
+			case '\r':
+				*end = '\0';
+				end--;
+				break;
+			default:
+				out = 0;
+				break;
+			}
+		}
+
+		if (start == '\0')
+			continue;
+
+		return start;
+	} while (1);
+
+	return NULL;
+}
+
+/**
+ *  @brief parse hex data
+ *  @param fp       File handler
+ *  @param dst      A pointer to receive hex data
+ *  @return         length of hex data
+ */
+int
+fparse_for_hex(FILE * fp, t_u8 *dst)
+{
+	t_s8 *ptr;
+	t_u8 *dptr;
+	t_s8 buf[256];
+
+	dptr = dst;
+	while (fgets(buf, sizeof(buf), fp)) {
+		ptr = buf;
+
+		while (*ptr) {
+			/* skip leading spaces */
+			while (*ptr && (isspace(*ptr) || *ptr == '\t'))
+				ptr++;
+
+			/* skip blank lines and lines beginning with '#' */
+			if (*ptr == '\0' || *ptr == '#')
+				break;
+
+			if (isxdigit(*ptr)) {
+				ptr = convert2hex(ptr, dptr++);
+			} else {
+				/* Invalid character on data line */
+				ptr++;
+			}
+		}
+	}
+
+	return (dptr - dst);
+}
+
+#define STACK_NBYTES            	100	/**< Number of bytes in stack */
+#define MAX_BYTESEQ 		       	6	/**< Maximum byte sequence */
+#define TYPE_DNUM           		1 /**< decimal number */
+#define TYPE_BYTESEQ        		2 /**< byte sequence */
+#define MAX_OPERAND         		0x40	/**< Maximum operands */
+#define TYPE_EQ         		(MAX_OPERAND+1)	/**< byte comparison:    == operator */
+#define TYPE_EQ_DNUM    		(MAX_OPERAND+2)	/**< decimal comparison: =d operator */
+#define TYPE_EQ_BIT     		(MAX_OPERAND+3)	/**< bit comparison:     =b operator */
+#define TYPE_AND        		(MAX_OPERAND+4)	/**< && operator */
+#define TYPE_OR         		(MAX_OPERAND+5)	/**< || operator */
+
+typedef struct {
+	t_u16 sp;		      /**< Stack pointer */
+	t_u8 byte[STACK_NBYTES];      /**< Stack */
+} mstack_t;
+
+typedef struct {
+	t_u8 type;		  /**< Type */
+	t_u8 reserve[3];   /**< so 4-byte align val array */
+	/* byte sequence is the largest among all the operands and operators. */
+	/* byte sequence format: 1 byte of num of bytes, then variable num bytes */
+	t_u8 val[MAX_BYTESEQ + 1];/**< Value */
+} op_t;
+
+/**
+ *  @brief push data to stack
+ *
+ *  @param s			a pointer to mstack_t structure
+ *
+ *  @param nbytes		number of byte to push to stack
+ *
+ *  @param val			a pointer to data buffer
+ *
+ *  @return			TRUE-- sucess , FALSE -- fail
+ *
+ */
+static int
+push_n(mstack_t * s, t_u8 nbytes, t_u8 *val)
+{
+	if ((s->sp + nbytes) < STACK_NBYTES) {
+		memcpy((void *)(s->byte + s->sp), (const void *)val,
+		       (size_t) nbytes);
+		s->sp += nbytes;
+		/* printf("push: n %d sp %d\n", nbytes, s->sp); */
+		return TRUE;
+	} else			/* stack full */
+		return FALSE;
+}
+
+/**
+ *  @brief push data to stack
+ *
+ *  @param s			a pointer to mstack_t structure
+ *
+ *  @param op			a pointer to op_t structure
+ *
+ *  @return			TRUE-- sucess , FALSE -- fail
+ *
+ */
+static int
+push(mstack_t * s, op_t * op)
+{
+	t_u8 nbytes;
+	switch (op->type) {
+	case TYPE_DNUM:
+		if (push_n(s, 4, op->val))
+			return (push_n(s, 1, &op->type));
+		return FALSE;
+	case TYPE_BYTESEQ:
+		nbytes = op->val[0];
+		if (push_n(s, nbytes, op->val + 1) &&
+		    push_n(s, 1, op->val) && push_n(s, 1, &op->type))
+			return TRUE;
+		return FALSE;
+	default:
+		return (push_n(s, 1, &op->type));
+	}
+}
+
+/**
+ *  @brief parse RPN string
+ *
+ *  @param s			a pointer to Null-terminated string to scan.
+ *
+ *  @param first_time		a pointer to return first_time
+ *
+ *  @return			A pointer to the last token found in string.
+ *  				NULL is returned when there are no more tokens to be found.
+ *
+ */
+static char *
+getop(char *s, int *first_time)
+{
+	const char delim[] = " \t\n";
+	char *p;
+	if (*first_time) {
+		p = strtok(s, delim);
+		*first_time = FALSE;
+	} else {
+		p = strtok(NULL, delim);
+	}
+	return (p);
+}
+
+/**
+ *  @brief Verify hex digit.
+ *
+ *  @param c			input ascii char
+ *  @param h			a pointer to return integer value of the digit char.
+ *  @return			TURE -- c is hex digit, FALSE -- c is not hex digit.
+ */
+static int
+ishexdigit(char c, t_u8 *h)
+{
+	if (c >= '0' && c <= '9') {
+		*h = c - '0';
+		return (TRUE);
+	} else if (c >= 'a' && c <= 'f') {
+		*h = c - 'a' + 10;
+		return (TRUE);
+	} else if (c >= 'A' && c <= 'F') {
+		*h = c - 'A' + 10;
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/**
+ *  @brief convert hex string to integer.
+ *
+ *  @param s			A pointer to hex string, string length up to 2 digits.
+ *  @return			integer value.
+ */
+static t_u8
+hex_atoi(char *s)
+{
+	int i;
+	t_u8 digit;		/* digital value */
+	t_u8 t = 0;		/* total value */
+
+	for (i = 0, t = 0; ishexdigit(s[i], &digit) && i < 2; i++)
+		t = 16 * t + digit;
+	return (t);
+}
+
+/**
+ *  @brief Parse byte sequence in hex format string to a byte sequence.
+ *
+ *  @param opstr		A pointer to byte sequence in hex format string, with ':' as delimiter between two byte.
+ *  @param val			A pointer to return byte sequence string
+ *  @return			NA
+ */
+static void
+parse_hex(char *opstr, t_u8 *val)
+{
+	char delim = ':';
+	char *p;
+	char *q;
+	t_u8 i;
+
+	/* +1 is for skipping over the preceding h character. */
+	p = opstr + 1;
+
+	/* First byte */
+	val[1] = hex_atoi(p++);
+
+	/* Parse subsequent bytes. */
+	/* Each byte is preceded by the : character. */
+	for (i = 1; *p; i++) {
+		q = strchr(p, delim);
+		if (!q)
+			break;
+		p = q + 1;
+		val[i + 1] = hex_atoi(p);
+	}
+	/* Set num of bytes */
+	val[0] = i;
+}
+
+/**
+ *  @brief str2bin, convert RPN string to binary format
+ *
+ *  @param str			A pointer to rpn string
+ *  @param stack		A pointer to mstack_t structure
+ *  @return			MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+str2bin(char *str, mstack_t * stack)
+{
+	int first_time;
+	char *opstr;
+	op_t op;		/* operator/operand */
+	int dnum;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	memset(stack, 0, sizeof(mstack_t));
+	first_time = TRUE;
+	while ((opstr = getop(str, &first_time)) != NULL) {
+		if (isdigit(*opstr)) {
+			op.type = TYPE_DNUM;
+			dnum = cpu_to_le32(atoi(opstr));
+			memcpy((t_u8 *)op.val, &dnum, sizeof(dnum));
+			if (!push(stack, &op)) {
+				printf("push decimal number failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (*opstr == 'h') {
+			op.type = TYPE_BYTESEQ;
+			parse_hex(opstr, op.val);
+			if (!push(stack, &op)) {
+				printf("push byte sequence failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "==")) {
+			op.type = TYPE_EQ;
+			if (!push(stack, &op)) {
+				printf("push byte cmp operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "=d")) {
+			op.type = TYPE_EQ_DNUM;
+			if (!push(stack, &op)) {
+				printf("push decimal cmp operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "=b")) {
+			op.type = TYPE_EQ_BIT;
+			if (!push(stack, &op)) {
+				printf("push bit cmp operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "&&")) {
+			op.type = TYPE_AND;
+			if (!push(stack, &op)) {
+				printf("push AND operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "||")) {
+			op.type = TYPE_OR;
+			if (!push(stack, &op)) {
+				printf("push OR operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else {
+			printf("Unknown operand\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+	}
+	return ret;
+}
+
+/**
+ *  @brief Converts colon separated MAC address to hex value
+ *
+ *  @param mac      A pointer to the colon separated MAC string
+ *  @param raw      A pointer to the hex data buffer
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *                  MAC_BROADCAST   - if breadcast mac
+ *                  MAC_MULTICAST   - if multicast mac
+ */
+static int
+mac2raw(char *mac, t_u8 *raw)
+{
+	unsigned int temp_raw[ETH_ALEN];
+	int num_tokens = 0;
+	int i;
+
+	if (strlen(mac) != ((2 * ETH_ALEN) + (ETH_ALEN - 1))) {
+		return MLAN_STATUS_FAILURE;
+	}
+	num_tokens = sscanf(mac, "%2x:%2x:%2x:%2x:%2x:%2x",
+			    temp_raw + 0, temp_raw + 1, temp_raw + 2,
+			    temp_raw + 3, temp_raw + 4, temp_raw + 5);
+	if (num_tokens != ETH_ALEN) {
+		return MLAN_STATUS_FAILURE;
+	}
+	for (i = 0; i < num_tokens; i++)
+		raw[i] = (t_u8)temp_raw[i];
+
+	if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) {
+		return MAC_BROADCAST;
+	} else if (raw[0] & 0x01) {
+		return MAC_MULTICAST;
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief          Parse function for a configuration line
+ *
+ *  @param s        Storage buffer for data
+ *  @param size     Maximum size of data
+ *  @param stream   File stream pointer
+ *  @param line     Pointer to current line within the file
+ *  @param _pos     Output string or NULL
+ *  @return         String or NULL
+ */
+static char *
+config_get_line(char *s, int size, FILE * stream, int *line, char **_pos)
+{
+	*_pos = mlan_config_get_line(stream, s, size, line);
+	return *_pos;
+}
+
+/**
+ *  @brief Parses a command line
+ *
+ *  @param line     The line to parse
+ *  @param args     Pointer to the argument buffer to be filled in
+ *  @return         Number of arguments in the line or EOF
+ */
+static int
+parse_line(char *line, char *args[])
+{
+	int arg_num = 0;
+	int is_start = 0;
+	int is_quote = 0;
+	int length = 0;
+	int i = 0;
+
+	arg_num = 0;
+	length = strlen(line);
+	/* Process line */
+
+	/* Find number of arguments */
+	is_start = 0;
+	is_quote = 0;
+	for (i = 0; i < length; i++) {
+		/* Ignore leading spaces */
+		if (is_start == 0) {
+			if (line[i] == ' ') {
+				continue;
+			} else if (line[i] == '\t') {
+				continue;
+			} else if (line[i] == '\n') {
+				break;
+			} else {
+				is_start = 1;
+				args[arg_num] = &line[i];
+				arg_num++;
+			}
+		}
+		if (is_start == 1) {
+			/* Ignore comments */
+			if (line[i] == '#') {
+				if (is_quote == 0) {
+					line[i] = '\0';
+					arg_num--;
+				}
+				break;
+			}
+			/* Separate by '=' */
+			if (line[i] == '=') {
+				line[i] = '\0';
+				is_start = 0;
+				continue;
+			}
+			/* Separate by ',' */
+			if (line[i] == ',') {
+				line[i] = '\0';
+				is_start = 0;
+				continue;
+			}
+			/* Change ',' to ' ', but not inside quotes */
+			if ((line[i] == ',') && (is_quote == 0)) {
+				line[i] = ' ';
+				continue;
+			}
+		}
+		/* Remove newlines */
+		if (line[i] == '\n') {
+			line[i] = '\0';
+		}
+		/* Check for quotes */
+		if (line[i] == '"') {
+			is_quote = (is_quote == 1) ? 0 : 1;
+			continue;
+		}
+		if (((line[i] == ' ') || (line[i] == '\t')) && (is_quote == 0)) {
+			line[i] = '\0';
+			is_start = 0;
+			continue;
+		}
+	}
+	return arg_num;
+}
+
+#define FILTER_BYTESEQ 		TYPE_EQ	/**< byte sequence */
+#define FILTER_DNUM    		TYPE_EQ_DNUM /**< decimal number */
+#define FILTER_BITSEQ		TYPE_EQ_BIT /**< bit sequence */
+#define FILTER_TEST		FILTER_BITSEQ+1	/**< test */
+
+#define NAME_TYPE		1	    /**< Field name 'type' */
+#define NAME_PATTERN		2	/**< Field name 'pattern' */
+#define NAME_OFFSET		3	    /**< Field name 'offset' */
+#define NAME_NUMBYTE		4	/**< Field name 'numbyte' */
+#define NAME_REPEAT		5	    /**< Field name 'repeat' */
+#define NAME_BYTE		6	    /**< Field name 'byte' */
+#define NAME_MASK		7	    /**< Field name 'mask' */
+#define NAME_DEST		8	    /**< Field name 'dest' */
+
+static struct mef_fields {
+	t_s8 *name;
+	      /**< Name */
+	t_s8 nameid;
+		/**< Name Id. */
+} mef_fields[] = {
+	{
+	"type", NAME_TYPE}, {
+	"pattern", NAME_PATTERN}, {
+	"offset", NAME_OFFSET}, {
+	"numbyte", NAME_NUMBYTE}, {
+	"repeat", NAME_REPEAT}, {
+	"byte", NAME_BYTE}, {
+	"mask", NAME_MASK}, {
+	"dest", NAME_DEST}
+};
+
+/**
+ *  @brief get filter data
+ *
+ *  @param fp			A pointer to file stream
+ *  @param ln			A pointer to line number
+ *  @param buf			A pointer to hostcmd data
+ *  @param size			A pointer to the return size of hostcmd buffer
+ *  @return			MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+mlan_get_filter_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
+{
+	t_s32 errors = 0, i;
+	t_s8 line[256], *pos, *pos1;
+	t_u16 type = 0;
+	t_u32 pattern = 0;
+	t_u16 repeat = 0;
+	t_u16 offset = 0;
+	t_s8 byte_seq[50];
+	t_s8 mask_seq[50];
+	t_u16 numbyte = 0;
+	t_s8 type_find = 0;
+	t_s8 pattern_find = 0;
+	t_s8 offset_find = 0;
+	t_s8 numbyte_find = 0;
+	t_s8 repeat_find = 0;
+	t_s8 byte_find = 0;
+	t_s8 mask_find = 0;
+	t_s8 dest_find = 0;
+	t_s8 dest_seq[50];
+
+	*size = 0;
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
+		if (strcmp(pos, "}") == 0) {
+			break;
+		}
+		pos1 = strchr(pos, '=');
+		if (pos1 == NULL) {
+			printf("Line %d: Invalid mef_filter line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos1++ = '\0';
+		for (i = 0; (t_u32)i < NELEMENTS(mef_fields); i++) {
+			if (strncmp
+			    (pos, mef_fields[i].name,
+			     strlen(mef_fields[i].name)) == 0) {
+				switch (mef_fields[i].nameid) {
+				case NAME_TYPE:
+					type = a2hex_or_atoi(pos1);
+					if ((type != FILTER_DNUM) &&
+					    (type != FILTER_BYTESEQ)
+					    && (type != FILTER_BITSEQ) &&
+					    (type != FILTER_TEST)) {
+						printf("Invalid filter type:%d\n", type);
+						return MLAN_STATUS_FAILURE;
+					}
+					type_find = 1;
+					break;
+				case NAME_PATTERN:
+					pattern = a2hex_or_atoi(pos1);
+					pattern_find = 1;
+					break;
+				case NAME_OFFSET:
+					offset = a2hex_or_atoi(pos1);
+					offset_find = 1;
+					break;
+				case NAME_NUMBYTE:
+					numbyte = a2hex_or_atoi(pos1);
+					numbyte_find = 1;
+					break;
+				case NAME_REPEAT:
+					repeat = a2hex_or_atoi(pos1);
+					repeat_find = 1;
+					break;
+				case NAME_BYTE:
+					memset(byte_seq, 0, sizeof(byte_seq));
+					strncpy(byte_seq, pos1,
+						(sizeof(byte_seq) - 1));
+					byte_find = 1;
+					break;
+				case NAME_MASK:
+					memset(mask_seq, 0, sizeof(mask_seq));
+					strncpy(mask_seq, pos1,
+						(sizeof(mask_seq) - 1));
+					mask_find = 1;
+					break;
+				case NAME_DEST:
+					memset(dest_seq, 0, sizeof(dest_seq));
+					strncpy(dest_seq, pos1,
+						(sizeof(dest_seq) - 1));
+					dest_find = 1;
+					break;
+				}
+				break;
+			}
+		}
+		if (i == NELEMENTS(mef_fields)) {
+			printf("Line %d: unknown mef field '%s'.\n",
+			       *line, pos);
+			errors++;
+		}
+	}
+	if (type_find == 0) {
+		printf("Can not find filter type\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	switch (type) {
+	case FILTER_DNUM:
+		if (!pattern_find || !offset_find || !numbyte_find) {
+			printf("Missing field for FILTER_DNUM: pattern=%d,offset=%d,numbyte=%d\n", pattern_find, offset_find, numbyte_find);
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(line, 0, sizeof(line));
+		snprintf(line, sizeof(line), "%d %d %d =d ", pattern, offset,
+			 numbyte);
+		break;
+	case FILTER_BYTESEQ:
+		if (!byte_find || !offset_find || !repeat_find) {
+			printf("Missing field for FILTER_BYTESEQ: byte=%d,offset=%d,repeat=%d\n", byte_find, offset_find, repeat_find);
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(line, 0, sizeof(line));
+		snprintf(line, sizeof(line), "%d h%s %d == ", repeat, byte_seq,
+			 offset);
+		break;
+	case FILTER_BITSEQ:
+		if (!byte_find || !offset_find || !mask_find) {
+			printf("Missing field for FILTER_BITSEQ: byte=%d,offset=%d,mask_find=%d\n", byte_find, offset_find, mask_find);
+			return MLAN_STATUS_FAILURE;
+		}
+		if (strlen(byte_seq) != strlen(mask_seq)) {
+			printf("byte string's length is different with mask's length!\n");
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(line, 0, sizeof(line));
+		snprintf(line, sizeof(line), "h%s %d h%s =b ", byte_seq, offset,
+			 mask_seq);
+		break;
+	case FILTER_TEST:
+		if (!byte_find || !offset_find || !repeat_find || !dest_find) {
+			printf("Missing field for FILTER_TEST: byte=%d,offset=%d,repeat=%d,dest=%d\n", byte_find, offset_find, repeat_find, dest_find);
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(line, 0, sizeof(line));
+		snprintf(line, sizeof(line), "h%s %d h%s %d ", dest_seq, repeat,
+			 byte_seq, offset);
+		break;
+	}
+	memcpy(buf, line, strlen(line));
+	*size = strlen(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+#define NAME_MODE	1	/**< Field name 'mode' */
+#define NAME_ACTION	2	/**< Field name 'action' */
+#define NAME_FILTER_NUM	3   /**< Field name 'filter_num' */
+#define NAME_RPN	4	/**< Field name 'RPN' */
+static struct mef_entry_fields {
+	t_s8 *name;
+	      /**< Name */
+	t_s8 nameid;
+		/**< Name id */
+} mef_entry_fields[] = {
+	{
+	"mode", NAME_MODE}, {
+	"action", NAME_ACTION}, {
+	"filter_num", NAME_FILTER_NUM}, {
+"RPN", NAME_RPN},};
+
+typedef struct _MEF_ENTRY {
+    /** Mode */
+	t_u8 Mode;
+    /** Size */
+	t_u8 Action;
+    /** Size of expression */
+	t_u16 ExprSize;
+} MEF_ENTRY;
+
+/**
+ *  @brief get mef_entry data
+ *
+ *  @param fp			A pointer to file stream
+ *  @param ln			A pointer to line number
+ *  @param buf			A pointer to hostcmd data
+ *  @param size			A pointer to the return size of hostcmd buffer
+ *  @return			MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+mlan_get_mef_entry_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
+{
+	t_s8 line[256], *pos, *pos1;
+	t_u8 mode, action, filter_num = 0;
+	t_s8 rpn[256];
+	t_s8 mode_find = 0;
+	t_s8 action_find = 0;
+	t_s8 filter_num_find = 0;
+	t_s8 rpn_find = 0;
+	t_s8 rpn_str[256];
+	int rpn_len = 0;
+	t_s8 filter_name[50];
+	t_s8 name_found = 0;
+	t_u16 len = 0;
+	int i;
+	int first_time = TRUE;
+	char *opstr;
+	t_s8 filter_action[10];
+	t_s32 errors = 0;
+	MEF_ENTRY *pMefEntry = (MEF_ENTRY *) buf;
+	mstack_t stack;
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
+		if (strcmp(pos, "}") == 0) {
+			break;
+		}
+		pos1 = strchr(pos, '=');
+		if (pos1 == NULL) {
+			printf("Line %d: Invalid mef_entry line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos1++ = '\0';
+		if (!mode_find || !action_find || !filter_num_find || !rpn_find) {
+			for (i = 0;
+			     (unsigned int)i < NELEMENTS(mef_entry_fields);
+			     i++) {
+				if (strncmp
+				    (pos, mef_entry_fields[i].name,
+				     strlen(mef_entry_fields[i].name)) == 0) {
+					switch (mef_entry_fields[i].nameid) {
+					case NAME_MODE:
+						mode = a2hex_or_atoi(pos1);
+						if (mode & ~0x7) {
+							printf("invalid mode=%d\n", mode);
+							return MLAN_STATUS_FAILURE;
+						}
+						pMefEntry->Mode = mode;
+						mode_find = 1;
+						break;
+					case NAME_ACTION:
+						action = a2hex_or_atoi(pos1);
+						if (action & ~0xff) {
+							printf("invalid action=%d\n", action);
+							return MLAN_STATUS_FAILURE;
+						}
+						pMefEntry->Action = action;
+						action_find = 1;
+						break;
+					case NAME_FILTER_NUM:
+						filter_num =
+							a2hex_or_atoi(pos1);
+						filter_num_find = 1;
+						break;
+					case NAME_RPN:
+						memset(rpn, 0, sizeof(rpn));
+						strncpy(rpn, pos1,
+							(sizeof(rpn) - 1));
+						rpn_find = 1;
+						break;
+					}
+					break;
+				}
+			}
+			if (i == NELEMENTS(mef_fields)) {
+				printf("Line %d: unknown mef_entry field '%s'.\n", *line, pos);
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+		if (mode_find && action_find && filter_num_find && rpn_find) {
+			for (i = 0; i < filter_num; i++) {
+				opstr = getop(rpn, &first_time);
+				if (opstr == NULL)
+					break;
+				snprintf(filter_name, sizeof(filter_name),
+					 "%s={", opstr);
+				name_found = 0;
+				while ((pos =
+					mlan_config_get_line(fp, line,
+							     sizeof(line),
+							     ln))) {
+					if (strncmp
+					    (pos, filter_name,
+					     strlen(filter_name)) == 0) {
+						name_found = 1;
+						break;
+					}
+				}
+				if (!name_found) {
+					fprintf(stderr,
+						"mlanconfig: %s not found in file\n",
+						filter_name);
+					return MLAN_STATUS_FAILURE;
+				}
+				if (MLAN_STATUS_FAILURE ==
+				    mlan_get_filter_data(fp, ln,
+							 (t_u8 *)(rpn_str +
+								  rpn_len),
+							 &len))
+					break;
+				rpn_len += len;
+				if (i > 0) {
+					memcpy(rpn_str + rpn_len, filter_action,
+					       strlen(filter_action));
+					rpn_len += strlen(filter_action);
+				}
+				opstr = getop(rpn, &first_time);
+				if (opstr == NULL)
+					break;
+				memset(filter_action, 0, sizeof(filter_action));
+				snprintf(filter_action, sizeof(filter_action),
+					 "%s ", opstr);
+			}
+			/* Remove the last space */
+			if (rpn_len > 0) {
+				rpn_len--;
+				rpn_str[rpn_len] = 0;
+			}
+			if (MLAN_STATUS_FAILURE == str2bin(rpn_str, &stack)) {
+				printf("Fail on str2bin!\n");
+				return MLAN_STATUS_FAILURE;
+			}
+			*size = sizeof(MEF_ENTRY);
+			pMefEntry->ExprSize = cpu_to_le16(stack.sp);
+			memmove(buf + sizeof(MEF_ENTRY), stack.byte, stack.sp);
+			*size += stack.sp;
+			break;
+		} else if (mode_find && action_find && filter_num_find &&
+			   (filter_num == 0)) {
+			pMefEntry->ExprSize = 0;
+			*size = sizeof(MEF_ENTRY);
+			break;
+		}
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+#define MEFCFG_CMDCODE	0x009a
+/**
+ *  @brief Process mef cfg
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_mef_cfg(int argc, char *argv[])
+{
+	int ioctl_val, subioctl_val;
+	t_s8 line[256], cmdname[256], *pos;
+	int cmdname_found = 0, name_found = 0;
+	int ln = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+	int i;
+	t_u8 *buf;
+	t_u16 buf_len = 0;
+	t_u16 len;
+	struct iwreq iwr;
+	HostCmd_DS_MEF_CFG *mefcmd;
+	HostCmd_DS_GEN *hostcmd;
+	FILE *fp = NULL;
+
+	if (argc < 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanconfig eth1 mefcfg <mef.conf>\n");
+		exit(1);
+	}
+	if (get_priv_ioctl("hostcmd",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+	snprintf(cmdname, sizeof(cmdname), "%s={", argv[2]);
+	cmdname_found = 0;
+	if ((fp = fopen(argv[3], "r")) == NULL) {
+		fprintf(stderr, "Cannot open file %s\n", argv[4]);
+		exit(1);
+	}
+
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (buf == NULL) {
+		fclose(fp);
+		fprintf(stderr, "Cannot alloc memory\n");
+		exit(1);
+	}
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	hostcmd = (HostCmd_DS_GEN *)(buf);
+	hostcmd->command = cpu_to_le16(MEFCFG_CMDCODE);
+	mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN);
+	buf_len = sizeof(HostCmd_DS_MEF_CFG) + S_DS_GEN;
+
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, cmdname) == 0) {
+			cmdname_found = 1;
+			snprintf(cmdname, sizeof(cmdname), "Criteria=");
+			name_found = 0;
+			while ((pos =
+				mlan_config_get_line(fp, line, sizeof(line),
+						     &ln))) {
+				if (strncmp(pos, cmdname, strlen(cmdname)) == 0) {
+					name_found = 1;
+					mefcmd->Criteria =
+						a2hex_or_atoi(pos +
+							      strlen(cmdname));
+					break;
+				}
+			}
+			if (!name_found) {
+				fprintf(stderr,
+					"mlanconfig: criteria not found in file '%s'\n",
+					argv[3]);
+				break;
+			}
+			snprintf(cmdname, sizeof(cmdname), "NumEntries=");
+			name_found = 0;
+			while ((pos =
+				mlan_config_get_line(fp, line, sizeof(line),
+						     &ln))) {
+				if (strncmp(pos, cmdname, strlen(cmdname)) == 0) {
+					name_found = 1;
+					mefcmd->NumEntries =
+						a2hex_or_atoi(pos +
+							      strlen(cmdname));
+					break;
+				}
+			}
+			if (!name_found) {
+				fprintf(stderr,
+					"mlanconfig: NumEntries not found in file '%s'\n",
+					argv[3]);
+				break;
+			}
+			for (i = 0; i < mefcmd->NumEntries; i++) {
+				snprintf(cmdname, sizeof(cmdname),
+					 "mef_entry_%d={", i);
+				name_found = 0;
+				while ((pos =
+					mlan_config_get_line(fp, line,
+							     sizeof(line),
+							     &ln))) {
+					if (strncmp
+					    (pos, cmdname,
+					     strlen(cmdname)) == 0) {
+						name_found = 1;
+						break;
+					}
+				}
+				if (!name_found) {
+					fprintf(stderr,
+						"mlanconfig: %s not found in file '%s'\n",
+						cmdname, argv[3]);
+					break;
+				}
+				if (MLAN_STATUS_FAILURE ==
+				    mlan_get_mef_entry_data(fp, &ln,
+							    buf + buf_len,
+							    &len)) {
+					ret = MLAN_STATUS_FAILURE;
+					break;
+				}
+				buf_len += len;
+			}
+			break;
+		}
+	}
+	fclose(fp);
+	/* hexdump("mef_cfg",buf,buf_len, ' '); */
+	if (!cmdname_found)
+		fprintf(stderr,
+			"mlanconfig: cmdname '%s' not found in file '%s'\n",
+			argv[4], argv[3]);
+
+	if (!cmdname_found || !name_found) {
+		ret = MLAN_STATUS_FAILURE;
+		goto mef_exit;
+	}
+	hostcmd->size = cpu_to_le16(buf_len);
+	mefcmd->Criteria = cpu_to_le32(mefcmd->Criteria);
+	mefcmd->NumEntries = cpu_to_le16(mefcmd->NumEntries);
+
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = buf;
+	iwr.u.data.length = buf_len;
+	iwr.u.data.flags = 0;
+	if (ioctl(sockfd, ioctl_val, &iwr)) {
+		fprintf(stderr, "mlanconfig: MEFCFG is not supported by %s\n",
+			dev_name);
+		ret = MLAN_STATUS_FAILURE;
+		goto mef_exit;
+	}
+	ret = process_host_cmd_resp(buf);
+
+mef_exit:
+	if (buf)
+		free(buf);
+	return ret;
+
+}
+
+/**
+ *  @brief Process transmission of mgmt frames
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_mgmt_frame_tx(int argc, char *argv[])
+{
+	struct ifreq ifr;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, arg_num = 0, ret = 0, i = 0;
+	char *args[100], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 data_len = 0, subtype = 0;
+	wlan_mgmt_frame_tx *pmgmt_frame;
+	t_u8 *buffer = NULL;
+	pkt_header *hdr = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX mgmtframetx <config/pkt.conf>\n");
+		exit(1);
+	}
+
+	data_len = sizeof(wlan_mgmt_frame_tx);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	hdr = (pkt_header *)buffer;
+	pmgmt_frame = (wlan_mgmt_frame_tx *)(buffer + sizeof(pkt_header));
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		arg_num = parse_line(line, args);
+		if (strcmp(args[0], "PktSubType") == 0) {
+			subtype = (t_u16)A2HEXDECIMAL(args[1]);
+			pmgmt_frame->frm_ctl |= subtype << 4;
+		} else if (strncmp(args[0], "Addr", 4) == 0) {
+			strncpy(mac_addr, args[1], 20);
+			if ((ret =
+			     mac2raw(mac_addr,
+				     peer_mac)) != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			i = atoi(args[0] + 4);
+			switch (i) {
+			case 1:
+				memcpy(pmgmt_frame->addr1, peer_mac, ETH_ALEN);
+				break;
+			case 2:
+				memcpy(pmgmt_frame->addr2, peer_mac, ETH_ALEN);
+				break;
+			case 3:
+				memcpy(pmgmt_frame->addr3, peer_mac, ETH_ALEN);
+				break;
+			case 4:
+				memcpy(pmgmt_frame->addr4, peer_mac, ETH_ALEN);
+				break;
+			}
+		} else if (strcmp(args[0], "Data") == 0) {
+			for (i = 0; i < arg_num - 1; i++)
+				pmgmt_frame->payload[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			data_len += arg_num - 1;
+		}
+	}
+	pmgmt_frame->frm_len = data_len - sizeof(pmgmt_frame->frm_len);
+#define MRVL_PKT_TYPE_MGMT_FRAME 0xE5
+	hdr->pkt_len = data_len;
+	hdr->TxPktType = MRVL_PKT_TYPE_MGMT_FRAME;
+	hdr->TxControl = 0;
+	hexdump("Frame Tx", buffer, data_len + sizeof(pkt_header), ' ');
+	/* Send collective command */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)buffer;
+
+	/* Perform ioctl */
+	if (ioctl(sockfd, FRAME_TX_IOCTL, &ifr)) {
+		perror("");
+		printf("ERR:Could not send management frame.\n");
+	} else {
+		printf("Mgmt Frame sucessfully sent.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Performs the ioctl operation to send the command to
+ *  the driver.
+ *
+ *  @param cmd_buf       Pointer to the command buffer
+ *  @param buf_size      Size of the allocated command buffer
+ *  @return              MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static int
+tdls_ioctl(t_u8 *cmd_buf, t_u16 buf_size)
+{
+	struct ifreq ifr;
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd_buf;
+
+	/* Perform ioctl */
+	if (ioctl(sockfd, TDLS_IOCTL, &ifr)) {
+		perror("");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief enable/disable tdls config
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_config(int argc, char *argv[])
+{
+
+	tdls_config *param_buf = NULL;
+	int ret = 0;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_config <0/1>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_config);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_config *) buffer;
+	param_buf->action = ACTION_TDLS_CONFIG;
+
+	param_buf->data = (t_u16)A2HEXDECIMAL(argv[3]);
+	if ((param_buf->data != 0) && (param_buf->data != 1)) {
+		printf("ERR:Incorrect arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_config <0/1>\n");
+		goto done;
+	}
+	hexdump("tdls_config ", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS %s successful.\n",
+		       (param_buf->data) ? "enable" : "disable");
+	} else {
+		printf("ERR:TDLS %s failed.\n",
+		       (param_buf->data) ? "enable" : "disable");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_setinfo
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_setinfo(int argc, char *argv[])
+{
+	tdls_setinfo *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, arg_num = 0, ret = 0, i = 0, cmd_found = 0, pairwise_index =
+		0, akm_index = 0, pmkid_index = 0;
+	char *args[30], *pos = NULL;
+	t_u16 cmd_len = 0, tlv_len = 0, tlv_len_rsn = 0, tlv_len_supp_chan =
+		0, tlv_len_domain = 0;
+	t_u16 no_of_sub_band = 0, no_of_supp_chan_sub_band =
+		0, pairwise_offset = 0, akm_offset =
+		0, num_of_regulatory_class = 0, tlv_len_reg_class;
+	t_u16 akm_count = 0, pmk_count = 0, rsn_cap = 0;
+	t_u8 *buffer = NULL;
+	char country[COUNTRY_CODE_LEN];
+	tlvbuf_DomainParamSet_t *domain = NULL;
+	tlvbuf_SupportedChannels_t *supp_chan = NULL;
+	tlvbuf_RegulatoryClass_t *reg_class = NULL;
+	tlvbuf_HTCap_t *tlv_ht_cap = NULL;
+	tlvbuf_RsnParamSet_t *rsn_ie = NULL;
+	tlvbuf_HTInfo_t *tlv_ht_info = NULL;
+	t_u8 pairwise_cipher_suite[PAIRWISE_CIPHER_SUITE_LEN];
+	t_u8 akm_suite[AKM_SUITE_LEN];
+	t_u8 pmkid[PMKID_LEN];
+	tlvbuf_VHTCap_t *tlv_vht_cap = NULL;
+	tlvbuf_VHTOpra_t *tlv_vht_oper = NULL;
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_setinfo <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_setinfo);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	param_buf = (tdls_setinfo *)buffer;
+	param_buf->action = ACTION_TDLS_SETINFO;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		arg_num = parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+		if (strcmp(args[0], "CapInfo") == 0) {
+			param_buf->cap_info = (t_u16)A2HEXDECIMAL(args[1]);
+			param_buf->cap_info = cpu_to_le16(param_buf->cap_info);
+		} else if (strcmp(args[0], "Rate") == 0) {
+			tlvbuf_RatesParamSet_t *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_RatesParamSet_t) + arg_num - 1;
+			tlv = (tlvbuf_RatesParamSet_t *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = TLV_TYPE_RATES;
+			tlv->length = arg_num - 1;
+			for (i = 0; i < tlv->length; i++) {
+				tlv->rates[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			endian_convert_tlv_header_out(tlv);
+		} else if (strcmp(args[0], "QosInfo") == 0) {
+			tlvbuf_QosInfo_t *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_QosInfo_t);
+			tlv = (tlvbuf_QosInfo_t *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = TLV_TYPE_QOSINFO;
+			tlv->length = sizeof(tlvbuf_QosInfo_t) - TLVHEADER_LEN;
+			tlv->u.qos_info_byte = (t_u8)A2HEXDECIMAL(args[1]);
+			if ((tlv->u.qos_info_byte != 0) &&
+			    (tlv->u.qos_info_byte != 0x0F)) {
+				printf("Invalid QosInfo. Should be 0x00 or 0x0F.\n");
+				goto done;
+			}
+			endian_convert_tlv_header_out(tlv);
+		} else if (strcmp(args[0], "ExtendCapabilities") == 0) {
+			tlvbuf_ExtCap_t *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_ExtCap_t) + arg_num - 1;
+			tlv = (tlvbuf_ExtCap_t *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = TLV_TYPE_EXTCAP;
+			tlv->length = arg_num - 1;
+			for (i = 0; i < tlv->length; i++) {
+				tlv->ext_cap[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			endian_convert_tlv_header_out(tlv);
+		} else if (strcmp(args[0], "HTCapability") == 0) {
+			/* Append a new TLV */
+			tlv_ht_cap = (tlvbuf_HTCap_t *)(buffer + cmd_len);
+			tlv_len = sizeof(tlvbuf_HTCap_t);
+			tlv_ht_cap->tag = TLV_TYPE_HT_CAP;
+			tlv_ht_cap->length =
+				sizeof(tlvbuf_HTCap_t) - TLVHEADER_LEN;
+			cmd_len += tlv_len;
+			endian_convert_tlv_header_out(tlv_ht_cap);
+		} else if (strcmp(args[0], "HTCapabilityInfo") == 0) {
+			tlv_ht_cap->ht_cap.ht_cap_info =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_ht_cap->ht_cap.ht_cap_info =
+				cpu_to_le16(tlv_ht_cap->ht_cap.ht_cap_info);
+		} else if (strcmp(args[0], "AMPDUParam") == 0) {
+			tlv_ht_cap->ht_cap.ampdu_param =
+				(t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "SupportedMCSSet") == 0) {
+			for (i = 0; i < MCS_SET_LEN; i++)
+				tlv_ht_cap->ht_cap.supported_mcs_set[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "HTExtCapability") == 0) {
+			tlv_ht_cap->ht_cap.ht_ext_cap =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_ht_cap->ht_cap.ht_ext_cap =
+				cpu_to_le16(tlv_ht_cap->ht_cap.ht_ext_cap);
+		} else if (strcmp(args[0], "TxBfCapability") == 0) {
+			tlv_ht_cap->ht_cap.tx_bf_cap =
+				(t_u32)A2HEXDECIMAL(args[1]);
+			tlv_ht_cap->ht_cap.tx_bf_cap =
+				cpu_to_le32(tlv_ht_cap->ht_cap.tx_bf_cap);
+		} else if (strcmp(args[0], "AntennaSel") == 0) {
+			tlv_ht_cap->ht_cap.asel = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "HTInformation") == 0) {
+			/* Append a new TLV */
+			tlv_ht_info = (tlvbuf_HTInfo_t *)(buffer + cmd_len);
+			tlv_len = sizeof(tlvbuf_HTInfo_t);
+			tlv_ht_info->tag = TLV_TYPE_HT_INFO;
+			tlv_ht_info->length =
+				sizeof(tlvbuf_HTInfo_t) - TLVHEADER_LEN;
+			cmd_len += tlv_len;
+			endian_convert_tlv_header_out(tlv_ht_info);
+		} else if (strcmp(args[0], "PrimaryChannel") == 0) {
+			tlv_ht_info->ht_info.pri_chan = A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "Field2") == 0) {
+			tlv_ht_info->ht_info.field2 = A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "Field3") == 0) {
+			tlv_ht_info->ht_info.field3 =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_ht_info->ht_info.field3 =
+				cpu_to_le16(tlv_ht_info->ht_info.field3);
+		} else if (strcmp(args[0], "Field4") == 0) {
+			tlv_ht_info->ht_info.field4 =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_ht_info->ht_info.field4 =
+				cpu_to_le16(tlv_ht_info->ht_info.field4);
+		} else if (strcmp(args[0], "BasicMCSSet") == 0) {
+			if ((arg_num - 1) != MCS_SET_LEN) {
+				printf("Incorrect number of arguments for BasicMCSSet.\n");
+				goto done;
+			}
+			for (i = 0; i < MCS_SET_LEN; i++)
+				tlv_ht_info->ht_info.basic_mcs_set[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "2040BSSCoex") == 0) {
+			tlvbuf_2040BSSCo_t *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_2040BSSCo_t);
+			tlv = (tlvbuf_2040BSSCo_t *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = TLV_TYPE_2040BSS_COEXISTENCE;
+			tlv->length =
+				sizeof(tlvbuf_2040BSSCo_t) - TLVHEADER_LEN;
+			tlv->bss_co_2040.bss_co_2040_value =
+				(t_u8)A2HEXDECIMAL(args[1]);
+			endian_convert_tlv_header_out(tlv);
+		} else if (strcmp(args[0], "RSNInfo") == 0) {
+			/* Append a new TLV */
+			rsn_ie = (tlvbuf_RsnParamSet_t *)(buffer + cmd_len);
+			tlv_len_rsn = sizeof(tlvbuf_RsnParamSet_t);
+			rsn_ie->tag = TLV_TYPE_RSN_IE;
+			rsn_ie->version = VERSION_RSN_IE;
+			rsn_ie->version = cpu_to_le16(rsn_ie->version);
+			cmd_len += tlv_len_rsn;
+		} else if (strcmp(args[0], "GroupCipherSuite") == 0) {
+			for (i = 0; i < GROUP_CIPHER_SUITE_LEN; i++)
+				rsn_ie->group_cipher_suite[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "PairwiseCipherCount") == 0) {
+			rsn_ie->pairwise_cipher_count = (t_u16)atoi(args[1]);
+			rsn_ie->pairwise_cipher_count =
+				cpu_to_le16(rsn_ie->pairwise_cipher_count);
+		} else if (strncmp(args[0], "PairwiseCipherSuite", 19) == 0) {
+			if (pairwise_index > MAX_PAIRWISE_CIPHER_SUITE_COUNT) {
+				printf("PairwiseCipherSuite exceeds max count\n");
+				goto done;
+			}
+			tlv_len_rsn += PAIRWISE_CIPHER_SUITE_LEN;
+			cmd_len += PAIRWISE_CIPHER_SUITE_LEN;
+			for (i = 0; i < PAIRWISE_CIPHER_SUITE_LEN; i++) {
+				pairwise_cipher_suite[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			memcpy((t_u8 *)(rsn_ie->pairwise_cipher_suite +
+					(pairwise_index *
+					 PAIRWISE_CIPHER_SUITE_LEN)),
+			       pairwise_cipher_suite,
+			       PAIRWISE_CIPHER_SUITE_LEN);
+			pairwise_index++;
+			pairwise_offset =
+				pairwise_index * PAIRWISE_CIPHER_SUITE_LEN;
+		} else if (strcmp(args[0], "AKMSuiteCount") == 0) {
+			akm_count = (t_u16)atoi(args[1]);
+			akm_count = cpu_to_le16(akm_count);
+			memcpy((((t_u8 *)(&rsn_ie->akm_suite_count)) +
+				pairwise_offset), &akm_count, sizeof(t_u16));
+		} else if (strncmp(args[0], "AKMSuite", 8) == 0) {
+			if (akm_index > MAX_AKM_SUITE_COUNT) {
+				printf("AKMSuite exceeds max count\n");
+				goto done;
+			}
+			tlv_len_rsn += AKM_SUITE_LEN;
+			cmd_len += AKM_SUITE_LEN;
+			for (i = 0; i < AKM_SUITE_LEN; i++) {
+				akm_suite[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			memcpy((t_u8 *)(rsn_ie->akm_suite +
+					(akm_index * AKM_SUITE_LEN)
+					+ pairwise_offset), akm_suite,
+			       AKM_SUITE_LEN);
+			akm_index++;
+			akm_offset = akm_index * AKM_SUITE_LEN;
+		} else if (strcmp(args[0], "RSNCapability") == 0) {
+			rsn_cap = (t_u16)A2HEXDECIMAL(args[1]);
+			rsn_cap = cpu_to_le16(rsn_cap);
+			memcpy(((t_u8 *)(&(rsn_ie->rsn_capability))) +
+			       pairwise_offset + akm_offset, &rsn_cap,
+			       sizeof(t_u16));
+		} else if (strcmp(args[0], "PMKIDCount") == 0) {
+			pmk_count = (t_u16)atoi(args[1]);
+			pmk_count = cpu_to_le16(pmk_count);
+			memcpy((((t_u8 *)(&rsn_ie->pmkid_count)) +
+				pairwise_offset + akm_offset), &pmk_count,
+			       sizeof(t_u16));
+			rsn_ie->length = tlv_len_rsn - TLVHEADER_LEN;
+			endian_convert_tlv_header_out(rsn_ie);
+		} else if (strncmp(args[0], "PMKIDList", 9) == 0) {
+			if (pmkid_index > MAX_PMKID_COUNT) {
+				printf("PMKIDSuite exceeds max count\n");
+				goto done;
+			}
+			for (i = 0; i < PMKID_LEN; i++)
+				pmkid[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
+			memcpy((t_u8 *)(rsn_ie->pmkid_list +
+					(pmkid_index * PMKID_LEN) +
+					pairwise_offset + akm_offset), pmkid,
+			       PMKID_LEN);
+			pmkid_index++;
+			tlv_len_rsn += PMKID_LEN;
+			cmd_len += PMKID_LEN;
+			/* undo conversion done in PMKIDCount */
+			endian_convert_tlv_header_in(rsn_ie);
+			rsn_ie->length = tlv_len_rsn - TLVHEADER_LEN;
+			endian_convert_tlv_header_out(rsn_ie);
+		} else if (strcmp(args[0], "SupportedChannels") == 0) {
+			/* Append a new TLV */
+			supp_chan =
+				(tlvbuf_SupportedChannels_t *)(buffer +
+							       cmd_len);
+			supp_chan->tag = TLV_TYPE_SUPPORTED_CHANNELS;
+			supp_chan->length = sizeof(tlvbuf_SupportedChannels_t)
+				- TLVHEADER_LEN;
+			tlv_len_supp_chan = sizeof(tlvbuf_SupportedChannels_t);
+			cmd_len += tlv_len_supp_chan;
+		} else if (strncmp(args[0], "FirstChannelNo", 14) == 0) {
+			supp_chan->subband[no_of_supp_chan_sub_band].
+				start_chan = atoi(args[1]);
+		} else if (strcmp(args[0], "NumberofSubBandChannels") == 0) {
+			supp_chan->subband[no_of_supp_chan_sub_band].num_chans =
+				atoi(args[1]);
+			no_of_supp_chan_sub_band++;
+			tlv_len_supp_chan +=
+				sizeof(IEEEtypes_SupportChan_Subband_t);
+			supp_chan->length +=
+				sizeof(IEEEtypes_SupportChan_Subband_t);
+			cmd_len += sizeof(IEEEtypes_SupportChan_Subband_t);
+			endian_convert_tlv_header_out(supp_chan);
+		} else if (strcmp(args[0], "SupportedRegulatoryClasses") == 0) {
+			/* Append a new TLV */
+			reg_class =
+				(tlvbuf_RegulatoryClass_t *)(buffer + cmd_len);
+			tlv_len_reg_class = sizeof(tlvbuf_RegulatoryClass_t);
+			reg_class->tag = TLV_TYPE_REGULATORY_CLASSES;
+			cmd_len += tlv_len_reg_class;
+		} else if (strcmp(args[0], "CurrentRegulatoryClass") == 0) {
+			reg_class->regulatory_class.cur_regulatory_class =
+				atoi(args[1]);
+			reg_class->length = 1;
+		} else if (strcmp(args[0], "NumofRegulatoryClasses") == 0) {
+			num_of_regulatory_class = atoi(args[1]);
+			reg_class->length += num_of_regulatory_class;
+			cmd_len += num_of_regulatory_class;
+			endian_convert_tlv_header_out(reg_class);
+		} else if (strcmp(args[0], "ListOfRegulatoryClasses") == 0) {
+			for (i = 0; i < num_of_regulatory_class; i++)
+				reg_class->regulatory_class.
+					regulatory_classes_list[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "CountryInfo") == 0) {
+			/* Append a new TLV */
+			domain = (tlvbuf_DomainParamSet_t *)(buffer + cmd_len);
+			domain->tag = TLV_TYPE_DOMAIN;
+			domain->length = sizeof(tlvbuf_DomainParamSet_t)
+				- TLVHEADER_LEN;
+			tlv_len_domain = sizeof(tlvbuf_DomainParamSet_t);
+			cmd_len += tlv_len_domain;
+		} else if (strcmp(args[0], "CountryString") == 0) {
+			strncpy(country, args[1] + 1, strlen(args[1]) - 2);
+			country[strlen(args[1]) - 2] = '\0';
+			for (i = 1; (unsigned int)i < strlen(country) - 2; i++) {
+				if ((country[i] < 'A') || (country[i] > 'z')) {
+					printf("Invalid Country Code\n");
+					goto done;
+				}
+				if (country[i] > 'Z')
+					country[i] = country[i] - 'a' + 'A';
+			}
+			memset(domain->country_code, ' ',
+			       sizeof(domain->country_code));
+			memcpy(domain->country_code, country, strlen(country));
+		} else if (strncmp(args[0], "FirstChannel", 12) == 0) {
+			domain->sub_band[no_of_sub_band].first_chan =
+				atoi(args[1]);
+		} else if (strncmp(args[0], "NumberofChannels", 16) == 0) {
+			domain->sub_band[no_of_sub_band].no_of_chan =
+				atoi(args[1]);
+		} else if (strncmp(args[0], "TxPower", 7) == 0) {
+			domain->sub_band[no_of_sub_band].max_tx_pwr =
+				atoi(args[1]);
+			no_of_sub_band++;
+			domain->length += sizeof(IEEEtypes_SubbandSet_t);
+			tlv_len_domain += sizeof(IEEEtypes_SubbandSet_t);
+			cmd_len += sizeof(IEEEtypes_SubbandSet_t);
+			endian_convert_tlv_header_out(domain);
+		} else if (strcmp(args[0], "VHTCapability") == 0) {
+			/* Append a new TLV */
+			tlv_vht_cap = (tlvbuf_VHTCap_t *)(buffer + cmd_len);
+			tlv_len = sizeof(tlvbuf_VHTCap_t);
+			tlv_vht_cap->tag = TLV_TYPE_VHT_CAP;
+			tlv_vht_cap->length =
+				sizeof(tlvbuf_VHTCap_t) - TLVHEADER_LEN;
+			cmd_len += tlv_len;
+			endian_convert_tlv_header_out(tlv_vht_cap);
+		} else if (strcmp(args[0], "VHTCapabilityInfo") == 0) {
+			tlv_vht_cap->vht_cap.vht_cap_info =
+				(t_u32)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.vht_cap_info =
+				cpu_to_le16(tlv_vht_cap->vht_cap.vht_cap_info);
+		} else if (strcmp(args[0], "RxMCSMap") == 0) {
+			tlv_vht_cap->vht_cap.mcs_sets.rx_mcs_map =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.mcs_sets.rx_mcs_map =
+				cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets.
+					    rx_mcs_map);
+		} else if (strcmp(args[0], "TxMCSMap") == 0) {
+			tlv_vht_cap->vht_cap.mcs_sets.tx_mcs_map =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.mcs_sets.tx_mcs_map =
+				cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets.
+					    tx_mcs_map);
+		} else if (strcmp(args[0], "RxMaxRate") == 0) {
+			tlv_vht_cap->vht_cap.mcs_sets.rx_max_rate =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.mcs_sets.rx_max_rate =
+				cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets.
+					    rx_max_rate);
+		} else if (strcmp(args[0], "TxMaxRate") == 0) {
+			tlv_vht_cap->vht_cap.mcs_sets.tx_max_rate =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.mcs_sets.tx_max_rate =
+				cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets.
+					    tx_max_rate);
+		} else if (strcmp(args[0], "VHTOper") == 0) {
+			/* Append a new TLV */
+			tlv_vht_oper = (tlvbuf_VHTOpra_t *)(buffer + cmd_len);
+			tlv_len = sizeof(tlvbuf_VHTOpra_t);
+			tlv_vht_oper->tag = TLV_TYPE_VHT_OPER;
+			tlv_vht_oper->length =
+				sizeof(tlvbuf_VHTOpra_t) - TLVHEADER_LEN;
+			cmd_len += tlv_len;
+			endian_convert_tlv_header_out(tlv_vht_oper);
+		} else if (strcmp(args[0], "ChanWidth") == 0) {
+			tlv_vht_oper->chan_width = A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "ChanCF1") == 0) {
+			tlv_vht_oper->chan_cf1 = A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "ChanCF2") == 0) {
+			tlv_vht_oper->chan_cf2 = (t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "BasicMCSMap") == 0) {
+			if ((arg_num - 1) != VHT_MCS_MAP_LEN) {
+				printf("Incorrect number of arguments for BasicMCSMap.\n");
+				goto done;
+			}
+			for (i = 0; i < VHT_MCS_MAP_LEN; i++)
+				tlv_vht_oper->basic_mcs_map[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		}
+	}
+	/* adjust for size of action and tlv_len, capInfo */
+	param_buf->tlv_len = cmd_len - sizeof(tdls_setinfo);
+
+	hexdump("tdls_setinfo", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS Info settings sucessfully set.\n");
+	} else {
+		printf("ERR:Could not set TDLS info configuration.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_discovery
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_discovery(int argc, char *argv[])
+{
+	tdls_discovery *param_buf = NULL;
+	tdls_discovery_resp *resp_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0, rssi = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0, buf_len = 0, resp_len = 0;
+	t_u8 *buffer = NULL, *raw = NULL;
+	IEEEtypes_Header_t *tlv = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_discovery <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_discovery);
+	buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, buf_len);
+	param_buf = (tdls_discovery *)buffer;
+	param_buf->action = ACTION_TDLS_DISCOVERY;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			if ((ret =
+			     mac2raw(mac_addr,
+				     peer_mac)) != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_discovery", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		hexdump("tdls_response", buffer, 0x40, ' ');
+		printf("TDLS discovery done.\n");
+		resp_buf = (tdls_discovery_resp *)buffer;
+		resp_len = resp_buf->payload_len;
+		printf("Response Length = %d\n", resp_len);
+		if (resp_len > 0) {
+			/* MAC */
+			raw = resp_buf->peer_mac;
+			printf("\tPeer - %02x:%02x:%02x:%02x:%02x:%02x\n",
+			       (unsigned int)raw[0], (unsigned int)raw[1],
+			       (unsigned int)raw[2], (unsigned int)raw[3],
+			       (unsigned int)raw[4], (unsigned int)raw[5]);
+
+			/* RSSI, CapInfo */
+			rssi = (int)(resp_buf->rssi);
+			if (rssi > 0x7f)
+				rssi = -(256 - rssi);
+			printf("\tRssi : %d dBm\n", rssi);
+			printf("\tCapInfo = 0x%02X\n", resp_buf->cap_info);
+
+			resp_len -= ETH_ALEN + sizeof(resp_buf->rssi) +
+				sizeof(resp_buf->cap_info);
+
+			/* TLVs */
+			tlv = (IEEEtypes_Header_t *)&resp_buf->tlv_buffer;
+			while (resp_len > IEEE_HEADER_LEN) {
+				switch (tlv->element_id) {
+				case TLV_TYPE_RATES:
+					printf("\tRates : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_EXTENDED_SUPPORTED_RATES:
+					printf("\tExtended Rates : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_TYPE_QOSINFO:
+					printf("\tQosInfo ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_EXTCAP:
+					printf("\tExtended Cap ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_HT_CAP:
+					printf("\tHT Cap ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_HT_INFO:
+					printf("\tHT Info");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_2040BSS_COEXISTENCE:
+					printf("\t2040 BSS Coex ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_RSN_IE:
+					printf("\tRSN IE ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_SUPPORTED_CHANNELS:
+					printf("\tSupported Channels ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_DOMAIN:
+					printf("\tDomain Info ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_LINK_IDENTIFIER:
+					printf("\tLink identifier : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_TIMEOUT_INTERVAL:
+					printf("\tTimeout interval : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_TYPE_REGULATORY_CLASSES:
+					printf("\t Regulatory classes : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				default:
+					printf("Unknown TLV\n");
+					hexdump(NULL, ((t_u8 *)tlv),
+						IEEE_HEADER_LEN + tlv->len,
+						' ');
+					break;
+				}
+				resp_len -= tlv->len + IEEE_HEADER_LEN;
+				tlv = (IEEEtypes_Header_t *)((t_u8 *)tlv +
+							     tlv->len +
+							     IEEE_HEADER_LEN);
+			}
+		}
+
+	} else {
+		printf("ERR:Command response = Fail!\n");
+	}
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_setup
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_setup(int argc, char *argv[])
+{
+	tdls_setup *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_setup <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_setup);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_setup *) buffer;
+	param_buf->action = ACTION_TDLS_SETUP;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			if ((ret =
+			     mac2raw(mac_addr,
+				     peer_mac)) != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "WaitTimems") == 0) {
+			param_buf->wait_time = (t_u32)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "KeyLifetime") == 0) {
+			param_buf->key_life_time = (t_u32)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_setup", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS setup request successful.\n");
+	} else {
+		printf("ERR:TDLS setup request failed.\n");
+	}
+
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_teardown
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_teardown(int argc, char *argv[])
+{
+	tdls_teardown *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_teardown <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_teardown);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_teardown *)buffer;
+	param_buf->action = ACTION_TDLS_TEARDOWN;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			if ((ret =
+			     mac2raw(mac_addr,
+				     peer_mac)) != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "ReasonCode") == 0) {
+			param_buf->reason_code = (t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_teardown", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS teardown request successful.\n");
+	} else {
+		printf("ERR:TDLS teardown request failed.\n");
+	}
+
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_powermode
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_powermode(int argc, char *argv[])
+{
+	tdls_powermode *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_powermode <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_powermode);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_powermode *)buffer;
+	param_buf->action = ACTION_TDLS_POWER_MODE;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			if ((ret =
+			     mac2raw(mac_addr,
+				     peer_mac)) != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "PowerMode") == 0) {
+			param_buf->power_mode = (t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->power_mode > 1) {
+				printf("ERR: Incorrect PowerMode value %s\n",
+				       args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_powermode", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS powermode request successful.\n");
+	} else {
+		printf("ERR:TDLS powermode request failed.\n");
+	}
+
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_link_status
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_link_status(int argc, char *argv[])
+{
+	int ret = 0;
+	tdls_link_status *param_buf = NULL;
+	tdls_link_status_resp *resp_buf = NULL;
+	t_u16 cmd_len = 0, buf_len = 0, resp_len = 0, curr_link_len = 0;
+	t_u8 no_of_links = 0, peer_mac[ETH_ALEN];
+	t_u8 *buffer = NULL, *raw = NULL;
+	tdls_each_link_status *link_ptr = NULL;
+
+	/* Check arguments */
+	if (argc != 3 && argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_link_status [peer_mac_addr]\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_link_status);
+	buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, buf_len);
+	param_buf = (tdls_link_status *)buffer;
+	param_buf->action = ACTION_TDLS_LINK_STATUS;
+
+	if (argc == 4) {
+		if ((ret = mac2raw(argv[3], peer_mac)) != MLAN_STATUS_SUCCESS) {
+			printf("ERR: %s Address \n",
+			       ret ==
+			       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret ==
+			       MAC_BROADCAST ? "Broadcast" : "Multicast");
+			goto done;
+		}
+		if (memcmp(peer_mac, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)) {
+			memcpy(buffer + cmd_len, peer_mac, ETH_ALEN);
+			cmd_len += ETH_ALEN;
+		}
+	}
+
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		hexdump("tdls_response", buffer, 0x60, ' ');
+		printf("TDLS Link Status - .\n");
+		resp_buf = (tdls_link_status_resp *)buffer;
+		resp_len = resp_buf->payload_len;
+		printf("Response Length = %d\n", resp_len);
+		no_of_links = resp_buf->active_links;
+		printf("No of active links = %d\n", no_of_links);
+		resp_len--;
+		link_ptr = resp_buf->link_stats;
+		while (resp_len > 0 && no_of_links > 0) {
+			curr_link_len = 0;
+			/* MAC */
+			raw = link_ptr->peer_mac;
+			printf("\tPeer - %02x:%02x:%02x:%02x:%02x:%02x\n",
+			       (unsigned int)raw[0], (unsigned int)raw[1],
+			       (unsigned int)raw[2], (unsigned int)raw[3],
+			       (unsigned int)raw[4], (unsigned int)raw[5]);
+
+			printf("\t %s initiated link.\n",
+			       (link_ptr->link_flags & 0x01) ? "Self" : "Peer");
+			printf("\t Security %s.\n",
+			       (link_ptr->
+				link_flags & 0x02) ? "Enabled" : "Disabled");
+			printf("\t Self PS status = %s.\n",
+			       (link_ptr->
+				link_flags & 0x04) ? "Sleep" : "Active");
+			printf("\t Peer PS status = %s.\n",
+			       (link_ptr->
+				link_flags & 0x08) ? "Sleep" : "Active");
+			printf("\t Channel switch is %ssupported\n",
+			       (link_ptr->link_flags & 0x10) ? "" : "NOT ");
+			printf("\t Current Channel %s\n",
+			       (link_ptr->link_flags & 0x20) ? "off" : "base");
+
+			if (link_ptr->traffic_status) {
+				printf("\t Buffered traffic for");
+				printf("%s",
+				       (link_ptr->
+					traffic_status & 0x01) ? "AC_BK, " :
+				       "");
+				printf("%s",
+				       (link_ptr->
+					traffic_status & 0x02) ? "AC_BE, " :
+				       "");
+				printf("%s",
+				       (link_ptr->
+					traffic_status & 0x04) ? "AC_VI, " :
+				       "");
+				printf("%s",
+				       (link_ptr->
+					traffic_status & 0x08) ? "AC_VO" : "");
+				printf(".\n");
+			}
+			printf("\t Successive Tx Failure count = %d\n",
+			       link_ptr->tx_fail_count);
+			printf("\t Active channel number = %d\n",
+			       link_ptr->active_channel);
+			printf("\t Last Data RSSI        = %d dBm\n",
+			       link_ptr->data_rssi_last);
+			printf("\t Last Data NF          = %d dBm\n",
+			       link_ptr->data_nf_last);
+			printf("\t Average Data RSSI     = %d dBm\n",
+			       link_ptr->data_rssi_avg);
+			printf("\t Average Data NF       = %d dBm\n",
+			       link_ptr->data_nf_avg);
+			printf("\t Tx data rate          = %d Mbps\n",
+			       link_ptr->u.final_data_rate);
+
+			/* size of unsecure structure */
+			curr_link_len = sizeof(tdls_each_link_status) -
+				(sizeof(t_u32) + sizeof(t_u8) + sizeof(t_u8));
+
+			if (link_ptr->link_flags & 0x02) {
+				/* security details */
+				printf("\t Security Method = %s\n",
+				       (link_ptr->security_method ==
+					1) ? "AES" : "None");
+				printf("\t Key Lifetime = %d ms\n\t",
+				       link_ptr->key_lifetime);
+				hexdump("Key", ((t_u8 *)link_ptr->key),
+					link_ptr->key_length, ' ');
+				curr_link_len +=
+					sizeof(t_u32) + sizeof(t_u8) +
+					sizeof(t_u8)
+					+ link_ptr->key_length;
+			}
+			resp_len -= curr_link_len;
+			link_ptr =
+				(tdls_each_link_status *)(((t_u8 *)link_ptr) +
+							  curr_link_len);
+			printf(".\n");
+		}
+
+	} else {
+		printf("ERR:Command response = Fail!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_channel_swtich
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_channel_switch(int argc, char *argv[])
+{
+
+	tdls_channel_switch *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_channel_switch <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_channel_switch);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_channel_switch *)buffer;
+	param_buf->action = ACTION_TDLS_INIT_CHAN_SWITCH;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			if ((ret =
+			     mac2raw(mac_addr,
+				     peer_mac)) != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "Band") == 0) {
+			param_buf->band = (t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->band != BAND_BG &&
+			    param_buf->band != BAND_A) {
+				printf("ERR: Incorrect Band value %s\n",
+				       args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "RegulatoryClass") == 0) {
+			param_buf->regulatory_class =
+				(t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "PrimaryChannel") == 0) {
+			param_buf->primary_channel =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->band == BAND_BG &&
+			    param_buf->primary_channel < MIN_BG_CHANNEL &&
+			    param_buf->primary_channel > MAX_BG_CHANNEL) {
+				printf("ERR: Incorrect Primary Channel value  %s\n", args[1]);
+				goto done;
+			} else if (param_buf->band == BAND_A
+				   && param_buf->primary_channel < MIN_A_CHANNEL
+				   && param_buf->primary_channel >
+				   MAX_A_CHANNEL) {
+				printf("ERR: Incorrect Primary Channel value  %s\n", args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "SecondaryChannelOffset") == 0) {
+			param_buf->secondary_channel_offset =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->secondary_channel_offset != 0 &&
+			    param_buf->secondary_channel_offset !=
+			    SECOND_CHANNEL_ABOVE &&
+			    param_buf->secondary_channel_offset !=
+			    SECOND_CHANNEL_BELOW) {
+				printf("ERR: Incorrect Secondary Channel Offset value  %s\n", args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "ChannelSwitchTime") == 0) {
+			param_buf->switch_time = (t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->switch_time == 0) {
+				printf("ERR: Incorrect Channel Switch time  %s\n", args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "ChannelSwitchTimeout") == 0) {
+			param_buf->switch_timeout =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->switch_timeout == 0) {
+				printf("ERR: Incorrect Channel Switch timeout  %s\n", args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "Periodicity") == 0) {
+			param_buf->periodicity = (t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->periodicity != NO_PERIODIC_SWITCH
+			    && param_buf->periodicity !=
+			    ENABLE_PERIODIC_SWITCH) {
+				printf("ERR: Incorrect Periodicity value %s\n",
+				       args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_channel_switch", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS channel switch request successful.\n");
+	} else {
+		printf("ERR:TDLS channel switch request failed.\n");
+	}
+
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief disable tdls_channel_swtich
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_disable_channel_switch(int argc, char *argv[])
+{
+
+	tdls_disable_cs *param_buf = NULL;
+	int ret = 0;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_disable_cs <0/1>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_disable_cs);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_disable_cs *) buffer;
+	param_buf->action = ACTION_TDLS_CS_DISABLE;
+
+	param_buf->data = (t_u16)A2HEXDECIMAL(argv[3]);
+	if ((param_buf->data != 0) && (param_buf->data != 1)) {
+		printf("ERR:Incorrect arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_disable_cs <0/1>\n");
+		goto done;
+	}
+	hexdump("tdls_disable_cs", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS disable channel switch successful.\n");
+	} else {
+		printf("ERR:TDLS disable channel switch failed.\n");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_stop_channel_switch
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_stop_channel_switch(int argc, char *argv[])
+{
+	tdls_stop_chan_switch *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_stop_channel_switch <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_stop_chan_switch);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_stop_chan_switch *) buffer;
+	param_buf->action = ACTION_TDLS_STOP_CHAN_SWITCH;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			if ((ret =
+			     mac2raw(mac_addr,
+				     peer_mac)) != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_stop_channel_switch", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS stop channel switch successful.\n");
+	} else {
+		printf("ERR:TDLS stop channel switch failed.\n");
+	}
+
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_cs_params
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_cs_params(int argc, char *argv[])
+{
+	tdls_cs_params *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_cs_params <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_cs_params);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_cs_params *) buffer;
+	param_buf->action = ACTION_TDLS_CS_PARAMS;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "UnitTime") == 0) {
+			param_buf->unit_time = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "ThresholdOtherLink") == 0) {
+			param_buf->threshold_otherlink =
+				(t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "ThresholdDirectLink") == 0) {
+			param_buf->threshold_directlink =
+				(t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_cs_params", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS set channel switch parameters successful.\n");
+	} else {
+		printf("ERR:TDLS set channel switch parameters failed.\n");
+	}
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_debug
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_debug(int argc, char *argv[])
+{
+	int ret = 0;
+	tdls_debug *param_buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+	t_u16 action = 0, value = 0;
+
+	/* Check arguments */
+	if (argc < 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanconfig mlanX tdls_debug <options>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_debug);
+
+	/* wrong_bss */
+	if (!strcmp(argv[3], "wrong_bss")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_WRONG_BSS;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanconfig mlanX tdls_debug wrong_bss <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* same link */
+	else if (!strcmp(argv[3], "setup_existing_link")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_SETUP_SAME_LINK;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanconfig mlanX tdls_debug setup_existing_link <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* fail_setup_confirm */
+	else if (!strcmp(argv[3], "fail_setup_confirm")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_FAIL_SETUP_CONFIRM;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanconfig mlanX tdls_debug fail_setup_confirm <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* setup prohibited */
+	else if (!strcmp(argv[3], "setup_with_prohibited")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_SETUP_PROHIBITED;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanconfig mlanX tdls_debug setup_with_prohibited <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* setup higher/lower mac */
+	else if (!strcmp(argv[3], "higher_lower_mac")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_HIGHER_LOWER_MAC;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanconfig mlanX tdls_debug higher_lower_mac <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* ignore key lifetime expiry */
+	else if (!strcmp(argv[3], "ignore_key_expiry")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_IGNORE_KEY_EXPIRY;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanconfig mlanX tdls_debug ignore_key_expiry <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* allow weak security */
+	else if (!strcmp(argv[3], "allow_weak_security")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_ALLOW_WEAK_SECURITY;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanconfig mlanX tdls_debug allow_weak_security <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* stop RX */
+	else if (!strcmp(argv[3], "stop_rx")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_STOP_RX;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanconfig mlanX tdls_debug stop_rx <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* Immediate return */
+	else if (!strcmp(argv[3], "cs_im_return")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_CS_RET_IM;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanconfig mlanX tdls_debug cs_im_return <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	} else {
+		printf("ERR:Incorrect command!\n");
+		exit(1);
+	}
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		return -1;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_debug *)buffer;
+	param_buf->action = action;
+	memcpy(param_buf->data, &value, sizeof(value));
+
+	hexdump("tdls_debug", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS debug request successful.\n");
+	} else {
+		printf("ERR:TDLS debug request failed.\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Entry function for mlanconfig
+ *  @param argc		number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+main(int argc, char *argv[])
+{
+	t_s32 cmd;
+
+	if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) {
+		fprintf(stdout, "Marvell mlanconfig version %s\n",
+			MLANCONFIG_VER);
+		exit(0);
+	}
+	if (argc < 3) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		display_usage();
+		exit(1);
+	}
+
+	strncpy(dev_name, argv[1], IFNAMSIZ - 1);
+
+	/*
+	 * create a socket
+	 */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		fprintf(stderr, "mlanconfig: Cannot open socket.\n");
+		exit(1);
+	}
+	if (get_range() < 0) {
+		fprintf(stderr, "mlanconfig: Cannot get range.\n");
+		close(sockfd);
+		exit(1);
+	}
+	switch ((cmd = findcommand(NELEMENTS(commands), commands, argv[2]))) {
+	case CMD_HOSTCMD:
+		process_host_cmd(argc, argv);
+		break;
+	case CMD_MEFCFG:
+		process_mef_cfg(argc, argv);
+		break;
+	case CMD_ARPFILTER:
+		process_arpfilter(argc, argv);
+		break;
+	case CMD_CFG_DATA:
+		process_cfg_data(argc, argv);
+		break;
+	case CMD_CMD52RW:
+		process_sdcmd52rw(argc, argv);
+		break;
+	case CMD_CMD53RW:
+		process_sdcmd53rw(argc, argv);
+		break;
+	case CMD_GET_SCAN_RSP:
+		process_getscantable(argc, argv);
+		break;
+	case CMD_SET_USER_SCAN:
+		process_setuserscan(argc, argv);
+		break;
+	case CMD_ADD_TS:
+		process_addts(argc, argv);
+		break;
+	case CMD_DEL_TS:
+		process_delts(argc, argv);
+		break;
+	case CMD_QCONFIG:
+		process_qconfig(argc, argv);
+		break;
+	case CMD_QSTATS:
+		process_qstats(argc, argv);
+		break;
+	case CMD_TS_STATUS:
+		process_wmm_ts_status(argc, argv);
+		break;
+	case CMD_WMM_QSTATUS:
+		process_wmm_qstatus(argc, argv);
+		break;
+	case CMD_REGRW:
+		process_regrdwr(argc, argv);
+		break;
+	case CMD_MEMRW:
+		process_memrdwr(argc, argv);
+		break;
+	case CMD_STA_CUSTOM_IE:
+		process_custom_ie(argc, argv);
+		break;
+	case CMD_STA_MGMT_FRAME_TX:
+		process_mgmt_frame_tx(argc, argv);
+		break;
+	case CMD_TDLS_CONF:
+		process_tdls_config(argc, argv);
+		break;
+	case CMD_TDLS_INFO:
+		process_tdls_setinfo(argc, argv);
+		break;
+	case CMD_TDLS_DISCOVERY:
+		process_tdls_discovery(argc, argv);
+		break;
+	case CMD_TDLS_SETUP:
+		process_tdls_setup(argc, argv);
+		break;
+	case CMD_TDLS_TEARDOWN:
+		process_tdls_teardown(argc, argv);
+		break;
+	case CMD_TDLS_POWERMODE:
+		process_tdls_powermode(argc, argv);
+		break;
+	case CMD_TDLS_LINK_STATUS:
+		process_tdls_link_status(argc, argv);
+		break;
+	case CMD_TDLS_CHANNEL_SWITCH:
+		process_tdls_channel_switch(argc, argv);
+		break;
+	case CMD_TDLS_STOP_CHAN_SWITCH:
+		process_tdls_stop_channel_switch(argc, argv);
+		break;
+	case CMD_TDLS_CS_PARAMS:
+		process_tdls_cs_params(argc, argv);
+		break;
+	case CMD_TDLS_CS_DISABLE:
+		process_tdls_disable_channel_switch(argc, argv);
+		break;
+	case CMD_TDLS_DEBUG:
+		process_tdls_debug(argc, argv);
+		break;
+	default:
+		fprintf(stderr, "Invalid command specified!\n");
+		display_usage();
+		close(sockfd);
+		exit(1);
+	}
+
+	close(sockfd);
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/mlanconfig.h b/wlan_sd8897/mapp/mlanconfig/mlanconfig.h
new file mode 100644
index 0000000..3d1508c
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/mlanconfig.h
@@ -0,0 +1,791 @@
+/** @file  mlanconfig.h
+  *
+  * @brief This file contains definitions for application
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     11/26/2008: initial version
+************************************************************************/
+#ifndef _MLANCONFIG_H_
+#define _MLANCONFIG_H_
+
+/** Include header files */
+#include    <stdio.h>
+#include    <ctype.h>
+#include    <unistd.h>
+#include    <string.h>
+#include    <stdlib.h>
+#include    <sys/socket.h>
+#include    <sys/ioctl.h>
+#include    <errno.h>
+#include    <linux/if.h>
+#include    <linux/wireless.h>
+#include    <sys/types.h>
+#include    <linux/if_ether.h>
+#include    <time.h>
+
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#undef BIG_ENDIAN_SUPPORT
+#endif
+
+/** Type definition: boolean */
+typedef enum { FALSE, TRUE } boolean;
+
+/**
+ * This macro specifies the attribute pack used for structure packing
+ */
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__  __attribute__((packed))
+#endif
+
+/** 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)))
+
+/** Convert to correct endian format */
+#ifdef 	BIG_ENDIAN_SUPPORT
+/** CPU to little-endian convert for 16-bit */
+#define 	cpu_to_le16(x)	swap_byte_16(x)
+/** CPU to little-endian convert for 32-bit */
+#define		cpu_to_le32(x)  swap_byte_32(x)
+/** Little-endian to CPU convert for 16-bit */
+#define 	le16_to_cpu(x)	swap_byte_16(x)
+/** Little-endian to CPU convert for 32-bit */
+#define		le32_to_cpu(x)  swap_byte_32(x)
+#else
+/** Do nothing */
+#define		cpu_to_le16(x)	(x)
+/** Do nothing */
+#define		cpu_to_le32(x)  (x)
+/** Do nothing */
+#define 	le16_to_cpu(x)	(x)
+/** Do nothing */
+#define 	le32_to_cpu(x)	(x)
+#endif
+
+/** Character, 1 byte */
+typedef char t_s8;
+/** Unsigned character, 1 byte */
+typedef unsigned char t_u8;
+
+/** Short integer */
+typedef signed short t_s16;
+/** Unsigned short integer */
+typedef unsigned short t_u16;
+
+/** Integer */
+typedef signed int t_s32;
+/** Unsigned integer */
+typedef unsigned int t_u32;
+
+/** Long long integer */
+typedef signed long long t_s64;
+/** Unsigned long long integer */
+typedef unsigned long long t_u64;
+
+/** Void pointer (4-bytes) */
+typedef void t_void;
+
+/** Success */
+#define MLAN_STATUS_SUCCESS         (0)
+/** Failure */
+#define MLAN_STATUS_FAILURE         (-1)
+
+t_s8 *mlan_config_get_line(FILE * fp, t_s8 *s, t_s32 size, int *line);
+int get_priv_ioctl(char *ioctl_name, int *ioctl_val, int *subioctl_val);
+int fparse_for_hex(FILE * fp, t_u8 *dst);
+
+/**
+ * Hex or Decimal to Integer
+ * @param   num string to convert into decimal or hex
+ */
+#define A2HEXDECIMAL(num)  \
+    (strncasecmp("0x", (num), 2)?(unsigned int) strtoll((num),NULL,0):a2hex((num)))
+
+/** Convert character to integer */
+#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0'))
+
+/** Convert TLV header from little endian format to CPU format */
+#define endian_convert_tlv_header_in(x)            \
+    {                                               \
+        (x)->tag = le16_to_cpu((x)->tag);       \
+        (x)->length = le16_to_cpu((x)->length); \
+    }
+
+/** Convert TLV header to little endian format from CPU format */
+#define endian_convert_tlv_header_out(x)            \
+    {                                               \
+        (x)->tag = cpu_to_le16((x)->tag);       \
+        (x)->length = cpu_to_le16((x)->length); \
+    }
+/** Private command ID to pass custom IE list */
+#define CUSTOM_IE_CFG          (SIOCDEVPRIVATE + 13)
+/* TLV Definitions */
+/** TLV header */
+#define TLVHEADER       /** Tag */      \
+                        t_u16 tag;      \
+                        /** Length */   \
+                        t_u16 length
+
+/** Maximum IE buffer length */
+#define MAX_IE_BUFFER_LEN 256
+
+/** TLV: Management IE list */
+#define MRVL_MGMT_IE_LIST_TLV_ID          (PROPRIETARY_TLV_BASE_ID + 0x69)	//0x0169
+
+/** TLV: Max Management IE */
+#define MRVL_MAX_MGMT_IE_TLV_ID           (PROPRIETARY_TLV_BASE_ID + 0xaa)	//0x01aa
+
+/** custom IE info */
+typedef struct _custom_ie_info {
+    /** size of buffer */
+	t_u16 buf_size;
+    /** no of buffers of buf_size */
+	t_u16 buf_count;
+} __ATTRIB_PACK__ custom_ie_info;
+
+/** TLV buffer : custom IE */
+typedef struct _tlvbuf_max_mgmt_ie {
+    /** Header */
+	TLVHEADER;
+    /** No of tuples */
+	t_u16 count;
+    /** custom IE info tuples */
+	custom_ie_info info[0];
+} __ATTRIB_PACK__ tlvbuf_max_mgmt_ie;
+
+/** custom IE */
+typedef 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[0];
+} __ATTRIB_PACK__ custom_ie;
+
+/** TLV buffer : custom IE */
+typedef struct _tlvbuf_custom_ie {
+    /** Header */
+	TLVHEADER;
+    /** custom IE data */
+	custom_ie ie_data[0];
+} __ATTRIB_PACK__ tlvbuf_custom_ie;
+
+/** Maximum length of lines in configuration file */
+#define MAX_CONFIG_LINE                 1024
+/** Ethernet address length */
+#define ETH_ALEN                        6
+/** MAC BROADCAST */
+#define MAC_BROADCAST   0x1FF
+/** MAC MULTICAST */
+#define MAC_MULTICAST   0x1FE
+
+/** pkt_header */
+typedef struct _pkt_header {
+    /** pkt_len */
+	t_u32 pkt_len;
+    /** pkt_type */
+	t_u32 TxPktType;
+    /** tx control */
+	t_u32 TxControl;
+} pkt_header;
+
+/** wlan_802_11_header packet from FW with length */
+typedef struct _wlan_mgmt_frame_tx {
+    /** Packet Length */
+	t_u16 frm_len;
+    /** Frame Control */
+	t_u16 frm_ctl;
+    /** Duration ID */
+	t_u16 duration_id;
+    /** Address1 */
+	t_u8 addr1[ETH_ALEN];
+    /** Address2 */
+	t_u8 addr2[ETH_ALEN];
+    /** Address3 */
+	t_u8 addr3[ETH_ALEN];
+    /** Sequence Control */
+	t_u16 seq_ctl;
+    /** Address4 */
+	t_u8 addr4[ETH_ALEN];
+    /** Frame payload */
+	t_u8 payload[0];
+} __ATTRIB_PACK__ wlan_mgmt_frame_tx;
+
+/** frame tx ioctl number */
+#define FRAME_TX_IOCTL               (SIOCDEVPRIVATE + 12)
+
+/** band BG */
+#define BAND_BG        0
+/** band A */
+#define BAND_A         1
+/** secondary channel is above */
+#define SECOND_CHANNEL_ABOVE    0x1
+/** secondary channel is below */
+#define SECOND_CHANNEL_BELOW    0x3
+/** NO PERIODIC SWITCH */
+#define NO_PERIODIC_SWITCH      0
+/** Enable periodic channel switch */
+#define ENABLE_PERIODIC_SWITCH  1
+/** Min channel value for BG band */
+#define MIN_BG_CHANNEL 1
+/** Max channel value for BG band */
+#define MAX_BG_CHANNEL 14
+/** Max channel value for A band */
+#define MIN_A_CHANNEL 36
+/** Max channel value for A band */
+#define MAX_A_CHANNEL 252
+
+/** Host Command ioctl number */
+#define TDLS_IOCTL               (SIOCDEVPRIVATE + 5)
+/** TDLS action definitions */
+/** Action ID for TDLS config */
+#define ACTION_TDLS_CONFIG       0x0000
+/** Action ID for TDLS setinfo request */
+#define ACTION_TDLS_SETINFO      0x0001
+/** Action ID for TDLS Discovery request */
+#define ACTION_TDLS_DISCOVERY    0x0002
+/** Action ID for TDLS setup request */
+#define ACTION_TDLS_SETUP        0x0003
+/** Action ID for TDLS Teardown request */
+#define ACTION_TDLS_TEARDOWN     0x0004
+/** Action ID for TDLS power mode */
+#define ACTION_TDLS_POWER_MODE   0x0005
+/**Action ID for init TDLS Channel Switch*/
+#define ACTION_TDLS_INIT_CHAN_SWITCH     0x06
+/** Action ID for stop TDLS Channel Switch */
+#define ACTION_TDLS_STOP_CHAN_SWITCH     0x07
+/** Action ID for configure CS related parameters */
+#define ACTION_TDLS_CS_PARAMS            0x08
+/** Action ID for TDLS Disable Channel switch */
+#define ACTION_TDLS_CS_DISABLE          0x09
+/** Action ID for TDLS Link status */
+#define ACTION_TDLS_LINK_STATUS  0x000A
+/** Action ID for TDLS CS immediate return */
+#define ACTION_TDLS_DEBUG_CS_RET_IM 0xFFF7
+/** Action ID for TDLS Stop RX */
+#define ACTION_TDLS_DEBUG_STOP_RX 0xFFF8
+/** Action ID for TDLS Allow weak security */
+#define ACTION_TDLS_DEBUG_ALLOW_WEAK_SECURITY 0xFFF9
+/** Action ID for TDLS Ignore key lifetime expiry */
+#define ACTION_TDLS_DEBUG_IGNORE_KEY_EXPIRY 0xFFFA
+/** Action ID for TDLS Higher/Lower mac Test */
+#define ACTION_TDLS_DEBUG_HIGHER_LOWER_MAC 0xFFFB
+/** Action ID for TDLS Prohibited Test */
+#define ACTION_TDLS_DEBUG_SETUP_PROHIBITED 0xFFFC
+/** Action ID for TDLS Existing link Test */
+#define ACTION_TDLS_DEBUG_SETUP_SAME_LINK 0xFFFD
+/** Action ID for TDLS Fail Setup Confirm */
+#define ACTION_TDLS_DEBUG_FAIL_SETUP_CONFIRM 0xFFFE
+/** Action ID for TDLS WRONG BSS Test */
+#define ACTION_TDLS_DEBUG_WRONG_BSS 0xFFFF
+
+/** TLV type : Rates */
+#define TLV_TYPE_RATES                          0x0001
+/** TLV type : Domain */
+#define TLV_TYPE_DOMAIN                         0x0007
+/** TLV type : Supported channels */
+#define TLV_TYPE_SUPPORTED_CHANNELS             0x0024
+/** TLV type : HT Capabilities */
+#define TLV_TYPE_HT_CAP                         0x002d
+/** TLV type : Qos Info */
+#define TLV_TYPE_QOSINFO                        0x002e
+/** TLV type : RSN IE */
+#define TLV_TYPE_RSN_IE                         0x0030
+/** TLV type : extended supported rates */
+#define TLV_EXTENDED_SUPPORTED_RATES            0x0032
+/** TLV type :  timeout interval    */
+#define TLV_TIMEOUT_INTERVAL                    0x0038
+/** TLV type : Regulatory classes */
+#define TLV_TYPE_REGULATORY_CLASSES             0x003b
+/** TLV type : HT Information */
+#define TLV_TYPE_HT_INFO                        0x003d
+/** TLV type : 20/40 BSS Coexistence */
+#define TLV_TYPE_2040BSS_COEXISTENCE            0x0048
+/** TLv Type : Link identifier */
+#define TLV_LINK_IDENTIFIER                     0x0065
+/** TLV type : Extended capabilities */
+#define TLV_TYPE_EXTCAP                         0x007f
+
+/** TLV type : VHT capabilities */
+#define TLV_TYPE_VHT_CAP		        0x00BF
+/** TLV type : VHT operations */
+#define TLV_TYPE_VHT_OPER	                0x00C0
+/** Length of Basic MCS MAP */
+#define VHT_MCS_MAP_LEN    			2
+
+/** Country code length */
+#define COUNTRY_CODE_LEN                        3
+/** Length of Group Cipher Suite */
+#define GROUP_CIPHER_SUITE_LEN     4
+/** Length of Pairwise Cipher Suite */
+#define PAIRWISE_CIPHER_SUITE_LEN  4
+/** Length of AKM Suite */
+#define AKM_SUITE_LEN          4
+/** PMKID length */
+#define PMKID_LEN              16
+/** Maximum number of pairwise_cipher_suite */
+#define MAX_PAIRWISE_CIPHER_SUITE_COUNT    2
+/** Maximum number of AKM suite */
+#define MAX_AKM_SUITE_COUNT    2
+/** Maximum number of PMKID list count */
+#define MAX_PMKID_COUNT    2
+/** Length of MCS set */
+#define MCS_SET_LEN    16
+/** Version in RSN IE */
+#define VERSION_RSN_IE    0x0001
+
+/** tdls setinfo */
+typedef struct _tdls_setinfo {
+    /** Action */
+	t_u16 action;
+    /** (TLV + capInfo) length */
+	t_u16 tlv_len;
+    /** Capability Info */
+	t_u16 cap_info;
+    /** tdls info */
+	t_u8 tlv_buffer[0];
+} __ATTRIB_PACK__ tdls_setinfo;
+
+/** tdls discovery */
+typedef struct _tdls_discovery {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+} __ATTRIB_PACK__ tdls_discovery;
+
+/** tdls link status */
+typedef struct _tdls_links_status {
+    /** Action */
+	t_u16 action;
+} __ATTRIB_PACK__ tdls_link_status;
+
+/** tdls discovery response */
+typedef struct _tdls_discovery_resp {
+    /** Action */
+	t_u16 action;
+    /** payload length */
+	t_u16 payload_len;
+    /** peer mac Address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** RSSI */
+	signed char rssi;
+    /** Cap Info */
+	t_u16 cap_info;
+    /** TLV buffer */
+	t_u8 tlv_buffer[0];
+} __ATTRIB_PACK__ tdls_discovery_resp;
+
+/** tdls each link rate information */
+typedef struct _tdls_link_rate_info {
+    /** Tx Data Rate */
+	t_u8 tx_data_rate;
+    /** Tx Rate HT info*/
+	t_u8 tx_rate_htinfo;
+} __ATTRIB_PACK__ tdls_link_rate_info;
+
+/** tdls each link status */
+typedef struct _tdls_each_link_status {
+    /** peer mac Address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** 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;
+	/** final rate value*/
+		t_u16 final_data_rate;
+	} u;
+    /** Security Method */
+	t_u8 security_method;
+    /** Key Lifetime */
+	t_u32 key_lifetime;
+    /** Key Length */
+	t_u8 key_length;
+    /** actual key */
+	t_u8 key[0];
+} __ATTRIB_PACK__ tdls_each_link_status;
+
+/** tdls link status response */
+typedef struct _tdls_link_status_resp {
+    /** Action */
+	t_u16 action;
+    /** payload length */
+	t_u16 payload_len;
+    /** number of links */
+	t_u8 active_links;
+    /** structure for link status */
+	tdls_each_link_status link_stats[1];
+} __ATTRIB_PACK__ tdls_link_status_resp;
+
+/** tdls setup */
+typedef struct _tdls_setup {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** Time to wait for response from peer*/
+	t_u32 wait_time;
+    /** Key Life Time */
+	t_u32 key_life_time;
+} __ATTRIB_PACK__ tdls_setup;
+
+/** tdls tear down */
+typedef struct _tdls_tear_down {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** Reason code */
+	t_u16 reason_code;
+} __ATTRIB_PACK__ tdls_teardown;
+
+/** tdls power mode */
+typedef struct _tdls_power_mode {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** Power mode */
+	t_u16 power_mode;
+} __ATTRIB_PACK__ tdls_powermode;
+
+/** tdls channel switch info */
+typedef struct _tdls_channel_switch {
+    /** Action */
+	t_u16 action;
+    /** peer mac Address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** 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*/
+	t_u16 switch_time;
+    /** Channel Switch timeout*/
+	t_u16 switch_timeout;
+    /** Channel Regulatory class*/
+	t_u8 regulatory_class;
+    /** Channel Switch periodicity*/
+	t_u8 periodicity;
+} __ATTRIB_PACK__ tdls_channel_switch;
+
+/** tdls stop channel switch */
+typedef struct _tdls_stop_chan_switch {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+} __ATTRIB_PACK__ tdls_stop_chan_switch;
+
+/** tdls disable channel switch */
+typedef struct _tdls_disable_cs {
+    /** Action */
+	t_u16 action;
+    /** Data*/
+	t_u16 data;
+} __ATTRIB_PACK__ tdls_disable_cs, tdls_config;
+
+/** tdls channel switch parameters */
+typedef struct _tdls_cs_params {
+    /** Action */
+	t_u16 action;
+    /** 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;
+} __ATTRIB_PACK__ tdls_cs_params;
+
+/** tdls debug */
+typedef struct _tdls_debug {
+    /** Action */
+	t_u16 action;
+    /** Data */
+	t_u8 data[0];
+} __ATTRIB_PACK__ tdls_debug;
+
+/** TLV header */
+#define TLVHEADER       /** Tag */      \
+                        t_u16 tag;      \
+                        /** Length */   \
+                        t_u16 length
+
+/** Length of TLV header */
+#define TLVHEADER_LEN  4
+
+/** Data structure for subband set */
+typedef struct _IEEEtypes_SubbandSet_t {
+    /** First channel */
+	t_u8 first_chan;
+    /** Number of channels */
+	t_u8 no_of_chan;
+    /** Maximum Tx power */
+	t_u8 max_tx_pwr;
+} __ATTRIB_PACK__ IEEEtypes_SubbandSet_t, *pIEEEtypes_SubbandSet_t;
+
+/** tlvbuf_DomainParamSet_t */
+typedef struct _tlvbuf_DomainParamSet {
+    /** Header */
+	TLVHEADER;
+    /** Country code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+    /** Set of subbands */
+	IEEEtypes_SubbandSet_t sub_band[0];
+} __ATTRIB_PACK__ tlvbuf_DomainParamSet_t;
+
+/** Data structure of WMM QoS information */
+typedef 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 */
+} __ATTRIB_PACK__ IEEEtypes_WmmQosInfo_t;
+
+/** Qos Info TLV */
+typedef struct _tlvbuf_QosInfo_t {
+    /** Header */
+	TLVHEADER;
+    /** QosInfo */
+	union {
+	/** QosInfo bitfield */
+		IEEEtypes_WmmQosInfo_t qos_info;
+	/** QosInfo byte */
+		t_u8 qos_info_byte;
+	} u;
+} __ATTRIB_PACK__ tlvbuf_QosInfo_t;
+
+/** HT Capabilities Data */
+typedef struct _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;
+} __ATTRIB_PACK__ HTCap_t, *pHTCap_t;
+
+/** HT Information Data */
+typedef struct _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];
+} __ATTRIB_PACK__ HTInfo_t, *pHTInfo_t;
+
+/** 20/40 BSS Coexistence Data */
+typedef struct _BSSCo2040_t {
+    /** 20/40 BSS Coexistence value */
+	t_u8 bss_co_2040_value;
+} __ATTRIB_PACK__ BSSCo2040_t, *pBSSCo2040_t;
+
+/** HT Capabilities element */
+typedef struct _tlvbuf_HTCap_t {
+    /** Header */
+	TLVHEADER;
+    /** HTCap struct */
+	HTCap_t ht_cap;
+} __ATTRIB_PACK__ tlvbuf_HTCap_t;
+
+/** HT Information element */
+typedef struct _tlvbuf_HTInfo_t {
+    /** Header */
+	TLVHEADER;
+
+    /** HTInfo struct */
+	HTInfo_t ht_info;
+} __ATTRIB_PACK__ tlvbuf_HTInfo_t;
+
+/** VHT MCS rate set field, refer to 802.11ac */
+typedef 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 */
+} __ATTRIB_PACK__ VHT_MCS_set_t, *pVHT_MCS_set_t;
+
+typedef struct _VHT_capa {
+	t_u32 vht_cap_info;
+	VHT_MCS_set_t mcs_sets;
+} __ATTRIB_PACK__ VHT_capa_t, *pVHT_capa_t;
+
+/** VHT Capabilities IE */
+typedef struct _IEEEtypes_VHTCap_t {
+    /** Header */
+	TLVHEADER;
+    /** VHTInfo struct */
+	VHT_capa_t vht_cap;
+} __ATTRIB_PACK__ tlvbuf_VHTCap_t, *ptlvbuf_VHTCap_t;
+
+/** VHT Operations IE */
+typedef struct _IEEEtypes_VHTOprat_t {
+    /** Header */
+	TLVHEADER;
+    /** VHTOpra struct */
+	t_u8 chan_width;
+	t_u8 chan_cf1;
+	t_u8 chan_cf2;
+    /** Basic MCS set map, each 2 bits stands for a Nss */
+	t_u8 basic_mcs_map[VHT_MCS_MAP_LEN];
+} __ATTRIB_PACK__ tlvbuf_VHTOpra_t, *ptlvbuf_VHTOpra_t;
+
+/** 20/40 BSS Coexistence element */
+typedef struct _tlvbuf_2040BSSCo_t {
+    /** Header */
+	TLVHEADER;
+
+    /** BSSCo2040_t struct */
+	BSSCo2040_t bss_co_2040;
+} __ATTRIB_PACK__ tlvbuf_2040BSSCo_t;
+
+/** Extended Capabilities element */
+typedef struct _tlvbuf_ExtCap_t {
+    /** Header */
+	TLVHEADER;
+    /** ExtCap_t struct */
+	t_u8 ext_cap[0];
+} __ATTRIB_PACK__ tlvbuf_ExtCap_t;
+
+/** tlvbuf_RatesParamSet_t */
+typedef struct _tlvbuf_RatesParamSet_t {
+    /** Header */
+	TLVHEADER;
+    /** Rates */
+	t_u8 rates[0];
+} __ATTRIB_PACK__ tlvbuf_RatesParamSet_t;
+
+/*  IEEE Supported Channel sub-band description (7.3.2.19) */
+/*  Sub-band description used in the supported channels element. */
+typedef struct _IEEEtypes_SupportChan_Subband_t {
+	t_u8 start_chan;/**< Starting channel in the subband */
+	t_u8 num_chans;	/**< Number of channels in the subband */
+
+} __ATTRIB_PACK__ 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 struct _tlvbuf_SupportedChannels_t {
+    /** Header */
+	TLVHEADER;
+		 /**< IEEE Element ID = 36 */
+    /** Configured sub-bands information in the element */
+	IEEEtypes_SupportChan_Subband_t subband[0];
+} __ATTRIB_PACK__ tlvbuf_SupportedChannels_t;
+
+/*  IEEE Supported Regulatory Classes description (7.3.2.54) */
+typedef struct _IEEEtypes_RegulatoryClass_t {
+    /** current regulatory class */
+	t_u8 cur_regulatory_class;
+    /** supported regulatory class list */
+	t_u8 regulatory_classes_list[0];
+
+} __ATTRIB_PACK__ IEEEtypes_RegulatoryClass_t;
+
+/*  IEEE Supported Regulatory Classes TLV (7.3.2.54) */
+typedef struct _tlvbuf_RegulatoryClass_t {
+    /** Header */
+	TLVHEADER;
+		 /**< IEEE Element ID = 59 */
+    /** supported regulatory class */
+	IEEEtypes_RegulatoryClass_t regulatory_class;
+} __ATTRIB_PACK__ tlvbuf_RegulatoryClass_t;
+
+/** tlvbuf_RsnParamSet_t */
+typedef struct _tlvbuf_RsnParamSet_t {
+    /** Header */
+	TLVHEADER;
+    /** Version */
+	t_u16 version;
+    /** Group Cipher Suite */
+	t_u8 group_cipher_suite[4];
+    /** Pairwise Cipher Suite count */
+	t_u16 pairwise_cipher_count;
+    /** Pairwise Cipher Suite */
+	t_u8 pairwise_cipher_suite[0];
+    /** AKM Suite Sount */
+	t_u16 akm_suite_count;
+    /** AKM Suite */
+	t_u8 akm_suite[0];
+    /** RSN Capability */
+	t_u16 rsn_capability;
+    /** PMKID Count */
+	t_u16 pmkid_count;
+    /** PMKID list */
+	t_u8 pmkid_list[0];
+} __ATTRIB_PACK__ tlvbuf_RsnParamSet_t;
+
+extern t_s32 sockfd;  /**< socket */
+extern t_s8 dev_name[IFNAMSIZ + 1];   /**< device name */
+
+#endif /* _MLANCONFIG_H_ */
diff --git a/wlan_sd8897/mapp/mlanconfig/mlanhostcmd.c b/wlan_sd8897/mapp/mlanconfig/mlanhostcmd.c
new file mode 100644
index 0000000..7ff73bc
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/mlanhostcmd.c
@@ -0,0 +1,920 @@
+/** @file  mlanhostcmd.c
+  *
+  * @brief This file contains mlanconfig helper functions
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     11/26/2008: initial version
+************************************************************************/
+
+#include	"mlanconfig.h"
+#include	"mlanhostcmd.h"
+
+#ifndef MIN
+/** Find minimum value */
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief get hostcmd data
+ *
+ *  @param ln			A pointer to line number
+ *  @param buf			A pointer to hostcmd data
+ *  @param size			A pointer to the return size of hostcmd buffer
+ *  @return      		MLAN_STATUS_SUCCESS
+ */
+static int
+mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
+{
+	t_s32 errors = 0, i;
+	t_s8 line[256], *pos, *pos1, *pos2, *pos3;
+	t_u16 len;
+
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
+		(*ln)++;
+		if (strcmp(pos, "}") == 0) {
+			break;
+		}
+
+		pos1 = strchr(pos, ':');
+		if (pos1 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos1++ = '\0';
+
+		pos2 = strchr(pos1, '=');
+		if (pos2 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos2++ = '\0';
+
+		len = a2hex_or_atoi(pos1);
+		if (len < 1 || len > MRVDRV_SIZE_OF_CMD_BUFFER) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+
+		*size += len;
+
+		if (*pos2 == '"') {
+			pos2++;
+			if ((pos3 = strchr(pos2, '"')) == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln,
+				       pos);
+				errors++;
+				continue;
+			}
+			*pos3 = '\0';
+			memset(buf, 0, len);
+			memmove(buf, pos2, MIN(strlen(pos2), len));
+			buf += len;
+		} else if (*pos2 == '\'') {
+			pos2++;
+			if ((pos3 = strchr(pos2, '\'')) == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln,
+				       pos);
+				errors++;
+				continue;
+			}
+			*pos3 = ',';
+			for (i = 0; i < len; i++) {
+				if ((pos3 = strchr(pos2, ',')) != NULL) {
+					*pos3 = '\0';
+					*buf++ = (t_u8)a2hex_or_atoi(pos2);
+					pos2 = pos3 + 1;
+				} else
+					*buf++ = 0;
+			}
+		} else if (*pos2 == '{') {
+			t_u16 tlvlen = 0, tmp_tlvlen;
+			mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen);
+			tmp_tlvlen = tlvlen;
+			while (len--) {
+				*buf++ = (t_u8)(tmp_tlvlen & 0xff);
+				tmp_tlvlen >>= 8;
+			}
+			*size += tlvlen;
+			buf += tlvlen;
+		} else {
+			t_u32 value = a2hex_or_atoi(pos2);
+			while (len--) {
+				*buf++ = (t_u8)(value & 0xff);
+				value >>= 8;
+			}
+		}
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief convert char to hex integer
+ *
+ *  @param chr 		char to convert
+ *  @return      	hex integer or 0
+ */
+int
+hexval(t_s32 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 Hump hex data
+ *
+ *  @param prompt	A pointer prompt buffer
+ *  @param p		A pointer to data buffer
+ *  @param len		the len of data buffer
+ *  @param delim	delim char
+ *  @return            	hex integer
+ */
+t_void
+hexdump(t_s8 *prompt, t_void *p, t_s32 len, t_s8 delim)
+{
+	t_s32 i;
+	t_u8 *s = p;
+
+	if (prompt) {
+		printf("%s: len=%d\n", prompt, (int)len);
+	}
+	for (i = 0; i < len; i++) {
+		if (i != len - 1)
+			printf("%02x%c", *s++, delim);
+		else
+			printf("%02x\n", *s);
+		if ((i + 1) % 16 == 0)
+			printf("\n");
+	}
+	printf("\n");
+}
+
+/**
+ *  @brief convert char to hex integer
+ *
+ *  @param chr		char
+ *  @return            	hex integer
+ */
+t_u8
+hexc2bin(t_s8 chr)
+{
+	if (chr >= '0' && chr <= '9')
+		chr -= '0';
+	else if (chr >= 'A' && chr <= 'F')
+		chr -= ('A' - 10);
+	else if (chr >= 'a' && chr <= 'f')
+		chr -= ('a' - 10);
+
+	return chr;
+}
+
+/**
+ *  @brief convert string to hex integer
+ *
+ *  @param s		A pointer string buffer
+ *  @return            	hex integer
+ */
+t_u32
+a2hex(t_s8 *s)
+{
+	t_u32 val = 0;
+
+	if (!strncasecmp("0x", s, 2)) {
+		s += 2;
+	}
+
+	while (*s && isxdigit(*s)) {
+		val = (val << 4) + hexc2bin(*s++);
+	}
+
+	return val;
+}
+
+/*
+ *  @brief convert String to integer
+ *
+ *  @param value	A pointer to string
+ *  @return             integer
+ */
+t_u32
+a2hex_or_atoi(t_s8 *value)
+{
+	if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) {
+		return a2hex(value + 2);
+	} else if (isdigit(*value)) {
+		return atoi(value);
+	} else {
+		return *value;
+	}
+}
+
+/**
+ *  @brief convert string to hex
+ *
+ *  @param ptr		A pointer to data buffer
+ *  @param chr 		A pointer to return integer
+ *  @return      	A pointer to next data field
+ */
+t_s8 *
+convert2hex(t_s8 *ptr, t_u8 *chr)
+{
+	t_u8 val;
+
+	for (val = 0; *ptr && isxdigit(*ptr); ptr++) {
+		val = (val * 16) + hexval(*ptr);
+	}
+
+	*chr = val;
+
+	return ptr;
+}
+
+/**
+ *  @brief Check the Hex String
+ *  @param s  A pointer to the string
+ *  @return   MLAN_STATUS_SUCCESS --HexString, MLAN_STATUS_FAILURE --not HexString
+ */
+int
+ishexstring(t_s8 *s)
+{
+	int ret = MLAN_STATUS_FAILURE;
+	t_s32 tmp;
+
+	if (!strncasecmp("0x", s, 2)) {
+		s += 2;
+	}
+	while (*s) {
+		tmp = toupper(*s);
+		if (((tmp >= 'A') && (tmp <= 'F')) ||
+		    ((tmp >= '0') && (tmp <= '9'))) {
+			ret = MLAN_STATUS_SUCCESS;
+		} else {
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		s++;
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief Convert String to Integer
+ *  @param buf      A pointer to the string
+ *  @return         Integer
+ */
+int
+atoval(t_s8 *buf)
+{
+	if (!strncasecmp(buf, "0x", 2))
+		return a2hex(buf + 2);
+	else if (!ishexstring(buf))
+		return a2hex(buf);
+	else
+		return atoi(buf);
+}
+
+/**
+ *  @brief Prepare host-command buffer
+ *  @param fp		File handler
+ *  @param cmd_name	Command name
+ *  @param buf		A pointer to comand buffer
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf)
+{
+	t_s8 line[256], cmdname[256], *pos, cmdcode[10];
+	HostCmd_DS_GEN *hostcmd;
+	int ln = 0;
+	int cmdname_found = 0, cmdcode_found = 0;
+
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	hostcmd->command = 0xffff;
+
+	snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name);
+	cmdname_found = 0;
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, cmdname) == 0) {
+			cmdname_found = 1;
+			snprintf(cmdcode, sizeof(cmdcode), "CmdCode=");
+			cmdcode_found = 0;
+			while ((pos =
+				mlan_config_get_line(fp, line, sizeof(line),
+						     &ln))) {
+				if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) {
+					cmdcode_found = 1;
+					hostcmd->command =
+						a2hex_or_atoi(pos +
+							      strlen(cmdcode));
+					hostcmd->size = S_DS_GEN;
+					mlan_get_hostcmd_data(fp, &ln,
+							      buf +
+							      hostcmd->size,
+							      &hostcmd->size);
+					break;
+				}
+			}
+			if (!cmdcode_found) {
+				fprintf(stderr,
+					"mlanconfig: CmdCode not found in conf file\n");
+				return MLAN_STATUS_FAILURE;
+			}
+			break;
+		}
+	}
+
+	if (!cmdname_found) {
+		fprintf(stderr,
+			"mlanconfig: cmdname '%s' is not found in conf file\n",
+			cmd_name);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	hostcmd->command = cpu_to_le16(hostcmd->command);
+	hostcmd->size = cpu_to_le16(hostcmd->size);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/** Config data header length */
+#define CFG_DATA_HEADER_LEN 6
+
+/**
+ *  @brief Prepare cfg-data buffer
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param fp       File handler
+ *  @param buf      A pointer to comand buffer
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_cfg_data_buffer(int argc, char *argv[], FILE * fp, t_u8 *buf)
+{
+	int ln = 0, type;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_802_11_CFG_DATA *pcfg_data;
+
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA);
+	pcfg_data = (HostCmd_DS_802_11_CFG_DATA *)(buf + S_DS_GEN);
+	pcfg_data->action =
+		(argc == 4) ? HostCmd_ACT_GEN_GET : HostCmd_ACT_GEN_SET;
+	type = atoi(argv[3]);
+	if ((type < 1) || (type > 2)) {
+		fprintf(stderr, "mlanconfig: Invalid register type\n");
+		return MLAN_STATUS_FAILURE;
+	} else {
+		pcfg_data->type = type;
+	}
+	if (argc == 5) {
+		ln = fparse_for_hex(fp, pcfg_data->data);
+	}
+	pcfg_data->data_len = ln;
+	hostcmd->size =
+		cpu_to_le16(pcfg_data->data_len + S_DS_GEN +
+			    CFG_DATA_HEADER_LEN);
+	pcfg_data->data_len = cpu_to_le16(pcfg_data->data_len);
+	pcfg_data->type = cpu_to_le16(pcfg_data->type);
+	pcfg_data->action = cpu_to_le16(pcfg_data->action);
+
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process host_cmd response
+ *  @param buf		A pointer to the response buffer
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_host_cmd_resp(t_u8 *buf)
+{
+	HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	hostcmd->command = le16_to_cpu(hostcmd->command);
+	hostcmd->size = le16_to_cpu(hostcmd->size);
+	hostcmd->seq_num = le16_to_cpu(hostcmd->seq_num);
+	hostcmd->result = le16_to_cpu(hostcmd->result);
+
+	hostcmd->command &= ~HostCmd_RET_BIT;
+	if (!hostcmd->result) {
+		switch (hostcmd->command) {
+		case HostCmd_CMD_CFG_DATA:
+			{
+				HostCmd_DS_802_11_CFG_DATA *pstcfgData =
+					(HostCmd_DS_802_11_CFG_DATA *)(buf +
+								       S_DS_GEN);
+				pstcfgData->data_len =
+					le16_to_cpu(pstcfgData->data_len);
+				pstcfgData->action =
+					le16_to_cpu(pstcfgData->action);
+
+				if (pstcfgData->action == HostCmd_ACT_GEN_GET) {
+					hexdump("cfgdata", pstcfgData->data,
+						pstcfgData->data_len, ' ');
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+			{
+				mlan_ioctl_11h_tpc_resp *tpcIoctlResp =
+					(mlan_ioctl_11h_tpc_resp *)(buf +
+								    S_DS_GEN);
+				if (tpcIoctlResp->status_code == 0) {
+					printf("tpcrequest:  txPower(%d), linkMargin(%d), rssi(%d)\n", tpcIoctlResp->tx_power, tpcIoctlResp->link_margin, tpcIoctlResp->rssi);
+				} else {
+					printf("tpcrequest:  failure, status = %d\n", tpcIoctlResp->status_code);
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_CRYPTO:
+			{
+				t_u16 alg =
+					le16_to_cpu((t_u16)
+						    *(buf + S_DS_GEN +
+						      sizeof(t_u16)));
+				if (alg != CIPHER_TEST_AES_CCM) {
+					HostCmd_DS_802_11_CRYPTO *cmd =
+						(HostCmd_DS_802_11_CRYPTO *)(buf
+									     +
+									     S_DS_GEN);
+					cmd->encdec = le16_to_cpu(cmd->encdec);
+					cmd->algorithm =
+						le16_to_cpu(cmd->algorithm);
+					cmd->key_IV_length =
+						le16_to_cpu(cmd->key_IV_length);
+					cmd->key_length =
+						le16_to_cpu(cmd->key_length);
+					cmd->data.header.type =
+						le16_to_cpu(cmd->data.header.
+							    type);
+					cmd->data.header.len =
+						le16_to_cpu(cmd->data.header.
+							    len);
+
+					printf("crypto_result: encdec=%d algorithm=%d,KeyIVLen=%d," " KeyLen=%d,dataLen=%d\n", cmd->encdec, cmd->algorithm, cmd->key_IV_length, cmd->key_length, cmd->data.header.len);
+					hexdump("KeyIV", cmd->keyIV,
+						cmd->key_IV_length, ' ');
+					hexdump("Key", cmd->key,
+						cmd->key_length, ' ');
+					hexdump("Data", cmd->data.data,
+						cmd->data.header.len, ' ');
+				} else {
+					HostCmd_DS_802_11_CRYPTO_AES_CCM
+						*cmd_aes_ccm =
+						(HostCmd_DS_802_11_CRYPTO_AES_CCM
+						 *)(buf + S_DS_GEN);
+
+					cmd_aes_ccm->encdec
+						=
+						le16_to_cpu(cmd_aes_ccm->
+							    encdec);
+					cmd_aes_ccm->algorithm =
+						le16_to_cpu(cmd_aes_ccm->
+							    algorithm);
+					cmd_aes_ccm->key_length =
+						le16_to_cpu(cmd_aes_ccm->
+							    key_length);
+					cmd_aes_ccm->nonce_length =
+						le16_to_cpu(cmd_aes_ccm->
+							    nonce_length);
+					cmd_aes_ccm->AAD_length =
+						le16_to_cpu(cmd_aes_ccm->
+							    AAD_length);
+					cmd_aes_ccm->data.header.type =
+						le16_to_cpu(cmd_aes_ccm->data.
+							    header.type);
+					cmd_aes_ccm->data.header.len =
+						le16_to_cpu(cmd_aes_ccm->data.
+							    header.len);
+
+					printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_aes_ccm->encdec, cmd_aes_ccm->algorithm, cmd_aes_ccm->key_length, cmd_aes_ccm->nonce_length, cmd_aes_ccm->AAD_length, cmd_aes_ccm->data.header.len);
+
+					hexdump("Key", cmd_aes_ccm->key,
+						cmd_aes_ccm->key_length, ' ');
+					hexdump("Nonce", cmd_aes_ccm->nonce,
+						cmd_aes_ccm->nonce_length, ' ');
+					hexdump("AAD", cmd_aes_ccm->AAD,
+						cmd_aes_ccm->AAD_length, ' ');
+					hexdump("Data", cmd_aes_ccm->data.data,
+						cmd_aes_ccm->data.header.len,
+						' ');
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_AUTO_TX:
+			{
+				HostCmd_DS_802_11_AUTO_TX *at =
+					(HostCmd_DS_802_11_AUTO_TX *)(buf +
+								      S_DS_GEN);
+
+				if (le16_to_cpu(at->action) ==
+				    HostCmd_ACT_GEN_GET) {
+					if (S_DS_GEN + sizeof(at->action) ==
+					    hostcmd->size) {
+						printf("auto_tx not configured\n");
+
+					} else {
+						MrvlIEtypesHeader_t *header =
+							&at->auto_tx.header;
+
+						header->type =
+							le16_to_cpu(header->
+								    type);
+						header->len =
+							le16_to_cpu(header->
+								    len);
+
+						if ((S_DS_GEN +
+						     sizeof(at->action)
+						     +
+						     sizeof(MrvlIEtypesHeader_t)
+						     + header->len ==
+						     hostcmd->size) &&
+						    (header->type ==
+						     TLV_TYPE_AUTO_TX)) {
+
+							AutoTx_MacFrame_t *atmf
+								=
+								&at->auto_tx.
+								auto_tx_mac_frame;
+
+							printf("Interval: %d second(s)\n", le16_to_cpu(atmf->interval));
+							printf("Priority: %#x\n", atmf->priority);
+							printf("Frame Length: %d\n", le16_to_cpu(atmf->frame_len));
+							printf("Dest Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->dest_mac_addr[0], atmf->dest_mac_addr[1], atmf->dest_mac_addr[2], atmf->dest_mac_addr[3], atmf->dest_mac_addr[4], atmf->dest_mac_addr[5]);
+							printf("Src Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->src_mac_addr[0], atmf->src_mac_addr[1], atmf->src_mac_addr[2], atmf->src_mac_addr[3], atmf->src_mac_addr[4], atmf->src_mac_addr[5]);
+
+							hexdump("Frame Payload",
+								atmf->payload,
+								le16_to_cpu
+								(atmf->
+								 frame_len)
+								-
+								MLAN_MAC_ADDR_LENGTH
+								* 2, ' ');
+						} else {
+							printf("incorrect auto_tx command response\n");
+						}
+					}
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
+			{
+				HostCmd_DS_802_11_SUBSCRIBE_EVENT *se =
+					(HostCmd_DS_802_11_SUBSCRIBE_EVENT
+					 *)(buf + S_DS_GEN);
+				if (le16_to_cpu(se->action) ==
+				    HostCmd_ACT_GEN_GET) {
+					int len =
+						S_DS_GEN +
+						sizeof
+						(HostCmd_DS_802_11_SUBSCRIBE_EVENT);
+					printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n");
+					while (len < hostcmd->size) {
+						MrvlIEtypesHeader_t *header =
+							(MrvlIEtypesHeader_t
+							 *)(buf + len);
+						switch (le16_to_cpu
+							(header->type)) {
+						case TLV_TYPE_RSSI_LOW:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*low_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0001) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_SNR_LOW:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*low_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0002) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_FAILCOUNT:
+							{
+								MrvlIEtypes_FailureCount_t
+									*failure_count
+									=
+									(MrvlIEtypes_FailureCount_t
+									 *)(buf
+									    +
+									    len);
+								printf("Failure Count\t%d\t%d\t%s\n", failure_count->fail_value, failure_count->fail_freq, (le16_to_cpu(se->events) & 0x0004) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_BCNMISS:
+							{
+								MrvlIEtypes_BeaconsMissed_t
+									*bcn_missed
+									=
+									(MrvlIEtypes_BeaconsMissed_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon Missed\t%d\tN/A\t%s\n", bcn_missed->beacon_missed, (le16_to_cpu(se->events) & 0x0008) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_RSSI_HIGH:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*high_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Bcn High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0010) ? "yes" : "no");
+								break;
+							}
+
+						case TLV_TYPE_SNR_HIGH:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*high_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0020) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_RSSI_LOW_DATA:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*low_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0040) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_SNR_LOW_DATA:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*low_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0080) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_RSSI_HIGH_DATA:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*high_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0100) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_SNR_HIGH_DATA:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*high_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0200) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_LINK_QUALITY:
+							{
+								MrvlIEtypes_LinkQuality_t
+									*link_qual
+									=
+									(MrvlIEtypes_LinkQuality_t
+									 *)(buf
+									    +
+									    len);
+								printf("Link Quality Parameters:\n");
+								printf("------------------------\n");
+								printf("Link Quality Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0400) ? "yes" : "no");
+								printf("Link SNR Threshold   = %d\n", le16_to_cpu(link_qual->link_SNR_thrs));
+								printf("Link SNR Frequency   = %d\n", le16_to_cpu(link_qual->link_SNR_freq));
+								printf("Min Rate Value       = %d\n", le16_to_cpu(link_qual->min_rate_val));
+								printf("Min Rate Frequency   = %d\n", le16_to_cpu(link_qual->min_rate_freq));
+								printf("Tx Latency Value     = %d\n", le32_to_cpu(link_qual->tx_latency_val));
+								printf("Tx Latency Threshold = %d\n", le32_to_cpu(link_qual->tx_latency_thrs));
+
+								break;
+							}
+						case TLV_TYPE_PRE_BEACON_LOST:
+							{
+								MrvlIEtypes_PreBeaconLost_t
+									*pre_bcn_lost
+									=
+									(MrvlIEtypes_PreBeaconLost_t
+									 *)(buf
+									    +
+									    len);
+								printf("------------------------\n");
+								printf("Pre-Beacon Lost Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0800) ? "yes" : "no");
+								printf("Pre-Beacon Lost: %d\n", pre_bcn_lost->pre_beacon_lost);
+								break;
+							}
+						default:
+							printf("Unknown subscribed event TLV Type=%#x," " Len=%d\n", le16_to_cpu(header->type), le16_to_cpu(header->len));
+							break;
+						}
+
+						len += (sizeof
+							(MrvlIEtypesHeader_t)
+							+
+							le16_to_cpu(header->
+								    len));
+					}
+				}
+				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:
+			{
+				HostCmd_DS_REG *preg =
+					(HostCmd_DS_REG *)(buf + S_DS_GEN);
+				preg->action = le16_to_cpu(preg->action);
+				if (preg->action == HostCmd_ACT_GEN_GET) {
+					preg->value = le32_to_cpu(preg->value);
+					printf("value = 0x%08x\n", preg->value);
+				}
+				break;
+			}
+		case HostCmd_CMD_MEM_ACCESS:
+			{
+				HostCmd_DS_MEM *pmem =
+					(HostCmd_DS_MEM *)(buf + S_DS_GEN);
+				pmem->action = le16_to_cpu(pmem->action);
+				if (pmem->action == HostCmd_ACT_GEN_GET) {
+					pmem->value = le32_to_cpu(pmem->value);
+					printf("value = 0x%08x\n", pmem->value);
+				}
+				break;
+			}
+		default:
+			printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x,"
+			       " SeqNum=%#04x, Result=%#04x\n",
+			       hostcmd->command, hostcmd->size,
+			       hostcmd->seq_num, hostcmd->result);
+			hexdump("payload",
+				(t_void *)(buf + S_DS_GEN),
+				hostcmd->size - S_DS_GEN, ' ');
+			break;
+		}
+	} else {
+		printf("HOSTCMD failed: CmdCode=%#04x, Size=%#04x,"
+		       " SeqNum=%#04x, Result=%#04x\n",
+		       hostcmd->command, hostcmd->size,
+		       hostcmd->seq_num, hostcmd->result);
+	}
+	return ret;
+}
+
+/**
+ *  @brief Prepare ARP filter buffer
+ *  @param fp		File handler
+ *  @param buf		A pointer to the buffer
+ *  @param length	A pointer to the length of buffer
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_arp_filter_buffer(FILE * fp, t_u8 *buf, t_u16 *length)
+{
+	t_s8 line[256], *pos;
+	int ln = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+	int arpfilter_found = 0;
+
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, "arpfilter={") == 0) {
+			arpfilter_found = 1;
+			mlan_get_hostcmd_data(fp, &ln, buf, length);
+			break;
+		}
+	}
+	if (!arpfilter_found) {
+		fprintf(stderr,
+			"mlanconfig: 'arpfilter' not found in conf file");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	return ret;
+}
+
+/**
+ *  @brief Prepare the hostcmd for register access
+ *  @param type     Register type
+ *  @param offset   Register offset
+ *  @param value    Pointer to value (NULL for read)
+ *  @param buf      Pointer to hostcmd buffer
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf)
+{
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_REG *preg;
+
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	switch (type) {
+	case 1:
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_MAC_REG_ACCESS);
+		break;
+	case 2:
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_BBP_REG_ACCESS);
+		break;
+	case 3:
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_RF_REG_ACCESS);
+		break;
+	case 5:
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_CAU_REG_ACCESS);
+		break;
+	default:
+		printf("Invalid register set specified\n");
+		return -EINVAL;
+	}
+	preg = (HostCmd_DS_REG *)(buf + S_DS_GEN);
+	preg->action = (value) ? HostCmd_ACT_GEN_SET : HostCmd_ACT_GEN_GET;
+	preg->action = cpu_to_le16(preg->action);
+	preg->offset = cpu_to_le16((t_u16)offset);
+	if (value)
+		preg->value = cpu_to_le32(*value);
+	else
+		preg->value = 0;
+	hostcmd->size = cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_REG));
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/mlanhostcmd.h b/wlan_sd8897/mapp/mlanconfig/mlanhostcmd.h
new file mode 100644
index 0000000..09d72ab
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/mlanhostcmd.h
@@ -0,0 +1,355 @@
+/** @file  mlanhostcmd.h
+  *
+  * @brief This file contains command structures for mlanconfig application
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     11/26/2008: initial version
+************************************************************************/
+#ifndef _MLANHOSTCMD_H_
+#define _MLANHOSTCMD_H_
+
+/** Find number of elements */
+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
+
+/** MLAN MAC Address Length */
+#define MLAN_MAC_ADDR_LENGTH     (6)
+/** Size of command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER		(2 * 1024)
+
+/** 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 : Clear */
+#define HostCmd_ACT_GEN_CLEAR				0x0004
+/** General purpose action : Remove */
+#define HostCmd_ACT_GEN_REMOVE          0x0004
+
+/** Host Command ID : Memory access */
+#define HostCmd_CMD_MEM_ACCESS                0x0086
+
+/** Pre-Authenticate - 11r only */
+#define HostCmd_CMD_802_11_AUTHENTICATE       0x0011
+
+/** Read/Write Mac register */
+#define HostCmd_CMD_MAC_REG_ACCESS            0x0019
+/** Read/Write BBP register */
+#define HostCmd_CMD_BBP_REG_ACCESS            0x001a
+/** Read/Write RF register */
+#define HostCmd_CMD_RF_REG_ACCESS             0x001b
+/** Get TX Power data */
+#define HostCmd_CMD_802_11_RF_TX_POWER        0x001e
+/** Get the current TSF */
+#define HostCmd_CMD_GET_TSF                   0x0080
+/** Host Command ID : CAU register access */
+#define HostCmd_CMD_CAU_REG_ACCESS            0x00ed
+
+/** Host Command ID : 802.11 BG scan configuration */
+#define HostCmd_CMD_802_11_BG_SCAN_CONFIG     0x006b
+/** Host Command ID : Configuration data */
+#define HostCmd_CMD_CFG_DATA                  0x008f
+/** Host Command ID : 802.11 TPC adapt req */
+#define HostCmd_CMD_802_11_TPC_ADAPT_REQ      0x0060
+/** Host Command ID : 802.11 crypto */
+#define HostCmd_CMD_802_11_CRYPTO             0x0078
+/** Host Command ID : 802.11 auto Tx */
+#define HostCmd_CMD_802_11_AUTO_TX      	0x0082
+
+/** Host Command ID : 802.11 subscribe event */
+#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT       0x0075
+
+/** Host Command ID : Channel TRPC config */
+#define HostCmd_CMD_CHAN_TRPC_CONFIG                0x00fb
+
+/** TLV  type ID definition */
+#define PROPRIETARY_TLV_BASE_ID     0x0100
+/** 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 : 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 : Auto Tx */
+#define TLV_TYPE_AUTO_TX            (PROPRIETARY_TLV_BASE_ID + 0x18)	//0x0118
+/** 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: Pre-Beacon Lost */
+#define TLV_TYPE_PRE_BEACON_LOST    (PROPRIETARY_TLV_BASE_ID + 0x49)	//0x0149
+
+/** TLV type : Channel TRPC */
+#define TLV_TYPE_CHAN_TRPC              (PROPRIETARY_TLV_BASE_ID + 0x89)	//0x0189
+
+/* Define general hostcmd data structure */
+/** HostCmd_DS_GEN */
+typedef struct MAPP_HostCmd_DS_GEN {
+    /** Command */
+	t_u16 command;
+    /** Size */
+	t_u16 size;
+    /** Sequence number */
+	t_u16 seq_num;
+    /** Result */
+	t_u16 result;
+} __ATTRIB_PACK__ HostCmd_DS_GEN;
+
+typedef struct _HostCmd_DS_MEF_CFG {
+    /** Criteria */
+	t_u32 Criteria;
+    /** Number of entries */
+	t_u16 NumEntries;
+} __ATTRIB_PACK__ HostCmd_DS_MEF_CFG;
+
+typedef struct _MEF_CFG_DATA {
+    /** Size */
+	t_u16 size;
+    /** Data */
+	HostCmd_DS_MEF_CFG data;
+} __ATTRIB_PACK__ MEF_CFG_DATA;
+
+/** Size of HostCmd_DS_GEN */
+#define S_DS_GEN    sizeof(HostCmd_DS_GEN)
+
+/** HostCmd_DS_REG */
+typedef struct MAPP_HostCmd_DS_REG {
+    /** Read or write */
+	t_u16 action;
+    /** Register offset */
+	t_u16 offset;
+    /** Value */
+	t_u32 value;
+} __ATTRIB_PACK__ HostCmd_DS_REG;
+
+/** HostCmd_DS_MEM */
+typedef struct MAPP_HostCmd_DS_MEM {
+    /** Read or write */
+	t_u16 action;
+    /** Reserved */
+	t_u16 reserved;
+    /** Address */
+	t_u32 addr;
+    /** Value */
+	t_u32 value;
+} __ATTRIB_PACK__ HostCmd_DS_MEM;
+
+/** HostCmd_DS_802_11_CFG_DATA */
+typedef struct MAPP_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;
+
+/** mlan_ioctl_11h_tpc_resp */
+typedef struct {
+	int status_code;
+		     /**< Firmware command result status code */
+	int tx_power;/**< Reported TX Power from the TPC Report */
+	int link_margin;
+		     /**< Reported Link margin from the TPC Report */
+	int rssi;    /**< RSSI of the received TPC Report frame */
+} __ATTRIB_PACK__ mlan_ioctl_11h_tpc_resp;
+
+/** MrvlIEtypesHeader_t */
+typedef struct MrvlIEtypesHeader {
+    /** Header type */
+	t_u16 type;
+    /** Header length */
+	t_u16 len;
+} __ATTRIB_PACK__ MrvlIEtypesHeader_t;
+
+/** MrvlIEtypes_Data_t */
+typedef struct MrvlIEtypes_Data_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Data */
+	t_u8 data[1];
+} __ATTRIB_PACK__ MrvlIEtypes_Data_t;
+
+/** HostCmd_DS_802_11_CRYPTO */
+typedef struct MAPP_HostCmd_DS_802_11_CRYPTO {
+	t_u16 encdec;	  /**< Decrypt=0, Encrypt=1 */
+	t_u16 algorithm;  /**< RC4=1 AES=2 , AES_KEY_WRAP=3 */
+	t_u16 key_IV_length;/**< Length of Key IV (bytes)   */
+	t_u8 keyIV[32];	  /**< Key IV */
+	t_u16 key_length;  /**< Length of Key (bytes) */
+	t_u8 key[32];	  /**< Key */
+	MrvlIEtypes_Data_t data;   /**< Plain text if encdec=Encrypt, Ciphertext data if encdec=Decrypt*/
+} __ATTRIB_PACK__ HostCmd_DS_802_11_CRYPTO;
+
+/** HostCmd_DS_802_11_CRYPTO_AES_CCM */
+typedef struct MAPP_HostCmd_DS_802_11_CRYPTO_AES_CCM {
+	t_u16 encdec;	  /**< Decrypt=0, Encrypt=1 */
+	t_u16 algorithm;  /**< AES_CCM=4 */
+	t_u16 key_length;  /**< Length of Key (bytes)  */
+	t_u8 key[32];	  /**< Key  */
+	t_u16 nonce_length;/**< Length of Nonce (bytes) */
+	t_u8 nonce[14];	  /**< Nonce */
+	t_u16 AAD_length;  /**< Length of AAD (bytes) */
+	t_u8 AAD[32];	  /**< AAD */
+	MrvlIEtypes_Data_t data;   /**< Plain text if encdec=Encrypt, Ciphertext data if encdec=Decrypt*/
+} __ATTRIB_PACK__ HostCmd_DS_802_11_CRYPTO_AES_CCM;
+
+/** AES CCM cipher test */
+#define CIPHER_TEST_AES_CCM (4)
+/** AutoTx_MacFrame_t */
+typedef struct AutoTx_MacFrame {
+	t_u16 interval;	      /**< in seconds */
+	t_u8 priority;	      /**< User Priority: 0~7, ignored if non-WMM */
+	t_u8 reserved;	      /**< set to 0 */
+	t_u16 frame_len;       /**< Length of MAC frame payload */
+	t_u8 dest_mac_addr[MLAN_MAC_ADDR_LENGTH];	/**< Destination MAC address */
+	t_u8 src_mac_addr[MLAN_MAC_ADDR_LENGTH];	/**< Source MAC address */
+	t_u8 payload[];			  /**< Payload */
+} __ATTRIB_PACK__ AutoTx_MacFrame_t;
+
+/** MrvlIEtypes_AutoTx_t */
+typedef struct MrvlIEtypes_AutoTx {
+	MrvlIEtypesHeader_t header;	    /**< Header */
+	AutoTx_MacFrame_t auto_tx_mac_frame;  /**< Auto Tx MAC frame */
+} __ATTRIB_PACK__ MrvlIEtypes_AutoTx_t;
+
+/** HostCmd_DS_802_11_AUTO_TX */
+typedef struct MAPP_HostCmd_DS_802_11_AUTO_TX {
+    /** Action */
+	t_u16 action;		/* 0 = ACT_GET; 1 = ACT_SET; */
+	MrvlIEtypes_AutoTx_t auto_tx;	 /**< Auto Tx */
+} __ATTRIB_PACK__ HostCmd_DS_802_11_AUTO_TX;
+
+/** HostCmd_DS_802_11_SUBSCRIBE_EVENT */
+typedef struct MAPP_HostCmd_DS_802_11_SUBSCRIBE_EVENT {
+    /** Action */
+	t_u16 action;
+    /** Events */
+	t_u16 events;
+} __ATTRIB_PACK__ HostCmd_DS_802_11_SUBSCRIBE_EVENT;
+
+/** MrvlIEtypes_RssiParamSet_t */
+typedef struct MrvlIEtypes_RssiThreshold {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** RSSI value */
+	t_u8 RSSI_value;
+    /** RSSI frequency */
+	t_u8 RSSI_freq;
+} __ATTRIB_PACK__ MrvlIEtypes_RssiThreshold_t;
+
+/** MrvlIEtypes_SnrThreshold_t */
+typedef struct MrvlIEtypes_SnrThreshold {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** SNR value */
+	t_u8 SNR_value;
+    /** SNR frequency */
+	t_u8 SNR_freq;
+} __ATTRIB_PACK__ MrvlIEtypes_SnrThreshold_t;
+
+/** MrvlIEtypes_FailureCount_t */
+typedef struct MrvlIEtypes_FailureCount {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Failure value */
+	t_u8 fail_value;
+    /** Failure frequency */
+	t_u8 fail_freq;
+} __ATTRIB_PACK__ MrvlIEtypes_FailureCount_t;
+
+/** MrvlIEtypes_BeaconsMissed_t */
+typedef struct MrvlIEtypes_BeaconsMissed {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Number of beacons missed */
+	t_u8 beacon_missed;
+    /** Reserved */
+	t_u8 reserved;
+} __ATTRIB_PACK__ MrvlIEtypes_BeaconsMissed_t;
+
+/** MrvlIEtypes_LinkQuality_t */
+typedef struct MrvlIEtypes_LinkQuality {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Link SNR threshold */
+	t_u16 link_SNR_thrs;
+    /** Link SNR frequency */
+	t_u16 link_SNR_freq;
+    /** Minimum rate value */
+	t_u16 min_rate_val;
+    /** Minimum rate frequency */
+	t_u16 min_rate_freq;
+    /** Tx latency value */
+	t_u32 tx_latency_val;
+    /** Tx latency threshold */
+	t_u32 tx_latency_thrs;
+} __ATTRIB_PACK__ MrvlIEtypes_LinkQuality_t;
+
+/** MrvlIEtypes_PreBeaconLost_t */
+typedef struct MrvlIEtypes_PreBeaconLost {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Pre-Beacon Lost */
+	t_u8 pre_beacon_lost;
+    /** Reserved */
+	t_u8 reserved;
+} __ATTRIB_PACK__ MrvlIEtypes_PreBeaconLost_t;
+
+/* String helper functions */
+/** Convert char to hex integer */
+int hexval(t_s32 chr);
+/** Convert char to hex integer */
+t_u8 hexc2bin(t_s8 chr);
+/** Convert string to hex integer */
+t_u32 a2hex(t_s8 *s);
+/** Check the Hex String */
+int ishexstring(t_s8 *s);
+/** Convert String to integer */
+t_u32 a2hex_or_atoi(t_s8 *value);
+/** Convert String to Integer */
+int atoval(t_s8 *buf);
+/** Hump hex data */
+void hexdump(t_s8 *prompt, void *p, t_s32 len, t_s8 delim);
+/** Convert String to Hex */
+t_s8 *convert2hex(t_s8 *ptr, t_u8 *chr);
+
+int process_host_cmd_resp(t_u8 *buf);
+int prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf);
+int prepare_arp_filter_buffer(FILE * fp, t_u8 *buf, t_u16 *length);
+int prepare_cfg_data_buffer(int argc, char *argv[], FILE * fp, t_u8 *buf);
+int prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf);
+
+#endif /* _MLANHOSTCMD_H_ */
diff --git a/wlan_sd8897/mapp/mlanconfig/mlanmisc.c b/wlan_sd8897/mapp/mlanconfig/mlanmisc.c
new file mode 100644
index 0000000..8d3399f
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/mlanmisc.c
@@ -0,0 +1,1161 @@
+/** @file  mlanmisc.c
+  *
+  * @brief Program to prepare command buffer
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+Change log:
+     03/10/2009: initial version
+************************************************************************/
+
+#include    "mlanconfig.h"
+#include    "mlanhostcmd.h"
+#include    "mlanmisc.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief Helper function for process_getscantable_idx
+ *
+ *  @param pbuf     A pointer to the buffer
+ *  @param buf_len  buffer length
+ *
+ *  @return         NA
+ *
+ */
+static void
+dump_scan_elems(const t_u8 *pbuf, uint buf_len)
+{
+	uint idx;
+	uint marker = 2 + pbuf[1];
+
+	for (idx = 0; idx < buf_len; idx++) {
+		if (idx % 0x10 == 0) {
+			printf("\n%04x: ", idx);
+		}
+
+		if (idx == marker) {
+			printf("|");
+			marker = idx + pbuf[idx + 1] + 2;
+		} else {
+			printf(" ");
+		}
+
+		printf("%02x ", pbuf[idx]);
+	}
+
+	printf("\n");
+}
+
+/**
+ *  @brief Helper function for process_getscantable_idx
+ *  Find next element
+ *
+ *  @param pp_ie_out    pointer of a IEEEtypes_Generic_t structure pointer
+ *  @param p_buf_left   integer pointer, which contains the number of left p_buf
+ *
+ *  @return             MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE
+ */
+static int
+scantable_elem_next(IEEEtypes_Generic_t **pp_ie_out, int *p_buf_left)
+{
+	IEEEtypes_Generic_t *pie_gen;
+	t_u8 *p_next;
+
+	if (*p_buf_left < 2) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pie_gen = *pp_ie_out;
+
+	p_next = (t_u8 *)pie_gen + (pie_gen->ieee_hdr.len
+				    + sizeof(pie_gen->ieee_hdr));
+	*p_buf_left -= (p_next - (t_u8 *)pie_gen);
+
+	*pp_ie_out = (IEEEtypes_Generic_t *)p_next;
+
+	if (*p_buf_left <= 0) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+ /**
+  *  @brief Helper function for process_getscantable_idx
+  *         scantable find element
+  *
+  *  @param ie_buf       pointer of the IE buffer
+  *  @param ie_buf_len   IE buffer length
+  *  @param ie_type      IE type
+  *  @param ppie_out     pointer to the IEEEtypes_Generic_t structure pointer
+  *  @return             MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE
+  */
+static int
+scantable_find_elem(t_u8 *ie_buf,
+		    unsigned int ie_buf_len,
+		    IEEEtypes_ElementId_e ie_type,
+		    IEEEtypes_Generic_t **ppie_out)
+{
+	int found;
+	unsigned int ie_buf_left;
+
+	ie_buf_left = ie_buf_len;
+
+	found = FALSE;
+
+	*ppie_out = (IEEEtypes_Generic_t *)ie_buf;
+
+	do {
+		found = ((*ppie_out)->ieee_hdr.element_id == ie_type);
+
+	} while (!found &&
+		 (scantable_elem_next(ppie_out, (int *)&ie_buf_left) == 0));
+
+	if (!found) {
+		*ppie_out = NULL;
+	}
+
+	return (found ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE);
+}
+
+ /**
+  *  @brief Helper function for process_getscantable_idx
+  *         It gets SSID from IE
+  *
+  *  @param ie_buf       IE buffer
+  *  @param ie_buf_len   IE buffer length
+  *  @param pssid        SSID
+  *  @param ssid_buf_max size of SSID
+  *  @return             MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE
+  */
+static int
+scantable_get_ssid_from_ie(t_u8 *ie_buf,
+			   unsigned int ie_buf_len,
+			   t_u8 *pssid, unsigned int ssid_buf_max)
+{
+	int retval;
+	IEEEtypes_Generic_t *pie_gen;
+
+	retval = scantable_find_elem(ie_buf, ie_buf_len, SSID, &pie_gen);
+
+	memcpy(pssid, pie_gen->data, MIN(pie_gen->ieee_hdr.len, ssid_buf_max));
+
+	return retval;
+}
+
+/**
+ *  @brief Display detailed information for a specific scan table entry
+ *
+ *  @param prsp_info_req    Scan table entry request structure
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_getscantable_idx(wlan_ioctl_get_scan_table_info *prsp_info_req)
+{
+	int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+	t_u8 *pcurrent;
+	int ret = 0;
+	char ssid[33];
+	t_u16 tmp_cap;
+	t_u8 tsf[8];
+	t_u16 beacon_interval;
+	t_u8 *scan_rsp_buf = NULL;
+	t_u16 cap_info;
+	wlan_ioctl_get_scan_table_info *prsp_info;
+
+	wlan_get_scan_table_fixed fixed_fields;
+	t_u32 fixed_field_length;
+	t_u32 bss_info_length;
+
+	scan_rsp_buf = (t_u8 *)malloc(SCAN_RESP_BUF_SIZE);
+	if (scan_rsp_buf == NULL) {
+		printf("Error: allocate memory for scan_rsp_buf failed\n");
+		return -ENOMEM;
+	}
+	memset(ssid, 0x00, sizeof(ssid));
+
+	prsp_info = (wlan_ioctl_get_scan_table_info *)scan_rsp_buf;
+
+	memcpy(prsp_info, prsp_info_req,
+	       sizeof(wlan_ioctl_get_scan_table_info));
+
+	if (get_priv_ioctl("getscantable",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+	/*
+	 * Set up and execute the ioctl call
+	 */
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = (caddr_t) prsp_info;
+	iwr.u.data.length = SCAN_RESP_BUF_SIZE;
+	iwr.u.data.flags = subioctl_val;
+
+	if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+		perror("mlanconfig: getscantable ioctl");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (prsp_info->scan_number == 0) {
+		printf("mlanconfig: getscantable ioctl - index out of range\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	pcurrent = prsp_info->scan_table_entry_buf;
+
+	memcpy((t_u8 *)&fixed_field_length,
+	       (t_u8 *)pcurrent, sizeof(fixed_field_length));
+	pcurrent += sizeof(fixed_field_length);
+
+	memcpy((t_u8 *)&bss_info_length,
+	       (t_u8 *)pcurrent, sizeof(bss_info_length));
+	pcurrent += sizeof(bss_info_length);
+
+	memcpy((t_u8 *)&fixed_fields, (t_u8 *)pcurrent, sizeof(fixed_fields));
+	pcurrent += fixed_field_length;
+
+	/* time stamp is 8 byte long */
+	memcpy(tsf, pcurrent, sizeof(tsf));
+	pcurrent += sizeof(tsf);
+	bss_info_length -= sizeof(tsf);
+
+	/* beacon interval is 2 byte long */
+	memcpy(&beacon_interval, pcurrent, sizeof(beacon_interval));
+	pcurrent += sizeof(beacon_interval);
+	bss_info_length -= sizeof(beacon_interval);
+
+	/* capability information is 2 byte long */
+	memcpy(&cap_info, pcurrent, sizeof(cap_info));
+	pcurrent += sizeof(cap_info);
+	bss_info_length -= sizeof(cap_info);
+
+	scantable_get_ssid_from_ie(pcurrent,
+				   bss_info_length, (t_u8 *)ssid, sizeof(ssid));
+
+	printf("\n*** [%s], %02x:%02x:%02x:%02x:%02x:%2x\n",
+	       ssid,
+	       fixed_fields.bssid[0],
+	       fixed_fields.bssid[1],
+	       fixed_fields.bssid[2],
+	       fixed_fields.bssid[3],
+	       fixed_fields.bssid[4], fixed_fields.bssid[5]);
+	memcpy(&tmp_cap, &cap_info, sizeof(tmp_cap));
+	printf("Channel = %d, SS = %d, CapInfo = 0x%04x, BcnIntvl = %d\n",
+	       fixed_fields.channel,
+	       255 - fixed_fields.rssi, tmp_cap, beacon_interval);
+
+	printf("TSF Values: AP(0x%02x%02x%02x%02x%02x%02x%02x%02x), ",
+	       tsf[7], tsf[6], tsf[5], tsf[4], tsf[3], tsf[2], tsf[1], tsf[0]);
+
+	printf("Network(0x%016llx)\n", fixed_fields.network_tsf);
+	printf("\n");
+	printf("Element Data (%d bytes)\n", (int)bss_info_length);
+	printf("------------");
+	dump_scan_elems(pcurrent, bss_info_length);
+	printf("\n");
+
+done:
+
+	if (scan_rsp_buf)
+		free(scan_rsp_buf);
+
+	return ret;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+/** Maximum SDIO command-52 buffer length */
+#define CMD52_BUF_LEN    3
+
+/**
+ *  @brief SD comand52 read/write
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_sdcmd52rw(int argc, char *argv[])
+{
+	struct iwreq iwr;
+	int ioctl_val, subioctl_val, buf[CMD52_BUF_LEN];
+
+	if (get_priv_ioctl("sdcmd52rw",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	if (argc == 5) {
+		/* CMD52 read */
+		iwr.u.data.length = CMD52_BUF_LEN - 1;
+	} else if (argc == 6) {
+		/* CMD52 write */
+		buf[2] = atoval(argv[5]);	/* data */
+		iwr.u.data.length = CMD52_BUF_LEN;
+	} else {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	buf[0] = atoval(argv[3]);	/* func */
+	buf[1] = atoval(argv[4]);	/* reg */
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.flags = subioctl_val;
+	iwr.u.data.pointer = (caddr_t) buf;
+
+	if (ioctl(sockfd, ioctl_val, &iwr)) {
+		perror("mlanconfig");
+		fprintf(stderr,
+			"mlanconfig: CMD52 R/W not supported by "
+			"interface %s\n", dev_name);
+		return MLAN_STATUS_FAILURE;
+	}
+	printf("sdcmd52rw returns 0x%02X\n", buf[0]);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/** Maximum SDIO command-53 buffer length */
+#define CMD53_BUF_LEN    2000
+
+/**
+ *  @brief SD comand53 read/write
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_sdcmd53rw(int argc, char *argv[])
+{
+	struct iwreq iwr;
+	t_s8 *buf = NULL;
+	int addr, mode, blklen, blknum, i, rw;
+	int ioctl_val, subioctl_val;
+
+	if (get_priv_ioctl("sdcmd53rw",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	if (argc < 8) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (!(buf = malloc(CMD53_BUF_LEN)))
+		return -ENOMEM;
+	memset(buf, 0, CMD53_BUF_LEN);
+
+	if (argc == 8) {
+		rw = buf[0] = 0;	/* CMD53 read */
+	} else {
+		rw = buf[0] = 1;	/* CMD53 write */
+	}
+	buf[1] = atoval(argv[3]);	/* func */
+	addr = atoval(argv[4]);	/* address */
+	buf[2] = addr & 0xff;
+	buf[3] = (addr >> 8) & 0xff;
+	buf[4] = (addr >> 16) & 0xff;
+	buf[5] = (addr >> 24) & 0xff;
+	mode = atoval(argv[5]);	/* mode */
+	buf[6] = (t_u8)mode;
+	blklen = atoval(argv[6]);	/* block size */
+	buf[7] = blklen & 0xff;
+	buf[8] = (blklen >> 8) & 0xff;
+	blknum = atoval(argv[7]);	/* block number or byte number */
+	buf[9] = blknum & 0xff;
+	buf[10] = (blknum >> 8) & 0xff;
+	iwr.u.data.length = 11;
+	if (buf[0]) {
+		for (i = 0; i < (argc - 8); i++)
+			buf[11 + i] = atoval(argv[8 + i]);
+		iwr.u.data.length += (argc - 8);
+	}
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.flags = subioctl_val;
+	iwr.u.data.pointer = (caddr_t) buf;
+
+	if (ioctl(sockfd, ioctl_val, &iwr)) {
+		perror("mlanconfig");
+		fprintf(stderr,
+			"mlanconfig: CMD53 R/W not supported by "
+			"interface %s\n", dev_name);
+		free(buf);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (mode) {
+		fprintf(stderr, "CMD53rw blklen = %d, blknum = %d\n", blklen,
+			blknum);
+	} else {
+		blklen = 1;
+		fprintf(stderr, "CMD53rw bytelen = %d\n", blknum);
+	}
+	if (!rw)
+		hexdump("data", buf, blklen * blknum, ' ');
+
+	free(buf);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Retrieve and display the contents of the driver scan table.
+ *
+ *  The ioctl to retrieve the scan table contents will be invoked, and portions
+ *   of the scan data will be displayed on stdout.  The entire beacon or
+ *   probe response is also retrieved (if available in the driver).  This
+ *   data would be needed in case the application was explicitly controlling
+ *   the association (inserting IEs, TLVs, etc).
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_getscantable(int argc, char *argv[])
+{
+	int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+	t_u8 *scan_rsp_buf = NULL;
+
+	struct wlan_ioctl_get_scan_list *scan_list_head = NULL;
+	struct wlan_ioctl_get_scan_list *scan_list_node = NULL;
+	struct wlan_ioctl_get_scan_list *curr = NULL, *prev = NULL, *next =
+		NULL;
+
+	t_u32 total_scan_res = 0;
+
+	unsigned int scan_start;
+	int idx, ret = 0;
+
+	t_u8 *pcurrent;
+	t_u8 *pnext;
+	IEEEtypes_ElementId_e *pelement_id;
+	t_u8 *pelement_len;
+	int ssid_idx;
+	t_u8 *pbyte;
+	t_u16 new_ss;
+	t_u16 curr_ss;
+
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+	const t_u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
+
+	IEEEtypes_WmmParameter_t *pwmm_ie;
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	IEEEtypes_VendorSpecific_t *pwps_ie;
+	const t_u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 };
+
+	int displayed_info;
+
+	wlan_ioctl_get_scan_table_info rspInfoReq;
+	wlan_ioctl_get_scan_table_info *prsp_info;
+
+	wlan_get_scan_table_fixed fixed_fields;
+	t_u32 fixed_field_length;
+	t_u32 bss_info_length;
+	wlan_ioctl_get_bss_info *bss_info;
+
+	scan_rsp_buf = (t_u8 *)malloc(SCAN_RESP_BUF_SIZE);
+	if (scan_rsp_buf == NULL) {
+		printf("Error: allocate memory for scan_rsp_buf failed\n");
+		return -ENOMEM;
+	}
+	prsp_info = (wlan_ioctl_get_scan_table_info *)scan_rsp_buf;
+
+	if (get_priv_ioctl("getscantable",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+	if (argc > 3 && (strcmp(argv[3], "tsf") != 0)
+	    && (strcmp(argv[3], "help") != 0)) {
+
+		idx = strtol(argv[3], NULL, 10);
+
+		if (idx >= 0) {
+			if (scan_rsp_buf) {
+				free(scan_rsp_buf);
+			}
+			rspInfoReq.scan_number = idx;
+			return process_getscantable_idx(&rspInfoReq);
+		}
+	}
+
+	displayed_info = FALSE;
+	scan_start = 1;
+
+	do {
+		prsp_info->scan_number = scan_start;
+
+		/*
+		 * Set up and execute the ioctl call
+		 */
+		strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+		iwr.u.data.pointer = (caddr_t) prsp_info;
+		iwr.u.data.length = SCAN_RESP_BUF_SIZE;
+		iwr.u.data.flags = subioctl_val;
+
+		if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+			perror("mlanconfig: getscantable ioctl");
+			ret = -EFAULT;
+			goto done;
+		}
+		total_scan_res += prsp_info->scan_number;
+
+		pcurrent = 0;
+		pnext = prsp_info->scan_table_entry_buf;
+
+		for (idx = 0; (unsigned int)idx < prsp_info->scan_number; idx++) {
+
+			/* Alloc memory for new node for next BSS */
+			scan_list_node = (struct wlan_ioctl_get_scan_list *)
+				malloc(sizeof(struct wlan_ioctl_get_scan_list));
+			if (scan_list_node == NULL) {
+				printf("Error: allocate memory for scan_list_head failed\n");
+				return -ENOMEM;
+			}
+			memset(scan_list_node, 0,
+			       sizeof(struct wlan_ioctl_get_scan_list));
+
+			/*
+			 * Set pcurrent to pnext in case pad bytes are at the end
+			 *   of the last IE we processed.
+			 */
+			pcurrent = pnext;
+
+			/* Start extracting each BSS to prepare a linked list */
+			memcpy((t_u8 *)&fixed_field_length,
+			       (t_u8 *)pcurrent, sizeof(fixed_field_length));
+			pcurrent += sizeof(fixed_field_length);
+
+			memcpy((t_u8 *)&bss_info_length,
+			       (t_u8 *)pcurrent, sizeof(bss_info_length));
+			pcurrent += sizeof(bss_info_length);
+
+			memcpy((t_u8 *)&fixed_fields,
+			       (t_u8 *)pcurrent, sizeof(fixed_fields));
+			pcurrent += fixed_field_length;
+
+			scan_list_node->fixed_buf.fixed_field_length =
+				fixed_field_length;
+			scan_list_node->fixed_buf.bss_info_length =
+				bss_info_length;
+			scan_list_node->fixed_buf.fixed_fields = fixed_fields;
+
+			bss_info = &scan_list_node->bss_info_buf;
+
+			/* Set next to be the start of the next scan entry */
+			pnext = pcurrent + bss_info_length;
+
+			if (bss_info_length >=
+			    (sizeof(bss_info->tsf) +
+			     sizeof(bss_info->beacon_interval) +
+			     sizeof(bss_info->cap_info))) {
+
+				/* time stamp is 8 byte long */
+				memcpy(bss_info->tsf, pcurrent,
+				       sizeof(bss_info->tsf));
+				pcurrent += sizeof(bss_info->tsf);
+				bss_info_length -= sizeof(bss_info->tsf);
+
+				/* beacon interval is 2 byte long */
+				memcpy(&bss_info->beacon_interval, pcurrent,
+				       sizeof(bss_info->beacon_interval));
+				pcurrent += sizeof(bss_info->beacon_interval);
+				bss_info_length -=
+					sizeof(bss_info->beacon_interval);
+
+				/* capability information is 2 byte long */
+				memcpy(&bss_info->cap_info, pcurrent,
+				       sizeof(bss_info->cap_info));
+				pcurrent += sizeof(bss_info->cap_info);
+				bss_info_length -= sizeof(bss_info->cap_info);
+			}
+
+			bss_info->wmm_cap = ' ';	/* M (WMM), C (WMM-Call Admission Control) */
+			bss_info->wps_cap = ' ';	/* "S" */
+			bss_info->dot11k_cap = ' ';	/* "K" */
+			bss_info->dot11r_cap = ' ';	/* "R" */
+			bss_info->ht_cap = ' ';	/* "N" */
+
+			/* "P" for Privacy (WEP) since "W" is WPA, and "2" is RSN/WPA2 */
+			bss_info->priv_cap =
+				bss_info->cap_info.privacy ? 'P' : ' ';
+
+			memset(bss_info->ssid, 0, MRVDRV_MAX_SSID_LENGTH + 1);
+			bss_info->ssid_len = 0;
+
+			while (bss_info_length >= 2) {
+				pelement_id = (IEEEtypes_ElementId_e *)pcurrent;
+				pelement_len = pcurrent + 1;
+				pcurrent += 2;
+
+				switch (*pelement_id) {
+
+				case SSID:
+					if (*pelement_len &&
+					    *pelement_len <=
+					    MRVDRV_MAX_SSID_LENGTH) {
+						memcpy(bss_info->ssid, pcurrent,
+						       *pelement_len);
+						bss_info->ssid_len =
+							*pelement_len;
+					}
+					break;
+
+				case WPA_IE:
+					pwpa_ie =
+						(IEEEtypes_VendorSpecific_t *)
+						pelement_id;
+					if ((memcmp
+					     (pwpa_ie->vend_hdr.oui, wpa_oui,
+					      sizeof(pwpa_ie->vend_hdr.oui)) ==
+					     0)
+					    && (pwpa_ie->vend_hdr.oui_type ==
+						wpa_oui[3])) {
+						/* WPA IE found, 'W' for WPA */
+						bss_info->priv_cap = 'W';
+					} else {
+						pwmm_ie =
+							(IEEEtypes_WmmParameter_t
+							 *)pelement_id;
+						if ((memcmp
+						     (pwmm_ie->vend_hdr.oui,
+						      wmm_oui,
+						      sizeof(pwmm_ie->vend_hdr.
+							     oui)) == 0)
+						    && (pwmm_ie->vend_hdr.
+							oui_type ==
+							wmm_oui[3])) {
+							/* Check the subtype: 1 == parameter, 0 == info */
+							if ((pwmm_ie->vend_hdr.
+							     oui_subtype == 1)
+							    && pwmm_ie->
+							    ac_params
+							    [WMM_AC_VO].
+							    aci_aifsn.acm) {
+								/* Call admission on VO; 'C' for CAC */
+								bss_info->
+									wmm_cap
+									= 'C';
+							} else {
+								/* No CAC; 'M' for uh, WMM */
+								bss_info->
+									wmm_cap
+									= 'M';
+							}
+						} else {
+							pwps_ie =
+								(IEEEtypes_VendorSpecific_t
+								 *)pelement_id;
+							if ((memcmp
+							     (pwps_ie->vend_hdr.
+							      oui, wps_oui,
+							      sizeof(pwps_ie->
+								     vend_hdr.
+								     oui)) == 0)
+							    && (pwps_ie->
+								vend_hdr.
+								oui_type ==
+								wps_oui[3])) {
+								bss_info->
+									wps_cap
+									= 'S';
+							}
+						}
+					}
+					break;
+
+				case RSN_IE:
+					/* RSN IE found; '2' for WPA2 (RSN) */
+					bss_info->priv_cap = '2';
+					break;
+				case HT_CAPABILITY:
+					bss_info->ht_cap = 'N';
+					break;
+				case VHT_CAPABILITY:
+					bss_info->vht_cap[0] = 'A';
+					bss_info->vht_cap[1] = 'C';
+					break;
+				default:
+					break;
+				}
+
+				pcurrent += *pelement_len;
+				bss_info_length -= (2 + *pelement_len);
+			}
+
+			/* Create a sorted list of BSS using Insertion Sort.
+			   Sort as per Signal Strength (descending order) */
+			new_ss = 255 - fixed_fields.rssi;
+
+			if (scan_list_head == NULL) {
+				// Node is the first element in the list.
+				scan_list_head = scan_list_node;
+				scan_list_node->next = NULL;
+			} else {
+
+				curr_ss =
+					255 -
+					scan_list_head->fixed_buf.fixed_fields.
+					rssi;
+
+				if (new_ss > curr_ss) {
+					// Insert the node to head of the list
+					scan_list_node->next = scan_list_head;
+					scan_list_head = scan_list_node;
+				} else {
+
+					for (curr = scan_list_head;
+					     curr != NULL; curr = curr->next) {
+
+						curr_ss =
+							255 -
+							curr->fixed_buf.
+							fixed_fields.rssi;
+						if (new_ss > curr_ss) {
+							// Insert the node to current position in list
+							scan_list_node->next =
+								curr;
+							prev->next =
+								scan_list_node;
+							break;
+						}
+						prev = curr;
+					}
+					if (curr == NULL) {
+
+						// Insert the node to tail of the list
+						prev->next = scan_list_node;
+						scan_list_node->next = NULL;
+					}
+				}
+			}
+		}
+
+		scan_start += prsp_info->scan_number;
+	} while (prsp_info->scan_number);
+
+	// Display scan results
+	printf("---------------------------------------");
+	printf("---------------------------------------\n");
+	printf("# | ch  | ss  |       bssid       |   cap    |   SSID \n");
+	printf("---------------------------------------");
+	printf("---------------------------------------\n");
+
+	for (curr = scan_list_head, idx = 0;
+	     (curr != NULL) && ((unsigned int)idx < total_scan_res);
+	     curr = curr->next, idx++) {
+
+		fixed_fields = curr->fixed_buf.fixed_fields;
+		bss_info = &curr->bss_info_buf;
+
+		printf("%02u| %03d | %03d | %02x:%02x:%02x:%02x:%02x:%02x |",
+		       idx,
+		       fixed_fields.channel,
+		       255 - fixed_fields.rssi,
+		       fixed_fields.bssid[0],
+		       fixed_fields.bssid[1],
+		       fixed_fields.bssid[2],
+		       fixed_fields.bssid[3],
+		       fixed_fields.bssid[4], fixed_fields.bssid[5]);
+
+		displayed_info = TRUE;
+
+		/* "A" for Adhoc
+		 * "I" for Infrastructure,
+		 * "D" for DFS (Spectrum Mgmt)
+		 */
+		printf(" %c%c%c%c%c%c%c%c%c%c | ", bss_info->cap_info.ibss ? 'A' : 'I', bss_info->priv_cap,	/* P (WEP), W (WPA), 2 (WPA2) */
+		       bss_info->cap_info.spectrum_mgmt ? 'D' : ' ', bss_info->wmm_cap,	/* M (WMM), C (WMM-Call Admission Control) */
+		       bss_info->dot11k_cap,	/* K */
+		       bss_info->dot11r_cap,	/* R */
+		       bss_info->wps_cap,	/* S */
+		       bss_info->ht_cap,	/* N */
+		       bss_info->vht_cap[0],	/* AC */
+		       bss_info->vht_cap[1]);
+
+		/* Print out the ssid or the hex values if non-printable */
+		for (ssid_idx = 0; ssid_idx < bss_info->ssid_len; ssid_idx++) {
+			if (isprint(bss_info->ssid[ssid_idx])) {
+				printf("%c", bss_info->ssid[ssid_idx]);
+			} else {
+				printf("\\%02x", bss_info->ssid[ssid_idx]);
+			}
+		}
+
+		printf("\n");
+
+		if (argc > 3 && strcmp(argv[3], "tsf") == 0) {
+			/* TSF is a u64, some formatted printing libs have trouble
+			   printing long longs, so cast and dump as bytes */
+			pbyte = (t_u8 *)&fixed_fields.network_tsf;
+			printf("    TSF=%02x%02x%02x%02x%02x%02x%02x%02x\n",
+			       pbyte[7], pbyte[6], pbyte[5], pbyte[4],
+			       pbyte[3], pbyte[2], pbyte[1], pbyte[0]);
+		}
+	}
+
+	if (displayed_info == TRUE) {
+		if (argc > 3 && strcmp(argv[3], "help") == 0) {
+			printf("\n\n"
+			       "Capability Legend (Not all may be supported)\n"
+			       "-----------------\n"
+			       " I [ Infrastructure ]\n"
+			       " A [ Ad-hoc ]\n"
+			       " W [ WPA IE ]\n"
+			       " 2 [ WPA2/RSN IE ]\n"
+			       " M [ WMM IE ]\n"
+			       " C [ Call Admission Control - WMM IE, VO ACM set ]\n"
+			       " D [ Spectrum Management - DFS (11h) ]\n"
+			       " K [ 11k ]\n"
+			       " R [ 11r ]\n"
+			       " S [ WPS ]\n"
+			       " N [ HT (11n) ]\n"
+			       " AC [VHT (11ac) ]\n" "\n\n");
+		}
+	} else {
+		printf("< No Scan Results >\n");
+	}
+
+done:
+	if (scan_rsp_buf)
+		free(scan_rsp_buf);
+	for (curr = scan_list_head; curr != NULL; curr = next) {
+		next = curr->next;
+		free(curr);
+	}
+	return ret;
+}
+
+/** Maximum channel scratch */
+#define MAX_CHAN_SCRATCH  100
+
+/** Maximum channel number for b/g band */
+#define MAX_CHAN_BG_BAND  14
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES        4
+
+/** Scan all the channels in specified band */
+#define BAND_SPECIFIED    0x80
+/**
+ *  @brief Request a scan from the driver and display the scan table afterwards
+ *
+ *  Command line interface for performing a specific immediate scan based
+ *    on the following keyword parsing:
+ *
+ *     chan=[chan#][band][mode] where band is [a,b,g,n] and mode is
+ *                              blank for active or 'p' for passive
+ *     bssid=xx:xx:xx:xx:xx:xx  specify a BSSID filter for the scan
+ *     ssid="[SSID]"            specify a SSID filter for the scan
+ *     keep=[0 or 1]            keep the previous scan results (1), discard (0)
+ *     dur=[scan time]          time to scan for each channel in milliseconds
+ *     probes=[#]               number of probe requests to send on each chan
+ *     type=[1,2,3]             BSS type: 1 (Infra), 2(Adhoc), 3(Any)
+ *
+ *  Any combination of the above arguments can be supplied on the command line.
+ *    If the chan token is absent, a full channel scan will be completed by
+ *    the driver.  If the dur or probes tokens are absent, the drivers default
+ *    setting will be used.  The bssid and ssid fields, if blank,
+ *    will produce an unfiltered scan. The type field will default to 3 (Any)
+ *    and the keep field will default to 0 (Discard).
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_setuserscan(int argc, char *argv[])
+{
+	wlan_ioctl_user_scan_cfg scan_req;
+	int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+	char *parg_tok;
+	char *pchan_tok;
+	char *parg_cookie;
+	char *pchan_cookie;
+	int arg_idx;
+	int chan_parse_idx;
+	int chan_cmd_idx;
+	char chan_scratch[MAX_CHAN_SCRATCH];
+	char *pscratch;
+	int tmp_idx;
+	int scan_time;
+	int num_ssid;
+	int is_radio_set;
+	unsigned int mac[ETH_ALEN];
+
+	memset(&scan_req, 0x00, sizeof(scan_req));
+	chan_cmd_idx = 0;
+	scan_time = 0;
+	num_ssid = 0;
+
+	if (get_priv_ioctl("setuserscan",
+			   &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+	}
+
+	for (arg_idx = 0; arg_idx < argc; arg_idx++) {
+
+		if (strncmp(argv[arg_idx], "ssid=", strlen("ssid=")) == 0) {
+			/*
+			 *  "ssid" token string handler
+			 */
+			if (num_ssid < MRVDRV_MAX_SSID_LIST_LENGTH) {
+				strncpy(scan_req.ssid_list[num_ssid].ssid,
+					argv[arg_idx] + strlen("ssid="),
+					sizeof(scan_req.ssid_list[num_ssid].
+					       ssid));
+
+				scan_req.ssid_list[num_ssid].max_len = 0;
+
+				num_ssid++;
+			}
+		} else if (strncmp(argv[arg_idx], "bssid=", strlen("bssid=")) ==
+			   0) {
+			/*
+			 *  "bssid" token string handler
+			 */
+			sscanf(argv[arg_idx] + strlen("bssid="),
+			       "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1,
+			       mac + 2, mac + 3, mac + 4, mac + 5);
+
+			for (tmp_idx = 0;
+			     (unsigned int)tmp_idx < NELEMENTS(mac);
+			     tmp_idx++) {
+				scan_req.specific_bssid[tmp_idx] =
+					(t_u8)mac[tmp_idx];
+			}
+		} else if (strncmp(argv[arg_idx], "chan=", strlen("chan=")) ==
+			   0) {
+			/*
+			 *  "chan" token string handler
+			 */
+			parg_tok = argv[arg_idx] + strlen("chan=");
+
+			if (strlen(parg_tok) > MAX_CHAN_SCRATCH) {
+				printf("Error: Specified channels exceeds max limit\n");
+				return MLAN_STATUS_FAILURE;
+			}
+			is_radio_set = FALSE;
+
+			while ((parg_tok =
+				strtok_r(parg_tok, ",",
+					 &parg_cookie)) != NULL) {
+
+				memset(chan_scratch, 0x00,
+				       sizeof(chan_scratch));
+				pscratch = chan_scratch;
+
+				for (chan_parse_idx = 0;
+				     (unsigned int)chan_parse_idx <
+				     strlen(parg_tok); chan_parse_idx++) {
+					if (isalpha
+					    (*(parg_tok + chan_parse_idx))) {
+						*pscratch++ = ' ';
+					}
+
+					*pscratch++ =
+						*(parg_tok + chan_parse_idx);
+				}
+				*pscratch = 0;
+				parg_tok = NULL;
+
+				pchan_tok = chan_scratch;
+
+				while ((pchan_tok = strtok_r(pchan_tok, " ",
+							     &pchan_cookie)) !=
+				       NULL) {
+					if (isdigit(*pchan_tok)) {
+						scan_req.
+							chan_list[chan_cmd_idx].
+							chan_number =
+							atoi(pchan_tok);
+						if (scan_req.
+						    chan_list[chan_cmd_idx].
+						    chan_number >
+						    MAX_CHAN_BG_BAND)
+							scan_req.
+								chan_list
+								[chan_cmd_idx].
+								radio_type = 1;
+					} else {
+						switch (toupper(*pchan_tok)) {
+						case 'A':
+							scan_req.
+								chan_list
+								[chan_cmd_idx].
+								radio_type = 1;
+							is_radio_set = TRUE;
+							break;
+						case 'B':
+						case 'G':
+							scan_req.
+								chan_list
+								[chan_cmd_idx].
+								radio_type = 0;
+							is_radio_set = TRUE;
+							break;
+						case 'N':
+							break;
+						case 'P':
+							scan_req.
+								chan_list
+								[chan_cmd_idx].
+								scan_type =
+								MLAN_SCAN_TYPE_PASSIVE;
+							break;
+						default:
+							printf("Error: Band type not supported!\n");
+							return -EOPNOTSUPP;
+						}
+						if (!chan_cmd_idx &&
+						    !scan_req.
+						    chan_list[chan_cmd_idx].
+						    chan_number && is_radio_set)
+							scan_req.
+								chan_list
+								[chan_cmd_idx].
+								radio_type |=
+								BAND_SPECIFIED;
+					}
+					pchan_tok = NULL;
+				}
+				chan_cmd_idx++;
+			}
+		} else if (strncmp(argv[arg_idx], "keep=", strlen("keep=")) ==
+			   0) {
+			/*
+			 *  "keep" token string handler
+			 */
+			scan_req.keep_previous_scan =
+				atoi(argv[arg_idx] + strlen("keep="));
+		} else if (strncmp(argv[arg_idx], "dur=", strlen("dur=")) == 0) {
+			/*
+			 *  "dur" token string handler
+			 */
+			scan_time = atoi(argv[arg_idx] + strlen("dur="));
+			scan_req.chan_list[0].scan_time = scan_time;
+
+		} else if (strncmp(argv[arg_idx], "wc=", strlen("wc=")) == 0) {
+
+			if (num_ssid < MRVDRV_MAX_SSID_LIST_LENGTH) {
+				/*
+				 *  "wc" token string handler
+				 */
+				pscratch = strrchr(argv[arg_idx], ',');
+
+				if (pscratch) {
+					*pscratch = 0;
+					pscratch++;
+
+					if (isdigit(*pscratch)) {
+						scan_req.ssid_list[num_ssid].
+							max_len =
+							atoi(pscratch);
+					} else {
+						scan_req.ssid_list[num_ssid].
+							max_len = *pscratch;
+					}
+				} else {
+					/* Standard wildcard matching */
+					scan_req.ssid_list[num_ssid].max_len =
+						0xFF;
+				}
+
+				strncpy(scan_req.ssid_list[num_ssid].ssid,
+					argv[arg_idx] + strlen("wc="),
+					sizeof(scan_req.ssid_list[num_ssid].
+					       ssid));
+
+				num_ssid++;
+			}
+		} else if (strncmp(argv[arg_idx], "probes=", strlen("probes="))
+			   == 0) {
+			/*
+			 *  "probes" token string handler
+			 */
+			scan_req.num_probes =
+				atoi(argv[arg_idx] + strlen("probes="));
+			if (scan_req.num_probes > MAX_PROBES) {
+				fprintf(stderr, "Invalid probes (> %d)\n",
+					MAX_PROBES);
+				return -EOPNOTSUPP;
+			}
+		} else if (strncmp(argv[arg_idx], "type=", strlen("type=")) ==
+			   0) {
+			/*
+			 *  "type" token string handler
+			 */
+			scan_req.bss_mode =
+				atoi(argv[arg_idx] + strlen("type="));
+			switch (scan_req.bss_mode) {
+			case MLAN_SCAN_MODE_BSS:
+			case MLAN_SCAN_MODE_IBSS:
+				break;
+			case MLAN_SCAN_MODE_ANY:
+			default:
+				/* Set any unknown types to ANY */
+				scan_req.bss_mode = MLAN_SCAN_MODE_ANY;
+				break;
+			}
+		}
+	}
+
+	/*
+	 * Update all the channels to have the same scan time
+	 */
+	for (tmp_idx = 1; tmp_idx < chan_cmd_idx; tmp_idx++) {
+		scan_req.chan_list[tmp_idx].scan_time = scan_time;
+	}
+
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ - 1);
+	iwr.u.data.pointer = (caddr_t) & scan_req;
+	iwr.u.data.length = sizeof(scan_req);
+	iwr.u.data.flags = subioctl_val;
+
+	if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+		perror("mlanconfig: setuserscan ioctl");
+		return -EFAULT;
+	}
+
+	process_getscantable(0, 0);
+
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/wlan_sd8897/mapp/mlanconfig/mlanmisc.h b/wlan_sd8897/mapp/mlanconfig/mlanmisc.h
new file mode 100644
index 0000000..076ce6b
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanconfig/mlanmisc.h
@@ -0,0 +1,683 @@
+/** @file  mlanmisc.h
+  *
+  * @brief This file contains command definitions for application
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     03/10/2009: initial version
+************************************************************************/
+
+#ifndef _MLANMISC_H_
+#define _MLANMISC_H_
+
+/** Maximum size of IEEE Information Elements */
+#define IEEE_MAX_IE_SIZE  256
+
+/** Maximum scan response buffer size */
+#define SCAN_RESP_BUF_SIZE 2000
+
+#ifdef FALSE
+#undef FALSE
+#endif
+
+#ifdef TRUE
+#undef TRUE
+#endif
+
+#ifndef MIN
+/** Find minimum value */
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+#ifndef MAX
+/** Find maximum value */
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif /* MAX */
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} __ATTRIB_PACK__ mlan_wmm_ac_e;
+
+/** Maximum length of SSID */
+#define MRVDRV_MAX_SSID_LENGTH          32
+
+/** Enumeration for scan mode */
+enum {
+	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_UNCHANGED = 0,
+	MLAN_SCAN_TYPE_ACTIVE,
+	MLAN_SCAN_TYPE_PASSIVE
+};
+
+/** Length of ethernet address */
+#ifndef ETH_ALEN
+#define ETH_ALEN            6
+#endif
+/** Maximum length of SSID list */
+#define MRVDRV_MAX_SSID_LIST_LENGTH         10
+
+/** Maximum number of channels that can be sent in a setuserscan ioctl */
+#define WLAN_IOCTL_USER_SCAN_CHAN_MAX  50
+
+/** IEEE Type definitions  */
+typedef 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,
+	SUPPORTED_CHANNELS = 36,
+	CHANNEL_SWITCH_ANN = 37,
+	QUIET = 40,
+	IBSS_DFS = 41,
+	HT_CAPABILITY = 45,
+	HT_OPERATION = 61,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	EXT_CAPABILITY = 127,
+
+	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,
+
+	ERP_INFO = 42,
+	EXTENDED_SUPPORTED_RATES = 50,
+
+	VENDOR_SPECIFIC_221 = 221,
+	WMM_IE = VENDOR_SPECIFIC_221,
+
+	WPS_IE = VENDOR_SPECIFIC_221,
+
+	WPA_IE = VENDOR_SPECIFIC_221,
+	RSN_IE = 48,
+} __ATTRIB_PACK__ IEEEtypes_ElementId_e;
+
+/** Capability Bit Map*/
+#ifdef BIG_ENDIAN_SUPPORT
+typedef struct _IEEEtypes_CapInfo_t {
+	t_u8 rsrvd1:2;
+	t_u8 dsss_ofdm:1;
+	t_u8 rsvrd2:2;
+	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;
+} __ATTRIB_PACK__ IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#else
+typedef 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;
+} __ATTRIB_PACK__ IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** IEEE IE header */
+typedef struct _IEEEtypes_Header_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+} __ATTRIB_PACK__ IEEEtypes_Header_t, *pIEEEtypes_Header_t;
+
+/** IEEE IE header */
+#define IEEE_HEADER_LEN   sizeof(IEEEtypes_Header_t)
+
+/** Vendor specific IE header */
+typedef 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;
+} __ATTRIB_PACK__ IEEEtypes_VendorHeader_t, *pIEEEtypes_VendorHeader_t;
+
+/** Vendor specific IE */
+typedef 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)];
+} __ATTRIB_PACK__ IEEEtypes_VendorSpecific_t, *pIEEEtypes_VendorSpecific_t;
+
+/** IEEE IE */
+typedef 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)];
+} __ATTRIB_PACK__ IEEEtypes_Generic_t, *pIEEEtypes_Generic_t;
+
+/** Size of a TSPEC.  Used to allocate necessary buffer space in commands */
+#define WMM_TSPEC_SIZE              63
+
+/** Maximum number of AC QOS queues available in the driver/firmware */
+#define MAX_AC_QUEUES               4
+
+/** Maximum number of User Priorities */
+#define MAX_USER_PRIORITIES         8
+
+/** Extra IE bytes allocated in messages for appended IEs after a TSPEC */
+#define WMM_ADDTS_EXTRA_IE_BYTES    256
+
+/**
+ *  @brief Enumeration for the command result from an ADDTS or DELTS command
+ */
+typedef enum {
+	TSPEC_RESULT_SUCCESS = 0,
+	TSPEC_RESULT_EXEC_FAILURE = 1,
+	TSPEC_RESULT_TIMEOUT = 2,
+	TSPEC_RESULT_DATA_INVALID = 3,
+} __ATTRIB_PACK__ mlan_wmm_tspec_result_e;
+
+/**
+ *  @brief Enumeration for the action field in the Queue configure command
+ */
+typedef enum {
+	WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+
+	WMM_QUEUE_CONFIG_ACTION_MAX
+} __ATTRIB_PACK__ mlan_wmm_queue_config_action_e;
+
+/**
+ *   @brief Enumeration for the action field in the queue stats command
+ */
+typedef enum {
+	WMM_STATS_ACTION_START = 0,
+	WMM_STATS_ACTION_STOP = 1,
+	WMM_STATS_ACTION_GET_CLR = 2,
+	WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+
+	WMM_STATS_ACTION_MAX
+} __ATTRIB_PACK__ mlan_wmm_stats_action_e;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef 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
+} __ATTRIB_PACK__ IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef 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
+} __ATTRIB_PACK__ IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn;  /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;		    /**< Ecw */
+	t_u16 tx_op_limit;		    /**< Tx op limit */
+} __ATTRIB_PACK__ IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef 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;
+
+} __ATTRIB_PACK__ IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef 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];
+
+} __ATTRIB_PACK__ IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/**
+ *  @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 wlan_wmm_addts_req_ioctl
+ */
+typedef struct {
+	mlan_wmm_tspec_result_e commandResult;
+					   /**< Firmware execution result */
+
+	t_u32 timeout_ms;		/**< Timeout value in milliseconds */
+	t_u8 ieeeStatusCode;		/**< IEEE status code */
+
+	t_u32 ieDataLen;
+	t_u8 ieData[WMM_TSPEC_SIZE
+				 /**< TSPEC to send in the ADDTS */
+		    + WMM_ADDTS_EXTRA_IE_BYTES];
+					     /**< ADDTS 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 wlan_wmm_delts_req_ioctl
+ */
+typedef struct {
+	mlan_wmm_tspec_result_e commandResult;
+					    /**< Firmware execution result */
+	t_u8 ieeeReasonCode;	  /**< IEEE reason code sent, unused for WMM */
+
+	t_u32 ieDataLen;
+	t_u8 ieData[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.
+ *
+ *  - msduLifetimeExpiry is ignored if set to 0 on a set command
+ *
+ *  @sa wlan_wmm_queue_config_ioctl
+ */
+typedef struct {
+	mlan_wmm_queue_config_action_e action;
+					   /**< Set, Get, or Default */
+	mlan_wmm_ac_e accessCategory;	   /**< WMM_AC_BK(0) to WMM_AC_VO(3) */
+	t_u16 msduLifetimeExpiry;	   /**< lifetime expiry in TUs */
+	t_u8 supportedRates[10];	   /**< Not supported yet */
+} wlan_ioctl_wmm_queue_config_t;
+
+/** Number of bins in the histogram for the HostCmd_DS_WMM_QUEUE_STATS */
+#define WMM_STATS_PKTS_HIST_BINS  7
+
+/**
+ *  @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 wlan_wmm_queue_stats_ioctl
+ */
+typedef struct {
+	mlan_wmm_stats_action_e action;
+				     /**< Start, Stop, or Get  */
+	t_u8 userPriority;
+			 /**< User Priority (0 to 7) */
+	t_u16 pktCount;	 /**< Number of successful packets transmitted */
+	t_u16 pktLoss;	 /**< Packets lost; not included in pktCount   */
+	t_u32 avgQueueDelay;
+			 /**< Average Queue delay in microseconds */
+	t_u32 avgTxDelay;/**< Average Transmission delay in microseconds */
+	t_u16 usedTime;	 /**< Calculated used time - units of 32 microsec */
+	t_u16 policedTime;
+			 /**< Calculated 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 delayHistogram[WMM_STATS_PKTS_HIST_BINS];
+} wlan_ioctl_wmm_queue_stats_t;
+
+/**
+ *  @brief IOCTL and command sub structure for a Traffic stream status.
+ */
+typedef struct {
+	t_u8 tid;	    /**< TSID: Range: 0->7 */
+	t_u8 valid;	    /**< TSID specified is valid  */
+	t_u8 accessCategory;/**< AC TSID is active on */
+	t_u8 userPriority;  /**< UP specified for the TSID */
+
+	t_u8 psb;	    /**< Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 flowDir;	    /**< Upstream (0), Downlink(1), Bidirectional(3) */
+	t_u16 mediumTime;   /**< Medium time granted for the TSID */
+} __ATTRIB_PACK__ HostCmd_DS_WMM_TS_STATUS,
+	wlan_ioctl_wmm_ts_status_t, wlan_cmd_wmm_ts_status_t;
+
+/**
+ *  @brief IOCTL sub structure for a specific WMM AC Status
+ */
+typedef struct {
+    /** WMM Acm */
+	t_u8 wmmAcm;
+    /** Flow required flag */
+	t_u8 flowRequired;
+    /** Flow created flag */
+	t_u8 flowCreated;
+    /** Disabled flag */
+	t_u8 disabled;
+    /** delivery enabled */
+	t_u8 deliveryEnabled;
+    /** trigger enabled */
+	t_u8 triggerEnabled;
+} 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 wlan_wmm_queue_status_ioctl
+ */
+typedef struct {
+    /** WMM AC queue status */
+	wlan_ioctl_wmm_queue_status_ac_t acStatus[MAX_AC_QUEUES];
+} wlan_ioctl_wmm_queue_status_t;
+
+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;
+    /** TSF value from the firmware at packet reception */
+	t_u64 network_tsf;
+} wlan_get_scan_table_fixed;
+
+/**
+ *  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[1]; */
+} wlan_ioctl_get_scan_table_entry;
+
+/**
+ *  Structure to store BSS info (probe resp or beacon) & IEEE IE info for each
+ *  BSS returned in WLAN_GET_SCAN_RESP IOCTL
+ */
+typedef struct _wlan_ioctl_get_bss_info {
+	/**
+	 *  Length of the BSS Information (probe resp or beacon) that
+	 *    follows after the fixed_field
+	 */
+	t_u32 bss_info_length;
+
+	/**
+	 *  Probe response or beacon scanned for the BSS.
+	 *
+	 *  Field layout:
+	 */
+	/** TSF              8 octets */
+	t_u8 tsf[8];
+	/** Beacon Interval  2 octets */
+	t_u16 beacon_interval;
+	/** Capability Info  2 octets */
+	IEEEtypes_CapInfo_t cap_info;
+
+	/**
+	 *  IEEE Infomation Elements; variable number & length per 802.11 spec
+	 */
+	/** SSID */
+	char ssid[MRVDRV_MAX_SSID_LENGTH + 1];
+	/** SSID Length */
+	t_u32 ssid_len;
+	/** WMM Capability */
+	char wmm_cap;
+	/** WPS Capability */
+	char wps_cap;
+	/** Privacy Capability - WEP/WPA/RSN */
+	char priv_cap;
+	/** HT (11N) Capability */
+	char ht_cap;
+	/** VHT (11AC) Capability */
+	char vht_cap[2];
+	/* 802.11k Capability */
+	char dot11k_cap;
+	/** 802.11r Capability */
+	char dot11r_cap;
+} wlan_ioctl_get_bss_info;
+
+/**
+ *  Structure to save of scan table info for each BSS returned
+ * in WLAN_GET_SCAN_RESP IOCTL
+ */
+struct wlan_ioctl_get_scan_list {
+	/** fixed info */
+	wlan_ioctl_get_scan_table_entry fixed_buf;
+	/** variable info - BSS info (probe resp or beacon) & IEEE IE info */
+	wlan_ioctl_get_bss_info bss_info_buf;
+	/** pointer to next node in list */
+	struct wlan_ioctl_get_scan_list *next;
+};
+
+/**
+ *  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;
+
+typedef struct {
+	t_u8 chan_number;
+		       /**< Channel Number to scan */
+	t_u8 radio_type;
+		       /**< Radio type: 'B/G' Band = 0, 'A' Band = 1 */
+	t_u8 scan_type;/**< Scan type: Active = 1, Passive = 2 */
+	t_u8 reserved;/**< Reserved */
+	t_u32 scan_time;
+		       /**< Scan duration in milliseconds; if 0 default used */
+} __ATTRIB_PACK__ wlan_ioctl_user_scan_chan;
+
+typedef struct {
+	char ssid[MRVDRV_MAX_SSID_LENGTH + 1];
+					    /**< SSID */
+	t_u8 max_len;			       /**< Maximum length of SSID */
+} __ATTRIB_PACK__ wlan_ioctl_user_scan_ssid;
+
+typedef struct {
+
+    /** Flag set to keep the previous scan table intact */
+	t_u8 keep_previous_scan;	/* Do not erase the existing scan results */
+
+    /** BSS mode to be sent in the firmware command */
+	t_u8 bss_mode;
+
+    /** Configure the number of probe requests for active chan scans */
+	t_u8 num_probes;
+
+    /** Reserved */
+	t_u8 reserved;
+
+    /** BSSID filter sent in the firmware command to limit the results */
+	t_u8 specific_bssid[ETH_ALEN];
+
+    /** SSID filter list used in the to limit the scan results */
+	wlan_ioctl_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH];
+
+    /** Variable number (fixed maximum) of channels to scan up */
+	wlan_ioctl_user_scan_chan chan_list[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
+
+} __ATTRIB_PACK__ wlan_ioctl_user_scan_cfg;
+
+int process_sdcmd52rw(int argc, char *argv[]);
+int process_sdcmd53rw(int argc, char *argv[]);
+int process_setuserscan(int argc, char *argv[]);
+int process_getscantable(int argc, char *argv[]);
+int process_getscantable_idx(wlan_ioctl_get_scan_table_info *prsp_info_req);
+
+#endif /* _MLANMISC_H_ */
diff --git a/wlan_sd8897/mapp/mlanevent/Makefile b/wlan_sd8897/mapp/mlanevent/Makefile
new file mode 100644
index 0000000..ae2a463
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanevent/Makefile
@@ -0,0 +1,51 @@
+# File : mlanevent/Makefile
+#
+# Copyright (C) 2008-2017, Marvell International Ltd. All Rights Reserved
+
+# Path to the top directory of the wlan distribution
+PATH_TO_TOP = ../..
+
+# Determine how we should copy things to the install directory
+ABSPATH := $(filter /%, $(INSTALLDIR))
+RELPATH := $(filter-out /%, $(INSTALLDIR))
+INSTALLPATH := $(ABSPATH)
+ifeq ($(strip $(INSTALLPATH)),)
+INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH)
+endif
+
+# Override CFLAGS for application sources, remove __ kernel namespace defines
+CFLAGS := $(filter-out -D__%, $(ccflags-y))
+# remove KERNEL include dir
+CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS))
+
+
+#CFLAGS += -DAP22 -fshort-enums
+CFLAGS += -Wall
+#ECHO = @
+LIBS = -lrt
+
+.PHONY: default tags all
+
+OBJECTS = mlanevent.o
+HEADERS = mlanevent.h
+
+TARGET = mlanevent.exe
+
+build default: $(TARGET)
+	@cp -f $(TARGET) $(INSTALLPATH)
+
+all : tags default
+
+$(TARGET): $(OBJECTS) $(HEADERS)
+	$(ECHO)$(CC) $(LIBS) -o $@ $(OBJECTS)
+
+%.o: %.c $(HEADERS)
+	$(ECHO)$(CC) $(CFLAGS) -c -o $@ $<
+
+tags:
+	ctags -R -f tags.txt
+
+distclean clean:
+	$(ECHO)$(RM) $(OBJECTS) $(TARGET)
+	$(ECHO)$(RM) tags.txt
+
diff --git a/wlan_sd8897/mapp/mlanevent/mlanevent.c b/wlan_sd8897/mapp/mlanevent/mlanevent.c
new file mode 100644
index 0000000..5397f54
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanevent/mlanevent.c
@@ -0,0 +1,2716 @@
+/** @file  mlanevent.c
+ *
+ *  @brief Program to receive events from the driver/firmware of the uAP
+ *         driver.
+ *
+ *  Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available along with the File in the gpl.txt file or by writing to
+ *  the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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/18/08: Initial creation
+****************************************************************************/
+
+/****************************************************************************
+        Header files
+****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/time.h>
+#include <getopt.h>
+
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/if.h>
+#include "mlanevent.h"
+#ifdef WIFI_DIRECT_SUPPORT
+#include <arpa/inet.h>
+#endif
+
+/****************************************************************************
+        Definitions
+****************************************************************************/
+/** Enable or disable debug outputs */
+#define DEBUG   0
+
+/****************************************************************************
+        Global variables
+****************************************************************************/
+/** Termination flag */
+int terminate_flag = 0;
+
+/****************************************************************************
+        Local functions
+****************************************************************************/
+/**
+ *  @brief Signal handler
+ *
+ *  @param sig      Received signal number
+ *  @return         N/A
+ */
+void
+sig_handler(int sig)
+{
+	printf("Stopping application.\n");
+#if DEBUG
+	printf("Process ID of process killed = %d\n", getpid());
+#endif
+	terminate_flag = 1;
+}
+
+/**
+ *  @brief Dump hex data
+ *
+ *  @param p        A pointer to data buffer
+ *  @param len      The len of data buffer
+ *  @param delim    Deliminator character
+ *  @return         Hex integer
+ */
+static void
+hexdump(void *p, t_s32 len, char delim)
+{
+	t_s32 i;
+	t_u8 *s = p;
+	for (i = 0; i < len; i++) {
+		if (i != len - 1)
+			printf("%02x%c", *s++, delim);
+		else
+			printf("%02x\n", *s);
+		if ((i + 1) % 16 == 0)
+			printf("\n");
+	}
+}
+
+/**
+ *  @brief      Hex to number
+ *
+ *  @param c    Hex value
+ *  @return     Integer value or -1
+ */
+int
+hex2num(char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+
+	return -1;
+}
+
+/**
+ *  @brief      Check hex string
+ *
+ *  @param hex      A pointer to hex string
+ *  @return         0 or MLAN_EVENT_FAILURE
+ */
+int
+ishexstring(void *hex)
+{
+	int i, a;
+	char *p = hex;
+	int len = strlen(p);
+	if (!strncasecmp("0x", p, 2)) {
+		p += 2;
+		len -= 2;
+	}
+	for (i = 0; i < len; i++) {
+		a = hex2num(*p);
+		if (a < 0)
+			return MLAN_EVENT_FAILURE;
+		p++;
+	}
+	return 0;
+}
+
+/**
+ *    @brief Convert char to hex integer
+ *
+ *    @param chr          Char
+ *    @return             Hex integer
+ */
+unsigned char
+hexc2bin(char chr)
+{
+	if (chr >= '0' && chr <= '9')
+		chr -= '0';
+	else if (chr >= 'A' && chr <= 'F')
+		chr -= ('A' - 10);
+	else if (chr >= 'a' && chr <= 'f')
+		chr -= ('a' - 10);
+
+	return chr;
+}
+
+/**
+ *    @brief Convert string to hex integer
+ *
+ *    @param s            A pointer string buffer
+ *    @return             Hex integer
+ */
+unsigned int
+a2hex(char *s)
+{
+	unsigned int val = 0;
+	if (!strncasecmp("0x", s, 2)) {
+		s += 2;
+	}
+	while (*s && isxdigit(*s)) {
+		val = (val << 4) + hexc2bin(*s++);
+	}
+	return val;
+}
+
+/**
+ *  @brief Prints a MAC address in colon separated form from raw data
+ *
+ *  @param raw      A pointer to the hex data buffer
+ *  @return         N/A
+ */
+void
+print_mac(t_u8 *raw)
+{
+	printf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)raw[0],
+	       (unsigned int)raw[1], (unsigned int)raw[2], (unsigned int)raw[3],
+	       (unsigned int)raw[4], (unsigned int)raw[5]);
+	return;
+}
+
+/**
+ *  @brief Print usage information
+ *
+ *  @return         N/A
+ */
+void
+print_usage(void)
+{
+	printf("\n");
+	printf("Usage : mlanevent.exe [-v] [-h]\n");
+	printf("    -v               : Print version information\n");
+	printf("    -h               : Print help information\n");
+	printf("    -i               : Specify device number from 0 to %d\n",
+	       MAX_NO_OF_DEVICES - 1);
+	printf("                       0xff for all devices\n");
+	printf("\n");
+}
+
+/**
+ *  @brief Parse and print STA deauthentication event data
+ *
+ *  @param buffer   Pointer to received event buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_event_sta_deauth(t_u8 *buffer, t_u16 size)
+{
+	eventbuf_sta_deauth *event_body = NULL;
+
+	if (size < sizeof(eventbuf_sta_deauth)) {
+		printf("ERR:Event buffer too small!\n");
+		return;
+	}
+	event_body = (eventbuf_sta_deauth *)buffer;
+	event_body->reason_code = uap_le16_to_cpu(event_body->reason_code);
+	printf("EVENT: STA_DEAUTH\n");
+	printf("Deauthenticated STA MAC: ");
+	print_mac(event_body->sta_mac_address);
+	printf("\nReason: ");
+	switch (event_body->reason_code) {
+	case 1:
+		printf("Client station leaving the network\n");
+		break;
+	case 2:
+		printf("Client station aged out\n");
+		break;
+	case 3:
+		printf("Client station deauthenticated by user's request\n");
+		break;
+	case 4:
+		printf("Client station authentication failure\n");
+		break;
+	case 5:
+		printf("Client station association failure\n");
+		break;
+	case 6:
+		printf("Client mac address is blocked by ACL filter\n");
+		break;
+	case 7:
+		printf("Client station table is full\n");
+		break;
+	case 8:
+		printf("Client 4-way handshake timeout\n");
+		break;
+	case 9:
+		printf("Client group key handshake timeout\n");
+		break;
+	default:
+		printf("Unspecified\n");
+		break;
+	}
+	return;
+}
+
+/**
+ *  @brief Parse and print WEP ICV error event data
+ *
+ *  @param buffer   Pointer to received event buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_event_wep_icv_error(t_u8 *buffer, t_u16 size)
+{
+	int i = 0;
+	eventbuf_wep_icv_error *event_body = NULL;
+
+	if (size < sizeof(eventbuf_wep_icv_error)) {
+		printf("ERR:Event buffer too small!\n");
+		return;
+	}
+	event_body = (eventbuf_wep_icv_error *)buffer;
+	event_body->reason_code = uap_le16_to_cpu(event_body->reason_code);
+	printf("EVENT: WEP_ICV_ERROR\n");
+	printf("Deauthenticated STA MAC: ");
+	print_mac(event_body->sta_mac_address);
+	printf("WEP key index = %d\n", event_body->wep_key_index);
+	printf("WEP key length = %d\n", event_body->wep_key_length);
+	printf("WEP key : \n");
+	for (i = 0; i < event_body->wep_key_length; i++) {
+		printf("%02x ", event_body->wep_key[i]);
+	}
+	printf("\n");
+	return;
+}
+
+/**
+ *  @brief Prints mgmt frame
+ *
+ *  @param mgmt_tlv A pointer to mgmt_tlv
+ *  @param tlv_len  Length of tlv payload
+ *  @return         N/A
+ */
+void
+print_mgmt_frame(MrvlIETypes_MgmtFrameSet_t *mgmt_tlv, int tlv_len)
+{
+	IEEEtypes_AssocRqst_t *assoc_req = NULL;
+	IEEEtypes_ReAssocRqst_t *reassoc_req = NULL;
+	IEEEtypes_AssocRsp_t *assoc_resp = NULL;
+	t_u16 frm_ctl = 0;
+	printf("\nMgmt Frame:\n");
+	memcpy(&frm_ctl, &mgmt_tlv->frame_control, sizeof(t_u16));
+	printf("FrameControl: 0x%x\n", frm_ctl);
+	if (mgmt_tlv->frame_control.type != 0) {
+		printf("Frame type=%d subtype=%d:\n",
+		       mgmt_tlv->frame_control.type,
+		       mgmt_tlv->frame_control.sub_type);
+		hexdump(mgmt_tlv->frame_contents, tlv_len - sizeof(t_u16), ' ');
+		return;
+	}
+	switch (mgmt_tlv->frame_control.sub_type) {
+	case SUBTYPE_ASSOC_REQUEST:
+		printf("Assoc Request:\n");
+		assoc_req = (IEEEtypes_AssocRqst_t *)mgmt_tlv->frame_contents;
+		printf("CapInfo: 0x%x  ListenInterval: 0x%x \n",
+		       uap_le16_to_cpu(assoc_req->cap_info),
+		       uap_le16_to_cpu(assoc_req->listen_interval));
+		printf("AssocReqIE:\n");
+		hexdump(assoc_req->ie_buffer,
+			tlv_len - sizeof(IEEEtypes_AssocRqst_t)
+			- sizeof(IEEEtypes_FrameCtl_t), ' ');
+		break;
+	case SUBTYPE_REASSOC_REQUEST:
+		printf("ReAssoc Request:\n");
+		reassoc_req =
+			(IEEEtypes_ReAssocRqst_t *)mgmt_tlv->frame_contents;
+		printf("CapInfo: 0x%x  ListenInterval: 0x%x \n",
+		       uap_le16_to_cpu(reassoc_req->cap_info),
+		       uap_le16_to_cpu(reassoc_req->listen_interval));
+		printf("Current AP address: ");
+		print_mac(reassoc_req->current_ap_addr);
+		printf("\nReAssocReqIE:\n");
+		hexdump(reassoc_req->ie_buffer,
+			tlv_len - sizeof(IEEEtypes_ReAssocRqst_t)
+			- sizeof(IEEEtypes_FrameCtl_t), ' ');
+		break;
+	case SUBTYPE_ASSOC_RESPONSE:
+	case SUBTYPE_REASSOC_RESPONSE:
+		if (mgmt_tlv->frame_control.sub_type == SUBTYPE_ASSOC_RESPONSE)
+			printf("Assoc Response:\n");
+		else
+			printf("ReAssoc Response:\n");
+		assoc_resp = (IEEEtypes_AssocRsp_t *)mgmt_tlv->frame_contents;
+		printf("CapInfo: 0x%x  StatusCode: %d  AID: 0x%x \n",
+		       uap_le16_to_cpu(assoc_resp->cap_info),
+		       (int)(uap_le16_to_cpu(assoc_resp->status_code)),
+		       uap_le16_to_cpu(assoc_resp->aid) & 0x3fff);
+		break;
+	default:
+		printf("Frame subtype = %d:\n",
+		       mgmt_tlv->frame_control.sub_type);
+		hexdump(mgmt_tlv->frame_contents, tlv_len - sizeof(t_u16), ' ');
+		break;
+	}
+	return;
+}
+
+/**
+ *  @brief Parse and print RSN connect event data
+ *
+ *  @param buffer   Pointer to received buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_event_rsn_connect(t_u8 *buffer, t_u16 size)
+{
+	int tlv_buf_left = size;
+	t_u16 tlv_type, tlv_len;
+	tlvbuf_header *tlv = NULL;
+	eventbuf_rsn_connect *event_body = NULL;
+	if (size < sizeof(eventbuf_rsn_connect)) {
+		printf("ERR:Event buffer too small!\n");
+		return;
+	}
+	event_body = (eventbuf_rsn_connect *)buffer;
+	printf("EVENT: RSN_CONNECT\n");
+	printf("Station MAC: ");
+	print_mac(event_body->sta_mac_address);
+	printf("\n");
+	tlv_buf_left = size - sizeof(eventbuf_rsn_connect);
+	if (tlv_buf_left < (int)sizeof(tlvbuf_header))
+		return;
+	tlv = (tlvbuf_header *)(buffer + sizeof(eventbuf_rsn_connect));
+
+	while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
+		tlv_type = uap_le16_to_cpu(tlv->type);
+		tlv_len = uap_le16_to_cpu(tlv->len);
+		if ((sizeof(tlvbuf_header) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len,
+			       tlv_buf_left);
+			break;
+		}
+		switch (tlv_type) {
+		case IEEE_WPA_IE:
+			printf("WPA IE:\n");
+			hexdump((t_u8 *)tlv + sizeof(tlvbuf_header), tlv_len,
+				' ');
+			break;
+		case IEEE_RSN_IE:
+			printf("RSN IE:\n");
+			hexdump((t_u8 *)tlv + sizeof(tlvbuf_header), tlv_len,
+				' ');
+			break;
+		default:
+			printf("unknown tlv: %d\n", tlv_type);
+			break;
+		}
+		tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
+		tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len +
+					sizeof(tlvbuf_header));
+	}
+	return;
+}
+
+/**
+ *  @brief Parse and print STA associate event data
+ *
+ *  @param buffer   Pointer to received buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_event_sta_assoc(t_u8 *buffer, t_u16 size)
+{
+	int tlv_buf_left = size;
+	t_u16 tlv_type, tlv_len;
+	tlvbuf_header *tlv = NULL;
+	MrvlIEtypes_WapiInfoSet_t *wapi_tlv = NULL;
+	MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = NULL;
+	eventbuf_sta_assoc *event_body = NULL;
+	if (size < sizeof(eventbuf_sta_assoc)) {
+		printf("ERR:Event buffer too small!\n");
+		return;
+	}
+	event_body = (eventbuf_sta_assoc *)buffer;
+	printf("EVENT: STA_ASSOCIATE\n");
+	printf("Associated STA MAC: ");
+	print_mac(event_body->sta_mac_address);
+	printf("\n");
+	tlv_buf_left = size - sizeof(eventbuf_sta_assoc);
+	if (tlv_buf_left < (int)sizeof(tlvbuf_header))
+		return;
+	tlv = (tlvbuf_header *)(buffer + sizeof(eventbuf_sta_assoc));
+
+	while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
+		tlv_type = uap_le16_to_cpu(tlv->type);
+		tlv_len = uap_le16_to_cpu(tlv->len);
+		if ((sizeof(tlvbuf_header) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len,
+			       tlv_buf_left);
+			break;
+		}
+		switch (tlv_type) {
+		case MRVL_WAPI_INFO_TLV_ID:
+			wapi_tlv = (MrvlIEtypes_WapiInfoSet_t *)tlv;
+			printf("WAPI Multicast PN:\n");
+			hexdump(wapi_tlv->multicast_PN, tlv_len, ' ');
+			break;
+		case MRVL_MGMT_FRAME_TLV_ID:
+			mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv;
+			print_mgmt_frame(mgmt_tlv, tlv_len);
+			break;
+		default:
+			printf("unknown tlv: %d\n", tlv_type);
+			break;
+		}
+		tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
+		tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len +
+					sizeof(tlvbuf_header));
+	}
+	return;
+}
+
+/**
+ *  @brief Parse and print BSS start event data
+ *
+ *  @param buffer   Pointer to received buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_event_bss_start(t_u8 *buffer, t_u16 size)
+{
+	eventbuf_bss_start *event_body = NULL;
+	int tlv_buf_left = size;
+	t_u16 tlv_type, tlv_len;
+	tlvbuf_header *tlv = NULL;
+	tlvbuf_channel_config *channel_tlv = NULL;
+
+	if (size < sizeof(eventbuf_bss_start)) {
+		printf("ERR:Event buffer too small!\n");
+		return;
+	}
+	event_body = (eventbuf_bss_start *)buffer;
+	printf("EVENT: BSS_START ");
+	printf("BSS MAC: ");
+	print_mac(event_body->ap_mac_address);
+	printf("\n");
+	tlv_buf_left = size - sizeof(eventbuf_bss_start);
+	if (tlv_buf_left < (int)sizeof(tlvbuf_header))
+		return;
+	tlv = (tlvbuf_header *)(buffer + sizeof(eventbuf_bss_start));
+
+	while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
+		tlv_type = uap_le16_to_cpu(tlv->type);
+		tlv_len = uap_le16_to_cpu(tlv->len);
+		if ((sizeof(tlvbuf_header) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len,
+			       tlv_buf_left);
+			break;
+		}
+		switch (tlv_type) {
+		case MRVL_CHANNELCONFIG_TLV_ID:
+			channel_tlv = (tlvbuf_channel_config *)tlv;
+			printf("Channel = %d\n", channel_tlv->chan_number);
+			printf("Band = %s\n",
+			       (channel_tlv->bandcfg.chanBand ==
+				BAND_5GHZ) ? "5GHz" : "2.4GHz");
+			printf("Channel Select Mode = %s\n",
+			       (channel_tlv->bandcfg.scanMode ==
+				SCAN_MODE_ACS) ? "ACS" : "Manual");
+			if (channel_tlv->bandcfg.chan2Offset == SEC_CHAN_NONE)
+				printf("no secondary channel\n");
+			else if (channel_tlv->bandcfg.chan2Offset ==
+				 SEC_CHAN_ABOVE)
+				printf("secondary channel is above primary channel\n");
+			else if (channel_tlv->bandcfg.chan2Offset ==
+				 SEC_CHAN_BELOW)
+				printf("secondary channel is below primary channel\n");
+			break;
+		default:
+#if DEBUG
+			printf("unknown tlv: %d\n", tlv_type);
+#endif
+			break;
+		}
+		tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
+		tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len +
+					sizeof(tlvbuf_header));
+	}
+
+	return;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ *  @brief Print WIFI_WPS IE elements from event payload
+ *
+ *  @param buffer   Pointer to received buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_wifi_wps_ie_elements(t_u8 *buffer, t_u16 size)
+{
+	t_u8 *ptr = buffer;
+	t_u8 *array_ptr;
+	int i;
+	t_u16 wps_len = 0, wps_type = 0;
+	t_u16 ie_len_wps = size;
+
+	while (ie_len_wps > sizeof(tlvbuf_wps_ie)) {
+		memcpy(&wps_type, ptr, sizeof(t_u16));
+		memcpy(&wps_len, ptr + 2, sizeof(t_u16));
+		endian_convert_tlv_wps_header_in(wps_type, wps_len);
+		switch (wps_type) {
+		case SC_Version:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				printf("\t WPS Version = 0x%2x\n",
+				       *(wps_tlv->data));
+			}
+			break;
+		case SC_Simple_Config_State:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				printf("\t WPS setupstate = 0x%x\n",
+				       *(wps_tlv->data));
+			}
+			break;
+		case SC_Request_Type:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				printf("\t WPS RequestType = 0x%x\n",
+				       *(wps_tlv->data));
+			}
+			break;
+		case SC_Response_Type:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				printf("\t WPS ResponseType = 0x%x\n",
+				       *(wps_tlv->data));
+			}
+			break;
+		case SC_Config_Methods:
+			{
+				t_u16 wps_config_methods = 0;
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				memcpy(&wps_config_methods, wps_tlv->data,
+				       sizeof(t_u16));
+				wps_config_methods = ntohs(wps_config_methods);
+				printf("\t WPS SpecConfigMethods = 0x%x\n",
+				       wps_config_methods);
+			}
+			break;
+		case SC_UUID_E:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				array_ptr = wps_tlv->data;
+				printf("\t WPS UUID = ");
+				for (i = 0; i < wps_len; i++)
+					printf("0x%02X ", *array_ptr++);
+				printf("\n");
+			}
+			break;
+		case SC_Primary_Device_Type:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				array_ptr = wps_tlv->data;
+				printf("\t WPS Primary Device Type = ");
+				for (i = 0; i < wps_len; i++)
+					printf("0x%02X ", *array_ptr++);
+				printf("\n");
+			}
+			break;
+		case SC_RF_Band:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				printf("\t WPS RF Band = 0x%x\n",
+				       *(wps_tlv->data));
+			}
+			break;
+		case SC_Association_State:
+			{
+				t_u16 wps_association_state = 0;
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				memcpy(&wps_association_state, wps_tlv->data,
+				       sizeof(t_u16));
+				wps_association_state =
+					ntohs(wps_association_state);
+				printf("\t WPS Association State = 0x%x\n",
+				       wps_association_state);
+			}
+			break;
+		case SC_Configuration_Error:
+			{
+				t_u16 wps_configuration_error = 0;
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				memcpy(&wps_configuration_error, wps_tlv->data,
+				       sizeof(t_u16));
+				wps_configuration_error =
+					ntohs(wps_configuration_error);
+				printf("\t WPS Configuration Error = 0x%x\n",
+				       wps_configuration_error);
+			}
+			break;
+		case SC_Device_Password_ID:
+			{
+				t_u16 wps_device_password_id = 0;
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				memcpy(&wps_device_password_id, wps_tlv->data,
+				       sizeof(t_u16));
+				wps_device_password_id =
+					ntohs(wps_device_password_id);
+				printf("\t WPS Device Password ID = 0x%x\n",
+				       wps_device_password_id);
+			}
+			break;
+		case SC_Device_Name:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				array_ptr = wps_tlv->data;
+				printf("\t WPS Device Name = ");
+				for (i = 0; i < wps_len; i++)
+					printf("%c", *array_ptr++);
+				printf("\n");
+			}
+			break;
+		case SC_Manufacturer:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				array_ptr = wps_tlv->data;
+				printf("\t WPS Manufacturer = ");
+				for (i = 0; i < wps_len; i++)
+					printf("%c", *array_ptr++);
+				printf("\n");
+			}
+			break;
+		case SC_Model_Name:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				array_ptr = wps_tlv->data;
+				printf("\t WPS Model Name = ");
+				for (i = 0; i < wps_len; i++)
+					printf("%c", *array_ptr++);
+				printf("\n");
+			}
+			break;
+		case SC_Model_Number:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				array_ptr = wps_tlv->data;
+				printf("\t WPS Model Number = ");
+				for (i = 0; i < wps_len; i++)
+					printf("%c", *array_ptr++);
+				printf("\n");
+			}
+			break;
+		case SC_Serial_Number:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				array_ptr = wps_tlv->data;
+				printf("\t WPS Serial Number = ");
+				for (i = 0; i < wps_len; i++)
+					printf("%c", *array_ptr++);
+				printf("\n");
+			}
+			break;
+		case SC_Vendor_Extension:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				array_ptr = wps_tlv->data;
+				printf("\t WPS 2.0 Vendor Extension = ");
+				for (i = 0; i < wps_len; i++)
+					printf("%x", *array_ptr++);
+				printf("\n");
+			}
+			break;
+		case SC_Selected_Registrar:
+			{
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				printf("\t Selected Registrar = %d\n",
+				       *(wps_tlv->data));
+			}
+			break;
+		case SC_SelectedRegistrarConfigMethods:
+			{
+				t_u16 sr_config_methods = 0;
+				tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
+				memcpy(&sr_config_methods, wps_tlv->data,
+				       sizeof(t_u16));
+				sr_config_methods = ntohs(sr_config_methods);
+				printf("\t Selected Registrar Configuration Methods = 0x%x\n", sr_config_methods);
+			}
+			break;
+		default:
+			printf("unknown ie=0x%x, len=%d\n", wps_type, wps_len);
+			break;
+		}
+		ptr += wps_len + sizeof(tlvbuf_wps_ie);
+		/* Take care of error condition */
+		if (wps_len + sizeof(tlvbuf_wps_ie) <= ie_len_wps)
+			ie_len_wps -= wps_len + sizeof(tlvbuf_wps_ie);
+		else
+			ie_len_wps = 0;
+	}
+}
+
+/**
+ *  @brief Print WIFIDIRECT IE elements from event payload
+ *
+ *  @param buffer   Pointer to received buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_wifidirect_ie_elements(t_u8 *buffer, t_u16 size)
+{
+	t_u8 *ptr = buffer;
+	t_u8 *array_ptr, *orig_ptr = NULL;
+	int i;
+	static t_u16 len = 0;
+	static t_u16 saved_len = 0;
+	static t_u16 pending_len = 0;
+	static t_u8 type = 0;
+	static t_u8 next_byte = WIFIDIRECT_OVERLAP_TYPE;
+	static t_u8 saved_data[WIFI_IE_MAX_PAYLOAD] = { 0 };
+	t_u16 temp;
+	t_u16 left_len = size;
+
+	while (left_len > 0) {
+		if (next_byte == WIFIDIRECT_OVERLAP_TYPE) {
+			type = *ptr;
+			next_byte = WIFIDIRECT_OVERLAP_LEN;
+			left_len--;
+			ptr++;
+		}
+		if (left_len >= sizeof(len) &&
+		    next_byte == WIFIDIRECT_OVERLAP_LEN) {
+			memcpy(&len, ptr, sizeof(t_u16));
+			len = uap_le16_to_cpu(len);
+			next_byte = WIFIDIRECT_OVERLAP_DATA;
+			left_len -= sizeof(t_u16);
+			ptr += sizeof(t_u16);
+
+			/* case when Type, Len in one frame and data in next */
+			if (left_len == 0) {
+				memcpy(saved_data,
+				       ptr - WIFIDIRECT_IE_HEADER_LEN,
+				       WIFIDIRECT_IE_HEADER_LEN);
+				saved_len = WIFIDIRECT_IE_HEADER_LEN;
+				pending_len = len;
+			}
+		}
+		if (left_len > 0 && next_byte == WIFIDIRECT_OVERLAP_DATA) {
+			/* copy next data */
+			if (pending_len > 0 &&
+			    (left_len <= (WIFI_IE_MAX_PAYLOAD - saved_len))) {
+				memcpy(saved_data + saved_len, ptr,
+				       pending_len);
+				orig_ptr = ptr;
+				ptr = saved_data;
+			} else {
+				ptr -= WIFIDIRECT_IE_HEADER_LEN;
+			}
+
+			if (!pending_len && !orig_ptr && left_len < len) {
+				/* save along with type and len */
+				memcpy(saved_data,
+				       ptr - WIFIDIRECT_IE_HEADER_LEN,
+				       left_len + WIFIDIRECT_IE_HEADER_LEN);
+				saved_len = left_len + WIFIDIRECT_IE_HEADER_LEN;
+				pending_len = len - left_len;
+				break;
+			}
+			switch (type) {
+			case TLV_TYPE_WIFIDIRECT_DEVICE_ID:
+				{
+					tlvbuf_wifidirect_device_id
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_device_id *)
+						ptr;
+					printf("\t Device ID - ");
+					print_mac(wifidirect_tlv->
+						  dev_mac_address);
+					printf("\n");
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_CAPABILITY:
+				{
+					tlvbuf_wifidirect_capability
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_capability *)
+						ptr;
+					printf("\t Device capability = %d\n",
+					       (int)wifidirect_tlv->
+					       dev_capability);
+					printf("\t Group capability = %d\n",
+					       (int)wifidirect_tlv->
+					       group_capability);
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_GROUPOWNER_INTENT:
+				{
+					tlvbuf_wifidirect_group_owner_intent
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_group_owner_intent
+						 *)ptr;
+					printf("\t Group owner intent = %d\n",
+					       (int)wifidirect_tlv->dev_intent);
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_MANAGEABILITY:
+				{
+					tlvbuf_wifidirect_manageability
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_manageability
+						 *)ptr;
+					printf("\t Manageability = %d\n",
+					       (int)wifidirect_tlv->
+					       manageability);
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_INVITATION_FLAG:
+				{
+					tlvbuf_wifidirect_invitation_flag
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_invitation_flag
+						 *)ptr;
+					printf("\t Invitation Flag = %d\n",
+					       (int)wifidirect_tlv->
+					       invitation_flag &
+					       INVITATION_FLAG_MASK);
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_CHANNEL_LIST:
+				{
+					tlvbuf_wifidirect_channel_list
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_channel_list
+						 *)ptr;
+					chan_entry *temp_ptr;
+					printf("\t Country String %c%c",
+					       wifidirect_tlv->
+					       country_string[0],
+					       wifidirect_tlv->
+					       country_string[1]);
+					if (isalpha
+					    (wifidirect_tlv->country_string[2]))
+						printf("%c",
+						       wifidirect_tlv->
+						       country_string[2]);
+					printf("\n");
+					temp_ptr =
+						(chan_entry *)wifidirect_tlv->
+						wifidirect_chan_entry_list;
+					temp = uap_le16_to_cpu(wifidirect_tlv->
+							       length) -
+						(sizeof
+						 (tlvbuf_wifidirect_channel_list)
+						 - WIFIDIRECT_IE_HEADER_LEN);
+					while (temp) {
+						printf("\t Regulatory_class = %d\n", (int)(temp_ptr->regulatory_class));
+						printf("\t No of channels = %d\n", (int)temp_ptr->num_of_channels);
+						printf("\t Channel list = ");
+						for (i = 0;
+						     i <
+						     temp_ptr->num_of_channels;
+						     i++) {
+							printf("%d ",
+							       *(temp_ptr->
+								 chan_list +
+								 i));
+						}
+						printf("\n");
+						temp -= sizeof(chan_entry) +
+							temp_ptr->
+							num_of_channels;
+						temp_ptr =
+							(chan_entry *)((t_u8 *)
+								       temp_ptr
+								       +
+								       sizeof
+								       (chan_entry)
+								       +
+								       temp_ptr->
+								       num_of_channels);
+					}
+					printf("\n");
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_NOTICE_OF_ABSENCE:
+				{
+					tlvbuf_wifidirect_notice_of_absence
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_notice_of_absence
+						 *)ptr;
+					noa_descriptor *temp_ptr;
+					printf("\t Instance of Notice of absence timing %d\n", (int)wifidirect_tlv->noa_index);
+					printf("\t CTWindow and Opportunistic power save parameters %d\n", (int)wifidirect_tlv->ctwindow_opp_ps);
+					temp_ptr =
+						(noa_descriptor *)
+						wifidirect_tlv->
+						wifidirect_noa_descriptor_list;
+					temp = uap_le16_to_cpu(wifidirect_tlv->
+							       length) -
+						(sizeof
+						 (tlvbuf_wifidirect_notice_of_absence)
+						 - WIFIDIRECT_IE_HEADER_LEN);
+					while (temp) {
+						printf("\t Count or Type = %d\n", (int)temp_ptr->count_type);
+						printf("\t Duration = %dms\n",
+						       uap_le32_to_cpu
+						       (temp_ptr->duration));
+						printf("\t Interval = %dms\n",
+						       uap_le32_to_cpu
+						       (temp_ptr->interval));
+						printf("\t Start Time = %d\n",
+						       uap_le32_to_cpu
+						       (temp_ptr->start_time));
+						printf("\n");
+						temp_ptr +=
+							sizeof(noa_descriptor);
+						temp -= sizeof(noa_descriptor);
+					}
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_DEVICE_INFO:
+				{
+					tlvbuf_wifidirect_device_info
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_device_info
+						 *)ptr;
+					printf("\t Device address - ");
+					print_mac(wifidirect_tlv->dev_address);
+					printf("\n");
+					printf("\t Config methods - 0x%02X\n",
+					       ntohs(wifidirect_tlv->
+						     config_methods));
+					printf("\t Primay device type = %02d-%02X%02X%02X%02X-%02d\n", (int)ntohs(wifidirect_tlv->primary_category), (int)wifidirect_tlv->primary_oui[0], (int)wifidirect_tlv->primary_oui[1], (int)wifidirect_tlv->primary_oui[2], (int)wifidirect_tlv->primary_oui[3], (int)ntohs(wifidirect_tlv->primary_subcategory));
+					printf("\t Secondary Device Count = %d\n", (int)wifidirect_tlv->secondary_dev_count);
+					array_ptr =
+						wifidirect_tlv->
+						secondary_dev_info;
+					for (i = 0;
+					     i <
+					     wifidirect_tlv->
+					     secondary_dev_count; i++) {
+						memcpy(&temp, array_ptr,
+						       sizeof(t_u16));
+						printf("\t Secondary device type = %02d-", ntohs(temp));
+						array_ptr += sizeof(temp);
+						printf("%02X%02X%02X%02X",
+						       array_ptr[0],
+						       array_ptr[1],
+						       array_ptr[2],
+						       array_ptr[3]);
+						array_ptr += 4;
+						memcpy(&temp, array_ptr,
+						       sizeof(t_u16));
+						printf("-%02d\n", ntohs(temp));
+						array_ptr += sizeof(temp);
+					}
+					/* display device name */
+					array_ptr =
+						wifidirect_tlv->device_name +
+						wifidirect_tlv->
+						secondary_dev_count *
+						WPS_DEVICE_TYPE_LEN;
+					if (*(t_u16 *)
+					    (((t_u8 *)(&wifidirect_tlv->
+						       device_name_len)) +
+					     wifidirect_tlv->
+					     secondary_dev_count *
+					     WPS_DEVICE_TYPE_LEN))
+						printf("\t Device Name =  ");
+					memcpy(&temp,
+					       (((t_u8 *)(&wifidirect_tlv->
+							  device_name_len)) +
+						wifidirect_tlv->
+						secondary_dev_count *
+						WPS_DEVICE_TYPE_LEN),
+					       sizeof(t_u16));
+					temp = ntohs(temp);
+					for (i = 0; i < temp; i++)
+						printf("%c", *array_ptr++);
+					printf("\n");
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_GROUP_INFO:
+				{
+					tlvbuf_wifidirect_group_info
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_group_info *)
+						ptr;
+					t_u8 wifidirect_client_dev_length;
+					wifidirect_client_dev_info *temp_ptr;
+					temp_ptr =
+						(wifidirect_client_dev_info *)
+						wifidirect_tlv->
+						wifidirect_client_dev_list;
+					if (temp_ptr == NULL)
+						break;
+					wifidirect_client_dev_length =
+						temp_ptr->dev_length;
+					temp = uap_le16_to_cpu(wifidirect_tlv->
+							       length) -
+						wifidirect_client_dev_length;
+					while (temp) {
+
+						printf("\t Group WifiDirect Client Device address - ");
+						print_mac(temp_ptr->
+							  wifidirect_dev_address);
+						printf("\n");
+						printf("\t Group WifiDirect Client Interface address - ");
+						print_mac(temp_ptr->
+							  wifidirect_intf_address);
+						printf("\n");
+						printf("\t Group WifiDirect Client Device capability = %d\n", (int)temp_ptr->wifidirect_dev_capability);
+						printf("\t Group WifiDirect Client Config methods - 0x%02X\n", ntohs(temp_ptr->config_methods));
+						printf("\t Group WifiDirect Client Primay device type = %02d-%02X%02X%02X%02X-%02d\n", (int)ntohs(temp_ptr->primary_category), (int)temp_ptr->primary_oui[0], (int)temp_ptr->primary_oui[1], (int)temp_ptr->primary_oui[2], (int)temp_ptr->primary_oui[3], (int)ntohs(temp_ptr->primary_subcategory));
+						printf("\t Group WifiDirect Client Secondary Device Count = %d\n", (int)temp_ptr->wifidirect_secondary_dev_count);
+						array_ptr =
+							temp_ptr->
+							wifidirect_secondary_dev_info;
+						for (i = 0;
+						     i <
+						     temp_ptr->
+						     wifidirect_secondary_dev_count;
+						     i++) {
+							memcpy(&temp, array_ptr,
+							       sizeof(t_u16));
+							printf("\t Group WifiDirect Client Secondary device type = %02d-", ntohs(temp));
+							array_ptr +=
+								sizeof(temp);
+							printf("%02X%02X%02X%02X", array_ptr[0], array_ptr[1], array_ptr[2], array_ptr[3]);
+							array_ptr += 4;
+							memcpy(&temp, array_ptr,
+							       sizeof(t_u16));
+							printf("-%02d\n",
+							       ntohs(temp));
+							array_ptr +=
+								sizeof(temp);
+						}
+						/* display device name */
+						array_ptr =
+							temp_ptr->
+							wifidirect_device_name +
+							temp_ptr->
+							wifidirect_secondary_dev_count
+							* WPS_DEVICE_TYPE_LEN;
+						printf("\t Group WifiDirect Device Name =  ");
+						memcpy(&temp,
+						       (((t_u8 *)(&temp_ptr->
+								  wifidirect_device_name_len))
+							+
+							temp_ptr->
+							wifidirect_secondary_dev_count
+							* WPS_DEVICE_TYPE_LEN),
+						       sizeof(t_u16));
+						temp = ntohs(temp);
+						for (i = 0; i < temp; i++)
+							printf("%c",
+							       *array_ptr++);
+						printf("\n");
+						temp_ptr +=
+							wifidirect_client_dev_length;
+						temp -= wifidirect_client_dev_length;
+						if (temp_ptr)
+							wifidirect_client_dev_length
+								=
+								temp_ptr->
+								dev_length;
+					}
+					printf("\n");
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_GROUP_ID:
+				{
+					tlvbuf_wifidirect_group_id
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_group_id *)
+						ptr;
+					printf("\t Group address - ");
+					print_mac(wifidirect_tlv->
+						  group_address);
+					printf("\n");
+					printf("\t Group ssid =  ");
+					for (i = 0;
+					     (unsigned int)i <
+					     uap_le16_to_cpu(wifidirect_tlv->
+							     length)
+					     -
+					     (sizeof(tlvbuf_wifidirect_group_id)
+					      - WIFIDIRECT_IE_HEADER_LEN); i++)
+						printf("%c",
+						       wifidirect_tlv->
+						       group_ssid[i]);
+					printf("\n");
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_GROUP_BSS_ID:
+				{
+					tlvbuf_wifidirect_group_bss_id
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_group_bss_id
+						 *)ptr;
+					printf("\t Group BSS Id - ");
+					print_mac(wifidirect_tlv->group_bssid);
+					printf("\n");
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_INTERFACE:
+				{
+					tlvbuf_wifidirect_interface
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_interface *)
+						ptr;
+					printf("\t Interface Id - ");
+					print_mac(wifidirect_tlv->interface_id);
+					printf("\t Interface count = %d",
+					       (int)wifidirect_tlv->
+					       interface_count);
+					for (i = 0;
+					     i <
+					     wifidirect_tlv->interface_count;
+					     i++) {
+						printf("\n\t Interface address [%d]", i + 1);
+						print_mac(&wifidirect_tlv->
+							  interface_idlist[i *
+									   ETH_ALEN]);
+					}
+					printf("\n");
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_CHANNEL:
+				{
+					tlvbuf_wifidirect_channel
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_channel *)
+						ptr;
+					printf("\t Listen Channel Country String %c%c", wifidirect_tlv->country_string[0], wifidirect_tlv->country_string[1]);
+					if (isalpha
+					    (wifidirect_tlv->country_string[2]))
+						printf("%c",
+						       wifidirect_tlv->
+						       country_string[2]);
+					printf("\n");
+					printf("\t Listen Channel regulatory class = %d\n", (int)wifidirect_tlv->regulatory_class);
+					printf("\t Listen Channel number = %d\n", (int)wifidirect_tlv->channel_number);
+				}
+				break;
+
+			case TLV_TYPE_WIFIDIRECT_OPCHANNEL:
+				{
+					tlvbuf_wifidirect_channel
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_channel *)
+						ptr;
+					printf("\t Operating Channel Country String %c%c", wifidirect_tlv->country_string[0], wifidirect_tlv->country_string[1]);
+					if (isalpha
+					    (wifidirect_tlv->country_string[2]))
+						printf("%c",
+						       wifidirect_tlv->
+						       country_string[2]);
+					printf("\n");
+					printf("\t Operating Channel regulatory class = %d\n", (int)wifidirect_tlv->regulatory_class);
+					printf("\t Operating Channel number = %d\n", (int)wifidirect_tlv->channel_number);
+				}
+				break;
+
+			case TLV_TYPE_WIFIDIRECT_CONFIG_TIMEOUT:
+				{
+					tlvbuf_wifidirect_config_timeout
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_config_timeout
+						 *)ptr;
+					printf("\t GO configuration timeout = %d msec\n", (int)wifidirect_tlv->group_config_timeout * 10);
+					printf("\t Client configuration timeout = %d msec\n", (int)wifidirect_tlv->device_config_timeout * 10);
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_EXTENDED_LISTEN_TIME:
+				{
+					tlvbuf_wifidirect_ext_listen_time
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_ext_listen_time
+						 *)ptr;
+					printf("\t Availability Period = %d msec\n", (int)wifidirect_tlv->availability_period);
+					printf("\t Availability Interval = %d msec\n", (int)wifidirect_tlv->availability_interval);
+				}
+				break;
+			case TLV_TYPE_WIFIDIRECT_INTENDED_ADDRESS:
+				{
+					tlvbuf_wifidirect_intended_addr
+						*wifidirect_tlv =
+						(tlvbuf_wifidirect_intended_addr
+						 *)ptr;
+					printf("\t Intended Interface Address - ");
+					print_mac(wifidirect_tlv->
+						  group_address);
+					printf("\n");
+				}
+				break;
+
+			case TLV_TYPE_WIFIDIRECT_STATUS:
+				{
+					tlvbuf_wifidirect_status *wifidirect_tlv
+						=
+						(tlvbuf_wifidirect_status *)ptr;
+					printf("\t Status = %d\n",
+					       wifidirect_tlv->status_code);
+				}
+				break;
+
+			default:
+				printf("unknown ie=0x%x, len=%d\n", type, len);
+				break;
+			}
+			next_byte = WIFIDIRECT_OVERLAP_TYPE;
+			if (orig_ptr)
+				ptr = orig_ptr + pending_len;
+		}
+		ptr += len + WIFIDIRECT_IE_HEADER_LEN;
+		left_len -= len;
+	}
+	printf("\n");
+	return;
+}
+
+/**
+ *  @brief Parse and print WIFIDIRECT generic event data
+ *
+ *  @param buffer   Pointer to received buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_event_wifidirect_generic(t_u8 *buffer, t_u16 size)
+{
+	const t_u8 wifi_oui[3] = { 0x50, 0x6F, 0x9A };
+	const t_u8 wps_oui[3] = { 0x00, 0x50, 0xF2 };
+	apeventbuf_wifidirect_generic *wifidirect_event;
+	wifidirect_ie_header *wifidirect_wps_header;
+	t_u16 wifidirect_wps_len = 0, type, sub_type;
+	printf("EVENT: WIFIDIRECT \n");
+	wifidirect_event = (apeventbuf_wifidirect_generic *)(buffer);
+	printf("Event length = %d\n",
+	       uap_le16_to_cpu(wifidirect_event->event_length));
+	printf("Event Type = ");
+	type = uap_le16_to_cpu(wifidirect_event->event_type);
+	switch (type) {
+	case 0:
+		printf("Negotiation Request\n");
+		break;
+	case 1:
+		printf("Negotiation Response\n");
+		break;
+	case 2:
+		printf("Negotiation Result\n");
+		break;
+	case 3:
+		printf("Invitation Request\n");
+		break;
+	case 4:
+		printf("Invitation Response\n");
+		break;
+	case 5:
+		printf("Discoverability Request\n");
+		break;
+	case 6:
+		printf("Discoverability Response\n");
+		break;
+	case 7:
+		printf("Provision Discovery Request\n");
+		break;
+	case 8:
+		printf("Provision Discovery Response\n");
+		break;
+	case 9:
+		printf("GO Negotiation response Tx Event\n");
+		break;
+	case 10:
+		printf("GO Negotiation confirm Tx Event\n");
+		break;
+	case 14:
+		printf("Peer Detected event\n");
+		break;
+	case 15:
+		printf("Client associated event\n");
+		break;
+	case 16:
+		printf("FW debug event: %s\n",
+		       wifidirect_event->entire_ie_list);
+		return;
+	default:
+		printf("Unknown\n");
+		break;
+	}
+	sub_type = uap_le16_to_cpu(wifidirect_event->event_sub_type);
+	if (type == 2) {
+		switch (sub_type) {
+		case 0:
+			printf("Event SubType = No Role\n");
+			break;
+		case 1:
+			printf("Event SubType = Group Owner Role\n");
+			break;
+		case 2:
+			printf("Event SubType = Client Role\n");
+			break;
+		default:
+			printf("Event SubType = %d\n", sub_type);
+			break;
+		}
+	} else if (type == 3 || type == 4) {
+		switch (sub_type & 0x03) {	/* lower 2 bits */
+		case 0:
+			printf("Event SubType = No Role\n");
+			break;
+		case 1:
+			printf("Event SubType = Group Owner Role\n");
+			break;
+		case 2:
+			printf("Event SubType = Client Role\n");
+			break;
+		}
+		switch ((sub_type & 0x1C) >> 2) {	/* next 3 bits */
+		case 0:
+			printf("Packet processing state = None\n");
+			break;
+		case 1:
+			printf("Packet processing state = Processing\n");
+			break;
+		case 2:
+			printf("Packet processing state = Insufficient information, Dropped\n");
+			break;
+		case 3:
+			printf("Packet processing state = Success\n");
+			break;
+		case 4:
+			printf("Packet processing state = Fail\n");
+			break;
+		default:
+			printf("Event SubType = %d\n", sub_type);
+			break;
+		}
+	} else if (type == 7 || type == 8) {
+		switch (sub_type) {
+		case 0:
+			printf("Event SubType = No Config Method\n");
+			break;
+		case 8:
+			printf("Event SubType = Config Method Display\n");
+			break;
+		case 0x80:
+			printf("Event SubType = Config Method Push Button\n");
+			break;
+		case 0x100:
+			printf("Event SubType = Config Method Keypad\n");
+			break;
+		default:
+			printf("Event SubType = %d\n", sub_type);
+			break;
+		}
+	}
+	printf("Peer Mac Address - ");
+	print_mac(wifidirect_event->peer_mac_addr);
+	printf("\n");
+	/* Print rest of IE elements */
+	wifidirect_wps_header =
+		(wifidirect_ie_header *)(wifidirect_event->entire_ie_list);
+	wifidirect_wps_len = uap_le16_to_cpu(wifidirect_event->event_length)
+		- sizeof(apeventbuf_wifidirect_generic);
+
+	while (wifidirect_wps_len >= sizeof(wifidirect_ie_header)) {
+		if (!memcmp
+		    (wifidirect_wps_header->oui, wifi_oui, sizeof(wifi_oui)) ||
+		    !(memcmp
+		      (wifidirect_wps_header->oui, wps_oui, sizeof(wps_oui)))) {
+			switch (wifidirect_wps_header->oui_type) {
+			case WIFIDIRECT_OUI_TYPE:
+				print_wifidirect_ie_elements
+					(wifidirect_wps_header->ie_list,
+					 wifidirect_wps_header->ie_length -
+					 sizeof(wifidirect_wps_header->oui)
+					 -
+					 sizeof(wifidirect_wps_header->
+						oui_type));
+				printf("\n");
+				break;
+			case WIFI_WPS_OUI_TYPE:
+				print_wifi_wps_ie_elements
+					(wifidirect_wps_header->ie_list,
+					 wifidirect_wps_header->ie_length -
+					 sizeof(wifidirect_wps_header->oui)
+					 -
+					 sizeof(wifidirect_wps_header->
+						oui_type));
+				printf("\n");
+				break;
+			}
+		}
+		wifidirect_wps_len -=
+			wifidirect_wps_header->ie_length + IE_HEADER_LEN;
+		wifidirect_wps_header =
+			(wifidirect_ie_header *)(((t_u8 *)wifidirect_wps_header)
+						 +
+						 wifidirect_wps_header->
+						 ie_length + IE_HEADER_LEN);
+	}
+}
+
+/**
+ *  @brief Parse and print WIFIDIRECT service discovery event data
+ *
+ *  @param buffer   Pointer to received buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_event_wifidirect_service_discovery(t_u8 *buffer, t_u16 size)
+{
+	unsigned int i;
+	t_u16 event_len = 0;
+	t_u16 dns_len = 0, dns_type;
+	t_u8 action = 0;	/* req = 0, resp = 1 */
+	apeventbuf_wifidirect_discovery_request *wifidirect_disc_req;
+	apeventbuf_wifidirect_discovery_response *wifidirect_disc_resp;
+	printf("EVENT: WIFIDIRECT SERVICE DISCOVERY\n");
+	memcpy(&event_len, buffer, sizeof(t_u16));
+	event_len = uap_le16_to_cpu(event_len);
+	printf("Event length = %d\n", event_len);
+	printf("Service Discovery packet:\n");
+	/* check request /response Byte at offset 2+6+2 */
+	action = *(buffer + sizeof(t_u16) + ETH_ALEN + sizeof(t_u8));
+	if (action == WIFIDIRECT_DISCOVERY_REQUEST_ACTION) {
+		wifidirect_disc_req =
+			(apeventbuf_wifidirect_discovery_request *)(buffer +
+								    sizeof
+								    (t_u16));
+		printf("\t Peer Mac Address - ");
+		print_mac(wifidirect_disc_req->peer_mac_addr);
+		printf("\n\t Category = %d\n", wifidirect_disc_req->category);
+		printf("\t Action = %d\n", wifidirect_disc_req->action);
+		printf("\t Dialog taken = %d\n",
+		       wifidirect_disc_req->dialog_taken);
+		printf("\t Advertize protocol IE - 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", wifidirect_disc_req->advertize_protocol_ie[0], wifidirect_disc_req->advertize_protocol_ie[1], wifidirect_disc_req->advertize_protocol_ie[2], wifidirect_disc_req->advertize_protocol_ie[3]);
+		printf("\t Request query length = %d\n",
+		       uap_le16_to_cpu(wifidirect_disc_req->query_len));
+		printf("\t Information Id - 0x%02x, 0x%02x\n",
+		       wifidirect_disc_req->info_id[0],
+		       wifidirect_disc_req->info_id[1]);
+		printf("\t Request length = %d\n",
+		       uap_le16_to_cpu(wifidirect_disc_req->request_len));
+		printf("\t OUI - 0x%02x, 0x%02x, 0x%02x\n",
+		       wifidirect_disc_req->oui[0], wifidirect_disc_req->oui[1],
+		       wifidirect_disc_req->oui[2]);
+		printf("\t OUI sub type = %d\n",
+		       wifidirect_disc_req->oui_sub_type);
+		printf("\t Service update Indicator = %d\n",
+		       uap_le16_to_cpu(wifidirect_disc_req->
+				       service_update_indicator));
+		printf("\t Vendor length = %d\n",
+		       uap_le16_to_cpu(wifidirect_disc_req->vendor_len));
+		printf("\t Service protocol = %d\n",
+		       wifidirect_disc_req->service_protocol);
+		printf("\t Service transaction Id = %d\n",
+		       wifidirect_disc_req->service_transaction_id);
+		printf("\t Query Data = ");
+		if (wifidirect_disc_req->service_protocol == 1) {
+			printf(" * Bonjour * \n");
+			printf("\t\t DNS = ");
+			dns_len =
+				uap_le16_to_cpu(wifidirect_disc_req->
+						vendor_len) -
+				WIFIDIRECT_DISCOVERY_BONJOUR_FIXED_LEN;
+			for (i = 0; i < dns_len; i++)
+				printf("%02x ",
+				       (int)*(wifidirect_disc_req->disc_query.u.
+					      bonjour.dns + i));
+			memcpy(&dns_type,
+			       (&wifidirect_disc_req->disc_query.u.bonjour.
+				dns_type + dns_len), sizeof(dns_type));
+			dns_type = uap_le16_to_cpu(dns_type);
+			printf("\n\t\t DNS Type = %d\n", dns_type);
+			printf("\t\t Version = %d\n",
+			       *(&wifidirect_disc_req->disc_query.u.bonjour.
+				 version + dns_len));
+		} else if (wifidirect_disc_req->service_protocol == 2) {
+			printf(" * uPnP * \n");
+			printf("\t\t Version = %d\n",
+			       wifidirect_disc_req->disc_query.u.upnp.version);
+			dns_len =
+				uap_le16_to_cpu(wifidirect_disc_req->
+						vendor_len) -
+				WIFIDIRECT_DISCOVERY_UPNP_FIXED_LEN;
+			printf("\t\t Value = ");
+			for (i = 0; i < dns_len; i++)
+				printf("%02x ",
+				       (int)*(wifidirect_disc_req->disc_query.u.
+					      upnp.value + i));
+		}
+		printf("\n");
+	} else if (action == WIFIDIRECT_DISCOVERY_RESPONSE_ACTION) {
+		wifidirect_disc_resp =
+			(apeventbuf_wifidirect_discovery_response *)(buffer +
+								     sizeof
+								     (t_u16));
+		printf("\t Peer Mac Address - ");
+		print_mac(wifidirect_disc_resp->peer_mac_addr);
+		printf("\n\t Category = %d\n", wifidirect_disc_resp->category);
+		printf("\t Action = %d\n", wifidirect_disc_resp->action);
+		printf("\t Dialog taken = %d\n",
+		       wifidirect_disc_resp->dialog_taken);
+		printf("\t Status code = %d\n",
+		       wifidirect_disc_resp->status_code);
+		printf("\t GAS reply - 0x%02x\n",
+		       uap_le16_to_cpu(wifidirect_disc_resp->gas_reply));
+		printf("\t Advertize protocol IE - 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", wifidirect_disc_resp->advertize_protocol_ie[0], wifidirect_disc_resp->advertize_protocol_ie[1], wifidirect_disc_resp->advertize_protocol_ie[2], wifidirect_disc_resp->advertize_protocol_ie[3]);
+		printf("\t Response query length = %d\n",
+		       uap_le16_to_cpu(wifidirect_disc_resp->query_len));
+		printf("\t Information Id - 0x%02x, 0x%02x\n",
+		       wifidirect_disc_resp->info_id[0],
+		       wifidirect_disc_resp->info_id[1]);
+		printf("\t Response length = %d\n",
+		       uap_le16_to_cpu(wifidirect_disc_resp->response_len));
+		printf("\t OUI - 0x%02x, 0x%02x, 0x%02x\n",
+		       wifidirect_disc_resp->oui[0],
+		       wifidirect_disc_resp->oui[1],
+		       wifidirect_disc_resp->oui[2]);
+		printf("\t OUI sub type = %d\n",
+		       wifidirect_disc_resp->oui_sub_type);
+		printf("\t Service update Indicator = %d\n",
+		       uap_le16_to_cpu(wifidirect_disc_resp->
+				       service_update_indicator));
+		printf("\t Vendor length = %d\n",
+		       uap_le16_to_cpu(wifidirect_disc_resp->vendor_len));
+		printf("\t Service protocol = %d\n",
+		       wifidirect_disc_resp->service_protocol);
+		printf("\t Service transaction Id = %d\n",
+		       wifidirect_disc_resp->service_transaction_id);
+		printf("\t Status Code = %d\n",
+		       wifidirect_disc_resp->disc_status_code);
+		printf("\t Response Data = ");
+		if (wifidirect_disc_resp->service_protocol == 1) {
+			printf(" * Bonjour * \n");
+			/*
+			   printf("\t\t DNS = ");
+			   dns_len = uap_le16_to_cpu(wifidirect_disc_resp->vendor_len) -
+			   (WIFIDIRECT_DISCOVERY_BONJOUR_FIXED_LEN + 1);
+			   for( i=0; i < dns_len; i++)
+			   printf("%c",*(wifidirect_disc_resp->disc_resp.u.bonjour.dns + i));
+			   memcpy(&dns_type, (&wifidirect_disc_req->disc_query.u.bonjour.dns_type
+			   + dns_len), sizeof(dns_type));
+			   dns_type = uap_le16_to_cpu(dns_type);
+			   printf("\n\t\t DNS Type = %d\n", dns_type);
+			   printf("\t\t Version = %d\n", *(&wifidirect_disc_resp->disc_resp.u.bonjour.version
+			   + dns_len));
+			 */
+		} else if (wifidirect_disc_resp->service_protocol == 2) {
+			printf(" * uPnP * \n");
+			printf("\t\t Version = %d\n",
+			       wifidirect_disc_resp->disc_resp.u.upnp.version);
+			dns_len =
+				uap_le16_to_cpu(wifidirect_disc_resp->
+						vendor_len) -
+				WIFIDIRECT_DISCOVERY_UPNP_FIXED_LEN;
+			printf("\t\t Value = ");
+			for (i = 0; i < dns_len; i++)
+				printf("%02x ",
+				       (int)*(wifidirect_disc_resp->disc_resp.u.
+					      upnp.value + i));
+		}
+		printf("\n");
+	}
+}
+#endif
+
+/**
+ *  @brief Parse and print TDLS generic event data
+ *
+ *  @param buffer   Pointer to received buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_event_tdls_generic(t_u8 *buffer, t_u16 size)
+{
+	eventbuf_tdls_generic *tdls_event;
+	eventbuf_tdls_debug *tdls_debug;
+	eventbuf_tdls_packet *tdls_pkt;
+	printf("EVENT: TDLS\n");
+	tdls_event = (eventbuf_tdls_generic *)(buffer);
+	printf("Event Type = ");
+	switch (uap_le16_to_cpu(tdls_event->event_type)) {
+	case TDLS_EVENT_TYPE_SETUP_FAILURE:
+		printf("TDLS setup failure\n");
+		break;
+	case TDLS_EVENT_TYPE_SETUP_REQ_RCVD:
+		printf("TDLS setup request received from peer\n");
+		break;
+	case TDLS_EVENT_TYPE_LINK_TORN_DOWN:
+		printf("TDLS link torn down\n");
+		break;
+	case TDLS_EVENT_TYPE_LINK_ESTABLISHED:
+		printf("TDLS link established\n");
+		break;
+	case TDLS_EVENT_TYPE_DEBUG:
+		tdls_debug = (eventbuf_tdls_debug *)(buffer);
+		printf("TDLS debug event, ");
+		printf("TSF  = %lld\n", uap_le64_to_cpu(tdls_debug->tsf));
+		printf("String = ");
+		printf((char *)(tdls_debug->string),
+		       uap_le32_to_cpu(tdls_debug->first_arg),
+		       uap_le32_to_cpu(tdls_debug->second_arg),
+		       uap_le32_to_cpu(tdls_debug->third_arg));
+		printf("\n");
+		return;
+	case TDLS_EVENT_TYPE_PACKET:
+		tdls_pkt = (eventbuf_tdls_packet *)(buffer);
+		printf("TDLS packet len=%d\n", tdls_pkt->length);
+		hexdump((t_u8 *)tdls_pkt->data, tdls_pkt->length, ' ');
+		return;
+	case TDLS_EVENT_TYPE_CHAN_SWITCH_RESULT:
+		if (tdls_event->u.switch_result.status) {
+			printf("TDLS Channel Switch Failed! current channel=%d Reasoncode %d\n", tdls_event->u.switch_result.current_channel, tdls_event->u.switch_result.reason);
+		} else {
+			printf("TDLS Channel Switch Successful. current channel=%d\n", tdls_event->u.switch_result.current_channel);
+		}
+		break;
+	case TDLS_EVENT_TYPE_START_CHAN_SWITCH:
+		printf("TDLS Start channel switch...\n");
+		break;
+	case TDLS_EVENT_TYPE_CHAN_SWITCH_STOPPED:
+		printf("TDLS Channel Switch stopped! reason=%d\n",
+		       tdls_event->u.cs_stop_reason);
+		break;
+	default:
+		printf("Unknown\n");
+		break;
+	}
+	printf("Peer Mac Address - ");
+	print_mac(tdls_event->peer_mac_addr);
+	printf("\n");
+	if (uap_le16_to_cpu(tdls_event->event_type) ==
+	    TDLS_EVENT_TYPE_SETUP_FAILURE) {
+		switch (uap_le16_to_cpu(tdls_event->u.reason_code)) {
+		case 1:
+			printf("Reason Code = Internal error\n");
+			break;
+		case 7:
+			printf("Reason Code = Timeout waiting for response\n");
+			break;
+		case 8:
+			printf("Reason Code = Non-zero setup response status\n");
+			break;
+		default:
+			printf("Reason Code = %d\n",
+			       uap_le16_to_cpu(tdls_event->u.reason_code));
+			break;
+		}
+	} else if (uap_le16_to_cpu(tdls_event->event_type) ==
+		   TDLS_EVENT_TYPE_LINK_TORN_DOWN) {
+		switch (uap_le16_to_cpu(tdls_event->u.reason_code)) {
+		case 3:
+			printf("Reason Code = Peer station is leaving BSS\n");
+			break;
+		case 25:
+			printf("Reason Code = Peer station is unreachable on direct link\n");
+			break;
+		case 26:
+			printf("Reason Code = Unspecified\n");
+			break;
+		case 211:
+			printf("Reason Code = Setup received from TDLS peer\n");
+			break;
+		case 212:
+			printf("Reason Code = Clearing TDLS connections due to deauth/disassoc\n");
+			break;
+		default:
+			printf("Reason Code = %d\n",
+			       uap_le16_to_cpu(tdls_event->u.reason_code));
+			break;
+		}
+	} else if (uap_le16_to_cpu(tdls_event->event_type) ==
+		   TDLS_EVENT_TYPE_LINK_ESTABLISHED) {
+		int ie_len = uap_le16_to_cpu(tdls_event->u.ie_length);
+		if (ie_len) {
+			printf("Peer IE len=%d\n", ie_len);
+			hexdump((t_u8 *)tdls_event->ie_ptr, ie_len, ' ');
+		}
+	}
+}
+
+/**
+ *  @brief Prints station reject state
+ *
+ *  @param state    Fail state
+ *  @return         N/A
+ */
+void
+print_reject_state(t_u8 state)
+{
+	switch (state) {
+	case REJECT_STATE_FAIL_EAPOL_2:
+		printf("Reject state: FAIL_EAPOL_2\n");
+		break;
+	case REJECT_STATE_FAIL_EAPOL_4:
+		printf("Reject state: FAIL_EAPOL_4:\n");
+		break;
+	case REJECT_STATE_FAIL_EAPOL_GROUP_2:
+		printf("Reject state: FAIL_EAPOL_GROUP_2\n");
+		break;
+	default:
+		printf("ERR: unknown reject state %d\n", state);
+		break;
+	}
+	return;
+}
+
+/**
+ *  @brief Prints station reject reason
+ *
+ *  @param reason   Reason code
+ *  @return         N/A
+ */
+void
+print_reject_reason(t_u16 reason)
+{
+	switch (reason) {
+	case IEEEtypes_REASON_INVALID_IE:
+		printf("Reject reason: Invalid IE\n");
+		break;
+	case IEEEtypes_REASON_MIC_FAILURE:
+		printf("Reject reason: Mic Failure\n");
+		break;
+	default:
+		printf("Reject reason: %d\n", reason);
+		break;
+	}
+	return;
+}
+
+/**
+ *  @brief Prints EAPOL state
+ *
+ *  @param state    Eapol state
+ *  @return         N/A
+ */
+void
+print_eapol_state(t_u8 state)
+{
+	switch (state) {
+	case EAPOL_START:
+		printf("Eapol state: EAPOL_START\n");
+		break;
+	case EAPOL_WAIT_PWK2:
+		printf("Eapol state: EAPOL_WAIT_PWK2\n");
+		break;
+	case EAPOL_WAIT_PWK4:
+		printf("Eapol state: EAPOL_WAIT_PWK4\n");
+		break;
+	case EAPOL_WAIT_GTK2:
+		printf("Eapol state: EAPOL_WAIT_GTK2\n");
+		break;
+	case EAPOL_END:
+		printf("Eapol state: EAPOL_END\n");
+		break;
+	default:
+		printf("ERR: unknow eapol state%d\n", state);
+		break;
+	}
+	return;
+}
+
+/**
+ *  @brief Parse and print debug event data
+ *
+ *  @param buffer   Pointer to received buffer
+ *  @param size     Length of the received event data
+ *  @return         N/A
+ */
+void
+print_event_debug(t_u8 *buffer, t_u16 size)
+{
+	eventbuf_debug *event_body = NULL;
+	if (size < sizeof(eventbuf_debug)) {
+		printf("ERR:Event buffer too small!\n");
+		return;
+	}
+	event_body = (eventbuf_debug *)buffer;
+	printf("Debug Event Type: %s\n",
+	       (event_body->debug_type == 0) ? "EVENT" : "INFO");
+	printf("%s log:\n",
+	       (uap_le32_to_cpu(event_body->debug_id_major) ==
+		DEBUG_ID_MAJ_AUTHENTICATOR) ? "Authenticator" : "Assoc_agent");
+	if (uap_le32_to_cpu(event_body->debug_id_major) ==
+	    DEBUG_ID_MAJ_AUTHENTICATOR) {
+		switch (uap_le32_to_cpu(event_body->debug_id_minor)) {
+		case DEBUG_MAJ_AUTH_MIN_PWK1:
+			printf("EAPOL Key message 1 (PWK):\n");
+			hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
+				sizeof(eapol_keymsg_debug_t), ' ');
+			break;
+		case DEBUG_MAJ_AUTH_MIN_PWK2:
+			printf("EAPOL Key message 2 (PWK):\n");
+			hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
+				sizeof(eapol_keymsg_debug_t), ' ');
+			break;
+		case DEBUG_MAJ_AUTH_MIN_PWK3:
+			printf("EAPOL Key message 3 (PWK):\n");
+			hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
+				sizeof(eapol_keymsg_debug_t), ' ');
+			break;
+		case DEBUG_MAJ_AUTH_MIN_PWK4:
+			printf("EAPOL Key message 4: (PWK)\n");
+			hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
+				sizeof(eapol_keymsg_debug_t), ' ');
+			break;
+		case DEBUG_MAJ_AUTH_MIN_GWK1:
+			printf("EAPOL Key message 1: (GWK)\n");
+			hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
+				sizeof(eapol_keymsg_debug_t), ' ');
+			break;
+		case DEBUG_MAJ_AUTH_MIN_GWK2:
+			printf("EAPOL Key message 2: (GWK)\n");
+			hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
+				sizeof(eapol_keymsg_debug_t), ' ');
+			break;
+		case DEBUG_MAJ_AUTH_MIN_STA_REJ:
+			printf("Reject STA MAC: ");
+			print_mac(event_body->info.sta_reject.sta_mac_addr);
+			printf("\n");
+			print_reject_state(event_body->info.sta_reject.
+					   reject_state);
+			print_reject_reason(uap_le16_to_cpu
+					    (event_body->info.sta_reject.
+					     reject_reason));
+			break;
+		case DEBUG_MAJ_AUTH_MIN_EAPOL_TR:
+			printf("STA MAC: ");
+			print_mac(event_body->info.eapol_state.sta_mac_addr);
+			printf("\n");
+			print_eapol_state(event_body->info.eapol_state.
+					  eapol_state);
+			break;
+		default:
+			printf("ERR: unknow debug_id_minor: %d\n",
+			       (int)uap_le32_to_cpu(event_body->
+						    debug_id_minor));
+			hexdump(buffer, size, ' ');
+			return;
+		}
+	} else if (uap_le32_to_cpu(event_body->debug_id_major) ==
+		   DEBUG_ID_MAJ_ASSOC_AGENT) {
+		switch (uap_le32_to_cpu(event_body->debug_id_minor)) {
+		case DEBUG_ID_MAJ_ASSOC_MIN_WPA_IE:
+			printf("STA MAC: ");
+			print_mac(event_body->info.wpaie.sta_mac_addr);
+			printf("\n");
+			printf("wpa ie:\n");
+			hexdump(event_body->info.wpaie.wpa_ie, MAX_WPA_IE_LEN,
+				' ');
+			break;
+		case DEBUG_ID_MAJ_ASSOC_MIN_STA_REJ:
+			printf("Reject STA MAC: ");
+			print_mac(event_body->info.sta_reject.sta_mac_addr);
+			printf("\n");
+			print_reject_state(event_body->info.sta_reject.
+					   reject_state);
+			print_reject_reason(uap_le16_to_cpu
+					    (event_body->info.sta_reject.
+					     reject_reason));
+			break;
+		default:
+			printf("ERR: unknow debug_id_minor: %d\n",
+			       (int)uap_le32_to_cpu(event_body->
+						    debug_id_minor));
+			hexdump(buffer, size, ' ');
+			return;
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief Parse and print received nlist event information
+ *
+ *  @param buffer   Pointer to the data buffer
+ *  @param size     Length of the received event
+ *  @return         N/A
+ */
+void
+print_event_11k_nlist_report(t_u8 *buffer, t_u16 size)
+{
+	int tlv_buf_left = 0;
+	tlvbuf_header *tlv;
+	nlist_entry_tlv *nlist;
+	int entry_num = 0;
+	t_u16 tlv_type, tlv_len;
+
+	if (size < 2) {
+		printf("No neighbor AP list found: %d\n", size);
+		return;
+	}
+	tlv_buf_left = *(t_u16 *)buffer;
+	tlv_buf_left = uap_le16_to_cpu(tlv_buf_left);
+	if (tlv_buf_left < (int)sizeof(tlvbuf_header))
+		return;
+	printf("neighbor AP list tlv len: %d\n", tlv_buf_left);
+	tlv = (tlvbuf_header *)(buffer + 2);
+	while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
+		tlv_type = uap_le16_to_cpu(tlv->type);
+		tlv_len = uap_le16_to_cpu(tlv->len);
+		if ((sizeof(tlvbuf_header) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len,
+			       tlv_buf_left);
+			break;
+		}
+		switch (tlv_type) {
+		case MRVL_NEIGHBOR_REPORT_TLV_ID:
+			nlist = (nlist_entry_tlv *) tlv;
+			printf("Neighbor entry %d:\n", entry_num);
+			printf("BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
+			       nlist->bssid[0], nlist->bssid[1],
+			       nlist->bssid[2], nlist->bssid[3],
+			       nlist->bssid[4], nlist->bssid[5]);
+			printf("BSSID Info: %02x:%02x:%02x:%02x \n",
+			       nlist->bssid_info[0], nlist->bssid_info[1],
+			       nlist->bssid_info[2], nlist->bssid_info[3]);
+			printf("reg class: %d, chan: %d, phy: %d \n",
+			       nlist->reg_class, nlist->chan, nlist->phy_type);
+			if (tlv_len > sizeof(nlist_entry_tlv)) {
+				printf("sub IE:\n");
+				hexdump((t_u8 *)tlv + sizeof(nlist_entry_tlv),
+					tlv_len - sizeof(nlist_entry_tlv) +
+					sizeof(tlvbuf_header), ' ');
+			}
+			entry_num++;
+			break;
+		default:
+#if DEBUG
+			printf("unknown tlv: %d\n", tlv_type);
+#endif
+			break;
+		}
+		tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
+		tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len +
+					sizeof(tlvbuf_header));
+	}
+	return;
+}
+
+/**
+ *  @brief Parse and print received event information
+ *
+ *  @param event    Pointer to received event
+ *  @param size     Length of the received event
+ *  @return         N/A
+ */
+void
+print_event(event_header *event, t_u16 size)
+{
+	t_u32 event_id = event->event_id;
+	switch (event_id) {
+	case MICRO_AP_EV_ID_STA_DEAUTH:
+		print_event_sta_deauth(event->event_data, size - EVENT_ID_LEN);
+		break;
+	case MICRO_AP_EV_ID_STA_ASSOC:
+		print_event_sta_assoc(event->event_data, size - EVENT_ID_LEN);
+		break;
+	case MICRO_AP_EV_ID_BSS_START:
+		print_event_bss_start(event->event_data, size - EVENT_ID_LEN);
+		break;
+	case MICRO_AP_EV_ID_DEBUG:
+		print_event_debug(event->event_data, size - EVENT_ID_LEN);
+		break;
+	case MICRO_AP_EV_BSS_IDLE:
+		printf("EVENT: BSS_IDLE\n");
+		break;
+	case MICRO_AP_EV_BSS_ACTIVE:
+		printf("EVENT: BSS_ACTIVE\n");
+		break;
+	case MICRO_AP_EV_RSN_CONNECT:
+		print_event_rsn_connect(event->event_data, size - EVENT_ID_LEN);
+		break;
+#ifdef WIFI_DIRECT_SUPPORT
+	case EVENT_WIFIDIRECT_GENERIC:
+		print_event_wifidirect_generic(event->event_data,
+					       size - EVENT_ID_LEN);
+		break;
+	case EVENT_WIFIDIRECT_SERVICE_DISCOVERY:
+		print_event_wifidirect_service_discovery(event->event_data,
+							 size - EVENT_ID_LEN);
+		break;
+#endif
+
+	case EVENT_TDLS_GENERIC:
+		print_event_tdls_generic(event->event_data,
+					 size - EVENT_ID_LEN);
+		break;
+	case UAP_EVENT_ID_DRV_HS_ACTIVATED:
+		printf("EVENT: uAP HS_ACTIVATED\n");
+		break;
+	case UAP_EVENT_ID_DRV_HS_DEACTIVATED:
+		printf("EVENT: uAP HS_DEACTIVATED\n");
+		break;
+	case UAP_EVENT_ID_HS_WAKEUP:
+		printf("EVENT: uAP HS_WAKEUP\n");
+		break;
+	case UAP_EVENT_HOST_SLEEP_AWAKE:
+		break;
+	case UAP_EVENT_ID_DRV_MGMT_FRAME:
+		printf("EVENT: Mgmt frame from FW\n");
+		hexdump((void *)event, size, ' ');
+		break;
+	case MICRO_AP_EV_WMM_STATUS_CHANGE:
+		printf("EVENT: WMM_STATUS_CHANGE\n");
+		break;
+	case EVENT_RADAR_DETECTED:
+		printf("EVENT: RADAR_DETECTED\n");
+		break;
+	case EVENT_CHANNEL_REPORT_RDY:
+		printf("EVENT: CHANNEL_REPORT_READY\n");
+		hexdump((void *)event, size, ' ');
+		break;
+	case EVENT_WEP_ICV_ERROR:
+		print_event_wep_icv_error(event->event_data,
+					  size - EVENT_ID_LEN);
+		break;
+	case EVENT_ID_DRV_SCAN_REPORT:
+		printf("Scan request completed.\n");
+		break;
+	case EVENT_NLIST_REPORT:
+		printf("EVENT: 11k neighbor AP list report\n");
+		print_event_11k_nlist_report(event->event_data,
+					     size - EVENT_ID_LEN);
+		break;
+
+	default:
+		/* Handle string based events */
+#define CUS_EVT_PORT_RELEASE           "EVENT=PORT_RELEASE"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_PORT_RELEASE,
+		     strlen(CUS_EVT_PORT_RELEASE))) {
+			printf("EVENT: PORT_RELEASE.\n");
+			break;
+		}
+#define CUS_EVT_TDLS_CONNECTED           "EVENT=TDLS_CONNECTED"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_TDLS_CONNECTED,
+		     strlen(CUS_EVT_TDLS_CONNECTED))) {
+			printf("EVENT: TDLS_CONNECTED\n");
+			print_mac((t_u8 *)event +
+				  strlen(CUS_EVT_TDLS_CONNECTED));
+			printf("\n");
+			break;
+		}
+#define CUS_EVT_TDLS_TEARDOWN            "EVENT=TDLS_TEARDOWN"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_TDLS_TEARDOWN,
+		     strlen(CUS_EVT_TDLS_TEARDOWN))) {
+			printf("EVENT: TDLS_TEARDOWN\n");
+			print_mac((t_u8 *)event +
+				  strlen(CUS_EVT_TDLS_TEARDOWN));
+			printf("\n");
+			break;
+		}
+#define CUS_EVT_STA_CONNECTED           "EVENT=STA_CONNECTED"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_STA_CONNECTED,
+		     strlen(CUS_EVT_STA_CONNECTED))) {
+			printf("EVENT: STA_CONNECTED\n");
+			print_mac((t_u8 *)event +
+				  strlen(CUS_EVT_STA_CONNECTED) + 1);
+			printf("\n");
+			break;
+		}
+#define CUS_EVT_STA_DISCONNECTED           "EVENT=STA_DISCONNECTED"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_STA_DISCONNECTED,
+		     strlen(CUS_EVT_STA_DISCONNECTED))) {
+			printf("EVENT: STA_DISCONNECTED\n");
+			break;
+		}
+#define CUS_EVT_AP_CONNECTED           "EVENT=AP_CONNECTED"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_AP_CONNECTED,
+		     strlen(CUS_EVT_AP_CONNECTED))) {
+			printf("EVENT: AP_CONNECTED\n");
+			print_mac((t_u8 *)event + strlen(CUS_EVT_AP_CONNECTED));
+			printf("\n");
+			break;
+		}
+#define CUS_EVT_ADHOC_LINK_SENSED   "EVENT=ADHOC_LINK_SENSED"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_ADHOC_LINK_SENSED,
+		     strlen(CUS_EVT_ADHOC_LINK_SENSED))) {
+			printf("EVENT: ADHOC_LINK_SENSED\n");
+			break;
+		}
+#define CUS_EVT_ADHOC_LINK_LOST     "EVENT=ADHOC_LINK_LOST"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_ADHOC_LINK_LOST,
+		     strlen(CUS_EVT_ADHOC_LINK_LOST))) {
+			printf("EVENT: ADHOC_LINK_LOST\n");
+			break;
+		}
+#define CUS_EVT_OBSS_SCAN_PARAM     "EVENT=OBSS_SCAN_PARAM"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_OBSS_SCAN_PARAM,
+		     strlen(CUS_EVT_OBSS_SCAN_PARAM))) {
+			printf("EVENT: OBSS_SCAN_PARAM\n");
+			break;
+		}
+#define CUS_EVT_BW_CHANGED      "EVENT=BW_CHANGED"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_BW_CHANGED,
+		     strlen(CUS_EVT_BW_CHANGED))) {
+			printf("EVENT: BW_CHANGED\n");
+			break;
+		}
+#define CUS_EVT_MLME_MIC_ERR_UNI    "MLME-MICHAELMICFAILURE.indication unicast"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_MLME_MIC_ERR_UNI,
+		     strlen(CUS_EVT_MLME_MIC_ERR_UNI))) {
+			printf("EVENT: MLME-MICHAELMICFAILURE.indication unicast\n");
+			break;
+		}
+#define CUS_EVT_MLME_MIC_ERR_MUL    "MLME-MICHAELMICFAILURE.indication multicast"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_MLME_MIC_ERR_MUL,
+		     strlen(CUS_EVT_MLME_MIC_ERR_MUL))) {
+			printf("EVENT: MLME-MICHAELMICFAILURE.indication multicast\n");
+			break;
+		}
+#define CUS_EVT_BEACON_RSSI_LOW     "EVENT=BEACON_RSSI_LOW"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_BEACON_RSSI_LOW,
+		     strlen(CUS_EVT_BEACON_RSSI_LOW))) {
+			printf("EVENT: BEACON_RSSI_LOW\n");
+			break;
+		}
+#define CUS_EVT_BEACON_RSSI_HIGH    "EVENT=BEACON_RSSI_HIGH"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_BEACON_RSSI_HIGH,
+		     strlen(CUS_EVT_BEACON_RSSI_HIGH))) {
+			printf("EVENT: BEACON_RSSI_HIGH\n");
+			break;
+		}
+#define CUS_EVT_BEACON_SNR_LOW      "EVENT=BEACON_SNR_LOW"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_BEACON_SNR_LOW,
+		     strlen(CUS_EVT_BEACON_SNR_LOW))) {
+			printf("EVENT: BEACON_SNR_LOW\n");
+			break;
+		}
+#define CUS_EVT_BEACON_SNR_HIGH     "EVENT=BEACON_SNR_HIGH"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_BEACON_SNR_HIGH,
+		     strlen(CUS_EVT_BEACON_SNR_HIGH))) {
+			printf("EVENT: BEACON_SNR_HIGH\n");
+			break;
+		}
+#define CUS_EVT_MAX_FAIL        "EVENT=MAX_FAIL"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_MAX_FAIL,
+		     strlen(CUS_EVT_MAX_FAIL))) {
+			printf("EVENT: MAX_FAIL\n");
+			break;
+		}
+#define CUS_EVT_DATA_RSSI_LOW       "EVENT=DATA_RSSI_LOW"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_DATA_RSSI_LOW,
+		     strlen(CUS_EVT_DATA_RSSI_LOW))) {
+			printf("EVENT: DATA_RSSI_LOW\n");
+			break;
+		}
+#define CUS_EVT_DATA_SNR_LOW        "EVENT=DATA_SNR_LOW"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_DATA_SNR_LOW,
+		     strlen(CUS_EVT_DATA_SNR_LOW))) {
+			printf("EVENT: DATA_SNR_LOW\n");
+			break;
+		}
+#define CUS_EVT_DATA_RSSI_HIGH      "EVENT=DATA_RSSI_HIGH"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_DATA_RSSI_HIGH,
+		     strlen(CUS_EVT_DATA_RSSI_HIGH))) {
+			printf("EVENT: DATA_RSSI_HIGH\n");
+			break;
+		}
+#define CUS_EVT_DATA_SNR_HIGH       "EVENT=DATA_SNR_HIGH"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_DATA_SNR_HIGH,
+		     strlen(CUS_EVT_DATA_SNR_HIGH))) {
+			printf("EVENT: DATA_SNR_HIGH\n");
+			break;
+		}
+#define CUS_EVT_LINK_QUALITY        "EVENT=LINK_QUALITY"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_LINK_QUALITY,
+		     strlen(CUS_EVT_LINK_QUALITY))) {
+			printf("EVENT: LINK_QUALITY\n");
+			break;
+		}
+#define CUS_EVT_WEP_ICV_ERR     "EVENT=WEP_ICV_ERR"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_WEP_ICV_ERR,
+		     strlen(CUS_EVT_WEP_ICV_ERR))) {
+			printf("EVENT: WEP_ICV_ERR\n");
+			break;
+		}
+#define CUS_EVT_CHANNEL_SWITCH_ANN  "EVENT=CHANNEL_SWITCH_ANN"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_CHANNEL_SWITCH_ANN,
+		     strlen(CUS_EVT_CHANNEL_SWITCH_ANN))) {
+			printf("EVENT: CHANNEL_SWITCH_ANN\n");
+			break;
+		}
+#define CUS_EVT_HS_WAKEUP       "HS_WAKEUP"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_HS_WAKEUP,
+		     strlen(CUS_EVT_HS_WAKEUP))) {
+			printf("EVENT: HS_WAKEUP\n");
+			break;
+		}
+#define CUS_EVT_HS_ACTIVATED        "HS_ACTIVATED"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_HS_ACTIVATED,
+		     strlen(CUS_EVT_HS_ACTIVATED))) {
+			printf("EVENT: HS_ACTIVATED\n");
+			break;
+		}
+#define CUS_EVT_HS_DEACTIVATED      "HS_DEACTIVATED"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_HS_DEACTIVATED,
+		     strlen(CUS_EVT_HS_DEACTIVATED))) {
+			printf("EVENT: HS_DEACTIVATED\n");
+			break;
+		}
+/** Custom indication message sent to the application layer for WMM changes */
+#define WMM_CONFIG_CHANGE_INDICATION  "WMM_CONFIG_CHANGE.indication"
+		if (!strncmp
+		    ((char *)event, WMM_CONFIG_CHANGE_INDICATION,
+		     strlen(WMM_CONFIG_CHANGE_INDICATION))) {
+			printf("EVENT: STA_DISCONNECTED\n");
+			break;
+		}
+#define CUS_EVT_DRIVER_HANG	            "EVENT=DRIVER_HANG"
+		if (!strncmp
+		    ((char *)event, CUS_EVT_DRIVER_HANG,
+		     strlen(CUS_EVT_DRIVER_HANG))) {
+			printf("EVENT: DRIVER_HANG\n");
+			break;
+		}
+		printf("ERR:Undefined event type (0x%X). Dumping event buffer:\n", (unsigned int)event_id);
+		hexdump((void *)event, size, ' ');
+		break;
+	}
+	return;
+}
+
+/**
+ *  @brief Read event data from netlink socket
+ *
+ *  @param sk_fd    Netlink socket handler
+ *  @param buffer   Pointer to the data buffer
+ *  @param nlh      Pointer to netlink message header
+ *  @param msg      Pointer to message header
+ *  @return         Number of bytes read or MLAN_EVENT_FAILURE
+ */
+int
+read_event_netlink_socket(int sk_fd, unsigned char *buffer,
+			  struct nlmsghdr *nlh, struct msghdr *msg)
+{
+	int count = -1;
+	count = recvmsg(sk_fd, msg, 0);
+#if DEBUG
+	printf("DBG:Waiting for message from NETLINK.\n");
+#endif
+	if (count < 0) {
+		printf("ERR:NETLINK read failed!\n");
+		terminate_flag++;
+		return MLAN_EVENT_FAILURE;
+	}
+#if DEBUG
+	printf("DBG:Received message payload (%d)\n", count);
+#endif
+	if (count > NLMSG_SPACE(NL_MAX_PAYLOAD)) {
+		printf("ERR:Buffer overflow!\n");
+		return MLAN_EVENT_FAILURE;
+	}
+	memset(buffer, 0, NL_MAX_PAYLOAD);
+	memcpy(buffer, NLMSG_DATA(nlh), count - NLMSG_HDRLEN);
+#if DEBUG
+	hexdump(buffer, count - NLMSG_HDRLEN, ' ');
+#endif
+	return count - NLMSG_HDRLEN;
+}
+
+/**
+ *  @brief Configure and read event data from netlink socket
+ *
+ *  @param sk_fd    Array of netlink sockets
+ *  @param no_of_sk Number of netlink sockets opened
+ *  @param recv_buf Pointer to the array of evt_buf structures
+ *  @param timeout  Socket listen timeout value
+ *  @param nlh      Pointer to netlink message header
+ *  @param msg      Pointer to message header
+ *  @return         Number of bytes read or MLAN_EVENT_FAILURE
+ */
+int
+read_event(int *sk_fd, int no_of_sk, evt_buf *recv_buf, int timeout,
+	   struct nlmsghdr *nlh, struct msghdr *msg)
+{
+	struct timeval tv;
+	fd_set rfds;
+	int i = 0, max_sk_fd = sk_fd[0];
+	int ret = MLAN_EVENT_FAILURE;
+
+	/* Setup read fds */
+	FD_ZERO(&rfds);
+	for (i = 0; i < no_of_sk; i++) {
+		if (sk_fd[i] > max_sk_fd)
+			max_sk_fd = sk_fd[i];
+
+		if (sk_fd[i] > 0)
+			FD_SET(sk_fd[i], &rfds);
+	}
+
+	/* Initialize timeout value */
+	if (timeout != 0)
+		tv.tv_sec = timeout;
+	else
+		tv.tv_sec = UAP_RECV_WAIT_DEFAULT;
+	tv.tv_usec = 0;
+
+	/* Wait for reply */
+	ret = select(max_sk_fd + 1, &rfds, NULL, NULL, &tv);
+	if (ret == -1) {
+		/* Error */
+		terminate_flag++;
+		return MLAN_EVENT_FAILURE;
+	} else if (!ret) {
+		/* Timeout. Try again */
+		return MLAN_EVENT_FAILURE;
+	}
+	for (i = 0; i < no_of_sk; i++) {
+		if (sk_fd[i] > 0) {
+			if (FD_ISSET(sk_fd[i], &rfds)) {
+				/* Success */
+				recv_buf[i].flag = 1;
+				recv_buf[i].length =
+					read_event_netlink_socket(sk_fd[i],
+								  recv_buf[i].
+								  buffer, nlh,
+								  msg);
+				ret += recv_buf[i].length;
+			}
+		}
+	}
+	return ret;
+}
+
+/* Command line options */
+static const struct option long_opts[] = {
+	{"help", no_argument, NULL, 'h'},
+	{"version", no_argument, NULL, 'v'},
+	{NULL, 0, NULL, 0}
+};
+
+/**
+ *  @brief Determine the netlink number
+ *
+ *  @param i socket number
+ *
+ *  @return         Netlink number to use
+ */
+static int
+get_netlink_num(int i)
+{
+	FILE *fp;
+	int netlink_num = NETLINK_MARVELL;
+	char str[64];
+	char *srch = "netlink_num";
+	char filename[64];
+
+	if (i == 0) {
+		strcpy(filename, "/proc/mwlan/config");
+	} else if (i > 0) {
+		sprintf(filename, "/proc/mwlan/config%d", i);
+	}
+	/* Try to open /proc/mwlan/config$ */
+	fp = fopen(filename, "r");
+	if (fp) {
+		while (!feof(fp)) {
+			fgets(str, sizeof(str), fp);
+			if (strncmp(str, srch, strlen(srch)) == 0) {
+				netlink_num = atoi(str + strlen(srch) + 1);
+				break;
+			}
+		}
+		fclose(fp);
+	} else {
+		return -1;
+	}
+	printf("Netlink number = %d\n", netlink_num);
+	return netlink_num;
+}
+
+/****************************************************************************
+        Global functions
+****************************************************************************/
+/**
+ *  @brief The main function
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         0 or 1
+ */
+int
+main(int argc, char *argv[])
+{
+	int opt;
+	int nl_sk[MAX_NO_OF_DEVICES];
+	struct nlmsghdr *nlh = NULL;
+	struct sockaddr_nl src_addr, dest_addr;
+	struct msghdr msg;
+	struct iovec iov;
+	evt_buf evt_recv_buf[MAX_NO_OF_DEVICES];
+	struct timeval current_time;
+	struct tm *timeinfo;
+	int num_events = 0;
+	event_header *event = NULL;
+	int ret = MLAN_EVENT_FAILURE;
+	int netlink_num[MAX_NO_OF_DEVICES];
+	char if_name[IFNAMSIZ + 1];
+	t_u32 event_id = 0;
+	int i = 0, no_of_sk = 0, dev_index = -1;
+
+	/* Check command line options */
+	while ((opt = getopt_long(argc, argv, "hvti:", long_opts, NULL)) > 0) {
+		switch (opt) {
+		case 'h':
+			print_usage();
+			return 0;
+		case 'v':
+			printf("mlanevent version : %s\n", MLAN_EVENT_VERSION);
+			return 0;
+			break;
+		case 'i':
+			if ((IS_HEX_OR_DIGIT(argv[2]) == MLAN_EVENT_FAILURE) ||
+			    (A2HEXDECIMAL(argv[2]) < 0)
+			    || ((A2HEXDECIMAL(argv[2]) >= MAX_NO_OF_DEVICES) &&
+				(A2HEXDECIMAL(argv[2]) != 0xff))) {
+				print_usage();
+				return 1;
+			} else {
+				dev_index = A2HEXDECIMAL(argv[2]);
+				argc -= optind;
+				argv += optind;
+			}
+			break;
+		default:
+			print_usage();
+			return 1;
+		}
+	}
+
+	if (optind < argc) {
+		fputs("Too many arguments.\n", stderr);
+		print_usage();
+		return 1;
+	}
+	if ((dev_index >= 0) && (dev_index < MAX_NO_OF_DEVICES)) {
+		no_of_sk = 1;
+	} else {
+		/* Currently, we support maximum 4 devices */
+		/* TODO: determine no_of_sk at run time */
+		no_of_sk = MAX_NO_OF_DEVICES;
+	}
+
+	for (i = 0; i < no_of_sk; i++) {
+		/* Initialise */
+		nl_sk[i] = -1;
+		if (no_of_sk == 1) {
+			netlink_num[i] = get_netlink_num(dev_index);
+			if (netlink_num[i] < 0) {
+				printf("ERR:Could not get netlink socket. Invalid device number.\n");
+				ret = MLAN_EVENT_FAILURE;
+				goto done;
+			}
+		} else {
+			netlink_num[i] = get_netlink_num(i);
+		}
+		if (netlink_num[i] >= 0) {
+			/* Open netlink socket */
+			nl_sk[i] = socket(PF_NETLINK, SOCK_RAW, netlink_num[i]);
+			if (nl_sk[i] < 0) {
+				printf("ERR:Could not open netlink socket.\n");
+				ret = MLAN_EVENT_FAILURE;
+				goto done;
+			}
+
+			/* Set source address */
+			memset(&src_addr, 0, sizeof(src_addr));
+			src_addr.nl_family = AF_NETLINK;
+			src_addr.nl_pid = getpid();	/* Our PID */
+			src_addr.nl_groups = NL_MULTICAST_GROUP;
+
+			/* Bind socket with source address */
+			if (bind
+			    (nl_sk[i], (struct sockaddr *)&src_addr,
+			     sizeof(src_addr)) < 0) {
+				printf("ERR:Could not bind socket!\n");
+				ret = MLAN_EVENT_FAILURE;
+				goto done;
+			}
+
+			/* Set destination address */
+			memset(&dest_addr, 0, sizeof(dest_addr));
+			dest_addr.nl_family = AF_NETLINK;
+			dest_addr.nl_pid = 0;	/* Kernel */
+			dest_addr.nl_groups = NL_MULTICAST_GROUP;
+
+			/* Initialize netlink header */
+			nlh = (struct nlmsghdr *)
+				malloc(NLMSG_SPACE(NL_MAX_PAYLOAD));
+			if (!nlh) {
+				printf("ERR: Could not alloc buffer\n");
+				ret = MLAN_EVENT_FAILURE;
+				goto done;
+			}
+			memset(nlh, 0, NLMSG_SPACE(NL_MAX_PAYLOAD));
+
+			/* Initialize I/O vector */
+			iov.iov_base = (void *)nlh;
+			iov.iov_len = NLMSG_SPACE(NL_MAX_PAYLOAD);
+
+			/* Initialize message header */
+			memset(&msg, 0, sizeof(struct msghdr));
+			msg.msg_name = (void *)&dest_addr;
+			msg.msg_namelen = sizeof(dest_addr);
+			msg.msg_iov = &iov;
+			msg.msg_iovlen = 1;
+
+			memset(&evt_recv_buf[i], 0, sizeof(evt_buf));
+		}
+	}
+	gettimeofday(&current_time, NULL);
+
+	printf("\n");
+	printf("**********************************************\n");
+	if ((timeinfo = localtime(&(current_time.tv_sec))))
+		printf("mlanevent start time : %s", asctime(timeinfo));
+	printf("                      %u usecs\n",
+	       (unsigned int)current_time.tv_usec);
+	printf("**********************************************\n");
+
+	signal(SIGTERM, sig_handler);
+	signal(SIGINT, sig_handler);
+	signal(SIGALRM, sig_handler);
+	while (1) {
+		if (terminate_flag) {
+			printf("Stopping!\n");
+			break;
+		}
+		ret = read_event(nl_sk, no_of_sk, evt_recv_buf, 0, nlh, &msg);
+
+		/* No result. Loop again */
+		if (ret == MLAN_EVENT_FAILURE) {
+			continue;
+		}
+		if (ret == 0) {
+			/* Zero bytes received */
+			printf("ERR:Received zero bytes!\n");
+			continue;
+		}
+		for (i = 0; i < no_of_sk; i++) {
+			if (evt_recv_buf[i].flag == 1) {
+				num_events++;
+				gettimeofday(&current_time, NULL);
+				printf("\n");
+				printf("============================================\n");
+				printf("Received event");
+				if ((timeinfo =
+				     localtime(&(current_time.tv_sec))))
+					printf(": %s", asctime(timeinfo));
+				printf("                     %u usecs\n",
+				       (unsigned int)current_time.tv_usec);
+				printf("============================================\n");
+
+				memcpy(&event_id, evt_recv_buf[i].buffer,
+				       sizeof(event_id));
+				if (((event_id & 0xFF000000) == 0x80000000) ||
+				    ((event_id & 0xFF000000) == 0)) {
+					event = (event_header
+						 *)(evt_recv_buf[i].buffer);
+				} else {
+					memset(if_name, 0, IFNAMSIZ + 1);
+					memcpy(if_name, evt_recv_buf[i].buffer,
+					       IFNAMSIZ);
+					printf("EVENT for interface %s\n",
+					       if_name);
+					event = (event_header
+						 *)((t_u8 *)(evt_recv_buf[i].
+							     buffer) +
+						    IFNAMSIZ);
+					ret -= IFNAMSIZ;
+					evt_recv_buf[i].length -= IFNAMSIZ;
+				}
+#if DEBUG
+				printf("DBG:Received buffer =\n");
+				hexdump(evt_recv_buf[i].buffer,
+					evt_recv_buf[i].length + IFNAMSIZ, ' ');
+#endif
+				print_event(event, evt_recv_buf[i].length);
+				/* Reset event flag after reading */
+				evt_recv_buf[i].flag = 0;
+			}
+		}
+		fflush(stdout);
+	}
+	gettimeofday(&current_time, NULL);
+	printf("\n");
+	printf("*********************************************\n");
+	if ((timeinfo = localtime(&(current_time.tv_sec))))
+		printf("mlanevent end time  : %s", asctime(timeinfo));
+	printf("                     %u usecs\n",
+	       (unsigned int)current_time.tv_usec);
+	printf("Total events       : %u\n", num_events);
+	printf("*********************************************\n");
+done:
+	for (i = 0; i < no_of_sk; i++) {
+		if (nl_sk[i] > 0)
+			close(nl_sk[i]);
+	}
+	if (nlh)
+		free(nlh);
+	return 0;
+}
diff --git a/wlan_sd8897/mapp/mlanevent/mlanevent.h b/wlan_sd8897/mapp/mlanevent/mlanevent.h
new file mode 100644
index 0000000..c3b2c67
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanevent/mlanevent.h
@@ -0,0 +1,1375 @@
+/** @file  mlanevent.h
+ *
+ *  @brief Header file for mlanevent application
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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/18/08: Initial creation
+************************************************************************/
+
+#ifndef _MLAN_EVENT_H
+#define _MLAN_EVENT_H
+
+/** Character, 1 byte */
+typedef signed char t_s8;
+/** Unsigned character, 1 byte */
+typedef unsigned char t_u8;
+
+/** Short integer */
+typedef signed short t_s16;
+/** Unsigned short integer */
+typedef unsigned short t_u16;
+
+/** Integer */
+typedef signed int t_s32;
+/** Unsigned integer */
+typedef unsigned int t_u32;
+
+/** Long long integer */
+typedef long long t_s64;
+/** Unsigned long long integer */
+typedef unsigned long long t_u64;
+
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#undef BIG_ENDIAN_SUPPORT
+#endif
+
+/** 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 from 16 bit little endian format to CPU format */
+#define uap_le16_to_cpu(x) swap_byte_16(x)
+/** Convert from 32 bit little endian format to CPU format */
+#define uap_le32_to_cpu(x) swap_byte_32(x)
+/** Convert from 64 bit little endian format to CPU format */
+#define uap_le64_to_cpu(x) swap_byte_64(x)
+/** Convert to 16 bit little endian format from CPU format */
+#define uap_cpu_to_le16(x) swap_byte_16(x)
+/** Convert to 32 bit little endian format from CPU format */
+#define uap_cpu_to_le32(x) swap_byte_32(x)
+/** Convert to 64 bit little endian format from CPU format */
+#define uap_cpu_to_le64(x) swap_byte_64(x)
+#else /* BIG_ENDIAN_SUPPORT */
+/** Do nothing */
+#define uap_le16_to_cpu(x) x
+/** Do nothing */
+#define uap_le32_to_cpu(x) x
+/** Do nothing */
+#define uap_le64_to_cpu(x) x
+/** Do nothing */
+#define uap_cpu_to_le16(x) x
+/** Do nothing */
+#define uap_cpu_to_le32(x) x
+/** Do nothing */
+#define uap_cpu_to_le64(x) x
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** Convert WPS TLV header from network to host order */
+#define endian_convert_tlv_wps_header_in(t,l)       \
+    {                                               \
+        (t) = ntohs(t);       \
+        (l) = ntohs(l);       \
+    }
+
+/**
+ * Hex or Decimal to Integer
+ * @param   num string to convert into decimal or hex
+ */
+#define A2HEXDECIMAL(num)  \
+    (strncasecmp("0x", (num), 2)?(unsigned int) strtoll((num),NULL,0):a2hex((num)))\
+
+/**
+ * Check of decimal or hex string
+ * @param   num string
+ */
+#define IS_HEX_OR_DIGIT(num) \
+    (strncasecmp("0x", (num), 2)?ISDIGIT((num)):ishexstring((num)))\
+
+/** MLan Event application version string */
+#define MLAN_EVENT_VERSION         "MlanEvent 2.0"
+
+/** Failure */
+#define MLAN_EVENT_FAILURE     -1
+
+#ifdef __GNUC__
+/** Structure packing begins */
+#define PACK_START
+/** Structure packeing end */
+#define PACK_END  __attribute__ ((packed))
+#else
+/** Structure packing begins */
+#define PACK_START   __packed
+/** Structure packeing end */
+#define PACK_END
+#endif
+
+#ifndef ETH_ALEN
+/** MAC address length */
+#define ETH_ALEN    6
+#endif
+
+/** Netlink protocol number */
+#define NETLINK_MARVELL         (MAX_LINKS - 1)
+/** Netlink maximum payload size */
+#define NL_MAX_PAYLOAD          1024
+/** Netlink multicast group number */
+#define NL_MULTICAST_GROUP      1
+/** Default wait time in seconds for events */
+#define UAP_RECV_WAIT_DEFAULT   10
+/** Maximum number of devices */
+#define MAX_NO_OF_DEVICES       4
+
+#ifndef NLMSG_HDRLEN
+/** NL message header length */
+#define NLMSG_HDRLEN            ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#endif
+
+/** 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)
+
+/** Invitation Flag mask */
+#define INVITATION_FLAG_MASK            0x01
+
+/* Event buffer */
+typedef PACK_START struct _evt_buf {
+    /** Flag to check if event data is present in the buffer or not  */
+	int flag;
+    /** Event length */
+	int length;
+    /** Event data */
+	t_u8 buffer[NL_MAX_PAYLOAD];
+} PACK_END evt_buf;
+
+/** Event header */
+typedef PACK_START struct _event_header {
+    /** Event ID */
+	t_u32 event_id;
+    /** Event data */
+	t_u8 event_data[0];
+} PACK_END event_header;
+
+/** Event ID length */
+#define EVENT_ID_LEN    4
+
+/** Event ID : WMM status change */
+#define MICRO_AP_EV_WMM_STATUS_CHANGE       0x00000017
+
+/** Event ID: STA deauth */
+#define MICRO_AP_EV_ID_STA_DEAUTH           0x0000002c
+
+/** Event ID: STA associated */
+#define MICRO_AP_EV_ID_STA_ASSOC            0x0000002d
+
+/** Event ID: BSS started */
+#define MICRO_AP_EV_ID_BSS_START            0x0000002e
+
+/** Event ID: Debug event */
+#define MICRO_AP_EV_ID_DEBUG                0x00000036
+
+/** Event ID: BSS idle event */
+#define MICRO_AP_EV_BSS_IDLE                0x00000043
+
+/** Event ID: BSS active event */
+#define MICRO_AP_EV_BSS_ACTIVE              0x00000044
+
+/** Event ID: WEP ICV error */
+#define EVENT_WEP_ICV_ERROR                 0x00000046
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** Event ID: UAP,STA wifidirect generic event */
+#define EVENT_WIFIDIRECT_GENERIC                   0x00000049
+
+/** Event ID: UAP,STA wifidirect service discovery event */
+#define EVENT_WIFIDIRECT_SERVICE_DISCOVERY         0x0000004a
+#endif
+
+/** Event ID: RSN Connect event */
+#define MICRO_AP_EV_RSN_CONNECT             0x00000051
+
+/** Event ID: TDLS generic event */
+#define EVENT_TDLS_GENERIC                  0x00000052
+
+/** 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_RCVD        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
+
+/** Event ID: Radar Detected */
+#define EVENT_RADAR_DETECTED                0x00000053
+/** Event ID: Channel Report Ready */
+#define EVENT_CHANNEL_REPORT_RDY            0x00000054
+
+/** Event ID: NLIST REPORT */
+#define EVENT_NLIST_REPORT                0x00000079
+/** NLIST_REPORT TLV */
+#define MRVL_NEIGHBOR_REPORT_TLV_ID   	  0x1de
+
+/** 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 AWAKE  event id in legacy PS*/
+#define UAP_EVENT_HOST_SLEEP_AWAKE         0x00000012
+
+/** HS WAKE UP event id */
+#define UAP_EVENT_ID_DRV_MGMT_FRAME        0x80000005
+
+/** SCAN REPORT Event id */
+#define EVENT_ID_DRV_SCAN_REPORT           0x80000009
+
+/** WPA IE Tag */
+#define  IEEE_WPA_IE                 221
+/** RSN IE Tag */
+#define  IEEE_RSN_IE                 48
+
+/** TLV ID : WAPI Information */
+#define MRVL_WAPI_INFO_TLV_ID        0x0167
+
+/** TLV ID : Management Frame */
+#define MRVL_MGMT_FRAME_TLV_ID       0x0168
+
+/** TLV Id : Channel Config */
+#define MRVL_CHANNELCONFIG_TLV_ID    0x012a
+
+/** Assoc Request */
+#define SUBTYPE_ASSOC_REQUEST        0
+/** Assoc Response */
+#define SUBTYPE_ASSOC_RESPONSE       1
+/** ReAssoc Request */
+#define SUBTYPE_REASSOC_REQUEST      2
+/** ReAssoc Response */
+#define SUBTYPE_REASSOC_RESPONSE     3
+/** WEP key user input length */
+#define WEP_KEY_USER_INPUT           13
+
+/** TLV buffer header*/
+typedef PACK_START struct _tlvbuf_header {
+    /** Header type */
+	t_u16 type;
+    /** Header length */
+	t_u16 len;
+} PACK_END tlvbuf_header;
+
+/** Event body : STA deauth */
+typedef PACK_START struct _eventbuf_sta_deauth {
+    /** Deauthentication reason */
+	t_u16 reason_code;
+    /** MAC address of deauthenticated STA */
+	t_u8 sta_mac_address[ETH_ALEN];
+} PACK_END eventbuf_sta_deauth;
+
+/** Event body : WEP ICV error */
+typedef PACK_START struct _eventbuf_wep_icv_error {
+    /** Deauthentication reason */
+	t_u16 reason_code;
+    /** MAC address of deauthenticated STA */
+	t_u8 sta_mac_address[ETH_ALEN];
+    /** WEP key index */
+	t_u8 wep_key_index;
+    /** WEP key length */
+	t_u8 wep_key_length;
+    /** WEP key */
+	t_u8 wep_key[WEP_KEY_USER_INPUT];
+} PACK_END eventbuf_wep_icv_error;
+
+/** Event body : STA associated */
+typedef PACK_START struct _eventbuf_sta_assoc {
+    /** Reserved */
+	t_u8 reserved[2];
+    /** MAC address of associated STA */
+	t_u8 sta_mac_address[ETH_ALEN];
+    /** Assoc request/response buffer */
+	t_u8 assoc_payload[0];
+} PACK_END eventbuf_sta_assoc;
+
+/** Event body : RSN Connect */
+typedef PACK_START struct _eventbuf_rsn_connect {
+    /** Reserved */
+	t_u8 reserved[2];
+    /** MAC address of Station */
+	t_u8 sta_mac_address[ETH_ALEN];
+    /** WPA/WPA2 TLV IEs */
+	t_u8 tlv_list[0];
+} PACK_END eventbuf_rsn_connect;
+
+/** Event body : BSS started */
+typedef PACK_START struct _eventbuf_bss_start {
+    /** Reserved */
+	t_u8 reserved[2];
+    /** MAC address of BSS */
+	t_u8 ap_mac_address[ETH_ALEN];
+} PACK_END eventbuf_bss_start;
+
+/**
+ *                 IEEE 802.11 MAC Message Data Structures
+ *
+ * Each IEEE 802.11 MAC message includes a MAC header, a frame body (which
+ * can be empty), and a frame check sequence field. This section gives the
+ * structures that used for the MAC message headers and frame bodies that
+ * can exist in the three types of MAC messages - 1) Control messages,
+ * 2) Data messages, and 3) Management messages.
+ */
+#ifdef BIG_ENDIAN_SUPPORT
+typedef 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;
+} PACK_END IEEEtypes_FrameCtl_t;
+#else
+typedef 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;
+} PACK_END IEEEtypes_FrameCtl_t;
+#endif
+
+/** IEEEtypes_AssocRqst_t */
+typedef PACK_START struct _IEEEtypes_AssocRqst_t {
+    /** Capability Info */
+	t_u16 cap_info;
+    /** Listen Interval */
+	t_u16 listen_interval;
+    /** IE Buffer */
+	t_u8 ie_buffer[0];
+} PACK_END IEEEtypes_AssocRqst_t;
+
+/** IEEEtypes_AssocRsp_t */
+typedef PACK_START struct _IEEEtypes_AssocRsp_t {
+    /** Capability Info */
+	t_u16 cap_info;
+    /** Status Code */
+	t_u16 status_code;
+    /** AID */
+	t_u16 aid;
+} PACK_END IEEEtypes_AssocRsp_t;
+
+/** IEEEtypes_ReAssocRqst_t */
+typedef 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[ETH_ALEN];
+    /** IE Buffer */
+	t_u8 ie_buffer[0];
+} PACK_END IEEEtypes_ReAssocRqst_t;
+
+/** 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,
+};
+
+/** Band_Config_t */
+typedef 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
+} PACK_END Band_Config_t;
+
+/** TLV buffer : Channel Config */
+typedef PACK_START struct _tlvbuf_channel_config {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** Band Configuration */
+	Band_Config_t bandcfg;
+    /** Channel number */
+	t_u8 chan_number;
+} PACK_END tlvbuf_channel_config;
+
+/** MrvlIEtypes_WapiInfoSet_t */
+typedef PACK_START struct _MrvlIEtypes_WapiInfoSet_t {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** Multicast PN */
+	t_u8 multicast_PN[16];
+} PACK_END MrvlIEtypes_WapiInfoSet_t;
+
+/** MrvlIETypes_MgmtFrameSet_t */
+typedef PACK_START struct _MrvlIETypes_MgmtFrameSet_t {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** Frame Control */
+	IEEEtypes_FrameCtl_t frame_control;
+    /** Frame Contents */
+	t_u8 frame_contents[0];
+} PACK_END MrvlIETypes_MgmtFrameSet_t;
+
+/** Debug Type : Event */
+#define DEBUG_TYPE_EVENT    0
+/** Debug Type : Info */
+#define DEBUG_TYPE_INFO     1
+
+/** Major debug id: Authenticator */
+#define DEBUG_ID_MAJ_AUTHENTICATOR      1
+/** Minor debug id: PWK1 */
+#define DEBUG_MAJ_AUTH_MIN_PWK1         0
+/** Minor debug id: PWK2 */
+#define DEBUG_MAJ_AUTH_MIN_PWK2         1
+/** Minor debug id: PWK3 */
+#define DEBUG_MAJ_AUTH_MIN_PWK3         2
+/** Minor debug id: PWK4 */
+#define DEBUG_MAJ_AUTH_MIN_PWK4         3
+/** Minor debug id: GWK1 */
+#define DEBUG_MAJ_AUTH_MIN_GWK1         4
+/** Minor debug id: GWK2 */
+#define DEBUG_MAJ_AUTH_MIN_GWK2         5
+/** Minor debug id: station reject */
+#define DEBUG_MAJ_AUTH_MIN_STA_REJ      6
+/** Minor debug id: EAPOL_TR */
+#define DEBUG_MAJ_AUTH_MIN_EAPOL_TR     7
+
+/** Major debug id: Assoicate agent */
+#define DEBUG_ID_MAJ_ASSOC_AGENT        2
+/** Minor debug id: WPA IE*/
+#define DEBUG_ID_MAJ_ASSOC_MIN_WPA_IE   0
+/** Minor debug id: station reject */
+#define DEBUG_ID_MAJ_ASSOC_MIN_STA_REJ  1
+
+/** ether_hdr */
+typedef PACK_START struct {
+    /** Dest address */
+	t_u8 da[ETH_ALEN];
+    /** Src address */
+	t_u8 sa[ETH_ALEN];
+    /** Header type */
+	t_u16 type;
+} PACK_END ether_hdr_t;
+
+/** 8021x header */
+typedef PACK_START struct {
+    /** Protocol version*/
+	t_u8 protocol_ver;
+    /** Packet type*/
+	t_u8 pckt_type;
+    /** Packet len */
+	t_u8 pckt_body_len;
+} PACK_END hdr_8021x_t;
+
+/** Nonce size */
+#define NONCE_SIZE      32
+/** Max WPA IE len */
+#define MAX_WPA_IE_LEN  64
+/** EAPOL mic size */
+#define EAPOL_MIC_SIZE  16
+
+/** EAPOL key message */
+typedef PACK_START struct {
+    /** Ether header */
+	ether_hdr_t ether_hdr;
+    /** 8021x header */
+	hdr_8021x_t hdr_8021x;
+    /** desc_type */
+	t_u8 desc_type;
+    /** Key info */
+	t_u16 k;
+    /** Key length */
+	t_u16 key_length;
+    /** Replay count */
+	t_u32 replay_cnt[2];
+    /** Key nonce */
+	t_u8 key_nonce[NONCE_SIZE];
+    /** Key IV */
+	t_u8 eapol_key_iv[16];
+    /** Key RSC */
+	t_u8 key_rsc[8];
+    /** Key ID */
+	t_u8 key_id[8];
+    /** Key MIC */
+	t_u8 key_mic[EAPOL_MIC_SIZE];
+    /** Key len */
+	t_u16 key_material_len;
+    /** Key data */
+	t_u8 key_data[MAX_WPA_IE_LEN];
+} PACK_END eapol_keymsg_debug_t;
+
+/** Failure after receive EAPOL MSG2 PMK */
+#define REJECT_STATE_FAIL_EAPOL_2       1
+/** Failure after receive EAPOL MSG4 PMK*/
+#define REJECT_STATE_FAIL_EAPOL_4       2
+/** Failure after receive EAPOL Group MSG2 GWK */
+#define REJECT_STATE_FAIL_EAPOL_GROUP_2 3
+
+/** Fail reason: Invalid ie */
+#define IEEEtypes_REASON_INVALID_IE     13
+/** Fail reason: Mic failure */
+#define IEEEtypes_REASON_MIC_FAILURE    14
+
+/** Station reject */
+typedef PACK_START struct {
+    /** Reject state */
+	t_u8 reject_state;
+    /** Reject reason */
+	t_u16 reject_reason;
+    /** Station mac address */
+	t_u8 sta_mac_addr[ETH_ALEN];
+} PACK_END sta_reject_t;
+
+/** wpa_ie */
+typedef PACK_START struct {
+    /** Station mac address */
+	t_u8 sta_mac_addr[ETH_ALEN];
+    /** WPA IE */
+	t_u8 wpa_ie[MAX_WPA_IE_LEN];
+} PACK_END wpaie_t;
+
+/** Initial state of the state machine */
+#define EAPOL_START         1
+/** Sent eapol msg1, wait for msg2 from the client */
+#define EAPOL_WAIT_PWK2     2
+/** Sent eapol msg3, wait for msg4 from the client */
+#define EAPOL_WAIT_PWK4     3
+/** Sent eapol group key msg1, wait for group msg2 from the client */
+#define EAPOL_WAIT_GTK2     4
+/** Eapol handshake complete */
+#define EAPOL_END           5
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** TLV : WifiDirect status */
+#define TLV_TYPE_WIFIDIRECT_STATUS               0x0000
+/** TLV : WifiDirect param capability */
+#define TLV_TYPE_WIFIDIRECT_CAPABILITY           0x0002
+/** TLV : WifiDirect param device Id */
+#define TLV_TYPE_WIFIDIRECT_DEVICE_ID            0x0003
+/** TLV : WifiDirect param group owner intent */
+#define TLV_TYPE_WIFIDIRECT_GROUPOWNER_INTENT    0x0004
+/** TLV : WifiDirect param config timeout */
+#define TLV_TYPE_WIFIDIRECT_CONFIG_TIMEOUT       0x0005
+/** TLV : WifiDirect param channel */
+#define TLV_TYPE_WIFIDIRECT_CHANNEL              0x0006
+/** TLV : WifiDirect param group bssId */
+#define TLV_TYPE_WIFIDIRECT_GROUP_BSS_ID         0x0007
+/** TLV : WifiDirect param extended listen time */
+#define TLV_TYPE_WIFIDIRECT_EXTENDED_LISTEN_TIME 0x0008
+/** TLV : WifiDirect param intended address */
+#define TLV_TYPE_WIFIDIRECT_INTENDED_ADDRESS     0x0009
+/** TLV : WifiDirect param manageability */
+#define TLV_TYPE_WIFIDIRECT_MANAGEABILITY        0x000a
+/** TLV : WifiDirect param channel list */
+#define TLV_TYPE_WIFIDIRECT_CHANNEL_LIST         0x000b
+/** TLV : WifiDirect Notice of Absence */
+#define TLV_TYPE_WIFIDIRECT_NOTICE_OF_ABSENCE    0x000c
+/** TLV : WifiDirect param device Info */
+#define TLV_TYPE_WIFIDIRECT_DEVICE_INFO          0x000d
+/** TLV : WifiDirect param Group Info */
+#define TLV_TYPE_WIFIDIRECT_GROUP_INFO           0x000e
+/** TLV : WifiDirect param group Id */
+#define TLV_TYPE_WIFIDIRECT_GROUP_ID             0x000f
+/** TLV : WifiDirect param interface */
+#define TLV_TYPE_WIFIDIRECT_INTERFACE            0x0010
+/** TLV : WifiDirect param operating channel */
+#define TLV_TYPE_WIFIDIRECT_OPCHANNEL            0x0011
+/** TLV : WifiDirect param invitation flag */
+#define TLV_TYPE_WIFIDIRECT_INVITATION_FLAG      0x0012
+
+/** WPS Device Info OUI+Type+SubType Length */
+#define WPS_DEVICE_TYPE_LEN             8
+
+/** IE header len */
+#define IE_HEADER_LEN                   2
+
+/** WIFIDIRECT IE header len */
+#define WIFIDIRECT_IE_HEADER_LEN               3
+
+/** OUI Type WIFIDIRECT */
+#define WIFIDIRECT_OUI_TYPE                    9
+/** OUI Type WPS */
+#define WIFI_WPS_OUI_TYPE               4
+
+/*
+ * To handle overlapping WIFIDIRECT IEs
+ */
+/** IE next byte type */
+#define WIFIDIRECT_OVERLAP_TYPE                1
+/** IE next byte length */
+#define WIFIDIRECT_OVERLAP_LEN                 2
+/** IE next byte data */
+#define WIFIDIRECT_OVERLAP_DATA                3
+
+/** Max payload for IE buffer  */
+#define WIFI_IE_MAX_PAYLOAD             256
+
+/** Fixed length fields in bonjour payload query data */
+#define WIFIDIRECT_DISCOVERY_BONJOUR_FIXED_LEN  5
+
+/** Fixed length fields in uPnP payload query data */
+#define WIFIDIRECT_DISCOVERY_UPNP_FIXED_LEN     3
+
+/** Action field for discovery request */
+#define WIFIDIRECT_DISCOVERY_REQUEST_ACTION     10
+
+/** Action field for discovery response */
+#define WIFIDIRECT_DISCOVERY_RESPONSE_ACTION    11
+
+/** TLV buffer : WifiDirect Status */
+typedef PACK_START struct _tlvbuf_wifidirect_status {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT status code */
+	t_u8 status_code;
+} PACK_END tlvbuf_wifidirect_status;
+
+/** TLV buffer : wifidirect IE device Id */
+typedef PACK_START struct _tlvbuf_wifidirect_device_id {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT device MAC address */
+	t_u8 dev_mac_address[ETH_ALEN];
+} PACK_END tlvbuf_wifidirect_device_id;
+
+/** TLV buffer : wifidirect IE capability */
+typedef PACK_START struct _tlvbuf_wifidirect_capability {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT device capability */
+	t_u8 dev_capability;
+    /** WIFIDIRECT group capability */
+	t_u8 group_capability;
+} PACK_END tlvbuf_wifidirect_capability;
+
+/** TLV buffer : wifidirect IE Group owner intent */
+typedef PACK_START struct _tlvbuf_wifidirect_group_owner_intent {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT device group owner intent */
+	t_u8 dev_intent;
+} PACK_END tlvbuf_wifidirect_group_owner_intent;
+
+/** TLV buffer : WifiDirect IE Manageability */
+typedef PACK_START struct _tlvbuf_wifidirect_manageability {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT Manageability */
+	t_u8 manageability;
+} PACK_END tlvbuf_wifidirect_manageability;
+
+/** TLV buffer : WifiDirect IE Invitation Flag */
+typedef PACK_START struct _tlvbuf_wifidirect_invitation_flag {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT Manageability */
+	t_u8 invitation_flag;
+} PACK_END tlvbuf_wifidirect_invitation_flag;
+
+/** TLV buffer : wifidirect IE capability */
+typedef PACK_START struct _tlvbuf_wifidirect_channel {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT country string */
+	t_u8 country_string[3];
+    /** WIFIDIRECT regulatory class */
+	t_u8 regulatory_class;
+    /** WIFIDIRECT channel number */
+	t_u8 channel_number;
+} PACK_END tlvbuf_wifidirect_channel;
+
+/** Channel Entry */
+typedef PACK_START struct _chan_entry {
+    /** WIFIDIRECT regulatory class */
+	t_u8 regulatory_class;
+    /** WIFIDIRECT no of channels */
+	t_u8 num_of_channels;
+    /** WIFIDIRECT channel number */
+	t_u8 chan_list[0];
+} PACK_END chan_entry;
+
+/** TLV buffer : wifidirect IE channel list */
+typedef PACK_START struct _tlvbuf_wifidirect_channel_list {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT country string */
+	t_u8 country_string[3];
+    /** WIFIDIRECT channel entries */
+	chan_entry wifidirect_chan_entry_list[0];
+} PACK_END tlvbuf_wifidirect_channel_list;
+
+/** NoA Descriptor */
+typedef PACK_START struct _noa_descriptor {
+    /** WIFIDIRECT count OR type */
+	t_u8 count_type;
+    /** WIFIDIRECT duration */
+	t_u32 duration;
+    /** WIFIDIRECT interval */
+	t_u32 interval;
+    /** WIFIDIRECT start time */
+	t_u32 start_time;
+} PACK_END noa_descriptor;
+
+/** TLV buffer : WifiDirect IE Notice of Absence */
+typedef PACK_START struct _tlvbuf_wifidirect_notice_of_absence {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT NoA Index */
+	t_u8 noa_index;
+    /** WIFIDIRECT CTWindow and OppPS parameters */
+	t_u8 ctwindow_opp_ps;
+    /** WIFIDIRECT NoA Descriptor list */
+	noa_descriptor wifidirect_noa_descriptor_list[0];
+} PACK_END tlvbuf_wifidirect_notice_of_absence;
+
+/** TLV buffer : wifidirect IE device Info */
+typedef PACK_START struct _tlvbuf_wifidirect_device_info {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT device address */
+	t_u8 dev_address[ETH_ALEN];
+    /** WPS config methods */
+	t_u16 config_methods;
+    /** Primary device type : category */
+	t_u16 primary_category;
+    /** Primary device type : OUI */
+	t_u8 primary_oui[4];
+    /** Primary device type : sub-category */
+	t_u16 primary_subcategory;
+    /** Secondary Device Count */
+	t_u8 secondary_dev_count;
+    /** Secondary Device Info */
+	t_u8 secondary_dev_info[0];
+    /** WPS Device Name Tag */
+	t_u16 device_name_type;
+    /** WPS Device Name Length */
+	t_u16 device_name_len;
+    /** Device name */
+	t_u8 device_name[0];
+} PACK_END tlvbuf_wifidirect_device_info;
+
+typedef PACK_START struct _wifidirect_client_dev_info {
+    /** Length of each device */
+	t_u8 dev_length;
+    /** WIFIDIRECT device address */
+	t_u8 wifidirect_dev_address[ETH_ALEN];
+    /** WIFIDIRECT Interface  address */
+	t_u8 wifidirect_intf_address[ETH_ALEN];
+    /** WIFIDIRECT Device capability*/
+	t_u8 wifidirect_dev_capability;
+    /** WPS config methods */
+	t_u16 config_methods;
+    /** Primary device type : category */
+	t_u16 primary_category;
+    /** Primary device type : OUI */
+	t_u8 primary_oui[4];
+    /** Primary device type : sub-category */
+	t_u16 primary_subcategory;
+    /** Secondary Device Count */
+	t_u8 wifidirect_secondary_dev_count;
+    /** Secondary Device Info */
+	t_u8 wifidirect_secondary_dev_info[0];
+    /** WPS WIFIDIRECT Device Name Tag */
+	t_u16 wifidirect_device_name_type;
+    /** WPS WIFIDIRECT Device Name Length */
+	t_u16 wifidirect_device_name_len;
+    /** WIFIDIRECT Device name */
+	t_u8 wifidirect_device_name[0];
+} PACK_END wifidirect_client_dev_info;
+
+typedef PACK_START struct _tlvbuf_wifidirect_group_info {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** Secondary Device Info */
+	t_u8 wifidirect_client_dev_list[0];
+} PACK_END tlvbuf_wifidirect_group_info;
+
+/** TLV buffer : wifidirect IE group Id */
+typedef PACK_START struct _tlvbuf_wifidirect_group_id {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT group MAC address */
+	t_u8 group_address[ETH_ALEN];
+    /** WIFIDIRECT group SSID */
+	t_u8 group_ssid[0];
+} PACK_END tlvbuf_wifidirect_group_id;
+
+/** TLV buffer : wifidirect IE group BSS Id */
+typedef PACK_START struct _tlvbuf_wifidirect_group_bss_id {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT group Bss Id */
+	t_u8 group_bssid[ETH_ALEN];
+} PACK_END tlvbuf_wifidirect_group_bss_id;
+
+/** TLV buffer : wifidirect IE Interface */
+typedef PACK_START struct _tlvbuf_wifidirect_interface {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT interface Id */
+	t_u8 interface_id[ETH_ALEN];
+    /** WIFIDIRECT interface count */
+	t_u8 interface_count;
+    /** WIFIDIRECT interface addresslist */
+	t_u8 interface_idlist[0];
+} PACK_END tlvbuf_wifidirect_interface;
+
+/** TLV buffer : WifiDirect configuration timeout */
+typedef PACK_START struct _tlvbuf_wifidirect_config_timeout {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** Group configuration timeout */
+	t_u8 group_config_timeout;
+    /** Device configuration timeout */
+	t_u8 device_config_timeout;
+} PACK_END tlvbuf_wifidirect_config_timeout;
+
+/** TLV buffer : WifiDirect extended listen time */
+typedef PACK_START struct _tlvbuf_wifidirect_ext_listen_time {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** Availability period */
+	t_u16 availability_period;
+    /** Availability interval */
+	t_u16 availability_interval;
+} PACK_END tlvbuf_wifidirect_ext_listen_time;
+
+/** TLV buffer : WifiDirect Intended Interface Address */
+typedef PACK_START struct _tlvbuf_wifidirect_intended_addr {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT Group interface address */
+	t_u8 group_address[ETH_ALEN];
+} PACK_END tlvbuf_wifidirect_intended_addr;
+
+/** TLV buffer : Wifi WPS IE */
+typedef PACK_START struct _tlvbuf_wifi_wps_ie {
+    /** TLV Header tag */
+	t_u16 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFI WPS IE data */
+	t_u8 data[0];
+} PACK_END tlvbuf_wps_ie;
+
+/** WifiDirect IE Header */
+typedef PACK_START struct _wifidirect_ie_header {
+    /** Element ID */
+	t_u8 element_id;
+    /** IE Length */
+	t_u8 ie_length;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI type */
+	t_u8 oui_type;
+    /** IE List of TLV */
+	t_u8 ie_list[0];
+} PACK_END wifidirect_ie_header;
+
+/** Event : WifiDirect Generic event */
+typedef PACK_START struct _apeventbuf_wifidirect_generic {
+    /** Event Length */
+	t_u16 event_length;
+    /** Event Type */
+	t_u16 event_type;
+    /** Event SubType */
+	t_u16 event_sub_type;
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** IE List of TLV */
+	t_u8 entire_ie_list[0];
+} PACK_END apeventbuf_wifidirect_generic;
+
+/** Internal WIFIDIRECT structure for Query Data */
+typedef PACK_START struct wifidirect_query_data {
+	union {
+		PACK_START struct upnp_specific_query {
+	    /** version field */
+			t_u8 version;
+	    /** value */
+			t_u8 value[0];
+		} PACK_END upnp;
+
+		PACK_START struct bonjour_specific_query {
+	    /** DNS name */
+			t_u8 dns[0];
+	    /** DNS type */
+			t_u8 dns_type;
+	    /** version field */
+			t_u8 version;
+		} PACK_END bonjour;
+	} u;
+} PACK_END wifidirect_query_data;
+
+/** Internal WIFIDIRECT structure for Response Data */
+typedef PACK_START struct wifidirect_Response_data {
+	union {
+		PACK_START struct upnp_specific_response {
+	    /** version field */
+			t_u8 version;
+	    /** value */
+			t_u8 value[0];
+		} PACK_END upnp;
+
+		PACK_START struct bonjour_specific_response {
+	    /** DNS name */
+			t_u8 dns[0];
+	    /** DNS type */
+			t_u8 dns_type;
+	    /** version field */
+			t_u8 version;
+	    /** DNS name */
+			t_u8 record[0];
+		} PACK_END bonjour;
+	} u;
+} PACK_END wifidirect_response_data;
+
+/** Event : Service Discovery request */
+typedef PACK_START struct _apeventbuf_wifidirect_discovery_request {
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** Category */
+	t_u8 category;
+    /** Action */
+	t_u8 action;
+    /** Dialog taken */
+	t_u8 dialog_taken;
+    /** Advertize protocol IE */
+	t_u8 advertize_protocol_ie[4];
+    /** Query request Length */
+	t_u16 query_len;
+    /** Information identifier */
+	t_u8 info_id[2];
+    /** Request Length */
+	t_u16 request_len;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI sub type */
+	t_u8 oui_sub_type;
+    /** Service update indicator */
+	t_u16 service_update_indicator;
+    /** Vendor Length */
+	t_u16 vendor_len;
+    /** Service protocol */
+	t_u8 service_protocol;
+    /** Service transaction Id */
+	t_u8 service_transaction_id;
+    /** Query Data */
+	wifidirect_query_data disc_query;
+} PACK_END apeventbuf_wifidirect_discovery_request;
+
+/** HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY response */
+typedef PACK_START struct _apeventbuf_wifidirect_discovery_response {
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** Category */
+	t_u8 category;
+    /** Action */
+	t_u8 action;
+    /** Dialog taken */
+	t_u8 dialog_taken;
+    /** Status code */
+	t_u8 status_code;
+    /** GAS comback reply */
+	t_u16 gas_reply;
+    /** Advertize protocol IE */
+	t_u8 advertize_protocol_ie[4];
+    /** Query response Length */
+	t_u16 query_len;
+    /** Information identifier */
+	t_u8 info_id[2];
+    /** Response Length */
+	t_u16 response_len;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI sub type */
+	t_u8 oui_sub_type;
+    /** Service update indicator */
+	t_u16 service_update_indicator;
+    /** Vendor Length */
+	t_u16 vendor_len;
+    /** Service protocol */
+	t_u8 service_protocol;
+    /** Service transaction Id */
+	t_u8 service_transaction_id;
+    /** Discovery status code */
+	t_u8 disc_status_code;
+    /** Response Data */
+	wifidirect_response_data disc_resp;
+} PACK_END apeventbuf_wifidirect_discovery_response;
+
+/** enum : WPS attribute type */
+typedef enum {
+	SC_AP_Channel = 0x1001,
+	SC_Association_State = 0x1002,
+	SC_Authentication_Type = 0x1003,
+	SC_Authentication_Type_Flags = 0x1004,
+	SC_Authenticator = 0x1005,
+	SC_Config_Methods = 0x1008,
+	SC_Configuration_Error = 0x1009,
+	SC_Confirmation_URL4 = 0x100A,
+	SC_Confirmation_URL6 = 0x100B,
+	SC_Connection_Type = 0x100C,
+	SC_Connection_Type_Flags = 0x100D,
+	SC_Credential = 0x100E,
+	SC_Device_Name = 0x1011,
+	SC_Device_Password_ID = 0x1012,
+	SC_E_Hash1 = 0x1014,
+	SC_E_Hash2 = 0x1015,
+	SC_E_SNonce1 = 0x1016,
+	SC_E_SNonce2 = 0x1017,
+	SC_Encrypted_Settings = 0x1018,
+	SC_Encryption_Type = 0X100F,
+	SC_Encryption_Type_Flags = 0x1010,
+	SC_Enrollee_Nonce = 0x101A,
+	SC_Feature_ID = 0x101B,
+	SC_Identity = 0X101C,
+	SC_Identity_Proof = 0X101D,
+	SC_Key_Wrap_Authenticator = 0X101E,
+	SC_Key_Identifier = 0X101F,
+	SC_MAC_Address = 0x1020,
+	SC_Manufacturer = 0x1021,
+	SC_Message_Type = 0x1022,
+	SC_Model_Name = 0x1023,
+	SC_Model_Number = 0x1024,
+	SC_Network_Index = 0x1026,
+	SC_Network_Key = 0x1027,
+	SC_Network_Key_Index = 0x1028,
+	SC_New_Device_Name = 0x1029,
+	SC_New_Password = 0x102A,
+	SC_OOB_Device_Password = 0X102C,
+	SC_OS_Version = 0X102D,
+	SC_Power_Level = 0X102F,
+	SC_PSK_Current = 0x1030,
+	SC_PSK_Max = 0x1031,
+	SC_Public_Key = 0x1032,
+	SC_Radio_Enabled = 0x1033,
+	SC_Reboot = 0x1034,
+	SC_Registrar_Current = 0x1035,
+	SC_Registrar_Established = 0x1036,
+	SC_Registrar_List = 0x1037,
+	SC_Registrar_Max = 0x1038,
+	SC_Registrar_Nonce = 0x1039,
+	SC_Request_Type = 0x103A,
+	SC_Response_Type = 0x103B,
+	SC_RF_Band = 0X103C,
+	SC_R_Hash1 = 0X103D,
+	SC_R_Hash2 = 0X103E,
+	SC_R_SNonce1 = 0X103F,
+	SC_R_SNonce2 = 0x1040,
+	SC_Selected_Registrar = 0x1041,
+	SC_Serial_Number = 0x1042,
+	SC_Simple_Config_State = 0x1044,
+	SC_SSID = 0x1045,
+	SC_Total_Networks = 0x1046,
+	SC_UUID_E = 0x1047,
+	SC_UUID_R = 0x1048,
+	SC_Vendor_Extension = 0x1049,
+	SC_Version = 0x104A,
+	SC_X_509_Certificate_Request = 0x104B,
+	SC_X_509_Certificate = 0x104C,
+	SC_EAP_Identity = 0x104D,
+	SC_Message_Counter = 0x104E,
+	SC_Public_Key_Hash = 0x104F,
+	SC_Rekey_Key = 0x1050,
+	SC_Key_Lifetime = 0x1051,
+	SC_Permitted_Config_Methods = 0x1052,
+	SC_SelectedRegistrarConfigMethods = 0x1053,
+	SC_Primary_Device_Type = 0x1054,
+	SC_Secondary_Device_Type_List = 0x1055,
+	SC_Portable_Device = 0x1056,
+	SC_AP_Setup_Locked = 0x1057,
+	SC_Application_List = 0x1058,
+	SC_EAP_Type = 0x1059,
+	SC_Initialization_Vector = 0x1060,
+	SC_Key_Provided_Auto = 0x1061,
+	SC_8021x_Enabled = 0x1062,
+	SC_App_Session_key = 0x1063,
+	SC_WEP_Transmit_Key = 0x1064,
+} wps_simple_config_attribute;
+#endif
+
+/** structure for channel switch result from TDLS FW */
+typedef PACK_START struct _Channel_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;
+} PACK_END Channel_switch_result;
+
+/** Event : TDLS Generic event */
+typedef PACK_START struct _eventbuf_tdls_generic {
+    /** Event Type */
+	t_u16 event_type;
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+	union {
+	/** channel switch result structure*/
+		Channel_switch_result switch_result;
+	/** channel switch stop reason */
+		t_u8 cs_stop_reason;
+	/** Reason code */
+		t_u16 reason_code;
+	/** IE Length */
+		t_u16 ie_length;
+	} u;
+    /** IE pointer */
+	t_u8 ie_ptr[0];
+} PACK_END eventbuf_tdls_generic;
+
+/** Event : TDLS Debug event */
+typedef PACK_START struct _eventbuf_tdls_debug {
+    /** Event Type */
+	t_u16 event_type;
+    /** TimeStamp value */
+	t_u64 tsf;
+    /** First argument */
+	t_u32 first_arg;
+    /** Second argument */
+	t_u32 second_arg;
+    /** Third argument */
+	t_u32 third_arg;
+    /** Third argument */
+	t_u16 string_len;
+    /** Third argument */
+	t_u8 string[0];
+} PACK_END eventbuf_tdls_debug;
+
+/** Event : TDLS packet event */
+typedef PACK_START struct _eventbuf_tdls_packet {
+    /** Event Type */
+	t_u16 event_type;
+    /** Length */
+	t_u16 length;
+    /** packet data */
+	t_u8 data[0];
+} PACK_END eventbuf_tdls_packet;
+
+/** Eapol state */
+typedef PACK_START struct {
+    /** Eapol state*/
+	t_u8 eapol_state;
+    /** Station address*/
+	t_u8 sta_mac_addr[ETH_ALEN];
+} PACK_END eapol_state_t;
+
+/** Debug Info */
+typedef PACK_START union {
+    /** Eapol key message */
+	eapol_keymsg_debug_t eapol_pwkmsg;
+    /** Station reject*/
+	sta_reject_t sta_reject;
+    /** WPA IE */
+	wpaie_t wpaie;
+    /** Eapol state */
+	eapol_state_t eapol_state;
+} PACK_END d_info;
+
+/** Event body : Debug */
+typedef PACK_START struct _eventbuf_debug {
+    /** Debug type */
+	t_u8 debug_type;
+    /** Major debug id */
+	t_u32 debug_id_major;
+    /** Minor debug id */
+	t_u32 debug_id_minor;
+    /** Debug Info */
+	d_info info;
+} PACK_END eventbuf_debug;
+
+/** Event body : 11K NLIST */
+typedef PACK_START struct _nlist_entry_tlv {
+	tlvbuf_header hdr;
+	t_u8 bssid[6];
+	t_u8 bssid_info[4];
+	t_u8 reg_class;
+	t_u8 chan;
+	t_u8 phy_type;
+} PACK_END nlist_entry_tlv;
+
+int ishexstring(void *hex);
+unsigned int a2hex(char *s);
+/**
+ *    @brief isdigit for String.
+ *
+ *    @param x            Char string
+ *    @return             MLAN_EVENT_FAILURE for non-digit.
+ *                        0 for digit
+ */
+static inline int
+ISDIGIT(char *x)
+{
+	unsigned int i;
+	for (i = 0; i < strlen(x); i++)
+		if (isdigit(x[i]) == 0)
+			return MLAN_EVENT_FAILURE;
+	return 0;
+}
+
+#endif /* _MLAN_EVENT_H */
diff --git a/wlan_sd8897/mapp/mlanutl/Makefile b/wlan_sd8897/mapp/mlanutl/Makefile
new file mode 100644
index 0000000..b166f79
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/Makefile
@@ -0,0 +1,54 @@
+# File : mlanutl/Makefile
+#
+# Copyright (C) 2011-2017, Marvell International Ltd. All Rights Reserved
+
+# Path to the top directory of the wlan distribution
+PATH_TO_TOP = ../..
+
+# Determine how we should copy things to the install directory
+ABSPATH := $(filter /%, $(INSTALLDIR))
+RELPATH := $(filter-out /%, $(INSTALLDIR))
+INSTALLPATH := $(ABSPATH)
+ifeq ($(strip $(INSTALLPATH)),)
+INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH)
+endif
+
+# Override CFLAGS for application sources, remove __ kernel namespace defines
+CFLAGS := $(filter-out -D__%, $(ccflags-y))
+# remove KERNEL include dir
+CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS))
+
+
+#CFLAGS += -DAP22 -fshort-enums
+CFLAGS += -Wall
+#ECHO = @
+LIBS = -lrt
+
+.PHONY: default tags all
+
+OBJECTS = mlanutl.o
+HEADERS = mlanutl.h
+
+
+
+exectarget=mlanutl
+TARGET := $(exectarget)
+
+build default: $(TARGET)
+	@cp -f $(TARGET) $(INSTALLPATH)
+
+all : tags default
+
+$(TARGET): $(OBJECTS) $(HEADERS)
+	$(ECHO)$(CC) $(LIBS) -o $@ $(OBJECTS)
+
+%.o: %.c $(HEADERS)
+	$(ECHO)$(CC) $(CFLAGS) -c -o $@ $<
+
+tags:
+	ctags -R -f tags.txt
+
+distclean clean:
+	$(ECHO)$(RM) $(OBJECTS) $(TARGET)
+	$(ECHO)$(RM) tags.txt
+
diff --git a/wlan_sd8897/mapp/mlanutl/mlanhostcmd.c b/wlan_sd8897/mapp/mlanutl/mlanhostcmd.c
new file mode 100644
index 0000000..e61220f
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanhostcmd.c
@@ -0,0 +1,921 @@
+/** @file  mlanhostcmd.c
+  *
+  * @brief This file contains mlanutl helper functions
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     11/26/2008: initial version
+************************************************************************/
+
+#include	"mlanhostcmd.h"
+
+#ifndef MIN
+/** Find minimum value */
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief get hostcmd data
+ *
+ *  @param ln			A pointer to line number
+ *  @param buf			A pointer to hostcmd data
+ *  @param size			A pointer to the return size of hostcmd buffer
+ *  @return      		MLAN_STATUS_SUCCESS
+ */
+static int
+mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
+{
+	t_s32 errors = 0, i;
+	t_s8 line[256], *pos, *pos1, *pos2, *pos3;
+	t_u16 len;
+
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
+		(*ln)++;
+		if (strcmp(pos, "}") == 0) {
+			break;
+		}
+
+		pos1 = strchr(pos, ':');
+		if (pos1 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos1++ = '\0';
+
+		pos2 = strchr(pos1, '=');
+		if (pos2 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos2++ = '\0';
+
+		len = a2hex_or_atoi(pos1);
+		if (len < 1 || len > MRVDRV_SIZE_OF_CMD_BUFFER) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+
+		*size += len;
+
+		if (*pos2 == '"') {
+			pos2++;
+			pos3 = strchr(pos2, '"');
+			if (pos3 == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln,
+				       pos);
+				errors++;
+				continue;
+			}
+			*pos3 = '\0';
+			memset(buf, 0, len);
+			memmove(buf, pos2, MIN(strlen(pos2), len));
+			buf += len;
+		} else if (*pos2 == '\'') {
+			pos2++;
+			pos3 = strchr(pos2, '\'');
+			if (pos3 == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln,
+				       pos);
+				errors++;
+				continue;
+			}
+			*pos3 = ',';
+			for (i = 0; i < len; i++) {
+				pos3 = strchr(pos2, ',');
+				if (pos3 != NULL) {
+					*pos3 = '\0';
+					*buf++ = (t_u8)a2hex_or_atoi(pos2);
+					pos2 = pos3 + 1;
+				} else
+					*buf++ = 0;
+			}
+		} else if (*pos2 == '{') {
+			t_u16 tlvlen = 0, tmp_tlvlen;
+			mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen);
+			tmp_tlvlen = tlvlen;
+			while (len--) {
+				*buf++ = (t_u8)(tmp_tlvlen & 0xff);
+				tmp_tlvlen >>= 8;
+			}
+			*size += tlvlen;
+			buf += tlvlen;
+		} else {
+			t_u32 value = a2hex_or_atoi(pos2);
+			while (len--) {
+				*buf++ = (t_u8)(value & 0xff);
+				value >>= 8;
+			}
+		}
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief convert char to hex integer
+ *
+ *  @param chr 		char to convert
+ *  @return      	hex integer or 0
+ */
+int
+hexval(t_s32 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 Hump hex data
+ *
+ *  @param prompt	A pointer prompt buffer
+ *  @param p		A pointer to data buffer
+ *  @param len		the len of data buffer
+ *  @param delim	delim char
+ *  @return            	hex integer
+ */
+t_void
+hexdump(t_s8 *prompt, t_void *p, t_s32 len, t_s8 delim)
+{
+	t_s32 i;
+	t_u8 *s = p;
+
+	if (prompt) {
+		printf("%s: len=%d\n", prompt, (int)len);
+	}
+	for (i = 0; i < len; i++) {
+		if (i != len - 1)
+			printf("%02x%c", *s++, delim);
+		else
+			printf("%02x\n", *s);
+		if ((i + 1) % 16 == 0)
+			printf("\n");
+	}
+	printf("\n");
+}
+
+/**
+ *  @brief convert char to hex integer
+ *
+ *  @param chr		char
+ *  @return            	hex integer
+ */
+t_u8
+hexc2bin(t_s8 chr)
+{
+	if (chr >= '0' && chr <= '9')
+		chr -= '0';
+	else if (chr >= 'A' && chr <= 'F')
+		chr -= ('A' - 10);
+	else if (chr >= 'a' && chr <= 'f')
+		chr -= ('a' - 10);
+
+	return chr;
+}
+
+/**
+ *  @brief convert string to hex integer
+ *
+ *  @param s		A pointer string buffer
+ *  @return            	hex integer
+ */
+t_u32
+a2hex(t_s8 *s)
+{
+	t_u32 val = 0;
+
+	if (!strncasecmp("0x", s, 2)) {
+		s += 2;
+	}
+
+	while (*s && isxdigit(*s)) {
+		val = (val << 4) + hexc2bin(*s++);
+	}
+
+	return val;
+}
+
+/*
+ *  @brief convert String to integer
+ *
+ *  @param value	A pointer to string
+ *  @return             integer
+ */
+t_u32
+a2hex_or_atoi(t_s8 *value)
+{
+	if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) {
+		return a2hex(value + 2);
+	} else if (isdigit(*value)) {
+		return atoi(value);
+	} else {
+		return *value;
+	}
+}
+
+/**
+ *  @brief convert string to hex
+ *
+ *  @param ptr		A pointer to data buffer
+ *  @param chr 		A pointer to return integer
+ *  @return      	A pointer to next data field
+ */
+t_s8 *
+convert2hex(t_s8 *ptr, t_u8 *chr)
+{
+	t_u8 val;
+
+	for (val = 0; *ptr && isxdigit(*ptr); ptr++) {
+		val = (val * 16) + hexval(*ptr);
+	}
+
+	*chr = val;
+
+	return ptr;
+}
+
+/**
+ *  @brief Check the Hex String
+ *  @param s  A pointer to the string
+ *  @return   MLAN_STATUS_SUCCESS --HexString, MLAN_STATUS_FAILURE --not HexString
+ */
+int
+ishexstring(t_s8 *s)
+{
+	int ret = MLAN_STATUS_FAILURE;
+	t_s32 tmp;
+
+	if (!strncasecmp("0x", s, 2)) {
+		s += 2;
+	}
+	while (*s) {
+		tmp = toupper(*s);
+		if (((tmp >= 'A') && (tmp <= 'F')) ||
+		    ((tmp >= '0') && (tmp <= '9'))) {
+			ret = MLAN_STATUS_SUCCESS;
+		} else {
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		s++;
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief Convert String to Integer
+ *  @param buf      A pointer to the string
+ *  @return         Integer
+ */
+int
+atoval(t_s8 *buf)
+{
+	if (!strncasecmp(buf, "0x", 2))
+		return a2hex(buf + 2);
+	else if (!ishexstring(buf))
+		return a2hex(buf);
+	else
+		return atoi(buf);
+}
+
+/**
+ *  @brief Prepare host-command buffer
+ *  @param fp		File handler
+ *  @param cmd_name	Command name
+ *  @param buf		A pointer to comand buffer
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf)
+{
+	t_s8 line[256], cmdname[256], *pos, cmdcode[10];
+	HostCmd_DS_GEN *hostcmd;
+	int ln = 0;
+	int cmdname_found = 0, cmdcode_found = 0;
+
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	hostcmd->command = 0xffff;
+
+	snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name);
+	cmdname_found = 0;
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, cmdname) == 0) {
+			cmdname_found = 1;
+			snprintf(cmdcode, sizeof(cmdcode), "CmdCode=");
+			cmdcode_found = 0;
+			while ((pos =
+				mlan_config_get_line(fp, line, sizeof(line),
+						     &ln))) {
+				if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) {
+					cmdcode_found = 1;
+					hostcmd->command =
+						a2hex_or_atoi(pos +
+							      strlen(cmdcode));
+					hostcmd->size = S_DS_GEN;
+					mlan_get_hostcmd_data(fp, &ln,
+							      buf +
+							      hostcmd->size,
+							      &hostcmd->size);
+					break;
+				}
+			}
+			if (!cmdcode_found) {
+				fprintf(stderr,
+					"mlanutl: CmdCode not found in conf file\n");
+				return MLAN_STATUS_FAILURE;
+			}
+			break;
+		}
+	}
+
+	if (!cmdname_found) {
+		fprintf(stderr,
+			"mlanutl: cmdname '%s' is not found in conf file\n",
+			cmd_name);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	hostcmd->command = cpu_to_le16(hostcmd->command);
+	hostcmd->size = cpu_to_le16(hostcmd->size);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/** Config data header length */
+#define CFG_DATA_HEADER_LEN 6
+
+/**
+ *  @brief Prepare cfg-data buffer
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param fp       File handler
+ *  @param buf      A pointer to comand buffer
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_cfg_data_buffer(int argc, char *argv[], FILE * fp, t_u8 *buf)
+{
+	int ln = 0, type;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_802_11_CFG_DATA *pcfg_data;
+
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA);
+	pcfg_data = (HostCmd_DS_802_11_CFG_DATA *)(buf + S_DS_GEN);
+	pcfg_data->action =
+		(argc == 4) ? HostCmd_ACT_GEN_GET : HostCmd_ACT_GEN_SET;
+	type = atoi(argv[3]);
+	if ((type < 1) || (type > 2)) {
+		fprintf(stderr, "mlanutl: Invalid register type\n");
+		return MLAN_STATUS_FAILURE;
+	} else {
+		pcfg_data->type = type;
+	}
+	if (argc == 5) {
+		ln = fparse_for_hex(fp, pcfg_data->data);
+	}
+	pcfg_data->data_len = ln;
+	hostcmd->size =
+		cpu_to_le16(pcfg_data->data_len + S_DS_GEN +
+			    CFG_DATA_HEADER_LEN);
+	pcfg_data->data_len = cpu_to_le16(pcfg_data->data_len);
+	pcfg_data->type = cpu_to_le16(pcfg_data->type);
+	pcfg_data->action = cpu_to_le16(pcfg_data->action);
+
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process host_cmd response
+ *  @param buf		A pointer to the response buffer
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_host_cmd_resp(t_u8 *buf)
+{
+	HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	hostcmd->command = le16_to_cpu(hostcmd->command);
+	hostcmd->size = le16_to_cpu(hostcmd->size);
+	hostcmd->seq_num = le16_to_cpu(hostcmd->seq_num);
+	hostcmd->result = le16_to_cpu(hostcmd->result);
+
+	hostcmd->command &= ~HostCmd_RET_BIT;
+	if (!hostcmd->result) {
+		switch (hostcmd->command) {
+		case HostCmd_CMD_CFG_DATA:
+			{
+				HostCmd_DS_802_11_CFG_DATA *pstcfgData =
+					(HostCmd_DS_802_11_CFG_DATA *)(buf +
+								       S_DS_GEN);
+				pstcfgData->data_len =
+					le16_to_cpu(pstcfgData->data_len);
+				pstcfgData->action =
+					le16_to_cpu(pstcfgData->action);
+
+				if (pstcfgData->action == HostCmd_ACT_GEN_GET) {
+					hexdump("cfgdata", pstcfgData->data,
+						pstcfgData->data_len, ' ');
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+			{
+				mlan_ioctl_11h_tpc_resp *tpcIoctlResp =
+					(mlan_ioctl_11h_tpc_resp *)(buf +
+								    S_DS_GEN);
+				if (tpcIoctlResp->status_code == 0) {
+					printf("tpcrequest:  txPower(%d), linkMargin(%d), rssi(%d)\n", tpcIoctlResp->tx_power, tpcIoctlResp->link_margin, tpcIoctlResp->rssi);
+				} else {
+					printf("tpcrequest:  failure, status = %d\n", tpcIoctlResp->status_code);
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_CRYPTO:
+			{
+				t_u16 alg =
+					le16_to_cpu((t_u16)
+						    *(buf + S_DS_GEN +
+						      sizeof(t_u16)));
+				if (alg != CIPHER_TEST_AES_CCM) {
+					HostCmd_DS_802_11_CRYPTO *cmd =
+						(HostCmd_DS_802_11_CRYPTO *)(buf
+									     +
+									     S_DS_GEN);
+					cmd->encdec = le16_to_cpu(cmd->encdec);
+					cmd->algorithm =
+						le16_to_cpu(cmd->algorithm);
+					cmd->key_IV_length =
+						le16_to_cpu(cmd->key_IV_length);
+					cmd->key_length =
+						le16_to_cpu(cmd->key_length);
+					cmd->data.header.type =
+						le16_to_cpu(cmd->data.header.
+							    type);
+					cmd->data.header.len =
+						le16_to_cpu(cmd->data.header.
+							    len);
+
+					printf("crypto_result: encdec=%d algorithm=%d,KeyIVLen=%d," " KeyLen=%d,dataLen=%d\n", cmd->encdec, cmd->algorithm, cmd->key_IV_length, cmd->key_length, cmd->data.header.len);
+					hexdump("KeyIV", cmd->keyIV,
+						cmd->key_IV_length, ' ');
+					hexdump("Key", cmd->key,
+						cmd->key_length, ' ');
+					hexdump("Data", cmd->data.data,
+						cmd->data.header.len, ' ');
+				} else {
+					HostCmd_DS_802_11_CRYPTO_AES_CCM
+						*cmd_aes_ccm =
+						(HostCmd_DS_802_11_CRYPTO_AES_CCM
+						 *)(buf + S_DS_GEN);
+
+					cmd_aes_ccm->encdec
+						=
+						le16_to_cpu(cmd_aes_ccm->
+							    encdec);
+					cmd_aes_ccm->algorithm =
+						le16_to_cpu(cmd_aes_ccm->
+							    algorithm);
+					cmd_aes_ccm->key_length =
+						le16_to_cpu(cmd_aes_ccm->
+							    key_length);
+					cmd_aes_ccm->nonce_length =
+						le16_to_cpu(cmd_aes_ccm->
+							    nonce_length);
+					cmd_aes_ccm->AAD_length =
+						le16_to_cpu(cmd_aes_ccm->
+							    AAD_length);
+					cmd_aes_ccm->data.header.type =
+						le16_to_cpu(cmd_aes_ccm->data.
+							    header.type);
+					cmd_aes_ccm->data.header.len =
+						le16_to_cpu(cmd_aes_ccm->data.
+							    header.len);
+
+					printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_aes_ccm->encdec, cmd_aes_ccm->algorithm, cmd_aes_ccm->key_length, cmd_aes_ccm->nonce_length, cmd_aes_ccm->AAD_length, cmd_aes_ccm->data.header.len);
+
+					hexdump("Key", cmd_aes_ccm->key,
+						cmd_aes_ccm->key_length, ' ');
+					hexdump("Nonce", cmd_aes_ccm->nonce,
+						cmd_aes_ccm->nonce_length, ' ');
+					hexdump("AAD", cmd_aes_ccm->AAD,
+						cmd_aes_ccm->AAD_length, ' ');
+					hexdump("Data", cmd_aes_ccm->data.data,
+						cmd_aes_ccm->data.header.len,
+						' ');
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_AUTO_TX:
+			{
+				HostCmd_DS_802_11_AUTO_TX *at =
+					(HostCmd_DS_802_11_AUTO_TX *)(buf +
+								      S_DS_GEN);
+
+				if (le16_to_cpu(at->action) ==
+				    HostCmd_ACT_GEN_GET) {
+					if (S_DS_GEN + sizeof(at->action) ==
+					    hostcmd->size) {
+						printf("auto_tx not configured\n");
+
+					} else {
+						MrvlIEtypesHeader_t *header =
+							&at->auto_tx.header;
+
+						header->type =
+							le16_to_cpu(header->
+								    type);
+						header->len =
+							le16_to_cpu(header->
+								    len);
+
+						if ((S_DS_GEN +
+						     sizeof(at->action)
+						     +
+						     sizeof(MrvlIEtypesHeader_t)
+						     + header->len ==
+						     hostcmd->size) &&
+						    (header->type ==
+						     TLV_TYPE_AUTO_TX)) {
+
+							AutoTx_MacFrame_t *atmf
+								=
+								&at->auto_tx.
+								auto_tx_mac_frame;
+
+							printf("Interval: %d second(s)\n", le16_to_cpu(atmf->interval));
+							printf("Priority: %#x\n", atmf->priority);
+							printf("Frame Length: %d\n", le16_to_cpu(atmf->frame_len));
+							printf("Dest Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->dest_mac_addr[0], atmf->dest_mac_addr[1], atmf->dest_mac_addr[2], atmf->dest_mac_addr[3], atmf->dest_mac_addr[4], atmf->dest_mac_addr[5]);
+							printf("Src Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->src_mac_addr[0], atmf->src_mac_addr[1], atmf->src_mac_addr[2], atmf->src_mac_addr[3], atmf->src_mac_addr[4], atmf->src_mac_addr[5]);
+
+							hexdump("Frame Payload",
+								atmf->payload,
+								le16_to_cpu
+								(atmf->
+								 frame_len)
+								-
+								MLAN_MAC_ADDR_LENGTH
+								* 2, ' ');
+						} else {
+							printf("incorrect auto_tx command response\n");
+						}
+					}
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
+			{
+				HostCmd_DS_802_11_SUBSCRIBE_EVENT *se =
+					(HostCmd_DS_802_11_SUBSCRIBE_EVENT
+					 *)(buf + S_DS_GEN);
+				if (le16_to_cpu(se->action) ==
+				    HostCmd_ACT_GEN_GET) {
+					int len =
+						S_DS_GEN +
+						sizeof
+						(HostCmd_DS_802_11_SUBSCRIBE_EVENT);
+					printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n");
+					while (len < hostcmd->size) {
+						MrvlIEtypesHeader_t *header =
+							(MrvlIEtypesHeader_t
+							 *)(buf + len);
+						switch (le16_to_cpu
+							(header->type)) {
+						case TLV_TYPE_RSSI_LOW:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*low_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0001) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_SNR_LOW:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*low_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0002) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_FAILCOUNT:
+							{
+								MrvlIEtypes_FailureCount_t
+									*failure_count
+									=
+									(MrvlIEtypes_FailureCount_t
+									 *)(buf
+									    +
+									    len);
+								printf("Failure Count\t%d\t%d\t%s\n", failure_count->fail_value, failure_count->fail_freq, (le16_to_cpu(se->events) & 0x0004) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_BCNMISS:
+							{
+								MrvlIEtypes_BeaconsMissed_t
+									*bcn_missed
+									=
+									(MrvlIEtypes_BeaconsMissed_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon Missed\t%d\tN/A\t%s\n", bcn_missed->beacon_missed, (le16_to_cpu(se->events) & 0x0008) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_RSSI_HIGH:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*high_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Bcn High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0010) ? "yes" : "no");
+								break;
+							}
+
+						case TLV_TYPE_SNR_HIGH:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*high_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0020) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_RSSI_LOW_DATA:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*low_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0040) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_SNR_LOW_DATA:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*low_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0080) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_RSSI_HIGH_DATA:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*high_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0100) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_SNR_HIGH_DATA:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*high_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0200) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_LINK_QUALITY:
+							{
+								MrvlIEtypes_LinkQuality_t
+									*link_qual
+									=
+									(MrvlIEtypes_LinkQuality_t
+									 *)(buf
+									    +
+									    len);
+								printf("Link Quality Parameters:\n");
+								printf("------------------------\n");
+								printf("Link Quality Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0400) ? "yes" : "no");
+								printf("Link SNR Threshold   = %d\n", le16_to_cpu(link_qual->link_SNR_thrs));
+								printf("Link SNR Frequency   = %d\n", le16_to_cpu(link_qual->link_SNR_freq));
+								printf("Min Rate Value       = %d\n", le16_to_cpu(link_qual->min_rate_val));
+								printf("Min Rate Frequency   = %d\n", le16_to_cpu(link_qual->min_rate_freq));
+								printf("Tx Latency Value     = %d\n", le32_to_cpu(link_qual->tx_latency_val));
+								printf("Tx Latency Threshold = %d\n", le32_to_cpu(link_qual->tx_latency_thrs));
+
+								break;
+							}
+						case TLV_TYPE_PRE_BEACON_LOST:
+							{
+								MrvlIEtypes_PreBeaconLost_t
+									*pre_bcn_lost
+									=
+									(MrvlIEtypes_PreBeaconLost_t
+									 *)(buf
+									    +
+									    len);
+								printf("------------------------\n");
+								printf("Pre-Beacon Lost Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0800) ? "yes" : "no");
+								printf("Pre-Beacon Lost: %d\n", pre_bcn_lost->pre_beacon_lost);
+								break;
+							}
+						default:
+							printf("Unknown subscribed event TLV Type=%#x," " Len=%d\n", le16_to_cpu(header->type), le16_to_cpu(header->len));
+							break;
+						}
+
+						len += (sizeof
+							(MrvlIEtypesHeader_t)
+							+
+							le16_to_cpu(header->
+								    len));
+					}
+				}
+				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:
+			{
+				HostCmd_DS_REG *preg =
+					(HostCmd_DS_REG *)(buf + S_DS_GEN);
+				preg->action = le16_to_cpu(preg->action);
+				if (preg->action == HostCmd_ACT_GEN_GET) {
+					preg->value = le32_to_cpu(preg->value);
+					printf("value = 0x%08x\n", preg->value);
+				}
+				break;
+			}
+		case HostCmd_CMD_MEM_ACCESS:
+			{
+				HostCmd_DS_MEM *pmem =
+					(HostCmd_DS_MEM *)(buf + S_DS_GEN);
+				pmem->action = le16_to_cpu(pmem->action);
+				if (pmem->action == HostCmd_ACT_GEN_GET) {
+					pmem->value = le32_to_cpu(pmem->value);
+					printf("value = 0x%08x\n", pmem->value);
+				}
+				break;
+			}
+		default:
+			printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x,"
+			       " SeqNum=%#04x, Result=%#04x\n",
+			       hostcmd->command, hostcmd->size,
+			       hostcmd->seq_num, hostcmd->result);
+			hexdump("payload",
+				(t_void *)(buf + S_DS_GEN),
+				hostcmd->size - S_DS_GEN, ' ');
+			break;
+		}
+	} else {
+		printf("HOSTCMD failed: CmdCode=%#04x, Size=%#04x,"
+		       " SeqNum=%#04x, Result=%#04x\n",
+		       hostcmd->command, hostcmd->size,
+		       hostcmd->seq_num, hostcmd->result);
+	}
+	return ret;
+}
+
+/**
+ *  @brief Prepare ARP filter buffer
+ *  @param fp		File handler
+ *  @param buf		A pointer to the buffer
+ *  @param length	A pointer to the length of buffer
+ *  @return      	MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_arp_filter_buffer(FILE * fp, t_u8 *buf, t_u16 *length)
+{
+	t_s8 line[256], *pos;
+	int ln = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+	int arpfilter_found = 0;
+
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, "arpfilter={") == 0) {
+			arpfilter_found = 1;
+			mlan_get_hostcmd_data(fp, &ln, buf, length);
+			break;
+		}
+	}
+	if (!arpfilter_found) {
+		fprintf(stderr, "mlanutl: 'arpfilter' not found in conf file");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	return ret;
+}
+
+/**
+ *  @brief Prepare the hostcmd for register access
+ *  @param type     Register type
+ *  @param offset   Register offset
+ *  @param value    Pointer to value (NULL for read)
+ *  @param buf      Pointer to hostcmd buffer
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf)
+{
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_REG *preg;
+
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	switch (type) {
+	case 1:
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_MAC_REG_ACCESS);
+		break;
+	case 2:
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_BBP_REG_ACCESS);
+		break;
+	case 3:
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_RF_REG_ACCESS);
+		break;
+	case 5:
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_CAU_REG_ACCESS);
+		break;
+	default:
+		printf("Invalid register set specified\n");
+		return -EINVAL;
+	}
+	preg = (HostCmd_DS_REG *)(buf + S_DS_GEN);
+	preg->action = (value) ? HostCmd_ACT_GEN_SET : HostCmd_ACT_GEN_GET;
+	preg->action = cpu_to_le16(preg->action);
+	preg->offset = cpu_to_le16((t_u16)offset);
+	if (value)
+		preg->value = cpu_to_le32(*value);
+	else
+		preg->value = 0;
+	hostcmd->size = cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_REG));
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/wlan_sd8897/mapp/mlanutl/mlanhostcmd.h b/wlan_sd8897/mapp/mlanutl/mlanhostcmd.h
new file mode 100644
index 0000000..47a4cf9
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanhostcmd.h
@@ -0,0 +1,119 @@
+/** @file  mlanhostcmd.h
+  *
+  * @brief This file contains command structures for mlanutl application
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     11/26/2008: initial version
+************************************************************************/
+#ifndef _MLANHOSTCMD_H_
+#define _MLANHOSTCMD_H_
+
+/** Find number of elements */
+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
+
+/** Size of command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER		(2 * 1024)
+
+/** Host Command ID : Memory access */
+#define HostCmd_CMD_MEM_ACCESS                0x0086
+
+/** Pre-Authenticate - 11r only */
+#define HostCmd_CMD_802_11_AUTHENTICATE       0x0011
+
+/** Read/Write Mac register */
+#define HostCmd_CMD_MAC_REG_ACCESS            0x0019
+/** Read/Write BBP register */
+#define HostCmd_CMD_BBP_REG_ACCESS            0x001a
+/** Read/Write RF register */
+#define HostCmd_CMD_RF_REG_ACCESS             0x001b
+/** Get TX Power data */
+#define HostCmd_CMD_802_11_RF_TX_POWER        0x001e
+/** Host Command ID : CAU register access */
+#define HostCmd_CMD_CAU_REG_ACCESS            0x00ed
+
+/** Host Command ID : 802.11 BG scan configuration */
+#define HostCmd_CMD_802_11_BG_SCAN_CONFIG     0x006b
+/** Host Command ID : Configuration data */
+#define HostCmd_CMD_CFG_DATA                  0x008f
+/** Host Command ID : 802.11 TPC adapt req */
+#define HostCmd_CMD_802_11_TPC_ADAPT_REQ      0x0060
+/** Host Command ID : 802.11 crypto */
+#define HostCmd_CMD_802_11_CRYPTO             0x0078
+/** Host Command ID : 802.11 auto Tx */
+#define HostCmd_CMD_802_11_AUTO_TX      	0x0082
+
+/** Host Command ID : 802.11 subscribe event */
+#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT       0x0075
+
+/** Host Command ID : Channel TRPC config */
+#define HostCmd_CMD_CHAN_TRPC_CONFIG                0x00fb
+
+/** TLV  type ID definition */
+#define PROPRIETARY_TLV_BASE_ID     0x0100
+/** 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 : 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 : Auto Tx */
+#define TLV_TYPE_AUTO_TX            (PROPRIETARY_TLV_BASE_ID + 0x18)	/* 0x0118 */
+/** 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: Pre-Beacon Lost */
+#define TLV_TYPE_PRE_BEACON_LOST    (PROPRIETARY_TLV_BASE_ID + 0x49)	/* 0x0149 */
+
+/** TLV type : Channel TRPC */
+#define TLV_TYPE_CHAN_TRPC              (PROPRIETARY_TLV_BASE_ID + 0x89)	/* 0x0189 */
+
+/** mlan_ioctl_11h_tpc_resp */
+typedef struct {
+	int status_code;
+		     /**< Firmware command result status code */
+	int tx_power;/**< Reported TX Power from the TPC Report */
+	int link_margin;
+		     /**< Reported Link margin from the TPC Report */
+	int rssi;    /**< RSSI of the received TPC Report frame */
+} __ATTRIB_PACK__ mlan_ioctl_11h_tpc_resp;
+
+/* Define general hostcmd data structure */
+
+/** Convert String to integer */
+t_u32 a2hex_or_atoi(char *value);
+char *mlan_config_get_line(FILE * fp, char *str, t_s32 size, int *lineno);
+
+int prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf);
+int prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf);
+
+#endif /* _MLANHOSTCMD_H_ */
diff --git a/wlan_sd8897/mapp/mlanutl/mlanoffload.c b/wlan_sd8897/mapp/mlanutl/mlanoffload.c
new file mode 100644
index 0000000..ffb3880
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanoffload.c
@@ -0,0 +1,2519 @@
+/** @file  mlanoffload.c
+ *
+ * @brief This files contains mlanutl offload command handling.
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+/************************************************************************
+Change log:
+     08/11/2009: initial version
+************************************************************************/
+
+#include    "mlanutl.h"
+#include    "mlanhostcmd.h"
+#include    "mlanoffload.h"
+
+/********************************************************
+				Local Variables
+********************************************************/
+
+t_void hexdump(char *prompt, t_void *p, t_s32 len, t_s8 delim);
+
+/********************************************************
+				Global Variables
+********************************************************/
+
+/********************************************************
+				Local Functions
+********************************************************/
+
+/**
+ *  @brief Remove unwanted spaces, tabs from a line
+ *
+ *  @param data     A pointer to the starting of the line
+ *  @return         NA
+ */
+static void
+profile_param_polish(char *data)
+{
+	t_u8 i, j, len = 0;
+	char *ptr;
+	ptr = strrchr(data, '\r');
+	if (ptr == NULL) {
+		ptr = strrchr(data, '\n');
+		if (ptr == NULL) {
+			return;
+		}
+	}
+	len = ptr - data;
+	for (i = 0; i < len; i++) {
+		if ((*(data + i) == ' ') || (*(data + i) == '\t')) {
+			for (j = i; j < len; j++) {
+				data[j] = data[j + 1];
+			}
+			i--;
+			len--;
+		}
+	}
+}
+
+static int
+ascii_value(char letter)
+{
+	if (letter >= '0' && letter <= '9')
+		return letter - '0';
+	if (letter >= 'a' && letter <= 'f')
+		return letter - 'a' + 10;
+	if (letter >= 'A' && letter <= 'F')
+		return letter - 'A' + 10;
+	return -1;
+}
+
+static int
+twodigit_ascii(const char *nibble)
+{
+	int a, b;
+	a = ascii_value(*nibble++);
+	if (a < 0)
+		return -1;
+	b = ascii_value(*nibble++);
+	if (b < 0)
+		return -1;
+	return (a << 4) | b;
+}
+
+/**
+ *  @brief Read a network block from the profile configuration file
+ *
+ *  @param fp       file pointer of the configuration file
+ *  @param p_head   profile head
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static int
+profile_read_block(FILE * fp, profile_entry_t *p_head)
+{
+	char line[0x100];
+	char *ptr, *eptr;
+	t_u8 key_cnt = 0;
+	t_u8 i, wep_len;
+	int byte;
+	int tmpIdx;
+	unsigned int mac[ETH_ALEN];
+
+	while (fgets(line, sizeof(line), fp)) {
+		/* call function to remove spaces, tabs */
+		profile_param_polish(line);
+
+		if (strstr(line, "}") != NULL) {
+			ptr = strstr(line, "}");
+			/* end of network */
+			break;
+
+		} else if (line[0] == '#') {
+			/* comments go ahead */
+			continue;
+
+		} else if (strstr(line, "bssid=") != NULL) {
+			ptr = strstr(line, "bssid=");
+			ptr = ptr + strlen("bssid=");
+			sscanf(ptr, "%2x:%2x:%2x:%2x:%2x:%2x",
+			       mac + 0, mac + 1, mac + 2, mac + 3, mac + 4,
+			       mac + 5);
+			for (tmpIdx = 0; (unsigned int)tmpIdx < NELEMENTS(mac);
+			     tmpIdx++) {
+				p_head->bssid[tmpIdx] = (t_u8)mac[tmpIdx];
+			}
+
+		} else if (strstr(line, "ssid=") != NULL) {
+
+			ptr = strstr(line, "ssid=");
+			ptr = ptr + strlen("ssid=");
+			eptr = strrchr(ptr + 1, '"');
+
+			if ((*ptr != '"') || (strrchr(ptr + 1, '"') == NULL)) {
+
+				fprintf(stderr, "ssid not within quotes\n");
+				break;
+			}
+
+			p_head->ssid_len =
+				MIN(IW_ESSID_MAX_SIZE, eptr - ptr - 1);
+			strncpy((char *)p_head->ssid, ptr + 1,
+				p_head->ssid_len);
+			p_head->ssid[p_head->ssid_len] = '\0';
+
+		} else if (strstr(line, "psk=") != NULL) {
+			ptr = strstr(line, "psk=");
+			ptr = ptr + strlen("psk=");
+			if (*ptr != '"') {
+				p_head->psk_config = 1;
+				strncpy((char *)p_head->psk, ptr, KEY_LEN);
+			} else {
+				eptr = strrchr(ptr + 1, '"');
+				if (eptr == NULL) {
+					fprintf(stderr,
+						"passphrase not within quotes.\n");
+					break;
+				}
+				p_head->passphrase_len =
+					MIN(PHRASE_LEN, eptr - ptr - 1);
+				strncpy((char *)p_head->passphrase, ptr + 1,
+					p_head->passphrase_len);
+			}
+		} else if (strstr(line, "wep_key") != NULL) {
+			ptr = strstr(line, "wep_key");
+			ptr = ptr + strlen("wep_key");
+			key_cnt = atoi(ptr);
+			ptr++;
+			if (*ptr != '=') {
+				fprintf(stderr,
+					"invalid wep_key, missing =.\n");
+				break;
+			}
+			eptr = strrchr(ptr + 1, '\r');
+			if (eptr == NULL) {
+				eptr = strrchr(ptr + 1, '\n');
+				if (eptr == NULL) {
+					fprintf(stderr,
+						"missing EOL from the wep_key config\n");
+					break;
+				}
+			}
+			ptr++;
+			if (*ptr == '"') {
+				eptr = strrchr(ptr + 1, '"');
+				if (eptr == NULL) {
+					fprintf(stderr,
+						"wep key does not end with quote.\n");
+					break;
+				}
+				*eptr = '\0';
+				p_head->wep_key_len[key_cnt] = eptr - ptr - 1;
+				strncpy((char *)p_head->wep_key[key_cnt],
+					ptr + 1, p_head->wep_key_len[key_cnt]);
+			} else {
+				while (*eptr == '\r' || *eptr == '\n')
+					eptr--;
+				*(eptr + 1) = '\0';
+				wep_len = strlen(ptr);
+				if (wep_len & 0x01) {
+					fprintf(stderr,
+						"incorrect wep key %s.\n", ptr);
+					break;
+				}
+				p_head->wep_key_len[key_cnt] = wep_len / 2;
+				for (i = 0; i < wep_len / 2; i++) {
+					byte = twodigit_ascii(ptr);
+					if (byte == -1) {
+						fprintf(stderr,
+							"incorrect wep key %s.\n",
+							ptr);
+						break;
+					}
+					*(p_head->wep_key[key_cnt] + i) =
+						(t_u8)byte;
+					ptr += 2;
+				}
+			}
+		} else if (strstr(line, "key_mgmt=") != NULL) {
+			ptr = strstr(line, "key_mgmt=");
+			ptr = ptr + strlen("key_mgmt=");
+			eptr = strstr(ptr, "WPA-EAP");
+			if (eptr != NULL) {
+				p_head->key_mgmt |=
+					PROFILE_DB_KEY_MGMT_IEEE8021X;
+			}
+			eptr = strstr(ptr, "WPA-PSK");
+			if (eptr != NULL) {
+				p_head->key_mgmt |= PROFILE_DB_KEY_MGMT_PSK;
+			}
+			eptr = strstr(ptr, "FT-EAP");
+			if (eptr != NULL) {
+				p_head->key_mgmt |=
+					PROFILE_DB_KEY_MGMT_FT_IEEE8021X;
+			}
+			eptr = strstr(ptr, "FT-PSK");
+			if (eptr != NULL) {
+				p_head->key_mgmt |= PROFILE_DB_KEY_MGMT_FT_PSK;
+			}
+			eptr = strstr(ptr, "WPA-EAP-SHA256");
+			if (eptr != NULL) {
+				p_head->key_mgmt |=
+					PROFILE_DB_KEY_MGMT_SHA256_IEEE8021X;
+			}
+			eptr = strstr(ptr, "WPA-PSK-SHA256");
+			if (eptr != NULL) {
+				p_head->key_mgmt |=
+					PROFILE_DB_KEY_MGMT_SHA256_PSK;
+			}
+			eptr = strstr(ptr, "CCKM");
+			if (eptr != NULL) {
+				p_head->key_mgmt |= PROFILE_DB_KEY_MGMT_CCKM;
+			}
+			eptr = strstr(ptr, "NONE");
+			if (eptr != NULL) {
+				p_head->key_mgmt |= PROFILE_DB_KEY_MGMT_NONE;
+			}
+		} else if (strstr(line, "proto=") != NULL) {
+			ptr = strstr(line, "proto=");
+			ptr = ptr + strlen("proto=");
+			eptr = strstr(ptr, "WPA");
+			if (eptr != NULL) {
+				p_head->protocol |= PROFILE_DB_PROTO_WPA;
+			}
+
+			eptr = strstr(ptr, "RSN");
+			if (eptr != NULL) {
+				p_head->protocol |= PROFILE_DB_PROTO_WPA2;
+
+			}
+		} else if (strstr(line, "pairwise=") != NULL) {
+			ptr = strstr(line, "pairwise=");
+			ptr = ptr + strlen("pairwise=");
+			eptr = strstr(ptr, "CCMP");
+			if (eptr != NULL) {
+				p_head->pairwise_cipher |=
+					PROFILE_DB_CIPHER_CCMP;
+			}
+			eptr = strstr(ptr, "TKIP");
+			if (eptr != NULL) {
+				p_head->pairwise_cipher |=
+					PROFILE_DB_CIPHER_TKIP;
+			}
+		} else if (strstr(line, "groupwise=") != NULL) {
+			ptr = strstr(line, "groupwise=");
+			ptr = ptr + strlen("groupwise=");
+			eptr = strstr(ptr, "CCMP");
+			if (eptr != NULL) {
+				p_head->groupwise_cipher |=
+					PROFILE_DB_CIPHER_CCMP;
+			}
+			eptr = strstr(ptr, "TKIP");
+			if (eptr != NULL) {
+				p_head->groupwise_cipher |=
+					PROFILE_DB_CIPHER_TKIP;
+			}
+		} else if (strstr(line, "wep_tx_keyidx=") != NULL) {
+			ptr = strstr(line, "wep_tx_keyidx=");
+			ptr = ptr + strlen("wep_tx_keyidx=");
+			p_head->wep_key_idx = atoi(ptr);
+		} else if (strstr(line, "roaming=") != NULL) {
+			ptr = strstr(line, "roaming=");
+			ptr = ptr + strlen("roaming=");
+			p_head->roaming = atoi(ptr);
+		} else if (strstr(line, "ccx=") != NULL) {
+			ptr = strstr(line, "ccx=");
+			ptr = ptr + strlen("ccx=");
+			p_head->ccx = atoi(ptr);
+		} else if (strstr(line, "mode=") != NULL) {
+			ptr = strstr(line, "mode=");
+			ptr = ptr + strlen("mode=");
+			p_head->mode = atoi(ptr);
+		}
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Issue profile command to add new profile to FW
+ *
+ *  @param filename     Name of profile file
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+profile_read_download(char *filename)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	int i = 0;
+	t_u16 temp, tempc;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	profile_entry_t *p_head = NULL;
+	FILE *fp;
+	char line[0x100];
+
+	fp = fopen(filename, "r");
+	if (fp == NULL) {
+		perror("fopen");
+		fprintf(stderr, "Cannot open file %s\n", filename);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	pos = (t_u8 *)hostcmd;
+	while (fgets(line, sizeof(line), fp)) {
+		/* call function to remove spaces, tabs */
+		profile_param_polish(line);
+		if ((strstr(line, "network={") == NULL) || (line[0] == '#')) {
+			continue;
+		}
+		/*
+		 * Memory allocation of every network block
+		 */
+		p_head = (profile_entry_t *)malloc(sizeof(profile_entry_t));
+		if (p_head == NULL) {
+			fprintf(stderr, "Memory error.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		memset(p_head, 0x00, sizeof(profile_entry_t));
+
+		ret = profile_read_block(fp, p_head);
+		if (ret || p_head->ssid_len == 0) {
+			free(p_head);
+			continue;
+		}
+
+		/*
+		 * Put all the ssid parameters in the buffer
+		 */
+		memset(pos, 0,
+		       (BUFFER_LENGTH - cmd_header_len - sizeof(t_u32)));
+
+		/* Cmd Header : Command */
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_PROFILE_DB);
+		cmd_len = sizeof(HostCmd_DS_GEN);
+
+		/* set action as set */
+		tempc = cpu_to_le16(HostCmd_ACT_GEN_SET);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+
+		/* ssid */
+		tempc = cpu_to_le16(TLV_TYPE_SSID);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		temp = strlen((char *)p_head->ssid);
+		tempc = cpu_to_le16(temp);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		memcpy((void *)(pos + cmd_len), p_head->ssid, temp);
+		cmd_len += temp;
+
+		if (memcmp(p_head->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)) {
+			/* bssid */
+			tempc = cpu_to_le16(TLV_TYPE_BSSID);
+			memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+			cmd_len += 2;
+			temp = ETH_ALEN;
+			tempc = cpu_to_le16(temp);
+			memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+			cmd_len += 2;
+			memcpy((void *)(pos + cmd_len), p_head->bssid, temp);
+			cmd_len += temp;
+		}
+
+		/* proto */
+		if (p_head->protocol == 0) {
+			p_head->protocol = 0xFFFF;
+		}
+
+		tempc = cpu_to_le16(TLV_TYPE_PROTO);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		temp = 2;
+		tempc = cpu_to_le16(temp);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		memcpy((pos + cmd_len), &(p_head->protocol), temp);
+		cmd_len += temp;
+
+		/* key_mgmt */
+		if (p_head->key_mgmt == 0) {
+			p_head->key_mgmt = 0xFFFF;
+		}
+
+		tempc = cpu_to_le16(TLV_TYPE_AKMP);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		temp = 2;
+		tempc = cpu_to_le16(temp);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		memcpy((pos + cmd_len), &(p_head->key_mgmt), temp);
+		cmd_len += temp;
+
+		/* pairwise */
+		if (p_head->pairwise_cipher == 0) {
+			p_head->pairwise_cipher = 0xFF;
+		}
+
+		/* groupwise */
+		if (p_head->groupwise_cipher == 0) {
+			p_head->groupwise_cipher = 0xFF;
+		}
+
+		tempc = cpu_to_le16(TLV_TYPE_CIPHER);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		temp = 2;
+		tempc = cpu_to_le16(temp);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		pos[cmd_len] = p_head->pairwise_cipher;
+		cmd_len += 1;
+		pos[cmd_len] = p_head->groupwise_cipher;
+		cmd_len += 1;
+
+		if (p_head->passphrase_len) {
+			/* passphrase */
+			tempc = cpu_to_le16(TLV_TYPE_PASSPHRASE);
+			memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+			cmd_len += 2;
+			temp = p_head->passphrase_len;
+			tempc = cpu_to_le16(temp);
+			memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+			cmd_len += 2;
+			memcpy((void *)(pos + cmd_len), p_head->passphrase,
+			       temp);
+			cmd_len += temp;
+		}
+
+		if (p_head->psk_config) {
+			/* psk method */
+			tempc = cpu_to_le16(TLV_TYPE_PMK);
+			memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+			cmd_len += 2;
+			temp = 32;
+			tempc = cpu_to_le16(temp);
+			memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+			cmd_len += 2;
+			memcpy((void *)(pos + cmd_len), p_head->psk, temp);
+			cmd_len += temp;
+		}
+
+		for (i = 0; i < WEP_KEY_CNT; i++) {
+			if (p_head->wep_key_len[i]) {
+				/* TAG_WEP_KEY */
+				tempc = cpu_to_le16(TLV_TYPE_WEP_KEY);
+				memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+				cmd_len += 2;
+				/* wep_key_len + sizeof(keyIndex) + sizeof(IsDefault) */
+				tempc = cpu_to_le16(p_head->wep_key_len[i] + 1 +
+						    1);
+				memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+				cmd_len += 2;
+				*(pos + cmd_len) = i;
+				cmd_len += 1;
+				*(pos + cmd_len) = (i == p_head->wep_key_idx);
+				cmd_len += 1;
+				temp = p_head->wep_key_len[i];
+				memcpy((void *)(pos + cmd_len),
+				       p_head->wep_key[i], temp);
+				cmd_len += temp;
+			}
+		}
+
+		if (p_head->roaming | p_head->ccx) {
+			tempc = cpu_to_le16(TLV_TYPE_OFFLOAD_ENABLE);
+			memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+			cmd_len += 2;
+			temp = 2;
+			tempc = cpu_to_le16(temp);
+			memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+			cmd_len += 2;
+			tempc = 0;
+			if (p_head->roaming)
+				tempc |= PROFILE_DB_FEATURE_ROAMING;
+			if (p_head->ccx)
+				tempc |= PROFILE_DB_FEATURE_CCX;
+			tempc = cpu_to_le16(tempc);
+			memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+			cmd_len += temp;
+		}
+
+		/* Put buffer length */
+		memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+		hostcmd->size = cpu_to_le16(cmd_len);
+
+		fprintf(stdout, "Downloading profile: %s ... ", p_head->ssid);
+		fflush(stdout);
+
+		/* Initialize the ifr structure */
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+		ifr.ifr_ifru.ifru_data = (void *)cmd;
+		/* Perform ioctl */
+		if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+			perror("ioctl[profiledb ioctl]");
+			printf("ERR:Command sending failed!\n");
+			ret = -EFAULT;
+			goto done;
+		} else {
+			hostcmd->result = le16_to_cpu(hostcmd->result);
+			if (hostcmd->result != 0) {
+				printf("hostcmd : profiledb ioctl failure, code %d\n", hostcmd->result);
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+
+		fprintf(stdout, "done.\n");
+
+		if (p_head)
+			free(p_head);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	if (fp)
+		fclose(fp);
+	return ret;
+}
+
+/********************************************************
+				Global Functions
+********************************************************/
+
+/**
+ *  @brief Process sub command
+ *
+ *  @param sub_cmd      Sub command
+ *  @param num_sub_cmds Number of subcommands
+ *  @param argc         Number of arguments
+ *  @param argv         A pointer to arguments array
+ *
+ *  @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_sub_cmd(sub_cmd_exec_t *sub_cmd, int num_sub_cmds,
+		int argc, char *argv[])
+{
+	int idx;
+	boolean invalid_cmd = TRUE;
+	int ret = MLAN_STATUS_FAILURE;
+
+	if (argv[3]) {
+		for (idx = 0; idx < num_sub_cmds; idx++) {
+			if (strncmp(argv[3],
+				    sub_cmd[idx].str,
+				    sub_cmd[idx].match_len) == 0) {
+				invalid_cmd = FALSE;
+				ret = sub_cmd[idx].callback(argc - 4, argv + 4);
+				break;
+			}
+		}
+	}
+
+	if (invalid_cmd) {
+		printf("\nUnknown %s command. Valid subcmds:\n", argv[2]);
+		for (idx = 0; idx < num_sub_cmds; idx++) {
+			if (sub_cmd[idx].display) {
+				printf("  - %s\n", sub_cmd[idx].str);
+			}
+		}
+		printf("\n");
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief  select the table's regclass
+ *
+ *  @param table_str  Reg channel table type
+ *  @param pTable     Pointer to the Reg channel table
+ *
+ *  @return           TRUE if success otherwise FALSE
+ */
+boolean
+reg_class_table_select(char *table_str, reg_chan_table_e *pTable)
+{
+	boolean retval = TRUE;
+
+	if (strcmp(table_str, "user") == 0) {
+		*pTable = REGTABLE_USER;
+	} else if ((strcmp(table_str, "md") == 0) ||
+		   (strncmp(table_str, "multidomain", 5) == 0)) {
+		*pTable = REGTABLE_MULTIDOMAIN;
+	} else if (strcmp(table_str, "ess") == 0) {
+		*pTable = REGTABLE_ESS;
+	} else if (strcmp(table_str, "default") == 0) {
+		*pTable = REGTABLE_DEFAULT;
+	} else {		/* If no option/wrong option set to default */
+		*pTable = REGTABLE_DEFAULT;
+	}
+
+	return retval;
+}
+
+/**
+ *  @brief Issue a measurement timing command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_measurement(int argc, char *argv[])
+{
+	int ret = 0;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	HostCmd_DS_MEASUREMENT_Timing *timing_cmd = NULL;
+	MrvlIETypes_MeasTiming_t *timing_tlv = NULL;
+	int idx, rsp_len;
+	t_u8 sel = 0;
+	t_u16 tlv_len = 0;
+	timing_sel_t sel_str[] = { {"disconnected", 1},
+	{"adhoc", 1},
+	{"fullpower", 1},
+	{"ieeeps", 1},
+	{"periodic", 1}
+	};
+
+	if ((argc < 4) || strncmp(argv[3], "timing",
+				  MAX(strlen("timing"), strlen(argv[3])))) {
+		printf("\nUnknown %s command. Valid subcmd: timing \n",
+		       argv[2]);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+	cmd_len = S_DS_GEN + sizeof(t_u16);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		return -ENOMEM;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return -ENOMEM;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_MEASUREMENT_TIMING_CONFIG);
+	hostcmd->size = cmd_len;
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	timing_cmd = (HostCmd_DS_MEASUREMENT_Timing *)pos;
+	timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+	timing_tlv = (MrvlIETypes_MeasTiming_t *)timing_cmd->tlv_buffer;
+
+	if (argc == 7) {
+		timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+		timing_tlv->header.type =
+			cpu_to_le16(TLV_TYPE_MEASUREMENT_TIMING);
+		timing_tlv->header.len =
+			cpu_to_le16(sizeof(MrvlIETypes_MeasTiming_t)
+				    - sizeof(timing_tlv->header));
+
+		for (idx = 1; (unsigned int)idx < NELEMENTS(sel_str); idx++) {
+			if (strncmp
+			    (argv[4], sel_str[idx].str,
+			     sel_str[idx].match_len) == 0) {
+				sel = idx + 1;
+				break;
+			}
+		}
+
+		if (idx == NELEMENTS(sel_str)) {
+			printf("Wrong argument for mode selected \"%s\"\n",
+			       argv[4]);
+			ret = -EINVAL;
+			goto done;
+		}
+
+		timing_tlv->mode = cpu_to_le32(sel);
+		timing_tlv->max_off_channel = cpu_to_le32(atoi(argv[5]));
+		timing_tlv->max_on_channel = cpu_to_le32(atoi(argv[6]));
+		cmd_len += sizeof(MrvlIETypes_MeasTiming_t);
+	}
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+	hostcmd->size = cpu_to_le16(cmd_len);
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[measurement timing ioctl]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	printf("--------------------------------------------------\n");
+	printf("%44s\n", "Measurement Timing Profiles (in ms)");
+	printf("--------------------------------------------------\n");
+	printf("     Profile    |  MaxOffChannel |  MaxOnChannel\n");
+	printf("--------------------------------------------------\n");
+
+	/* Changed to TLV parsing */
+	rsp_len = le16_to_cpu(hostcmd->size);
+	rsp_len -= (S_DS_GEN + sizeof(t_u16));
+	pos = (t_u8 *)hostcmd + S_DS_GEN + sizeof(t_u16);
+	while ((unsigned int)rsp_len > sizeof(MrvlIEtypesHeader_t)) {
+		switch (le16_to_cpu(*(t_u16 *)(pos))) {
+		case TLV_TYPE_MEASUREMENT_TIMING:
+			timing_tlv = (MrvlIETypes_MeasTiming_t *)pos;
+			tlv_len = le16_to_cpu(timing_tlv->header.len);
+			printf("%15s | %14d | %13d\n",
+			       sel_str[le32_to_cpu(timing_tlv->mode) - 1].str,
+			       (int)le32_to_cpu(timing_tlv->max_off_channel),
+			       (int)le32_to_cpu(timing_tlv->max_on_channel));
+			break;
+		}
+		pos += tlv_len + sizeof(MrvlIEtypesHeader_t);
+		rsp_len -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		rsp_len = (rsp_len > 0) ? rsp_len : 0;
+	}
+	printf("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Issue a profile command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_profile_entry(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	unsigned int mac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	int idx;
+	t_u16 temp, tempc;
+	char *ssid = NULL;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	if (argc < 4) {
+		fprintf(stderr, "Invalid number of argument!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (!strncmp(argv[3], "delete", sizeof("delete"))) {
+		if (argc > 4) {
+			if (strncmp(argv[4], "bssid=", strlen("bssid=")) == 0) {
+				/* "bssid" token string handler */
+				sscanf(argv[4] + strlen("bssid="),
+				       "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0,
+				       mac + 1, mac + 2, mac + 3, mac + 4,
+				       mac + 5);
+			} else if (strncmp(argv[4], "ssid=", strlen("ssid=")) ==
+				   0) {
+				/* "ssid" token string handler */
+				ssid = argv[4] + strlen("ssid=");
+			} else {
+				printf("Error: missing required option for command (ssid, bssid)\n");
+				ret = -ENOMEM;
+				goto done;
+			}
+			printf("Driver profile delete request\n");
+		} else {
+			printf("Error: missing required option for command (ssid, bssid)\n");
+			ret = -ENOMEM;
+			goto done;
+		}
+	} else if (!strncmp(argv[3], "flush", sizeof("flush"))) {
+		printf("Driver profile flush request\n");
+	} else {
+		ret = profile_read_download(argv[3]);
+		goto done;
+	}
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_PROFILE_DB);
+	hostcmd->size = 0;
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd;
+	cmd_len = S_DS_GEN;
+
+	/* set action as del */
+	tempc = cpu_to_le16(HostCmd_ACT_GEN_REMOVE);
+	memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+	cmd_len += 2;
+
+	/* ssid */
+	if (ssid) {
+		printf("For ssid %s\n", ssid);
+		tempc = cpu_to_le16(TLV_TYPE_SSID);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		temp = strlen((char *)ssid);
+		tempc = cpu_to_le16(temp);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		memcpy((void *)(pos + cmd_len), ssid, temp);
+		cmd_len += temp;
+	} else {
+		/* bssid */
+		if (mac[0] != 0xFF) {
+			printf("For bssid %02x:%02x:%02x:%02x:%02x:%02x\n",
+			       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+		}
+		tempc = cpu_to_le16(TLV_TYPE_BSSID);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		temp = ETH_ALEN;
+		tempc = cpu_to_le16(temp);
+		memcpy((pos + cmd_len), &tempc, sizeof(t_u16));
+		cmd_len += 2;
+		for (idx = 0; (unsigned int)idx < NELEMENTS(mac); idx++) {
+			pos[cmd_len + idx] = (t_u8)mac[idx];
+		}
+		cmd_len += temp;
+	}
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+	hostcmd->size = cpu_to_le16(cmd_len);
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[profiledb ioctl]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	} else {
+		hostcmd->result = le16_to_cpu(hostcmd->result);
+		if (hostcmd->result != 0) {
+			printf("hostcmd : profiledb ioctl failure, code %d\n",
+			       hostcmd->result);
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Issue a chan report command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_chanrpt(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int respLen;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	t_u8 *pByte;
+	t_u8 numBins;
+	t_u8 idx;
+	MrvlIEtypes_Data_t *pTlvHdr;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CHAN_RPT_RSP *pChanRptRsp;
+	HostCmd_DS_CHAN_RPT_REQ *pChanRptReq;
+
+	MrvlIEtypes_ChanRptBcn_t *pBcnRpt;
+	MrvlIEtypes_ChanRptChanLoad_t *pLoadRpt;
+	MrvlIEtypes_ChanRptNoiseHist_t *pNoiseRpt;
+	MrvlIEtypes_ChanRpt11hBasic_t *pBasicRpt;
+	MrvlIEtypes_ChanRptFrame_t *pFrameRpt;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_CHAN_RPT_REQ);
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	pChanRptReq = (HostCmd_DS_CHAN_RPT_REQ *)pos;
+	pChanRptRsp = (HostCmd_DS_CHAN_RPT_RSP *)pos;
+
+	memset((void *)pChanRptReq, 0x00, sizeof(HostCmd_DS_CHAN_RPT_REQ));
+
+	if ((argc != 5) && (argc != 6)) {
+		printf("\nchanrpt syntax: chanrpt <chan#> <millisecs> [sFreq]\n\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	pChanRptReq->chanDesc.chanNum = atoi(argv[3]);
+	pChanRptReq->millisecDwellTime = cpu_to_le32(atoi(argv[4]));
+
+	if (argc == 6) {
+		pChanRptReq->chanDesc.startFreq = cpu_to_le16(atoi(argv[5]));
+	}
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[chanrpt hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* TSF is a t_u64, some formatted printing libs have
+	 *   trouble printing long longs, so cast and dump as bytes
+	 */
+	pByte = (t_u8 *)&pChanRptRsp->startTsf;
+
+	printf("\n");
+	printf("[%03d]      TSF: 0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+	       atoi(argv[3]),
+	       pByte[7], pByte[6], pByte[5], pByte[4],
+	       pByte[3], pByte[2], pByte[1], pByte[0]);
+	printf("[%03d]    Dwell: %u us\n",
+	       atoi(argv[3]), (unsigned int)le32_to_cpu(pChanRptRsp->duration));
+
+	pByte = pChanRptRsp->tlvBuffer;
+
+	respLen = le16_to_cpu(hostcmd->size) - sizeof(HostCmd_DS_GEN);
+
+	respLen -= sizeof(pChanRptRsp->commandResult);
+	respLen -= sizeof(pChanRptRsp->startTsf);
+	respLen -= sizeof(pChanRptRsp->duration);
+
+	pByte = pChanRptRsp->tlvBuffer;
+
+	while ((unsigned int)respLen >= sizeof(pTlvHdr->header)) {
+		pTlvHdr = (MrvlIEtypes_Data_t *)pByte;
+		pTlvHdr->header.len = le16_to_cpu(pTlvHdr->header.len);
+
+		switch (le16_to_cpu(pTlvHdr->header.type)) {
+		case TLV_TYPE_CHANRPT_BCN:
+			pBcnRpt = (MrvlIEtypes_ChanRptBcn_t *)pTlvHdr;
+			printf("[%03d]   Beacon: scanReqId = %d\n",
+			       atoi(argv[3]), pBcnRpt->scanReqId);
+
+			break;
+
+		case TLV_TYPE_CHANRPT_CHAN_LOAD:
+			pLoadRpt = (MrvlIEtypes_ChanRptChanLoad_t *)pTlvHdr;
+			printf("[%03d] ChanLoad: %d%%\n",
+			       atoi(argv[3]),
+			       (pLoadRpt->ccaBusyFraction * 100) / 255);
+			break;
+
+		case TLV_TYPE_CHANRPT_NOISE_HIST:
+			pNoiseRpt = (MrvlIEtypes_ChanRptNoiseHist_t *)pTlvHdr;
+			numBins =
+				pNoiseRpt->header.len - sizeof(pNoiseRpt->anpi);
+			printf("[%03d]     ANPI: %d dB\n", atoi(argv[3]),
+			       le16_to_cpu(pNoiseRpt->anpi));
+			printf("[%03d] NoiseHst:", atoi(argv[3]));
+			for (idx = 0; idx < numBins; idx++) {
+				printf(" %03d", pNoiseRpt->rpiDensities[idx]);
+			}
+			printf("\n");
+			break;
+
+		case TLV_TYPE_CHANRPT_11H_BASIC:
+			pBasicRpt = (MrvlIEtypes_ChanRpt11hBasic_t *)pTlvHdr;
+			printf("[%03d] 11hBasic: BSS(%d), OFDM(%d), UnId(%d), Radar(%d): " "[0x%02x]\n", atoi(argv[3]), pBasicRpt->map.BSS, pBasicRpt->map.OFDM_Preamble, pBasicRpt->map.Unidentified, pBasicRpt->map.Radar, *(t_u8 *)&pBasicRpt->map);
+			break;
+
+		case TLV_TYPE_CHANRPT_FRAME:
+			pFrameRpt = (MrvlIEtypes_ChanRptFrame_t *)pTlvHdr;
+			printf("[%03d]    Frame: %02x:%02x:%02x:%02x:%02x:%02x  " "%02x:%02x:%02x:%02x:%02x:%02x  %3d   %02d\n", atoi(argv[3]), pFrameRpt->sourceAddr[0], pFrameRpt->sourceAddr[1], pFrameRpt->sourceAddr[2], pFrameRpt->sourceAddr[3], pFrameRpt->sourceAddr[4], pFrameRpt->sourceAddr[5], pFrameRpt->bssid[0], pFrameRpt->bssid[1], pFrameRpt->bssid[2], pFrameRpt->bssid[3], pFrameRpt->bssid[4], pFrameRpt->bssid[5], pFrameRpt->rssi, pFrameRpt->frameCnt);
+			break;
+
+		default:
+			printf("[%03d] Other: Id=0x%x, Size = %d\n",
+			       atoi(argv[3]),
+			       pTlvHdr->header.type, pTlvHdr->header.len);
+
+			break;
+		}
+
+		pByte += (pTlvHdr->header.len + sizeof(pTlvHdr->header));
+		respLen -= (pTlvHdr->header.len + sizeof(pTlvHdr->header));
+		respLen = (respLen > 0) ? respLen : 0;
+	}
+
+	printf("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Issue a assoc timing command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_assoc_timing(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_AssociationTiming_t *assoctiming;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_AssociationTiming_t);
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_ASSOCIATION_TIMING);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	assoctiming = (HostCmd_DS_AssociationTiming_t *)pos;
+	assoctiming->Action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (argc > 3) {
+		assoctiming->Action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+		switch (argc) {
+		case 9:
+			assoctiming->ReassocDiscMax =
+				cpu_to_le16(atoi(argv[8]));
+			/* No break, do everything below as well */
+		case 8:
+			assoctiming->PriorApDeauthDelay =
+				cpu_to_le16(atoi(argv[7]));
+			/* No break, do everything below as well */
+		case 7:
+			assoctiming->FrameExchangeTimeout =
+				cpu_to_le16(atoi(argv[6]));
+			/* No break, do everything below as well */
+		case 6:
+			assoctiming->HandShakeTimeout =
+				cpu_to_le16(atoi(argv[5]));
+			/* No break, do everything below as well */
+		case 5:
+			assoctiming->ReassocTimeout =
+				cpu_to_le16(atoi(argv[4]));
+			/* No break, do everything below as well */
+		case 4:
+			assoctiming->AssocTimeout = cpu_to_le16(atoi(argv[3]));
+			break;
+		}
+	}
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	puts("");
+	printf("------------------------------------------------\n");
+	printf("        Association Timing Parameters\n");
+	printf("------------------------------------------------\n");
+
+	printf("Association Timeout     %5u ms\n"
+	       "Reassociation Timeout   %5u ms\n"
+	       "Handshake Timeout       %5u ms\n"
+	       "Frame Exchange Timeout  %5u ms\n"
+	       "Prior AP Deauth Delay   %5u ms\n"
+	       "Reassoc Disconnect Max  %5u ms\n",
+	       le16_to_cpu(assoctiming->AssocTimeout),
+	       le16_to_cpu(assoctiming->ReassocTimeout),
+	       le16_to_cpu(assoctiming->HandShakeTimeout),
+	       le16_to_cpu(assoctiming->FrameExchangeTimeout),
+	       le16_to_cpu(assoctiming->PriorApDeauthDelay),
+	       le16_to_cpu(assoctiming->ReassocDiscMax));
+	puts("");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Retrieve the association response from the driver
+ *
+ *  Retrieve the buffered (re)association management frame from the driver.
+ *    The response is identical to the one received from the AP and conforms
+ *    to the IEEE specification.
+ *
+ *  @return MLAN_STATUS_SUCCESS or ioctl error code
+ */
+int
+process_get_assocrsp(int argc, char *argv[])
+{
+	int ret = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	IEEEtypes_AssocRsp_t *pAssocRsp = NULL;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pAssocRsp = (IEEEtypes_AssocRsp_t *)buffer;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), argv[2], strlen(argv[2]));
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: version fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (cmd->used_len) {
+		printf("getassocrsp: Status[%d], Cap[0x%04x]:\n",
+		       pAssocRsp->StatusCode,
+		       le16_to_cpu(*(t_u16 *)&pAssocRsp->Capability));
+		hexdump(NULL, buffer, cmd->used_len, ' ');
+	} else {
+		printf("getassocrsp: <empty>\n");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/*
+**  Process mlanutl fcontrol command:
+**
+**    mlanutl mlanX fcontrol %d [0xAA 0xBB... ]
+**
+**  Sets and/or retrieves the feature control settings for a specific
+**    control set (argv[3] decimal argument).
+**
+*/
+int
+process_fcontrol(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	t_u8 idx;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_OFFLOAD_FEATURE_CONTROL *pFcontrol;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	pFcontrol = (HostCmd_DS_OFFLOAD_FEATURE_CONTROL *)pos;
+
+	if (argc < 4) {
+		printf("Wrong number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	pFcontrol->controlSelect = atoi(argv[3]);
+	cmd_len = S_DS_GEN + sizeof(pFcontrol->controlSelect);
+
+	for (idx = 4; idx < argc; idx++) {
+		pFcontrol->controlBitmap[idx - 4] = a2hex_or_atoi(argv[idx]);
+		cmd_len++;
+	}
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_OFFLOAD_FEATURE_CONTROL);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[fcontrol hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	cmd_len = (le16_to_cpu(hostcmd->size) - sizeof(HostCmd_DS_GEN));
+
+	printf("Control[%d]", pFcontrol->controlSelect);
+	cmd_len--;
+
+	for (idx = 0; idx < cmd_len; idx++) {
+		printf("\t0x%02x", pFcontrol->controlBitmap[idx]);
+	}
+
+	printf("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/*
+**  Process mlanutl iapp command:
+**
+**    mlanutl mlanX iapp <timeout> 0xAA 0xBB [0x... 0x.. ]
+**
+**    0xAA = IAPP type
+**    0xBB = IAPP subtype
+**    0x.. = Remaning bytes are iapp data
+**
+*/
+int
+process_iapp(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	t_u8 idx;
+	t_u8 fixlen;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_IAPP_PROXY *pIappProxy;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_IAPP_PROXY);
+
+	pIappProxy = (HostCmd_DS_IAPP_PROXY *)pos;
+
+	if (argc < 6) {
+		printf("Wrong number of arguments\n");
+		ret = -EINVAL;
+	}
+
+	memset(pIappProxy, 0x00, sizeof(HostCmd_DS_IAPP_PROXY));
+
+	pIappProxy->iappType = a2hex_or_atoi(argv[4]);
+	pIappProxy->iappSubType = a2hex_or_atoi(argv[5]);
+
+	/* Fixed len portions of command */
+	fixlen = (S_DS_GEN + sizeof(HostCmd_DS_IAPP_PROXY)
+		  - sizeof(pIappProxy->iappData));
+
+	pIappProxy->timeout_ms = cpu_to_le32(a2hex_or_atoi(argv[3]));
+
+	for (idx = 6; idx < argc; idx++) {
+		pIappProxy->iappData[idx - 6] = a2hex_or_atoi(argv[idx]);
+		pIappProxy->iappDataLen++;
+	}
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_IAPP_PROXY);
+	hostcmd->size = cpu_to_le16(fixlen + pIappProxy->iappDataLen);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	pIappProxy->iappDataLen = cpu_to_le32(pIappProxy->iappDataLen);
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[iapp hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	printf("\nResult:   %d\n", le32_to_cpu(pIappProxy->commandResult));
+	printf("Type:     0x%02x\n", pIappProxy->iappType);
+	printf("SubType:  0x%02x\n", pIappProxy->iappSubType);
+
+	printf("IappData: ");
+	hexdump(NULL, pIappProxy->iappData,
+		le32_to_cpu(pIappProxy->iappDataLen), ' ');
+	printf("\n\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Issue a rf tx power command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_rf_tx_power(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_802_11_RF_TX_POWER *pRfTxPower;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_802_11_RF_TX_POWER);
+
+	pRfTxPower = (HostCmd_DS_802_11_RF_TX_POWER *)pos;
+
+	memset(pRfTxPower, 0x00, sizeof(HostCmd_DS_802_11_RF_TX_POWER));
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_802_11_RF_TX_POWER);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	printf("\n");
+	printf("  MinPower:  %2d\n", pRfTxPower->min_power);
+	printf("  MaxPower:  %2d\n", pRfTxPower->max_power);
+	printf("  Current:   %2d\n", le16_to_cpu(pRfTxPower->current_level));
+	printf("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Issue a authenticate command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_authenticate(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_802_11_AUTHENTICATE *pAuth;
+	unsigned int mac[ETH_ALEN];
+	int tmpIdx;
+
+	if (argc != 4) {
+		printf("Wrong number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_802_11_AUTHENTICATE);
+
+	pAuth = (HostCmd_DS_802_11_AUTHENTICATE *)pos;
+
+	memset(pAuth, 0x00, sizeof(HostCmd_DS_802_11_AUTHENTICATE));
+
+	sscanf(argv[3],
+	       "%2x:%2x:%2x:%2x:%2x:%2x",
+	       mac + 0, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5);
+
+	for (tmpIdx = 0; (unsigned int)tmpIdx < NELEMENTS(mac); tmpIdx++) {
+		pAuth->MacAddr[tmpIdx] = (t_u8)mac[tmpIdx];
+	}
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_802_11_AUTHENTICATE);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+static void
+display_channel(void)
+{
+	FILE *tmpfile;
+	char result[200];
+	char cmdStr[50];
+	int ghz, mhz, chan;
+
+	puts("\n");
+
+	sprintf(cmdStr, "iwlist %s chan", dev_name);
+
+	tmpfile = popen(cmdStr, "r");
+
+	if (tmpfile == NULL) {
+		perror("mlanutl: iwlist failed to get current channel");
+	} else {
+		while (fgets(result, sizeof(result), tmpfile)) {
+			if ((sscanf
+			     (result, " Current Frequency=%d.%d ", &ghz,
+			      &mhz) == 2) ||
+			    (sscanf
+			     (result, " Current Frequency:%d.%d ", &ghz,
+			      &mhz) == 2)) {
+				if (mhz < 10) {
+					mhz *= 100;
+				} else if (mhz < 100) {
+					mhz *= 10;
+				}
+
+				chan = ghz * 1000 + mhz;
+				if (chan > 5000) {
+					chan -= 5000;
+					chan /= 5;
+				} else if (chan == 2484) {
+					chan = 14;
+				} else {
+					chan -= 2407;
+					chan /= 5;
+				}
+				printf("   Channel: %3d [%d.%d GHz]\n", chan,
+				       ghz, mhz);
+			}
+		}
+		pclose(tmpfile);
+	}
+}
+
+static char *
+get_ratestr(int txRate)
+{
+	char *pStr;
+
+	switch (txRate) {
+	case 0:
+		pStr = "1";
+		break;
+	case 1:
+		pStr = "2";
+		break;
+	case 2:
+		pStr = "5.5";
+		break;
+	case 3:
+		pStr = "11";
+		break;
+	case 4:
+		pStr = "6";
+		break;
+	case 5:
+		pStr = "9";
+		break;
+	case 6:
+		pStr = "12";
+		break;
+	case 7:
+		pStr = "18";
+		break;
+	case 8:
+		pStr = "24";
+		break;
+	case 9:
+		pStr = "36";
+		break;
+	case 10:
+		pStr = "48";
+		break;
+	case 11:
+		pStr = "54";
+		break;
+	case 12:
+		pStr = "MCS0";
+		break;
+	case 13:
+		pStr = "MCS1";
+		break;
+	case 14:
+		pStr = "MCS2";
+		break;
+	case 15:
+		pStr = "MCS3";
+		break;
+	case 16:
+		pStr = "MCS4";
+		break;
+	case 17:
+		pStr = "MCS5";
+		break;
+	case 18:
+		pStr = "MCS6";
+		break;
+	case 19:
+		pStr = "MCS7";
+		break;
+
+	case 140:
+		pStr = "MCS0";
+		break;
+	case 141:
+		pStr = "MCS1";
+		break;
+	case 142:
+		pStr = "MCS2";
+		break;
+	case 143:
+		pStr = "MCS3";
+		break;
+	case 144:
+		pStr = "MCS4";
+		break;
+	case 145:
+		pStr = "MCS5";
+		break;
+	case 146:
+		pStr = "MCS6";
+		break;
+	case 147:
+		pStr = "MCS7";
+		break;
+
+	default:
+		pStr = "Unkn";
+		break;
+	}
+
+	return pStr;
+}
+
+typedef struct {
+	int rate;
+	int min;
+	int max;
+
+} RatePower_t;
+
+static int
+get_txpwrcfg(RatePower_t ratePower[])
+{
+	FILE *tmpfile;
+	char result[300];
+	char cmdStr[50];
+	int counter = 0;
+	char *pBuf;
+	int r1 = 0, r2 = 0, min = 0, max = 0, rate = 0;
+	int rateIdx = 0;
+
+	sprintf(cmdStr, "iwpriv %s txpowercfg", dev_name);
+
+	tmpfile = popen(cmdStr, "r");
+
+	if (tmpfile == NULL) {
+		perror("mlanutl: iwpriv failed to get txpowercfg");
+	} else {
+		while (fgets(result, sizeof(result), tmpfile)) {
+			pBuf = strtok(result, ": ");
+
+			while (pBuf != NULL) {
+				switch (counter % 5) {
+				case 0:
+					r1 = atoi(pBuf);
+					break;
+
+				case 1:
+					r2 = atoi(pBuf);
+					break;
+
+				case 2:
+					min = atoi(pBuf);
+					break;
+
+				case 3:
+					max = atoi(pBuf);
+					break;
+
+				case 4:
+					for (rate = r1; rate <= r2; rate++) {
+						ratePower[rateIdx].rate = rate;
+						ratePower[rateIdx].min = min;
+						ratePower[rateIdx].max = max;
+						rateIdx++;
+					}
+					break;
+				}
+
+				if (isdigit(*pBuf)) {
+					counter++;
+				}
+				pBuf = strtok(NULL, ": ");
+			}
+		}
+		pclose(tmpfile);
+	}
+
+	return rateIdx;
+}
+
+static void
+rateSort(RatePower_t rateList[], int numRates)
+{
+	int inc, i, j;
+	RatePower_t tmp;
+
+	inc = 3;
+
+	while (inc > 0) {
+		for (i = 0; i < numRates; i++) {
+			j = i;
+			memcpy(&tmp, &rateList[i], sizeof(RatePower_t));
+
+			while ((j >= inc) &&
+			       (rateList[j - inc].rate > tmp.rate)) {
+				memcpy(&rateList[j], &rateList[j - inc],
+				       sizeof(RatePower_t));
+				j -= inc;
+			}
+
+			memcpy(&rateList[j], &tmp, sizeof(RatePower_t));
+		}
+
+		if (inc >> 1) {
+			inc >>= 1;
+		} else if (inc == 1) {
+			inc = 0;
+		} else {
+			inc = 1;
+		}
+	}
+}
+
+typedef struct {
+	int rate;
+	int modGroup;
+
+} RateModPair_t;
+
+/*
+**
+** ModulationGroups
+**    0: CCK (1,2,5.5,11 Mbps)
+**    1: OFDM (6,9,12,18 Mbps)
+**    2: OFDM (24,36 Mbps)
+**    3: OFDM (48,54 Mbps)
+**    4: HT20 (0,1,2)
+**    5: HT20 (3,4)
+**    6: HT20 (5,6,7)
+**    7: HT40 (0,1,2)
+**    8: HT40 (3,4)
+**    9: HT40 (5,6,7)
+*/
+
+static RateModPair_t rateModPairs[] = {
+	{0, 0},			/* 1 */
+	{1, 0},			/* 2 */
+	{2, 0},			/* 5.5 */
+	{3, 0},			/* 11 */
+	{4, 1},			/* 6 */
+	{5, 1},			/* 9 */
+	{6, 1},			/* 12 */
+	{7, 1},			/* 18 */
+	{8, 2},			/* 24 */
+	{9, 2},			/* 36 */
+	{10, 3},		/* 48 */
+	{11, 3},		/* 54 */
+	{12, 4},		/* MCS0 */
+	{13, 4},		/* MCS1 */
+	{14, 4},		/* MCS2 */
+	{15, 5},		/* MCS3 */
+	{16, 5},		/* MCS4 */
+	{17, 6},		/* MCS5 */
+	{18, 6},		/* MCS6 */
+	{19, 6},		/* MCS7 */
+
+	{140, 7},		/* MCS0 */
+	{141, 7},		/* MCS1 */
+	{142, 7},		/* MCS2 */
+	{143, 8},		/* MCS3 */
+	{144, 8},		/* MCS4 */
+	{145, 9},		/* MCS5 */
+	{146, 9},		/* MCS6 */
+	{147, 9},		/* MCS7 */
+};
+
+int
+process_chantrpcdisp(int startRate, int endRate)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CHAN_TRPC_CONFIG *pChanTrpc;
+	MrvlIEtypes_ChanTrpcCfg_t *pChanTrpcTlv;
+	int totalTlvBytes = 0;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	pChanTrpc = (HostCmd_DS_CHAN_TRPC_CONFIG *)pos;
+	pChanTrpc->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+
+	cmd_len = S_DS_GEN + sizeof(pChanTrpc->action);
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_CHAN_TRPC_CONFIG);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[chantrpc hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	totalTlvBytes = (le16_to_cpu(hostcmd->size)
+			 - sizeof(HostCmd_DS_GEN)
+			 - sizeof(pChanTrpc->action)
+			 - sizeof(pChanTrpc->reserved));
+
+	pChanTrpcTlv = (MrvlIEtypes_ChanTrpcCfg_t *)pChanTrpc->tlv_buffer;
+
+	while (totalTlvBytes) {
+		int tlvSize, numModGroups, idx, modIdx, numOut;
+
+		/* Switch to TLV parsing */
+		printf("%4d.%-3d ",
+		       le16_to_cpu(pChanTrpcTlv->chanDesc.startFreq),
+		       pChanTrpcTlv->chanDesc.chanNum);
+
+		numOut = 0;
+
+		tlvSize = (le16_to_cpu(pChanTrpcTlv->header.len)
+			   + sizeof(pChanTrpcTlv->header));
+
+		numModGroups = (le16_to_cpu(pChanTrpcTlv->header.len)
+				- sizeof(pChanTrpcTlv->chanDesc));
+		numModGroups /= sizeof(pChanTrpcTlv->chanTrpcEntry[0]);
+
+		for (idx = 0; idx < NELEMENTS(rateModPairs); idx++) {
+			if ((rateModPairs[idx].rate >= startRate) &&
+			    (rateModPairs[idx].rate <= endRate)) {
+				for (modIdx = 0; modIdx < numModGroups;
+				     modIdx++) {
+					if (rateModPairs[idx].modGroup ==
+					    pChanTrpcTlv->chanTrpcEntry[modIdx].
+					    modGroup) {
+						printf("%*d",
+						       (numOut == 0) ? 3 : 6,
+						       pChanTrpcTlv->
+						       chanTrpcEntry[modIdx].
+						       txPower);
+						numOut++;
+					}
+				}
+
+				if (numOut == 0) {
+					printf(" --   ");
+				}
+			}
+		}
+
+		puts("");
+
+		pChanTrpcTlv =
+			(MrvlIEtypes_ChanTrpcCfg_t *)((t_u8 *)pChanTrpcTlv +
+						      tlvSize);
+		totalTlvBytes -= tlvSize;
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Issue a tx power display command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_txpowdisp(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int rateIdx, rates;
+	int connected;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_802_11_RF_TX_POWER *pRfTxPower;
+	RatePower_t ratePower[50];
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_802_11_RF_TX_POWER);
+
+	pRfTxPower = (HostCmd_DS_802_11_RF_TX_POWER *)pos;
+
+	memset(pRfTxPower, 0x00, sizeof(HostCmd_DS_802_11_RF_TX_POWER));
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_802_11_RF_TX_POWER);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	connected = le16_to_cpu(pRfTxPower->current_level) ? TRUE : FALSE;
+
+	if (connected) {
+		display_channel();
+
+		printf("\n");
+		printf("  MinPower:  %2d\n", pRfTxPower->min_power);
+		printf("  MaxPower:  %2d\n", pRfTxPower->max_power);
+		printf("  Current:   %2d\n",
+		       le16_to_cpu(pRfTxPower->current_level));
+		printf("\n");
+	}
+
+	rates = get_txpwrcfg(ratePower);
+
+	puts("");
+
+	rateSort(ratePower, rates);
+
+	printf("20MHz:");
+
+	for (rateIdx = 0; rateIdx < 12; rateIdx++) {
+		printf("%6s", get_ratestr(ratePower[rateIdx].rate));
+	}
+
+	printf("\n---------------------------------------"
+	       "----------------------------------------\n%s",
+	       connected ? "Active" : "Max   ");
+
+	for (rateIdx = 0; rateIdx < 12; rateIdx++) {
+		printf("%6d", ratePower[rateIdx].max);
+	}
+
+	if (!connected) {
+		printf("\n---------------------------------------"
+		       "----------------------------------------\n");
+
+		process_chantrpcdisp(ratePower[0].rate, ratePower[12 - 1].rate);
+	}
+
+	puts("\n");
+
+	/*
+	 ** MCS0 -> MCS7
+	 */
+
+	printf("20MHz:");
+
+	for (rateIdx = 12; rateIdx < 20; rateIdx++) {
+		printf("%6s", get_ratestr(ratePower[rateIdx].rate));
+	}
+
+	printf("\n---------------------------------------"
+	       "----------------------------------------\n%s",
+	       connected ? "Active" : "Max   ");
+
+	for (rateIdx = 12; rateIdx < 20; rateIdx++) {
+		printf("%6d", ratePower[rateIdx].max);
+	}
+
+	if (!connected) {
+		printf("\n---------------------------------------"
+		       "----------------------------------------\n");
+
+		process_chantrpcdisp(ratePower[12].rate,
+				     ratePower[20 - 1].rate);
+	}
+
+	puts("\n");
+
+	/*
+	 ** MCS0 -> MCS7 @ 40MHz
+	 */
+
+	printf("40MHz:");
+
+	for (rateIdx = 20; rateIdx < rates; rateIdx++) {
+		printf("%6s", get_ratestr(ratePower[rateIdx].rate));
+	}
+
+	printf("\n---------------------------------------"
+	       "----------------------------------------\n%s",
+	       connected ? "Active" : "Max   ");
+
+	for (rateIdx = 20; rateIdx < rates; rateIdx++) {
+		printf("%6d", ratePower[rateIdx].max);
+	}
+
+	if (!connected) {
+		printf("\n---------------------------------------"
+		       "----------------------------------------\n");
+
+		process_chantrpcdisp(ratePower[20].rate,
+				     ratePower[rates - 1].rate);
+	}
+
+	puts("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
diff --git a/wlan_sd8897/mapp/mlanutl/mlanoffload.h b/wlan_sd8897/mapp/mlanutl/mlanoffload.h
new file mode 100644
index 0000000..2e3e201
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanoffload.h
@@ -0,0 +1,441 @@
+/** @file  mlanoffload.h
+  *
+  * @brief This files contains mlanutl offload command handling.
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     08/11/2009: initial version
+************************************************************************/
+
+#ifndef _MLANOFFLOAD_H_
+#define _MLANOFFLOAD_H_
+
+#ifndef MAX
+/** Find maximum value */
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif /* MAX */
+
+/** Key length */
+#define KEY_LEN             32
+/** Phrase length */
+#define PHRASE_LEN          32
+/** WEP Key count */
+#define WEP_KEY_CNT         4
+
+/* Bitmap for  OFFLoad Enable  - Feature*/
+#ifdef BIG_ENDIAN_SUPPORT
+/** Roaming Feature */
+#define PROFILE_DB_FEATURE_ROAMING      0x8000
+/** CCX Feature */
+#define PROFILE_DB_FEATURE_CCX          0x4000
+/** UNUSED Feature */
+#define PROFILE_DB_FEATURE_UNUSED       0x2000
+/** adhoc/infra mode */
+#define PROFILE_DB_FEATURE_MODE         0x1000
+#else
+/** Roaming Feature */
+#define PROFILE_DB_FEATURE_ROAMING      0x0001
+/** CCX Feature */
+#define PROFILE_DB_FEATURE_CCX          0x0002
+/** UNUSED Feature */
+#define PROFILE_DB_FEATURE_UNUSED       0x0004
+/** adhoc/infra mode */
+#define PROFILE_DB_FEATURE_MODE         0x0008
+#endif
+
+/* Bitmap for profile AKMP Support */
+#ifdef BIG_ENDIAN_SUPPORT
+/** Key Management EAP */
+#define PROFILE_DB_KEY_MGMT_IEEE8021X        0x8000
+/** Key Management PSK */
+#define PROFILE_DB_KEY_MGMT_PSK              0x4000
+/** Key Management NONE */
+#define PROFILE_DB_KEY_MGMT_NONE             0x2000
+/** Key Management CCKM */
+#define PROFILE_DB_KEY_MGMT_CCKM             0x1000
+/** Key Management UNUSED */
+#define PROFILE_DB_KEY_MGMT_UNUSED           0x0800
+/** Key Management FT 802.1x */
+#define PROFILE_DB_KEY_MGMT_FT_IEEE8021X     0x0400
+/** Key Management FT PSK */
+#define PROFILE_DB_KEY_MGMT_FT_PSK           0x0200
+/** Key Management SHA256 802.1x */
+#define PROFILE_DB_KEY_MGMT_SHA256_IEEE8021X 0x0100
+/** Key Management SHA256 PSK*/
+#define PROFILE_DB_KEY_MGMT_SHA256_PSK       0x0080
+#else
+/** Key Management EAP */
+#define PROFILE_DB_KEY_MGMT_IEEE8021X        0x0001
+/** Key Management PSK */
+#define PROFILE_DB_KEY_MGMT_PSK              0x0002
+/** Key Management NONE */
+#define PROFILE_DB_KEY_MGMT_NONE             0x0004
+/** Key Management CCKM */
+#define PROFILE_DB_KEY_MGMT_CCKM             0x0008
+/** Key Management UNUSED */
+#define PROFILE_DB_KEY_MGMT_UNUSED           0x0010
+/** Key Management FT 802.1x */
+#define PROFILE_DB_KEY_MGMT_FT_IEEE8021X     0x0020
+/** Key Management FT PSK */
+#define PROFILE_DB_KEY_MGMT_FT_PSK           0x0040
+/** Key Management SHA256 802.1x */
+#define PROFILE_DB_KEY_MGMT_SHA256_IEEE8021X 0x0080
+/** Key Management SHA256 PSK*/
+#define PROFILE_DB_KEY_MGMT_SHA256_PSK       0x0100
+#endif
+
+/* Bitmap for profile Encryption protocol support */
+#ifdef BIG_ENDIAN_SUPPORT
+/** Encryption protocol noRsn */
+#define PROFILE_DB_PROTO_NO_RSN         0x8000
+/** Encryption protocol static wep */
+#define PROFILE_DB_PROTO_WEP_STATIC     0x4000
+/** Encryption protocol dynamic wep */
+#define PROFILE_DB_PROTO_WEP_DYNAMIC    0x2000
+/** Encryption protocol WPA */
+#define PROFILE_DB_PROTO_WPA            0x1000
+/** Encryption protocol WPA-none
+ *  Ad-hoc Networks */
+#define PROFILE_DB_PROTO_WPA_NONE       0x0800
+/** Encryption protocol WPA2 */
+#define PROFILE_DB_PROTO_WPA2           0x0400
+/** Encryption protocol CCKM */
+#define PROFILE_DB_PROTO_CCKM           0x0200
+#else
+/** Encryption protocol noRsn */
+#define PROFILE_DB_PROTO_NO_RSN         0x0001
+/** Encryption protocol static wep */
+#define PROFILE_DB_PROTO_WEP_STATIC     0x0002
+/** Encryption protocol dynamic wep */
+#define PROFILE_DB_PROTO_WEP_DYNAMIC    0x0004
+/** Encryption protocol WPA */
+#define PROFILE_DB_PROTO_WPA            0x0008
+/** Encryption protocol WPA-none
+ *  Ad-hoc Networks */
+#define PROFILE_DB_PROTO_WPA_NONE       0x0010
+/** Encryption protocol WPA2 */
+#define PROFILE_DB_PROTO_WPA2           0x0020
+/** Encryption protocol CCKM */
+#define PROFILE_DB_PROTO_CCKM           0x0040
+#endif
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Cipher wep40 */
+#define PROFILE_DB_CIPHER_WEP40         0x80
+/** Cipher wep104 */
+#define PROFILE_DB_CIPHER_WEP104        0x40
+/** Cipher tkip */
+#define PROFILE_DB_CIPHER_TKIP          0x20
+/** Cipher ccmp */
+#define PROFILE_DB_CIPHER_CCMP          0x10
+#else
+/** Cipher wep40 */
+#define PROFILE_DB_CIPHER_WEP40         0x01
+/** Cipher wep104 */
+#define PROFILE_DB_CIPHER_WEP104        0x02
+/** Cipher tkip */
+#define PROFILE_DB_CIPHER_TKIP          0x04
+/** Cipher ccmp */
+#define PROFILE_DB_CIPHER_CCMP          0x08
+#endif
+
+typedef struct {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+
+	t_u32 mode;	  /**< Mode */
+	t_u32 max_off_channel;
+			  /**< Maximum off-channel measurement duration (ms) */
+	t_u32 max_on_channel;
+			  /**< Maximum on-channel measurement duration (ms) */
+
+} __ATTRIB_PACK__ MrvlIETypes_MeasTiming_t;
+
+typedef struct {
+    /** Action Set or get */
+	t_u16 action;
+
+    /** TLV buffer starts here */
+	t_u8 tlv_buffer[1];
+
+	/*
+	 * MrvlIETypes_MeasTiming_t
+	 */
+} __ATTRIB_PACK__ HostCmd_DS_MEASUREMENT_Timing;
+
+/** helper structure for profile parsing */
+typedef struct {
+    /** SSID name string */
+	t_u8 ssid[IW_ESSID_MAX_SIZE + 1];
+    /** SSID len */
+	t_u32 ssid_len;
+    /** BSSID network name */
+	t_u8 bssid[ETH_ALEN];
+    /** passphrase configured */
+	t_s8 passphrase[PHRASE_LEN];
+    /** passphrase length */
+	t_u32 passphrase_len;
+    /** Pre-shared key config flag */
+	int psk_config;
+    /** Pre-shared key */
+	t_u8 psk[KEY_LEN];
+    /** wep keys */
+	t_u8 wep_key[WEP_KEY_CNT][KEY_LEN];
+    /** wep keys lengths */
+	t_u8 wep_key_len[WEP_KEY_CNT];
+    /** wep key index */
+	int wep_key_idx;
+    /** protocol fields */
+	t_u16 protocol;
+    /** pairwise Cipher values */
+	t_u8 pairwise_cipher;
+    /** Group Cipher values */
+	t_u8 groupwise_cipher;
+    /** key management */
+	t_u16 key_mgmt;
+    /** offload specific parameter(roaming) */
+	t_u16 roaming;
+    /** offload specific parameter */
+	t_u16 reserved;
+    /** offload specific parameter--ccx */
+	t_u16 ccx;
+    /** offload specific parameter--mode */
+	t_u16 mode;
+} profile_entry_t;
+
+typedef struct {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Reserved */
+	t_u8 Reserved:3;
+    /** Channel not measured */
+	t_u8 Unmeasured:1;
+    /** Radar detected */
+	t_u8 Radar:1;
+    /** Unidentified signal received */
+	t_u8 Unidentified:1;
+    /** OFDM Preamble received */
+	t_u8 OFDM_Preamble:1;
+    /** BSS found */
+	t_u8 BSS:1;
+#else
+    /** BSS found */
+	t_u8 BSS:1;
+    /** OFDM Preamble received */
+	t_u8 OFDM_Preamble:1;
+    /** Unidentified signal received */
+	t_u8 Unidentified:1;
+    /** Radar detected */
+	t_u8 Radar:1;
+    /** Channel not measured */
+	t_u8 Unmeasured:1;
+    /** Reserved */
+	t_u8 Reserved:3;
+#endif
+} __ATTRIB_PACK__ IEEEtypes_DFS_Map_t;
+
+typedef struct {
+	MrvlIEtypesHeader_t Header;  /**< Header */
+
+	t_u8 scanReqId;		       /**< Scan request id assigned in table */
+} __ATTRIB_PACK__ MrvlIEtypes_ChanRptBcn_t;
+
+typedef struct {
+	MrvlIEtypesHeader_t Header;  /**< Header */
+
+	IEEEtypes_DFS_Map_t map;     /**< IEEE 802.11h basic meas report */
+} __ATTRIB_PACK__ MrvlIEtypes_ChanRpt11hBasic_t;
+
+typedef struct {
+	MrvlIEtypesHeader_t Header;		/**< Header */
+
+	t_u8 sourceAddr[ETH_ALEN];		/**< Source MAC */
+	t_u8 bssid[ETH_ALEN];			/**< BSSID MAC */
+	t_s16 rssi;				/**< Avg RSSI of frames */
+	t_u16 frameCnt;				/**< # of frames */
+} __ATTRIB_PACK__ MrvlIEtypes_ChanRptFrame_t;
+
+typedef struct {
+	t_u8 modGroup;
+	t_u8 txPower;
+
+} __ATTRIB_PACK__ MrvlChanTrpcEntry_t;
+
+typedef struct {
+	MrvlIEtypesHeader_t header;
+				  /**< Header */
+
+	MrvlChannelDesc_t chanDesc;
+	MrvlChanTrpcEntry_t chanTrpcEntry[1];
+
+} __ATTRIB_PACK__ MrvlIEtypes_ChanTrpcCfg_t;
+
+typedef struct {
+	t_u16 action;
+		   /**< CMD Action Get/Set*/
+	t_u16 reserved;
+
+	t_u8 tlv_buffer[1];/** MrvlIEtypes_ChanTrpcCfg_t TLVs */
+
+} __ATTRIB_PACK__ HostCmd_DS_CHAN_TRPC_CONFIG;
+
+typedef struct {
+	t_u8 controlSelect;
+
+	t_u8 controlBitmap[1];	/* Variable length # of byte bitmaps */
+
+} __ATTRIB_PACK__ HostCmd_DS_OFFLOAD_FEATURE_CONTROL;
+
+#define IAPP_DATA_MAX 1000
+
+/**
+ *  @brief Enumeration for the command result from an IAPP Proxy command
+ */
+typedef enum {
+	IAPP_PROXY_RESULT_SUCCESS = 0,
+	IAPP_PROXY_RESULT_EXEC_FAILURE = 1,
+	IAPP_PROXY_RESULT_TIMEOUT = 2,
+	IAPP_PROXY_RESULT_DATA_INVALID = 3,
+} __ATTRIB_PACK__ mlan_iapp_proxy_result_e;
+
+typedef struct {
+	mlan_iapp_proxy_result_e commandResult;
+					    /**< Firmware execution result */
+
+	t_u32 timeout_ms;  /**< Timeout value in milliseconds */
+
+	t_u8 iappType;
+	t_u8 iappSubType;
+
+	t_u32 iappDataLen;
+	t_u8 iappData[IAPP_DATA_MAX];
+
+} __ATTRIB_PACK__ HostCmd_DS_IAPP_PROXY;
+
+typedef struct {
+    /** Action: GET/SET */
+	t_u16 Action;
+    /** Reserved */
+	t_u16 Reserved;
+    /** Association timeout */
+	t_u32 AssocTimeout;
+    /** Reassociation timeout */
+	t_u32 ReassocTimeout;
+    /** Hand shake timeout */
+	t_u32 HandShakeTimeout;
+    /** Frame exchange timeout */
+	t_u32 FrameExchangeTimeout;
+    /** Deauth of old AP in millisec; 0 to disable */
+	t_u32 PriorApDeauthDelay;
+    /** Maximum time after a disconnect where a reassoc frame will be sent */
+	t_u32 ReassocDiscMax;
+} __ATTRIB_PACK__ HostCmd_DS_AssociationTiming_t;
+
+/** 16 bit unsigned integer */
+typedef t_u16 IEEEtypes_AId_t;
+/** 16 bit unsigned integer */
+typedef t_u16 IEEEtypes_StatusCode_t;
+
+typedef struct {
+    /** Capability information */
+	IEEEtypes_CapInfo_t Capability;
+    /** Association response status code */
+	IEEEtypes_StatusCode_t StatusCode;
+    /** Association ID */
+	IEEEtypes_AId_t AId;
+    /** IE data buffer */
+	t_u8 IEBuffer[1];
+} __ATTRIB_PACK__ IEEEtypes_AssocRsp_t;
+
+/** Maximum number of AC QOS queues available in the driver/firmware */
+#define MAX_AC_QUEUES 4
+
+/** timing select structure */
+typedef struct {
+	char *str;	/**< Timing mode string */
+	int match_len;	/**< match length */
+	t_u8 sel;	/**< flag */
+
+} timing_sel_t;
+
+/** ENUM definition: reg_chan_table */
+typedef enum {
+	REGTABLE_DEFAULT = 0,
+	REGTABLE_ESS = 1,
+	REGTABLE_USER = 2,
+	REGTABLE_MULTIDOMAIN = 3,
+
+	REGTABLE_MAX = 0xFFFF,
+} reg_chan_table_e;
+
+/** Sub-command callback */
+typedef int (*sub_cmd_callback_t) (int argc, char *argv[]);
+
+/** Sub-command execution data */
+typedef struct {
+	char *str;
+	       /**< Command string */
+	int match_len;
+		     /**< Length */
+	int display;
+		   /**< display as valid cmd */
+	sub_cmd_callback_t callback;
+				 /**< Sub-command callback */
+
+} sub_cmd_exec_t;
+
+/**  HostCmd_CMD_802_11_RF_TX_POWER */
+typedef struct {
+	t_u16 action;
+	t_s16 current_level;
+	t_s8 max_power;
+	t_s8 min_power;
+
+} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_TX_POWER;
+
+/**  HostCmd_CMD_802_11_AUTHENTICATE */
+typedef struct {
+    /** MAC address */
+	t_u8 MacAddr[ETH_ALEN];
+    /** Authentication type */
+	t_u8 AuthType;
+} __ATTRIB_PACK__ HostCmd_DS_802_11_AUTHENTICATE;
+
+boolean reg_class_table_select(char *tableStr, reg_chan_table_e *pTable);
+int process_sub_cmd(sub_cmd_exec_t *sub_cmd, int num_sub_cmds,
+		    int argc, char *argv[]);
+int process_regclass(int argc, char *argv[]);
+int process_scanagent(int argc, char *argv[]);
+int process_measurement(int argc, char *argv[]);
+int process_profile_entry(int argc, char *argv[]);
+int process_get_ra_config(int argc, char *argv[]);
+int process_set_ra_config(int argc, char *argv[]);
+int process_chanrpt(int argc, char *argv[]);
+int process_assoc_timing(int argc, char *argv[]);
+int process_get_assocrsp(int argc, char *argv[]);
+int process_link_stats(int argc, char *argv[]);
+
+int process_opchan(int argc, char *argv[]);
+int process_changroup(int argc, char *argv[]);
+int process_fcontrol(int argc, char *argv[]);
+int process_iapp(int argc, char *argv[]);
+int process_rf_tx_power(int argc, char *argv[]);
+int process_authenticate(int argc, char *argv[]);
+int process_txpowdisp(int argc, char *argv[]);
+
+#endif /* _MLANOFFLOAD_H_ */
diff --git a/wlan_sd8897/mapp/mlanutl/mlanregclass.c b/wlan_sd8897/mapp/mlanutl/mlanregclass.c
new file mode 100644
index 0000000..53963e6
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanregclass.c
@@ -0,0 +1,539 @@
+/** @file  mlanregclass.c
+  *
+  * @brief This files contains mlanutl regclass command handling.
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     08/11/2009: initial version
+************************************************************************/
+
+#include    "mlanutl.h"
+#include    "mlanhostcmd.h"
+#include    "mlanoffload.h"
+#include    "mlanregclass.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief Convert reg domain number to string
+ *
+ *  @param reg_domain Reg Domain
+ *
+ *  @return           Reg Domain type
+ */
+static char *
+reg_domain_to_str(reg_domain_e reg_domain)
+{
+	switch (reg_domain) {
+	case REGDOMAIN_FCC:
+		return "FCC";
+
+	case REGDOMAIN_ETSI:
+		return "ETSI";
+
+	case REGDOMAIN_MIC:
+		return "MIC";
+
+	case REGDOMAIN_OTHER:
+		return "MULTI";
+
+	default:
+		break;
+	}
+
+	return "UNKN";
+}
+
+/**
+ *  @brief Convert reg channel table number to string
+ *
+ *  @param table_select Reg channel table
+ *
+ *  @return             Reg channel table type
+ */
+static char *
+table_num_to_str(reg_chan_table_e table_select)
+{
+	switch (table_select) {
+	case REGTABLE_USER:
+		return "User";
+
+	case REGTABLE_MULTIDOMAIN:
+		return "MultiDomain";
+
+	case REGTABLE_ESS:
+		return "ESS";
+
+	case REGTABLE_DEFAULT:
+		return "Default";
+
+	default:
+		break;
+	}
+
+	return "UNKN";
+}
+
+/**
+ *  @brief      Regclass dump channel table
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+reg_class_dump_chan_table(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_REGCLASS_GET_CHAN_TABLE *get_table;
+	int idx;
+	t_u16 regLimits;
+	boolean invalid_cmd = FALSE;
+
+	printf("ERR:Cannot allocate buffer for command!\n");
+	if (argv[0] == NULL) {
+		invalid_cmd = TRUE;
+	} else {
+
+		cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+		buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+		if (buffer == NULL) {
+			fprintf(stderr, "Cannot alloc memory\n");
+			ret = ENOMEM;
+			goto done;
+		}
+		memset(buffer, 0, BUFFER_LENGTH);
+
+		cmd = (struct eth_priv_cmd *)
+			malloc(sizeof(struct eth_priv_cmd));
+		if (!cmd) {
+			printf("ERR:Cannot allocate buffer for command!\n");
+			ret = ENOMEM;
+			goto done;
+		}
+
+		/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+		memset(cmd, 0, sizeof(struct eth_priv_cmd));
+		memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+		cmd->buf = buffer;
+#endif
+		cmd->used_len = 0;
+		cmd->total_len = BUFFER_LENGTH;
+
+		/* buffer = MRVL_CMD<cmd> */
+		strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+		strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD,
+			strlen(HOSTCMD));
+
+		/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+		hostcmd =
+			(HostCmd_DS_GEN *)(buffer + cmd_header_len +
+					   sizeof(t_u32));
+
+		/* Point after host command header */
+		pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+		cmd_len = S_DS_GEN + sizeof(HostCmd_DS_REGCLASS_GET_CHAN_TABLE);
+		hostcmd->command = cpu_to_le16(HostCmd_CMD_REGCLASS_CHAN_TABLE);
+		hostcmd->size = cpu_to_le16(cmd_len);
+		hostcmd->seq_num = 0;
+		hostcmd->result = 0;
+
+		get_table = (HostCmd_DS_REGCLASS_GET_CHAN_TABLE *)pos;
+		get_table->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+
+		if (reg_class_table_select(argv[0], (reg_chan_table_e *)
+					   &get_table->table_select) == FALSE) {
+			invalid_cmd = TRUE;
+		}
+	}
+
+	if (invalid_cmd) {
+		printf("\nValid tables table; valid [user, md, ess, default]\n\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	get_table->table_select = cpu_to_le16((t_u16)(get_table->table_select));
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[regClassIoctl]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!le16_to_cpu(hostcmd->result)) {
+		printf("HOSTCMD_RESP: ReturnCode=%#04x, Result=%#04x\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	}
+
+	get_table->table_select = le16_to_cpu(get_table->table_select);
+	get_table->chan = le32_to_cpu(get_table->chan);
+
+	printf("---------------------------------------");
+	printf("---------------------------------------\n");
+	printf("%35s: %s [%d]\n", "Channel Table",
+	       table_num_to_str(get_table->table_select), (int)get_table->chan);
+	printf("---------------------------------------");
+	printf("---------------------------------------\n");
+	printf(" chn | freq | sfrq | sp |  class   | maxP | behavior limits\n");
+	printf("---------------------------------------");
+	printf("---------------------------------------\n");
+
+	for (idx = 0; (unsigned int)idx < get_table->chan; idx++) {
+		char regDisp[8];
+
+		sprintf(regDisp, "%4s-%02u",
+			reg_domain_to_str(get_table->chan_entry[idx].
+					  reg_domain),
+			get_table->chan_entry[idx].regulatory_class);
+
+		printf(" %03u | %04u | %04u | %02u | %-8s |  %02u  |",
+		       get_table->chan_entry[idx].chan_num,
+		       (get_table->chan_entry[idx].start_freq +
+			(get_table->chan_entry[idx].chan_num * 5)),
+		       le16_to_cpu(get_table->chan_entry[idx].start_freq),
+		       le16_to_cpu(get_table->chan_entry[idx].chan_spacing),
+		       regDisp, get_table->chan_entry[idx].max_tx_power);
+
+		regLimits = le16_to_cpu(get_table->chan_entry[idx].reg_limits);
+
+		if (regLimits & BLIMIT_NOMADIC)
+			printf(" nomadic");
+		if (regLimits & BLIMIT_INDOOR_ONLY)
+			printf(" indoor");
+		if (regLimits & BLIMIT_TPC)
+			printf(" tpc");
+		if (regLimits & BLIMIT_DFS)
+			printf(" dfs");
+		if (regLimits & BLIMIT_IBSS_PROHIBIT)
+			printf(" no_ibss");
+		if (regLimits & BLIMIT_FOUR_MS_CS)
+			printf(" 4ms_cs");
+		if (regLimits & BLIMIT_LIC_BASE_STA)
+			printf(" base_sta");
+		if (regLimits & BLIMIT_MOBILE_STA)
+			printf(" mobile");
+		if (regLimits & BLIMIT_PUBLIC_SAFETY)
+			printf(" safety");
+		if (regLimits & BLIMIT_ISM_BANDS)
+			printf(" ism");
+
+		printf("\n");
+	}
+	printf("---------------------------------------");
+	printf("---------------------------------------\n");
+	printf("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief      Regclass configure user table
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+reg_class_config_user_table(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_REGCLASS_CONFIG_USER_TABLE *cfg_user_table;
+
+	if (argv[0] == NULL) {
+		printf("\nCountry string not specified\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_REGCLASS_CONFIG_USER_TABLE);
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_REGCLASS_CONFIG_USER_TABLE);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	cfg_user_table = (HostCmd_DS_REGCLASS_CONFIG_USER_TABLE *)pos;
+	cfg_user_table->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+	memcpy(cfg_user_table->regulatory_str,
+	       argv[0],
+	       MIN(strlen(argv[0]), sizeof(cfg_user_table->regulatory_str)));
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[regClassIoctl]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!le16_to_cpu(hostcmd->result)) {
+		printf("HOSTCMD_RESP: ReturnCode=%#04x, Result=%#04x\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief      Issue regclass multi-domain command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+reg_class_multidomain(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_REGCLASS_MULTIDOMAIN_CONTROL *multidomain_ctrl;
+	boolean invalid_cmd = FALSE;
+
+	if (argv[0] == NULL) {
+		invalid_cmd = TRUE;
+	} else {
+		cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+		buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+		if (buffer == NULL) {
+			fprintf(stderr, "Cannot alloc memory\n");
+			ret = ENOMEM;
+			goto done;
+		}
+		memset(buffer, 0, BUFFER_LENGTH);
+
+		cmd = (struct eth_priv_cmd *)
+			malloc(sizeof(struct eth_priv_cmd));
+		if (!cmd) {
+			printf("ERR:Cannot allocate buffer for command!\n");
+			ret = ENOMEM;
+			goto done;
+		}
+
+		/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+		memset(cmd, 0, sizeof(struct eth_priv_cmd));
+		memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+		cmd->buf = buffer;
+#endif
+		cmd->used_len = 0;
+		cmd->total_len = BUFFER_LENGTH;
+
+		/* buffer = MRVL_CMD<cmd> */
+		strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+		strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD,
+			strlen(HOSTCMD));
+
+		/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+		hostcmd =
+			(HostCmd_DS_GEN *)(buffer + cmd_header_len +
+					   sizeof(t_u32));
+
+		/* Point after host command header */
+		pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+		cmd_len =
+			S_DS_GEN +
+			sizeof(HostCmd_DS_REGCLASS_MULTIDOMAIN_CONTROL);
+		hostcmd->command =
+			cpu_to_le16(HostCmd_CMD_REGCLASS_MULTIDOMAIN_CONTROL);
+		hostcmd->size = cpu_to_le16(cmd_len);
+		hostcmd->seq_num = 0;
+		hostcmd->result = 0;
+
+		multidomain_ctrl =
+			(HostCmd_DS_REGCLASS_MULTIDOMAIN_CONTROL *)pos;
+		if (strcmp(argv[0], "on") == 0) {
+			multidomain_ctrl->multidomain_enable = 1;
+		} else if (strcmp(argv[0], "off") == 0) {
+			multidomain_ctrl->multidomain_enable = 0;
+		} else {
+			invalid_cmd = TRUE;
+		}
+	}
+
+	if (invalid_cmd) {
+		printf("\nUnknown multiDomain command; valid [on, off]\n\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	multidomain_ctrl->multidomain_enable =
+		cpu_to_le32(multidomain_ctrl->multidomain_enable);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[regClass]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	} else {
+		printf("\nMultiDomain: %s\n",
+		       le32_to_cpu(multidomain_ctrl->multidomain_enable) ?
+		       "Enabled" : "Disabled");
+	}
+
+	if (!le16_to_cpu(hostcmd->result)) {
+		printf("HOSTCMD_RESP: ReturnCode=%#04x, Result=%#04x\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Issue a regclass command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_regclass(int argc, char *argv[])
+{
+	sub_cmd_exec_t sub_cmd[] = { {"table", 1, 1, reg_class_dump_chan_table},
+	{"multidomain", 1, 1, reg_class_multidomain},
+	{"country", 1, 1, reg_class_config_user_table}
+	};
+
+	return process_sub_cmd(sub_cmd, NELEMENTS(sub_cmd), argc, argv);
+}
diff --git a/wlan_sd8897/mapp/mlanutl/mlanregclass.h b/wlan_sd8897/mapp/mlanutl/mlanregclass.h
new file mode 100644
index 0000000..5708c4e
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanregclass.h
@@ -0,0 +1,99 @@
+/** @file  mlanregclass.h
+  *
+  * @brief This files contains mlanutl regclass command handling.
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     08/11/2009: initial version
+************************************************************************/
+
+#ifndef _MLANREGCLASS_H
+#define _MLANREGCLASS_H
+
+/** Nomadic */
+#define BLIMIT_NOMADIC       (1 << 0)
+/** Indoor */
+#define BLIMIT_INDOOR_ONLY   (1 << 1)
+/** Tpc */
+#define BLIMIT_TPC           (1 << 2)
+/** Dfs */
+#define BLIMIT_DFS           (1 << 3)
+/** IBSS Prohibit */
+#define BLIMIT_IBSS_PROHIBIT (1 << 4)
+/** Four MS CS */
+#define BLIMIT_FOUR_MS_CS    (1 << 5)
+/** LIC Base STA */
+#define BLIMIT_LIC_BASE_STA  (1 << 6)
+/** Mobile STA */
+#define BLIMIT_MOBILE_STA    (1 << 7)
+/** Public Safety */
+#define BLIMIT_PUBLIC_SAFETY (1 << 8)
+/** ISM Bands */
+#define BLIMIT_ISM_BANDS     (1 << 9)
+
+/** Enum Definitions: reg_domain */
+typedef enum {
+	REGDOMAIN_NULL = 0x00,
+
+	REGDOMAIN_FCC = 0x01,
+	REGDOMAIN_ETSI = 0x02,
+	REGDOMAIN_MIC = 0x03,
+
+	REGDOMAIN_OTHER = 0xFF,
+
+} reg_domain_e;
+
+typedef struct {
+	t_u8 reg_domain;    /**< Domain */
+	t_u8 regulatory_class;
+			    /**< Regulatory class */
+	t_u8 chan_num;	    /**< Channel Number */
+	t_u8 reserved1;	    /**< Reserved */
+	t_u16 start_freq;   /**< Start frequency */
+	t_u16 chan_spacing; /**< channel spacing */
+	t_u8 max_tx_power;  /**< Max. tx power */
+	t_u8 coverage_class;/**< Coverage class */
+	t_u16 reg_limits;   /**< Limits */
+} __ATTRIB_PACK__ chan_entry_t;
+
+typedef struct {
+    /** Action: GET/SET */
+	t_u16 action;
+    /** Reg channel table */
+	t_u16 table_select;
+    /** Channel number */
+	t_u32 chan;
+    /** Channel entry */
+	chan_entry_t chan_entry[75];
+} __ATTRIB_PACK__ HostCmd_DS_REGCLASS_GET_CHAN_TABLE;
+
+typedef struct {
+	t_u16 action;
+		    /**< Action: GET/SET */
+	t_u16 reserved;
+		      /**< Reserved */
+	char regulatory_str[3];/**< Regulatory String */
+} __ATTRIB_PACK__ HostCmd_DS_REGCLASS_CONFIG_USER_TABLE;
+
+typedef struct {
+	t_u32 multidomain_enable;
+			      /**< Multi domain enable */
+} __ATTRIB_PACK__ HostCmd_DS_REGCLASS_MULTIDOMAIN_CONTROL;
+
+#endif /* _MLANREGCLASS_H */
diff --git a/wlan_sd8897/mapp/mlanutl/mlanroamagent.c b/wlan_sd8897/mapp/mlanutl/mlanroamagent.c
new file mode 100644
index 0000000..6170d63
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanroamagent.c
@@ -0,0 +1,3669 @@
+/** @file  mlanroamagent.c
+ *
+ * @brief This files contains mlanutl roamagent command handling.
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+/************************************************************************
+Change log:
+     08/11/2009: initial version
+************************************************************************/
+
+#include    "mlanutl.h"
+#include    "mlanhostcmd.h"
+#include    "mlanoffload.h"
+#include    "mlanroamagent.h"
+
+/********************************************************
+				Local Variables
+********************************************************/
+
+/********************************************************
+				Global Variables
+********************************************************/
+
+/********************************************************
+				Local Functions
+********************************************************/
+
+/**
+ *  @brief          Issue getra failcnt command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetFailureCount(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int failCount, failTimeThresh, state, i;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
+	MrvlIEtypes_FailureCount_t *pFailureCount;
+	MrvlIEtypesHeader_t *pTlvHdr;
+	t_u8 *tlvptr;
+	const char *states[] =
+		{ "Stable", "Degrading", "Unacceptable", "Hardroam" };
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
+	cmd_len =
+		(S_DS_GEN +
+		 sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD)
+		 - sizeof(statsthreshold->TlvBuffer));
+
+	/* Can be extended to all states later */
+	for (state = STATE_HARDROAM - 1; state < STATE_HARDROAM; state++) {
+		statsthreshold->State = state + 1;
+		hostcmd->command =
+			cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
+		hostcmd->size = cpu_to_le16(cmd_len);
+		hostcmd->seq_num = 0;
+		hostcmd->result = 0;
+		statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+
+		/* Put buffer length */
+		memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+		/* Initialize the ifr structure */
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+		ifr.ifr_ifru.ifru_data = (void *)cmd;
+		/* Perform ioctl */
+		if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+			perror("ioctl[roamstatistics]");
+			printf("ERR:Command sending failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		i = le16_to_cpu(hostcmd->size);
+		i -= cmd_len;
+		tlvptr = statsthreshold->TlvBuffer;
+
+		while (i > 2) {
+			pTlvHdr = (MrvlIEtypesHeader_t *)tlvptr;
+
+			switch (le16_to_cpu(pTlvHdr->type)) {
+			case TLV_TYPE_FAILCOUNT:
+				pFailureCount =
+					(MrvlIEtypes_FailureCount_t *)pTlvHdr;
+				failCount = pFailureCount->fail_value;
+				failTimeThresh =
+					le16_to_cpu(pFailureCount->
+						    fail_min_thresh_time_millisecs);
+				break;
+			}
+
+			tlvptr += (le16_to_cpu(pTlvHdr->len)
+				   + sizeof(MrvlIEtypesHeader_t));
+			i -= (le16_to_cpu(pTlvHdr->len)
+			      + sizeof(MrvlIEtypesHeader_t));
+		}
+
+		printf("State: %-8s. FailCount = %d, FailTimeThresh(ms) = %d\n",
+		       states[state], failCount, failTimeThresh);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue getra bcnmiss command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetPreBeaconMiss(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int bcnmiss, state = STATE_HARDROAM, i;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
+	MrvlIEtypes_BeaconsMissed_t *pBeaconMissed;
+	MrvlIEtypesHeader_t *pTlvHdr;
+	t_u8 *tlvptr;
+	const char *states[] =
+		{ "Stable", "Degrading", "Unacceptable", "Hardroam" };
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
+	cmd_len =
+		(S_DS_GEN +
+		 sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD)
+		 - sizeof(statsthreshold->TlvBuffer));
+
+	/* Can be extended to all states later */
+	for (state = STATE_HARDROAM - 1; state < STATE_HARDROAM; state++) {
+		statsthreshold->State = state + 1;
+		hostcmd->command =
+			cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
+		hostcmd->size = cpu_to_le16(cmd_len);
+		hostcmd->seq_num = 0;
+		hostcmd->result = 0;
+		statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+
+		/* Put buffer length */
+		memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+		/* Initialize the ifr structure */
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+		ifr.ifr_ifru.ifru_data = (void *)cmd;
+		/* Perform ioctl */
+		if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+			perror("ioctl[beacon miss]");
+			printf("ERR:Command sending failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		i = le16_to_cpu(hostcmd->size);
+		i -= cmd_len;
+		tlvptr = statsthreshold->TlvBuffer;
+
+		while (i > 2) {
+			pTlvHdr = (MrvlIEtypesHeader_t *)tlvptr;
+
+			switch (le16_to_cpu(pTlvHdr->type)) {
+
+			case TLV_TYPE_PRE_BEACON_LOST:
+				pBeaconMissed =
+					(MrvlIEtypes_BeaconsMissed_t *)pTlvHdr;
+				bcnmiss = pBeaconMissed->beacon_missed;
+			}
+
+			tlvptr += (le16_to_cpu(pTlvHdr->len)
+				   + sizeof(MrvlIEtypesHeader_t));
+			i -= (le16_to_cpu(pTlvHdr->len)
+			      + sizeof(MrvlIEtypesHeader_t));
+		}
+
+		printf("State: %-8s. Pre Beacon missed threshold %d\n",
+		       states[state], bcnmiss);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue getra rssi/snr command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param type     RSSI/SNR threshold type
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetStatsThreshold(int argc, char *argv[], int type)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int state = 0, i = 0, profile = 1;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
+	MrvlIEtypes_BeaconHighRssiThreshold_t *pHighRssiThreshold;
+	MrvlIEtypes_BeaconLowRssiThreshold_t *pLowRssiThreshold;
+	MrvlIEtypes_BeaconHighSnrThreshold_t *pHighSnrThreshold;
+	MrvlIEtypes_BeaconLowSnrThreshold_t *pLowSnrThreshold;
+	t_s8 high, low;
+	t_u8 *tlvptr;
+	t_u16 tlv;
+	const char *states[] = { "Stable", "Degrading", "Unacceptable" };
+
+	if (argc) {
+		if (strncmp(argv[0], "configured", strlen("config")) == 0) {
+			profile = 0;
+		} else if (strncmp(argv[0], "active", strlen("active"))) {
+			printf("\nIncorrect parameter %s for getra command\n\n",
+			       argv[0]);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
+	cmd_len =
+		(S_DS_GEN +
+		 sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD)
+		 - sizeof(statsthreshold->TlvBuffer));
+
+	printf("---------------------------------------------\n");
+	if (type == RSSI_THRESHOLD) {
+		printf("               RSSI Thresholds\n");
+	} else {
+		printf("                SNR Thresholds\n");
+	}
+	printf("---------------------------------------------\n");
+
+	for (state = STATE_STABLE - 1; state < STATE_UNACCEPTABLE; state++) {
+		statsthreshold->State = state + 1;
+		statsthreshold->Profile = profile;
+		hostcmd->command =
+			cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
+		hostcmd->size = cpu_to_le16(cmd_len);
+		hostcmd->seq_num = 0;
+		hostcmd->result = 0;
+		statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+
+		/* Put buffer length */
+		memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+		/* Initialize the ifr structure */
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+		ifr.ifr_ifru.ifru_data = (void *)cmd;
+		/* Perform ioctl */
+		if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+			perror("ioctl[roamstatistics]");
+			printf("ERR:Command sending failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		if (le16_to_cpu(hostcmd->result)) {
+			printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", le16_to_cpu(hostcmd->command), le16_to_cpu(hostcmd->result));
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		i = le16_to_cpu(hostcmd->size);
+		i -= cmd_len;
+		tlvptr = statsthreshold->TlvBuffer;
+		while (i > 2) {
+			/*
+			 * ENDIANNESS for Response
+			 */
+			tlv = le16_to_cpu(*((t_u16 *)(tlvptr)));
+
+			switch (tlv) {
+			case TLV_TYPE_RSSI_HIGH:
+				high = *(t_s8 *)(tlvptr + sizeof(t_u16) +
+						 sizeof(t_u16));
+				pHighRssiThreshold =
+					(MrvlIEtypes_BeaconHighRssiThreshold_t
+					 *)(tlvptr);
+				tlvptr +=
+					(le16_to_cpu
+					 (pHighRssiThreshold->Header.len) +
+					 sizeof(MrvlIEtypesHeader_t));
+				i -= (le16_to_cpu
+				      (pHighRssiThreshold->Header.len) +
+				      sizeof(MrvlIEtypesHeader_t));
+				break;
+
+			case TLV_TYPE_RSSI_LOW:
+				low = *(t_s8 *)(tlvptr + sizeof(t_u16) +
+						sizeof(t_u16));
+				pLowRssiThreshold =
+					(MrvlIEtypes_BeaconLowRssiThreshold_t
+					 *)(tlvptr);
+				tlvptr +=
+					(le16_to_cpu
+					 (pLowRssiThreshold->Header.len) +
+					 sizeof(MrvlIEtypesHeader_t));
+				i -= (le16_to_cpu(pLowRssiThreshold->Header.len)
+				      + sizeof(MrvlIEtypesHeader_t));
+				break;
+
+			case TLV_TYPE_SNR_HIGH:
+				high = *(t_s8 *)(tlvptr + sizeof(t_u16) +
+						 sizeof(t_u16));
+				pHighSnrThreshold =
+					(MrvlIEtypes_BeaconHighSnrThreshold_t
+					 *)(tlvptr);
+				tlvptr +=
+					(le16_to_cpu
+					 (pHighSnrThreshold->Header.len) +
+					 sizeof(MrvlIEtypesHeader_t));
+				i -= (le16_to_cpu(pHighSnrThreshold->Header.len)
+				      + sizeof(MrvlIEtypesHeader_t));
+				break;
+
+			case TLV_TYPE_SNR_LOW:
+				low = *(t_s8 *)(tlvptr + sizeof(t_u16) +
+						sizeof(t_u16));
+				pLowSnrThreshold =
+					(MrvlIEtypes_BeaconLowSnrThreshold_t
+					 *)(tlvptr);
+				tlvptr +=
+					(le16_to_cpu
+					 (pLowSnrThreshold->Header.len) +
+					 sizeof(MrvlIEtypesHeader_t));
+				i -= (le16_to_cpu(pLowSnrThreshold->Header.len)
+				      + sizeof(MrvlIEtypesHeader_t));
+				break;
+			}
+		}
+
+		printf("%-13s|  High = %4d  |  Low = %4d  |\n",
+		       states[state], high, low);
+	}
+	puts("");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue getra rssi/snr command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetRssiStatsThreshold(int argc, char *argv[])
+{
+	return roamGetStatsThreshold(argc, argv, RSSI_THRESHOLD);
+}
+
+/**
+ *  @brief          Coverts ms to exactTime
+ *
+ *  @param ms       number of milliseconds
+ *  @param t        converted into this structure
+ *
+ *  @return         none
+ */
+static void
+ms2exactTime(t_u32 ms, ExactTime_t *t)
+{
+	memset(t, 0, sizeof(ExactTime_t));
+
+	t->msecs = ms % 1000;
+	if (ms >= 1000) {
+		ms = (ms - t->msecs) / 1000;
+		t->secs = ms % 60;
+		if (ms >= 60) {
+			ms = (ms - t->secs) / 60;
+			t->mins = ms % 60;
+			if (ms >= 60) {
+				ms = (ms - t->mins) / 60;
+				t->hrs = ms;
+			}
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief          Issue getra neighbor assessment command
+ *
+ *  @pNborAssessment neighbour assessment struct
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+getNborAssessment(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT
+		  *pNborAssessmentParam)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *pNborAssessment;
+
+	/*
+	 * NEIGHBOR_ASSESSMENT
+	 */
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	pNborAssessment = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *)pos;
+	cmd_len = S_DS_GEN + sizeof(pNborAssessment->action);
+	pNborAssessment->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[GetNeibhorAssesinfo]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	/*
+	 * ENDIANNESS for Response
+	 */
+	pNborAssessment->QualifyingNumNeighbor =
+		le16_to_cpu(pNborAssessment->QualifyingNumNeighbor);
+	pNborAssessment->ShortBlacklistPeriod =
+		le32_to_cpu(pNborAssessment->ShortBlacklistPeriod);
+	pNborAssessment->LongBlacklistPeriod =
+		le32_to_cpu(pNborAssessment->LongBlacklistPeriod);
+	pNborAssessment->StaleCount = le16_to_cpu(pNborAssessment->StaleCount);
+	pNborAssessment->StalePeriod =
+		le32_to_cpu(pNborAssessment->StalePeriod);
+
+	memcpy((void *)pNborAssessmentParam, (void *)pNborAssessment,
+	       sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT));
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Display exactTime structure elements
+ *
+ *  @param t        ExactTime_t struct
+ *
+ *  @return         None
+ */
+static void
+printExactTime2stdout(ExactTime_t *t)
+{
+	int flag = 0;
+	if (t->hrs) {
+		printf("%dh ", t->hrs);
+		flag = 1;
+	}
+	if (t->mins) {
+		printf("%dm ", t->mins);
+		flag = 1;
+	}
+	if (t->secs) {
+		printf("%ds ", t->secs);
+		flag = 1;
+	}
+	if (t->msecs) {
+		printf("%dms", t->msecs);
+		flag = 1;
+	}
+	if (!flag) {
+		printf(" 0");
+	}
+}
+
+static int
+printNeighborAssessmentConfig(void)
+{
+	HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT nborAssessment;
+	int idx;
+	int threshDisp = FALSE;
+
+	if (getNborAssessment(&nborAssessment) != MLAN_STATUS_SUCCESS) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	printf("----------------------------------------------------------\n");
+	printf("             Neighbor Threshold Parameters\n");
+	printf("----------------------------------------------------------\n");
+	printf(" Neighbors needed for tracking mode = %d\n",
+	       nborAssessment.QualifyingNumNeighbor);
+	printf(" Config RSSI qualification offset   = %d dB\n",
+	       nborAssessment.ConfQualSignalStrength);
+	printf(" Active RSSI qualification offset   = %d dB\n",
+	       nborAssessment.ActiveQualSignalStrength);
+	printf(" Short black list period            = %d ms\n",
+	       (int)nborAssessment.ShortBlacklistPeriod);
+	printf(" Long black list period             = %d ms\n",
+	       (int)nborAssessment.LongBlacklistPeriod);
+	printf(" Stale count                        = %d\n",
+	       (int)nborAssessment.StaleCount);
+	printf(" Stale period                       = %d ms\n",
+	       (int)nborAssessment.StalePeriod);
+	printf(" Proactive Roaming Thresholds       =");
+	for (idx = 0; idx < NELEMENTS(nborAssessment.RoamThresh); idx++) {
+		if (nborAssessment.RoamThresh[idx].RssiNborDiff) {
+			if (threshDisp) {
+				printf("                                     ");
+			}
+
+			threshDisp = TRUE;
+			printf("%3d to %4d [%d]\n",
+			       nborAssessment.RoamThresh[idx].RssiHighLevel,
+			       nborAssessment.RoamThresh[idx].RssiLowLevel,
+			       nborAssessment.RoamThresh[idx].RssiNborDiff);
+		}
+	}
+
+	if (!threshDisp) {
+		puts(" < None >");
+	}
+	puts("");
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief          Issue getra neighbors command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetNborList(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int cmdresplen, i;
+	struct ifreq ifr;
+	char neighflag[6];
+	ExactTime_t t;
+	t_u16 tlv;
+	t_u8 *buffer = NULL, *pos = NULL, *tlvptr = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST *pNborList;
+	MrvlIEtypes_NeighborEntry_t *pNeighbor;
+
+	/*
+	 * NEIGHBOR_LIST
+	 */
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	pNborList = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST *)pos;
+	cmd_len = S_DS_GEN + sizeof(pNborList->action);
+	pNborList->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBORLIST);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[roamneighborlist]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	cmdresplen = le16_to_cpu(hostcmd->size);
+	cmdresplen -= cmd_len + sizeof(pNborList->Reserved);
+	tlvptr = pNborList->TlvBuffer;
+
+	printf("----------------------------------------------------"
+	       "--------------\n");
+	printf("       BSSID       | RSSI |  Age  | Qualified |"
+	       " Blacklist Duration\n");
+	printf("----------------------------------------------------"
+	       "--------------\n");
+
+	i = 0;
+
+	while (cmdresplen > 2) {
+		i++;
+		/*
+		 * ENDIANNESS for Response
+		 */
+		tlv = le16_to_cpu(*((t_u16 *)(tlvptr)));
+		switch (tlv) {
+		case TLV_TYPE_NEIGHBOR_ENTRY:
+			pNeighbor = (MrvlIEtypes_NeighborEntry_t *)(tlvptr);
+			pNeighbor->SignalStrength =
+				le16_to_cpu(pNeighbor->SignalStrength);
+			pNeighbor->Age = le16_to_cpu(pNeighbor->Age);
+			pNeighbor->QualifiedNeighborBitmap =
+				le32_to_cpu(pNeighbor->QualifiedNeighborBitmap);
+
+			pNeighbor->BlackListDuration =
+				le32_to_cpu(pNeighbor->BlackListDuration);
+			ms2exactTime(pNeighbor->BlackListDuration, &t);
+			neighflag[0] = '\0';
+
+			if ((pNeighbor->QualifiedNeighborBitmap
+			     & (BIT_NEIGHFLAG_RSSI
+				| BIT_NEIGHFLAG_AGE
+				| BIT_NEIGHFLAG_BLACKLIST
+				| BIT_NEIGHFLAG_ADMISSION_CAP
+				| BIT_NEIGHFLAG_UPLINK_RSSI))
+			    == (BIT_NEIGHFLAG_RSSI
+				| BIT_NEIGHFLAG_AGE
+				| BIT_NEIGHFLAG_BLACKLIST
+				| BIT_NEIGHFLAG_ADMISSION_CAP
+				| BIT_NEIGHFLAG_UPLINK_RSSI)) {
+				strcat(neighflag, "Yes");
+			} else {
+				strcat(neighflag, "No: ");
+				if (!
+				    (pNeighbor->
+				     QualifiedNeighborBitmap &
+				     BIT_NEIGHFLAG_RSSI)) {
+					strcat(neighflag, "R");
+				}
+				if (!
+				    (pNeighbor->
+				     QualifiedNeighborBitmap &
+				     BIT_NEIGHFLAG_AGE)) {
+					strcat(neighflag, "S");
+				}
+				if (!(pNeighbor->QualifiedNeighborBitmap
+				      & BIT_NEIGHFLAG_BLACKLIST)) {
+					strcat(neighflag, "B");
+				}
+				if (!(pNeighbor->QualifiedNeighborBitmap
+				      & BIT_NEIGHFLAG_ADMISSION_CAP)) {
+					strcat(neighflag, "A");
+				}
+				if (!(pNeighbor->QualifiedNeighborBitmap
+				      & BIT_NEIGHFLAG_UPLINK_RSSI)) {
+					strcat(neighflag, "U");
+				}
+			}
+			printf(" %02x:%02x:%02x:%02x:%02x:%02x | %3d  | %5d | %9s | ", pNeighbor->Bssid[0], pNeighbor->Bssid[1], pNeighbor->Bssid[2], pNeighbor->Bssid[3], pNeighbor->Bssid[4], pNeighbor->Bssid[5], pNeighbor->SignalStrength, pNeighbor->Age, neighflag);
+
+			if (pNeighbor->BlackListDuration) {
+				printExactTime2stdout(&t);
+			} else {
+				printf("Not Blacklisted");
+			}
+			printf("\n");
+
+			tlvptr += (le16_to_cpu(pNeighbor->Header.len) +
+				   sizeof(MrvlIEtypesHeader_t));
+			cmdresplen -= (le16_to_cpu(pNeighbor->Header.len) +
+				       sizeof(MrvlIEtypesHeader_t));
+			break;
+
+		default:
+			printf("\nIncorrect response.\n\n");
+			break;
+		}
+	}
+
+	if (i == 0) {
+		printf("< Empty >\n");
+	}
+
+	printf("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue getra neighbor params command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetNborParams(int argc, char *argv[])
+{
+	printNeighborAssessmentConfig();
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief          Issue getra metrics command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetMetrics(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int i;
+	t_u16 Metrics = 0;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *metricscmd;
+
+	const char *metricslist[] = { "beacon", "data", "per", "fer" };
+
+	if (argc != 0) {
+		puts("\nIncorrect number of arguments.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	metricscmd = (HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *)pos;
+	cmd_len = S_DS_GEN + sizeof(metricscmd->action);
+	metricscmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[roam set matrics]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	Metrics = le16_to_cpu(metricscmd->Metrics);
+
+	if (le16_to_cpu(hostcmd->result) == MLAN_STATUS_SUCCESS) {
+		printf("\n Metrics Activated: ");
+		for (i = 0; (unsigned int)i < NELEMENTS(metricslist); i++) {
+			if (Metrics & BIT(i)) {
+				printf(" %s ", metricslist[i]);
+			}
+		}
+		printf("\n");
+
+		if (Metrics & BIT(3)) {
+			printf("FER Threshold : %u %% \n",
+			       metricscmd->UcFerThresholdValue);
+			printf("FER Packet Threshold: %d \n",
+			       le32_to_cpu(metricscmd->UiFerPktThreshold));
+			printf("FER period. Stable : %d ms, Degrading : %d ms, "
+			       "Unacceptable : %d ms\n",
+			       le32_to_cpu(metricscmd->StableFERPeriod_ms),
+			       le32_to_cpu(metricscmd->DegradingFERPeriod_ms),
+			       le32_to_cpu(metricscmd->
+					   UnacceptableFERPeriod_ms));
+		}
+
+		if (Metrics & BIT(2)) {
+			printf("PER Threshold : %u %% \n",
+			       metricscmd->UcPerThresholdValue);
+			printf("PER Packet Threshold: %d \n",
+			       le32_to_cpu(metricscmd->UiPerPktThreshold));
+			printf("PER period. Stable : %d ms, Degrading : %d ms, "
+			       "Unacceptable : %d ms\n",
+			       le32_to_cpu(metricscmd->StablePERPeriod_ms),
+			       le32_to_cpu(metricscmd->DegradingPERPeriod_ms),
+			       le32_to_cpu(metricscmd->
+					   UnacceptablePERPeriod_ms));
+		}
+
+		if (Metrics & BIT(1)) {
+			printf("Data Packet Threshold: %d \n",
+			       le32_to_cpu(metricscmd->UiRxPktThreshold));
+		}
+
+		if ((Metrics & BIT(1)) || (Metrics & BIT(2)) ||
+		    (Metrics & BIT(3))) {
+
+			printf("Inactivity Period: %d ms \n",
+			       le32_to_cpu(metricscmd->
+					   InactivityPeriodThreshold_ms));
+		}
+	} else {
+		printf("command response failure %d.\n",
+		       le16_to_cpu(hostcmd->result));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue getra scanperiod command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetScanPeriod(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int state = 0, scanmode = 0, cmdresplen;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL, *tlvptr = NULL;
+	t_u16 tlv;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP *scanPeriodInfo;
+	MrvlIEtypes_NeighborScanPeriod_t *pscanperiod;
+	const char *states[] = { "Stable", "Degrading", "Unacceptable" };
+	const char *scanmodes[] = { "Discovery", "Tracking" };
+	/* scanperiodValues[state][scanmode] */
+	t_u32 values[3][2];
+
+	/*
+	 * NEIGHBOR_SCANPERIOD
+	 */
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	scanPeriodInfo =
+		(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP *)pos;
+	cmd_len = S_DS_GEN + sizeof(scanPeriodInfo->action);
+	scanPeriodInfo->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_SCAN_PERIOD);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[roamscanperiod]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	cmdresplen = le16_to_cpu(hostcmd->size);
+	cmdresplen -= cmd_len + sizeof(scanPeriodInfo->Reserved);
+	tlvptr = scanPeriodInfo->TlvBuffer;
+	while (cmdresplen > 2) {
+		/*
+		 * ENDIANNESS for Response
+		 */
+		tlv = le16_to_cpu(*((t_u16 *)(tlvptr)));
+		switch (tlv) {
+		case TLV_TYPE_NEIGHBOR_SCANPERIOD:
+			pscanperiod =
+				(MrvlIEtypes_NeighborScanPeriod_t *)(tlvptr);
+			pscanperiod->SearchMode =
+				le16_to_cpu(pscanperiod->SearchMode);
+			pscanperiod->State = le16_to_cpu(pscanperiod->State);
+			pscanperiod->ScanPeriod =
+				le32_to_cpu(pscanperiod->ScanPeriod);
+			state = pscanperiod->State;
+			scanmode = pscanperiod->SearchMode;
+			if ((state < STATE_STABLE) ||
+			    (state > STATE_UNACCEPTABLE)) {
+				puts("\nIncorrect state in response.\n");
+			}
+			if ((scanmode < DISCOVERY_MODE) ||
+			    (scanmode > TRACKING_MODE)) {
+				puts("\nIncorrect scanmode in response.\n");
+			}
+			values[state - 1][scanmode - 1] =
+				pscanperiod->ScanPeriod;
+			tlvptr +=
+				(le16_to_cpu(pscanperiod->Header.len) +
+				 sizeof(MrvlIEtypesHeader_t));
+			cmdresplen -=
+				(le16_to_cpu(pscanperiod->Header.len) +
+				 sizeof(MrvlIEtypesHeader_t));
+			break;
+
+		default:
+			puts("\nIncorrect response.\n");
+			break;
+		}
+	}
+
+	for (state = STATE_STABLE - 1; state < STATE_UNACCEPTABLE; state++) {
+		printf("\nState: %-14s  ", states[state]);
+		for (scanmode = DISCOVERY_MODE - 1;
+		     scanmode < TRACKING_MODE; scanmode++) {
+			printf("%s = %6d ms\t",
+			       scanmodes[scanmode],
+			       (int)values[state][scanmode]);
+		}
+	}
+	printf("\n");
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue getra command
+ *
+ *  @param pcontrol control struct to return
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+getControl(HostCmd_DS_CMD_ROAMAGENT_CONTROL *pcontrol)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_CONTROL *roamcontrolcmd = NULL;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+	cmd_len = S_DS_GEN + sizeof(roamcontrolcmd->action);
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_CONTROL);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	roamcontrolcmd = (HostCmd_DS_CMD_ROAMAGENT_CONTROL *)pos;
+
+	roamcontrolcmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[roamcontrol]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy((void *)pcontrol,
+	       (void *)roamcontrolcmd,
+	       sizeof(HostCmd_DS_CMD_ROAMAGENT_CONTROL));
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue getra command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param control  roma control indicator value
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetEventBitmap(int argc, char *argv[])
+{
+	t_u8 hostevent;
+	HostCmd_DS_CMD_ROAMAGENT_CONTROL roamcontrolcmd;
+
+	if (getControl(&roamcontrolcmd) != MLAN_STATUS_SUCCESS) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	hostevent = roamcontrolcmd.HostEvent;
+	if (!(hostevent | 0)) {
+		puts("\nHost events are disabled.\n");
+		return MLAN_STATUS_SUCCESS;
+	}
+	printf("\nHost events enabled: ");
+	if (hostevent & HOST_EVENT_NBOR_ENABLE)
+		printf("neighbor ");
+
+	if (hostevent & HOST_EVENT_ROAM_ENABLE)
+		printf("roam ");
+
+	if (hostevent & HOST_EVENT_STATE_ENABLE)
+		printf("state");
+
+	printf("\n");
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief          Issue getra command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param control  roma control indicator value
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetControl(int argc, char *argv[])
+{
+	t_u8 control;
+	HostCmd_DS_CMD_ROAMAGENT_CONTROL roamcontrolcmd;
+
+	if (getControl(&roamcontrolcmd) != MLAN_STATUS_SUCCESS) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	control = roamcontrolcmd.Control;
+	printf("\nGlobal roaming agent state: ");
+	if (control & ROAM_CONTROL_ENABLE) {
+		printf("enabled, ");
+		if (control & ROAM_CONTROL_SUSPEND)
+			printf("suspend.\n");
+		else
+			printf("resume.\n");
+	} else
+		printf("disabled.\n");
+
+	printf("Crossband: ");
+	if (control & CROSSBAND_ENABLE)
+		printf("enabled.\n");
+	else
+		printf("disabled.\n");
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief                    Internal funtion to issue getra backoff
+ *
+ *  @param roambackoffcmd     Backoff command structure
+ *  @return                   MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+getBackOff(HostCmd_DS_CMD_ROAMAGENT_BACKOFF *roambackoffcmdParam)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_BACKOFF *roambackoffcmd;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	roambackoffcmd = (HostCmd_DS_CMD_ROAMAGENT_BACKOFF *)pos;
+	cmd_len = S_DS_GEN + sizeof(roambackoffcmd->action);
+	roambackoffcmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_BACKOFF);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[roambackoff]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/*
+	 * ENDIANNESS for Response
+	 */
+	roambackoffcmd->Scans = le16_to_cpu(roambackoffcmd->Scans);
+	roambackoffcmd->Period = le32_to_cpu(roambackoffcmd->Period);
+
+	memcpy((void *)roambackoffcmdParam, (void *)roambackoffcmd,
+	       sizeof(HostCmd_DS_CMD_ROAMAGENT_BACKOFF));
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue getra backoff command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param control  roma control indicator value
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamGetBackOff(int argc, char *argv[])
+{
+	HostCmd_DS_CMD_ROAMAGENT_BACKOFF backoffcmd;
+
+	if (getBackOff(&backoffcmd) != MLAN_STATUS_SUCCESS) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	puts("");
+	printf("----------------------------------------------------\n");
+	printf("           Scanning Backoff Parameters              \n");
+	printf("----------------------------------------------------\n");
+	printf(" Backoff period (max time in tracking) = %d ms\n",
+	       backoffcmd.Period);
+	printf(" # of discovery scans before backoff   = %d\n",
+	       backoffcmd.Scans);
+	puts("");
+
+	if (backoffcmd.Scans) {
+		printf(" - Discovery backoff mode is enabled.\n"
+		       "   After %d discovery scans without a change in the number\n"
+		       "   of neighbors, the RA will only track the existing\n"
+		       "   neighbors until the backoff period expires.\n",
+		       backoffcmd.Scans);
+	} else {
+		printf(" - Discovery backoff mode is disabled.\n"
+		       "   The RA will only move to tracking mode if a minimum\n"
+		       "   number of good neighbors have been found. See the\n"
+		       "   getra neighbor command for the current min setting.\n");
+	}
+	puts("");
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+static int
+printGetNeighborDeprecation(int argc, char *argv[])
+{
+	printf("\nInfo: getra neighbor replaced with:\n"
+	       "      - getra nlist   (display neighbor list)\n"
+	       "      - getra nparams (display neighbor assessment params)\n\n");
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get the Roaming agent configuration parameters from FW.
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_get_ra_config(int argc, char *argv[])
+{
+	if (argc == 3) {
+		return roamGetControl(argc, argv);
+	}
+
+	sub_cmd_exec_t subCmds[] = {
+		{"rssi", 1, 1, roamGetRssiStatsThreshold},
+		{"prebcnmiss", 1, 1, roamGetPreBeaconMiss},
+		{"failcnt", 1, 1, roamGetFailureCount},
+		{"backoff", 1, 1, roamGetBackOff},
+		{"neighbor", 2, 0, printGetNeighborDeprecation},
+		{"nlist", 2, 1, roamGetNborList},
+		{"nparams", 2, 1, roamGetNborParams},
+		{"scanperiod", 1, 1, roamGetScanPeriod},
+		{"metrics", 1, 1, roamGetMetrics},
+		{"event", 1, 1, roamGetEventBitmap}
+	};
+
+	return process_sub_cmd(subCmds, NELEMENTS(subCmds), argc, argv);
+}
+
+/**
+ *  @brief          Issue setra bcnmiss command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetPreBeaconLoss(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int bcnmiss;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
+	MrvlIEtypes_BeaconsMissed_t *beaconmiss;
+
+	if (argc != 1) {
+		puts("\nIncorrect number of arguments.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bcnmiss = atoi(argv[0]);
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
+	cmd_len = sizeof(HostCmd_DS_GEN) + sizeof(statsthreshold->action) +
+		sizeof(statsthreshold->State) +
+		sizeof(statsthreshold->Profile) +
+		sizeof(MrvlIEtypes_BeaconsMissed_t);
+
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
+	statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+	statsthreshold->State = STATE_HARDROAM;
+
+	beaconmiss = (MrvlIEtypes_BeaconsMissed_t *)&statsthreshold->TlvBuffer;
+	beaconmiss->beacon_missed = bcnmiss;
+	beaconmiss->header.type = cpu_to_le16(TLV_TYPE_PRE_BEACON_LOST);
+	beaconmiss->header.len =
+		cpu_to_le16(sizeof(MrvlIEtypes_BeaconsMissed_t) -
+			    sizeof(MrvlIEtypesHeader_t));
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[setra]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (le16_to_cpu(hostcmd->result)) {
+		printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		roamGetPreBeaconMiss(argc, argv);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue setra failurecnt command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetFailureCount(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int failCount, failTimeThresh;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
+	MrvlIEtypes_FailureCount_t *failcnt;
+
+	if (argc != 2) {
+		puts("\n2 arguments required: FailCnt, FailTimeThresh(ms)\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	failCount = atoi(argv[0]);
+	failTimeThresh = atoi(argv[1]);
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
+
+	cmd_len = (S_DS_GEN +
+		   sizeof(statsthreshold->action) +
+		   sizeof(statsthreshold->State) +
+		   sizeof(statsthreshold->Profile) +
+		   sizeof(MrvlIEtypes_FailureCount_t));
+
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+	statsthreshold->State = STATE_HARDROAM;
+
+	failcnt = (MrvlIEtypes_FailureCount_t *)&statsthreshold->TlvBuffer;
+	failcnt->fail_value = failCount;
+	failcnt->fail_min_thresh_time_millisecs = cpu_to_le16(failTimeThresh);
+	failcnt->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT);
+	failcnt->header.len = cpu_to_le16(sizeof(MrvlIEtypes_FailureCount_t)
+					  - sizeof(MrvlIEtypesHeader_t));
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[setra]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (le16_to_cpu(hostcmd->result)) {
+		printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		roamGetFailureCount(argc, argv);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue setra rssi/snr command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param type     RSSI/SNR threshold type
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetStatsThreshold(int argc, char *argv[], int type)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int i, state = 0, low = 0, high = 0, lowval, highval;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
+	MrvlIEtypes_BeaconHighRssiThreshold_t *bcnhighrssi;
+	MrvlIEtypes_BeaconLowRssiThreshold_t *bcnlowrssi;
+	MrvlIEtypes_BeaconHighSnrThreshold_t *bcnhighsnr;
+	MrvlIEtypes_BeaconLowSnrThreshold_t *bcnlowsnr;
+
+	if (argv[0] == NULL) {
+		puts("\nInsufficient arguments.. \n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argv[0] && strncmp(argv[0], "stable", strlen("stable")) == 0) {
+		state = STATE_STABLE;
+		/* degrad[ing] */
+	} else if (argv[0] && strncmp(argv[0], "degrad", strlen("degrad")) == 0) {
+		state = STATE_DEGRADING;
+		/* unaccep[table] */
+	} else if (argv[0]
+		   && strncmp(argv[0], "unaccep", strlen("unaccep")) == 0) {
+		state = STATE_UNACCEPTABLE;
+	} else {
+		puts("\nUnknown state. Use stable/degrading/unacceptable\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (argc != 3 && argc != 5) {
+		puts("\nIncorrect number of arguments.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (argv[1] && strncmp(argv[1], "low", strlen("low")) == 0) {
+		low = 1;
+		lowval = atoi(argv[2]);
+		/* TODO validation check on lowval */
+	}
+	if (argv[1 + (2 * low)]
+	    && strncmp(argv[1 + (2 * low)], "high", strlen("high")) == 0) {
+		high = 1;
+		highval = atoi(argv[2 + (2 * low)]);
+		/* TODO validation check on highval */
+	}
+	/* check if low is specified after high */
+	if ((low == 0) && (argc == 5)) {
+		if (argv[1 + (2 * high)]
+		    && strncmp(argv[1 + (2 * high)], "low", strlen("low")) == 0) {
+			low = 1;
+			lowval = atoi(argv[2 + 2 * (high)]);
+			/* TODO validation check on lowval */
+		}
+	}
+
+	if (!low && !high) {
+		puts("\nIncorrect argument. Use low <low val>/high <high val>\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
+	cmd_len =
+		(S_DS_GEN +
+		 sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD)
+		 - sizeof(statsthreshold->TlvBuffer));
+	if (type == RSSI_THRESHOLD) {
+		if (high) {
+			cmd_len +=
+				sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t);
+		}
+		if (low) {
+			cmd_len += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+		}
+	} else {
+		if (high) {
+			cmd_len += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t);
+		}
+		if (low) {
+			cmd_len += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t);
+		}
+	}
+
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+	statsthreshold->State = state;
+
+	/*
+	 * TLV buffer start pointer initialization
+	 */
+	i = 0;
+	if (type == RSSI_THRESHOLD) {
+		if (high) {
+			bcnhighrssi = (MrvlIEtypes_BeaconHighRssiThreshold_t *)
+				(((t_u8 *)&statsthreshold->TlvBuffer) + i);
+			bcnhighrssi->Header.type = TLV_TYPE_RSSI_HIGH;
+			bcnhighrssi->Header.len =
+				(sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t)
+				 - sizeof(MrvlIEtypesHeader_t));
+			bcnhighrssi->Value = highval;
+			i += sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t);
+			/*
+			 * ENDIANNESS
+			 */
+			bcnhighrssi->Header.type =
+				cpu_to_le16(bcnhighrssi->Header.type);
+			bcnhighrssi->Header.len =
+				cpu_to_le16(bcnhighrssi->Header.len);
+		}
+
+		if (low) {
+			bcnlowrssi = (MrvlIEtypes_BeaconLowRssiThreshold_t *)
+				(((t_u8 *)&statsthreshold->TlvBuffer) + i);
+			bcnlowrssi->Header.type = TLV_TYPE_RSSI_LOW;
+			bcnlowrssi->Header.len =
+				(sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t)
+				 - sizeof(MrvlIEtypesHeader_t));
+			bcnlowrssi->Value = lowval;
+			i += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+			/*
+			 * ENDIANNESS
+			 */
+			bcnlowrssi->Header.type =
+				cpu_to_le16(bcnlowrssi->Header.type);
+			bcnlowrssi->Header.len =
+				cpu_to_le16(bcnlowrssi->Header.len);
+		}
+	} else {
+		if (high) {
+			bcnhighsnr = (MrvlIEtypes_BeaconHighSnrThreshold_t *)
+				(((t_u8 *)&statsthreshold->TlvBuffer) + i);
+			bcnhighsnr->Header.type = TLV_TYPE_SNR_HIGH;
+			bcnhighsnr->Header.len =
+				(sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t)
+				 - sizeof(MrvlIEtypesHeader_t));
+			bcnhighsnr->Value = highval;
+			i += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t);
+			/*
+			 * ENDIANNESS
+			 */
+			bcnhighsnr->Header.type =
+				cpu_to_le16(bcnhighsnr->Header.type);
+			bcnhighsnr->Header.len =
+				cpu_to_le16(bcnhighsnr->Header.len);
+		}
+		if (low) {
+			bcnlowsnr = (MrvlIEtypes_BeaconLowSnrThreshold_t *)
+				(((t_u8 *)&statsthreshold->TlvBuffer) + i);
+			bcnlowsnr->Header.type = TLV_TYPE_SNR_LOW;
+			bcnlowsnr->Header.len =
+				(sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t)
+				 - sizeof(MrvlIEtypesHeader_t));
+			bcnlowsnr->Value = lowval;
+			i += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t);
+			/*
+			 * ENDIANNESS
+			 */
+			bcnlowsnr->Header.type =
+				cpu_to_le16(bcnlowsnr->Header.type);
+			bcnlowsnr->Header.len =
+				cpu_to_le16(bcnlowsnr->Header.len);
+		}
+	}
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[setra]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (le16_to_cpu(hostcmd->result)) {
+		printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue setra rssi command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetRssiStatsThreshold(int argc, char *argv[])
+{
+	if (roamSetStatsThreshold(argc, argv, RSSI_THRESHOLD)
+	    == MLAN_STATUS_SUCCESS) {
+		roamGetStatsThreshold(0, argv, RSSI_THRESHOLD);
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief          Issue setra scanperiod command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetScanPeriod(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int scanmode = 0, period = 0, state = 0;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD *scanPeriodInfo;
+
+	if (argv[0] == NULL) {
+		puts("\nInsufficient arguments.. \n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* scanperiod */
+	if (argc != 3) {
+		puts("\nIncorrect number of arguments.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argv[0] && strncmp(argv[0], "stable", strlen("stable")) == 0) {
+		state = STATE_STABLE;
+		/* degrad[ing] */
+	} else if (argv[0] && strncmp(argv[0], "degrad", strlen("degrad")) == 0) {
+		state = STATE_DEGRADING;
+		/* unaccep[table] */
+	} else if (argv[0]
+		   && strncmp(argv[0], "unaccep", strlen("unaccep")) == 0) {
+		state = STATE_UNACCEPTABLE;
+	} else {
+		puts("\nUnknown state. Use stable/degrading/unacceptable\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argv[1] && strncmp(argv[1], "disc", strlen("disc")) == 0) {
+		scanmode = DISCOVERY_MODE;
+		/* track[ing] */
+	} else if (argv[1] && strncmp(argv[1], "track", strlen("track")) == 0) {
+		scanmode = TRACKING_MODE;
+	} else {
+		puts("\nUnknown scamode. Use discovery/ tracking\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	period = atoi(argv[2]);
+	/* TODO validation check on period */
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	scanPeriodInfo = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD *)pos;
+	cmd_len =
+		S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD);
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_SCAN_PERIOD);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	scanPeriodInfo->action = HostCmd_ACT_GEN_SET;
+	scanPeriodInfo->scanPeriod.Header.type = TLV_TYPE_NEIGHBOR_SCANPERIOD;
+	scanPeriodInfo->scanPeriod.Header.len =
+		sizeof(MrvlIEtypes_NeighborScanPeriod_t) -
+		sizeof(MrvlIEtypesHeader_t);
+	scanPeriodInfo->scanPeriod.SearchMode = scanmode;
+	scanPeriodInfo->scanPeriod.State = state;
+	scanPeriodInfo->scanPeriod.ScanPeriod = period;
+
+	/*
+	 * ENDIANNESS
+	 */
+	scanPeriodInfo->action = cpu_to_le16(scanPeriodInfo->action);
+	scanPeriodInfo->scanPeriod.Header.type = cpu_to_le16
+		(scanPeriodInfo->scanPeriod.Header.type);
+	scanPeriodInfo->scanPeriod.Header.len = cpu_to_le16
+		(scanPeriodInfo->scanPeriod.Header.len);
+	scanPeriodInfo->scanPeriod.SearchMode = cpu_to_le16
+		(scanPeriodInfo->scanPeriod.SearchMode);
+	scanPeriodInfo->scanPeriod.State = cpu_to_le16
+		(scanPeriodInfo->scanPeriod.State);
+	scanPeriodInfo->scanPeriod.ScanPeriod = cpu_to_le32
+		(scanPeriodInfo->scanPeriod.ScanPeriod);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[neighborlist maintain]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (le16_to_cpu(hostcmd->result)) {
+		printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Check it string contains digits
+ *  @param str      string to check for digits
+ *  @return         same as isdigit(char)
+ */
+static inline int
+isdigitstr(char *str)
+{
+	unsigned int i = 0;
+	for (i = 0; i < strlen(str); i++) {
+		if (!isdigit((str)[i]))
+			return 0;
+	}
+	return 1;
+}
+
+/**
+ *  @brief          Process sub command
+ *
+ *  @param valid_cmds   valid commands array
+ *  @param count        number of  valid commands
+ *  @param argc         number of arguments
+ *  @param argv         A pointer to arguments array
+ *  @param param        argc parameter counter
+ *  @param value        values to update back
+ *
+ *  @return             command index--success, otherwise--fail
+ */
+static int
+process_subcmd(char *valid_cmds[], int count, int argc, char *argv[],
+	       int *param, int *value)
+{
+	int ret = 0;
+	int j = *param;
+	int k;
+	while (1) {
+		for (k = 0; k < count; k++)
+			if (argv[j] &&
+			    !strncmp(valid_cmds[k], argv[j],
+				     strlen(valid_cmds[k])))
+				break;
+		if (k >= count) {
+			break;
+		} else {
+			/* special case */
+			if (!strncmp
+			    (valid_cmds[k], "perperiod", strlen("perperiod")) ||
+			    !strncmp(valid_cmds[k], "ferperiod",
+				     strlen("ferperiod"))) {
+				*param = j;
+				return ret | 1 << k;
+			}
+			if (!argv[j + 1] || !isdigitstr(argv[j + 1]))
+				return -1;
+			value[k] = atoi(argv[j + 1]);
+			j = j + 2;
+			ret |= (1 << k);
+		}
+
+		if (j >= argc) {
+			break;
+		}
+	}
+
+	if (*param == j) {
+		return -1;
+	}
+
+	*param = j;
+	return ret;
+}
+
+static int
+printSetNeighborDeprecation(int argc, char *argv[])
+{
+	printf("\nInfo: setra neighbor replaced with:\n"
+	       "      - setra nparams (config neighbor assessment params)\n\n");
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief          Issue setra neighbor command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetNborParams(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int trackcount = 0, i = 0, j = 0;
+	int blist[2] = { 0, 0 };	/* blacklist short and long:  0-short 1-long */
+	int qualoffset[1] = { 0 };	/* rssi */
+	int stalecount = ~0;
+	int staleperiod = ~0;
+	signed char temp;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	char *valid_cmds[] = { "trackcount", "qualoffset", "blacklistdur",
+		"stalecount", "staleperiod", "roamthresh"
+	};
+
+    /** blacklistdur sub commands */
+	char *valid_blcmds[] = { "short", "long" };
+
+    /** qualoffset sub commands */
+	char *valid_bfcmds[] = { "rssi" };
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *pNborAssessment;
+
+	if (argv[0] == NULL) {
+		puts("\nUnknown setra nparams subcmd. Valid subcmds:");
+		for (i = 0; i < NELEMENTS(valid_cmds); i++) {
+			printf("  - %s\n", valid_cmds[i]);
+		}
+		printf("\n");
+
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc < 2 || argc > 18) {
+		puts("\nIncorrect number of arguments.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	pNborAssessment = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *)pos;
+	cmd_len =
+		S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT);
+
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Get parameters unspecified on command line */
+	if (getNborAssessment(pNborAssessment) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	while (argc - j) {
+		for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds); i++) {
+			if (!strncmp
+			    (valid_cmds[i], argv[j], strlen(valid_cmds[i])))
+				break;
+		}
+
+		if ((unsigned int)i >= NELEMENTS(valid_cmds)) {
+			printf("\nInvalid argument to \"%s\"\n\n", argv[0]);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		switch (i) {
+
+		case 0:
+		/** trackcount */
+			trackcount = atoi(argv[j + 1]);
+			pNborAssessment->QualifyingNumNeighbor = trackcount;
+			j = j + 2;
+			break;
+
+		case 1:
+		/** qualoffset */
+			j++;
+			ret = process_subcmd(valid_bfcmds,
+					     NELEMENTS(valid_bfcmds), argc,
+					     argv, &j, qualoffset);
+			if (ret == -1) {
+				printf("\nInvalid argument to \"%s\"\n\n",
+				       argv[j - 1]);
+				ret = ret;
+				goto done;
+			}
+			pNborAssessment->ConfQualSignalStrength = qualoffset[0];
+			break;
+
+		case 2:
+		/** blacklistdur */
+			j++;
+			ret = process_subcmd(valid_blcmds,
+					     NELEMENTS(valid_blcmds), argc,
+					     argv, &j, blist);
+			if (ret == -1) {
+				printf("\nInvalid argument to \"%s\"\n\n",
+				       argv[j - 1]);
+				ret = ret;
+				goto done;
+			} else {
+				if (ret & 0x01) {
+					pNborAssessment->ShortBlacklistPeriod =
+						blist[0];
+				}
+				if (ret & 0x02) {
+					pNborAssessment->LongBlacklistPeriod =
+						blist[1];
+				}
+			}
+			break;
+
+		case 3:
+		/** stalecount */
+			stalecount = atoi(argv[j + 1]);
+			pNborAssessment->StaleCount = stalecount;
+			j = j + 2;
+			break;
+
+		case 4:
+		/** staleperiod */
+			staleperiod = atoi(argv[j + 1]);
+			pNborAssessment->StalePeriod = staleperiod;
+			j = j + 2;
+			break;
+
+		case 5:
+		/** roamthresh */
+			j++;
+			temp = 0;
+			for (i = 0; j + i < argc; i++) {
+				if (isdigit(*argv[j + i]) ||
+				    (*argv[j + i] == '-')) {
+					temp++;
+				} else {
+					break;
+				}
+			}
+
+			if ((temp % 3 != 0) || (temp > 12)) {
+				puts("");
+				printf("Error: %d numeric arguments detected for roamthresh.\n" "       Roam threhold values must be specified in\n" "       multiples of 3 (low, high, diff triplets) up\n" "       to a maximum of 4 sets (12 numbers max).\n", temp);
+				puts("");
+
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+
+			for (i = 0; (i < 12); i++) {
+				if ((j >= argc) ||
+				    (!isdigit(*argv[j]) && *argv[j] != '-')) {
+					temp = 0;
+				} else {
+					temp = atoi(argv[j]);
+					j++;
+				}
+
+				switch (i % 3) {
+				case 0:
+					pNborAssessment->RoamThresh[i /
+								    3].
+						RssiHighLevel = temp;
+					break;
+
+				case 1:
+					pNborAssessment->RoamThresh[i /
+								    3].
+						RssiLowLevel = temp;
+					break;
+
+				case 2:
+					pNborAssessment->RoamThresh[i /
+								    3].
+						RssiNborDiff = temp;
+					break;
+				}
+			}
+			break;
+		}
+	}
+
+	pNborAssessment->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+
+	/* Both stalecount, staleperiod can not be zero */
+	if ((pNborAssessment->StaleCount == 0) &&
+	    (pNborAssessment->StalePeriod == 0)) {
+
+		puts("\nstalecount and staleperiod both can not be zero\n");
+		ret = (MLAN_STATUS_FAILURE);
+		goto done;
+	}
+
+	/*
+	 * ENDIANNESS
+	 */
+	pNborAssessment->QualifyingNumNeighbor =
+		cpu_to_le16(pNborAssessment->QualifyingNumNeighbor);
+	pNborAssessment->ShortBlacklistPeriod =
+		cpu_to_le32(pNborAssessment->ShortBlacklistPeriod);
+	pNborAssessment->LongBlacklistPeriod =
+		cpu_to_le32(pNborAssessment->LongBlacklistPeriod);
+	pNborAssessment->StaleCount = cpu_to_le16(pNborAssessment->StaleCount);
+	pNborAssessment->StalePeriod =
+		cpu_to_le16(pNborAssessment->StalePeriod);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[roam neighbor assessment]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (le16_to_cpu(hostcmd->result)) {
+		printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printNeighborAssessmentConfig();
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue setra metrics command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetMetrics(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *metricscmd;
+
+	int perlist[3] = { 0, 0, 0 };	/* 0=inactivity,
+					   1=perthreshold,
+					   2=packetthreshold */
+	int ferlist[3] = { 0, 0, 0 };	/* 0=inactivity,
+					   1=ferthreshold,
+					   2=framethreshold */
+	int perstate[3] = { 0, 0, 0 };	/* 0=stable, 1=degrading, 2=unacceptable */
+	int ferstate[3] = { 0, 0, 0 };	/* 0=stable, 1=degrading, 2=unacceptable */
+	int datalist[2] = { 0, 0 };	/* 0=inactivity, 1=datathreshold */
+	char *valid_cmds[] = { "Beacon", "Data", "PER", "FER" };
+
+    /** PER sub commands */
+	char *valid_percmds[] = { "inactivity", "perthreshold",
+		"packetthreshold", "perperiod"
+	};
+
+	char *valid_fercmds[] = { "inactivity", "ferthreshold",
+		"framethreshold", "ferperiod"
+	};
+
+    /** PER period states */
+	char *per_states[] = { "stable", "degrading", "unacceptable" };
+
+    /** Data sub commands */
+	char *valid_datacmds[] = { "inactivity", "datathreshold" };
+
+	int i = 0, j = 0;
+
+	if (argv[0] == NULL) {
+		puts("\nInsufficient arguments.. \n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc < 1 || argc > 38) {
+		puts("\nIncorrect number of arguments.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len =
+		S_DS_GEN +
+		sizeof(HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD);
+
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	metricscmd = (HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *)pos;
+	metricscmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+
+	/* clear [ Beacon/Data/PER ] */
+	if (!strncmp("clear", argv[j], strlen("clear"))) {
+		if (argc == 1) {
+			puts("\nInvalid number of argument");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		while (1) {
+			j++;
+			for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds);
+			     i++) {
+				if (!strncmp
+				    (valid_cmds[i], argv[j],
+				     strlen(valid_cmds[i])))
+					break;
+			}
+			if ((unsigned int)i >= NELEMENTS(valid_cmds)) {
+				printf("\nInvalid argument \"%s\"\n\n",
+				       argv[j]);
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			} else {
+				metricscmd->Metrics |= BIT(i);
+			}
+
+			if (j >= (argc - 1)) {
+				break;
+			}
+		}
+		metricscmd->action = HostCmd_ACT_GEN_REMOVE;
+	} else {		/* set [ Beacon/Data/PER ] */
+
+		while (argc - j) {
+			for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds);
+			     i++) {
+				if (!strncmp
+				    (valid_cmds[i], argv[j],
+				     strlen(valid_cmds[i])))
+					break;
+			}
+			if ((unsigned int)i >= NELEMENTS(valid_cmds)) {
+				printf("\nInvalid argument to \"%s\"\n\n",
+				       argv[j]);
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+
+			switch (i) {
+			case 0:
+		    /** Beacon */
+				j++;
+				metricscmd->Metrics |= 0x01;
+				break;
+
+			case 1:
+		    /** Data*/
+				j++;
+				ret = process_subcmd(valid_datacmds,
+						     NELEMENTS(valid_datacmds),
+						     argc, argv, &j, datalist);
+				if (ret > 0) {
+					if (ret & 0x01) {
+						metricscmd->
+							InactivityPeriodThreshold_ms
+							= datalist[0];
+					}
+					if (ret & 0x02) {
+						metricscmd->UiRxPktThreshold =
+							datalist[1];
+					}
+				}
+				metricscmd->Metrics |= 0x02;
+				break;
+
+			case 2:
+		    /** PER */
+				j++;
+				ret = process_subcmd(valid_percmds,
+						     NELEMENTS(valid_percmds),
+						     argc, argv, &j, perlist);
+				if (ret > 0) {
+					if (ret & 0x01) {
+						metricscmd->
+							InactivityPeriodThreshold_ms
+							= perlist[0];
+					}
+					if (ret & 0x02) {
+						metricscmd->
+							UcPerThresholdValue =
+							perlist[1];
+					}
+					if (ret & 0x04) {
+						metricscmd->UiPerPktThreshold =
+							perlist[2];
+					}
+					if (ret & 0x08) {
+						j++;
+						ret = process_subcmd(per_states,
+								     NELEMENTS
+								     (per_states),
+								     argc, argv,
+								     &j,
+								     perstate);
+						if (ret & 0x01) {
+							metricscmd->
+								StablePERPeriod_ms
+								= perstate[0];
+						}
+						if (ret & 0x02) {
+							metricscmd->
+								DegradingPERPeriod_ms
+								= perstate[1];
+						}
+						if (ret & 0x04) {
+							metricscmd->
+								UnacceptablePERPeriod_ms
+								= perstate[2];
+						}
+						if (j < argc) {
+							ret = process_subcmd
+								(valid_percmds,
+								 NELEMENTS
+								 (valid_percmds),
+								 argc, argv, &j,
+								 perlist);
+							if (ret > 0) {
+								if (ret & 0x01) {
+									metricscmd->
+										InactivityPeriodThreshold_ms
+										=
+										perlist
+										[0];
+								}
+								if (ret & 0x02) {
+									metricscmd->
+										UcPerThresholdValue
+										=
+										perlist
+										[1];
+								}
+								if (ret & 0x04) {
+									metricscmd->
+										UiPerPktThreshold
+										=
+										perlist
+										[2];
+								}
+							}
+						}
+					}
+				}
+				metricscmd->Metrics |= 0x04;
+				break;
+
+			case 3:
+		    /** FER */
+				j++;
+				ret = process_subcmd(valid_fercmds,
+						     NELEMENTS(valid_fercmds),
+						     argc, argv, &j, ferlist);
+				if (ret > 0) {
+					if (ret & 0x01) {
+						metricscmd->
+							InactivityPeriodThreshold_ms
+							= ferlist[0];
+					}
+					if (ret & 0x02) {
+						metricscmd->
+							UcFerThresholdValue =
+							ferlist[1];
+					}
+					if (ret & 0x04) {
+						metricscmd->UiFerPktThreshold =
+							ferlist[2];
+					}
+					if (ret & 0x08) {
+						j++;
+						ret = process_subcmd(per_states,
+								     NELEMENTS
+								     (per_states),
+								     argc, argv,
+								     &j,
+								     ferstate);
+						if (ret & 0x01) {
+							metricscmd->
+								StableFERPeriod_ms
+								= ferstate[0];
+						}
+						if (ret & 0x02) {
+							metricscmd->
+								DegradingFERPeriod_ms
+								= ferstate[1];
+						}
+						if (ret & 0x04) {
+							metricscmd->
+								UnacceptableFERPeriod_ms
+								= ferstate[2];
+						}
+						if (j < argc) {
+							ret = process_subcmd
+								(valid_fercmds,
+								 NELEMENTS
+								 (valid_fercmds),
+								 argc, argv, &j,
+								 ferlist);
+							if (ret > 0) {
+								if (ret & 0x01) {
+									metricscmd->
+										InactivityPeriodThreshold_ms
+										=
+										ferlist
+										[0];
+								}
+								if (ret & 0x02) {
+									metricscmd->
+										UcFerThresholdValue
+										=
+										ferlist
+										[1];
+								}
+								if (ret & 0x04) {
+									metricscmd->
+										UiFerPktThreshold
+										=
+										ferlist
+										[2];
+								}
+							}
+						}
+					}
+				}
+				metricscmd->Metrics |= 0x08;
+				break;
+			}
+			metricscmd->action = HostCmd_ACT_GEN_SET;
+		}
+	}
+
+	/*
+	 * ENDIANNESS
+	 */
+	metricscmd->action = cpu_to_le16(metricscmd->action);
+	metricscmd->Metrics = cpu_to_le16(metricscmd->Metrics);
+	metricscmd->UiPerPktThreshold =
+		cpu_to_le32(metricscmd->UiPerPktThreshold);
+	metricscmd->StablePERPeriod_ms =
+		cpu_to_le32(metricscmd->StablePERPeriod_ms);
+	metricscmd->DegradingPERPeriod_ms =
+		cpu_to_le32(metricscmd->DegradingPERPeriod_ms);
+	metricscmd->UnacceptablePERPeriod_ms =
+		cpu_to_le32(metricscmd->UnacceptablePERPeriod_ms);
+	metricscmd->InactivityPeriodThreshold_ms =
+		cpu_to_le32(metricscmd->InactivityPeriodThreshold_ms);
+	metricscmd->UiRxPktThreshold =
+		cpu_to_le32(metricscmd->UiRxPktThreshold);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[neighborlist maintain]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (le16_to_cpu(hostcmd->result)) {
+		printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ * @brief       Process maintenance of Neighbor list
+ *
+ * @param       argc    # arguments
+ * @param       argv    A pointer to arguments array
+ *
+ */
+static int
+roamSetNborMaintenance(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	char *valid_cmds[] = { "blacklist", "clear" };
+	int i = 0, j = 0, k = 0;
+	unsigned int mac[ETH_ALEN];
+
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE *pNborMaintainance;
+
+	if (argv[0] == NULL) {
+		puts("\nInsufficient arguments.. \n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc != 2) {
+		puts("\nIncorrect number of arguments.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds); i++)
+		if (!strncmp(valid_cmds[i], argv[j], strlen(valid_cmds[i])))
+			break;
+	if ((unsigned int)i >= NELEMENTS(valid_cmds)) {
+		printf("\nInvalid argument \"%s\"\n\n", argv[0]);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	switch (i) {
+	case 0:
+	    /** blacklist */
+		j++;
+		sscanf(argv[j], "%2x:%2x:%2x:%2x:%2x:%2x",
+		       mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5);
+		for (k = 0; k < ETH_ALEN; k++) {
+			if (*(mac + k) != 0xFF) {
+				break;
+			}
+		}
+
+		if (k == ETH_ALEN) {
+			puts("\nBlacklisting a Broadcast address is not allowed");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		break;
+
+	case 1:
+	    /** clear */
+		j++;
+		if (!strncmp("all", argv[j], strlen("all"))) {
+			for (k = 0; k < ETH_ALEN; k++) {
+				*(mac + k) = 0xFF;
+			}
+		} else {
+			sscanf(argv[j], "%2x:%2x:%2x:%2x:%2x:%2x",
+			       mac, mac + 1, mac + 2, mac + 3, mac + 4,
+			       mac + 5);
+		}
+		break;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	pNborMaintainance
+		= (HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE *)pos;
+
+	cmd_len = S_DS_GEN +
+		sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE);
+
+	hostcmd->command
+		= cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	pNborMaintainance->action = ((i == 0) ? HostCmd_ACT_ADD_TO_BLACKLIST :
+				     HostCmd_ACT_REMOVE_FROM_BLACKLIST);
+	pNborMaintainance->action = cpu_to_le16(pNborMaintainance->action);
+	for (k = 0; k < ETH_ALEN; k++) {
+		pNborMaintainance->BSSID[k] = *(mac + k);
+	}
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[neighborlist maintain]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (le16_to_cpu(hostcmd->result)) {
+		printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue setra backoff command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetBackOff(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	int spflag[2] = { 0, 0 };	/*scan,priod */
+	t_u16 minscan;
+	t_u32 bperiod;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_BACKOFF *roambackoffcmd;
+	int i;
+
+	if (argv[0] == NULL) {
+		puts("\nInsufficient arguments.. \n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/* BackOff */
+	if ((argc != 2) && (argc != 4)) {
+		puts("\nIncorrect number of arguments.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	for (i = 0; i < 4; i++) {
+		if (argv[i + 0] &&
+		    strncmp(argv[i + 0], "scans", strlen("scans")) == 0) {
+			minscan = atoi(argv[i + 1]);
+			i++;
+			spflag[0] = 1;
+			/* TODO validation check on minscan */
+		}
+		if (argv[i + 0] &&
+		    strncmp(argv[i + 0], "period", strlen("period")) == 0) {
+			bperiod = atoi(argv[i + 1]);
+			i++;
+			spflag[1] = 1;
+			/* TODO validation check on bperiod */
+		}
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	roambackoffcmd = (HostCmd_DS_CMD_ROAMAGENT_BACKOFF *)pos;
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_BACKOFF);
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_BACKOFF);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	switch (spflag[0] + spflag[1]) {
+	case 0:
+		/* error */
+		puts("\nIncorrect arguments for setra backoff command.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+
+	case 1:
+		/* get missing parameter */
+		if (getBackOff(roambackoffcmd) != MLAN_STATUS_SUCCESS) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		if (spflag[0] == 0) {
+			minscan = roambackoffcmd->Scans;
+		} else {
+			bperiod = roambackoffcmd->Period;
+		}
+		break;
+
+	case 2:
+	default:
+		break;
+	}
+
+	roambackoffcmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+	roambackoffcmd->Scans = cpu_to_le16(minscan);
+	roambackoffcmd->Period = cpu_to_le16(bperiod);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[roambackoff]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (le16_to_cpu(hostcmd->result)) {
+		printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue setra enable/disable/resume/suspend command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param set/reset set/reset flag
+ *  @param value    roam control/ host event bitmap value
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetControl(int argc, char *argv[], int setreset, t_u8 value)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CMD_ROAMAGENT_CONTROL *roamcontrolcmd;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_CONTROL);
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_CONTROL);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	roamcontrolcmd = (HostCmd_DS_CMD_ROAMAGENT_CONTROL *)pos;
+
+	/* get current value */
+	if (getControl(roamcontrolcmd) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	roamcontrolcmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+	switch (setreset) {
+	case 0:
+		roamcontrolcmd->Control &= value;
+		break;
+	case 1:
+		roamcontrolcmd->Control |= value;
+		break;
+	case 2:
+		roamcontrolcmd->HostEvent &= value;
+		break;
+	case 3:
+		roamcontrolcmd->HostEvent |= value;
+		break;
+	}
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[roamcontrol]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (le16_to_cpu(hostcmd->result)) {
+		printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	} else {
+		printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
+		       le16_to_cpu(hostcmd->command),
+		       le16_to_cpu(hostcmd->result));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief          Issue setra enable command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetEnableControl(int argc, char *argv[])
+{
+	return roamSetControl(argc, argv, 1, ROAM_CONTROL_ENABLE);
+}
+
+/**
+ *  @brief          Issue setra disable command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetDisableControl(int argc, char *argv[])
+{
+	return roamSetControl(argc, argv, 0, ROAM_CONTROL_DISABLE);
+}
+
+/**
+ *  @brief          Issue setra suspend command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetSuspendControl(int argc, char *argv[])
+{
+	return roamSetControl(argc, argv, 1, ROAM_CONTROL_SUSPEND);
+}
+
+/**
+ *  @brief          Issue setra resume command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetResumeControl(int argc, char *argv[])
+{
+	return roamSetControl(argc, argv, 0, ROAM_CONTROL_RESUME);
+}
+
+/**
+ *  @brief          Issue setra crossband command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to argument array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetCrossband(int argc, char *argv[])
+{
+	if (argc != 1) {
+		printf("Invalid Usage \n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if (strncmp(argv[0], "enable", strlen("enable")) == 0) {
+		return roamSetControl(argc, argv, 1, CROSSBAND_ENABLE);
+	} else if (strncmp(argv[0], "disable", strlen("disable")) == 0) {
+		return roamSetControl(argc, argv, 0, CROSSBAND_DISABLE);
+	}
+
+	printf("Invalid Usage \n");
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief          Issue setra event command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to argument array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+roamSetEventBitmap(int argc, char *argv[])
+{
+	int i, enableFlag, found = 0;
+	t_u8 value;
+	if (argc > 4 || argc < 2) {
+		printf("Invalid Usage \n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if (strncmp(argv[0], "enable", strlen("enable")) == 0) {
+		enableFlag = 3;
+		value = HOST_EVENT_NBOR_DISABLE & HOST_EVENT_ROAM_DISABLE
+			& HOST_EVENT_STATE_DISABLE;
+	} else if (strncmp(argv[0], "disable", strlen("disable")) == 0) {
+		enableFlag = 2;
+		value = HOST_EVENT_NBOR_ENABLE | HOST_EVENT_ROAM_ENABLE
+			| HOST_EVENT_STATE_ENABLE;
+	} else {
+		printf("Invalid parameter %s \n", argv[0]);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	for (i = 1; i < argc; i++) {
+		found = 0;
+		if (strncmp(argv[i], "neighbor", strlen("neighbor")) == 0) {
+			found = 1;
+			if (enableFlag == 3) {
+				value |= HOST_EVENT_NBOR_ENABLE;
+			} else {
+				value &= HOST_EVENT_NBOR_DISABLE;
+			}
+		}
+		if (strncmp(argv[i], "roam", strlen("roam")) == 0) {
+			found = 1;
+			if (enableFlag == 3) {
+				value |= HOST_EVENT_ROAM_ENABLE;
+			} else {
+				value &= HOST_EVENT_ROAM_DISABLE;
+			}
+		}
+		if (strncmp(argv[i], "state", strlen("state")) == 0) {
+			found = 1;
+			if (enableFlag == 3) {
+				value |= HOST_EVENT_STATE_ENABLE;
+			} else {
+				value &= HOST_EVENT_STATE_DISABLE;
+			}
+		}
+		if (found == 0) {
+			printf("Invalid parameter %s \n", argv[i]);
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	return roamSetControl(argc, argv, enableFlag, value);
+}
+
+/**
+ *  @brief Set the Roaming agent configuration parameters to FW.
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_set_ra_config(int argc, char *argv[])
+{
+	sub_cmd_exec_t subCmds[] = {
+		{"rssi", 2, 1, roamSetRssiStatsThreshold},
+		{"prebcnmiss", 2, 1, roamSetPreBeaconLoss},
+		{"failcnt", 2, 1, roamSetFailureCount},
+		{"neighbor", 2, 0, printSetNeighborDeprecation},
+		{"nparams", 2, 1, roamSetNborParams},
+		{"maintain", 2, 1, roamSetNborMaintenance},
+		{"scanperiod", 2, 1, roamSetScanPeriod},
+		{"backoff", 2, 1, roamSetBackOff},
+		{"enable", 2, 1, roamSetEnableControl},
+		{"disable", 2, 1, roamSetDisableControl},
+		{"suspend", 2, 1, roamSetSuspendControl},
+		{"resume", 2, 1, roamSetResumeControl},
+		{"metrics", 2, 1, roamSetMetrics},
+		{"crossband", 2, 1, roamSetCrossband},
+		{"event", 2, 1, roamSetEventBitmap}
+	};
+
+	return process_sub_cmd(subCmds, NELEMENTS(subCmds), argc, argv);
+}
diff --git a/wlan_sd8897/mapp/mlanutl/mlanroamagent.h b/wlan_sd8897/mapp/mlanutl/mlanroamagent.h
new file mode 100644
index 0000000..2b32cba
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanroamagent.h
@@ -0,0 +1,314 @@
+/** @file  mlanroamagent.h
+  *
+  * @brief This files contains mlanutl roamagent command handling.
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     08/11/2009: initial version
+************************************************************************/
+
+#ifndef _MLANROAMAGENT_H_
+#define _MLANROAMAGENT_H_
+
+/** Bit definitions */
+#ifndef BIT
+#define BIT(x)  (1UL << (x))
+#endif
+
+/* Define actionsd for HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE */
+/** Blacklist */
+#define HostCmd_ACT_ADD_TO_BLACKLIST            0x0001
+/** Flushing blacklisted entry */
+#define HostCmd_ACT_REMOVE_FROM_BLACKLIST       0x0002
+
+/** Roaming scanmode: discovery */
+#define DISCOVERY_MODE          1
+/** Roaming scanmode: tracking */
+#define TRACKING_MODE           2
+
+/** Threshold configuration: RSSI */
+#define RSSI_THRESHOLD          1
+/** Threshold configuration: SNR */
+#define SNR_THRESHOLD           2
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Bit values for Qualified Neighbor RSSI Entry */
+#define BIT_NEIGHFLAG_RSSI  0x80000000
+/** Bit values for Qualified Neighbor AGE Entry */
+#define BIT_NEIGHFLAG_AGE   0x40000000
+/** Bit values for Qualified Neighbor Blacklist Entry */
+#define BIT_NEIGHFLAG_BLACKLIST 0x20000000
+/** Bit values for Qualified Neighbor Admission Capacity */
+#define BIT_NEIGHFLAG_ADMISSION_CAP     0x10000000
+/** Bit values for Qualified Neighbor Uplink RSSI */
+#define BIT_NEIGHFLAG_UPLINK_RSSI    0x08000000
+#else
+/** Bit values for Qualified Neighbor RSSI Entry */
+#define BIT_NEIGHFLAG_RSSI  0x01
+/** Bit values for Qualified Neighbor AGE Entry */
+#define BIT_NEIGHFLAG_AGE   0x02
+/** Bit values for Qualified Neighbor Blacklist Entry */
+#define BIT_NEIGHFLAG_BLACKLIST 0x04
+/** Bit values for Qualified Neighbor Admission Capacity */
+#define BIT_NEIGHFLAG_ADMISSION_CAP     0x08
+/** Bit values for Qualified Neighbor Uplink RSSI */
+#define BIT_NEIGHFLAG_UPLINK_RSSI    0x10
+#endif
+
+/** milliseconds time conversion data */
+typedef struct exactTime {
+	t_u16 hrs;   /**< Number of hours */
+	t_u16 mins;  /**< Number of minutes */
+	t_u16 secs;  /**< Number of seconds */
+	t_u16 msecs; /**< Number of milliseconds left */
+} ExactTime_t;
+
+/** ROAMAGENT HostEvent bitmasks */
+typedef enum {
+	HOST_EVENT_NBOR_DISABLE = 6,	/* reset bit 0 */
+	HOST_EVENT_NBOR_ENABLE = 1,	/* set bit 0   */
+	HOST_EVENT_ROAM_DISABLE = 5,	/* reset bit 1 */
+	HOST_EVENT_ROAM_ENABLE = 2,	/* set bit 1   */
+	HOST_EVENT_STATE_DISABLE = 3,	/* reset bit 2 */
+	HOST_EVENT_STATE_ENABLE = 4,	/* reset bit 2 */
+} __ATTRIB_PACK__ HostEvent_e;
+
+/** ROAMAGENT_CONTROL command identifiers */
+typedef enum {
+	ROAM_CONTROL_DISABLE = 6,	/* reset bit 0 */
+	ROAM_CONTROL_ENABLE = 1,	/* set bit 0   */
+	ROAM_CONTROL_RESUME = 5,	/* reset bit 1 */
+	ROAM_CONTROL_SUSPEND = 2,	/* set bit 1   */
+	CROSSBAND_DISABLE = 3,	/* reset bit 2 */
+	CROSSBAND_ENABLE = 4	/* set bit 2   */
+} __ATTRIB_PACK__ RoamControl_e;
+
+/*
+ * Definitions of roaming state and other constants
+ */
+/** Enum Definitations: Roaming agent state */
+typedef enum {
+	STATE_DISCONNECTED,
+	STATE_STABLE,
+	STATE_DEGRADING,
+	STATE_UNACCEPTABLE,
+	STATE_HARDROAM,
+	STATE_LINKLOSS,
+	STATE_SOFTROAM,
+	STATE_SUSPEND,
+	STATE_CMD_SUSPEND,
+	STATE_ASYNCASSOC_SUSPEND
+} RoamingAgentState;
+
+/** statistics threshold High RSSI */
+typedef struct {
+    /** Header */
+	MrvlIEtypesHeader_t Header;
+    /** RSSI threshold (dBm) */
+	t_u8 Value;
+    /** reporting frequency */
+	t_u8 Frequency;
+} __ATTRIB_PACK__ MrvlIEtypes_BeaconHighRssiThreshold_t,
+	MrvlIEtypes_BeaconLowRssiThreshold_t,
+	MrvlIEtypes_BeaconHighSnrThreshold_t,
+	MrvlIEtypes_BeaconLowSnrThreshold_t;
+
+/** HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD */
+typedef struct {
+    /** Action */
+	t_u16 action;
+    /** roaming state */
+	t_u8 State;
+    /** active/configured user */
+	t_u8 Profile;
+    /** TLV buffer */
+	t_u8 TlvBuffer[1];
+	/* MrvlIEtypes_BeaconHighRssiThreshold_t BeaconHighRssiThreshold;
+	 * MrvlIEtypes_BeaconLowRssiThreshold_t  BeaconLowRssiThreshold;
+	 * MrvlIEtypes_BeaconHighSnrThreshold_t  BeaconHighSnrThreshold;
+	 * MrvlIEtypes_BeaconLowSnrThreshold_t   BeaconLowSnrThreshold;
+	 * MrvlIEtypes_BeaconsMissed_t           PreBeaconMissed;
+	 * MrvlIEtypes_FailureCount_t            FailureCnt;
+	 */
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD;
+
+typedef struct {
+    /**  */
+	signed char RssiHighLevel;
+    /**  */
+	signed char RssiLowLevel;
+    /** */
+	signed char RssiNborDiff;
+
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_ROAM_THRESHOLD;
+
+#define ROAM_THRESH_MAX  4
+
+/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT */
+typedef struct {
+    /** Action */
+	t_u16 action;
+    /** configured qualifying snr */
+	signed char ConfQualSignalStrength;
+    /** active qualifying snr */
+	signed char ActiveQualSignalStrength;
+    /** qualifying neighbor count */
+	t_u16 QualifyingNumNeighbor;
+    /** inactivity in # scans */
+	t_u16 StaleCount;
+    /** inactivity in time (ms) */
+	t_u32 StalePeriod;
+    /** blacklist duration in ms due to minor failures */
+	t_u32 ShortBlacklistPeriod;
+    /** blacklist duration in ms due to severe failures */
+	t_u32 LongBlacklistPeriod;
+
+	HostCmd_DS_CMD_ROAMAGENT_ROAM_THRESHOLD RoamThresh[ROAM_THRESH_MAX];
+
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT;
+
+/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST */
+typedef struct {
+    /** Action */
+	t_u16 action;
+    /** Reserved */
+	t_u16 Reserved;
+    /** TLV buffer */
+	t_u8 TlvBuffer[1];
+	/* MrvlIEtypes_NeighborEntry_t Neighbors[MRVL_ROAM_MAX_NEIGHBORS];
+	 * MRVL_ROAM_MAX_NEIGHBORS = 5
+	 */
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST;
+
+/** neighbor entry details roaming agent */
+typedef struct {
+    /** Header */
+	MrvlIEtypesHeader_t Header;
+    /** bssid of neighbor */
+	t_u8 Bssid[ETH_ALEN];
+    /** Reserved */
+	t_u16 Reserved;
+    /** neighbor snr */
+	t_s16 SignalStrength;
+    /** neighbor age */
+	t_u16 Age;
+    /** bit map for qualified neighbor */
+	t_u32 QualifiedNeighborBitmap;
+    /** blacklist duration in ms */
+	t_u32 BlackListDuration;
+} __ATTRIB_PACK__ MrvlIEtypes_NeighborEntry_t;
+
+/** HostCmd_DS_ROAMAGENT_ADV_METRIC_THRESHOLD */
+typedef struct {
+    /** Action */
+	t_u16 action;
+    /** Beacon RSSI Metrics,Data RSSI Metrics or PER Metrics */
+	t_u16 Metrics;
+    /** Percentage FER Threshold value to exceed for making a roam decision */
+	t_u8 UcFerThresholdValue;
+    /** Percentage PER Threshold value to exceed for making a roam decision */
+	t_u8 UcPerThresholdValue;
+    /** Reserved for later use */
+	t_u8 Reserved[2];
+    /** Time (ms) for which FER should prevail in stable state */
+	t_u32 StableFERPeriod_ms;
+    /** Time (ms) for which FER should prevail in degrading  state */
+	t_u32 DegradingFERPeriod_ms;
+    /** Time (ms) for which FER should prevail in unacceptable state */
+	t_u32 UnacceptableFERPeriod_ms;
+    /** Time (ms) for which FER should prevail in stable state */
+	t_u32 StablePERPeriod_ms;
+    /** Time (ms) for which PER should prevail in degrading  state */
+	t_u32 DegradingPERPeriod_ms;
+    /** Time (ms) for which PER should prevail in unacceptable state */
+	t_u32 UnacceptablePERPeriod_ms;
+    /** Number of TX packets to exceed in period_ms ms for the FER for Roam */
+	t_u32 UiFerPktThreshold;
+    /** Number of TX packets to exceed in period_ms ms for the PER for Roam */
+	t_u32 UiPerPktThreshold;
+    /** Time in ms for which inactivity should prevail for state transition */
+	t_u32 InactivityPeriodThreshold_ms;
+    /** With Data RSSI Metrics, Roam only when RX packets in period_ms ms exceeds this */
+	t_u32 UiRxPktThreshold;
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD;
+
+/** scan period for each search mode and state for roaming agent */
+typedef struct {
+    /** Header */
+	MrvlIEtypesHeader_t Header;
+    /** search mode */
+	t_u16 SearchMode;
+    /** roaming state */
+	t_u16 State;
+    /** scan period value */
+	t_u32 ScanPeriod;
+} __ATTRIB_PACK__ MrvlIEtypes_NeighborScanPeriod_t;
+
+/** HostCmd_DS_CMD_ROAMAGENT_CONTROL */
+typedef struct {
+    /** Action */
+	t_u16 action;
+    /** enable control */
+	t_u8 Control;
+    /** host event control */
+	t_u8 HostEvent;
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_CONTROL;
+
+/** HostCmd_DS_CMD_ROAMAGENT_BACKOFF */
+typedef struct {
+    /** Action */
+	t_u16 action;
+    /** minimum scans */
+	t_u16 Scans;
+    /** backoff period */
+	t_u32 Period;
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_BACKOFF;
+
+/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD */
+typedef struct {
+    /** Action */
+	t_u16 action;
+    /** Reserved */
+	t_u16 Reserved;
+    /** scanPeriod TLV */
+	MrvlIEtypes_NeighborScanPeriod_t scanPeriod;
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD;
+
+/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP */
+typedef struct {
+    /** Action */
+	t_u16 action;
+    /** Reserved */
+	t_u16 Reserved;
+    /** TLV buffer */
+	t_u8 TlvBuffer[1];
+	/* MrvlIEtypes_NeighborScanPeriod_t scanPeriod[MRVL_ROAM_SCAN_PERIODS];
+	 * MRVL_ROAM_SCAN_PERIODS  = 6
+	 */
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP;
+
+/** HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE */
+typedef struct {
+    /** Action */
+	t_u16 action;
+    /** BSSID */
+	t_u8 BSSID[ETH_ALEN];
+} __ATTRIB_PACK__ HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE;
+
+#endif /* _MLANROAMAGENT_H_ */
diff --git a/wlan_sd8897/mapp/mlanutl/mlanscanagent.c b/wlan_sd8897/mapp/mlanutl/mlanscanagent.c
new file mode 100644
index 0000000..3f5745f
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanscanagent.c
@@ -0,0 +1,840 @@
+/** @file  mlanscanagent.c
+  *
+  * @brief This files contains mlanutl scanagent command handling.
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     08/11/2009: initial version
+************************************************************************/
+
+#include    "mlanutl.h"
+#include    "mlanhostcmd.h"
+#include    "mlanoffload.h"
+#include    "mlanscanagent.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief scanagent configure scan table
+ *
+ *  @param age_limit    age limit
+ *  @param hold_limit   hold limit
+ *
+ *  @return             MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_cfg_scan_table_limits(t_u32 age_limit, t_u32 hold_limit)
+{
+	int ret = 0;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS *scan_table_limits = NULL;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		return -ENOMEM;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return -ENOMEM;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_SCAN_TABLE_LIMITS);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	scan_table_limits = (HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS *)pos;
+	scan_table_limits->table_age_limit = cpu_to_le16(age_limit);
+	scan_table_limits->table_hold_limit = cpu_to_le16(hold_limit);
+
+	/* 0 set values are ignored by firmware */
+	scan_table_limits->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[scanAgentIoctl]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	printf("\nAge limit  = %7d seconds\n",
+	       le16_to_cpu(scan_table_limits->table_age_limit));
+	printf("Hold limit = %7d seconds\n\n",
+	       le16_to_cpu(scan_table_limits->table_hold_limit));
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Set scanagent age limit
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_age_limit(int argc, char *argv[])
+{
+	t_u32 age_limit = 0;
+
+	if (argc) {
+		age_limit = atoi(argv[0]);
+	}
+
+	return scanagent_cfg_scan_table_limits(age_limit, 0);
+}
+
+/**
+ *  @brief Set scanagent hold limit
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_hold_limit(int argc, char *argv[])
+{
+	t_u32 hold_limit = 0;
+
+	if (argc) {
+		hold_limit = atoi(argv[0]);
+	}
+
+	return scanagent_cfg_scan_table_limits(0, hold_limit);
+}
+
+/**
+ *  @brief Set scanagent scan timing
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_timing(int argc, char *argv[])
+{
+	int ret = 0;
+	struct ifreq ifr;
+	int idx;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len = 0, sel = 0;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	HostCmd_DS_SCANAGENT_CONFIG_TIMING *cfg_timing_cmd = NULL;
+	MrvlIEtypes_ConfigScanTiming_t *cfg_timing_tlv = NULL;
+	timing_sel_t sel_str[] = { {"disconnected", 1},
+	{"adhoc", 1},
+	{"fullpower", 1},
+	{"ieeeps", 1},
+	{"periodic", 1}
+	};
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+	cmd_len = S_DS_GEN + sizeof(t_u16);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		return -ENOMEM;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return -ENOMEM;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_SCAN_TIMING);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cfg_timing_cmd = (HostCmd_DS_SCANAGENT_CONFIG_TIMING *)pos;
+	cfg_timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+
+	cfg_timing_tlv
+		= (MrvlIEtypes_ConfigScanTiming_t *)cfg_timing_cmd->tlv_buffer;
+
+	if (argc == 5) {
+		cfg_timing_cmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+		cfg_timing_tlv->header.type = cpu_to_le16(TLV_TYPE_SCAN_TIMING);
+		cfg_timing_tlv->header.len =
+			cpu_to_le16(sizeof(MrvlIEtypes_ConfigScanTiming_t)
+				    - sizeof(cfg_timing_tlv->header));
+
+		for (idx = 0; (unsigned int)idx < NELEMENTS(sel_str); idx++) {
+			if (strncmp(argv[0],
+				    sel_str[idx].str,
+				    sel_str[idx].match_len) == 0) {
+				sel = idx + 1;
+				break;
+			}
+		}
+
+		if (idx == NELEMENTS(sel_str)) {
+			printf("Wrong argument for mode selected \"%s\"\n",
+			       argv[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+
+		/*
+		 *  HostCmd_DS_ScanagentTimingMode_e;
+		 *     TIMING_MODE_INVALID        = 0,
+		 *     TIMING_MODE_DISCONNECTED   = 1,
+		 *     TIMING_MODE_ADHOC          = 2,
+		 *     TIMING_MODE_FULL_POWER     = 3,
+		 *     TIMING_MODE_IEEE_PS        = 4,
+		 *     TIMING_MODE_PERIODIC_PS    = 5,
+		 */
+		cfg_timing_tlv->mode = cpu_to_le32(sel);
+		cfg_timing_tlv->dwell = cpu_to_le32(atoi(argv[1]));
+		cfg_timing_tlv->max_off = cpu_to_le32(atoi(argv[2]));
+		cfg_timing_tlv->min_link = cpu_to_le32(atoi(argv[3]));
+		cfg_timing_tlv->rsp_timeout = cpu_to_le32(atoi(argv[4]));
+
+		cmd_len += sizeof(MrvlIEtypes_ConfigScanTiming_t);
+	}
+
+	hostcmd->size = cpu_to_le16(cmd_len);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[scanAgentIoctl]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ret = process_host_cmd_resp(HOSTCMD, buffer);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Set scanagent profile scan period
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_profile_period(int argc, char *argv[])
+{
+	int ret = 0;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len = 0;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN *cfg_profile_scan = NULL;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		return -ENOMEM;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return -ENOMEM;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+	hostcmd->command =
+		cpu_to_le16(HostCmd_CMD_SCANAGENT_CONFIG_PROFILE_SCAN);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cfg_profile_scan = (HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN *)pos;
+	if (argc == 1) {
+		cfg_profile_scan->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
+		cfg_profile_scan->scan_interval = cpu_to_le16(atoi(argv[0]));
+	} else {
+		cfg_profile_scan->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
+	}
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[scanAgentIoctl]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	cfg_profile_scan->scan_interval =
+		le16_to_cpu(cfg_profile_scan->scan_interval);
+	if ((int)cfg_profile_scan->scan_interval == 0)
+		printf("\nProfile Scan interval: <disabled>\n\n");
+	else
+		printf("\nProfile Scan interval: %d seconds\n\n",
+		       (int)cfg_profile_scan->scan_interval);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief scanagent parse entry selection
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param psel     A pointer to scanagent entry selection
+ *
+ *  @return         None
+ */
+static void
+scanAgentParseEntrySel(int argc, char *argv[],
+		       HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE *psel,
+		       int *cmd_len)
+{
+	int arg_idx, tmp_idx;
+	t_u8 *tlv_pos;
+	MrvlIEtypes_SsIdParamSet_t *ssid;
+	MrvlIEtypes_Bssid_List_t *bssid;
+	unsigned int mac[ETH_ALEN];
+
+	tlv_pos = (t_u8 *)psel->tlv_buffer;
+
+	for (arg_idx = 0; arg_idx < argc; arg_idx++) {
+		if (strncmp(argv[arg_idx], "ssid=", strlen("ssid=")) == 0) {
+			ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv_pos;
+			ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
+			ssid->header.len =
+				strlen(argv[arg_idx]) - strlen("ssid=");
+			strncpy((char *)ssid->ssid,
+				(argv[arg_idx] + strlen("ssid=")),
+				ssid->header.len);
+			tlv_pos +=
+				ssid->header.len + sizeof(MrvlIEtypesHeader_t);
+			ssid->header.len = cpu_to_le16(ssid->header.len);
+
+		} else if (strncmp(argv[arg_idx], "bssid=", strlen("bssid=")) ==
+			   0) {
+			bssid = (MrvlIEtypes_Bssid_List_t *)tlv_pos;
+			bssid->header.type = cpu_to_le16(TLV_TYPE_BSSID);
+			bssid->header.len = ETH_ALEN;
+			/*
+			 *  "bssid" token string handler
+			 */
+			sscanf(argv[arg_idx] + strlen("bssid="),
+			       "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1,
+			       mac + 2, mac + 3, mac + 4, mac + 5);
+			for (tmp_idx = 0;
+			     (unsigned int)tmp_idx < NELEMENTS(mac);
+			     tmp_idx++) {
+				bssid->bssid[tmp_idx] = (t_u8)mac[tmp_idx];
+			}
+			tlv_pos +=
+				bssid->header.len + sizeof(MrvlIEtypesHeader_t);
+			bssid->header.len = cpu_to_le16(bssid->header.len);
+
+		} else if (strncmp(argv[arg_idx], "age=", strlen("age=")) == 0) {
+			psel->age =
+				cpu_to_le32(atoi
+					    (argv[arg_idx] + strlen("age=")));
+
+		} else if (strncmp(argv[arg_idx], "id=", strlen("id=")) == 0) {
+			psel->scan_request_id =
+				cpu_to_le32(atoi
+					    (argv[arg_idx] + strlen("id=")));
+		}
+	}
+
+	*cmd_len += (tlv_pos - psel->tlv_buffer);
+}
+
+/**
+ *  @brief scanagent execute scan
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_exec_scan(int argc, char *argv[])
+{
+	int ret = 0;
+	struct ifreq ifr;
+	int arg_idx, tmp_idx;
+	t_u32 cmd_len = 0, cmd_header_len = 0;
+	t_u8 *buffer = NULL, *pos = NULL, *tlv_pos = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	HostCmd_DS_SCANAGENT_SCAN_EXEC *scan_exec = NULL;
+	MrvlIEtypes_SsIdParamSet_t *ssid = NULL;
+	MrvlIEtypes_Bssid_List_t *bssid = NULL;
+	MrvlIEtypes_ConfigScanTiming_t *cfg_timing_tlv = NULL;
+	unsigned int mac[ETH_ALEN];
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+	cmd_len = (S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_SCAN_EXEC)
+		   - sizeof(scan_exec->tlv_buffer));
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		return -ENOMEM;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return -ENOMEM;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_SCAN_EXEC);
+	hostcmd->size = 0;
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	scan_exec = (HostCmd_DS_SCANAGENT_SCAN_EXEC *)pos;
+	tlv_pos = scan_exec->tlv_buffer;
+
+	for (arg_idx = 0; arg_idx < argc; arg_idx++) {
+		if (strncmp(argv[arg_idx], "ssid=", strlen("ssid=")) == 0) {
+			/*
+			 *  "ssid" token string handler
+			 */
+			ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv_pos;
+			ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
+			ssid->header.len =
+				strlen(argv[arg_idx]) - strlen("ssid=");
+			strncpy((char *)ssid->ssid,
+				argv[arg_idx] + strlen("ssid="),
+				ssid->header.len);
+			tlv_pos +=
+				ssid->header.len + sizeof(MrvlIEtypesHeader_t);
+			ssid->header.len = cpu_to_le16(ssid->header.len);
+		} else if (strncmp(argv[arg_idx], "bssid=", strlen("bssid=")) ==
+			   0) {
+			bssid = (MrvlIEtypes_Bssid_List_t *)tlv_pos;
+			bssid->header.type = cpu_to_le16(TLV_TYPE_BSSID);
+			bssid->header.len = ETH_ALEN;
+			/*
+			 *  "bssid" token string handler
+			 */
+			sscanf(argv[arg_idx] + strlen("bssid="),
+			       "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1,
+			       mac + 2, mac + 3, mac + 4, mac + 5);
+			for (tmp_idx = 0;
+			     (unsigned int)tmp_idx < NELEMENTS(mac);
+			     tmp_idx++) {
+				bssid->bssid[tmp_idx] = (t_u8)mac[tmp_idx];
+			}
+			tlv_pos +=
+				bssid->header.len + sizeof(MrvlIEtypesHeader_t);
+			bssid->header.len = cpu_to_le16(bssid->header.len);
+		} else if (strncmp(argv[arg_idx], "type=", strlen("type=")) ==
+			   0) {
+			/*
+			   if (strcmp(argv[arg_idx] + strlen("type="), "prof") == 0) {
+			   scan_exec->scan_type = CONFIG_PROFILE;
+			   } else {
+			   scan_exec->scan_type = CONFIG_SITE_SURVEY;
+			   }
+			 */
+			scan_exec->scan_type = CONFIG_SITE_SURVEY;
+			scan_exec->scan_type =
+				cpu_to_le16(scan_exec->scan_type);
+		} else if (strncmp(argv[arg_idx], "group=", strlen("group=")) ==
+			   0) {
+			sscanf(argv[arg_idx] + strlen("group="), "0x%x",
+			       &tmp_idx);
+			scan_exec->chan_group = cpu_to_le32(tmp_idx);
+		} else if (strncmp(argv[arg_idx], "delay=", strlen("delay=")) ==
+			   0) {
+			/*
+			 *  "delay" token string handler
+			 */
+			sscanf(argv[arg_idx] + strlen("delay="),
+			       "%d", (int *)&scan_exec->delay);
+			scan_exec->delay = cpu_to_le32(scan_exec->delay);
+		} else if (strncmp(argv[arg_idx], "timing=", strlen("timing="))
+			   == 0) {
+			cfg_timing_tlv =
+				(MrvlIEtypes_ConfigScanTiming_t *)tlv_pos;
+			cfg_timing_tlv->header.type =
+				cpu_to_le16(TLV_TYPE_SCAN_TIMING);
+			cfg_timing_tlv->header.len = ((sizeof(cfg_timing_tlv)
+						       -
+						       sizeof(cfg_timing_tlv->
+							      header)));
+			/*
+			 *  "timing" token string handler
+			 */
+			sscanf(argv[arg_idx] + strlen("timing="), "%d,%d,%d,%d",
+			       (int *)&cfg_timing_tlv->dwell,
+			       (int *)&cfg_timing_tlv->max_off,
+			       (int *)&cfg_timing_tlv->min_link,
+			       (int *)&cfg_timing_tlv->rsp_timeout);
+
+			cfg_timing_tlv->mode = 0;
+			cfg_timing_tlv->dwell =
+				cpu_to_le32(cfg_timing_tlv->dwell);
+			cfg_timing_tlv->max_off =
+				cpu_to_le32(cfg_timing_tlv->max_off);
+			cfg_timing_tlv->min_link =
+				cpu_to_le32(cfg_timing_tlv->min_link);
+			cfg_timing_tlv->rsp_timeout =
+				cpu_to_le32(cfg_timing_tlv->rsp_timeout);
+
+			tlv_pos += sizeof(MrvlIEtypesHeader_t);
+			tlv_pos += cfg_timing_tlv->header.len;
+			cfg_timing_tlv->header.len =
+				cpu_to_le16(cfg_timing_tlv->header.len);
+		}
+	}
+
+	cmd_len += (tlv_pos - scan_exec->tlv_buffer);
+	hostcmd->size = cpu_to_le16(cmd_len);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[scanAgentIoctl]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	} else {
+		printf("\nScan Scheduled, ID = %d\n\n",
+		       (int)le32_to_cpu(scan_exec->scan_req_id_out));
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Issue a scanagent cmd_type subcommand
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @param cmd_type command type
+ *
+ *  @return         MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_table_entry_sub_cmd(int argc, char *argv[],
+			      HostCmd_DS_ScanagentTableMaintenance_e cmd_type)
+{
+	int ret = 0;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len = 0;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE *table_maintenance = NULL;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+	cmd_len = (S_DS_GEN + sizeof(HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE)
+		   - sizeof(table_maintenance->tlv_buffer));
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		return -ENOMEM;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return -ENOMEM;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_SCANAGENT_TABLE_MAINTENANCE);
+	hostcmd->size = 0;
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	table_maintenance = (HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE *)pos;
+	table_maintenance->action = cpu_to_le16((t_u16)cmd_type);
+
+	scanAgentParseEntrySel(argc, argv, table_maintenance, (int *)&cmd_len);
+
+	hostcmd->size = cpu_to_le16(cmd_len);
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[scanAgentIoctl]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Issue a scanagent table lock subcommand
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_table_lock(int argc, char *argv[])
+{
+	return scanagent_table_entry_sub_cmd(argc, argv, SCAN_TABLE_OP_LOCK);
+}
+
+/**
+ *  @brief Issue a scanagent table unlock subcommand
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_table_unlock(int argc, char *argv[])
+{
+	return scanagent_table_entry_sub_cmd(argc, argv, SCAN_TABLE_OP_UNLOCK);
+}
+
+/**
+ *  @brief Issue a scanagent table purge subcommand
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS on success, otherwise error code
+ */
+static int
+scanagent_table_purge(int argc, char *argv[])
+{
+	return scanagent_table_entry_sub_cmd(argc, argv, SCAN_TABLE_OP_PURGE);
+}
+
+/**
+ *  @brief Issue a scanagent command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_scanagent(int argc, char *argv[])
+{
+	sub_cmd_exec_t sub_cmd[] = {
+		{"timing", 2, 1, scanagent_timing},
+		{"scan", 2, 1, scanagent_exec_scan},
+		{"lock", 2, 1, scanagent_table_lock},
+		{"unlock", 2, 1, scanagent_table_unlock},
+		{"purge", 2, 1, scanagent_table_purge},
+		{"profile", 2, 1, scanagent_profile_period},
+		{"holdlimit", 2, 1, scanagent_hold_limit},
+		{"agelimit", 2, 1, scanagent_age_limit}
+	};
+
+	return process_sub_cmd(sub_cmd, NELEMENTS(sub_cmd), argc, argv);
+}
diff --git a/wlan_sd8897/mapp/mlanutl/mlanscanagent.h b/wlan_sd8897/mapp/mlanutl/mlanscanagent.h
new file mode 100644
index 0000000..f09d33b
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanscanagent.h
@@ -0,0 +1,149 @@
+/** @file  mlanscanagent.h
+  *
+  * @brief This files contains mlanutl scanagent command handling.
+  *
+  * Copyright (C) 2008-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     08/11/2009: initial version
+************************************************************************/
+
+#ifndef _MLAN_SCANAGENT_H_
+#define _MLAN_SCANAGENT_H_
+
+typedef struct {
+    /** Action GET or SET */
+	t_u16 action;
+    /** scan interval */
+	t_u16 scan_interval;
+} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_CONFIG_PROFILE_SCAN;
+
+typedef struct {
+	t_u32 scan_req_id_out;
+			    /**< Scan request id */
+	t_u32 delay;	    /**< Delay */
+	t_u32 chan_group;   /**< Channel Group */
+	t_u16 scan_type;    /**< Scan type */
+	t_u16 reserved;	    /**< Reserved */
+
+	t_u8 tlv_buffer[1]; /**< Rest is TLV buffer */
+
+	/*  MrvlIEtypes_SsIdParamSet_t
+	 *  MrvlIEtypes_Bssid_List_t
+	 *  MrvlIEtypes_ConfigScanTiming_t
+	 */
+} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_SCAN_EXEC;
+
+typedef struct {
+    /** Action Set or get */
+	t_u16 action;
+    /** Reserved */
+	t_u16 reserved;
+    /** Table age limit */
+	t_u16 table_age_limit;
+    /** Table hold limit */
+	t_u16 table_hold_limit;
+} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_SCAN_TABLE_LIMITS;
+
+typedef struct {
+    /** Action Set or get */
+	t_u16 action;
+    /** TLV buffer starts here */
+	t_u8 tlv_buffer[1];
+	/* MrvlIEtypes_ConfigScanTiming_t */
+} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_CONFIG_TIMING;
+
+typedef struct {
+    /** HostCmd_DS_ScanagentTableMaintenance_e action */
+	t_u16 action;
+    /** Reserved */
+	t_u16 reserved;
+    /** Request Id, 0 to disable */
+	t_u32 scan_request_id;
+    /** Age, 0 to disable */
+	t_u32 age;
+    /** TLV Buffer follows */
+	t_u8 tlv_buffer[1];
+
+	/*  MrvlIEtypes_SsIdParamSet_t
+	 *  MrvlIEtypes_Bssid_List_t
+	 */
+} __ATTRIB_PACK__ HostCmd_DS_SCANAGENT_TABLE_MAINTENANCE;
+
+/** ENUM definition: Scanagent Table Maintenance */
+typedef enum {
+	SCAN_TABLE_OP_INVALID = 0,
+
+	SCAN_TABLE_OP_LOCK = 1,
+	SCAN_TABLE_OP_UNLOCK = 2,
+	SCAN_TABLE_OP_PURGE = 3,
+
+} __ATTRIB_PACK__ HostCmd_DS_ScanagentTableMaintenance_e;
+
+/** MrvlIEtypes_SsIdParamSet_t */
+typedef struct _MrvlIEtypes_SsIdParamSet_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** SSID */
+	t_u8 ssid[1];
+} __ATTRIB_PACK__ MrvlIEtypes_SsIdParamSet_t;
+
+/** _MrvlIEtypes_Bssid_List_t */
+typedef struct _MrvlIEtypes_Bssid_List_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** BSSID */
+	t_u8 bssid[ETH_ALEN];
+} __ATTRIB_PACK__ MrvlIEtypes_Bssid_List_t;
+
+typedef struct {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+
+	t_u32 mode;    /**< Mode */
+	t_u32 dwell;   /**< Dwell */
+	t_u32 max_off; /**< Max. off */
+	t_u32 min_link;/**< Minimum Link */
+	t_u32 rsp_timeout;
+		       /**< Rsp Timeout */
+
+} __ATTRIB_PACK__ MrvlIEtypes_ConfigScanTiming_t;
+
+/** ENUM definition: ScanAgentScanType  */
+typedef enum {
+	CONFIG_SITE_SURVEY = 0,
+	CONFIG_NEIGHBOR = 1,
+	CONFIG_PROFILE = 2,
+	CONFIG_ARBITRARY_CHANNEL = 3,
+
+} __ATTRIB_PACK__ HostCmd_DS_ScanagentScanType_e;
+
+/** ENUM definition: ScanAgentScanTimingMode  */
+typedef enum {
+	TIMING_MODE_INVALID = 0,
+
+	TIMING_MODE_DISCONNECTED = 1,
+	TIMING_MODE_ADHOC = 2,
+	TIMING_MODE_FULL_POWER = 3,
+	TIMING_MODE_IEEE_PS = 4,
+	TIMING_MODE_PERIODIC_PS = 5,
+
+} __ATTRIB_PACK__HostCmd_DS_ScanagentTimingMode_e;
+
+int process_host_cmd_resp(char *cmd_name, t_u8 *buf);
+#endif /* _MLAN_SCANAGENT_H_ */
diff --git a/wlan_sd8897/mapp/mlanutl/mlanutl.c b/wlan_sd8897/mapp/mlanutl/mlanutl.c
new file mode 100644
index 0000000..851930a
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanutl.c
@@ -0,0 +1,17344 @@
+/** @file  mlanutl.c
+  *
+  * @brief Program to control parameters in the mlandriver
+  *
+  * Copyright (C) 2011-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     11/04/2011: initial version
+************************************************************************/
+
+#include    "mlanutl.h"
+
+/** Supported stream modes */
+#define HT_STREAM_MODE_1X1   0x11
+#define HT_STREAM_MODE_2X2   0x22
+
+/** mlanutl version number */
+#define MLANUTL_VER "M1.3"
+
+/** Initial number of total private ioctl calls */
+#define IW_INIT_PRIV_NUM    128
+/** Maximum number of total private ioctl calls supported */
+#define IW_MAX_PRIV_NUM     1024
+
+typedef struct {
+	t_u8 chanNum;	  /**< Channel Number */
+	t_u8 chanLoad;	  /**< Channel Load fraction */
+	t_s16 anpi;	  /**< Channel ANPI */
+
+} ChanRptInfo_t;
+
+/********************************************************
+			Local Variables
+********************************************************/
+#define BAND_B       (1U << 0)
+#define BAND_G       (1U << 1)
+#define BAND_A       (1U << 2)
+#define BAND_GN      (1U << 3)
+#define BAND_AN      (1U << 4)
+#define BAND_GAC     (1U << 5)
+#define BAND_AAC     (1U << 6)
+
+static char *band[] = {
+	"B",
+	"G",
+	"A",
+	"GN",
+	"AN",
+	"GAC",
+	"AAC",
+};
+
+static char *adhoc_bw[] = {
+	"20 MHz",
+	"HT 40 MHz above",
+	" ",
+	"HT 40 MHz below",
+	"VHT 80 MHz",
+};
+
+/** Stringification of rateId enumeration */
+const char *rateIdStr[] = { "1", "2", "5.5", "11", "--",
+	"6", "9", "12", "18", "24", "36", "48", "54", "--",
+	"M0", "M1", "M2", "M3", "M4", "M5", "M6", "M7",
+	"H0", "H1", "H2", "H3", "H4", "H5", "H6", "H7"
+};
+
+#ifdef DEBUG_LEVEL1
+#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 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
+static int process_multi_chan_cfg(int argc, char *argv[]);
+static int process_multi_chan_policy(int argc, char *argv[]);
+static int process_drcs_time_slicing_cfg(int argc, char *argv[]);
+#ifdef RX_PACKET_COALESCE
+static int process_rx_pkt_coalesce_cfg(int argc, char *argv[]);
+static void print_rx_packet_coalesc_help(void);
+#endif
+static int process_version(int argc, char *argv[]);
+static int process_bandcfg(int argc, char *argv[]);
+static int process_hostcmd(int argc, char *argv[]);
+static int process_httxcfg(int argc, char *argv[]);
+static int process_htcapinfo(int argc, char *argv[]);
+static int process_addbapara(int argc, char *argv[]);
+static int process_aggrpriotbl(int argc, char *argv[]);
+static int process_addbareject(int argc, char *argv[]);
+static int process_delba(int argc, char *argv[]);
+static int process_rejectaddbareq(int argc, char *argv[]);
+static int process_vhtcfg(int argc, char *argv[]);
+static int process_opermodecfg(int argc, char *argv[]);
+static int process_datarate(int argc, char *argv[]);
+static int process_txratecfg(int argc, char *argv[]);
+static int process_getlog(int argc, char *argv[]);
+static int process_esuppmode(int argc, char *argv[]);
+static int process_passphrase(int argc, char *argv[]);
+static int process_deauth(int argc, char *argv[]);
+#ifdef UAP_SUPPORT
+static int process_getstalist(int argc, char *argv[]);
+#endif
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+static int process_bssrole(int argc, char *argv[]);
+#endif
+#endif
+#ifdef STA_SUPPORT
+static int process_setuserscan(int argc, char *argv[]);
+static int wlan_process_getscantable(int argc, char *argv[],
+				     wlan_ioctl_user_scan_cfg *scan_req);
+static int process_getscantable(int argc, char *argv[]);
+static int process_extcapcfg(int argc, char *argv[]);
+static int process_cancelscan(int argc, char *argv[]);
+#endif
+static int process_deepsleep(int argc, char *argv[]);
+static int process_ipaddr(int argc, char *argv[]);
+static int process_otpuserdata(int argc, char *argv[]);
+static int process_countrycode(int argc, char *argv[]);
+static int process_tcpackenh(int argc, char *argv[]);
+#ifdef REASSOCIATION
+static int process_assocessid(int argc, char *argv[]);
+#endif
+#ifdef STA_SUPPORT
+static int process_listeninterval(int argc, char *argv[]);
+static int process_psmode(int argc, char *argv[]);
+#endif
+#ifdef DEBUG_LEVEL1
+static int process_drvdbg(int argc, char *argv[]);
+#endif
+static int process_hscfg(int argc, char *argv[]);
+static int process_hssetpara(int argc, char *argv[]);
+static int process_wakeupresaon(int argc, char *argv[]);
+static int process_mgmtfilter(int argc, char *argv[]);
+static int process_scancfg(int argc, char *argv[]);
+static int process_warmreset(int argc, char *argv[]);
+static int process_txpowercfg(int argc, char *argv[]);
+static int process_pscfg(int argc, char *argv[]);
+static int process_bcntimeoutcfg(int argc, char *argv[]);
+static int process_sleeppd(int argc, char *argv[]);
+static int process_txcontrol(int argc, char *argv[]);
+static int process_host_tdls_config(int argc, char *argv[]);
+static int process_tdls_config(int argc, char *argv[]);
+static int process_tdls_setinfo(int argc, char *argv[]);
+static int process_tdls_discovery(int argc, char *argv[]);
+static int process_tdls_setup(int argc, char *argv[]);
+static int process_tdls_teardown(int argc, char *argv[]);
+static int process_tdls_powermode(int argc, char *argv[]);
+static int process_tdls_link_status(int argc, char *argv[]);
+static int process_tdls_debug(int argc, char *argv[]);
+static int process_tdls_channel_switch(int argc, char *argv[]);
+static int process_tdls_stop_channel_switch(int argc, char *argv[]);
+static int process_tdls_cs_params(int argc, char *argv[]);
+static int process_tdls_disable_channel_switch(int argc, char *argv[]);
+static int process_tdls_idle_time(int argc, char *argv[]);
+static int process_dfs_offload_enable(int argc, char *argv[]);
+static int process_customie(int argc, char *argv[]);
+static int process_regrdwr(int argc, char *argv[]);
+static int process_rdeeprom(int argc, char *argv[]);
+static int process_memrdwr(int argc, char *argv[]);
+static int process_sdcmd52rw(int argc, char *argv[]);
+static int process_mefcfg(int argc, char *argv[]);
+#ifdef STA_SUPPORT
+static int process_arpfilter(int argc, char *argv[]);
+#endif
+static int process_cfgdata(int argc, char *argv[]);
+static int process_mgmtframetx(int argc, char *argv[]);
+static int process_mgmt_frame_passthrough(int argc, char *argv[]);
+static int process_qconfig(int argc, char *argv[]);
+static int process_addts(int argc, char *argv[]);
+static int process_delts(int argc, char *argv[]);
+static int process_wmm_qstatus(int argc, char *argv[]);
+static int process_wmm_ts_status(int argc, char *argv[]);
+static int process_qos_config(int argc, char *argv[]);
+static int process_macctrl(int argc, char *argv[]);
+static int process_fwmacaddr(int argc, char *argv[]);
+static int process_regioncode(int argc, char *argv[]);
+static int process_offchannel(int argc, char *argv[]);
+static int process_linkstats(int argc, char *argv[]);
+#if defined(STA_SUPPORT)
+static int process_pmfcfg(int argc, char *argv[]);
+#endif
+static int process_verext(int argc, char *argv[]);
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+static int process_radio_ctrl(int argc, char *argv[]);
+#endif
+static int process_wmm_cfg(int argc, char *argv[]);
+static int process_wmm_param_config(int argc, char *argv[]);
+#if defined(STA_SUPPORT)
+static int process_11d_cfg(int argc, char *argv[]);
+static int process_11d_clr_tbl(int argc, char *argv[]);
+#endif
+static int process_wws_cfg(int argc, char *argv[]);
+#if defined(REASSOCIATION)
+static int process_set_get_reassoc(int argc, char *argv[]);
+#endif
+static int process_txbuf_cfg(int argc, char *argv[]);
+#ifdef STA_SUPPORT
+static int process_set_get_auth_type(int argc, char *argv[]);
+#endif
+static int process_11h_local_pwr_constraint(int argc, char *argv[]);
+static int process_ht_stream_cfg(int argc, char *argv[]);
+static int process_thermal(int argc, char *argv[]);
+static int process_beacon_interval(int argc, char *argv[]);
+static int process_cwmode(int argc, char *argv[]);
+#ifdef STA_SUPPORT
+static int process_get_signal(int argc, char *argv[]);
+static int process_get_signal_ext(int argc, char *argv[]);
+static int process_signalext_cfg(int argc, char *argv[]);
+#endif
+static int process_inactivity_timeout_ext(int argc, char *argv[]);
+static int process_atim_window(int argc, char *argv[]);
+static int process_11n_amsdu_aggr_ctrl(int argc, char *argv[]);
+static int process_tx_bf_cap_ioctl(int argc, char *argv[]);
+static int process_sdio_clock_ioctl(int argc, char *argv[]);
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+static int process_sdio_mpa_ctrl(int argc, char *argv[]);
+#endif
+static int process_sleep_params(int argc, char *argv[]);
+#if defined(DFS_TESTING_SUPPORT)
+static int process_dfs_testing(int argc, char *argv[]);
+#endif
+static int process_cfp_code(int argc, char *argv[]);
+static int process_set_get_tx_rx_ant(int argc, char *argv[]);
+static int process_sysclock(int argc, char *argv[]);
+static int process_adhoc_aes(int argc, char *argv[]);
+static int process_associate_ssid_bssid(int argc, char *argv[]);
+static int process_tx_bf_cfg(int argc, char *argv[]);
+static int process_wps_cfg(int argc, char *argv[]);
+static int process_port_ctrl(int argc, char *argv[]);
+static int process_bypassed_packet(int argc, char *argv[]);
+static int process_coalescing_status(int argc, char *argv[]);
+/* #ifdef FW_WAKEUP_METHOD */
+static int process_fw_wakeup_method(int argc, char *argv[]);
+/* #endif */
+static int process_sdcmd53rw(int argc, char *argv[]);
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+static int process_cfg_noa_opp_ps(int argc, char *argv[]);
+#endif
+#endif
+static int process_dscpmap(int argc, char *argv[]);
+#ifdef WIFI_DIRECT_SUPPORT
+static int process_miracastcfg(int argc, char *argv[]);
+#endif
+static int process_coex_rx_winsize(int argc, char *argv[]);
+static int process_dfs_repeater(int argc, char *argv[]);
+static int process_txaggrctrl(int argc, char *argv[]);
+static int process_auto_tdls(int argc, char *argv[]);
+static int process_get_sensor_temp(int argc, char *argv[]);
+static int process_chan_graph(int argc, char *argv[]);
+static int process_11k_cfg(int argc, char *argv[]);
+static int process_11k_neighbor_report(int argc, char *argv[]);
+static int process_extend_channel_switch(int argc, char *argv[]);
+#if defined(SDIO_SUSPEND_RESUME)
+static int process_auto_arp(int argc, char *argv[]);
+#endif
+int process_tsf(int argc, char *argv[]);
+static int process_dyn_bw(int argc, char *argv[]);
+static int process_ctrldeauth(int argc, char *argv[]);
+static int process_robustcoex(int argc, char *argv[]);
+
+struct command_node command_list[] = {
+	{"version", process_version},
+	{"bandcfg", process_bandcfg},
+	{"hostcmd", process_hostcmd},
+	{"httxcfg", process_httxcfg},
+	{"htcapinfo", process_htcapinfo},
+	{"addbapara", process_addbapara},
+	{"aggrpriotbl", process_aggrpriotbl},
+	{"addbareject", process_addbareject},
+	{"delba", process_delba},
+	{"rejectaddbareq", process_rejectaddbareq},
+	{"vhtcfg", process_vhtcfg},
+	{"opermodecfg", process_opermodecfg},
+	{"getdatarate", process_datarate},
+	{"txratecfg", process_txratecfg},
+	{"getlog", process_getlog},
+	{"esuppmode", process_esuppmode},
+	{"passphrase", process_passphrase},
+	{"deauth", process_deauth},
+#ifdef UAP_SUPPORT
+	{"getstalist", process_getstalist},
+#endif
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	{"bssrole", process_bssrole},
+#endif
+#endif
+#ifdef STA_SUPPORT
+	{"setuserscan", process_setuserscan},
+	{"getscantable", process_getscantable},
+	{"extcapcfg", process_extcapcfg},
+	{"cancelscan", process_cancelscan},
+#endif
+	{"deepsleep", process_deepsleep},
+	{"ipaddr", process_ipaddr},
+	{"otpuserdata", process_otpuserdata},
+	{"countrycode", process_countrycode},
+	{"tcpackenh", process_tcpackenh},
+#ifdef REASSOCIATION
+	{"assocessid", process_assocessid},
+	{"assocessid_bssid", process_assocessid},
+#endif
+#ifdef STA_SUPPORT
+	{"listeninterval", process_listeninterval},
+	{"psmode", process_psmode},
+#endif
+#ifdef DEBUG_LEVEL1
+	{"drvdbg", process_drvdbg},
+#endif
+	{"hscfg", process_hscfg},
+	{"hssetpara", process_hssetpara},
+	{"wakeupreason", process_wakeupresaon},
+	{"mgmtfilter", process_mgmtfilter},
+	{"scancfg", process_scancfg},
+	{"warmreset", process_warmreset},
+	{"txpowercfg", process_txpowercfg},
+	{"pscfg", process_pscfg},
+	{"bcntimeoutcfg", process_bcntimeoutcfg},
+	{"sleeppd", process_sleeppd},
+	{"txcontrol", process_txcontrol},
+	{"host_tdls_config", process_host_tdls_config},
+	{"tdls_config", process_tdls_config},
+	{"tdls_setinfo", process_tdls_setinfo},
+	{"tdls_discovery", process_tdls_discovery},
+	{"tdls_setup", process_tdls_setup},
+	{"tdls_teardown", process_tdls_teardown},
+	{"tdls_powermode", process_tdls_powermode},
+	{"tdls_link_status", process_tdls_link_status},
+	{"tdls_debug", process_tdls_debug},
+	{"tdls_channel_switch", process_tdls_channel_switch},
+	{"tdls_stop_channel_switch", process_tdls_stop_channel_switch},
+	{"tdls_cs_params", process_tdls_cs_params},
+	{"tdls_disable_cs", process_tdls_disable_channel_switch},
+	{"tdls_idle_time", process_tdls_idle_time},
+	{"dfs_offload", process_dfs_offload_enable},
+	{"customie", process_customie},
+	{"regrdwr", process_regrdwr},
+	{"rdeeprom", process_rdeeprom},
+	{"memrdwr", process_memrdwr},
+	{"sdcmd52rw", process_sdcmd52rw},
+	{"mefcfg", process_mefcfg},
+#ifdef STA_SUPPORT
+	{"arpfilter", process_arpfilter},
+#endif
+	{"cfgdata", process_cfgdata},
+	{"mgmtframetx", process_mgmtframetx},
+	{"mgmtframectrl", process_mgmt_frame_passthrough},
+	{"qconfig", process_qconfig},
+	{"addts", process_addts},
+	{"delts", process_delts},
+	{"ts_status", process_wmm_ts_status},
+	{"qstatus", process_wmm_qstatus},
+	{"qoscfg", process_qos_config},
+	{"macctrl", process_macctrl},
+	{"fwmacaddr", process_fwmacaddr},
+	{"regioncode", process_regioncode},
+	{"offchannel", process_offchannel},
+	{"linkstats", process_linkstats},
+#if defined(STA_SUPPORT)
+	{"pmfcfg", process_pmfcfg},
+#endif
+	{"verext", process_verext},
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+	{"radioctrl", process_radio_ctrl},
+#endif
+	{"wmmcfg", process_wmm_cfg},
+	{"wmmparamcfg", process_wmm_param_config},
+#if defined(STA_SUPPORT)
+	{"11dcfg", process_11d_cfg},
+	{"11dclrtbl", process_11d_clr_tbl},
+#endif
+	{"wwscfg", process_wws_cfg},
+#if defined(REASSOCIATION)
+	{"reassoctrl", process_set_get_reassoc},
+#endif
+	{"txbufcfg", process_txbuf_cfg},
+#ifdef STA_SUPPORT
+	{"authtype", process_set_get_auth_type},
+#endif
+	{"powercons", process_11h_local_pwr_constraint},
+	{"htstreamcfg", process_ht_stream_cfg},
+	{"thermal", process_thermal},
+	{"bcninterval", process_beacon_interval},
+	{"cwmode", process_cwmode},
+#ifdef STA_SUPPORT
+	{"getsignal", process_get_signal},
+	{"getsignalext", process_get_signal_ext},
+	{"getsignalextv2", process_get_signal_ext},
+	{"signalextcfg", process_signalext_cfg},
+#endif
+	{"inactivityto", process_inactivity_timeout_ext},
+	{"atimwindow", process_atim_window},
+	{"amsduaggrctrl", process_11n_amsdu_aggr_ctrl},
+	{"httxbfcap", process_tx_bf_cap_ioctl},
+	{"sdioclock", process_sdio_clock_ioctl},
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	{"mpactrl", process_sdio_mpa_ctrl},
+#endif
+	{"sleepparams", process_sleep_params},
+#if defined(DFS_TESTING_SUPPORT)
+	{"dfstesting", process_dfs_testing},
+#endif
+	{"cfpcode", process_cfp_code},
+	{"antcfg", process_set_get_tx_rx_ant},
+	{"dscpmap", process_dscpmap},
+	{"changraph", process_chan_graph},
+	{"adhocaes", process_adhoc_aes},
+	{"associate", process_associate_ssid_bssid},
+	{"httxbfcfg", process_tx_bf_cfg},
+	{"wpssession", process_wps_cfg},
+	{"port_ctrl", process_port_ctrl},
+	{"pb_bypass", process_bypassed_packet},
+	{"coalesce_status", process_coalescing_status},
+/* #ifdef FW_WAKEUP_METHOD */
+	{"fwwakeupmethod", process_fw_wakeup_method},
+/* #endif */
+	{"sysclock", process_sysclock},
+	{"sdcmd53rw", process_sdcmd53rw},
+	{"mc_cfg", process_multi_chan_cfg},
+	{"mc_policy", process_multi_chan_policy},
+	{"mc_cfg_ext", process_drcs_time_slicing_cfg},
+#ifdef RX_PACKET_COALESCE
+	{"rxpktcoal_cfg", process_rx_pkt_coalesce_cfg},
+#endif
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	{"cfg_noa", process_cfg_noa_opp_ps},
+	{"cfg_opp_ps", process_cfg_noa_opp_ps},
+#endif
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	{"miracastcfg", process_miracastcfg},
+#endif
+	{"coex_rx_winsize", process_coex_rx_winsize},
+	{"dfs_repeater", process_dfs_repeater},
+	{"txaggrctrl", process_txaggrctrl},
+	{"autotdls", process_auto_tdls},
+	{"get_sensor_temp", process_get_sensor_temp},
+	{"11k_enable", process_11k_cfg},
+	{"neighbor_report", process_11k_neighbor_report},
+	{"channel_switch", process_extend_channel_switch},
+#if defined(SDIO_SUSPEND_RESUME)
+	{"auto_arp", process_auto_arp},
+#endif
+	{"tsf", process_tsf},
+	{"dyn_bw", process_dyn_bw},
+	{"ctrldeauth", process_ctrldeauth},
+	{"robustcoex", process_robustcoex},
+};
+
+static char *usage[] = {
+	"Usage: ",
+	"   mlanutl -v  (version)",
+	"   mlanutl <ifname> <cmd> [...]",
+	"   where",
+	"   ifname : wireless network interface name, such as mlanX or uapX",
+	"   cmd :",
+	"         11dcfg",
+	"         11dclrtbl",
+	"         addbapara",
+	"         addbareject",
+	"         addts",
+	"         adhocaes",
+	"         aggrpriotbl",
+	"         amsduaggrctrl",
+	"         antcfg",
+#ifdef STA_SUPPORT
+	"         arpfilter",
+#endif
+#ifdef REASSOCIATION
+	"         assocessid",
+	"         assocessid_bssid",
+#endif
+	"         associate",
+	"         atimwindow",
+	"         authtype",
+	"         autotdls",
+	"         bandcfg",
+	"         bcninterval",
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	"         bssrole",
+#endif
+#endif
+	"         cfgdata",
+	"         cfpcode",
+	"         changraph",
+	"         coex_rx_winsize",
+	"         countrycode",
+	"         customie",
+	"         deauth",
+	"         deepsleep",
+	"         delba",
+	"         delts",
+#if defined(DFS_TESTING_SUPPORT)
+	"         dfstesting",
+#endif
+	"         dfs_repeater",
+#ifdef DEBUG_LEVEL1
+	"         drvdbg",
+#endif
+	"         dscpmap",
+	"         esuppmode",
+#ifdef STA_SUPPORT
+	"         extcapcfg",
+	"         cancelscan",
+#endif
+	"         fwmacaddr",
+/* #ifdef FW_WAKEUP_METHOD */
+	"         fwwakeupmethod",
+/* #endif */
+	"         getdatarate",
+	"         getlog",
+#ifdef STA_SUPPORT
+	"         getscantable",
+#endif
+	"         getsignal",
+#ifdef UAP_SUPPORT
+	"         getstalist",
+#endif
+	"         hostcmd",
+	"         hscfg",
+	"         hssetpara",
+	"         mgmtfilter",
+	"         htcapinfo",
+	"         htstreamcfg",
+#ifdef STA_SUPPORT
+	"         signalextcfg",
+	"         getsignalext",
+	"         getsignalextv2",
+#endif
+	"         httxbfcap",
+	"         httxbfcfg",
+	"         httxcfg",
+	"         inactivityto",
+	"         ipaddr",
+	"         linkstats",
+#ifdef STA_SUPPORT
+	"         listeninterval",
+#endif
+	"         macctrl",
+	"         mefcfg",
+	"         memrdwr",
+#ifdef WIFI_DIRECT_SUPPORT
+	"         miracastcfg",
+#endif
+	"         mgmtframectrl",
+	"         mgmtframetx",
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	"         mpactrl",
+#endif
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	"         cfg_noa",
+	"         cfg_opp_ps",
+#endif
+#endif
+	"         offchannel",
+	"         otpuserdata",
+	"         passphrase",
+	"         pb_bypass",
+#if defined(STA_SUPPORT)
+	"         pmfcfg",
+#endif
+	"         port_ctrl",
+	"         powercons",
+	"         pscfg",
+#ifdef STA_SUPPORT
+	"         psmode",
+#endif
+	"         qconfig",
+	"         qoscfg",
+	"         qstatus",
+#ifdef STA_WEXT
+	"         radioctrl",
+#endif
+	"         rdeeprom",
+#if defined(REASSOCIATION)
+	"         reassoctrl",
+#endif
+	"         regioncode",
+	"         regrdwr",
+	"         rejectaddbareq",
+	"         scancfg",
+	"         sdcmd52rw",
+	"         sdcmd53rw",
+	"         sdioclock",
+#ifdef STA_SUPPORT
+	"         setuserscan",
+#endif
+	"         sleepparams",
+	"         sleeppd",
+	"         sysclock",
+	"         tcpackenh",
+	"         tdls_idle_time",
+	"         tdls_channel_switch",
+	"         tdls_config",
+	"         tdls_cs_params",
+	"         tdls_debug",
+	"         tdls_disable_cs",
+	"         tdls_discovery",
+	"         tdls_link_status",
+	"         tdls_powermode",
+	"         tdls_setinfo",
+	"         tdls_setup",
+	"         tdls_stop_channel_switch",
+	"         tdls_teardown",
+	"         thermal",
+	"         ts_status",
+	"         tsf",
+	"         txaggrctrl",
+	"         txbufcfg",
+	"         txcontrol",
+	"         txpowercfg",
+	"         txratecfg",
+	"         verext",
+	"         version",
+	"         vhtcfg",
+	"         opermodecfg",
+	"         wakeupreason",
+	"         warmreset",
+	"         wmmcfg",
+	"         wmmparamcfg",
+	"         wpssession",
+	"         wwscfg",
+	"         mc_cfg",
+	"         mc_policy",
+	"         mc_cfg_ext",
+#ifdef RX_PACKET_COALESCE
+	"         rxpktcoal_cfg",
+#endif
+	"         get_sensor_temp",
+	"         11k_enable",
+	"         neighbor_report",
+	"         channel_switch",
+	"         dfs_offload",
+
+	"         cwmode",
+	"         dyn_bw",
+	"         ctrldeauth",
+	"         robustcoex",
+};
+
+/** Socket */
+t_s32 sockfd;
+/** Device name */
+char dev_name[IFNAMSIZ + 1];
+#define HOSTCMD "hostcmd"
+
+#define BSSID_FILTER 1
+#define SSID_FILTER 2
+/********************************************************
+			Global Variables
+********************************************************/
+
+int setuserscan_filter = 0;
+int num_ssid_filter = 0;
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *    @brief isdigit for String.
+ *
+ *    @param x            Char string
+ *    @return             MLAN_STATUS_FAILURE for non-digit.
+ *                        MLAN_STATUS_SUCCESS for digit
+ */
+static int
+ISDIGIT(char *x)
+{
+	unsigned int i;
+	for (i = 0; i < strlen(x); i++)
+		if (isdigit(x[i]) == 0)
+			return MLAN_STATUS_FAILURE;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * Check of decimal or hex string
+ * @param   num string
+ */
+#define IS_HEX_OR_DIGIT(num) \
+    (strncasecmp("0x", (num), 2)?ISDIGIT((num)):ishexstring((num)))
+
+/**
+ *  @brief Convert char to hex integer
+ *
+ *  @param chr      Char to convert
+ *  @return         Hex integer or 0
+ */
+int
+hexval(t_s32 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 Hump hex data
+ *
+ *  @param prompt   A pointer prompt buffer
+ *  @param p        A pointer to data buffer
+ *  @param len      The len of data buffer
+ *  @param delim    Delim char
+ *  @return         Hex integer
+ */
+t_void
+hexdump(char *prompt, t_void *p, t_s32 len, char delim)
+{
+	t_s32 i;
+	t_u8 *s = p;
+
+	if (prompt) {
+		printf("%s: len=%d\n", prompt, (int)len);
+	}
+	for (i = 0; i < len; i++) {
+		if (i != len - 1)
+			printf("%02x%c", *s++, delim);
+		else
+			printf("%02x\n", *s);
+		if ((i + 1) % 16 == 0)
+			printf("\n");
+	}
+	printf("\n");
+}
+
+/**
+ *  @brief Convert char to hex integer
+ *
+ *  @param chr      Char
+ *  @return         Hex integer
+ */
+t_u8
+hexc2bin(char chr)
+{
+	if (chr >= '0' && chr <= '9')
+		chr -= '0';
+	else if (chr >= 'A' && chr <= 'F')
+		chr -= ('A' - 10);
+	else if (chr >= 'a' && chr <= 'f')
+		chr -= ('a' - 10);
+
+	return chr;
+}
+
+/**
+ *  @brief Convert string to hex integer
+ *
+ *  @param s        A pointer string buffer
+ *  @return         Hex integer
+ */
+t_u32
+a2hex(char *s)
+{
+	t_u32 val = 0;
+
+	if (!strncasecmp("0x", s, 2)) {
+		s += 2;
+	}
+
+	while (*s && isxdigit(*s)) {
+		val = (val << 4) + hexc2bin(*s++);
+	}
+
+	return val;
+}
+
+/*
+ *  @brief Convert String to integer
+ *
+ *  @param value    A pointer to string
+ *  @return         Integer
+ */
+t_u32
+a2hex_or_atoi(char *value)
+{
+	if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) {
+		return a2hex(value + 2);
+	} else {
+		return (t_u32)atoi(value);
+	}
+}
+
+/**
+ *  @brief Convert string to hex
+ *
+ *  @param ptr      A pointer to data buffer
+ *  @param chr      A pointer to return integer
+ *  @return         A pointer to next data field
+ */
+char *
+convert2hex(char *ptr, t_u8 *chr)
+{
+	t_u8 val;
+
+	for (val = 0; *ptr && isxdigit(*ptr); ptr++) {
+		val = (val * 16) + hexval(*ptr);
+	}
+
+	*chr = val;
+
+	return ptr;
+}
+
+/**
+ *  @brief Check the Hex String
+ *  @param s  A pointer to the string
+ *  @return   MLAN_STATUS_SUCCESS --HexString, MLAN_STATUS_FAILURE --not HexString
+ */
+int
+ishexstring(char *s)
+{
+	int ret = MLAN_STATUS_FAILURE;
+	t_s32 tmp;
+
+	if (!strncasecmp("0x", s, 2)) {
+		s += 2;
+	}
+	while (*s) {
+		tmp = toupper(*s);
+		if (((tmp >= 'A') && (tmp <= 'F')) ||
+		    ((tmp >= '0') && (tmp <= '9'))) {
+			ret = MLAN_STATUS_SUCCESS;
+		} else {
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		s++;
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief Convert String to Integer
+ *  @param buf      A pointer to the string
+ *  @return         Integer
+ */
+int
+atoval(char *buf)
+{
+	if (!strncasecmp(buf, "0x", 2))
+		return a2hex(buf + 2);
+	else if (!ishexstring(buf))
+		return a2hex(buf);
+	else
+		return atoi(buf);
+}
+
+/**
+ *  @brief Display usage
+ *
+ *  @return       NA
+ */
+static t_void
+display_usage(t_void)
+{
+	t_u32 i;
+	for (i = 0; i < NELEMENTS(usage); i++)
+		fprintf(stderr, "%s\n", usage[i]);
+}
+
+/**
+ *  @brief Find and execute command
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS for success, otherwise failure
+ */
+static int
+process_command(int argc, char *argv[])
+{
+	int i = 0, ret = MLAN_STATUS_NOTFOUND;
+	struct command_node *node = NULL;
+
+	for (i = 0; i < (int)NELEMENTS(command_list); i++) {
+		node = &command_list[i];
+		if (!strcasecmp(node->name, argv[2])) {
+			ret = node->handler(argc, argv);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * @brief Converts a string to hex value
+ *
+ * @param str      A pointer to the string
+ * @param raw      A pointer to the raw data buffer
+ * @return         Number of bytes read
+ **/
+int
+string2raw(char *str, unsigned char *raw)
+{
+	int len = (strlen(str) + 1) / 2;
+
+	do {
+		if (!isxdigit(*str)) {
+			return -1;
+		}
+		*str = toupper(*str);
+		*raw = CHAR2INT(*str) << 4;
+		++str;
+		*str = toupper(*str);
+		if (*str == '\0')
+			break;
+		*raw |= CHAR2INT(*str);
+		++raw;
+	} while (*++str != '\0');
+	return len;
+}
+
+/**
+ *  @brief Prepare command buffer
+ *  @param buffer   Command buffer to be filled
+ *  @param cmd      Command id
+ *  @param num      Number of arguments
+ *  @param args     Arguments list
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static int
+prepare_buffer(t_u8 *buffer, char *cmd, t_u32 num, char *args[])
+{
+	t_u8 *pos = NULL;
+	unsigned int i = 0;
+
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Flag it for our use */
+	pos = buffer;
+	strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL));
+	pos += (strlen(CMD_MARVELL));
+
+	/* Insert command */
+	strncpy((char *)pos, (char *)cmd, strlen(cmd));
+	pos += (strlen(cmd));
+
+	/* Insert arguments */
+	for (i = 0; i < num; i++) {
+		strncpy((char *)pos, args[i], strlen(args[i]));
+		pos += strlen(args[i]);
+		if (i < (num - 1)) {
+			strncpy((char *)pos, " ", strlen(" "));
+			pos += 1;
+		}
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Set Robustcoex gpiocfg
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+
+static int
+process_robustcoex(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+
+	if (argc <= 4) {
+		printf("Err: Invalid number of arguments\n");
+		printf("Usage: ./mlanutl <interface> robustcoex [gpiocfg] [value]\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if (strcmp(argv[3], "gpiocfg") == 0) {
+		if (argc != 7 && argc != 5) {
+			printf("ERR: Invalid number of arguments\n");
+			printf("Usage: ./mlanutl <interface> robustcoex gpiocfg [Enable][Gpionum][Gpiopolarity]\n");
+			printf("Usage: ./mlanutl <interface> robustcoex gpiocfg [Disable]\n");
+			return MLAN_STATUS_FAILURE;
+		}
+	} else {
+		printf("ERR: Invalid arguments\n");
+		printf("Usage: ./mlanutl <interface> robustcoex [gpiocfg][value]\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: robustcoex fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get one line from the File
+ *
+ *  @param fp       File handler
+ *  @param str      Storage location for data.
+ *  @param size     Maximum number of characters to read.
+ *  @param lineno   A pointer to return current line number
+ *  @return         returns string or NULL
+ */
+char *
+mlan_config_get_line(FILE * fp, char *str, t_s32 size, int *lineno)
+{
+	char *start, *end;
+	int out, next_line;
+
+	if (!fp || !str)
+		return NULL;
+
+	do {
+read_line:
+		if (!fgets(str, size, fp))
+			break;
+		start = str;
+		start[size - 1] = '\0';
+		end = start + strlen(str);
+		(*lineno)++;
+
+		out = 1;
+		while (out && (start < end)) {
+			next_line = 0;
+			/* Remove empty lines and lines starting with # */
+			switch (start[0]) {
+			case ' ':	/* White space */
+			case '\t':	/* Tab */
+				start++;
+				break;
+			case '#':
+			case '\n':
+			case '\0':
+				next_line = 1;
+				break;
+			case '\r':
+				if (start[1] == '\n')
+					next_line = 1;
+				else
+					start++;
+				break;
+			default:
+				out = 0;
+				break;
+			}
+			if (next_line)
+				goto read_line;
+		}
+
+		/* Remove # comments unless they are within a double quoted
+		 * string. Remove trailing white space. */
+		end = strstr(start, "\"");
+		if (end) {
+			end = strstr(end + 1, "\"");
+			if (!end)
+				end = start;
+		} else
+			end = start;
+
+		end = strstr(end + 1, "#");
+		if (end)
+			*end-- = '\0';
+		else
+			end = start + strlen(start) - 1;
+
+		out = 1;
+		while (out && (start < end)) {
+			switch (*end) {
+			case ' ':	/* White space */
+			case '\t':	/* Tab */
+			case '\n':
+			case '\r':
+				*end = '\0';
+				end--;
+				break;
+			default:
+				out = 0;
+				break;
+			}
+		}
+
+		if (start == '\0')
+			continue;
+
+		return start;
+	} while (1);
+
+	return NULL;
+}
+
+/**
+ *  @brief          Parse function for a configuration line
+ *
+ *  @param s        Storage buffer for data
+ *  @param size     Maximum size of data
+ *  @param stream   File stream pointer
+ *  @param line     Pointer to current line within the file
+ *  @param _pos     Output string or NULL
+ *  @return         String or NULL
+ */
+static char *
+config_get_line(char *s, int size, FILE * stream, int *line, char **_pos)
+{
+	*_pos = mlan_config_get_line(stream, s, size, line);
+	return *_pos;
+}
+
+/**
+ *  @brief Converts colon separated MAC address to hex value
+ *
+ *  @param mac      A pointer to the colon separated MAC string
+ *  @param raw      A pointer to the hex data buffer
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *                  MAC_BROADCAST   - if broadcast mac
+ *                  MAC_MULTICAST   - if multicast mac
+ */
+static int
+mac2raw(char *mac, t_u8 *raw)
+{
+	unsigned int temp_raw[ETH_ALEN];
+	int num_tokens = 0;
+	int i;
+
+	if (strlen(mac) != ((2 * ETH_ALEN) + (ETH_ALEN - 1))) {
+		return MLAN_STATUS_FAILURE;
+	}
+	num_tokens = sscanf(mac, "%2x:%2x:%2x:%2x:%2x:%2x",
+			    temp_raw + 0, temp_raw + 1, temp_raw + 2,
+			    temp_raw + 3, temp_raw + 4, temp_raw + 5);
+	if (num_tokens != ETH_ALEN) {
+		return MLAN_STATUS_FAILURE;
+	}
+	for (i = 0; i < num_tokens; i++)
+		raw[i] = (t_u8)temp_raw[i];
+
+	if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) {
+		return MAC_BROADCAST;
+	} else if (raw[0] & 0x01) {
+		return MAC_MULTICAST;
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Parses a command line
+ *
+ *  @param line     The line to parse
+ *  @param args     Pointer to the argument buffer to be filled in
+ *  @return         Number of arguments in the line or EOF
+ */
+static int
+parse_line(char *line, char *args[])
+{
+	int arg_num = 0;
+	int is_start = 0;
+	int is_quote = 0;
+	int length = 0;
+	int i = 0;
+
+	arg_num = 0;
+	length = strlen(line);
+	/* Process line */
+
+	/* Find number of arguments */
+	is_start = 0;
+	is_quote = 0;
+	for (i = 0; i < length; i++) {
+		/* Ignore leading spaces */
+		if (is_start == 0) {
+			if (line[i] == ' ') {
+				continue;
+			} else if (line[i] == '\t') {
+				continue;
+			} else if (line[i] == '\n') {
+				break;
+			} else {
+				is_start = 1;
+				args[arg_num] = &line[i];
+				arg_num++;
+			}
+		}
+		if (is_start == 1) {
+			/* Ignore comments */
+			if (line[i] == '#') {
+				if (is_quote == 0) {
+					line[i] = '\0';
+					arg_num--;
+				}
+				break;
+			}
+			/* Separate by '=' */
+			if (line[i] == '=') {
+				line[i] = '\0';
+				is_start = 0;
+				continue;
+			}
+			/* Separate by ',' */
+			if (line[i] == ',') {
+				line[i] = '\0';
+				is_start = 0;
+				continue;
+			}
+			/* Change ',' to ' ', but not inside quotes */
+			if ((line[i] == ',') && (is_quote == 0)) {
+				line[i] = ' ';
+				continue;
+			}
+		}
+		/* Remove newlines */
+		if (line[i] == '\n') {
+			line[i] = '\0';
+		}
+		/* Check for quotes */
+		if (line[i] == '"') {
+			is_quote = (is_quote == 1) ? 0 : 1;
+			continue;
+		}
+		if (((line[i] == ' ') || (line[i] == '\t')) && (is_quote == 0)) {
+			line[i] = '\0';
+			is_start = 0;
+			continue;
+		}
+	}
+	return arg_num;
+}
+
+/**
+ *  @brief Process version
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_version(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: version fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("Version string received: %s\n", buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process band configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_bandcfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	int i;
+	struct eth_priv_cmd *cmd = NULL;
+	struct eth_priv_bandcfg *bandcfg = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: bandcfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	bandcfg = (struct eth_priv_bandcfg *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("Band Configuration:\n");
+		printf("  Infra Band: %d (", (int)bandcfg->config_bands);
+		for (i = 0; i < 7; i++) {
+			if ((bandcfg->config_bands >> i) & 0x1)
+				printf(" %s", band[i]);
+		}
+		printf(" )\n");
+		printf("  Adhoc Start Band: %d (",
+		       (int)bandcfg->adhoc_start_band);
+		for (i = 0; i < 7; i++) {
+			if ((bandcfg->adhoc_start_band >> i) & 0x1)
+				printf(" %s", band[i]);
+		}
+		printf(" )\n");
+		printf("  Adhoc Start Channel: %d\n",
+		       (int)bandcfg->adhoc_channel);
+		printf("  Adhoc Band Width: %d (%s)\n",
+		       (int)bandcfg->adhoc_chan_bandwidth,
+		       adhoc_bw[bandcfg->adhoc_chan_bandwidth]);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief get hostcmd data
+ *
+ *  @param ln           A pointer to line number
+ *  @param buf          A pointer to hostcmd data
+ *  @param size         A pointer to the return size of hostcmd buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static int
+mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
+{
+	t_s32 errors = 0, i;
+	char line[256], *pos, *pos1, *pos2, *pos3;
+	t_u16 len;
+
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
+		(*ln)++;
+		if (strcmp(pos, "}") == 0) {
+			break;
+		}
+
+		pos1 = strchr(pos, ':');
+		if (pos1 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos1++ = '\0';
+
+		pos2 = strchr(pos1, '=');
+		if (pos2 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos2++ = '\0';
+
+		len = a2hex_or_atoi(pos1);
+		if (len < 1 || len > BUFFER_LENGTH) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+
+		*size += len;
+
+		if (*pos2 == '"') {
+			pos2++;
+			pos3 = strchr(pos2, '"');
+			if (pos3 == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln,
+				       pos);
+				errors++;
+				continue;
+			}
+			*pos3 = '\0';
+			memset(buf, 0, len);
+			memmove(buf, pos2, MIN(strlen(pos2), len));
+			buf += len;
+		} else if (*pos2 == '\'') {
+			pos2++;
+			pos3 = strchr(pos2, '\'');
+			if (pos3 == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln,
+				       pos);
+				errors++;
+				continue;
+			}
+			*pos3 = ',';
+			for (i = 0; i < len; i++) {
+				pos3 = strchr(pos2, ',');
+				if (pos3 != NULL) {
+					*pos3 = '\0';
+					*buf++ = (t_u8)a2hex_or_atoi(pos2);
+					pos2 = pos3 + 1;
+				} else
+					*buf++ = 0;
+			}
+		} else if (*pos2 == '{') {
+			t_u16 tlvlen = 0, tmp_tlvlen;
+			mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen);
+			tmp_tlvlen = tlvlen;
+			while (len--) {
+				*buf++ = (t_u8)(tmp_tlvlen & 0xff);
+				tmp_tlvlen >>= 8;
+			}
+			*size += tlvlen;
+			buf += tlvlen;
+		} else {
+			t_u32 value = a2hex_or_atoi(pos2);
+			while (len--) {
+				*buf++ = (t_u8)(value & 0xff);
+				value >>= 8;
+			}
+		}
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Prepare host-command buffer
+ *  @param fp       File handler
+ *  @param cmd_name Command name
+ *  @param buf      A pointer to comand buffer
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf)
+{
+	char line[256], cmdname[256], *pos, cmdcode[10];
+	HostCmd_DS_GEN *hostcmd;
+	t_u32 hostcmd_size = 0;
+	int ln = 0;
+	int cmdname_found = 0, cmdcode_found = 0;
+
+	hostcmd = (HostCmd_DS_GEN *)(buf + sizeof(t_u32));
+	hostcmd->command = 0xffff;
+
+	snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name);
+	cmdname_found = 0;
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, cmdname) == 0) {
+			cmdname_found = 1;
+			snprintf(cmdcode, sizeof(cmdcode), "CmdCode=");
+			cmdcode_found = 0;
+			while ((pos =
+				mlan_config_get_line(fp, line, sizeof(line),
+						     &ln))) {
+				if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) {
+					cmdcode_found = 1;
+					hostcmd->command =
+						a2hex_or_atoi(pos +
+							      strlen(cmdcode));
+					hostcmd->size = S_DS_GEN;
+					mlan_get_hostcmd_data(fp, &ln,
+							      buf +
+							      sizeof(t_u32) +
+							      hostcmd->size,
+							      &hostcmd->size);
+					break;
+				}
+			}
+			if (!cmdcode_found) {
+				fprintf(stderr,
+					"mlanutl: CmdCode not found in conf file\n");
+				return MLAN_STATUS_FAILURE;
+			}
+			break;
+		}
+	}
+
+	if (!cmdname_found) {
+		fprintf(stderr,
+			"mlanutl: cmdname '%s' is not found in conf file\n",
+			cmd_name);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	hostcmd->command = cpu_to_le16(hostcmd->command);
+	hostcmd->size = cpu_to_le16(hostcmd->size);
+
+	hostcmd_size = (t_u32)(hostcmd->size);
+	memcpy(buf, (t_u8 *)&hostcmd_size, sizeof(t_u32));
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Prints a MAC address in colon separated form from raw data
+ *
+ *  @param raw      A pointer to the hex data buffer
+ *  @return         N/A
+ */
+void
+print_mac(t_u8 *raw)
+{
+	printf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)raw[0],
+	       (unsigned int)raw[1], (unsigned int)raw[2], (unsigned int)raw[3],
+	       (unsigned int)raw[4], (unsigned int)raw[5]);
+	return;
+}
+
+/**
+ *  @brief Process host_cmd response
+ *  @param cmd_name Command name
+ *  @param buf      A pointer to the response buffer
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_host_cmd_resp(char *cmd_name, t_u8 *buf)
+{
+	t_u32 hostcmd_size = 0;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	buf += strlen(CMD_MARVELL) + strlen(cmd_name);
+	memcpy((t_u8 *)&hostcmd_size, buf, sizeof(t_u32));
+	buf += sizeof(t_u32);
+
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	hostcmd->command = le16_to_cpu(hostcmd->command);
+	hostcmd->size = le16_to_cpu(hostcmd->size);
+	hostcmd->seq_num = le16_to_cpu(hostcmd->seq_num);
+	hostcmd->result = le16_to_cpu(hostcmd->result);
+
+	hostcmd->command &= ~HostCmd_RET_BIT;
+	if (!hostcmd->result) {
+		switch (hostcmd->command) {
+		case HostCmd_CMD_CFG_DATA:
+			{
+				HostCmd_DS_802_11_CFG_DATA *pstcfgData =
+					(HostCmd_DS_802_11_CFG_DATA *)(buf +
+								       S_DS_GEN);
+				pstcfgData->data_len =
+					le16_to_cpu(pstcfgData->data_len);
+				pstcfgData->action =
+					le16_to_cpu(pstcfgData->action);
+
+				if (pstcfgData->action == HostCmd_ACT_GEN_GET) {
+					hexdump("cfgdata", pstcfgData->data,
+						pstcfgData->data_len, ' ');
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+			{
+				mlan_ioctl_11h_tpc_resp *tpcIoctlResp =
+					(mlan_ioctl_11h_tpc_resp *)(buf +
+								    S_DS_GEN);
+				if (tpcIoctlResp->status_code == 0) {
+					printf("tpcrequest:  txPower(%d), linkMargin(%d), rssi(%d)\n", tpcIoctlResp->tx_power, tpcIoctlResp->link_margin, tpcIoctlResp->rssi);
+				} else {
+					printf("tpcrequest:  failure, status = %d\n", tpcIoctlResp->status_code);
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_CRYPTO:
+			{
+				t_u16 alg =
+					le16_to_cpu((t_u16)
+						    *(buf + S_DS_GEN +
+						      sizeof(t_u16)));
+				if (alg != CIPHER_TEST_AES_CCM) {
+					HostCmd_DS_802_11_CRYPTO *cmd =
+						(HostCmd_DS_802_11_CRYPTO *)(buf
+									     +
+									     S_DS_GEN);
+					cmd->encdec = le16_to_cpu(cmd->encdec);
+					cmd->algorithm =
+						le16_to_cpu(cmd->algorithm);
+					cmd->key_IV_length =
+						le16_to_cpu(cmd->key_IV_length);
+					cmd->key_length =
+						le16_to_cpu(cmd->key_length);
+					cmd->data.header.type =
+						le16_to_cpu(cmd->data.header.
+							    type);
+					cmd->data.header.len =
+						le16_to_cpu(cmd->data.header.
+							    len);
+
+					printf("crypto_result: encdec=%d algorithm=%d,KeyIVLen=%d," " KeyLen=%d,dataLen=%d\n", cmd->encdec, cmd->algorithm, cmd->key_IV_length, cmd->key_length, cmd->data.header.len);
+					hexdump("KeyIV", cmd->keyIV,
+						cmd->key_IV_length, ' ');
+					hexdump("Key", cmd->key,
+						cmd->key_length, ' ');
+					hexdump("Data", cmd->data.data,
+						cmd->data.header.len, ' ');
+				} else {
+					HostCmd_DS_802_11_CRYPTO_AES_CCM
+						*cmd_aes_ccm =
+						(HostCmd_DS_802_11_CRYPTO_AES_CCM
+						 *)(buf + S_DS_GEN);
+
+					cmd_aes_ccm->encdec
+						=
+						le16_to_cpu(cmd_aes_ccm->
+							    encdec);
+					cmd_aes_ccm->algorithm =
+						le16_to_cpu(cmd_aes_ccm->
+							    algorithm);
+					cmd_aes_ccm->key_length =
+						le16_to_cpu(cmd_aes_ccm->
+							    key_length);
+					cmd_aes_ccm->nonce_length =
+						le16_to_cpu(cmd_aes_ccm->
+							    nonce_length);
+					cmd_aes_ccm->AAD_length =
+						le16_to_cpu(cmd_aes_ccm->
+							    AAD_length);
+					cmd_aes_ccm->data.header.type =
+						le16_to_cpu(cmd_aes_ccm->data.
+							    header.type);
+					cmd_aes_ccm->data.header.len =
+						le16_to_cpu(cmd_aes_ccm->data.
+							    header.len);
+
+					printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_aes_ccm->encdec, cmd_aes_ccm->algorithm, cmd_aes_ccm->key_length, cmd_aes_ccm->nonce_length, cmd_aes_ccm->AAD_length, cmd_aes_ccm->data.header.len);
+
+					hexdump("Key", cmd_aes_ccm->key,
+						cmd_aes_ccm->key_length, ' ');
+					hexdump("Nonce", cmd_aes_ccm->nonce,
+						cmd_aes_ccm->nonce_length, ' ');
+					hexdump("AAD", cmd_aes_ccm->AAD,
+						cmd_aes_ccm->AAD_length, ' ');
+					hexdump("Data", cmd_aes_ccm->data.data,
+						cmd_aes_ccm->data.header.len,
+						' ');
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_AUTO_TX:
+			{
+				HostCmd_DS_802_11_AUTO_TX *at =
+					(HostCmd_DS_802_11_AUTO_TX *)(buf +
+								      S_DS_GEN);
+
+				if (le16_to_cpu(at->action) ==
+				    HostCmd_ACT_GEN_GET) {
+					if (S_DS_GEN + sizeof(at->action) ==
+					    hostcmd->size) {
+						printf("auto_tx not configured\n");
+
+					} else {
+						MrvlIEtypesHeader_t *header =
+							&at->auto_tx.header;
+
+						header->type =
+							le16_to_cpu(header->
+								    type);
+						header->len =
+							le16_to_cpu(header->
+								    len);
+
+						if ((S_DS_GEN +
+						     sizeof(at->action)
+						     +
+						     sizeof(MrvlIEtypesHeader_t)
+						     + header->len ==
+						     hostcmd->size) &&
+						    (header->type ==
+						     TLV_TYPE_AUTO_TX)) {
+
+							AutoTx_MacFrame_t *atmf
+								=
+								&at->auto_tx.
+								auto_tx_mac_frame;
+
+							printf("Interval: %d second(s)\n", le16_to_cpu(atmf->interval));
+							printf("Priority: %#x\n", atmf->priority);
+							printf("Frame Length: %d\n", le16_to_cpu(atmf->frame_len));
+							printf("Dest Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->dest_mac_addr[0], atmf->dest_mac_addr[1], atmf->dest_mac_addr[2], atmf->dest_mac_addr[3], atmf->dest_mac_addr[4], atmf->dest_mac_addr[5]);
+							printf("Src Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->src_mac_addr[0], atmf->src_mac_addr[1], atmf->src_mac_addr[2], atmf->src_mac_addr[3], atmf->src_mac_addr[4], atmf->src_mac_addr[5]);
+
+							hexdump("Frame Payload",
+								atmf->payload,
+								le16_to_cpu
+								(atmf->
+								 frame_len)
+								-
+								MLAN_MAC_ADDR_LENGTH
+								* 2, ' ');
+						} else {
+							printf("incorrect auto_tx command response\n");
+						}
+					}
+				}
+				break;
+			}
+		case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
+			{
+				HostCmd_DS_802_11_SUBSCRIBE_EVENT *se =
+					(HostCmd_DS_802_11_SUBSCRIBE_EVENT
+					 *)(buf + S_DS_GEN);
+				if (le16_to_cpu(se->action) ==
+				    HostCmd_ACT_GEN_GET) {
+					int len =
+						S_DS_GEN +
+						sizeof
+						(HostCmd_DS_802_11_SUBSCRIBE_EVENT);
+					printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n");
+					while (len < hostcmd->size) {
+						MrvlIEtypesHeader_t *header =
+							(MrvlIEtypesHeader_t
+							 *)(buf + len);
+						switch (le16_to_cpu
+							(header->type)) {
+						case TLV_TYPE_RSSI_LOW:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*low_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0001) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_SNR_LOW:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*low_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0002) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_FAILCOUNT:
+							{
+								MrvlIEtypes_FailureCount_t
+									*failure_count
+									=
+									(MrvlIEtypes_FailureCount_t
+									 *)(buf
+									    +
+									    len);
+								printf("Failure Count\t%d\t%d\t%s\n", failure_count->fail_value, failure_count->fail_freq, (le16_to_cpu(se->events) & 0x0004) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_BCNMISS:
+							{
+								MrvlIEtypes_BeaconsMissed_t
+									*bcn_missed
+									=
+									(MrvlIEtypes_BeaconsMissed_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon Missed\t%d\tN/A\t%s\n", bcn_missed->beacon_missed, (le16_to_cpu(se->events) & 0x0008) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_RSSI_HIGH:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*high_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Bcn High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0010) ? "yes" : "no");
+								break;
+							}
+
+						case TLV_TYPE_SNR_HIGH:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*high_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Beacon High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0020) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_RSSI_LOW_DATA:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*low_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0040) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_SNR_LOW_DATA:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*low_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0080) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_RSSI_HIGH_DATA:
+							{
+								MrvlIEtypes_RssiThreshold_t
+									*high_rssi
+									=
+									(MrvlIEtypes_RssiThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0100) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_SNR_HIGH_DATA:
+							{
+								MrvlIEtypes_SnrThreshold_t
+									*high_snr
+									=
+									(MrvlIEtypes_SnrThreshold_t
+									 *)(buf
+									    +
+									    len);
+								printf("Data High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0200) ? "yes" : "no");
+								break;
+							}
+						case TLV_TYPE_LINK_QUALITY:
+							{
+								MrvlIEtypes_LinkQuality_t
+									*link_qual
+									=
+									(MrvlIEtypes_LinkQuality_t
+									 *)(buf
+									    +
+									    len);
+								printf("Link Quality Parameters:\n");
+								printf("------------------------\n");
+								printf("Link Quality Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0400) ? "yes" : "no");
+								printf("Link SNR Threshold   = %d\n", le16_to_cpu(link_qual->link_SNR_thrs));
+								printf("Link SNR Frequency   = %d\n", le16_to_cpu(link_qual->link_SNR_freq));
+								printf("Min Rate Value       = %d\n", le16_to_cpu(link_qual->min_rate_val));
+								printf("Min Rate Frequency   = %d\n", le16_to_cpu(link_qual->min_rate_freq));
+								printf("Tx Latency Value     = %d\n", le32_to_cpu(link_qual->tx_latency_val));
+								printf("Tx Latency Threshold = %d\n", le32_to_cpu(link_qual->tx_latency_thrs));
+
+								break;
+							}
+						case TLV_TYPE_PRE_BEACON_LOST:
+							{
+								MrvlIEtypes_PreBeaconLost_t
+									*pre_bcn_lost
+									=
+									(MrvlIEtypes_PreBeaconLost_t
+									 *)(buf
+									    +
+									    len);
+								printf("------------------------\n");
+								printf("Pre-Beacon Lost Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0800) ? "yes" : "no");
+								printf("Pre-Beacon Lost: %d\n", pre_bcn_lost->pre_beacon_lost);
+								break;
+							}
+						default:
+							printf("Unknown subscribed event TLV Type=%#x," " Len=%d\n", le16_to_cpu(header->type), le16_to_cpu(header->len));
+							break;
+						}
+
+						len += (sizeof
+							(MrvlIEtypesHeader_t)
+							+
+							le16_to_cpu(header->
+								    len));
+					}
+				}
+				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:
+			{
+				HostCmd_DS_REG *preg =
+					(HostCmd_DS_REG *)(buf + S_DS_GEN);
+				preg->action = le16_to_cpu(preg->action);
+				if (preg->action == HostCmd_ACT_GEN_GET) {
+					preg->value = le32_to_cpu(preg->value);
+					printf("value = 0x%08x\n", preg->value);
+				}
+				break;
+			}
+		case HostCmd_CMD_MEM_ACCESS:
+			{
+				HostCmd_DS_MEM *pmem =
+					(HostCmd_DS_MEM *)(buf + S_DS_GEN);
+				pmem->action = le16_to_cpu(pmem->action);
+				if (pmem->action == HostCmd_ACT_GEN_GET) {
+					pmem->value = le32_to_cpu(pmem->value);
+					printf("value = 0x%08x\n", pmem->value);
+				}
+				break;
+			}
+		case HostCmd_CMD_LINK_STATS_SUMMARY:
+			{
+				HostCmd_DS_LINK_STATS_SUMMARY *linkstats =
+					(HostCmd_DS_LINK_STATS_SUMMARY *)(buf +
+									  S_DS_GEN);
+				/* GET operation */
+				printf("Link Statistics: \n");
+				/* format */
+				printf("Duration:   %u\n",
+				       (int)le32_to_cpu(linkstats->
+							timeSinceLastQuery_ms));
+
+				printf("Beacon count:     %u\n",
+				       le16_to_cpu(linkstats->bcnCnt));
+				printf("Beacon missing:   %u\n",
+				       le16_to_cpu(linkstats->bcnMiss));
+				printf("Beacon RSSI avg:  %d\n",
+				       le16_to_cpu(linkstats->bcnRssiAvg));
+				printf("Beacon SNR avg:   %d\n",
+				       le16_to_cpu(linkstats->bcnSnrAvg));
+
+				printf("Rx packets:       %u\n",
+				       (int)le32_to_cpu(linkstats->rxPkts));
+				printf("Rx RSSI avg:      %d\n",
+				       le16_to_cpu(linkstats->rxRssiAvg));
+				printf("Rx SNR avg:       %d\n",
+				       le16_to_cpu(linkstats->rxSnrAvg));
+
+				printf("Tx packets:       %u\n",
+				       (int)le32_to_cpu(linkstats->txPkts));
+				printf("Tx Attempts:      %u\n",
+				       (int)le32_to_cpu(linkstats->txAttempts));
+				printf("Tx Failures:      %u\n",
+				       (int)le32_to_cpu(linkstats->txFailures));
+				printf("Tx Initial Rate:  %s\n",
+				       rateIdStr[linkstats->txInitRate]);
+
+				printf("Tx AC VO:         %u [ %u ]\n",
+				       le16_to_cpu(linkstats->
+						   txQueuePktCnt[WMM_AC_VO]),
+				       (int)le32_to_cpu(linkstats->
+							txQueueDelay[WMM_AC_VO])
+				       / 1000);
+				printf("Tx AC VI:         %u [ %u ]\n",
+				       le16_to_cpu(linkstats->
+						   txQueuePktCnt[WMM_AC_VI]),
+				       (int)le32_to_cpu(linkstats->
+							txQueueDelay[WMM_AC_VI])
+				       / 1000);
+				printf("Tx AC BE:         %u [ %u ]\n",
+				       le16_to_cpu(linkstats->
+						   txQueuePktCnt[WMM_AC_BE]),
+				       (int)le32_to_cpu(linkstats->
+							txQueueDelay[WMM_AC_BE])
+				       / 1000);
+				printf("Tx AC BK:         %u [ %u ]\n",
+				       le16_to_cpu(linkstats->
+						   txQueuePktCnt[WMM_AC_BK]),
+				       (int)le32_to_cpu(linkstats->
+							txQueueDelay[WMM_AC_BK])
+				       / 1000);
+				break;
+			}
+		case HostCmd_CMD_WMM_PARAM_CONFIG:
+			{
+				HostCmd_DS_WMM_PARAM_CONFIG *wmm_param =
+					(HostCmd_DS_WMM_PARAM_CONFIG *) (buf +
+									 S_DS_GEN);
+				printf("WMM Params: \n");
+				printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_param->ac_params[AC_BE].aci_aifsn.aifsn, wmm_param->ac_params[AC_BE].ecw.ecw_max, wmm_param->ac_params[AC_BE].ecw.ecw_min, le16_to_cpu(wmm_param->ac_params[AC_BE].tx_op_limit));
+				printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_param->ac_params[AC_BK].aci_aifsn.aifsn, wmm_param->ac_params[AC_BK].ecw.ecw_max, wmm_param->ac_params[AC_BK].ecw.ecw_min, le16_to_cpu(wmm_param->ac_params[AC_BK].tx_op_limit));
+				printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_param->ac_params[AC_VI].aci_aifsn.aifsn, wmm_param->ac_params[AC_VI].ecw.ecw_max, wmm_param->ac_params[AC_VI].ecw.ecw_min, le16_to_cpu(wmm_param->ac_params[AC_VI].tx_op_limit));
+				printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n", wmm_param->ac_params[AC_VO].aci_aifsn.aifsn, wmm_param->ac_params[AC_VO].ecw.ecw_max, wmm_param->ac_params[AC_VO].ecw.ecw_min, le16_to_cpu(wmm_param->ac_params[AC_VO].tx_op_limit));
+				break;
+			}
+		default:
+			printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x,"
+			       " SeqNum=%#04x, Result=%#04x\n",
+			       hostcmd->command, hostcmd->size,
+			       hostcmd->seq_num, hostcmd->result);
+			hexdump("payload",
+				(t_void *)(buf + S_DS_GEN),
+				hostcmd->size - S_DS_GEN, ' ');
+			break;
+		}
+	} else {
+		printf("HOSTCMD failed: CmdCode=%#04x, Size=%#04x,"
+		       " SeqNum=%#04x, Result=%#04x\n",
+		       hostcmd->command, hostcmd->size,
+		       hostcmd->seq_num, hostcmd->result);
+	}
+	return ret;
+}
+
+/**
+ *  @brief Trims leading and traling spaces only
+ *  @param str  A pointer to argument string
+ *  @return     pointer to trimmed string
+ */
+char *
+trim_spaces(char *str)
+{
+	char *str_end = NULL;
+
+	if (!str)
+		return NULL;
+
+	/* Trim leading spaces */
+	while (!*str && isspace(*str))
+		str++;
+
+	if (*str == 0)		/* All spaces? */
+		return str;
+
+	/* Trim trailing spaces */
+	str_end = str + strlen(str) - 1;
+	while (str_end > str && isspace(*str_end))
+		str_end--;
+
+	/* null terminate the string */
+	*(str_end + 1) = '\0';
+
+	return str;
+}
+
+/**
+ *  @brief Process hostcmd command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_hostcmd(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL, *raw_buf = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	FILE *fp = NULL;
+	FILE *fp_raw = NULL;
+	FILE *fp_dtsi = NULL;
+	char cmdname[256];
+	boolean call_ioctl = TRUE;
+	t_u32 buf_len = 0, i, j, k;
+	char *line = NULL, *pos = NULL;
+	int li = 0, blk_count = 0, ob = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	struct cmd_node {
+		char cmd_string[256];
+		struct cmd_node *next;
+	};
+	struct cmd_node *command = NULL, *header = NULL, *new_node = NULL;
+
+	if (argc < 5) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanutl mlanX hostcmd <hostcmd.conf> <cmdname>\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	snprintf(cmdname, sizeof(cmdname), "%s", argv[4]);
+
+	if (!strcmp(cmdname, "generate_raw")) {
+		call_ioctl = FALSE;
+	}
+
+	if (!call_ioctl && argc != 6) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanutl mlanX hostcmd <hostcmd.conf> %s <raw_data_file>\n", cmdname);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	fp = fopen(argv[3], "r");
+	if (fp == NULL) {
+		fprintf(stderr, "Cannot open file %s\n", argv[3]);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	if (call_ioctl) {
+		/* Prepare the hostcmd buffer */
+		prepare_buffer(buffer, argv[2], 0, NULL);
+		if (MLAN_STATUS_FAILURE ==
+		    prepare_host_cmd_buffer(fp, cmdname,
+					    buffer + strlen(CMD_MARVELL) +
+					    strlen(argv[2]))) {
+			fclose(fp);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		fclose(fp);
+	} else {
+		line = (char *)malloc(MAX_CONFIG_LINE);
+		if (!line) {
+			printf("ERR:Cannot allocate memory for line\n");
+			fclose(fp);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		memset(line, 0, MAX_CONFIG_LINE);
+
+		while (config_get_line(line, MAX_CONFIG_LINE, fp, &li, &pos)) {
+			line = trim_spaces(line);
+			if (line[strlen(line) - 1] == '{') {
+				if (ob == 0) {
+					new_node =
+						(struct cmd_node *)
+						malloc(sizeof(struct cmd_node));
+					if (!new_node) {
+						printf("ERR:Cannot allocate memory for cmd_node\n");
+						fclose(fp);
+						ret = MLAN_STATUS_FAILURE;
+						goto done;
+					}
+					memset(new_node, 0,
+					       sizeof(struct cmd_node));
+					new_node->next = NULL;
+					if (blk_count == 0) {
+						header = new_node;
+						command = new_node;
+					} else {
+						command->next = new_node;
+						command = new_node;
+					}
+					strncpy(command->cmd_string, line,
+						(strchr(line, '=') - line));
+					memmove(command->cmd_string,
+						trim_spaces(command->
+							    cmd_string),
+						strlen(trim_spaces
+						       (command->cmd_string)) +
+						1);
+				}
+				ob++;
+				continue;	/* goto while() */
+			}
+			if (line[strlen(line) - 1] == '}') {
+				ob--;
+				if (ob == 0)
+					blk_count++;
+				continue;	/* goto while() */
+			}
+		}
+
+		rewind(fp);	/* Set the source file pointer to the beginning again */
+		command = header;	/* Set 'command' at the beginning of the command list */
+
+		fp_raw = fopen(argv[5], "w");
+		if (fp_raw == NULL) {
+			fprintf(stderr,
+				"Cannot open the destination raw_data file %s\n",
+				argv[5]);
+			fclose(fp);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		/* prepare .dtsi output */
+		snprintf(cmdname, sizeof(cmdname), "%s.dtsi", argv[5]);
+		fp_dtsi = fopen(cmdname, "w");
+		if (fp_dtsi == NULL) {
+			fprintf(stderr, "Cannot open the destination file %s\n",
+				cmdname);
+			fclose(fp);
+			fclose(fp_raw);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		for (k = 0; k < blk_count && command != NULL; k++) {
+			if (MLAN_STATUS_FAILURE ==
+			    prepare_host_cmd_buffer(fp, command->cmd_string,
+						    buffer))
+				memset(buffer, 0, BUFFER_LENGTH);
+
+			memcpy(&buf_len, buffer, sizeof(t_u32));
+			if (buf_len) {
+				raw_buf = buffer + sizeof(t_u32);	/* raw_buf points to start of actual <raw data> */
+				printf("buf_len = %d\n", (int)buf_len);
+				if (k > 0)
+					fprintf(fp_raw, "\n\n");
+				fprintf(fp_raw, "%s={\n", command->cmd_string);
+				fprintf(fp_dtsi,
+					"/ {\n\tmarvell_cfgdata {\n\t\tmarvell,%s = /bits/ 8 <\n",
+					command->cmd_string);
+				i = j = 0;
+				while (i < buf_len) {
+					for (j = 0; j < 16; j++) {
+						fprintf(fp_raw, "%02x ",
+							*(raw_buf + i));
+						if (i >= 8) {
+							fprintf(fp_dtsi,
+								"0x%02x",
+								*(raw_buf + i));
+							if ((j < 16 - 1) &&
+							    (i < buf_len - 1))
+								fprintf(fp_dtsi,
+									" ");
+						}
+						if (++i >= buf_len)
+							break;
+					}
+					fputc('\n', fp_raw);
+					fputc('\n', fp_dtsi);
+				}
+				fprintf(fp_raw, "}");
+				fprintf(fp_dtsi, "\t\t>;\n\t};\n};\n");
+			}
+			command = command->next;
+			rewind(fp);
+		}
+
+		fclose(fp_dtsi);
+		fclose(fp_raw);
+		fclose(fp);
+	}
+
+	if (call_ioctl) {
+		cmd = (struct eth_priv_cmd *)
+			malloc(sizeof(struct eth_priv_cmd));
+		if (!cmd) {
+			printf("ERR:Cannot allocate buffer for command!\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+		memset(cmd, 0, sizeof(struct eth_priv_cmd));
+		memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+		cmd->buf = buffer;
+#endif
+		cmd->used_len = 0;
+		cmd->total_len = BUFFER_LENGTH;
+
+		/* Perform IOCTL */
+		memset(&ifr, 0, sizeof(struct ifreq));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+		ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+		if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+			perror("mlanutl");
+			fprintf(stderr, "mlanutl: hostcmd fail\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		/* Process result */
+		process_host_cmd_resp(argv[2], buffer);
+	}
+
+done:
+	while (header) {
+		command = header;
+		header = header->next;
+		free(command);
+	}
+	if (line)
+		free(line);
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Process HT Tx configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_httxcfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	t_u32 *data = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: httxcfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (argc == 3) {
+		/* Get result */
+		data = (t_u32 *)buffer;
+		printf("HT Tx cfg: \n");
+		printf("    BG band:  0x%08x\n", data[0]);
+		printf("     A band:  0x%08x\n", data[1]);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process HT capability configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_htcapinfo(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct eth_priv_htcapinfo *ht_cap = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: htcapinfo fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		ht_cap = (struct eth_priv_htcapinfo *)buffer;
+		printf("HT cap info: \n");
+		printf("    BG band:  0x%08x\n", ht_cap->ht_cap_info_bg);
+		printf("     A band:  0x%08x\n", ht_cap->ht_cap_info_a);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process HT Add BA parameters
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_addbapara(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	struct eth_priv_addba *addba = NULL;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: addbapara fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (argc == 3) {
+		/* Get */
+		addba = (struct eth_priv_addba *)buffer;
+		printf("Add BA configuration: \n");
+		printf("    Time out : %d\n", addba->time_out);
+		printf("    TX window: %d\n", addba->tx_win_size);
+		printf("    RX window: %d\n", addba->rx_win_size);
+		printf("    TX AMSDU : %d\n", addba->tx_amsdu);
+		printf("    RX AMSDU : %d\n", addba->rx_amsdu);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process Aggregation priority table parameters
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_aggrpriotbl(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int i;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: aggrpriotbl fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (argc == 3) {
+		/* Get */
+		printf("Aggregation priority table cfg: \n");
+		printf("    TID      AMPDU      AMSDU \n");
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			printf("     %d        %3d        %3d \n",
+			       i, buffer[2 * i], buffer[2 * i + 1]);
+		}
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process HT Add BA reject configurations
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_addbareject(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int i;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: addbareject fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (argc == 3) {
+		/* Get */
+		printf("Add BA reject configuration: \n");
+		printf("    TID      Reject \n");
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			printf("     %d        %d\n", i, buffer[i]);
+		}
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process HT Del BA command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_delba(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: delba fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process reject addba req command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_rejectaddbareq(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: rejectaddbareq fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("Reject addba req command response: %s\n", buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process VHT configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_vhtcfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct eth_priv_vhtcfg vhtcfg;
+	struct ifreq ifr;
+	t_u8 i, num = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Sanity tests */
+	if (argc < 5) {
+		printf("Insufficient parameters\n");
+		printf("For STA interface: mlanutl mlanX vhtcfg <band> <txrx> [bwcfg] [vhtcap]\n");
+		printf("For uAP interface: mlanutl uapX vhtcfg <band> <txrx> [bwcfg] [vhtcap] [vht_tx_mcs] [vht_rx_mcs]\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: vhtcfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	/* the first attribute is the number of vhtcfg entries */
+	num = *buffer;
+	if (argc == 5) {
+		/* GET operation */
+		printf("11AC VHT Configuration: \n");
+		for (i = 0; i < num; i++) {
+			memcpy(&vhtcfg, buffer + 1 + i * sizeof(vhtcfg),
+			       sizeof(vhtcfg));
+			/* Band */
+			if (vhtcfg.band == 1)
+				printf("Band: 2.4G\n");
+			else
+				printf("Band: 5G\n");
+			/* BW confi9 */
+
+			if (vhtcfg.bwcfg == 0)
+				printf("    BW config: Follow BW in the 11N config\n");
+			else
+				printf("    BW config: Follow BW in VHT Capabilities\n");
+
+			/* Tx/Rx */
+			if (vhtcfg.txrx & 0x1)
+				printf("    VHT operation for Tx: 0x%08x\n",
+				       vhtcfg.vht_cap_info);
+			if (vhtcfg.txrx & 0x2)
+				/* VHT capabilities */
+				printf("    VHT Capabilities Info: 0x%08x\n",
+				       vhtcfg.vht_cap_info);
+			/* MCS */
+			if (vhtcfg.txrx & 0x2) {
+				printf("    Tx MCS set: 0x%04x\n",
+				       vhtcfg.vht_tx_mcs);
+				printf("    Rx MCS set: 0x%04x\n",
+				       vhtcfg.vht_rx_mcs);
+			}
+		}
+	} else {
+		/* SET operation */
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process Operating Mode Notification configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_opermodecfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct eth_priv_opermodecfg *cfg = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: opermodecfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	cfg = (struct eth_priv_opermodecfg *)(buffer);
+	printf("11AC Operating Mode Notification Configuration: \n");
+	printf("    bw: %d\n", cfg->bw);
+	printf("    nss: %d\n", cfg->nss);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+static char *rate_format[3] = { "LG", "HT", "VHT" };
+
+static char *lg_rate[] = { "1 Mbps", "2 Mbps", "5.5 Mbps", "11 Mbps",
+	"6 Mbps", "9 Mbps", "12 Mbps", "18 Mbps",
+	"24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps"
+};
+
+/**
+ *  @brief Process Get data rate
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_datarate(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct eth_priv_data_rate *datarate = NULL;
+	struct ifreq ifr;
+	char *bw[] = { "20 MHz", "40 MHz", "80 MHz", "160 MHz" };
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: getdatarate fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	datarate = (struct eth_priv_data_rate *)buffer;
+	printf("Data Rate:\n");
+	printf("  TX: \n");
+	if (datarate->tx_rate_format <= 2) {
+		printf("    Type: %s\n", rate_format[datarate->tx_rate_format]);
+		if ((datarate->tx_rate_format == 0) &&
+		    datarate->tx_data_rate <= 11)
+			/* LG */
+			printf("    Rate: %s\n",
+			       lg_rate[datarate->tx_data_rate]);
+		else {
+			/* HT and VHT */
+			if (datarate->tx_bw <= 3)
+				printf("    BW:   %s\n", bw[datarate->tx_bw]);
+			if (datarate->tx_gi == 0)
+				printf("    GI:   Long\n");
+			else
+				printf("    GI:   Short\n");
+			if (datarate->tx_rate_format == 3)
+				printf("    NSS:  %d\n", datarate->tx_nss);
+			if (datarate->tx_mcs_index != 0xFF)
+				printf("    MCS:  MCS %d\n",
+				       (int)datarate->tx_mcs_index);
+			else
+				printf("    MCS:  Auto\n");
+			printf("    Rate: %f Mbps\n",
+			       (float)datarate->tx_data_rate / 2);
+		}
+	}
+
+	printf("  RX: \n");
+	if (datarate->rx_rate_format <= 2) {
+		printf("    Type: %s\n", rate_format[datarate->rx_rate_format]);
+		if ((datarate->rx_rate_format == 0) &&
+		    datarate->rx_data_rate <= 11)
+			/* LG */
+			printf("    Rate: %s\n",
+			       lg_rate[datarate->rx_data_rate]);
+		else {
+			/* HT and VHT */
+			if (datarate->rx_bw <= 3)
+				printf("    BW:   %s\n", bw[datarate->rx_bw]);
+			if (datarate->rx_gi == 0)
+				printf("    GI:   Long\n");
+			else
+				printf("    GI:   Short\n");
+			if (datarate->rx_rate_format == 3)
+				printf("    NSS:  %d\n", datarate->rx_nss);
+			if (datarate->rx_mcs_index != 0xFF)
+				printf("    MCS:  MCS %d\n",
+				       (int)datarate->rx_mcs_index);
+			else
+				printf("    MCS:  Auto\n");
+			printf("    Rate: %f Mbps\n",
+			       (float)datarate->rx_data_rate / 2);
+		}
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tx rate configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_txratecfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct eth_priv_tx_rate_cfg *txratecfg = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: txratecfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	txratecfg = (struct eth_priv_tx_rate_cfg *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("Tx Rate Configuration: \n");
+		/* format */
+		if (txratecfg->rate_format == 0xFF) {
+			printf("    Type:       0xFF (Auto)\n");
+		} else if (txratecfg->rate_format <= 2) {
+			printf("    Type:       %d (%s)\n",
+			       txratecfg->rate_format,
+			       rate_format[txratecfg->rate_format]);
+			if (txratecfg->rate_format == 0)
+				printf("    Rate Index: %d (%s)\n",
+				       txratecfg->rate_index,
+				       lg_rate[txratecfg->rate_index]);
+			else if (txratecfg->rate_format >= 1)
+				printf("    MCS Index:  %d\n",
+				       (int)txratecfg->rate_index);
+			if (txratecfg->rate_format == 2)
+				printf("    NSS:        %d\n",
+				       (int)txratecfg->nss);
+		} else {
+			printf("    Unknown rate format.\n");
+		}
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process get wireless stats
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_getlog(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct eth_priv_get_log *stats = NULL;
+	struct ifreq ifr;
+	struct timeval tv;
+	int i = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: getlog fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	gettimeofday(&tv, NULL);
+
+	/* Process results */
+	stats = (struct eth_priv_get_log *)buffer;
+	printf("Get log: timestamp %d.%06d sec\n", (int)tv.tv_sec,
+	       (int)tv.tv_usec);
+	printf("dot11GroupTransmittedFrameCount    %u\n"
+	       "dot11FailedCount                   %u\n"
+	       "dot11RetryCount                    %u\n"
+	       "dot11MultipleRetryCount            %u\n"
+	       "dot11FrameDuplicateCount           %u\n"
+	       "dot11RTSSuccessCount               %u\n"
+	       "dot11RTSFailureCount               %u\n"
+	       "dot11ACKFailureCount               %u\n"
+	       "dot11ReceivedFragmentCount         %u\n"
+	       "dot11GroupReceivedFrameCount       %u\n"
+	       "dot11FCSErrorCount                 %u\n"
+	       "dot11TransmittedFrameCount         %u\n"
+	       "wepicverrcnt-1                     %u\n"
+	       "wepicverrcnt-2                     %u\n"
+	       "wepicverrcnt-3                     %u\n"
+	       "wepicverrcnt-4                     %u\n"
+	       "beaconReceivedCount                %u\n"
+	       "beaconMissedCount                  %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 (cmd->used_len == sizeof(struct eth_priv_get_log)) {
+		printf("dot11TransmittedFragmentCount      %u\n",
+		       stats->tx_frag_cnt);
+		printf("dot11QosTransmittedFragmentCount   ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_tx_frag_cnt[i]);
+		}
+		printf("\ndot11QosFailedCount                ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_failed_cnt[i]);
+		}
+		printf("\ndot11QosRetryCount                 ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_retry_cnt[i]);
+		}
+		printf("\ndot11QosMultipleRetryCount         ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_multi_retry_cnt[i]);
+		}
+		printf("\ndot11QosFrameDuplicateCount        ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_frm_dup_cnt[i]);
+		}
+		printf("\ndot11QosRTSSuccessCount            ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_rts_suc_cnt[i]);
+		}
+		printf("\ndot11QosRTSFailureCount            ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_rts_failure_cnt[i]);
+		}
+		printf("\ndot11QosACKFailureCount            ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_ack_failure_cnt[i]);
+		}
+		printf("\ndot11QosReceivedFragmentCount      ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_rx_frag_cnt[i]);
+		}
+		printf("\ndot11QosTransmittedFrameCount      ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_tx_frm_cnt[i]);
+		}
+		printf("\ndot11QosDiscardedFrameCount        ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_discarded_frm_cnt[i]);
+		}
+		printf("\ndot11QosMPDUsReceivedCount         ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_mpdus_rx_cnt[i]);
+		}
+		printf("\ndot11QosRetriesReceivedCount       ");
+		for (i = 0; i < 8; i++) {
+			printf("%u ", stats->qos_retries_rx_cnt[i]);
+		}
+		printf("\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);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process esuppmode command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_esuppmode(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct eth_priv_esuppmode_cfg *esuppmodecfg = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: esuppmode fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	esuppmodecfg = (struct eth_priv_esuppmode_cfg *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("Esupplicant Mode Configuration: \n");
+		/* RSN mode */
+		printf("    RSN mode:         0x%x ( ", esuppmodecfg->rsn_mode);
+		if (esuppmodecfg->rsn_mode & MBIT(0))
+			printf("No-RSN ");
+		if (esuppmodecfg->rsn_mode & MBIT(3))
+			printf("WPA ");
+		if (esuppmodecfg->rsn_mode & MBIT(4))
+			printf("WPA-None ");
+		if (esuppmodecfg->rsn_mode & MBIT(5))
+			printf("WPA2 ");
+		printf(")\n");
+		/* Pairwise cipher */
+		printf("    Pairwise cipher:  0x%x ( ",
+		       esuppmodecfg->pairwise_cipher);
+		if (esuppmodecfg->pairwise_cipher & MBIT(2))
+			printf("TKIP ");
+		if (esuppmodecfg->pairwise_cipher & MBIT(3))
+			printf("AES ");
+		printf(")\n");
+		/* Group cipher */
+		printf("    Group cipher:     0x%x ( ",
+		       esuppmodecfg->group_cipher);
+		if (esuppmodecfg->group_cipher & MBIT(2))
+			printf("TKIP ");
+		if (esuppmodecfg->group_cipher & MBIT(3))
+			printf("AES ");
+		printf(")\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process passphrase command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_passphrase(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* The argument being a string, this requires special handling */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+	if (argc >= 4) {
+		strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])),
+		       argv[3]);
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: passphrase fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("Passphrase Configuration: %s\n", (char *)buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process deauth command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_deauth(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* The argument being a string, this requires special handling */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+	if (argc >= 4) {
+		strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])),
+		       argv[3]);
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: deauth fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef UAP_SUPPORT
+/**
+ *  @brief Process getstalist command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_getstalist(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	struct eth_priv_getstalist *list = NULL;
+	int i = 0, rssi = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* The argument being a string, this requires special handling */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: getstalist fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	list = (struct eth_priv_getstalist *)(buffer + strlen(CMD_MARVELL) +
+					      strlen(argv[2]));
+
+	printf("Number of STA = %d\n\n", list->sta_count);
+
+	for (i = 0; i < list->sta_count; i++) {
+		printf("STA %d information:\n", i + 1);
+		printf("=====================\n");
+		printf("MAC Address: ");
+		print_mac(list->client_info[i].mac_address);
+		printf("\nPower mfg status: %s\n",
+		       (list->client_info[i].power_mfg_status ==
+			0) ? "active" : "power save");
+
+	/** On some platform, s8 is same as unsigned char*/
+		rssi = (int)list->client_info[i].rssi;
+		if (rssi > 0x7f)
+			rssi = -(256 - rssi);
+		printf("Rssi : %d dBm\n\n", rssi);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/**
+ *  @brief Process BSS role command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_bssrole(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: bssrole fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		/* GET operation */
+		printf("BSS role: %d\n", buffer[0]);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+#endif
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Helper function for process_getscantable_idx
+ *
+ *  @param pbuf     A pointer to the buffer
+ *  @param buf_len  Buffer length
+ *
+ *  @return         NA
+ *
+ */
+static void
+dump_scan_elems(const t_u8 *pbuf, uint buf_len)
+{
+	uint idx;
+	uint marker = 2 + pbuf[1];
+
+	for (idx = 0; idx < buf_len; idx++) {
+		if (idx % 0x10 == 0) {
+			printf("\n%04x: ", idx);
+		}
+
+		if (idx == marker) {
+			printf("|");
+			marker = idx + pbuf[idx + 1] + 2;
+		} else {
+			printf(" ");
+		}
+
+		printf("%02x ", pbuf[idx]);
+	}
+
+	printf("\n");
+}
+
+/**
+ *  @brief Helper function for process_getscantable_idx
+ *  Find next element
+ *
+ *  @param pp_ie_out    Pointer of a IEEEtypes_Generic_t structure pointer
+ *  @param p_buf_left   Integer pointer, which contains the number of left p_buf
+ *
+ *  @return             MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE
+ */
+static int
+scantable_elem_next(IEEEtypes_Generic_t **pp_ie_out, int *p_buf_left)
+{
+	IEEEtypes_Generic_t *pie_gen;
+	t_u8 *p_next;
+
+	if (*p_buf_left < 2) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pie_gen = *pp_ie_out;
+
+	p_next = (t_u8 *)pie_gen + (pie_gen->ieee_hdr.len
+				    + sizeof(pie_gen->ieee_hdr));
+	*p_buf_left -= (p_next - (t_u8 *)pie_gen);
+
+	*pp_ie_out = (IEEEtypes_Generic_t *)p_next;
+
+	if (*p_buf_left <= 0) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+ /**
+  *  @brief Helper function for process_getscantable_idx
+  *         scantable find element
+  *
+  *  @param ie_buf       Pointer of the IE buffer
+  *  @param ie_buf_len   IE buffer length
+  *  @param ie_type      IE type
+  *  @param ppie_out     Pointer to the IEEEtypes_Generic_t structure pointer
+  *  @return             MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE
+  */
+static int
+scantable_find_elem(t_u8 *ie_buf,
+		    unsigned int ie_buf_len,
+		    IEEEtypes_ElementId_e ie_type,
+		    IEEEtypes_Generic_t **ppie_out)
+{
+	int found;
+	unsigned int ie_buf_left;
+
+	ie_buf_left = ie_buf_len;
+
+	found = FALSE;
+
+	*ppie_out = (IEEEtypes_Generic_t *)ie_buf;
+
+	do {
+		found = ((*ppie_out)->ieee_hdr.element_id == ie_type);
+
+	} while (!found &&
+		 (scantable_elem_next(ppie_out, (int *)&ie_buf_left) == 0));
+
+	if (!found) {
+		*ppie_out = NULL;
+	}
+
+	return found ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE;
+}
+
+ /**
+  *  @brief Helper function for process_getscantable_idx
+  *         It gets SSID from IE
+  *
+  *  @param ie_buf       IE buffer
+  *  @param ie_buf_len   IE buffer length
+  *  @param pssid        SSID
+  *  @param ssid_buf_max Size of SSID
+  *  @return             MLAN_STATUS_SUCCESS on success, otherwise MLAN_STATUS_FAILURE
+  */
+static int
+scantable_get_ssid_from_ie(t_u8 *ie_buf,
+			   unsigned int ie_buf_len,
+			   t_u8 *pssid, unsigned int ssid_buf_max)
+{
+	int retval;
+	IEEEtypes_Generic_t *pie_gen;
+
+	retval = scantable_find_elem(ie_buf, ie_buf_len, SSID, &pie_gen);
+
+	memcpy(pssid, pie_gen->data, MIN(pie_gen->ieee_hdr.len, ssid_buf_max));
+
+	return retval;
+}
+
+/**
+ *  @brief Display detailed information for a specific scan table entry
+ *
+ *  @param cmd_name         Command name
+ *  @param prsp_info_req    Scan table entry request structure
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_getscantable_idx(char *cmd_name,
+			 wlan_ioctl_get_scan_table_info *prsp_info_req)
+{
+	int ret = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	t_u8 *pcurrent;
+	char ssid[33];
+	t_u16 tmp_cap;
+	t_u8 tsf[8];
+	t_u16 beacon_interval;
+	t_u16 cap_info;
+	wlan_ioctl_get_scan_table_info *prsp_info;
+
+	wlan_get_scan_table_fixed fixed_fields;
+	t_u32 fixed_field_length;
+	t_u32 bss_info_length;
+
+	memset(ssid, 0x00, sizeof(ssid));
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, cmd_name, 0, NULL);
+
+	prsp_info =
+		(wlan_ioctl_get_scan_table_info *)(buffer +
+						   strlen(CMD_MARVELL) +
+						   strlen(cmd_name));
+
+	memcpy(prsp_info, prsp_info_req,
+	       sizeof(wlan_ioctl_get_scan_table_info));
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/*
+	 * Set up and execute the ioctl call
+	 */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		if (errno == EAGAIN) {
+			ret = -EAGAIN;
+		} else {
+			perror("mlanutl");
+			fprintf(stderr, "mlanutl: getscantable fail\n");
+			ret = MLAN_STATUS_FAILURE;
+		}
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return ret;
+	}
+
+	prsp_info = (wlan_ioctl_get_scan_table_info *)buffer;
+	if (prsp_info->scan_number == 0) {
+		printf("mlanutl: getscantable ioctl - index out of range\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return -EINVAL;
+	}
+
+	pcurrent = prsp_info->scan_table_entry_buf;
+
+	memcpy((t_u8 *)&fixed_field_length,
+	       (t_u8 *)pcurrent, sizeof(fixed_field_length));
+	pcurrent += sizeof(fixed_field_length);
+
+	memcpy((t_u8 *)&bss_info_length,
+	       (t_u8 *)pcurrent, sizeof(bss_info_length));
+	pcurrent += sizeof(bss_info_length);
+
+	memcpy((t_u8 *)&fixed_fields, (t_u8 *)pcurrent, sizeof(fixed_fields));
+	pcurrent += fixed_field_length;
+
+	/* Time stamp is 8 byte long */
+	memcpy(tsf, pcurrent, sizeof(tsf));
+	pcurrent += sizeof(tsf);
+	bss_info_length -= sizeof(tsf);
+
+	/* Beacon interval is 2 byte long */
+	memcpy(&beacon_interval, pcurrent, sizeof(beacon_interval));
+	pcurrent += sizeof(beacon_interval);
+	bss_info_length -= sizeof(beacon_interval);
+
+	/* Capability information is 2 byte long */
+	memcpy(&cap_info, pcurrent, sizeof(cap_info));
+	pcurrent += sizeof(cap_info);
+	bss_info_length -= sizeof(cap_info);
+
+	scantable_get_ssid_from_ie(pcurrent,
+				   bss_info_length, (t_u8 *)ssid, sizeof(ssid));
+
+	printf("\n*** [%s], %02x:%02x:%02x:%02x:%02x:%2x\n",
+	       ssid,
+	       fixed_fields.bssid[0],
+	       fixed_fields.bssid[1],
+	       fixed_fields.bssid[2],
+	       fixed_fields.bssid[3],
+	       fixed_fields.bssid[4], fixed_fields.bssid[5]);
+	memcpy(&tmp_cap, &cap_info, sizeof(tmp_cap));
+	printf("Channel = %d, SS = %d, CapInfo = 0x%04x, BcnIntvl = %d\n",
+	       fixed_fields.channel,
+	       255 - fixed_fields.rssi, tmp_cap, beacon_interval);
+
+	printf("TSF Values: AP(0x%02x%02x%02x%02x%02x%02x%02x%02x), ",
+	       tsf[7], tsf[6], tsf[5], tsf[4], tsf[3], tsf[2], tsf[1], tsf[0]);
+
+	printf("Network(0x%016llx)\n", fixed_fields.network_tsf);
+	printf("\n");
+	printf("Element Data (%d bytes)\n", (int)bss_info_length);
+	printf("------------");
+	dump_scan_elems(pcurrent, bss_info_length);
+	printf("\n");
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief channel validation.
+ *  @param scan_req  A pointer to wlan_ioctl_user_scan_cfg structure
+ *  @param chan_num  channel number
+ *
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+wlan_is_channel_valid(wlan_ioctl_user_scan_cfg *scan_req, t_u8 chan_number)
+{
+	int ret = -1;
+	int i;
+	if (scan_req && scan_req->chan_list[0].chan_number) {
+		for (i = 0;
+		     i < WLAN_IOCTL_USER_SCAN_CHAN_MAX &&
+		     scan_req->chan_list[i].chan_number; i++) {
+			if (scan_req->chan_list[i].chan_number == chan_number) {
+				ret = 0;
+				break;
+			}
+		}
+	} else {
+		ret = 0;
+	}
+	return ret;
+}
+
+/**
+ *  @brief filter_ssid_result
+ *  @param scan_req  A pointer to wlan_ioctl_user_scan_cfg structure
+ *  @param num_ssid_rqst Number of SSIDs which are filterted
+ *  @param bss_info  A pointer to current bss information structure
+ *  @return 0--success, otherwise--fail
+ */
+
+int
+filter_ssid_result(wlan_ioctl_user_scan_cfg *scan_req, int num_ssid_rqst,
+		   wlan_ioctl_get_bss_info *bss_info)
+{
+	int i, ret = 1;
+
+	for (i = 0; i < num_ssid_rqst; i++) {
+		if ((memcmp(scan_req->ssid_list[i].ssid, bss_info->ssid,
+			    (int)bss_info->ssid_len)) == 0) {
+			return 0;
+		}
+	}
+	return ret;
+}
+
+/**
+ *  @brief Process getscantable command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @param scan_req  A pointer to wlan_ioctl_user_scan_cfg structure
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+wlan_process_getscantable(int argc, char *argv[],
+			  wlan_ioctl_user_scan_cfg *scan_req)
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	struct wlan_ioctl_get_scan_list *scan_list_head = NULL;
+	struct wlan_ioctl_get_scan_list *scan_list_node = NULL;
+	struct wlan_ioctl_get_scan_list *curr = NULL, *next = NULL;
+
+	t_u32 total_scan_res = 0;
+
+	unsigned int scan_start;
+	int idx, ret = 0;
+
+	t_u8 *pcurrent;
+	t_u8 *pnext;
+	IEEEtypes_ElementId_e *pelement_id;
+	t_u8 *pelement_len;
+	int ssid_idx;
+	int insert = 0;
+	int sort_by_channel = 0;
+	t_u8 *pbyte;
+	t_u16 new_ss = 0;
+	t_u16 curr_ss = 0;
+	t_u8 new_ch = 0;
+	t_u8 curr_ch = 0;
+
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+	const t_u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
+
+	IEEEtypes_WmmParameter_t *pwmm_ie;
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	IEEEtypes_VendorSpecific_t *pwps_ie;
+	const t_u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 };
+
+	int displayed_info;
+
+	wlan_ioctl_get_scan_table_info rsp_info_req;
+	wlan_ioctl_get_scan_table_info *prsp_info;
+
+	wlan_get_scan_table_fixed fixed_fields;
+	t_u32 fixed_field_length;
+	t_u32 bss_info_length;
+	wlan_ioctl_get_bss_info *bss_info;
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	if (argc > 3 && (strcmp(argv[3], "tsf") != 0)
+	    && (strcmp(argv[3], "help") != 0)
+	    && (strcmp(argv[3], "ch") != 0)) {
+
+		idx = strtol(argv[3], NULL, 10);
+
+		if (idx >= 0) {
+			rsp_info_req.scan_number = idx;
+			ret = process_getscantable_idx(argv[2], &rsp_info_req);
+			if (buffer)
+				free(buffer);
+			if (cmd)
+				free(cmd);
+			return ret;
+		}
+	}
+
+	displayed_info = FALSE;
+	scan_start = 1;
+
+	do {
+		prepare_buffer(buffer, argv[2], 0, NULL);
+		prsp_info =
+			(wlan_ioctl_get_scan_table_info *)(buffer +
+							   strlen(CMD_MARVELL) +
+							   strlen(argv[2]));
+
+		prsp_info->scan_number = scan_start;
+
+		/*
+		 * Set up and execute the ioctl call
+		 */
+		memset(&ifr, 0, sizeof(struct ifreq));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+		ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+		if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+			if (errno == EAGAIN) {
+				ret = -EAGAIN;
+			} else {
+				perror("mlanutl");
+				fprintf(stderr, "mlanutl: getscantable fail\n");
+				ret = MLAN_STATUS_FAILURE;
+			}
+			if (cmd)
+				free(cmd);
+			if (buffer)
+				free(buffer);
+			return ret;
+		}
+
+		prsp_info = (wlan_ioctl_get_scan_table_info *)buffer;
+		pcurrent = 0;
+		pnext = prsp_info->scan_table_entry_buf;
+		total_scan_res += prsp_info->scan_number;
+
+		for (idx = 0; (unsigned int)idx < prsp_info->scan_number; idx++) {
+			/* Alloc memory for new node for next BSS */
+			scan_list_node = (struct wlan_ioctl_get_scan_list *)
+				malloc(sizeof(struct wlan_ioctl_get_scan_list));
+			if (scan_list_node == NULL) {
+				printf("Error: allocate memory for scan_list_head failed\n");
+				return -ENOMEM;
+			}
+			memset(scan_list_node, 0,
+			       sizeof(struct wlan_ioctl_get_scan_list));
+
+			/*
+			 * Set pcurrent to pnext in case pad bytes are at the end
+			 *   of the last IE we processed.
+			 */
+			pcurrent = pnext;
+
+			/* Start extracting each BSS to prepare a linked list */
+			memcpy((t_u8 *)&fixed_field_length,
+			       (t_u8 *)pcurrent, sizeof(fixed_field_length));
+			pcurrent += sizeof(fixed_field_length);
+
+			memcpy((t_u8 *)&bss_info_length,
+			       (t_u8 *)pcurrent, sizeof(bss_info_length));
+			pcurrent += sizeof(bss_info_length);
+
+			memcpy((t_u8 *)&fixed_fields,
+			       (t_u8 *)pcurrent, sizeof(fixed_fields));
+			pcurrent += fixed_field_length;
+
+			scan_list_node->fixed_buf.fixed_field_length =
+				fixed_field_length;
+			scan_list_node->fixed_buf.bss_info_length =
+				bss_info_length;
+			scan_list_node->fixed_buf.fixed_fields = fixed_fields;
+
+			bss_info = &scan_list_node->bss_info_buf;
+
+			/* Set next to be the start of the next scan entry */
+			pnext = pcurrent + bss_info_length;
+
+			if (bss_info_length >=
+			    (sizeof(bss_info->tsf) +
+			     sizeof(bss_info->beacon_interval) +
+			     sizeof(bss_info->cap_info))) {
+
+				/* time stamp is 8 byte long */
+				memcpy(bss_info->tsf, pcurrent,
+				       sizeof(bss_info->tsf));
+				pcurrent += sizeof(bss_info->tsf);
+				bss_info_length -= sizeof(bss_info->tsf);
+
+				/* beacon interval is 2 byte long */
+				memcpy(&bss_info->beacon_interval, pcurrent,
+				       sizeof(bss_info->beacon_interval));
+				pcurrent += sizeof(bss_info->beacon_interval);
+				bss_info_length -=
+					sizeof(bss_info->beacon_interval);
+				/* capability information is 2 byte long */
+				memcpy(&bss_info->cap_info, pcurrent,
+				       sizeof(bss_info->cap_info));
+				pcurrent += sizeof(bss_info->cap_info);
+				bss_info_length -= sizeof(bss_info->cap_info);
+			}
+
+			bss_info->wmm_cap = ' ';	/* M (WMM), C (WMM-Call Admission Control) */
+			bss_info->wps_cap = ' ';	/* "S" */
+			bss_info->dot11k_cap = ' ';	/* "K" */
+			bss_info->dot11r_cap = ' ';	/* "R" */
+			bss_info->ht_cap = ' ';	/* "N" */
+			bss_info->vht_cap[0] = 'A';
+			bss_info->vht_cap[1] = 'C';
+			/* "P" for Privacy (WEP) since "W" is WPA, and "2" is RSN/WPA2 */
+			bss_info->priv_cap =
+				bss_info->cap_info.privacy ? 'P' : ' ';
+
+			memset(bss_info->ssid, 0, MRVDRV_MAX_SSID_LENGTH + 1);
+			bss_info->ssid_len = 0;
+
+			while (bss_info_length >= 2) {
+				pelement_id = (IEEEtypes_ElementId_e *)pcurrent;
+				pelement_len = pcurrent + 1;
+				pcurrent += 2;
+
+				switch (*pelement_id) {
+				case SSID:
+					if (*pelement_len &&
+					    *pelement_len <=
+					    MRVDRV_MAX_SSID_LENGTH) {
+						memcpy(bss_info->ssid, pcurrent,
+						       *pelement_len);
+						bss_info->ssid_len =
+							*pelement_len;
+					}
+					break;
+
+				case WPA_IE:
+					pwpa_ie =
+						(IEEEtypes_VendorSpecific_t *)
+						pelement_id;
+					if ((memcmp
+					     (pwpa_ie->vend_hdr.oui, wpa_oui,
+					      sizeof(pwpa_ie->vend_hdr.oui)) ==
+					     0)
+					    && (pwpa_ie->vend_hdr.oui_type ==
+						wpa_oui[3])) {
+						/* WPA IE found, 'W' for WPA */
+						bss_info->priv_cap = 'W';
+					} else {
+						pwmm_ie =
+							(IEEEtypes_WmmParameter_t
+							 *)pelement_id;
+						if ((memcmp
+						     (pwmm_ie->vend_hdr.oui,
+						      wmm_oui,
+						      sizeof(pwmm_ie->vend_hdr.
+							     oui)) == 0)
+						    && (pwmm_ie->vend_hdr.
+							oui_type ==
+							wmm_oui[3])) {
+							/* Check the subtype: 1 == parameter, 0 == info */
+							if ((pwmm_ie->vend_hdr.
+							     oui_subtype == 1)
+							    && pwmm_ie->
+							    ac_params
+							    [WMM_AC_VO].
+							    aci_aifsn.acm) {
+								/* Call admission on VO; 'C' for CAC */
+								bss_info->
+									wmm_cap
+									= 'C';
+							} else {
+								/* No CAC; 'M' for uh, WMM */
+								bss_info->
+									wmm_cap
+									= 'M';
+							}
+						} else {
+							pwps_ie =
+								(IEEEtypes_VendorSpecific_t
+								 *)pelement_id;
+							if ((memcmp
+							     (pwps_ie->vend_hdr.
+							      oui, wps_oui,
+							      sizeof(pwps_ie->
+								     vend_hdr.
+								     oui)) == 0)
+							    && (pwps_ie->
+								vend_hdr.
+								oui_type ==
+								wps_oui[3])) {
+								bss_info->
+									wps_cap
+									= 'S';
+							}
+						}
+					}
+					break;
+
+				case RSN_IE:
+					/* RSN IE found; '2' for WPA2 (RSN) */
+					bss_info->priv_cap = '2';
+					break;
+				case HT_CAPABILITY:
+					bss_info->ht_cap = 'N';
+					break;
+				case VHT_CAPABILITY:
+					bss_info->vht_cap[0] = 'A';
+					bss_info->vht_cap[1] = 'C';
+					break;
+				default:
+					break;
+				}
+
+				pcurrent += *pelement_len;
+				bss_info_length -= (2 + *pelement_len);
+			}
+
+			/* Create a sorted list of BSS using Insertion Sort. */
+			if ((argc > 3) && !strcmp(argv[3], "ch")) {
+				/* Sort by channel number (ascending order) */
+				new_ch = fixed_fields.channel;
+				sort_by_channel = 1;
+			} else {
+				/* Sort as per Signal Strength (descending order) (Default case) */
+				new_ss = 255 - fixed_fields.rssi;
+			}
+			if (scan_list_head == NULL) {
+				/* Node is the first element in the list. */
+				scan_list_head = scan_list_node;
+				scan_list_node->next = NULL;
+				scan_list_node->prev = NULL;
+			} else {
+				curr = scan_list_head;
+				insert = 0;
+				do {
+					if (sort_by_channel) {
+						curr_ch =
+							curr->fixed_buf.
+							fixed_fields.channel;
+						if (new_ch < curr_ch)
+							insert = 1;
+					} else {
+						curr_ss =
+							255 -
+							curr->fixed_buf.
+							fixed_fields.rssi;
+						if (new_ss > curr_ss) {
+							insert = 1;
+						}
+					}
+					if (insert) {
+						if (curr == scan_list_head) {
+							/* Insert the node to head of the list */
+							scan_list_node->next =
+								scan_list_head;
+							scan_list_head->prev =
+								scan_list_node;
+							scan_list_head =
+								scan_list_node;
+						} else {
+							/* Insert the node to current position in list */
+							scan_list_node->prev =
+								curr->prev;
+							scan_list_node->next =
+								curr;
+							(curr->prev)->next =
+								scan_list_node;
+							curr->prev =
+								scan_list_node;
+						}
+						break;
+					}
+					if (curr->next == NULL) {
+						/* Insert the node to tail of the list */
+						curr->next = scan_list_node;
+						scan_list_node->prev = curr;
+						scan_list_node->next = NULL;
+						break;
+					}
+					curr = curr->next;
+				} while (curr != NULL);
+			}
+		}
+		scan_start += prsp_info->scan_number;
+	} while (prsp_info->scan_number);
+
+	/* Display scan results */
+	printf("---------------------------------------");
+	printf("---------------------------------------\n");
+	printf("# | ch  | ss  |       bssid       |   cap    |   SSID \n");
+	printf("---------------------------------------");
+	printf("---------------------------------------\n");
+
+	for (curr = scan_list_head, idx = 0;
+	     (curr != NULL) && ((unsigned int)idx < total_scan_res);
+	     curr = curr->next, idx++) {
+		fixed_fields = curr->fixed_buf.fixed_fields;
+		bss_info = &curr->bss_info_buf;
+		if (wlan_is_channel_valid(scan_req, fixed_fields.channel))
+			continue;
+
+		if (setuserscan_filter == BSSID_FILTER) {
+			if (memcmp
+			    (scan_req->specific_bssid, fixed_fields.bssid,
+			     ETH_ALEN))
+				continue;
+		}
+		if (setuserscan_filter == SSID_FILTER) {
+			if (filter_ssid_result
+			    (scan_req, num_ssid_filter, bss_info))
+				continue;
+		}
+		printf("%02u| %03d | %03d | %02x:%02x:%02x:%02x:%02x:%02x |",
+		       idx,
+		       fixed_fields.channel,
+		       -fixed_fields.rssi,
+		       fixed_fields.bssid[0],
+		       fixed_fields.bssid[1],
+		       fixed_fields.bssid[2],
+		       fixed_fields.bssid[3],
+		       fixed_fields.bssid[4], fixed_fields.bssid[5]);
+
+		displayed_info = TRUE;
+
+		/* "A" for Adhoc
+		 * "I" for Infrastructure,
+		 * "D" for DFS (Spectrum Mgmt)
+		 */
+		printf(" %c%c%c%c%c%c%c%c%c%c | ", bss_info->cap_info.ibss ? 'A' : 'I', bss_info->priv_cap,	/* P (WEP), W (WPA), 2 (WPA2) */
+		       bss_info->cap_info.spectrum_mgmt ? 'D' : ' ', bss_info->wmm_cap,	/* M (WMM), C (WMM-Call Admission Control) */
+		       bss_info->dot11k_cap,	/* K */
+		       bss_info->dot11r_cap,	/* R */
+		       bss_info->wps_cap,	/* S */
+		       bss_info->ht_cap,	/* N */
+		       bss_info->vht_cap[0],	/* AC */
+		       bss_info->vht_cap[1]);
+
+		/* Print out the ssid or the hex values if non-printable */
+		for (ssid_idx = 0; ssid_idx < (int)bss_info->ssid_len;
+		     ssid_idx++) {
+			if (isprint(bss_info->ssid[ssid_idx])) {
+				printf("%c", bss_info->ssid[ssid_idx]);
+			} else {
+				printf("\\%02x", bss_info->ssid[ssid_idx]);
+			}
+		}
+
+		printf("\n");
+
+		if (argc > 3 && strcmp(argv[3], "tsf") == 0) {
+			/* TSF is a u64, some formatted printing libs have trouble
+			   printing long longs, so cast and dump as bytes */
+			pbyte = (t_u8 *)&fixed_fields.network_tsf;
+			printf("    TSF=%02x%02x%02x%02x%02x%02x%02x%02x\n",
+			       pbyte[7], pbyte[6], pbyte[5], pbyte[4],
+			       pbyte[3], pbyte[2], pbyte[1], pbyte[0]);
+		}
+	}
+
+	if (displayed_info == TRUE) {
+		if (argc > 3 && strcmp(argv[3], "help") == 0) {
+			printf("\n\n"
+			       "Capability Legend (Not all may be supported)\n"
+			       "-----------------\n"
+			       " I [ Infrastructure ]\n"
+			       " A [ Ad-hoc ]\n"
+			       " W [ WPA IE ]\n"
+			       " 2 [ WPA2/RSN IE ]\n"
+			       " M [ WMM IE ]\n"
+			       " C [ Call Admission Control - WMM IE, VO ACM set ]\n"
+			       " D [ Spectrum Management - DFS (11h) ]\n"
+			       " K [ 11k ]\n"
+			       " R [ 11r ]\n"
+			       " S [ WPS ]\n"
+			       " N [ HT (11n) ]\n"
+			       " AC [VHT (11ac) ]\n" "\n\n");
+		}
+	} else {
+		printf("< No Scan Results >\n");
+	}
+
+	for (curr = scan_list_head; curr != NULL; curr = next) {
+		next = curr->next;
+		free(curr);
+	}
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process getscantable command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @param scan_req  A pointer to wlan_ioctl_user_scan_cfg structure
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_getscantable(int argc, char *argv[])
+{
+	return wlan_process_getscantable(argc, argv, NULL);
+}
+
+/**
+ *  @brief Prepare setuserscan command buffer
+ *  @param scan_req pointer to wlan_ioctl_user_scan_cfg structure
+ *  @param num      Number of arguments
+ *  @param args     Arguments list
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static int
+prepare_setuserscan_buffer(wlan_ioctl_user_scan_cfg *scan_req, t_u32 num,
+			   char *args[])
+{
+	int arg_idx = 0;
+	int num_ssid = 0;
+	char *parg_tok = NULL;
+	char *pchan_tok = NULL;
+	char *parg_cookie = NULL;
+	char *pchan_cookie = NULL;
+	int chan_parse_idx = 0;
+	int chan_cmd_idx = 0;
+	char chan_scratch[MAX_CHAN_SCRATCH];
+	char *pscratch = NULL;
+	int tmp_idx = 0;
+	int scan_time = 0;
+	int is_radio_set = 0;
+	unsigned int mac[ETH_ALEN];
+
+	for (arg_idx = 0; arg_idx < (int)num; arg_idx++) {
+		if (strncmp(args[arg_idx], "ssid=", strlen("ssid=")) == 0) {
+			/* "ssid" token string handler */
+			if (num_ssid < MRVDRV_MAX_SSID_LIST_LENGTH) {
+				strncpy(scan_req->ssid_list[num_ssid].ssid,
+					args[arg_idx] + strlen("ssid="),
+					sizeof(scan_req->ssid_list[num_ssid].
+					       ssid));
+
+				scan_req->ssid_list[num_ssid].max_len = 0;
+				setuserscan_filter = SSID_FILTER;
+				num_ssid++;
+				num_ssid_filter++;
+			}
+		} else if (strncmp(args[arg_idx], "bssid=", strlen("bssid=")) ==
+			   0) {
+			/* "bssid" token string handler */
+			sscanf(args[arg_idx] + strlen("bssid="),
+			       "%2x:%2x:%2x:%2x:%2x:%2x", mac + 0, mac + 1,
+			       mac + 2, mac + 3, mac + 4, mac + 5);
+			setuserscan_filter = BSSID_FILTER;
+			for (tmp_idx = 0;
+			     (unsigned int)tmp_idx < NELEMENTS(mac);
+			     tmp_idx++) {
+				scan_req->specific_bssid[tmp_idx] =
+					(t_u8)mac[tmp_idx];
+			}
+		} else if (strncmp(args[arg_idx], "chan=", strlen("chan=")) ==
+			   0) {
+			/* "chan" token string handler */
+			parg_tok = args[arg_idx] + strlen("chan=");
+
+			if (strlen(parg_tok) > MAX_CHAN_SCRATCH) {
+				printf("Error: Specified channels exceeds max limit\n");
+				return MLAN_STATUS_FAILURE;
+			}
+			is_radio_set = FALSE;
+
+			while ((parg_tok =
+				strtok_r(parg_tok, ",",
+					 &parg_cookie)) != NULL) {
+
+				memset(chan_scratch, 0x00,
+				       sizeof(chan_scratch));
+				pscratch = chan_scratch;
+
+				for (chan_parse_idx = 0;
+				     (unsigned int)chan_parse_idx <
+				     strlen(parg_tok); chan_parse_idx++) {
+					if (isalpha
+					    (*(parg_tok + chan_parse_idx))) {
+						*pscratch++ = ' ';
+					}
+
+					*pscratch++ =
+						*(parg_tok + chan_parse_idx);
+				}
+				*pscratch = 0;
+				parg_tok = NULL;
+
+				pchan_tok = chan_scratch;
+
+				while ((pchan_tok = strtok_r(pchan_tok, " ",
+							     &pchan_cookie)) !=
+				       NULL) {
+					if (isdigit(*pchan_tok)) {
+						scan_req->
+							chan_list[chan_cmd_idx].
+							chan_number =
+							atoi(pchan_tok);
+						if (scan_req->
+						    chan_list[chan_cmd_idx].
+						    chan_number >
+						    MAX_CHAN_BG_BAND)
+							scan_req->
+								chan_list
+								[chan_cmd_idx].
+								radio_type = 1;
+					} else {
+						switch (toupper(*pchan_tok)) {
+						case 'A':
+							scan_req->
+								chan_list
+								[chan_cmd_idx].
+								radio_type = 1;
+							is_radio_set = TRUE;
+							break;
+						case 'B':
+						case 'G':
+							scan_req->
+								chan_list
+								[chan_cmd_idx].
+								radio_type = 0;
+							is_radio_set = TRUE;
+							break;
+						case 'N':
+							break;
+						case 'C':
+							scan_req->
+								chan_list
+								[chan_cmd_idx].
+								scan_type =
+								MLAN_SCAN_TYPE_ACTIVE;
+							break;
+						case 'P':
+							scan_req->
+								chan_list
+								[chan_cmd_idx].
+								scan_type =
+								MLAN_SCAN_TYPE_PASSIVE;
+							break;
+						default:
+							printf("Error: Band type not supported!\n");
+							return -EOPNOTSUPP;
+						}
+						if (!chan_cmd_idx &&
+						    !scan_req->
+						    chan_list[chan_cmd_idx].
+						    chan_number && is_radio_set)
+							scan_req->
+								chan_list
+								[chan_cmd_idx].
+								radio_type |=
+								BAND_SPECIFIED;
+					}
+					pchan_tok = NULL;
+				}
+				if (((scan_req->chan_list[chan_cmd_idx].
+				      chan_number > MAX_CHAN_BG_BAND)
+				     && !scan_req->chan_list[chan_cmd_idx].
+				     radio_type) ||
+				    ((scan_req->chan_list[chan_cmd_idx].
+				      chan_number < MAX_CHAN_BG_BAND)
+				     && (scan_req->chan_list[chan_cmd_idx].
+					 radio_type == 1))) {
+					printf("Error: Invalid Radio type: chan=%d radio_type=%d\n", scan_req->chan_list[chan_cmd_idx].chan_number, scan_req->chan_list[chan_cmd_idx].radio_type);
+					return MLAN_STATUS_FAILURE;
+				}
+				chan_cmd_idx++;
+			}
+		} else if (strncmp(args[arg_idx], "gap=", strlen("gap=")) == 0) {
+			scan_req->scan_chan_gap =
+				atoi(args[arg_idx] + strlen("gap="));
+		} else if (strncmp(args[arg_idx], "keep=", strlen("keep=")) ==
+			   0) {
+			/* "keep" token string handler */
+			scan_req->keep_previous_scan =
+				atoi(args[arg_idx] + strlen("keep="));
+		} else if (strncmp(args[arg_idx], "dur=", strlen("dur=")) == 0) {
+			/* "dur" token string handler */
+			scan_time = atoi(args[arg_idx] + strlen("dur="));
+			scan_req->chan_list[0].scan_time = scan_time;
+
+		} else if (strncmp(args[arg_idx], "wc=", strlen("wc=")) == 0) {
+
+			if (num_ssid < MRVDRV_MAX_SSID_LIST_LENGTH) {
+				/* "wc" token string handler */
+				pscratch = strrchr(args[arg_idx], ',');
+
+				if (pscratch) {
+					*pscratch = 0;
+					pscratch++;
+
+					if (isdigit(*pscratch)) {
+						scan_req->ssid_list[num_ssid].
+							max_len =
+							atoi(pscratch);
+					} else {
+						scan_req->ssid_list[num_ssid].
+							max_len = *pscratch;
+					}
+				} else {
+					/* Standard wildcard matching */
+					scan_req->ssid_list[num_ssid].max_len =
+						0xFF;
+				}
+
+				strncpy(scan_req->ssid_list[num_ssid].ssid,
+					args[arg_idx] + strlen("wc="),
+					sizeof(scan_req->ssid_list[num_ssid].
+					       ssid));
+
+				num_ssid++;
+			}
+		} else if (strncmp(args[arg_idx], "probes=", strlen("probes="))
+			   == 0) {
+			/* "probes" token string handler */
+			scan_req->num_probes =
+				atoi(args[arg_idx] + strlen("probes="));
+			if (scan_req->num_probes > MAX_PROBES) {
+				fprintf(stderr, "Invalid probes (> %d)\n",
+					MAX_PROBES);
+				return -EOPNOTSUPP;
+			}
+		} else if (strncmp
+			   (args[arg_idx], "bss_type=",
+			    strlen("bss_type=")) == 0) {
+			/* "bss_type" token string handler */
+			scan_req->bss_mode =
+				atoi(args[arg_idx] + strlen("bss_type="));
+			switch (scan_req->bss_mode) {
+			case MLAN_SCAN_MODE_BSS:
+			case MLAN_SCAN_MODE_IBSS:
+				break;
+			case MLAN_SCAN_MODE_ANY:
+			default:
+				/* Set any unknown types to ANY */
+				scan_req->bss_mode = MLAN_SCAN_MODE_ANY;
+				break;
+			}
+		} else if (strncmp
+			   (args[arg_idx], "scan_type=",
+			    strlen("scan_type=")) == 0) {
+			/* "scan_type" token string handler */
+			scan_req->ext_scan_type =
+				atoi(args[arg_idx] + strlen("scan_type="));
+		}
+	}
+
+	/* Update all the channels to have the same scan time */
+	for (tmp_idx = 1; tmp_idx < chan_cmd_idx; tmp_idx++) {
+		scan_req->chan_list[tmp_idx].scan_time = scan_time;
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process setuserscan command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_setuserscan(int argc, char *argv[])
+{
+	wlan_ioctl_user_scan_cfg *scan_req = NULL;
+	t_u8 *pos = NULL;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int status = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Flag it for our use */
+	pos = buffer;
+	strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL));
+	pos += (strlen(CMD_MARVELL));
+
+	/* Insert command */
+	strncpy((char *)pos, (char *)argv[2], strlen(argv[2]));
+	pos += (strlen(argv[2]));
+
+	/* Insert arguments */
+	scan_req = (wlan_ioctl_user_scan_cfg *)pos;
+
+	if (prepare_setuserscan_buffer(scan_req, (argc - 3), &argv[3])) {
+		printf("ERR:Invalid parameter\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: setuserscan fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	if (argc > 3) {
+		if (!strcmp(argv[3], "sort_by_ch")) {
+			argv[3] = "ch";
+		} else {
+			argc = 0;
+		}
+	}
+	do {
+		argv[2] = "getscantable";
+		status = wlan_process_getscantable(argc, argv, scan_req);
+	} while (status == -EAGAIN);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process extended capabilities configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_extcapcfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL, ext_cap[9];
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	IEEEtypes_Header_t ie;
+
+	if (argc > 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX extcapcfg <extcapa>\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (argc == 4 && MLAN_STATUS_FAILURE == ishexstring(argv[3])) {
+		printf("ERR:Only hex digits are allowed.\n");
+		printf("Syntax: ./mlanutl mlanX extcapcfg <extcapa>\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Only insert command */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	if (argc == 4) {
+		if (!strncasecmp("0x", argv[3], 2))
+			argv[3] += 2;
+
+		if (strlen(argv[3]) > 2 * sizeof(ext_cap)) {
+			printf("ERR:Incorrect length of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX extcapcfg <extcapa>\n");
+			return MLAN_STATUS_FAILURE;
+		}
+
+		memset(ext_cap, 0, sizeof(ext_cap));
+		ie.element_id = TLV_TYPE_EXTCAP;
+		ie.len = sizeof(ext_cap);
+
+		string2raw(argv[3], ext_cap);
+		memcpy(buffer + strlen(CMD_MARVELL) + strlen(argv[2]), &ie,
+		       sizeof(ie));
+		memcpy(buffer + strlen(CMD_MARVELL) + strlen(argv[2]) +
+		       sizeof(ie), ext_cap, sizeof(ext_cap));
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr,
+			"mlanutl: extended capabilities configure fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	hexdump("Extended capabilities", buffer + sizeof(IEEEtypes_Header_t),
+		((IEEEtypes_Header_t *)buffer)->len, ' ');
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Cancel ongoing scan
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_cancelscan(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	if (argc != 3) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX cancelscan\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Only insert command */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: cancel scan fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief Process deep sleep configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_deepsleep(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: deepsleep fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("Deepsleep command response: %s\n", buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process ipaddr command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_ipaddr(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* The argument being a string, this requires special handling */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+	if (argc >= 4) {
+		strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])),
+		       argv[3]);
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: ipaddr fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("IP address Configuration: %s\n", (char *)buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process otpuserdata command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_otpuserdata(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	if (argc < 4) {
+		printf("ERR:No argument\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: otpuserdata fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	hexdump("OTP user data: ", buffer,
+		MIN(cmd->used_len, a2hex_or_atoi(argv[3])), ' ');
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process countrycode setting
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_countrycode(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct eth_priv_countrycode *countrycode = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* The argument being a string, this requires special handling */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+	if (argc >= 4) {
+		strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])),
+		       argv[3]);
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: countrycode fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	countrycode = (struct eth_priv_countrycode *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("Country code: %s\n", countrycode->country_code);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process TCP ACK enhancement configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tcpackenh(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: tcpackenh fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("TCP Ack enhancement: ");
+	if (buffer[0])
+		printf("enabled.\n");
+	else
+		printf("disabled.\n");
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef REASSOCIATION
+/**
+ *  @brief Process asynced essid setting
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_assocessid(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* The argument being a string, this requires special handling */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+	if (argc >= 4) {
+		strcpy((char *)(buffer + strlen(CMD_MARVELL) + strlen(argv[2])),
+		       argv[3]);
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: assocessid fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("Set Asynced ESSID: %s\n", (char *)buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+
+}
+#endif
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Process listen interval configuration
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_listeninterval(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: listen interval fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	if (argc == 3)
+		printf("Listen interval command response: %s\n", buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process power save mode setting
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_psmode(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int psmode = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: psmode fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	psmode = *(int *)buffer;
+	printf("PS mode: %d\n", psmode);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+#ifdef DEBUG_LEVEL1
+/**
+ *  @brief Process driver debug configuration
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_drvdbg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	t_u32 drvdbg;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: drvdbg config fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		memcpy(&drvdbg, buffer, sizeof(drvdbg));
+		printf("drvdbg: 0x%08x\n", drvdbg);
+#ifdef DEBUG_LEVEL2
+		printf("MINFO  (%08x) %s\n", MINFO,
+		       (drvdbg & MINFO) ? "X" : "");
+		printf("MWARN  (%08x) %s\n", MWARN,
+		       (drvdbg & MWARN) ? "X" : "");
+		printf("MENTRY (%08x) %s\n", MENTRY,
+		       (drvdbg & MENTRY) ? "X" : "");
+#endif
+		printf("MMPA_D (%08x) %s\n", MMPA_D,
+		       (drvdbg & MMPA_D) ? "X" : "");
+		printf("MIF_D  (%08x) %s\n", MIF_D,
+		       (drvdbg & MIF_D) ? "X" : "");
+		printf("MFW_D  (%08x) %s\n", MFW_D,
+		       (drvdbg & MFW_D) ? "X" : "");
+		printf("MEVT_D (%08x) %s\n", MEVT_D,
+		       (drvdbg & MEVT_D) ? "X" : "");
+		printf("MCMD_D (%08x) %s\n", MCMD_D,
+		       (drvdbg & MCMD_D) ? "X" : "");
+		printf("MDAT_D (%08x) %s\n", MDAT_D,
+		       (drvdbg & MDAT_D) ? "X" : "");
+		printf("MIOCTL (%08x) %s\n", MIOCTL,
+		       (drvdbg & MIOCTL) ? "X" : "");
+		printf("MINTR  (%08x) %s\n", MINTR,
+		       (drvdbg & MINTR) ? "X" : "");
+		printf("MEVENT (%08x) %s\n", MEVENT,
+		       (drvdbg & MEVENT) ? "X" : "");
+		printf("MCMND  (%08x) %s\n", MCMND,
+		       (drvdbg & MCMND) ? "X" : "");
+		printf("MDATA  (%08x) %s\n", MDATA,
+		       (drvdbg & MDATA) ? "X" : "");
+		printf("MERROR (%08x) %s\n", MERROR,
+		       (drvdbg & MERROR) ? "X" : "");
+		printf("MFATAL (%08x) %s\n", MFATAL,
+		       (drvdbg & MFATAL) ? "X" : "");
+		printf("MMSG   (%08x) %s\n", MMSG, (drvdbg & MMSG) ? "X" : "");
+
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief Process hscfg configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_hscfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	struct eth_priv_hs_cfg *hscfg;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: hscfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	hscfg = (struct eth_priv_hs_cfg *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("HS Configuration:\n");
+		printf("  Conditions: %d\n", (int)hscfg->conditions);
+		printf("  GPIO: %d\n", (int)hscfg->gpio);
+		printf("  GAP: %d\n", (int)hscfg->gap);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process hssetpara configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_hssetpara(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: hssetpara fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process wakeup reason
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_wakeupresaon(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: get wakeup reason fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("Get wakeup reason response: %s\n", buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process hscfg management frame config
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_mgmtfilter(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	FILE *fp = NULL;
+	int ret = MLAN_STATUS_SUCCESS;
+	char line[256], cmdname[256], *pos = NULL, *filter = NULL;
+	int cmdname_found = 0, name_found = 0;
+	int ln = 0, i = 0, numEntries = 0, len = 0;
+	eth_priv_mgmt_frame_wakeup hs_mgmt_filter[2];
+
+	if (argc < 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanutl mlanX mgmtfilter <mgmtfilter.conf>\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	pos = (char *)buffer;
+	strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL));
+	pos += (strlen(CMD_MARVELL));
+	len += (strlen(CMD_MARVELL));
+
+	/* Insert command */
+	strncpy((char *)pos, argv[2], strlen(argv[2]));
+	pos += (strlen(argv[2]));
+	len += (strlen(argv[2]));
+
+	filter = pos;
+
+	cmdname_found = 0;
+	snprintf(cmdname, sizeof(cmdname), "%s={", argv[2]);
+
+	fp = fopen(argv[3], "r");
+	if (fp == NULL) {
+		fprintf(stderr, "Cannot open file %s\n", argv[3]);
+		ret = MLAN_STATUS_FAILURE;
+		if (buffer)
+			free(buffer);
+		goto done;
+	}
+
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, cmdname) == 0) {
+			cmdname_found = 1;
+			snprintf(cmdname, sizeof(cmdname), "entry_num=");
+			name_found = 0;
+			while ((pos =
+				mlan_config_get_line(fp, line, sizeof(line),
+						     &ln))) {
+				if (strncmp(pos, cmdname, strlen(cmdname)) == 0) {
+					name_found = 1;
+					numEntries =
+						a2hex_or_atoi(pos +
+							      strlen(cmdname));
+					if (numEntries > 2) {
+						printf("mlanutl: NumEntries exceed max number.\
+						We support two entries in currently\n");
+						return MLAN_STATUS_FAILURE;
+					}
+					break;
+				}
+			}
+			if (!name_found) {
+				fprintf(stderr,
+					"mlanutl: NumEntries not found in file '%s'\n",
+					argv[3]);
+				break;
+			}
+			for (i = 0; i < numEntries; i++) {
+				snprintf(cmdname, sizeof(cmdname), "entry_%d={",
+					 i);
+				name_found = 0;
+				while ((pos =
+					mlan_config_get_line(fp, line,
+							     sizeof(line),
+							     &ln))) {
+					if (strncmp
+					    (pos, cmdname,
+					     strlen(cmdname)) == 0) {
+						name_found = 1;
+						break;
+					}
+				}
+				if (!name_found) {
+					fprintf(stderr,
+						"mlanutl: %s not found in file '%s'\n",
+						cmdname, argv[3]);
+					break;
+				}
+				snprintf(cmdname, sizeof(cmdname), "action=");
+				name_found = 0;
+				while ((pos =
+					mlan_config_get_line(fp, line,
+							     sizeof(line),
+							     &ln))) {
+					if (strncmp
+					    (pos, cmdname,
+					     strlen(cmdname)) == 0) {
+						name_found = 1;
+						hs_mgmt_filter[i].action =
+							a2hex_or_atoi(pos +
+								      strlen
+								      (cmdname));
+						break;
+					}
+				}
+				if (!name_found) {
+					fprintf(stderr,
+						"mlanutl: %s not found in file '%s'\n",
+						cmdname, argv[3]);
+					break;
+				}
+				snprintf(cmdname, sizeof(cmdname), "type=");
+				name_found = 0;
+				while ((pos =
+					mlan_config_get_line(fp, line,
+							     sizeof(line),
+							     &ln))) {
+					if (strncmp
+					    (pos, cmdname,
+					     strlen(cmdname)) == 0) {
+						name_found = 1;
+						hs_mgmt_filter[i].type =
+							a2hex_or_atoi(pos +
+								      strlen
+								      (cmdname));
+						break;
+					}
+				}
+				if (!name_found) {
+					fprintf(stderr,
+						"mlanutl: %s not found in file '%s'\n",
+						cmdname, argv[3]);
+					break;
+				}
+				snprintf(cmdname, sizeof(cmdname),
+					 "frame_mask=");
+				name_found = 0;
+				while ((pos =
+					mlan_config_get_line(fp, line,
+							     sizeof(line),
+							     &ln))) {
+					if (strncmp
+					    (pos, cmdname,
+					     strlen(cmdname)) == 0) {
+						name_found = 1;
+						hs_mgmt_filter[i].frame_mask =
+							a2hex_or_atoi(pos +
+								      strlen
+								      (cmdname));
+						break;
+					}
+				}
+				if (!name_found) {
+					fprintf(stderr,
+						"mlanutl: %s not found in file '%s'\n",
+						cmdname, argv[3]);
+					break;
+				}
+			}
+			break;
+		}
+	}
+	fclose(fp);
+	if (!cmdname_found) {
+		fprintf(stderr, "mlanutl: ipPkt data not found in file '%s'\n",
+			argv[3]);
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memcpy(filter, (t_u8 *)hs_mgmt_filter,
+	       sizeof(eth_priv_mgmt_frame_wakeup) * numEntries);
+	len += sizeof(eth_priv_mgmt_frame_wakeup) * numEntries;
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = len;
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: cloud keep alive fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+done:
+	return ret;
+}
+
+/**
+ *  @brief Process scancfg configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_scancfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	struct eth_priv_scan_cfg *scancfg;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: scancfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	scancfg = (struct eth_priv_scan_cfg *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("Scan Configuration:\n");
+		printf("    Scan Type:              %d (%s)\n",
+		       scancfg->scan_type,
+		       (scancfg->scan_type ==
+			1) ? "Active" : (scancfg->scan_type ==
+					 2) ? "Passive" : "");
+		printf("    Scan Mode:              %d (%s)\n",
+		       scancfg->scan_mode,
+		       (scancfg->scan_mode ==
+			1) ? "BSS" : (scancfg->scan_mode ==
+				      2) ? "IBSS" : (scancfg->scan_mode ==
+						     3) ? "Any" : "");
+		printf("    Scan Probes:            %d (%s)\n",
+		       scancfg->scan_probe, "per channel");
+		printf("    Specific Scan Time:     %d ms\n",
+		       scancfg->scan_time.specific_scan_time);
+		printf("    Active Scan Time:       %d ms\n",
+		       scancfg->scan_time.active_scan_time);
+		printf("    Passive Scan Time:      %d ms\n",
+		       scancfg->scan_time.passive_scan_time);
+		printf("    Extended Scan Support:  %d (%s)\n",
+		       scancfg->ext_scan,
+		       (scancfg->ext_scan == 0) ? "No" : (scancfg->ext_scan ==
+							  1) ? "Yes"
+		       : (scancfg->ext_scan == 2) ? "Enhanced" : "");
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process warmreset command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_warmreset(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* The argument being a string, this requires special handling */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: warmreset fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+static char *bandwidth[4] = { "20 MHz", "40 MHz", "80 MHz", "160 MHz" };
+
+/**
+ *  @brief Process txpowercfg command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_txpowercfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	struct eth_priv_power_cfg_ext *power_ext = NULL;
+	struct eth_priv_power_group *power_group = NULL;
+	int i = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(2 * BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = 2 * BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: txpowercfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	power_ext = (struct eth_priv_power_cfg_ext *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("Tx Power Configurations:\n");
+		for (i = 0; i < power_ext->num_pwr_grp; i++) {
+			power_group = &power_ext->power_group[i];
+			if (power_group->rate_format == MLAN_RATE_FORMAT_HT) {
+				if (power_group->bandwidth == MLAN_HT_BW20) {
+					power_group->first_rate_ind += 12;
+					power_group->last_rate_ind += 12;
+				} else if (power_group->bandwidth ==
+					   MLAN_HT_BW40) {
+					power_group->first_rate_ind += 140;
+					power_group->last_rate_ind += 140;
+				}
+			}
+			printf("    Power Group %d: \n", i);
+			printf("        Bandwidth:        %3s %s\n",
+			       rate_format[power_group->rate_format],
+			       bandwidth[power_group->bandwidth]);
+			if (power_group->rate_format == 2)
+    /** NSS */
+				printf("        NSS:              %3d\n",
+				       power_group->nss);
+			printf("        first rate index: %3d\n",
+			       power_group->first_rate_ind);
+			printf("        last rate index:  %3d\n",
+			       power_group->last_rate_ind);
+			printf("        minimum power:    %3d dBm\n",
+			       power_group->power_min);
+			printf("        maximum power:    %3d dBm\n",
+			       power_group->power_max);
+			printf("        power step:       %3d\n",
+			       power_group->power_step);
+			printf("\n");
+			power_group++;
+		}
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process pscfg command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_pscfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	struct eth_priv_ds_ps_cfg *ps_cfg = NULL;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: pscfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	ps_cfg = (struct eth_priv_ds_ps_cfg *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("PS Configurations:\n");
+		printf("%d", (int)ps_cfg->ps_null_interval);
+		printf("  %d", (int)ps_cfg->multiple_dtim_interval);
+		printf("  %d", (int)ps_cfg->listen_interval);
+		printf("  %d  ", (int)ps_cfg->adhoc_awake_period);
+		printf("  %d", (int)ps_cfg->bcn_miss_timeout);
+		printf("  %d", (int)ps_cfg->delay_to_ps);
+		printf("  %d", (int)ps_cfg->ps_mode);
+		printf("\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process bcntimeoutcfg command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_bcntimeoutcfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	if (argc != 7) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p]\n");
+		return -EINVAL;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return -ENOMEM;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return -ENOMEM;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: bcntimeoutcfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return -EFAULT;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return 0;
+}
+
+/**
+ *  @brief Process sleeppd configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_sleeppd(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int sleeppd = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: sleeppd fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	sleeppd = *(int *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("Sleep Period: %d ms\n", sleeppd);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tx control configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_txcontrol(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	t_u32 txcontrol = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: txcontrol fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	txcontrol = *(t_u32 *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("Tx control: 0x%x\n", txcontrol);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Performs the ioctl operation to send the command to driver.
+ *  @param cmd_buf       Pointer to the command buffer
+ *  @param buf_size      Size of the allocated command buffer
+ *  @return              MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static int
+tdls_ioctl(t_u8 *cmd_buf, t_u16 buf_size)
+{
+	struct ifreq ifr;
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd_buf;
+
+	/* Perform ioctl */
+	if (ioctl(sockfd, TDLS_IOCTL, &ifr)) {
+		perror("");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief host tdls config
+ *  @param argc     Number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_host_tdls_config(int argc, char *argv[])
+{
+	host_tdls_cfg *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, i = 0, cmd_found = 0;
+	char *args[30], *pos = NULL;
+	t_u16 cmd_len = 0, tlv_len_supp_chan = 0;
+	t_u16 no_of_supp_chan_sub_band = 0, num_of_regulatory_class =
+		0, tlv_len_reg_class;
+	t_u8 *buffer = NULL;
+	tlvbuf_SupportedChannels_t *supp_chan = NULL;
+	tlvbuf_RegulatoryClass_t *reg_class = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX host_tdls_config <config/host_tdls.conf>\n");
+		printf("Syntax: ./mlanutl mlanX host_tdls_config <0/1> \n ");
+		exit(1);
+	}
+
+	cmd_len = sizeof(host_tdls_cfg);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+	param_buf = (host_tdls_cfg *) buffer;
+	param_buf->action = ACTION_HOST_TDLS_CONFIG;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("ERR:Incorrect arguments.\n");
+		printf("Syntax: ./mlanutl mlanX host_tdls_config <config/host_tdls.conf>\n");
+		exit(1);
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+		if (strcmp(args[0], "uapsd_support") == 0) {
+			param_buf->uapsd_support = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "cs_support") == 0) {
+			param_buf->cs_support = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "SupportedChannels") == 0) {
+			/* Append a new TLV */
+			supp_chan =
+				(tlvbuf_SupportedChannels_t *)(buffer +
+							       cmd_len);
+			supp_chan->tag = TLV_TYPE_SUPPORTED_CHANNELS;
+			supp_chan->length = sizeof(tlvbuf_SupportedChannels_t)
+				- TLVHEADER_LEN;
+			tlv_len_supp_chan = sizeof(tlvbuf_SupportedChannels_t);
+			cmd_len += tlv_len_supp_chan;
+		} else if (strncmp(args[0], "FirstChannelNo", 14) == 0) {
+			supp_chan->subband[no_of_supp_chan_sub_band].
+				start_chan = atoi(args[1]);
+		} else if (strcmp(args[0], "NumberofSubBandChannels") == 0) {
+			supp_chan->subband[no_of_supp_chan_sub_band].num_chans =
+				atoi(args[1]);
+			no_of_supp_chan_sub_band++;
+			tlv_len_supp_chan +=
+				sizeof(IEEEtypes_SupportChan_Subband_t);
+			supp_chan->length +=
+				sizeof(IEEEtypes_SupportChan_Subband_t);
+			cmd_len += sizeof(IEEEtypes_SupportChan_Subband_t);
+			endian_convert_tlv_header_out(supp_chan);
+		} else if (strcmp(args[0], "SupportedRegulatoryClasses") == 0) {
+			/* Append a new TLV */
+			reg_class =
+				(tlvbuf_RegulatoryClass_t *)(buffer + cmd_len);
+			tlv_len_reg_class = sizeof(tlvbuf_RegulatoryClass_t);
+			reg_class->tag = TLV_TYPE_REGULATORY_CLASSES;
+			cmd_len += tlv_len_reg_class;
+		} else if (strcmp(args[0], "CurrentRegulatoryClass") == 0) {
+			reg_class->regulatory_class.cur_regulatory_class =
+				atoi(args[1]);
+			reg_class->length = 1;
+		} else if (strcmp(args[0], "NumofRegulatoryClasses") == 0) {
+			num_of_regulatory_class = atoi(args[1]);
+			reg_class->length += num_of_regulatory_class;
+			cmd_len += num_of_regulatory_class;
+			endian_convert_tlv_header_out(reg_class);
+		} else if (strcmp(args[0], "ListOfRegulatoryClasses") == 0) {
+			for (i = 0; i < num_of_regulatory_class; i++)
+				reg_class->regulatory_class.
+					regulatory_classes_list[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		}
+	}
+	/* adjust for size of action and tlv_len, capInfo */
+	param_buf->tlv_len = cmd_len - sizeof(host_tdls_cfg);
+
+	hexdump("host_tdls_config", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS Info settings sucessfully set.\n");
+	} else {
+		printf("ERR:Could not set TDLS info configuration.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief enable/disable tdls config
+ *  @param argc     Number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_config(int argc, char *argv[])
+{
+
+	tdls_config *param_buf = NULL;
+	int ret = 0;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_config <0/1>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_config);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_config *) buffer;
+	param_buf->action = ACTION_TDLS_CONFIG;
+
+	param_buf->data = (t_u16)A2HEXDECIMAL(argv[3]);
+	if ((param_buf->data != 0) && (param_buf->data != 1)) {
+		printf("ERR:Incorrect arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_config <0/1>\n");
+		goto done;
+	}
+	hexdump("tdls_config ", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS %s successful.\n",
+		       (param_buf->data) ? "enable" : "disable");
+	} else {
+		printf("ERR:TDLS %s failed.\n",
+		       (param_buf->data) ? "enable" : "disable");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_setinfo
+ *  @param argc     Number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_setinfo(int argc, char *argv[])
+{
+	tdls_setinfo *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, arg_num = 0, ret = 0, i = 0, cmd_found = 0, pairwise_index =
+		0, akm_index = 0, pmkid_index = 0;
+	char *args[30], *pos = NULL;
+	t_u16 cmd_len = 0, tlv_len = 0, tlv_len_rsn = 0, tlv_len_supp_chan =
+		0, tlv_len_domain = 0;
+	t_u16 no_of_sub_band = 0, no_of_supp_chan_sub_band =
+		0, pairwise_offset = 0, akm_offset =
+		0, num_of_regulatory_class = 0, tlv_len_reg_class;
+	t_u16 akm_count = 0, pmk_count = 0, rsn_cap = 0;
+	t_u8 *buffer = NULL;
+	char country[COUNTRY_CODE_LEN];
+	tlvbuf_DomainParamSet_t *domain = NULL;
+	tlvbuf_SupportedChannels_t *supp_chan = NULL;
+	tlvbuf_RegulatoryClass_t *reg_class = NULL;
+	tlvbuf_HTCap_t *tlv_ht_cap = NULL;
+	tlvbuf_RsnParamSet_t *rsn_ie = NULL;
+	tlvbuf_HTInfo_t *tlv_ht_info = NULL;
+	t_u8 pairwise_cipher_suite[PAIRWISE_CIPHER_SUITE_LEN];
+	t_u8 akm_suite[AKM_SUITE_LEN];
+	t_u8 pmkid[PMKID_LEN];
+	tlvbuf_VHTCap_t *tlv_vht_cap = NULL;
+	tlvbuf_VHTOpra_t *tlv_vht_oper = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_setinfo <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_setinfo);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+	param_buf = (tdls_setinfo *)buffer;
+	param_buf->action = ACTION_TDLS_SETINFO;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		arg_num = parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+		if (strcmp(args[0], "CapInfo") == 0) {
+			param_buf->cap_info = (t_u16)A2HEXDECIMAL(args[1]);
+			param_buf->cap_info = cpu_to_le16(param_buf->cap_info);
+		} else if (strcmp(args[0], "Rate") == 0) {
+			tlvbuf_RatesParamSet_t *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_RatesParamSet_t) + arg_num - 1;
+			tlv = (tlvbuf_RatesParamSet_t *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = TLV_TYPE_RATES;
+			tlv->length = arg_num - 1;
+			for (i = 0; i < tlv->length; i++) {
+				tlv->rates[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			endian_convert_tlv_header_out(tlv);
+		} else if (strcmp(args[0], "QosInfo") == 0) {
+			tlvbuf_QosInfo_t *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_QosInfo_t);
+			tlv = (tlvbuf_QosInfo_t *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = TLV_TYPE_QOSINFO;
+			tlv->length = sizeof(tlvbuf_QosInfo_t) - TLVHEADER_LEN;
+			tlv->u.qos_info_byte = (t_u8)A2HEXDECIMAL(args[1]);
+			if ((tlv->u.qos_info_byte != 0) &&
+			    (tlv->u.qos_info_byte != 0x0F)) {
+				printf("Invalid QosInfo. Should be 0x00 or 0x0F.\n");
+				goto done;
+			}
+			endian_convert_tlv_header_out(tlv);
+		} else if (strcmp(args[0], "ExtendCapabilities") == 0) {
+			tlvbuf_ExtCap_t *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_ExtCap_t) + arg_num - 1;
+			tlv = (tlvbuf_ExtCap_t *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = TLV_TYPE_EXTCAP;
+			tlv->length = arg_num - 1;
+			for (i = 0; i < tlv->length; i++) {
+				tlv->ext_cap[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			endian_convert_tlv_header_out(tlv);
+		} else if (strcmp(args[0], "HTCapability") == 0) {
+			/* Append a new TLV */
+			tlv_ht_cap = (tlvbuf_HTCap_t *)(buffer + cmd_len);
+			tlv_len = sizeof(tlvbuf_HTCap_t);
+			tlv_ht_cap->tag = TLV_TYPE_HT_CAP;
+			tlv_ht_cap->length =
+				sizeof(tlvbuf_HTCap_t) - TLVHEADER_LEN;
+			cmd_len += tlv_len;
+			endian_convert_tlv_header_out(tlv_ht_cap);
+		} else if (strcmp(args[0], "HTCapabilityInfo") == 0) {
+			tlv_ht_cap->ht_cap.ht_cap_info =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_ht_cap->ht_cap.ht_cap_info =
+				cpu_to_le16(tlv_ht_cap->ht_cap.ht_cap_info);
+		} else if (strcmp(args[0], "AMPDUParam") == 0) {
+			tlv_ht_cap->ht_cap.ampdu_param =
+				(t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "SupportedMCSSet") == 0) {
+			for (i = 0; i < MCS_SET_LEN; i++)
+				tlv_ht_cap->ht_cap.supported_mcs_set[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "HTExtCapability") == 0) {
+			tlv_ht_cap->ht_cap.ht_ext_cap =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_ht_cap->ht_cap.ht_ext_cap =
+				cpu_to_le16(tlv_ht_cap->ht_cap.ht_ext_cap);
+		} else if (strcmp(args[0], "TxBfCapability") == 0) {
+			tlv_ht_cap->ht_cap.tx_bf_cap =
+				(t_u32)A2HEXDECIMAL(args[1]);
+			tlv_ht_cap->ht_cap.tx_bf_cap =
+				cpu_to_le32(tlv_ht_cap->ht_cap.tx_bf_cap);
+		} else if (strcmp(args[0], "AntennaSel") == 0) {
+			tlv_ht_cap->ht_cap.asel = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "HTInformation") == 0) {
+			/* Append a new TLV */
+			tlv_ht_info = (tlvbuf_HTInfo_t *)(buffer + cmd_len);
+			tlv_len = sizeof(tlvbuf_HTInfo_t);
+			tlv_ht_info->tag = TLV_TYPE_HT_INFO;
+			tlv_ht_info->length =
+				sizeof(tlvbuf_HTInfo_t) - TLVHEADER_LEN;
+			cmd_len += tlv_len;
+			endian_convert_tlv_header_out(tlv_ht_info);
+		} else if (strcmp(args[0], "PrimaryChannel") == 0) {
+			tlv_ht_info->ht_info.pri_chan = A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "Field2") == 0) {
+			tlv_ht_info->ht_info.field2 = A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "Field3") == 0) {
+			tlv_ht_info->ht_info.field3 =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_ht_info->ht_info.field3 =
+				cpu_to_le16(tlv_ht_info->ht_info.field3);
+		} else if (strcmp(args[0], "Field4") == 0) {
+			tlv_ht_info->ht_info.field4 =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_ht_info->ht_info.field4 =
+				cpu_to_le16(tlv_ht_info->ht_info.field4);
+		} else if (strcmp(args[0], "BasicMCSSet") == 0) {
+			if ((arg_num - 1) != MCS_SET_LEN) {
+				printf("Incorrect number of arguments for BasicMCSSet.\n");
+				goto done;
+			}
+			for (i = 0; i < MCS_SET_LEN; i++)
+				tlv_ht_info->ht_info.basic_mcs_set[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "2040BSSCoex") == 0) {
+			tlvbuf_2040BSSCo_t *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_2040BSSCo_t);
+			tlv = (tlvbuf_2040BSSCo_t *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = TLV_TYPE_2040BSS_COEXISTENCE;
+			tlv->length =
+				sizeof(tlvbuf_2040BSSCo_t) - TLVHEADER_LEN;
+			tlv->bss_co_2040.bss_co_2040_value =
+				(t_u8)A2HEXDECIMAL(args[1]);
+			endian_convert_tlv_header_out(tlv);
+		} else if (strcmp(args[0], "RSNInfo") == 0) {
+			/* Append a new TLV */
+			rsn_ie = (tlvbuf_RsnParamSet_t *)(buffer + cmd_len);
+			tlv_len_rsn = sizeof(tlvbuf_RsnParamSet_t);
+			rsn_ie->tag = TLV_TYPE_RSN_IE;
+			rsn_ie->version = VERSION_RSN_IE;
+			rsn_ie->version = cpu_to_le16(rsn_ie->version);
+			cmd_len += tlv_len_rsn;
+		} else if (strcmp(args[0], "GroupCipherSuite") == 0) {
+			for (i = 0; i < GROUP_CIPHER_SUITE_LEN; i++)
+				rsn_ie->group_cipher_suite[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "PairwiseCipherCount") == 0) {
+			rsn_ie->pairwise_cipher_count = (t_u16)atoi(args[1]);
+			rsn_ie->pairwise_cipher_count =
+				cpu_to_le16(rsn_ie->pairwise_cipher_count);
+		} else if (strncmp(args[0], "PairwiseCipherSuite", 19) == 0) {
+			if (pairwise_index > MAX_PAIRWISE_CIPHER_SUITE_COUNT) {
+				printf("PairwiseCipherSuite exceeds max count\n");
+				goto done;
+			}
+			tlv_len_rsn += PAIRWISE_CIPHER_SUITE_LEN;
+			cmd_len += PAIRWISE_CIPHER_SUITE_LEN;
+			for (i = 0; i < PAIRWISE_CIPHER_SUITE_LEN; i++) {
+				pairwise_cipher_suite[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			memcpy((t_u8 *)(rsn_ie->pairwise_cipher_suite +
+					(pairwise_index *
+					 PAIRWISE_CIPHER_SUITE_LEN)),
+			       pairwise_cipher_suite,
+			       PAIRWISE_CIPHER_SUITE_LEN);
+			pairwise_index++;
+			pairwise_offset =
+				pairwise_index * PAIRWISE_CIPHER_SUITE_LEN;
+		} else if (strcmp(args[0], "AKMSuiteCount") == 0) {
+			akm_count = (t_u16)atoi(args[1]);
+			akm_count = cpu_to_le16(akm_count);
+			memcpy((((t_u8 *)(&rsn_ie->akm_suite_count)) +
+				pairwise_offset), &akm_count, sizeof(t_u16));
+		} else if (strncmp(args[0], "AKMSuite", 8) == 0) {
+			if (akm_index > MAX_AKM_SUITE_COUNT) {
+				printf("AKMSuite exceeds max count\n");
+				goto done;
+			}
+			tlv_len_rsn += AKM_SUITE_LEN;
+			cmd_len += AKM_SUITE_LEN;
+			for (i = 0; i < AKM_SUITE_LEN; i++) {
+				akm_suite[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			memcpy((t_u8 *)(rsn_ie->akm_suite +
+					(akm_index * AKM_SUITE_LEN)
+					+ pairwise_offset), akm_suite,
+			       AKM_SUITE_LEN);
+			akm_index++;
+			akm_offset = akm_index * AKM_SUITE_LEN;
+		} else if (strcmp(args[0], "RSNCapability") == 0) {
+			rsn_cap = (t_u16)A2HEXDECIMAL(args[1]);
+			rsn_cap = cpu_to_le16(rsn_cap);
+			memcpy(((t_u8 *)(&(rsn_ie->rsn_capability))) +
+			       pairwise_offset + akm_offset, &rsn_cap,
+			       sizeof(t_u16));
+		} else if (strcmp(args[0], "PMKIDCount") == 0) {
+			pmk_count = (t_u16)atoi(args[1]);
+			pmk_count = cpu_to_le16(pmk_count);
+			memcpy((((t_u8 *)(&rsn_ie->pmkid_count)) +
+				pairwise_offset + akm_offset), &pmk_count,
+			       sizeof(t_u16));
+			rsn_ie->length = tlv_len_rsn - TLVHEADER_LEN;
+			endian_convert_tlv_header_out(rsn_ie);
+		} else if (strncmp(args[0], "PMKIDList", 9) == 0) {
+			if (pmkid_index > MAX_PMKID_COUNT) {
+				printf("PMKIDSuite exceeds max count\n");
+				goto done;
+			}
+			for (i = 0; i < PMKID_LEN; i++)
+				pmkid[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
+			memcpy((t_u8 *)(rsn_ie->pmkid_list +
+					(pmkid_index * PMKID_LEN) +
+					pairwise_offset + akm_offset), pmkid,
+			       PMKID_LEN);
+			pmkid_index++;
+			tlv_len_rsn += PMKID_LEN;
+			cmd_len += PMKID_LEN;
+			/* undo conversion done in PMKIDCount */
+			endian_convert_tlv_header_in(rsn_ie);
+			rsn_ie->length = tlv_len_rsn - TLVHEADER_LEN;
+			endian_convert_tlv_header_out(rsn_ie);
+		} else if (strcmp(args[0], "SupportedChannels") == 0) {
+			/* Append a new TLV */
+			supp_chan =
+				(tlvbuf_SupportedChannels_t *)(buffer +
+							       cmd_len);
+			supp_chan->tag = TLV_TYPE_SUPPORTED_CHANNELS;
+			supp_chan->length = sizeof(tlvbuf_SupportedChannels_t)
+				- TLVHEADER_LEN;
+			tlv_len_supp_chan = sizeof(tlvbuf_SupportedChannels_t);
+			cmd_len += tlv_len_supp_chan;
+		} else if (strncmp(args[0], "FirstChannelNo", 14) == 0) {
+			supp_chan->subband[no_of_supp_chan_sub_band].
+				start_chan = atoi(args[1]);
+		} else if (strcmp(args[0], "NumberofSubBandChannels") == 0) {
+			supp_chan->subband[no_of_supp_chan_sub_band].num_chans =
+				atoi(args[1]);
+			no_of_supp_chan_sub_band++;
+			tlv_len_supp_chan +=
+				sizeof(IEEEtypes_SupportChan_Subband_t);
+			supp_chan->length +=
+				sizeof(IEEEtypes_SupportChan_Subband_t);
+			cmd_len += sizeof(IEEEtypes_SupportChan_Subband_t);
+			endian_convert_tlv_header_out(supp_chan);
+		} else if (strcmp(args[0], "SupportedRegulatoryClasses") == 0) {
+			/* Append a new TLV */
+			reg_class =
+				(tlvbuf_RegulatoryClass_t *)(buffer + cmd_len);
+			tlv_len_reg_class = sizeof(tlvbuf_RegulatoryClass_t);
+			reg_class->tag = TLV_TYPE_REGULATORY_CLASSES;
+			cmd_len += tlv_len_reg_class;
+		} else if (strcmp(args[0], "CurrentRegulatoryClass") == 0) {
+			reg_class->regulatory_class.cur_regulatory_class =
+				atoi(args[1]);
+			reg_class->length = 1;
+		} else if (strcmp(args[0], "NumofRegulatoryClasses") == 0) {
+			num_of_regulatory_class = atoi(args[1]);
+			reg_class->length += num_of_regulatory_class;
+			cmd_len += num_of_regulatory_class;
+			endian_convert_tlv_header_out(reg_class);
+		} else if (strcmp(args[0], "ListOfRegulatoryClasses") == 0) {
+			for (i = 0; i < num_of_regulatory_class; i++)
+				reg_class->regulatory_class.
+					regulatory_classes_list[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "CountryInfo") == 0) {
+			/* Append a new TLV */
+			domain = (tlvbuf_DomainParamSet_t *)(buffer + cmd_len);
+			domain->tag = TLV_TYPE_DOMAIN;
+			domain->length = sizeof(tlvbuf_DomainParamSet_t)
+				- TLVHEADER_LEN;
+			tlv_len_domain = sizeof(tlvbuf_DomainParamSet_t);
+			cmd_len += tlv_len_domain;
+		} else if (strcmp(args[0], "CountryString") == 0) {
+			strncpy(country, args[1] + 1, strlen(args[1]) - 2);
+			country[strlen(args[1]) - 2] = '\0';
+			for (i = 1; (unsigned int)i < strlen(country) - 2; i++) {
+				if ((country[i] < 'A') || (country[i] > 'z')) {
+					printf("Invalid Country Code\n");
+					goto done;
+				}
+				if (country[i] > 'Z')
+					country[i] = country[i] - 'a' + 'A';
+			}
+			memset(domain->country_code, ' ',
+			       sizeof(domain->country_code));
+			memcpy(domain->country_code, country, strlen(country));
+		} else if (strncmp(args[0], "FirstChannel", 12) == 0) {
+			domain->sub_band[no_of_sub_band].first_chan =
+				atoi(args[1]);
+		} else if (strncmp(args[0], "NumberofChannels", 16) == 0) {
+			domain->sub_band[no_of_sub_band].no_of_chan =
+				atoi(args[1]);
+		} else if (strncmp(args[0], "TxPower", 7) == 0) {
+			domain->sub_band[no_of_sub_band].max_tx_pwr =
+				atoi(args[1]);
+			no_of_sub_band++;
+			domain->length += sizeof(IEEEtypes_SubbandSet_t);
+			tlv_len_domain += sizeof(IEEEtypes_SubbandSet_t);
+			cmd_len += sizeof(IEEEtypes_SubbandSet_t);
+			endian_convert_tlv_header_out(domain);
+		} else if (strcmp(args[0], "VHTCapability") == 0) {
+			/* Append a new TLV */
+			tlv_vht_cap = (tlvbuf_VHTCap_t *)(buffer + cmd_len);
+			tlv_len = sizeof(tlvbuf_VHTCap_t);
+			tlv_vht_cap->tag = VHT_CAPABILITY;
+			tlv_vht_cap->length =
+				sizeof(tlvbuf_VHTCap_t) - TLVHEADER_LEN;
+			cmd_len += tlv_len;
+			endian_convert_tlv_header_out(tlv_vht_cap);
+		} else if (strcmp(args[0], "VHTCapabilityInfo") == 0) {
+			tlv_vht_cap->vht_cap.vht_cap_info =
+				(t_u32)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.vht_cap_info =
+				cpu_to_le16(tlv_vht_cap->vht_cap.vht_cap_info);
+		} else if (strcmp(args[0], "RxMCSMap") == 0) {
+			tlv_vht_cap->vht_cap.mcs_sets.rx_mcs_map =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.mcs_sets.rx_mcs_map =
+				cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets.
+					    rx_mcs_map);
+		} else if (strcmp(args[0], "TxMCSMap") == 0) {
+			tlv_vht_cap->vht_cap.mcs_sets.tx_mcs_map =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.mcs_sets.tx_mcs_map =
+				cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets.
+					    tx_mcs_map);
+		} else if (strcmp(args[0], "RxMaxRate") == 0) {
+			tlv_vht_cap->vht_cap.mcs_sets.rx_max_rate =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.mcs_sets.rx_max_rate =
+				cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets.
+					    rx_max_rate);
+		} else if (strcmp(args[0], "TxMaxRate") == 0) {
+			tlv_vht_cap->vht_cap.mcs_sets.tx_max_rate =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			tlv_vht_cap->vht_cap.mcs_sets.tx_max_rate =
+				cpu_to_le16(tlv_vht_cap->vht_cap.mcs_sets.
+					    tx_max_rate);
+		} else if (strcmp(args[0], "VHTOper") == 0) {
+			/* Append a new TLV */
+			tlv_vht_oper = (tlvbuf_VHTOpra_t *)(buffer + cmd_len);
+			tlv_len = sizeof(tlvbuf_VHTOpra_t);
+			tlv_vht_oper->tag = VHT_OPERATION;
+			tlv_vht_oper->length =
+				sizeof(tlvbuf_VHTOpra_t) - TLVHEADER_LEN;
+			cmd_len += tlv_len;
+			endian_convert_tlv_header_out(tlv_vht_oper);
+		} else if (strcmp(args[0], "ChanWidth") == 0) {
+			tlv_vht_oper->chan_width = A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "ChanCF1") == 0) {
+			tlv_vht_oper->chan_cf1 = A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "ChanCF2") == 0) {
+			tlv_vht_oper->chan_cf2 = (t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "BasicMCSMap") == 0) {
+			if ((arg_num - 1) != VHT_MCS_MAP_LEN) {
+				printf("Incorrect number of arguments for BasicMCSMap.\n");
+				goto done;
+			}
+			for (i = 0; i < VHT_MCS_MAP_LEN; i++)
+				tlv_vht_oper->basic_mcs_map[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		}
+	}
+	/* adjust for size of action and tlv_len, capInfo */
+	param_buf->tlv_len = cmd_len - sizeof(tdls_setinfo);
+
+	hexdump("tdls_setinfo", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS Info settings sucessfully set.\n");
+	} else {
+		printf("ERR:Could not set TDLS info configuration.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_discovery
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_discovery(int argc, char *argv[])
+{
+	tdls_discovery *param_buf = NULL;
+	tdls_discovery_resp *resp_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0, rssi = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0, buf_len = 0, resp_len = 0;
+	t_u8 *buffer = NULL, *raw = NULL;
+	IEEEtypes_Header_t *tlv = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_discovery <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_discovery);
+	buf_len = BUFFER_LENGTH;
+
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, buf_len);
+	param_buf = (tdls_discovery *)buffer;
+	param_buf->action = ACTION_TDLS_DISCOVERY;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			ret = mac2raw(mac_addr, peer_mac);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_discovery", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		hexdump("tdls_response", buffer, 0x40, ' ');
+		printf("TDLS discovery done.\n");
+		resp_buf = (tdls_discovery_resp *)buffer;
+		resp_len = resp_buf->payload_len;
+		printf("Response Length = %d\n", resp_len);
+		if (resp_len > 0) {
+			/* MAC */
+			raw = resp_buf->peer_mac;
+			printf("\tPeer - %02x:%02x:%02x:%02x:%02x:%02x\n",
+			       (unsigned int)raw[0], (unsigned int)raw[1],
+			       (unsigned int)raw[2], (unsigned int)raw[3],
+			       (unsigned int)raw[4], (unsigned int)raw[5]);
+
+			/* RSSI, CapInfo */
+			rssi = (int)(resp_buf->rssi);
+			if (rssi > 0x7f)
+				rssi = -(256 - rssi);
+			printf("\tRssi : %d dBm\n", rssi);
+			printf("\tCapInfo = 0x%02X\n", resp_buf->cap_info);
+
+			resp_len -= ETH_ALEN + sizeof(resp_buf->rssi) +
+				sizeof(resp_buf->cap_info);
+
+			/* TLVs */
+			tlv = (IEEEtypes_Header_t *)&resp_buf->tlv_buffer;
+			while (resp_len > IEEE_HEADER_LEN) {
+				switch (tlv->element_id) {
+				case TLV_TYPE_RATES:
+					printf("\tRates : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_EXTENDED_SUPPORTED_RATES:
+					printf("\tExtended Rates : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_TYPE_QOSINFO:
+					printf("\tQosInfo ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_EXTCAP:
+					printf("\tExtended Cap ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_HT_CAP:
+					printf("\tHT Cap ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_HT_INFO:
+					printf("\tHT Info");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_2040BSS_COEXISTENCE:
+					printf("\t2040 BSS Coex ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_RSN_IE:
+					printf("\tRSN IE ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_SUPPORTED_CHANNELS:
+					printf("\tSupported Channels ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+
+				case TLV_TYPE_DOMAIN:
+					printf("\tDomain Info ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_LINK_IDENTIFIER:
+					printf("\tLink identifier : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_TIMEOUT_INTERVAL:
+					printf("\tTimeout interval : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				case TLV_TYPE_REGULATORY_CLASSES:
+					printf("\t Regulatory classes : ");
+					hexdump(NULL,
+						((t_u8 *)tlv) + IEEE_HEADER_LEN,
+						tlv->len, ' ');
+					break;
+				default:
+					printf("Unknown TLV\n");
+					hexdump(NULL, ((t_u8 *)tlv),
+						IEEE_HEADER_LEN + tlv->len,
+						' ');
+					break;
+				}
+				resp_len -= tlv->len + IEEE_HEADER_LEN;
+				tlv = (IEEEtypes_Header_t *)((t_u8 *)tlv +
+							     tlv->len +
+							     IEEE_HEADER_LEN);
+			}
+		}
+
+	} else {
+		printf("ERR:Command response = Fail!\n");
+	}
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_setup
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_setup(int argc, char *argv[])
+{
+	tdls_setup *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_setup <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_setup);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_setup *) buffer;
+	param_buf->action = ACTION_TDLS_SETUP;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			ret = mac2raw(mac_addr, peer_mac);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "WaitTimems") == 0) {
+			param_buf->wait_time = (t_u32)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "KeyLifetime") == 0) {
+			param_buf->key_life_time = (t_u32)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_setup", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS setup request successful.\n");
+	} else {
+		printf("ERR:TDLS setup request failed.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_teardown
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_teardown(int argc, char *argv[])
+{
+	tdls_teardown *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_teardown <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_teardown);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_teardown *)buffer;
+	param_buf->action = ACTION_TDLS_TEARDOWN;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			ret = mac2raw(mac_addr, peer_mac);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "ReasonCode") == 0) {
+			param_buf->reason_code = (t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_teardown", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS teardown request successful.\n");
+	} else {
+		printf("ERR:TDLS teardown request failed.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_powermode
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_powermode(int argc, char *argv[])
+{
+	tdls_powermode *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_powermode <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_powermode);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_powermode *)buffer;
+	param_buf->action = ACTION_TDLS_POWER_MODE;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			ret = mac2raw(mac_addr, peer_mac);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "PowerMode") == 0) {
+			param_buf->power_mode = (t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->power_mode > 1) {
+				printf("ERR: Incorrect PowerMode value %s\n",
+				       args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_powermode", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS powermode request successful.\n");
+	} else {
+		printf("ERR:TDLS powermode request failed.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_link_status
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_link_status(int argc, char *argv[])
+{
+	int ret = 0;
+	tdls_link_status *param_buf = NULL;
+	tdls_link_status_resp *resp_buf = NULL;
+	t_u16 cmd_len = 0, buf_len = 0, resp_len = 0, curr_link_len = 0;
+	t_u8 no_of_links = 0, peer_mac[ETH_ALEN];
+	t_u8 *buffer = NULL, *raw = NULL;
+	tdls_each_link_status *link_ptr = NULL;
+
+	/* Check arguments */
+	if (argc != 3 && argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_link_status [peer_mac_addr]\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_link_status);
+	buf_len = BUFFER_LENGTH;
+
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, buf_len);
+	param_buf = (tdls_link_status *)buffer;
+	param_buf->action = ACTION_TDLS_LINK_STATUS;
+
+	if (argc == 4) {
+		ret = mac2raw(argv[3], peer_mac);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			printf("ERR: %s Address \n",
+			       ret ==
+			       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret ==
+			       MAC_BROADCAST ? "Broadcast" : "Multicast");
+			goto done;
+		}
+		if (memcmp(peer_mac, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)) {
+			memcpy(buffer + cmd_len, peer_mac, ETH_ALEN);
+			cmd_len += ETH_ALEN;
+		}
+	}
+
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		hexdump("tdls_response", buffer, 0x60, ' ');
+		printf("TDLS Link Status - .\n");
+		resp_buf = (tdls_link_status_resp *)buffer;
+		resp_len = resp_buf->payload_len;
+		printf("Response Length = %d\n", resp_len);
+		no_of_links = resp_buf->active_links;
+		printf("No of active links = %d\n", no_of_links);
+		resp_len--;
+		link_ptr = resp_buf->link_stats;
+		while (resp_len > 0 && no_of_links > 0) {
+			curr_link_len = 0;
+			/* MAC */
+			raw = link_ptr->peer_mac;
+			printf("\tPeer - %02x:%02x:%02x:%02x:%02x:%02x\n",
+			       (unsigned int)raw[0], (unsigned int)raw[1],
+			       (unsigned int)raw[2], (unsigned int)raw[3],
+			       (unsigned int)raw[4], (unsigned int)raw[5]);
+
+			printf("\t %s initiated link.\n",
+			       (link_ptr->link_flags & 0x01) ? "Self" : "Peer");
+			printf("\t Security %s.\n",
+			       (link_ptr->
+				link_flags & 0x02) ? "Enabled" : "Disabled");
+			printf("\t Self PS status = %s.\n",
+			       (link_ptr->
+				link_flags & 0x04) ? "Sleep" : "Active");
+			printf("\t Peer PS status = %s.\n",
+			       (link_ptr->
+				link_flags & 0x08) ? "Sleep" : "Active");
+			printf("\t Channel switch is %ssupported\n",
+			       (link_ptr->link_flags & 0x10) ? "" : "NOT ");
+			printf("\t Current Channel %s\n",
+			       (link_ptr->link_flags & 0x20) ? "off" : "base");
+
+			if (link_ptr->traffic_status) {
+				printf("\t Buffered traffic for");
+				printf("%s",
+				       (link_ptr->
+					traffic_status & 0x01) ? "AC_BK, " :
+				       "");
+				printf("%s",
+				       (link_ptr->
+					traffic_status & 0x02) ? "AC_BE, " :
+				       "");
+				printf("%s",
+				       (link_ptr->
+					traffic_status & 0x04) ? "AC_VI, " :
+				       "");
+				printf("%s",
+				       (link_ptr->
+					traffic_status & 0x08) ? "AC_VO" : "");
+				printf(".\n");
+			}
+			printf("\t Successive Tx Failure count = %d\n",
+			       link_ptr->tx_fail_count);
+			printf("\t Active channel number = %d\n",
+			       link_ptr->active_channel);
+			printf("\t Last Data RSSI        = %d dBm\n",
+			       link_ptr->data_rssi_last);
+			printf("\t Last Data NF          = %d dBm\n",
+			       link_ptr->data_nf_last);
+			printf("\t Average Data RSSI     = %d dBm\n",
+			       link_ptr->data_rssi_avg);
+			printf("\t Average Data NF       = %d dBm\n",
+			       link_ptr->data_nf_avg);
+			printf("\t Tx data rate          = %d Mbps\n",
+			       link_ptr->u.final_data_rate);
+
+			/* size of unsecure structure */
+			curr_link_len = sizeof(tdls_each_link_status) -
+				(sizeof(t_u32) + sizeof(t_u8) + sizeof(t_u8));
+
+			if (link_ptr->link_flags & 0x02) {
+				/* security details */
+				printf("\t Security Method = %s\n",
+				       (link_ptr->security_method ==
+					1) ? "AES" : "None");
+				printf("\t Key Lifetime = %d ms\n\t",
+				       link_ptr->key_lifetime);
+				hexdump("Key", ((t_u8 *)link_ptr->key),
+					link_ptr->key_length, ' ');
+				curr_link_len +=
+					sizeof(t_u32) + sizeof(t_u8) +
+					sizeof(t_u8)
+					+ link_ptr->key_length;
+			}
+			resp_len -= curr_link_len;
+			link_ptr =
+				(tdls_each_link_status *)(((t_u8 *)link_ptr) +
+							  curr_link_len);
+			printf(".\n");
+		}
+
+	} else {
+		printf("ERR:Command response = Fail!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_channel_swtich
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_channel_switch(int argc, char *argv[])
+{
+
+	tdls_channel_switch *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_channel_switch <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_channel_switch);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_channel_switch *)buffer;
+	param_buf->action = ACTION_TDLS_INIT_CHAN_SWITCH;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			ret = mac2raw(mac_addr, peer_mac);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "Band") == 0) {
+			param_buf->band = (t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->band != BAND_BG_TDLS &&
+			    param_buf->band != BAND_A_TDLS) {
+				printf("ERR: Incorrect Band value %s\n",
+				       args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "RegulatoryClass") == 0) {
+			param_buf->regulatory_class =
+				(t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "PrimaryChannel") == 0) {
+			param_buf->primary_channel =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->band == BAND_BG_TDLS &&
+			    param_buf->primary_channel < MIN_BG_CHANNEL &&
+			    param_buf->primary_channel > MAX_BG_CHANNEL) {
+				printf("ERR: Incorrect Primary Channel value  %s\n", args[1]);
+				goto done;
+			} else if (param_buf->band == BAND_A_TDLS
+				   && param_buf->primary_channel < MIN_A_CHANNEL
+				   && param_buf->primary_channel >
+				   MAX_A_CHANNEL) {
+				printf("ERR: Incorrect Primary Channel value  %s\n", args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "SecondaryChannelOffset") == 0) {
+			param_buf->secondary_channel_offset =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->secondary_channel_offset != SEC_CHAN_NONE
+			    && param_buf->secondary_channel_offset !=
+			    SEC_CHAN_ABOVE &&
+			    param_buf->secondary_channel_offset !=
+			    SEC_CHAN_BELOW) {
+				printf("ERR: Incorrect Secondary Channel Offset value  %s\n", args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "ChannelSwitchTime") == 0) {
+			param_buf->switch_time = (t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->switch_time == 0) {
+				printf("ERR: Incorrect Channel Switch time  %s\n", args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "ChannelSwitchTimeout") == 0) {
+			param_buf->switch_timeout =
+				(t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->switch_timeout == 0) {
+				printf("ERR: Incorrect Channel Switch timeout  %s\n", args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "Periodicity") == 0) {
+			param_buf->periodicity = (t_u16)A2HEXDECIMAL(args[1]);
+			if (param_buf->periodicity != NO_PERIODIC_SWITCH
+			    && param_buf->periodicity !=
+			    ENABLE_PERIODIC_SWITCH) {
+				printf("ERR: Incorrect Periodicity value %s\n",
+				       args[1]);
+				goto done;
+			}
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_channel_switch", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS channel switch request successful.\n");
+	} else {
+		printf("ERR:TDLS channel switch request failed.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief disable tdls_channel_swtich
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_disable_channel_switch(int argc, char *argv[])
+{
+
+	tdls_disable_cs *param_buf = NULL;
+	int ret = 0;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_disable_cs <0/1>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_disable_cs);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_disable_cs *) buffer;
+	param_buf->action = ACTION_TDLS_CS_DISABLE;
+
+	param_buf->data = (t_u16)A2HEXDECIMAL(argv[3]);
+	if ((param_buf->data != 0) && (param_buf->data != 1)) {
+		printf("ERR:Incorrect arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_disable_cs <0/1>\n");
+		goto done;
+	}
+	hexdump("tdls_disable_cs", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS disable channel switch successful.\n");
+	} else {
+		printf("ERR:TDLS disable channel switch failed.\n");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_stop_channel_switch
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_stop_channel_switch(int argc, char *argv[])
+{
+	tdls_stop_chan_switch *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_stop_channel_switch <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_stop_chan_switch);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_stop_chan_switch *) buffer;
+	param_buf->action = ACTION_TDLS_STOP_CHAN_SWITCH;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "PeerMAC") == 0) {
+			strncpy(mac_addr, args[1], 20);
+			ret = mac2raw(mac_addr, peer_mac);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				goto done;
+			}
+			memcpy(param_buf->peer_mac, peer_mac, ETH_ALEN);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_stop_channel_switch", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS stop channel switch successful.\n");
+	} else {
+		printf("ERR:TDLS stop channel switch failed.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_cs_params
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_cs_params(int argc, char *argv[])
+{
+	tdls_cs_params *param_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_cs_params <config/tdls.conf>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_cs_params);
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_cs_params *) buffer;
+	param_buf->action = ACTION_TDLS_CS_PARAMS;
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], argv[2], strlen(args[0])))
+			continue;
+
+		cmd_found = 1;
+
+		if (strcmp(args[0], "UnitTime") == 0) {
+			param_buf->unit_time = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "ThresholdOtherLink") == 0) {
+			param_buf->threshold_otherlink =
+				(t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "ThresholdDirectLink") == 0) {
+			param_buf->threshold_directlink =
+				(t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "}") == 0 && cmd_found) {
+			break;
+		}
+	}
+	hexdump("tdls_cs_params", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS set channel switch parameters successful.\n");
+	} else {
+		printf("ERR:TDLS set channel switch parameters failed.\n");
+	}
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls_debug
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_debug(int argc, char *argv[])
+{
+	int ret = 0;
+	tdls_debug *param_buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+	t_u16 action = 0, value = 0;
+
+	/* Check arguments */
+	if (argc < 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX tdls_debug <options>\n");
+		exit(1);
+	}
+
+	cmd_len = sizeof(tdls_debug);
+
+	/* wrong_bss */
+	if (!strcmp(argv[3], "wrong_bss")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_WRONG_BSS;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX tdls_debug wrong_bss <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* same link */
+	else if (!strcmp(argv[3], "setup_existing_link")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_SETUP_SAME_LINK;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX tdls_debug setup_existing_link <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* fail_setup_confirm */
+	else if (!strcmp(argv[3], "fail_setup_confirm")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_FAIL_SETUP_CONFIRM;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX tdls_debug fail_setup_confirm <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* setup prohibited */
+	else if (!strcmp(argv[3], "setup_with_prohibited")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_SETUP_PROHIBITED;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX tdls_debug setup_with_prohibited <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* setup higher/lower mac */
+	else if (!strcmp(argv[3], "higher_lower_mac")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_HIGHER_LOWER_MAC;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX tdls_debug higher_lower_mac <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* ignore key lifetime expiry */
+	else if (!strcmp(argv[3], "ignore_key_expiry")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_IGNORE_KEY_EXPIRY;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX tdls_debug ignore_key_expiry <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* allow weak security */
+	else if (!strcmp(argv[3], "allow_weak_security")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_ALLOW_WEAK_SECURITY;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX tdls_debug allow_weak_security <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* stop RX */
+	else if (!strcmp(argv[3], "stop_rx")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_STOP_RX;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX tdls_debug stop_rx <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	}
+	/* Immediate return */
+	else if (!strcmp(argv[3], "cs_im_return")) {
+		cmd_len += sizeof(t_u16);
+		action = ACTION_TDLS_DEBUG_CS_RET_IM;
+		if (argc < 5) {
+			printf("ERR:Incorrect number of arguments.\n");
+			printf("Syntax: ./mlanutl mlanX tdls_debug cs_im_return <0/1>\n");
+			exit(1);
+		}
+		value = (t_u16)A2HEXDECIMAL(argv[4]);
+	} else {
+		printf("ERR:Incorrect command!\n");
+		exit(1);
+	}
+
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		return -1;
+	}
+	memset(buffer, 0, cmd_len);
+	param_buf = (tdls_debug *)buffer;
+	param_buf->action = action;
+	memcpy(param_buf->data, &value, sizeof(value));
+
+	hexdump("tdls_debug", buffer, cmd_len, ' ');
+	/* Send collective command */
+	ret = tdls_ioctl((t_u8 *)buffer, cmd_len);
+
+	/* Process response */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		printf("TDLS debug request successful.\n");
+	} else {
+		printf("ERR:TDLS debug request failed.\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process tdls idle time set/get
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_tdls_idle_time(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int tdls_idle_time = 0;
+
+	/* Check arguments */
+	if (argc < 3 || argc > 4) {
+		printf("ERR:Incorrect number of arguments!\n");
+		printf("Syntax: ./mlanutl mlanX tdls_idle_time <time>\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: tdls_idle_time fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	tdls_idle_time = *(int *)buffer;
+	printf("TDLS idle time: %d\n", tdls_idle_time);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/** custom IE, auto mask value */
+#define	CUSTOM_IE_AUTO_MASK	0xffff
+
+/**
+ * @brief Show usage information for the customie
+ * command
+ *
+ * $return         N/A
+ **/
+void
+print_custom_ie_usage(void)
+{
+	printf("\nUsage : customie [INDEX] [MASK] [IEBuffer]");
+	printf("\n         empty - Get all IE settings\n");
+	printf("\n         INDEX:  0 - Get/Set IE index 0 setting");
+	printf("\n                 1 - Get/Set IE index 1 setting");
+	printf("\n                 2 - Get/Set IE index 2 setting");
+	printf("\n                 3 - Get/Set IE index 3 setting");
+	printf("\n                 .                             ");
+	printf("\n                 .                             ");
+	printf("\n                 .                             ");
+	printf("\n                -1 - Append/Delete IE automatically");
+	printf("\n                     Delete will delete the IE from the matching IE buffer");
+	printf("\n                     Append will append the IE to the buffer with the same mask");
+	printf("\n         MASK :  Management subtype mask value as per bit defintions");
+	printf("\n              :  Bit 0 - Association request.");
+	printf("\n              :  Bit 1 - Association response.");
+	printf("\n              :  Bit 2 - Reassociation request.");
+	printf("\n              :  Bit 3 - Reassociation response.");
+	printf("\n              :  Bit 4 - Probe request.");
+	printf("\n              :  Bit 5 - Probe response.");
+	printf("\n              :  Bit 8 - Beacon.");
+	printf("\n         MASK :  MASK = 0 to clear the mask and the IE buffer");
+	printf("\n         IEBuffer :  IE Buffer in hex (max 256 bytes)\n\n");
+	return;
+}
+
+/**
+ * @brief Creates a hostcmd request for custom IE settings
+ * and sends to the driver
+ *
+ * Usage: "customie [INDEX] [MASK] [IEBuffer]"
+ *
+ * Options: INDEX :      0 - Get/Delete IE index 0 setting
+ *                       1 - Get/Delete IE index 1 setting
+ *                       2 - Get/Delete IE index 2 setting
+ *                       3 - Get/Delete IE index 3 setting
+ *                       .
+ *                       .
+ *                       .
+ *                      -1 - Append IE at the IE buffer with same MASK
+ *          MASK  :      Management subtype mask value
+ *          IEBuffer:    IE Buffer in hex
+ *   					       empty - Get all IE settings
+ *
+ * @param argc     Number of arguments
+ * @param argv     Pointer to the arguments
+ * @return         N/A
+ **/
+static int
+process_customie(int argc, char *argv[])
+{
+	eth_priv_ds_misc_custom_ie *tlv = NULL;
+	tlvbuf_max_mgmt_ie *max_mgmt_ie_tlv = NULL;
+	t_u16 mgmt_subtype_mask = 0;
+	custom_ie *ie_ptr = NULL;
+	int ie_buf_len = 0, ie_len = 0, i = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* mlanutl mlan0 customie idx flag buf */
+	if (argc > 6) {
+		printf("ERR:Too many arguments.\n");
+		print_custom_ie_usage();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Error checks and initialize the command length */
+	if (argc > 3) {
+		if (((IS_HEX_OR_DIGIT(argv[3]) == MLAN_STATUS_FAILURE) &&
+		     (atoi(argv[3]) != -1)) || (atoi(argv[3]) < -1)) {
+			printf("ERR:Illegal index %s\n", argv[3]);
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	switch (argc) {
+	case 3:
+		break;
+	case 4:
+		if (atoi(argv[3]) < 0) {
+			printf("ERR:Illegal index %s. Must be either greater than or equal to 0 for Get Operation \n", argv[3]);
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		break;
+	case 5:
+		if (MLAN_STATUS_FAILURE == ishexstring(argv[4]) ||
+		    A2HEXDECIMAL(argv[4]) != 0) {
+			printf("ERR: Mask value should be 0 to clear IEBuffers.\n");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (atoi(argv[3]) == -1) {
+			printf("ERR: You must provide buffer for automatic deletion.\n");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		break;
+	case 6:
+		/* This is to check negative numbers and special symbols */
+		if (MLAN_STATUS_FAILURE == IS_HEX_OR_DIGIT(argv[4])) {
+			printf("ERR:Mask value must be 0 or hex digits\n");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		/* If above check is passed and mask is not hex, then it must be 0 */
+		if ((ISDIGIT(argv[4]) == MLAN_STATUS_SUCCESS) && atoi(argv[4])) {
+			printf("ERR:Mask value must be 0 or hex digits\n ");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (MLAN_STATUS_FAILURE == ishexstring(argv[5])) {
+			printf("ERR:Only hex digits are allowed\n");
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		ie_buf_len = strlen(argv[5]);
+		if (!strncasecmp("0x", argv[5], 2)) {
+			ie_len = (ie_buf_len - 2 + 1) / 2;
+			argv[5] += 2;
+		} else
+			ie_len = (ie_buf_len + 1) / 2;
+		if (ie_len > MAX_IE_BUFFER_LEN) {
+			printf("ERR:Incorrect IE length %d\n", ie_buf_len);
+			print_custom_ie_usage();
+			return MLAN_STATUS_FAILURE;
+		}
+		mgmt_subtype_mask = (t_u16)A2HEXDECIMAL(argv[4]);
+		break;
+	}
+	/* Initialize the command buffer */
+	tlv = (eth_priv_ds_misc_custom_ie *)(buffer + strlen(CMD_MARVELL) +
+					     strlen(argv[2]));
+	tlv->type = MRVL_MGMT_IE_LIST_TLV_ID;
+	if (argc == 3 || argc == 4) {
+		if (argc == 3)
+			tlv->len = 0;
+		else {
+			tlv->len = sizeof(t_u16);
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			ie_ptr->ie_index = (t_u16)(atoi(argv[3]));
+		}
+	} else {
+		/* Locate headers */
+		ie_ptr = (custom_ie *)(tlv->ie_data);
+		/* Set TLV fields */
+		tlv->len = sizeof(custom_ie) + ie_len;
+		ie_ptr->ie_index = atoi(argv[3]);
+		ie_ptr->mgmt_subtype_mask = mgmt_subtype_mask;
+		ie_ptr->ie_length = ie_len;
+		if (argc == 6)
+			string2raw(argv[5], ie_ptr->ie_buffer);
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[CUSTOM_IE_CFG]");
+		printf("ERR:Command sending failed!\n");
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Print response */
+	if (argc > 4) {
+		printf("Custom IE setting successful\n");
+	} else {
+		printf("Querying custom IE successful\n");
+		ie_len = tlv->len;
+		ie_ptr = (custom_ie *)(tlv->ie_data);
+		while (ie_len >= (int)sizeof(custom_ie)) {
+			printf("Index [%d]\n", ie_ptr->ie_index);
+			if (ie_ptr->ie_length)
+				printf("Management Subtype Mask = 0x%02x\n",
+				       (ie_ptr->mgmt_subtype_mask) == 0 ?
+				       CUSTOM_IE_AUTO_MASK :
+				       (ie_ptr->mgmt_subtype_mask));
+			else
+				printf("Management Subtype Mask = 0x%02x\n",
+				       (ie_ptr->mgmt_subtype_mask));
+			hexdump("IE Buffer", (void *)ie_ptr->ie_buffer,
+				ie_ptr->ie_length, ' ');
+			ie_len -= sizeof(custom_ie) + ie_ptr->ie_length;
+			ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+					       sizeof(custom_ie) +
+					       ie_ptr->ie_length);
+		}
+	}
+	max_mgmt_ie_tlv = (tlvbuf_max_mgmt_ie *)((t_u8 *)tlv +
+						 sizeof
+						 (eth_priv_ds_misc_custom_ie) +
+						 tlv->len);
+	if (max_mgmt_ie_tlv) {
+		if (max_mgmt_ie_tlv->type == MRVL_MAX_MGMT_IE_TLV_ID) {
+			for (i = 0; i < max_mgmt_ie_tlv->count; i++) {
+				printf("buf%d_size = %d\n", i,
+				       max_mgmt_ie_tlv->info[i].buf_size);
+				printf("number of buffers = %d\n",
+				       max_mgmt_ie_tlv->info[i].buf_count);
+				printf("\n");
+			}
+		}
+	}
+	if (buffer)
+		free(buffer);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process regrdwr command
+ *
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_regrdwr(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	struct eth_priv_ds_reg_rw *reg = NULL;
+
+	if (argc < 5 || argc > 6) {
+		printf("Error: invalid no of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: regrdwr fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	reg = (struct eth_priv_ds_reg_rw *)buffer;
+	if (argc == 5) {
+		/* GET operation */
+		printf("Value = 0x%x\n", reg->value);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process rdeeprom command
+ *
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_rdeeprom(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	struct eth_priv_ds_read_eeprom *eeprom = NULL;
+	int i = 0;
+
+	if (argc != 5) {
+		printf("Error: invalid no of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: rdeeprom fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	eeprom = (struct eth_priv_ds_read_eeprom *)buffer;
+	if (argc == 5) {
+		/* GET operation */
+		printf("Value:\n");
+		for (i = 0; i < MIN(MAX_EEPROM_DATA, eeprom->byte_count); i++)
+			printf(" %02x", eeprom->value[i]);
+		printf("\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process memrdwr command
+ *
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_memrdwr(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	struct eth_priv_ds_mem_rw *mem = NULL;
+
+	if (argc < 4 || argc > 5) {
+		printf("Error: invalid no of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: memrdwr fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	mem = (struct eth_priv_ds_mem_rw *)buffer;
+	if (argc == 4) {
+		/* GET operation */
+		printf("Value = 0x%x\n", mem->value);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process sdcmd52rw command
+ *
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_sdcmd52rw(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	if (argc < 5 || argc > 6) {
+		printf("Error: invalid no of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: sdcmd52rw fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	if (argc == 5) {
+		/* GET operation */
+		printf("Value = 0x%x\n", (int)(*buffer));
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+#define STACK_NBYTES            	100	/**< Number of bytes in stack */
+#define MAX_BYTESEQ 		       	6	/**< Maximum byte sequence */
+#define TYPE_DNUM           		1 /**< decimal number */
+#define TYPE_BYTESEQ        		2 /**< byte sequence */
+#define MAX_OPERAND         		0x40	/**< Maximum operands */
+#define TYPE_EQ         		(MAX_OPERAND+1)	/**< byte comparison:    == operator */
+#define TYPE_EQ_DNUM    		(MAX_OPERAND+2)	/**< decimal comparison: =d operator */
+#define TYPE_EQ_BIT     		(MAX_OPERAND+3)	/**< bit comparison:     =b operator */
+#define TYPE_AND        		(MAX_OPERAND+4)	/**< && operator */
+#define TYPE_OR         		(MAX_OPERAND+5)	/**< || operator */
+
+typedef struct {
+	t_u16 sp;		      /**< Stack pointer */
+	t_u8 byte[STACK_NBYTES];      /**< Stack */
+} mstack_t;
+
+typedef struct {
+	t_u8 type;		  /**< Type */
+	t_u8 reserve[3];   /**< so 4-byte align val array */
+	/* byte sequence is the largest among all the operands and operators. */
+	/* byte sequence format: 1 byte of num of bytes, then variable num bytes */
+	t_u8 val[MAX_BYTESEQ + 1];/**< Value */
+} op_t;
+
+/**
+ *  @brief push data to stack
+ *
+ *  @param s			a pointer to mstack_t structure
+ *
+ *  @param nbytes		number of byte to push to stack
+ *
+ *  @param val			a pointer to data buffer
+ *
+ *  @return			TRUE-- sucess , FALSE -- fail
+ *
+ */
+static int
+push_n(mstack_t * s, t_u8 nbytes, t_u8 *val)
+{
+	if ((s->sp + nbytes) < STACK_NBYTES) {
+		memcpy((void *)(s->byte + s->sp), (const void *)val,
+		       (size_t) nbytes);
+		s->sp += nbytes;
+		/* printf("push: n %d sp %d\n", nbytes, s->sp); */
+		return TRUE;
+	} else			/* stack full */
+		return FALSE;
+}
+
+/**
+ *  @brief push data to stack
+ *
+ *  @param s			a pointer to mstack_t structure
+ *
+ *  @param op			a pointer to op_t structure
+ *
+ *  @return			TRUE-- sucess , FALSE -- fail
+ *
+ */
+static int
+push(mstack_t * s, op_t * op)
+{
+	t_u8 nbytes;
+	switch (op->type) {
+	case TYPE_DNUM:
+		if (push_n(s, 4, op->val))
+			return push_n(s, 1, &op->type);
+		return FALSE;
+	case TYPE_BYTESEQ:
+		nbytes = op->val[0];
+		if (push_n(s, nbytes, op->val + 1) &&
+		    push_n(s, 1, op->val) && push_n(s, 1, &op->type))
+			return TRUE;
+		return FALSE;
+	default:
+		return push_n(s, 1, &op->type);
+	}
+}
+
+/**
+ *  @brief parse RPN string
+ *
+ *  @param s			a pointer to Null-terminated string to scan.
+ *
+ *  @param first_time		a pointer to return first_time
+ *
+ *  @return			A pointer to the last token found in string.
+ *  				NULL is returned when there are no more tokens to be found.
+ *
+ */
+static char *
+getop(char *s, int *first_time)
+{
+	const char delim[] = " \t\n";
+	char *p;
+	if (*first_time) {
+		p = strtok(s, delim);
+		*first_time = FALSE;
+	} else {
+		p = strtok(NULL, delim);
+	}
+	return p;
+}
+
+/**
+ *  @brief Verify hex digit.
+ *
+ *  @param c			input ascii char
+ *  @param h			a pointer to return integer value of the digit char.
+ *  @return			TURE -- c is hex digit, FALSE -- c is not hex digit.
+ */
+static int
+ishexdigit(char c, t_u8 *h)
+{
+	if (c >= '0' && c <= '9') {
+		*h = c - '0';
+		return TRUE;
+	} else if (c >= 'a' && c <= 'f') {
+		*h = c - 'a' + 10;
+		return TRUE;
+	} else if (c >= 'A' && c <= 'F') {
+		*h = c - 'A' + 10;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ *  @brief convert hex string to integer.
+ *
+ *  @param s			A pointer to hex string, string length up to 2 digits.
+ *  @return			integer value.
+ */
+static t_u8
+hex_atoi(char *s)
+{
+	int i;
+	t_u8 digit;		/* digital value */
+	t_u8 t = 0;		/* total value */
+
+	for (i = 0, t = 0; ishexdigit(s[i], &digit) && i < 2; i++)
+		t = 16 * t + digit;
+	return t;
+}
+
+/**
+ *  @brief Parse byte sequence in hex format string to a byte sequence.
+ *
+ *  @param opstr		A pointer to byte sequence in hex format string, with ':' as delimiter between two byte.
+ *  @param val			A pointer to return byte sequence string
+ *  @return			NA
+ */
+static void
+parse_hex(char *opstr, t_u8 *val)
+{
+	char delim = ':';
+	char *p;
+	char *q;
+	t_u8 i;
+
+	/* +1 is for skipping over the preceding h character. */
+	p = opstr + 1;
+
+	/* First byte */
+	val[1] = hex_atoi(p++);
+
+	/* Parse subsequent bytes. */
+	/* Each byte is preceded by the : character. */
+	for (i = 1; *p; i++) {
+		q = strchr(p, delim);
+		if (!q)
+			break;
+		p = q + 1;
+		val[i + 1] = hex_atoi(p);
+	}
+	/* Set num of bytes */
+	val[0] = i;
+}
+
+/**
+ *  @brief str2bin, convert RPN string to binary format
+ *
+ *  @param str			A pointer to rpn string
+ *  @param stack		A pointer to mstack_t structure
+ *  @return			MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+str2bin(char *str, mstack_t * stack)
+{
+	int first_time;
+	char *opstr;
+	op_t op;		/* operator/operand */
+	int dnum;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	memset(stack, 0, sizeof(mstack_t));
+	first_time = TRUE;
+	while ((opstr = getop(str, &first_time)) != NULL) {
+		if (isdigit(*opstr)) {
+			op.type = TYPE_DNUM;
+			dnum = cpu_to_le32(atoi(opstr));
+			memcpy((t_u8 *)op.val, &dnum, sizeof(dnum));
+			if (!push(stack, &op)) {
+				printf("push decimal number failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (*opstr == 'h') {
+			op.type = TYPE_BYTESEQ;
+			parse_hex(opstr, op.val);
+			if (!push(stack, &op)) {
+				printf("push byte sequence failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "==")) {
+			op.type = TYPE_EQ;
+			if (!push(stack, &op)) {
+				printf("push byte cmp operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "=d")) {
+			op.type = TYPE_EQ_DNUM;
+			if (!push(stack, &op)) {
+				printf("push decimal cmp operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "=b")) {
+			op.type = TYPE_EQ_BIT;
+			if (!push(stack, &op)) {
+				printf("push bit cmp operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "&&")) {
+			op.type = TYPE_AND;
+			if (!push(stack, &op)) {
+				printf("push AND operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else if (!strcmp(opstr, "||")) {
+			op.type = TYPE_OR;
+			if (!push(stack, &op)) {
+				printf("push OR operator failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+		} else {
+			printf("Unknown operand\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+	}
+	return ret;
+}
+
+#define FILTER_BYTESEQ 		TYPE_EQ	/**< byte sequence */
+#define FILTER_DNUM    		TYPE_EQ_DNUM /**< decimal number */
+#define FILTER_BITSEQ		TYPE_EQ_BIT /**< bit sequence */
+#define FILTER_TEST		(FILTER_BITSEQ+1) /**< test */
+
+#define NAME_TYPE		1	    /**< Field name 'type' */
+#define NAME_PATTERN		2	/**< Field name 'pattern' */
+#define NAME_OFFSET		3	    /**< Field name 'offset' */
+#define NAME_NUMBYTE		4	/**< Field name 'numbyte' */
+#define NAME_REPEAT		5	    /**< Field name 'repeat' */
+#define NAME_BYTE		6	    /**< Field name 'byte' */
+#define NAME_MASK		7	    /**< Field name 'mask' */
+#define NAME_DEST		8	    /**< Field name 'dest' */
+
+static struct mef_fields {
+	char *name;
+	      /**< Name */
+	t_s8 nameid;
+		/**< Name Id. */
+} mef_fields[] = {
+	{
+	"type", NAME_TYPE}, {
+	"pattern", NAME_PATTERN}, {
+	"offset", NAME_OFFSET}, {
+	"numbyte", NAME_NUMBYTE}, {
+	"repeat", NAME_REPEAT}, {
+	"byte", NAME_BYTE}, {
+	"mask", NAME_MASK}, {
+	"dest", NAME_DEST}
+};
+
+/**
+ *  @brief get filter data
+ *
+ *  @param fp			A pointer to file stream
+ *  @param ln			A pointer to line number
+ *  @param buf			A pointer to hostcmd data
+ *  @param size			A pointer to the return size of hostcmd buffer
+ *  @return			MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+mlan_get_filter_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
+{
+	t_s32 errors = 0, i;
+	char line[256], *pos = NULL, *pos1 = NULL;
+	t_u16 type = 0;
+	t_u32 pattern = 0;
+	t_u16 repeat = 0;
+	t_u16 offset = 0;
+	char byte_seq[50];
+	char mask_seq[50];
+	t_u16 numbyte = 0;
+	t_s8 type_find = 0;
+	t_s8 pattern_find = 0;
+	t_s8 offset_find = 0;
+	t_s8 numbyte_find = 0;
+	t_s8 repeat_find = 0;
+	t_s8 byte_find = 0;
+	t_s8 mask_find = 0;
+	t_s8 dest_find = 0;
+	char dest_seq[50];
+
+	*size = 0;
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
+		if (strcmp(pos, "}") == 0) {
+			break;
+		}
+		pos1 = strchr(pos, '=');
+		if (pos1 == NULL) {
+			printf("Line %d: Invalid mef_filter line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos1++ = '\0';
+		for (i = 0; (t_u32)i < NELEMENTS(mef_fields); i++) {
+			if (strncmp
+			    (pos, mef_fields[i].name,
+			     strlen(mef_fields[i].name)) == 0) {
+				switch (mef_fields[i].nameid) {
+				case NAME_TYPE:
+					type = a2hex_or_atoi(pos1);
+					if ((type != FILTER_DNUM) &&
+					    (type != FILTER_BYTESEQ)
+					    && (type != FILTER_BITSEQ) &&
+					    (type != FILTER_TEST)) {
+						printf("Invalid filter type:%d\n", type);
+						return MLAN_STATUS_FAILURE;
+					}
+					type_find = 1;
+					break;
+				case NAME_PATTERN:
+					pattern = a2hex_or_atoi(pos1);
+					pattern_find = 1;
+					break;
+				case NAME_OFFSET:
+					offset = a2hex_or_atoi(pos1);
+					offset_find = 1;
+					break;
+				case NAME_NUMBYTE:
+					numbyte = a2hex_or_atoi(pos1);
+					numbyte_find = 1;
+					break;
+				case NAME_REPEAT:
+					repeat = a2hex_or_atoi(pos1);
+					repeat_find = 1;
+					break;
+				case NAME_BYTE:
+					memset(byte_seq, 0, sizeof(byte_seq));
+					strncpy(byte_seq, pos1,
+						(sizeof(byte_seq) - 1));
+					byte_find = 1;
+					break;
+				case NAME_MASK:
+					memset(mask_seq, 0, sizeof(mask_seq));
+					strncpy(mask_seq, pos1,
+						(sizeof(mask_seq) - 1));
+					mask_find = 1;
+					break;
+				case NAME_DEST:
+					memset(dest_seq, 0, sizeof(dest_seq));
+					strncpy(dest_seq, pos1,
+						(sizeof(dest_seq) - 1));
+					dest_find = 1;
+					break;
+				}
+				break;
+			}
+		}
+		if (i == NELEMENTS(mef_fields)) {
+			printf("Line %d: unknown mef field '%s'.\n",
+			       *line, pos);
+			errors++;
+		}
+	}
+	if (type_find == 0) {
+		printf("Can not find filter type\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	switch (type) {
+	case FILTER_DNUM:
+		if (!pattern_find || !offset_find || !numbyte_find) {
+			printf("Missing field for FILTER_DNUM: pattern=%d,offset=%d,numbyte=%d\n", pattern_find, offset_find, numbyte_find);
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(line, 0, sizeof(line));
+		snprintf(line, sizeof(line), "%d %d %d =d ", pattern, offset,
+			 numbyte);
+		break;
+	case FILTER_BYTESEQ:
+		if (!byte_find || !offset_find || !repeat_find) {
+			printf("Missing field for FILTER_BYTESEQ: byte=%d,offset=%d,repeat=%d\n", byte_find, offset_find, repeat_find);
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(line, 0, sizeof(line));
+		snprintf(line, sizeof(line), "%d h%s %d == ", repeat, byte_seq,
+			 offset);
+		break;
+	case FILTER_BITSEQ:
+		if (!byte_find || !offset_find || !mask_find) {
+			printf("Missing field for FILTER_BITSEQ: byte=%d,offset=%d,mask_find=%d\n", byte_find, offset_find, mask_find);
+			return MLAN_STATUS_FAILURE;
+		}
+		if (strlen(byte_seq) != strlen(mask_seq)) {
+			printf("byte string's length is different with mask's length!\n");
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(line, 0, sizeof(line));
+		snprintf(line, sizeof(line), "h%s %d h%s =b ", byte_seq, offset,
+			 mask_seq);
+		break;
+	case FILTER_TEST:
+		if (!byte_find || !offset_find || !repeat_find || !dest_find) {
+			printf("Missing field for FILTER_TEST: byte=%d,offset=%d,repeat=%d,dest=%d\n", byte_find, offset_find, repeat_find, dest_find);
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(line, 0, sizeof(line));
+		snprintf(line, sizeof(line), "h%s %d h%s %d ", dest_seq, repeat,
+			 byte_seq, offset);
+		break;
+	}
+	memcpy(buf, line, strlen(line));
+	*size = strlen(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+#define NAME_MODE	1	/**< Field name 'mode' */
+#define NAME_ACTION	2	/**< Field name 'action' */
+#define NAME_FILTER_NUM	3   /**< Field name 'filter_num' */
+#define NAME_RPN	4	/**< Field name 'RPN' */
+static struct mef_entry_fields {
+	char *name;
+	      /**< Name */
+	t_s8 nameid;
+		/**< Name id */
+} mef_entry_fields[] = {
+	{
+	"mode", NAME_MODE}, {
+	"action", NAME_ACTION}, {
+	"filter_num", NAME_FILTER_NUM}, {
+"RPN", NAME_RPN},};
+
+typedef struct _MEF_ENTRY {
+    /** Mode */
+	t_u8 Mode;
+    /** Size */
+	t_u8 Action;
+    /** Size of expression */
+	t_u16 ExprSize;
+} MEF_ENTRY;
+
+/**
+ *  @brief get mef_entry data
+ *
+ *  @param fp			A pointer to file stream
+ *  @param ln			A pointer to line number
+ *  @param buf			A pointer to hostcmd data
+ *  @param size			A pointer to the return size of hostcmd buffer
+ *  @return			MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+mlan_get_mef_entry_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
+{
+	char line[256], *pos = NULL, *pos1 = NULL;
+	t_u8 mode, action, filter_num = 0;
+	char rpn[256];
+	t_s8 mode_find = 0;
+	t_s8 action_find = 0;
+	t_s8 filter_num_find = 0;
+	t_s8 rpn_find = 0;
+	char rpn_str[256];
+	int rpn_len = 0;
+	char filter_name[50];
+	t_s8 name_found = 0;
+	t_u16 len = 0;
+	int i;
+	int first_time = TRUE;
+	char *opstr = NULL;
+	char filter_action[10];
+	t_s32 errors = 0;
+	MEF_ENTRY *pMefEntry = (MEF_ENTRY *) buf;
+	mstack_t stack;
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
+		if (strcmp(pos, "}") == 0) {
+			break;
+		}
+		pos1 = strchr(pos, '=');
+		if (pos1 == NULL) {
+			printf("Line %d: Invalid mef_entry line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos1++ = '\0';
+		if (!mode_find || !action_find || !filter_num_find || !rpn_find) {
+			for (i = 0;
+			     (unsigned int)i < NELEMENTS(mef_entry_fields);
+			     i++) {
+				if (strncmp
+				    (pos, mef_entry_fields[i].name,
+				     strlen(mef_entry_fields[i].name)) == 0) {
+					switch (mef_entry_fields[i].nameid) {
+					case NAME_MODE:
+						mode = a2hex_or_atoi(pos1);
+						if (mode & ~0x7) {
+							printf("invalid mode=%d\n", mode);
+							return MLAN_STATUS_FAILURE;
+						}
+						pMefEntry->Mode = mode;
+						mode_find = 1;
+						break;
+					case NAME_ACTION:
+						action = a2hex_or_atoi(pos1);
+						if (action & ~0xff) {
+							printf("invalid action=%d\n", action);
+							return MLAN_STATUS_FAILURE;
+						}
+						pMefEntry->Action = action;
+						action_find = 1;
+						break;
+					case NAME_FILTER_NUM:
+						filter_num =
+							a2hex_or_atoi(pos1);
+						filter_num_find = 1;
+						break;
+					case NAME_RPN:
+						memset(rpn, 0, sizeof(rpn));
+						strncpy(rpn, pos1,
+							(sizeof(rpn) - 1));
+						rpn_find = 1;
+						break;
+					}
+					break;
+				}
+			}
+			if (i == NELEMENTS(mef_fields)) {
+				printf("Line %d: unknown mef_entry field '%s'.\n", *line, pos);
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+		if (mode_find && action_find && filter_num_find && rpn_find) {
+			for (i = 0; i < filter_num; i++) {
+				opstr = getop(rpn, &first_time);
+				if (opstr == NULL)
+					break;
+				snprintf(filter_name, sizeof(filter_name),
+					 "%s={", opstr);
+				name_found = 0;
+				while ((pos =
+					mlan_config_get_line(fp, line,
+							     sizeof(line),
+							     ln))) {
+					if (strncmp
+					    (pos, filter_name,
+					     strlen(filter_name)) == 0) {
+						name_found = 1;
+						break;
+					}
+				}
+				if (!name_found) {
+					fprintf(stderr,
+						"mlanutl: %s not found in file\n",
+						filter_name);
+					return MLAN_STATUS_FAILURE;
+				}
+				if (MLAN_STATUS_FAILURE ==
+				    mlan_get_filter_data(fp, ln,
+							 (t_u8 *)(rpn_str +
+								  rpn_len),
+							 &len))
+					break;
+				rpn_len += len;
+				if (i > 0) {
+					memcpy(rpn_str + rpn_len, filter_action,
+					       strlen(filter_action));
+					rpn_len += strlen(filter_action);
+				}
+				opstr = getop(rpn, &first_time);
+				if (opstr == NULL)
+					break;
+				memset(filter_action, 0, sizeof(filter_action));
+				snprintf(filter_action, sizeof(filter_action),
+					 "%s ", opstr);
+			}
+			/* Remove the last space */
+			if (rpn_len > 0) {
+				rpn_len--;
+				rpn_str[rpn_len] = 0;
+			}
+			if (MLAN_STATUS_FAILURE == str2bin(rpn_str, &stack)) {
+				printf("Fail on str2bin!\n");
+				return MLAN_STATUS_FAILURE;
+			}
+			*size = sizeof(MEF_ENTRY);
+			pMefEntry->ExprSize = cpu_to_le16(stack.sp);
+			memmove(buf + sizeof(MEF_ENTRY), stack.byte, stack.sp);
+			*size += stack.sp;
+			break;
+		} else if (mode_find && action_find && filter_num_find &&
+			   (filter_num == 0)) {
+			pMefEntry->ExprSize = 0;
+			*size = sizeof(MEF_ENTRY);
+			break;
+		}
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process enable/disable DFS offload
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_dfs_offload_enable(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Check arguments */
+	if (argc < 3 || argc > 4) {
+		printf("ERR:Incorrect number of arguments!\n");
+		printf("Syntax: ./mlanutl mlanX dfs_offload <0/1>\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: dfs offload enable/disable fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+#define MEFCFG_CMDCODE	0x009a
+
+/**
+ *  @brief Process mefcfg command
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_mefcfg(int argc, char *argv[])
+{
+	char line[256], cmdname[256], *pos = NULL;
+	int cmdname_found = 0, name_found = 0;
+	int ln = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+	int i;
+	t_u8 *buffer = NULL;
+	t_u16 len = 0;
+	HostCmd_DS_MEF_CFG *mefcmd = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	FILE *fp = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	if (argc < 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanutl mlan0 mefcfg <mef.conf>\n");
+		exit(1);
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen("HOSTCMD");
+	cmd_len = sizeof(HostCmd_DS_GEN) + sizeof(HostCmd_DS_MEF_CFG);
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fclose(fp);
+		fprintf(stderr, "Cannot alloc memory\n");
+		exit(1);
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	/* buf = MRVL_CMD<cmd> */
+	prepare_buffer(buffer, HOSTCMD, 0, NULL);
+
+	/* buf = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+	hostcmd->command = cpu_to_le16(MEFCFG_CMDCODE);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	/* buf = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><HostCmd_DS_MEF_CFG> */
+	mefcmd = (HostCmd_DS_MEF_CFG *)(buffer + cmd_header_len +
+					sizeof(t_u32) + S_DS_GEN);
+
+/* Host Command Population */
+	snprintf(cmdname, sizeof(cmdname), "%s={", argv[2]);
+	cmdname_found = 0;
+	fp = fopen(argv[3], "r");
+	if (fp == NULL) {
+		fprintf(stderr, "Cannot open file %s\n", argv[4]);
+		exit(1);
+	}
+
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, cmdname) == 0) {
+			cmdname_found = 1;
+			snprintf(cmdname, sizeof(cmdname), "Criteria=");
+			name_found = 0;
+			while ((pos =
+				mlan_config_get_line(fp, line, sizeof(line),
+						     &ln))) {
+				if (strncmp(pos, cmdname, strlen(cmdname)) == 0) {
+					name_found = 1;
+					mefcmd->Criteria =
+						a2hex_or_atoi(pos +
+							      strlen(cmdname));
+					break;
+				}
+			}
+			if (!name_found) {
+				fprintf(stderr,
+					"mlanutl: criteria not found in file '%s'\n",
+					argv[3]);
+				break;
+			}
+			snprintf(cmdname, sizeof(cmdname), "NumEntries=");
+			name_found = 0;
+			while ((pos =
+				mlan_config_get_line(fp, line, sizeof(line),
+						     &ln))) {
+				if (strncmp(pos, cmdname, strlen(cmdname)) == 0) {
+					name_found = 1;
+					mefcmd->NumEntries =
+						a2hex_or_atoi(pos +
+							      strlen(cmdname));
+					break;
+				}
+			}
+			if (!name_found) {
+				fprintf(stderr,
+					"mlanutl: NumEntries not found in file '%s'\n",
+					argv[3]);
+				break;
+			}
+			for (i = 0; i < mefcmd->NumEntries; i++) {
+				snprintf(cmdname, sizeof(cmdname),
+					 "mef_entry_%d={", i);
+				name_found = 0;
+				while ((pos =
+					mlan_config_get_line(fp, line,
+							     sizeof(line),
+							     &ln))) {
+					if (strncmp
+					    (pos, cmdname,
+					     strlen(cmdname)) == 0) {
+						name_found = 1;
+						break;
+					}
+				}
+				if (!name_found) {
+					fprintf(stderr,
+						"mlanutl: %s not found in file '%s'\n",
+						cmdname, argv[3]);
+					break;
+				}
+				if (MLAN_STATUS_FAILURE ==
+				    mlan_get_mef_entry_data(fp, &ln,
+							    (t_u8 *)hostcmd +
+							    cmd_len, &len)) {
+					ret = MLAN_STATUS_FAILURE;
+					break;
+				}
+				cmd_len += len;
+			}
+			break;
+		}
+	}
+	fclose(fp);
+	/* buf = MRVL_CMD<cmd><hostcmd_size> */
+	memcpy(buffer + cmd_header_len, (t_u8 *)&cmd_len, sizeof(t_u32));
+
+	if (!cmdname_found)
+		fprintf(stderr,
+			"mlanutl: cmdname '%s' not found in file '%s'\n",
+			argv[4], argv[3]);
+
+	if (!cmdname_found || !name_found) {
+		ret = MLAN_STATUS_FAILURE;
+		goto mef_exit;
+	}
+	hostcmd->size = cpu_to_le16(cmd_len);
+	mefcmd->Criteria = cpu_to_le32(mefcmd->Criteria);
+	mefcmd->NumEntries = cpu_to_le16(mefcmd->NumEntries);
+	hexdump("mefcfg", buffer + cmd_header_len, cmd_len, ' ');
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[MEF_CFG]");
+		printf("ERR:Command sending failed!\n");
+		if (buffer)
+			free(buffer);
+		if (cmd)
+			free(cmd);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	ret = process_host_cmd_resp(HOSTCMD, buffer);
+
+mef_exit:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Prepare ARP filter buffer
+ *  @param fp               File handler
+ *  @param buf              A pointer to the buffer
+ *  @param length           A pointer to the length of buffer
+ *  @param cmd_header_len   Command header length
+ *  @return                 MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_arp_filter_buffer(FILE * fp, t_u8 *buf, t_u16 *length,
+			  int cmd_header_len)
+{
+	char line[256], *pos = NULL;
+	int ln = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+	int arpfilter_found = 0;
+
+	memset(buf, 0, BUFFER_LENGTH - cmd_header_len - sizeof(t_u32));
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, "arpfilter={") == 0) {
+			arpfilter_found = 1;
+			mlan_get_hostcmd_data(fp, &ln, buf, length);
+			break;
+		}
+	}
+	if (!arpfilter_found) {
+		fprintf(stderr, "mlanutl: 'arpfilter' not found in conf file");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	return ret;
+}
+
+/**
+ *  @brief Process arpfilter
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_arpfilter(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	t_u16 length = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+	FILE *fp = NULL;
+	int cmd_header_len = 0;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	if (argc < 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanutl mlanX arpfilter <arpfilter.conf>\n");
+		exit(1);
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(argv[2]);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		printf("Error: allocate memory for arpfilter failed\n");
+		fclose(fp);
+		return -ENOMEM;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	/* buf = MRVL_CMD<cmd> */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	/* Reading the configuration file */
+	fp = fopen(argv[3], "r");
+	if (fp == NULL) {
+		fprintf(stderr, "Cannot open file %s\n", argv[3]);
+		ret = MLAN_STATUS_FAILURE;
+		goto arp_exit;
+	}
+	ret = prepare_arp_filter_buffer(fp,
+					buffer + cmd_header_len + sizeof(t_u32),
+					&length, cmd_header_len);
+	fclose(fp);
+
+	if (ret == MLAN_STATUS_FAILURE)
+		goto arp_exit;
+
+	/* buf = MRVL_CMD<cmd><hostcmd_size> */
+	memcpy(buffer + cmd_header_len, &length, sizeof(length));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[ARP_FILTER]");
+		printf("ERR:Command sending failed!\n");
+		if (buffer)
+			free(buffer);
+		if (cmd)
+			free(cmd);
+		return MLAN_STATUS_FAILURE;
+	}
+
+arp_exit:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief parse hex data
+ *  @param fp       File handler
+ *  @param dst      A pointer to receive hex data
+ *  @return         length of hex data
+ */
+int
+fparse_for_hex(FILE * fp, t_u8 *dst)
+{
+	char *ptr = NULL;
+	t_u8 *dptr = NULL;
+	char buf[256];
+
+	dptr = dst;
+	while (fgets(buf, sizeof(buf), fp)) {
+		ptr = buf;
+
+		while (*ptr) {
+			/* skip leading spaces */
+			while (*ptr && (isspace(*ptr) || *ptr == '\t'))
+				ptr++;
+
+			/* skip blank lines and lines beginning with '#' */
+			if (*ptr == '\0' || *ptr == '#')
+				break;
+
+			if (isxdigit(*ptr)) {
+				ptr = convert2hex(ptr, dptr++);
+			} else {
+				/* Invalid character on data line */
+				ptr++;
+			}
+		}
+	}
+
+	return dptr - dst;
+}
+
+/** Config data header length */
+#define CFG_DATA_HEADER_LEN 6
+
+/**
+ *  @brief Prepare cfg-data buffer
+ *  @param argc             Number of arguments
+ *  @param argv             A pointer to arguments array
+ *  @param fp               File handler
+ *  @param buf              A pointer to comand buffer
+ *  @param cmd_header_len   Length of the command header
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_cfg_data_buffer(int argc, char *argv[], FILE * fp, t_u8 *buf,
+			int cmd_header_len)
+{
+	int ln = 0, type;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	HostCmd_DS_802_11_CFG_DATA *pcfg_data = NULL;
+
+	memset(buf, 0, BUFFER_LENGTH - cmd_header_len - sizeof(t_u32));
+	hostcmd = (HostCmd_DS_GEN *)buf;
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA);
+	pcfg_data = (HostCmd_DS_802_11_CFG_DATA *)(buf + S_DS_GEN);
+	pcfg_data->action =
+		(argc == 4) ? HostCmd_ACT_GEN_GET : HostCmd_ACT_GEN_SET;
+	type = atoi(argv[3]);
+	if ((type < 1) || (type > 2)) {
+		fprintf(stderr, "mlanutl: Invalid register type\n");
+		return MLAN_STATUS_FAILURE;
+	} else {
+		pcfg_data->type = type;
+	}
+	if (argc == 5) {
+		ln = fparse_for_hex(fp, pcfg_data->data);
+	}
+	pcfg_data->data_len = ln;
+	hostcmd->size =
+		cpu_to_le16(pcfg_data->data_len + S_DS_GEN +
+			    CFG_DATA_HEADER_LEN);
+	pcfg_data->data_len = cpu_to_le16(pcfg_data->data_len);
+	pcfg_data->type = cpu_to_le16(pcfg_data->type);
+	pcfg_data->action = cpu_to_le16(pcfg_data->action);
+
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process cfgdata
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_cfgdata(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	int ret = MLAN_STATUS_SUCCESS;
+	FILE *fp = NULL;
+	int cmd_header_len = 0;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	if (argc < 4 || argc > 5) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./mlanutl mlanX cfgdata <register type> <filename>\n");
+		exit(1);
+	}
+
+	if (argc == 5) {
+		fp = fopen(argv[4], "r");
+		if (fp == NULL) {
+			fprintf(stderr, "Cannot open file %s\n", argv[3]);
+			exit(1);
+		}
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		printf("Error: allocate memory for hostcmd failed\n");
+		if (argc == 5)
+			fclose(fp);
+		return -ENOMEM;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	/* buf = MRVL_CMD<cmd> */
+	prepare_buffer(buffer, HOSTCMD, 0, NULL);
+
+	/* buf = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	ret = prepare_cfg_data_buffer(argc, argv, fp, (t_u8 *)hostcmd,
+				      cmd_header_len);
+	if (argc == 5)
+		fclose(fp);
+
+	if (ret == MLAN_STATUS_FAILURE)
+		goto _exit_;
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[CFG_DATA]");
+		printf("ERR:Command sending failed!\n");
+		if (buffer)
+			free(buffer);
+		if (cmd)
+			free(cmd);
+		return MLAN_STATUS_FAILURE;
+	}
+	ret = process_host_cmd_resp(HOSTCMD, buffer);
+
+_exit_:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Process transmission of mgmt frames
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_mgmtframetx(int argc, char *argv[])
+{
+	struct ifreq ifr;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int li = 0, arg_num = 0, ret = 0, i = 0;
+	char *args[100], *pos = NULL, mac_addr[20];
+	t_u8 peer_mac[ETH_ALEN];
+	t_u16 data_len = 0, type = 0, subtype = 0;
+	t_u16 seq_num = 0, frag_num = 0, from_ds = 0, to_ds = 0;
+	eth_priv_mgmt_frame_tx *pmgmt_frame = NULL;
+	t_u8 *buffer = NULL;
+	pkt_header *hdr = NULL;
+
+	/* Check arguments */
+	if (argc != 4) {
+		printf("ERR:Incorrect number of arguments.\n");
+		printf("Syntax: ./mlanutl mlanX mgmtframetx <config/mgmt_frame.conf>\n");
+		exit(1);
+	}
+
+	data_len = sizeof(eth_priv_mgmt_frame_tx);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+	hdr = (pkt_header *)buffer;
+	pmgmt_frame = (eth_priv_mgmt_frame_tx *)(buffer + sizeof(pkt_header));
+
+	/* Check if file exists */
+	config_file = fopen(argv[3], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		goto done;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		arg_num = parse_line(line, args);
+		if (strcmp(args[0], "PktType") == 0) {
+			type = (t_u16)A2HEXDECIMAL(args[1]);
+			pmgmt_frame->frm_ctl = (type & 0x3) << 2;
+		} else if (strcmp(args[0], "PktSubType") == 0) {
+			subtype = (t_u16)A2HEXDECIMAL(args[1]);
+			pmgmt_frame->frm_ctl |= subtype << 4;
+		} else if (strncmp(args[0], "Addr", 4) == 0) {
+			strncpy(mac_addr, args[1], 20);
+			ret = mac2raw(mac_addr, peer_mac);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				printf("%s Address \n",
+				       ret ==
+				       MLAN_STATUS_FAILURE ? "Invalid MAC" : ret
+				       ==
+				       MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				if (ret == MLAN_STATUS_FAILURE)
+					goto done;
+			}
+			i = atoi(args[0] + 4);
+			switch (i) {
+			case 1:
+				memcpy(pmgmt_frame->addr1, peer_mac, ETH_ALEN);
+				break;
+			case 2:
+				memcpy(pmgmt_frame->addr2, peer_mac, ETH_ALEN);
+				break;
+			case 3:
+				memcpy(pmgmt_frame->addr3, peer_mac, ETH_ALEN);
+				break;
+			case 4:
+				memcpy(pmgmt_frame->addr4, peer_mac, ETH_ALEN);
+				break;
+			}
+		} else if (strcmp(args[0], "Data") == 0) {
+			for (i = 0; i < arg_num - 1; i++)
+				pmgmt_frame->payload[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			data_len += arg_num - 1;
+		} else if (strcmp(args[0], "SeqNum") == 0) {
+			seq_num = (t_u16)A2HEXDECIMAL(args[1]);
+			pmgmt_frame->seq_ctl = seq_num << 4;
+		} else if (strcmp(args[0], "FragNum") == 0) {
+			frag_num = (t_u16)A2HEXDECIMAL(args[1]);
+			pmgmt_frame->seq_ctl |= frag_num;
+		} else if (strcmp(args[0], "FromDS") == 0) {
+			from_ds = (t_u16)A2HEXDECIMAL(args[1]);
+			pmgmt_frame->frm_ctl |= (from_ds & 0x1) << 9;
+		} else if (strcmp(args[0], "ToDS") == 0) {
+			to_ds = (t_u16)A2HEXDECIMAL(args[1]);
+			pmgmt_frame->frm_ctl |= (to_ds & 0x1) << 8;
+		}
+	}
+	pmgmt_frame->frm_len = data_len - sizeof(pmgmt_frame->frm_len);
+#define MRVL_PKT_TYPE_MGMT_FRAME 0xE5
+	hdr->pkt_len = data_len;
+	hdr->TxPktType = MRVL_PKT_TYPE_MGMT_FRAME;
+	hdr->TxControl = 0;
+	hexdump("Frame Tx", buffer, data_len + sizeof(pkt_header), ' ');
+	/* Send collective command */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)buffer;
+
+	/* Perform ioctl */
+	if (ioctl(sockfd, FRAME_TX_IOCTL, &ifr)) {
+		perror("");
+		printf("ERR:Could not send management frame.\n");
+	} else {
+		printf("Mgmt Frame sucessfully sent.\n");
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief set/get management frame passthrough
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_mgmt_frame_passthrough(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	t_u32 mask = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: htcapinfo fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	mask = *(t_u32 *)buffer;
+	if (argc == 3)
+		printf("Registed Management Frame Mask: 0x%x\n", mask);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief read current command
+ *  @param ptr      A pointer to data
+ *  @param curCmd   A pointer to the buf which will hold current command
+ *  @return         NULL or the pointer to the left command buf
+ */
+static t_s8 *
+readCurCmd(t_s8 *ptr, t_s8 *curCmd)
+{
+	t_s32 i = 0;
+#define MAX_CMD_SIZE 64	/**< Max command size */
+
+	while (*ptr != ']' && i < (MAX_CMD_SIZE - 1))
+		curCmd[i++] = *(++ptr);
+
+	if (*ptr != ']')
+		return NULL;
+
+	curCmd[i - 1] = '\0';
+
+	return ++ptr;
+}
+
+/**
+ *  @brief parse command and hex data
+ *  @param fp       A pointer to FILE stream
+ *  @param dst      A pointer to the dest buf
+ *  @param cmd      A pointer to command buf for search
+ *  @return         Length of hex data or MLAN_STATUS_FAILURE
+ */
+static int
+fparse_for_cmd_and_hex(FILE * fp, t_u8 *dst, t_u8 *cmd)
+{
+	t_s8 *ptr;
+	t_u8 *dptr;
+	t_s8 buf[256], curCmd[64];
+	t_s32 isCurCmd = 0;
+
+	dptr = dst;
+	while (fgets((char *)buf, sizeof(buf), fp)) {
+		ptr = buf;
+
+		while (*ptr) {
+			/* skip leading spaces */
+			while (*ptr && isspace(*ptr))
+				ptr++;
+
+			/* skip blank lines and lines beginning with '#' */
+			if (*ptr == '\0' || *ptr == '#')
+				break;
+
+			if (*ptr == '[' && *(ptr + 1) != '/') {
+				ptr = readCurCmd(ptr, curCmd);
+				if (!ptr)
+					return MLAN_STATUS_FAILURE;
+
+				if (strcasecmp((char *)curCmd, (char *)cmd))	/* Not equal */
+					isCurCmd = 0;
+				else
+					isCurCmd = 1;
+			}
+
+			/* Ignore the rest if it is not correct cmd */
+			if (!isCurCmd)
+				break;
+
+			if (*ptr == '[' && *(ptr + 1) == '/')
+				return dptr - dst;
+
+			if (isxdigit(*ptr)) {
+				ptr = (t_s8 *)convert2hex((char *)ptr, dptr++);
+			} else {
+				/* Invalid character on data line */
+				ptr++;
+			}
+		}
+	}
+
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Send a WMM AC Queue configuration command to get/set/default params
+ *
+ *  Configure or get the parameters of a WMM AC queue. The command takes
+ *    an optional Queue Id as a last parameter.  Without the queue id, all
+ *    queues will be acted upon.
+ *
+ *  mlanutl mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+ *  mlanutl mlanX qconfig get [Queue Id: 0-3]
+ *  mlanutl mlanX qconfig def [Queue Id: 0-3]
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_qconfig(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	wlan_ioctl_wmm_queue_config_t queue_config_cmd;
+	mlan_wmm_ac_e ac_idx;
+	mlan_wmm_ac_e ac_idx_start;
+	mlan_wmm_ac_e ac_idx_stop;
+	int cmd_header_len = 0;
+
+	const char *ac_str_tbl[] = { "BK", "BE", "VI", "VO" };
+
+	if (argc < 4) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return -EINVAL;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(argv[2]);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		printf("Error: allocate memory for qconfig failed\n");
+		return -ENOMEM;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	/* buf = MRVL_CMD<cmd> */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	memset(&queue_config_cmd, 0x00, sizeof(wlan_ioctl_wmm_queue_config_t));
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (strcmp(argv[3], "get") == 0) {
+		/*    3     4    5   */
+		/* qconfig get [qid] */
+		if (argc == 4) {
+			ac_idx_start = WMM_AC_BK;
+			ac_idx_stop = WMM_AC_VO;
+		} else if (argc == 5) {
+			if (atoi(argv[4]) < WMM_AC_BK ||
+			    atoi(argv[4]) > WMM_AC_VO) {
+				fprintf(stderr, "ERROR: Invalid Queue ID!\n");
+				return -EINVAL;
+			}
+			ac_idx_start = atoi(argv[4]);
+			ac_idx_stop = ac_idx_start;
+		} else {
+			fprintf(stderr, "Invalid number of parameters!\n");
+			return -EINVAL;
+		}
+		queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_GET;
+
+		for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) {
+			queue_config_cmd.accessCategory = ac_idx;
+			memcpy(buffer + cmd_header_len,
+			       (t_u8 *)&queue_config_cmd,
+			       sizeof(queue_config_cmd));
+			if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+				perror("qconfig ioctl");
+			} else {
+				memcpy((t_u8 *)&queue_config_cmd,
+				       buffer + cmd_header_len,
+				       sizeof(queue_config_cmd));
+				printf("qconfig %s(%d): MSDU Lifetime GET = 0x%04x (%d)\n", ac_str_tbl[ac_idx], ac_idx, queue_config_cmd.msduLifetimeExpiry, queue_config_cmd.msduLifetimeExpiry);
+			}
+		}
+	} else if (strcmp(argv[3], "set") == 0) {
+		if ((argc >= 5) && strcmp(argv[4], "msdu") == 0) {
+			/*    3     4    5     6      7   */
+			/* qconfig set msdu <value> [qid] */
+			if (argc == 6) {
+				ac_idx_start = WMM_AC_BK;
+				ac_idx_stop = WMM_AC_VO;
+			} else if (argc == 7) {
+				if (atoi(argv[6]) < WMM_AC_BK ||
+				    atoi(argv[6]) > WMM_AC_VO) {
+					fprintf(stderr,
+						"ERROR: Invalid Queue ID!\n");
+					return -EINVAL;
+				}
+				ac_idx_start = atoi(argv[6]);
+				ac_idx_stop = ac_idx_start;
+			} else {
+				fprintf(stderr,
+					"Invalid number of parameters!\n");
+				return -EINVAL;
+			}
+			queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_SET;
+			queue_config_cmd.msduLifetimeExpiry = atoi(argv[5]);
+
+			for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop;
+			     ac_idx++) {
+				queue_config_cmd.accessCategory = ac_idx;
+				memcpy(buffer + cmd_header_len,
+				       (t_u8 *)&queue_config_cmd,
+				       sizeof(queue_config_cmd));
+				if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+					perror("qconfig ioctl");
+				} else {
+					memcpy((t_u8 *)&queue_config_cmd,
+					       buffer + cmd_header_len,
+					       sizeof(queue_config_cmd));
+					printf("qconfig %s(%d): MSDU Lifetime SET = 0x%04x (%d)\n", ac_str_tbl[ac_idx], ac_idx, queue_config_cmd.msduLifetimeExpiry, queue_config_cmd.msduLifetimeExpiry);
+				}
+			}
+		} else {
+			/* Only MSDU Lifetime provisioning accepted for now */
+			fprintf(stderr, "Invalid set parameter: s/b [msdu]\n");
+			return -EINVAL;
+		}
+	} else if (strncmp(argv[3], "def", strlen("def")) == 0) {
+		/*    3     4    5   */
+		/* qconfig def [qid] */
+		if (argc == 4) {
+			ac_idx_start = WMM_AC_BK;
+			ac_idx_stop = WMM_AC_VO;
+		} else if (argc == 5) {
+			if (atoi(argv[4]) < WMM_AC_BK ||
+			    atoi(argv[4]) > WMM_AC_VO) {
+				fprintf(stderr, "ERROR: Invalid Queue ID!\n");
+				return -EINVAL;
+			}
+			ac_idx_start = atoi(argv[4]);
+			ac_idx_stop = ac_idx_start;
+		} else {
+			fprintf(stderr, "Invalid number of parameters!\n");
+			return -EINVAL;
+		}
+		queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_DEFAULT;
+
+		for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) {
+			queue_config_cmd.accessCategory = ac_idx;
+			memcpy(buffer + cmd_header_len,
+			       (t_u8 *)&queue_config_cmd,
+			       sizeof(queue_config_cmd));
+			if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+				perror("qconfig ioctl");
+			} else {
+				memcpy((t_u8 *)&queue_config_cmd,
+				       buffer + cmd_header_len,
+				       sizeof(queue_config_cmd));
+				printf("qconfig %s(%d): MSDU Lifetime DEFAULT = 0x%04x (%d)\n", ac_str_tbl[ac_idx], ac_idx, queue_config_cmd.msduLifetimeExpiry, queue_config_cmd.msduLifetimeExpiry);
+			}
+		}
+	} else {
+		fprintf(stderr,
+			"Invalid qconfig command; s/b [set, get, default]\n");
+		return -EINVAL;
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Send an ADDTS command to the associated AP
+ *
+ *  Process a given conf file for a specific TSPEC data block.  Send the
+ *    TSPEC along with any other IEs to the driver/firmware for transmission
+ *    in an ADDTS request to the associated AP.
+ *
+ *  Return the execution status of the command as well as the ADDTS response
+ *    from the AP if any.
+ *
+ *  mlanutl mlanX addts <filename.conf> <section# of tspec> <timeout in ms>
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_addts(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	wlan_ioctl_wmm_addts_req_t addtsReq;
+	FILE *fp = NULL;
+	char filename[48];
+	char config_id[20];
+	int cmd_header_len = 0, ret = 0, copy_len = 0;
+
+	memset(&addtsReq, 0x00, sizeof(addtsReq));
+	memset(filename, 0x00, sizeof(filename));
+
+	if (argc != 6) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(argv[2]);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		printf("Error: allocate memory for buffer failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	/* buf = MRVL_CMD<cmd> */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3])));
+	fp = fopen(filename, "r");
+	if (fp == NULL) {
+		perror("fopen");
+		fprintf(stderr, "Cannot open file %s\n", argv[3]);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	snprintf(config_id, sizeof(config_id), "tspec%d", atoi(argv[4]));
+
+	addtsReq.ieDataLen = fparse_for_cmd_and_hex(fp,
+						    addtsReq.ieData,
+						    (t_u8 *)config_id);
+
+	if (addtsReq.ieDataLen > 0) {
+		printf("Found %d bytes in the %s section of conf file %s\n",
+		       (int)addtsReq.ieDataLen, config_id, filename);
+	} else {
+		fprintf(stderr, "section %s not found in %s\n",
+			config_id, filename);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	addtsReq.timeout_ms = atoi(argv[5]);
+
+	printf("Cmd Input:\n");
+	hexdump(config_id, addtsReq.ieData, addtsReq.ieDataLen, ' ');
+	copy_len = sizeof(addtsReq);
+	memcpy(buffer + cmd_header_len, (t_u8 *)&addtsReq, copy_len);
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl: addts ioctl");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(&addtsReq, buffer, strlen((const char *)buffer));
+	printf("Cmd Output:\n");
+	printf("ADDTS Command Result = %d\n", addtsReq.commandResult);
+	printf("ADDTS IEEE Status    = %d\n", addtsReq.ieeeStatusCode);
+	hexdump(config_id, addtsReq.ieData, addtsReq.ieDataLen, ' ');
+
+done:
+	if (fp)
+		fclose(fp);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Send a DELTS command to the associated AP
+ *
+ *  Process a given conf file for a specific TSPEC data block.  Send the
+ *    TSPEC along with any other IEs to the driver/firmware for transmission
+ *    in a DELTS request to the associated AP.
+ *
+ *  Return the execution status of the command.  There is no response to a
+ *    DELTS from the AP.
+ *
+ *  mlanutl mlanX delts <filename.conf> <section# of tspec>
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_delts(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	wlan_ioctl_wmm_delts_req_t deltsReq;
+	FILE *fp = NULL;
+	char filename[48];
+	char config_id[20];
+	int cmd_header_len = 0, ret = 0, copy_len = 0;
+
+	memset(&deltsReq, 0x00, sizeof(deltsReq));
+	memset(filename, 0x00, sizeof(filename));
+
+	if (argc != 5) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(argv[2]);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		printf("Error: allocate memory for buffer failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	/* buf = MRVL_CMD<cmd> */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3])));
+	fp = fopen(filename, "r");
+	if (fp == NULL) {
+		perror("fopen");
+		fprintf(stderr, "Cannot open file %s\n", argv[3]);
+		ret = -EFAULT;;
+		goto done;
+	}
+
+	snprintf(config_id, sizeof(config_id), "tspec%d", atoi(argv[4]));
+
+	deltsReq.ieDataLen = fparse_for_cmd_and_hex(fp,
+						    deltsReq.ieData,
+						    (t_u8 *)config_id);
+
+	if (deltsReq.ieDataLen > 0) {
+		printf("Found %d bytes in the %s section of conf file %s\n",
+		       (int)deltsReq.ieDataLen, config_id, filename);
+	} else {
+		fprintf(stderr, "section %s not found in %s\n",
+			config_id, filename);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	printf("Cmd Input:\n");
+	hexdump(config_id, deltsReq.ieData, deltsReq.ieDataLen, ' ');
+
+	copy_len =
+		sizeof(deltsReq) - sizeof(deltsReq.ieData) + deltsReq.ieDataLen;
+	memcpy(buffer + cmd_header_len, (t_u8 *)&deltsReq, copy_len);
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("delts ioctl");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(&deltsReq, buffer, strlen((const char *)buffer));
+	printf("Cmd Output:\n");
+	printf("DELTS Command Result = %d\n", deltsReq.commandResult);
+
+done:
+	if (fp)
+		fclose(fp);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Get the current status of the WMM Queues
+ *
+ *  Command: mlanutl mlanX qstatus
+ *
+ *  Retrieve the following information for each AC if wmm is enabled:
+ *        - WMM IE ACM Required
+ *        - Firmware Flow Required
+ *        - Firmware Flow Established
+ *        - Firmware Queue Enabled
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_wmm_qstatus(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	wlan_ioctl_wmm_queue_status_t qstatus;
+	int ret = 0;
+	mlan_wmm_ac_e acVal;
+
+	if (argc != 3) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	memset(&qstatus, 0x00, sizeof(qstatus));
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		printf("Error: allocate memory for qconfig failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	/* buf = MRVL_CMD<cmd> */
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("qstatus ioctl");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(&qstatus, buffer, strlen((const char *)buffer));
+	for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) {
+		switch (acVal) {
+		case WMM_AC_BK:
+			printf("BK: ");
+			break;
+		case WMM_AC_BE:
+			printf("BE: ");
+			break;
+		case WMM_AC_VI:
+			printf("VI: ");
+			break;
+		case WMM_AC_VO:
+			printf("VO: ");
+			break;
+		default:
+			printf("??: ");
+		}
+
+		printf("ACM[%c], FlowReq[%c], FlowCreated[%c], Enabled[%c],"
+		       " DE[%c], TE[%c]\n",
+		       (qstatus.acStatus[acVal].wmmAcm ? 'X' : ' '),
+		       (qstatus.acStatus[acVal].flowRequired ? 'X' : ' '),
+		       (qstatus.acStatus[acVal].flowCreated ? 'X' : ' '),
+		       (qstatus.acStatus[acVal].disabled ? ' ' : 'X'),
+		       (qstatus.acStatus[acVal].deliveryEnabled ? 'X' : ' '),
+		       (qstatus.acStatus[acVal].triggerEnabled ? 'X' : ' '));
+	}
+
+done:
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Get the current status of the WMM Traffic Streams
+ *
+ *  Command: mlanutl mlanX ts_status
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_wmm_ts_status(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	wlan_ioctl_wmm_ts_status_t ts_status;
+	int tid;
+	int cmd_header_len = 0, ret = 0;
+
+	const char *ac_str_tbl[] = { "BK", "BE", "VI", "VO" };
+
+	if (argc != 3) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(argv[2]);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		printf("Error: allocate memory for qconfig failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	/* buf = MRVL_CMD<cmd> */
+
+	printf("\nTID   Valid    AC   UP   PSB   FlowDir  MediumTime\n");
+	printf("---------------------------------------------------\n");
+
+	for (tid = 0; tid <= 7; tid++) {
+		memset(buffer, 0, BUFFER_LENGTH);
+		prepare_buffer(buffer, argv[2], 0, NULL);
+		memset(&ts_status, 0x00, sizeof(ts_status));
+		ts_status.tid = tid;
+
+		/* Initialize the ifr structure */
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+		ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+		memcpy(buffer + cmd_header_len, (t_u8 *)&ts_status,
+		       sizeof(ts_status));
+
+		if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+			perror("ts_status ioctl");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memcpy(&ts_status, buffer, strlen((const char *)buffer));
+		printf(" %02d     %3s    %2s    %u     %c    ",
+		       ts_status.tid,
+		       (ts_status.valid ? "Yes" : "No"),
+		       (ts_status.
+			valid ? ac_str_tbl[ts_status.accessCategory] : "--"),
+		       ts_status.userPriority, (ts_status.psb ? 'U' : 'L'));
+
+		if ((ts_status.flowDir & 0x03) == 0) {
+			printf("%s", " ---- ");
+		} else {
+			printf("%2s%4s",
+			       (ts_status.flowDir & 0x01 ? "Up" : ""),
+			       (ts_status.flowDir & 0x02 ? "Down" : ""));
+		}
+
+		printf("%12u\n", ts_status.mediumTime);
+	}
+	printf("\n");
+
+done:
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Set/get WMM IE QoS info parameter
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_qos_config(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Insufficient parameters\n");
+		printf("mlanutl mlanX qoscfg [QoS]\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: qoscfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		/* GET operation */
+		printf("WMM QoS Info: %#x\n", *buffer);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set/get MAC control configuration
+ *
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+
+static int
+process_macctrl(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	t_u32 mac_ctrl = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Insufficient parameters\n");
+		printf("mlanutl mlanX macctrl [macctrl]\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: macctrl fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	mac_ctrl = *(t_u32 *)buffer;
+	if (argc == 3) {
+		/* GET operation */
+		printf("MAC Control: 0x%08x\n", mac_ctrl);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process generic commands
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_generic(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if ((ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) < 0) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: %s fail\n", argv[2]);
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		/* GET operation */
+		printf("%s command response received: %s\n", argv[2], buffer);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set/Get mlanX FW side MAC address
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_fwmacaddr(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Insufficient parameters\n");
+		printf("mlanutl mlanX fwmacaddr [fwmacaddr]\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: fwmacaddr fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		/* GET operation */
+		printf("FW MAC address = ");
+		print_mac(buffer);
+		printf("\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef RX_PACKET_COALESCE
+static void
+print_rx_packet_coalesc_help()
+{
+	printf("\nUSAGE: rxpktcoal_cfg [PKT-THRESHOLD] [TIMEOUT]\n\n");
+	printf("OPTIONS:");
+	printf("PKT-THRESHOLD: count after which packets would be sent to host. Valid values 1-7\n");
+	printf("\tTIMEOUT: Time after which packets would be sent to host Valid values 1-4\n");
+	printf("\tCoalescing is disabled if both or either of PKT-THRESHOLD or TIMEOUT is zero\n\n");
+	printf("\tEmpty - Get current packet coalescing settings\n");
+}
+
+static int
+process_rx_pkt_coalesce_cfg(int argc, char *argv[])
+{
+
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	tlvbuf_rx_pkt_coal_t *rx_pkt_info;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	if ((argc != 3) && (argc != 5)) {
+		printf("ERR:Invalid no. of arguments\n");
+		print_rx_packet_coalesc_help();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if ((ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) < 0) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: %s fail\n", argv[2]);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc == 3) {	/* GET operation */
+		rx_pkt_info = (tlvbuf_rx_pkt_coal_t *)(buffer);
+		printf("RX packet coalesce configuraion:\n");
+		printf("Packet threshold=%d\n", rx_pkt_info->rx_pkt_count);
+		printf("Timeout=%dms\n", rx_pkt_info->delay);
+	} else {
+		printf("RX packet coalesce configuration set successfully.\n");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+
+}
+#endif
+
+/**
+ *  @brief Set/Get mlanX channel time and buffer weight
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_multi_chan_cfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	eth_priv_multi_chan_cfg *multi_chan_info;
+	MrvlIEtypes_multi_chan_info_t *pmc_info = NULL;
+	MrvlIEtypes_multi_chan_group_info_t *pmc_grp_info = NULL;
+	MrvlIEtypesHeader_t *tlv = NULL;
+	t_u32 interfaces = 0;
+	t_u16 tlv_type, tlv_len;
+	int tlv_buf_left = 0, num_intf = 0, bss_type = 0, bss_num = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	if ((argc < 3) || (argc > 4)) {
+		printf("ERR:Invalid arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	multi_chan_info =
+		(eth_priv_multi_chan_cfg *)(buffer + strlen(CMD_MARVELL) +
+					    strlen(argv[2]));
+
+	if (argc > 3) {		/* SET operation */
+		multi_chan_info->channel_time = atoi(argv[3]);
+		multi_chan_info->buffer_weight = 1;
+	}
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if ((ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) < 0) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: %s fail\n", argv[2]);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc == 3) {	/* GET operation */
+		multi_chan_info = (eth_priv_multi_chan_cfg *)(buffer);
+		printf("Channel time = %dus\n", multi_chan_info->channel_time);
+		printf("Buffer weight = %d\n", multi_chan_info->buffer_weight);
+		if (multi_chan_info->tlv_len) {
+			pmc_info =
+				(MrvlIEtypes_multi_chan_info_t *)
+				multi_chan_info->tlv_buf;
+			tlv_buf_left = multi_chan_info->tlv_len;
+			if (tlv_buf_left < sizeof(MrvlIEtypes_multi_chan_info_t)
+			    || le16_to_cpu(pmc_info->header.type) !=
+			    MULTI_CHAN_INFO_TLV_ID) {
+				printf("Invalid TLV in command response!\n");
+				goto done;
+			}
+			tlv_buf_left =
+				le16_to_cpu(pmc_info->header.len) -
+				sizeof(pmc_info->status);
+			printf("Status = %s\n",
+			       le16_to_cpu(pmc_info->
+					   status) ? "Active" : "Inactive");
+			tlv = (MrvlIEtypesHeader_t *)pmc_info->tlv_buffer;
+			while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+				tlv_type = le16_to_cpu(tlv->type);
+				tlv_len = le16_to_cpu(tlv->len);
+				if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+				    (unsigned int)tlv_buf_left) {
+					printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, tlv_buf_left);
+					break;
+				}
+				if (tlv_type != MULTI_CHAN_GROUP_INFO_TLV_ID) {
+					printf("wrong tlv type:0x%x\n",
+					       tlv_type);
+					break;
+				}
+				pmc_grp_info =
+					(MrvlIEtypes_multi_chan_group_info_t *)
+					tlv;
+				printf("Multi-channel Info: GroupID=%d\n\tChan=%d, Numintf=%d\n", pmc_grp_info->chan_group_id, pmc_grp_info->chan_band_info.chan_num, pmc_grp_info->num_intf);
+				num_intf = pmc_grp_info->num_intf;
+				for (interfaces = 0; interfaces < num_intf;
+				     interfaces++) {
+					bss_type =
+						pmc_grp_info->
+						bss_type_numlist[interfaces] >>
+						4;
+					bss_num =
+						pmc_grp_info->
+						bss_type_numlist[interfaces] &
+						BSS_NUM_MASK;
+					printf("\tintf%d: bss_type=%d bss_num=%d\n", interfaces, bss_type, bss_num);
+				}
+				tlv_buf_left -=
+					(sizeof(MrvlIEtypesHeader_t) + tlv_len);
+				tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv +
+							      tlv_len +
+							      sizeof
+							      (MrvlIEtypesHeader_t));
+			}
+		}
+	} else {
+		printf("Channel time set successfully.\n");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Set/Get mlanX multi_channel policy
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_multi_chan_policy(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	t_u16 data = 0;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	if ((argc < 3) || (argc > 4)) {
+		printf("ERR:Invalid arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if ((ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) < 0) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: %s fail\n", argv[2]);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc == 3) {	/* GET operation */
+		data = *((t_u16 *)buffer);
+		printf("Multi-Channel Policy: %s\n",
+		       (data) ? "Enabled" : "Disabled");
+	} else {
+		printf("Multi-Channel Policy Setting successful!\n");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Set/Get mlanX drcs time slicing parameters
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_drcs_time_slicing_cfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	eth_priv_drcs_cfg *drcs_cfg;
+	t_u8 data[8], i;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	if (!((argc == 3) || (argc == 7) || (argc == 11))) {
+		printf("ERR:Invalid arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if (argc > 3) {
+		for (i = 3; i < argc; i++) {
+			data[i - 3] = a2hex_or_atoi(argv[i]);
+		}
+		if (!(data[0] > 0 && data[1] > 0 && data[2] > 0)) {
+			printf("ERR:Invalid arguments! time should be more than zero !\n");
+			return MLAN_STATUS_FAILURE;
+		}
+		if (data[3] < 0 || data[3] > 0x01) {
+			printf("ERR:Invalid arguments! Mode only can be set bit0 !\n");
+			return MLAN_STATUS_FAILURE;
+		}
+		/* Set the same parameters for two channels */
+		if (0x7 == argc) {
+			if (!(data[2] < data[1])) {
+				printf("ERR:Invalid arguments! Undozetime should be less than other channel's switchtime!\n");
+				return MLAN_STATUS_FAILURE;
+			}
+		} else {
+			if (!(data[4] > 0 && data[5] > 0 && data[6] > 0)) {
+				printf("ERR:Invalid arguments! time should be more than zero !\n");
+				return MLAN_STATUS_FAILURE;
+			}
+			if (!(data[2] < data[5] && data[6] < data[1])) {
+				printf("ERR:Invalid arguments! Undozetime should be less than other channel's switchtime!\n");
+				return MLAN_STATUS_FAILURE;
+			}
+			if (data[7] < 0 || data[7] > 0x01) {
+				printf("ERR:Invalid arguments! Mode only can be set bit0 !\n");
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+	}
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if ((ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) < 0) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: %s fail\n", argv[2]);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc == 3) {	/* GET operation */
+		drcs_cfg = (eth_priv_drcs_cfg *) (buffer);
+		printf("Channel index%d: chantime=%d switchtime=%d undozetime=%d mode=%d\n", (drcs_cfg->chan_idx - 1), drcs_cfg->chantime, drcs_cfg->switchtime, drcs_cfg->undozetime, drcs_cfg->mode);
+		drcs_cfg++;
+		printf("Channel index%d: chantime=%d switchtime=%d undozetime=%d mode=%d\n", (drcs_cfg->chan_idx - 1), drcs_cfg->chantime, drcs_cfg->switchtime, drcs_cfg->undozetime, drcs_cfg->mode);
+	} else {
+		printf("DRCS parameters are set successfully.\n");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Process regioncode configuration
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_regioncode(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	t_u32 regioncode;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: regioncode config fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		memcpy(&regioncode, buffer, sizeof(regioncode));
+		printf("regioncode: %d\n", regioncode);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process offchannel configuration
+ *  @param argc   number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_offchannel(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 6) {
+		printf("Incorrect number of parameters\n");
+		printf("mlanutl mlanX offchannel <action> [<channel> <duration>]\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: offchannel config fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("%s\n", buffer);
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process link statistics
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_linkstats(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u8 *buffer = NULL;
+	t_u8 *data = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	t_u32 cmd_len = 0;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* prepare the host cmd */
+	data = buffer;
+	prepare_buffer(buffer, HOSTCMD, 0, NULL);
+	data += strlen(CMD_MARVELL) + strlen(HOSTCMD);
+	/* add buffer size field */
+	cmd_len =
+		sizeof(HostCmd_DS_GEN) + sizeof(HostCmd_DS_LINK_STATS_SUMMARY);
+	cmd_len = cpu_to_le32(cmd_len);
+	memcpy(data, &cmd_len, sizeof(t_u32));
+	data += sizeof(t_u32);
+	/* add cmd header */
+	hostcmd = (HostCmd_DS_GEN *)data;
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_LINK_STATS_SUMMARY);
+	hostcmd->size = cpu_to_le16(sizeof(HostCmd_DS_GEN));
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: linkstats fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	ret = process_host_cmd_resp(HOSTCMD, buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+#if defined(STA_SUPPORT)
+/**
+ * @brief      Configure PMF parameters
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_pmfcfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct eth_priv_pmfcfg pmfcfg;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc > 5) || (argc == 4) ||
+	    ((argc == 5) && ((!atoi(argv[3])) && atoi(argv[4])))) {
+		printf("ERR: Invalid arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: pmfcfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* GET operation */
+	if (argc == 3) {
+		memcpy(&pmfcfg, buffer, sizeof(struct eth_priv_pmfcfg));
+		printf("Management Frame Protection Capability: %s\n",
+		       (pmfcfg.mfpc ? "Yes" : "No"));
+		if (pmfcfg.mfpc)
+			printf("Management Frame Protection: %s\n",
+			       (pmfcfg.mfpr ? "Required" : "Optional"));
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief Process extended version
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_verext(int argc, char *argv[])
+{
+	int ret = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX verext [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: verext fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	if (cmd->used_len)
+		printf("Extended Version string received: %s\n", buffer);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+/**
+ *  @brief Set/Get radio
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_radio_ctrl(int argc, char *argv[])
+{
+	int ret = 0, radio = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX radioctrl [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: radioctrl fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		memcpy(&radio, buffer, sizeof(radio));
+		if (radio == 0) {
+			printf("Radio is Disabled\n");
+		} else if (radio == 1) {
+			printf("Radio is Enabled\n");
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Implement WMM enable command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_wmm_cfg(int argc, char *argv[])
+{
+	int ret = 0, status = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX wmmcfg [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: wmmcfg fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		memcpy(&status, buffer, sizeof(status));
+		if (status == 0) {
+			printf("WMM is Disabled\n");
+		} else if (status == 1) {
+			printf("WMM is Enabled\n");
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+static int
+process_wmm_param_config(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u8 *buffer = NULL;
+	t_u8 *data = NULL;
+	HostCmd_DS_GEN *hostcmd = NULL;
+	t_u32 cmd_len = 0;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int i = 0;
+	t_u32 wmm_param[MAX_AC_QUEUES][5];
+	t_u8 aci = 0;
+	t_u8 aifsn = 0;
+	t_u8 ecwmax = 0;
+	t_u8 ecwmin = 0;
+	t_u16 txop = 0;
+	HostCmd_DS_WMM_PARAM_CONFIG *cmd_data = NULL;
+
+	/* Sanity tests */
+	if ((argc < 3) || (argc > (3 + 5 * MAX_AC_QUEUES)) ||
+	    (((argc - 3) % 5) != 0)) {
+		printf("Incorrect number of parameters\n");
+		printf("Format reference: mlanutl mlanX wmm_param_config \n");
+		printf("\t[AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+		printf("\t[AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+		printf("\t[AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+		printf("\t[AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	for (i = 3; i < argc; i++) {
+		if (IS_HEX_OR_DIGIT(argv[i]) == MLAN_STATUS_FAILURE) {
+			printf("ERR: Only Number values are allowed\n");
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	i = 3;
+	memset(wmm_param, 0x00, sizeof(wmm_param));
+	while (i < argc) {
+		aci = A2HEXDECIMAL(argv[i]);
+		aifsn = A2HEXDECIMAL(argv[i + 1]);
+		ecwmax = A2HEXDECIMAL(argv[i + 2]);
+		ecwmin = A2HEXDECIMAL(argv[i + 3]);
+		txop = A2HEXDECIMAL(argv[i + 4]);
+		if ((aci >= 0) && (aci <= 3) && !wmm_param[aci][0]) {
+			if (((aifsn >= 2) && (aifsn <= 15))
+			    && ((ecwmax >= 0) && (ecwmax <= 15))
+			    && ((ecwmin >= 0) && (ecwmin <= 15))
+			    && ((txop >= 0) && (txop <= 0xFFFF))) {
+				wmm_param[aci][0] = TRUE;
+				wmm_param[aci][1] = aifsn;
+				wmm_param[aci][2] = ecwmax;
+				wmm_param[aci][3] = ecwmin;
+				wmm_param[aci][4] = txop;
+			} else {
+				printf("wmm parmams invalid\n");
+				return MLAN_STATUS_FAILURE;
+			}
+		} else {
+			printf("aci out of range or repeated \n");
+			return MLAN_STATUS_FAILURE;
+		}
+		i = i + 5;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	memset(buffer, 0x00, BUFFER_LENGTH);
+
+	/* prepare the host cmd */
+	data = buffer;
+	prepare_buffer(buffer, HOSTCMD, 0, NULL);
+	data += strlen(CMD_MARVELL) + strlen(HOSTCMD);
+	/* add buffer size field */
+	cmd_len = sizeof(HostCmd_DS_GEN) + sizeof(HostCmd_DS_WMM_PARAM_CONFIG);
+	cmd_len = cpu_to_le32(cmd_len);
+	memcpy(data, &cmd_len, sizeof(t_u32));
+	data += sizeof(t_u32);
+	/* add cmd header */
+	hostcmd = (HostCmd_DS_GEN *)data;
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_WMM_PARAM_CONFIG);
+	hostcmd->size =
+		cpu_to_le16(sizeof(HostCmd_DS_GEN) +
+			    sizeof(HostCmd_DS_WMM_PARAM_CONFIG));
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+	data += sizeof(HostCmd_DS_GEN);
+	cmd_data = (HostCmd_DS_WMM_PARAM_CONFIG *) data;
+	if (argc > 3) {
+		cmd_data->action = ACTION_SET;
+		for (i = 0; i < MAX_AC_QUEUES; i++) {
+			if (wmm_param[i][0] == TRUE) {
+				cmd_data->ac_params[i].aci_aifsn.acm = 1;
+				cmd_data->ac_params[i].aci_aifsn.aci = (t_u8)i;
+				cmd_data->ac_params[i].aci_aifsn.aifsn =
+					(t_u8)(wmm_param[i][1]);
+				cmd_data->ac_params[i].ecw.ecw_max =
+					(t_u8)(wmm_param[i][2]);
+				cmd_data->ac_params[i].ecw.ecw_min =
+					(t_u8)(wmm_param[i][3]);
+				cmd_data->ac_params[i].tx_op_limit =
+					cpu_to_le16((t_u16)(wmm_param[i][4]));
+			}
+		}
+	} else
+		cmd_data->action = ACTION_GET;
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: linkstats fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	ret = process_host_cmd_resp(HOSTCMD, buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+#if defined(STA_SUPPORT)
+/**
+ *  @brief Implement 802.11D enable command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_11d_cfg(int argc, char *argv[])
+{
+	int ret = 0, status = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX 11dcfg [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: 11dcfg fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		memcpy(&status, buffer, sizeof(status));
+		if (status == 0) {
+			printf("802.11D is Disabled\n");
+		} else if (status == 1) {
+			printf("802.11D is Enabled\n");
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Implement 802.11D clear chan table command
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_11d_clr_tbl(int argc, char *argv[])
+{
+	int ret = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc != 3) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX 11dclrtbl\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: 11dclrtbl fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set/Get WWS configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_wws_cfg(int argc, char *argv[])
+{
+	int ret = 0, status = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX wwscfg [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: wwscfg fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		memcpy(&status, buffer, sizeof(status));
+		if (status == 1) {
+			printf("WWS is Enabled\n");
+		} else if (status == 0) {
+			printf("WWS is Disabled\n");
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+#if defined(REASSOCIATION)
+/**
+ *  @brief Set/Get reassociation settings
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_set_get_reassoc(int argc, char *argv[])
+{
+	int ret = 0, status = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX reassoctrl [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: reassoctrl fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		memcpy(&status, buffer, sizeof(status));
+		if (status == 1) {
+			printf("Re-association is Enabled\n");
+		} else if (status == 0) {
+			printf("Re-association is Disabled\n");
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Get Transmit buffer size
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_txbuf_cfg(int argc, char *argv[])
+{
+	int ret = 0, buf_size = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc != 3) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX txbufcfg\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: txbufcfg fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memcpy(&buf_size, buffer, sizeof(buf_size));
+	printf("Transmit buffer size is %d\n", buf_size);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Set/Get auth type
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_set_get_auth_type(int argc, char *argv[])
+{
+	int ret = 0, auth_type = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX authtype [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: authtype fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	if (argc == 3) {
+		memcpy(&auth_type, buffer, sizeof(auth_type));
+		if (auth_type == 1) {
+			printf("802.11 shared key authentication\n");
+		} else if (auth_type == 0) {
+			printf("802.11 open system authentication\n");
+		} else if (auth_type == 255) {
+			printf("Allow open system or shared key authentication\n");
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set/get user provisioned local power constraint
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_11h_local_pwr_constraint(int argc, char *argv[])
+{
+	int ret = 0, power_cons = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX powercons [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: powercons fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc == 3) {
+		/* Process result */
+		memcpy(&power_cons, buffer, sizeof(power_cons));
+		printf("Local power constraint is %d dbm\n", power_cons);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Set/get HT stream configurations
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_ht_stream_cfg(int argc, char *argv[])
+{
+	int ret = 0, mode = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX htstreamcfg [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: htstreamcfg fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	memcpy(&mode, buffer, sizeof(mode));
+	if (mode == HT_STREAM_MODE_1X1)
+		printf("HT stream is in 1x1 mode\n");
+	else if (mode == HT_STREAM_MODE_2X2)
+		printf("HT stream is in 2x2 mode\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Get thermal reading
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_thermal(int argc, char *argv[])
+{
+	int ret = 0, thermal = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc != 3) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX thermal\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: thermal fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	memcpy(&thermal, buffer, sizeof(thermal));
+	printf("Thermal reading is %d\n", thermal);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Get signal
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_get_signal(int argc, char *argv[])
+{
+#define DATA_SIZE   12
+	int ret = 0, data[DATA_SIZE], i = 0, copy_size = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	memset(data, 0, sizeof(data));
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 5) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX getsignal [m] [n]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: getsignal fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	copy_size = MIN(cmd->used_len, DATA_SIZE * sizeof(int));
+	memcpy(&data, buffer, copy_size);
+	printf("Get signal output is\t");
+	for (i = 0; i < (int)(copy_size / sizeof(int)); i++)
+		printf("%d\t", data[i]);
+	printf("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Set signalext cfg
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_signalext_cfg(int argc, char *argv[])
+{
+	int ret = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc != 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX signalextcfg [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: signalext cfg fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ *  @brief Get signal
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_get_signal_ext(int argc, char *argv[])
+{
+#define MAX_NUM_PATH 3
+#define PATH_SIZE  13
+#define PATH_A 		1
+#define PATH_B		2
+#define PATH_AB		3
+	int ret = 0, data[PATH_SIZE * MAX_NUM_PATH] = { 0 };
+	int i = 0, copy_size = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	t_u8 num_path = 0;
+
+	memset(data, 0, sizeof(data));
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc != 3 && argc != 4) {
+		printf("Error: invalid no of arguments\n");
+		if (strncmp(argv[2], "getsignalextv2", strlen("getsignalextv2"))
+		    == 0)
+			printf("mlanutl mlanX getsignalextv2 [m]\n");
+		else if (strncmp
+			 (argv[2], "getsignalext", strlen("getsignalext")) == 0)
+			printf("mlanutl mlanX getsignalext [m]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: getsignal fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	copy_size = cmd->used_len;
+	memcpy(&data, (int *)buffer, copy_size);
+
+	num_path = copy_size / sizeof(int) / PATH_SIZE;
+	for (i = 0; i < num_path; i++) {
+		if (data[i * PATH_SIZE] == PATH_A)
+			printf("PATH A:   %d %d %d %d %d %d %d %d %d %d %d %d\n", data[i * PATH_SIZE + 1], data[i * PATH_SIZE + 2], data[i * PATH_SIZE + 3], data[i * PATH_SIZE + 4], data[i * PATH_SIZE + 5], data[i * PATH_SIZE + 6], data[i * PATH_SIZE + 7], data[i * PATH_SIZE + 8], data[i * PATH_SIZE + 9], data[i * PATH_SIZE + 10], data[i * PATH_SIZE + 11], data[i * PATH_SIZE + 12]);
+		else if (data[i * PATH_SIZE] == PATH_B)
+			printf("PATH B:   %d %d %d %d %d %d %d %d %d %d %d %d\n", data[i * PATH_SIZE + 1], data[i * PATH_SIZE + 2], data[i * PATH_SIZE + 3], data[i * PATH_SIZE + 4], data[i * PATH_SIZE + 5], data[i * PATH_SIZE + 6], data[i * PATH_SIZE + 7], data[i * PATH_SIZE + 8], data[i * PATH_SIZE + 9], data[i * PATH_SIZE + 10], data[i * PATH_SIZE + 11], data[i * PATH_SIZE + 12]);
+		else if (data[i * PATH_SIZE] == PATH_AB)
+			printf("PATH A+B: %d %d %d %d %d %d %d %d %d %d %d %d\n", data[i * PATH_SIZE + 1], data[i * PATH_SIZE + 2], data[i * PATH_SIZE + 3], data[i * PATH_SIZE + 4], data[i * PATH_SIZE + 5], data[i * PATH_SIZE + 6], data[i * PATH_SIZE + 7], data[i * PATH_SIZE + 8], data[i * PATH_SIZE + 9], data[i * PATH_SIZE + 10], data[i * PATH_SIZE + 11], data[i * PATH_SIZE + 12]);
+	}
+	printf("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+#endif /* #ifdef STA_SUPPORT */
+
+/**
+ *  @brief Set/Get beacon interval
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return       MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_beacon_interval(int argc, char *argv[])
+{
+	int ret = 0, bcninterval = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc < 3 || argc > 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX bcninterval [#]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: bcninterval fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	memcpy(&bcninterval, buffer, sizeof(bcninterval));
+	printf("Beacon interval is %d\n", bcninterval);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ * @brief      Get/Set inactivity timeout extend
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_inactivity_timeout_ext(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	int data[4];
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 6) && (argc != 7)) {
+		printf("ERR: Invalid arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: inactivityto fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* GET operation */
+	if (argc == 3) {
+		memset(data, 0, sizeof(data));
+		memcpy(data, buffer, sizeof(data));
+		printf("Timeout unit is %d us\n"
+		       "Inactivity timeout for unicast data is %d ms\n"
+		       "Inactivity timeout for multicast data is %d ms\n"
+		       "Inactivity timeout for new Rx traffic is %d ms\n",
+		       data[0], data[1], data[2], data[3]);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Set/Get ATIM window
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_atim_window(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	int atim_window = 0;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 4)) {
+		printf("ERR: Invalid arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if ((argc == 4) && (atoi(argv[3]) < 0 || atoi(argv[3]) > 50)) {
+		printf("ERR: ATIM window out of range\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: inactivityto fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* GET operation */
+	if (argc == 3) {
+		memcpy(&atim_window, buffer, sizeof(atim_window));
+		printf("ATIM window value is %d\n", atim_window);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Enable/Disable amsdu_aggr_ctrl
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_11n_amsdu_aggr_ctrl(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	int ret = 0, data[2];
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 4)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: amsduaggrctrl fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(data, 0, sizeof(data));
+	memcpy(data, buffer, sizeof(data));
+	if (data[0] == 1)
+		printf("Feature is enabled\n");
+	if (data[0] == 0)
+		printf("Feature is disabled\n");
+	printf("Current AMSDU buffer size is %d\n", data[1]);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ * @brief      Set/Get Transmit beamforming capabilities
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_tx_bf_cap_ioctl(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	int ret = 0, bf_cap;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 4)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: httxbfcap fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memcpy(&bf_cap, buffer, sizeof(int));
+	printf("Current TX beamforming capability is 0x%x\n", bf_cap);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ * @brief      Turn on/off the sdio clock
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_sdio_clock_ioctl(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	int ret = 0, clock_state = 0;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 4)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: sdioclock fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc == 3) {
+		memcpy(&clock_state, buffer, sizeof(clock_state));
+		printf("Current SDIO clock state is %d\n", clock_state);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ * @brief      Set SDIO Multi-point aggregation control parameters
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_sdio_mpa_ctrl(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	int ret = 0, data[6];
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc < 3) && (argc > 9)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: diaglooptest fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (argc == 3) {
+		memset(data, 0, sizeof(data));
+		memcpy(data, buffer, sizeof(data));
+		printf("Enable MP aggregation for Tx is %d\n", data[0]);
+		printf("Enable MP aggregation for Rx is %d\n", data[1]);
+		printf("Tx buffer size is %d\n", data[2]);
+		printf("Rx buffer size is %d\n", data[3]);
+		printf("maximum Tx port is %d\n", data[4]);
+		printf("maximum Rx port is %d\n", data[5]);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+#endif
+
+/**
+ * @brief      Configure sleep parameters
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_sleep_params(int argc, char *argv[])
+{
+	int ret = 0, data[6];
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 9)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+/*    prepare_buffer(buffer, argv[2], 0, NULL); */
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: sleepparams fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(data, 0, sizeof(data));
+	memcpy(data, buffer, sizeof(data));
+	printf("Sleep clock error in ppm is %d\n", data[0]);
+	printf("Wakeup offset in usec is %d\n", data[1]);
+	printf("Clock stabilization time in usec is %d\n", data[2]);
+	printf("Control periodic calibration is %d\n", data[3]);
+	printf("Control the use of external sleep clock is %d\n", data[4]);
+	printf("Debug is %d\n", data[5]);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ * @brief      Set/Get cw mode
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_cwmode(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL, *pos = NULL, *action;
+	char *data = NULL, *args[100];
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	cw_mode_ctrl *cwmode = NULL;
+	FILE *config_file = NULL;
+	char *line = NULL;
+	int li = 0;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(buffer, 0, BUFFER_LENGTH);
+	pos = buffer;
+	strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL));
+	pos += (strlen(CMD_MARVELL));
+	strcpy((char *)pos, argv[2]);
+	pos += (strlen(argv[2]));
+	action = pos;
+	pos++;
+
+	if (argc > 3) {
+		*action = 1;
+		config_file = fopen(argv[3], "r");
+		if (config_file == NULL) {
+			perror("CONFIG");
+			exit(1);
+		}
+
+		line = (char *)malloc(MAX_CONFIG_LINE);
+		if (!line) {
+			printf("ERR:Cannot allocate memory for line\n");
+			exit(1);
+		}
+		memset(line, 0, MAX_CONFIG_LINE);
+		/* Parse file and process */
+		while (config_get_line
+		       (line, MAX_CONFIG_LINE, config_file, &li, &data)) {
+			parse_line(line, args);
+
+			if (strcmp(args[0], "CW_MODE") == 0)
+				cwmode = (cw_mode_ctrl *) pos;
+			else {
+				if (cwmode) {
+					if (strcmp(args[0], "Mode") == 0)
+						cwmode->mode =
+							a2hex_or_atoi(args[1]);
+					else if (strcmp(args[0], "Channel") ==
+						 0)
+						cwmode->channel =
+							a2hex_or_atoi(args[1]);
+					else if (strcmp(args[0], "Chaninfo") ==
+						 0)
+						cwmode->chanInfo =
+							a2hex_or_atoi(args[1]);
+					else if (strcmp(args[0], "TxPower") ==
+						 0)
+						cwmode->txPower =
+							a2hex_or_atoi(args[1]);
+					else if (strcmp(args[0], "PktLength") ==
+						 0)
+						cwmode->pktLength =
+							a2hex_or_atoi(args[1]);
+					else if (strcmp(args[0], "RateInfo") ==
+						 0)
+						cwmode->rateInfo =
+							a2hex_or_atoi(args[1]);
+				} else {
+					printf("invalid config file\n");
+					printf("Specify the parameters in CW_MODE header as shown below:\n");
+					printf("CW_MODE = {\n");
+					printf("//\n");
+					printf("// specify parameters between CW_MODE header only\n");
+					printf("//\n");
+					printf("}\n");
+					exit(1);
+				}
+			}
+		}
+	}
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+	cmd->buf = buffer;
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: cwmode fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	cwmode = (cw_mode_ctrl *) buffer;
+	printf("CW Mode:\nMode = %d\nChannel = %d\nChanInfo = 0x%x\n"
+	       "TxPower=%d\nRateInfo=0x%x\nPacket Length=%d\n",
+	       cwmode->mode, cwmode->channel, cwmode->chanInfo,
+	       cwmode->txPower, cwmode->rateInfo, cwmode->pktLength);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ * @brief      Set/Get DFS Testing settings
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_dfs_testing(int argc, char *argv[])
+{
+	int ret = 0, data[4];
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 7)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: dfstesting fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (argc == 3) {
+		memset(data, 0, sizeof(data));
+		memcpy(data, buffer, sizeof(data));
+		printf("User-configured Channel Availability Check in msec is %d\n", data[0]);
+		printf("User-configured Non-Occupancy Period in sec is %d\n",
+		       data[1]);
+		printf("No channel change on radar enabled is %d\n", data[2]);
+		printf("User-configured channel to change to on radar is %d\n",
+		       data[3]);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+#endif
+
+/**
+ * @brief      Set/Get CFP table codes
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_cfp_code(int argc, char *argv[])
+{
+	int ret = 0, data[2];
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 4) && (argc != 5)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: cfpcode fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (argc == 3) {
+		memset(data, 0, sizeof(data));
+		memcpy(data, buffer, sizeof(data));
+		printf("Code of the CFP table for 2.4GHz is %d\n", data[0]);
+		printf("Code of the CFP table for 5GHz is %d\n", data[1]);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ * @brief      Set/Get Tx/Rx antenna
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_set_get_tx_rx_ant(int argc, char *argv[])
+{
+	int ret = 0;
+	int data[3] = { 0 };
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 4)
+	    && (argc != 5)
+		) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: antcfg fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (argc == 3) {
+		if (cmd->used_len < sizeof(data)) {
+			memcpy(data, buffer, cmd->used_len);
+			printf("Mode of Tx path is %d\n", data[0]);
+			if (cmd->used_len == (sizeof(int) * 2))
+				printf("Mode of Rx path is %d\n", data[1]);
+		} else {
+			memcpy(data, buffer, sizeof(data));
+			printf("Mode of Tx/Rx path is %d\n", data[0]);
+			/* Evaluate time is valid only when SAD is enabled */
+			if (data[0] == 0xffff) {
+				printf("Evaluate time = %d\n", data[1]);
+				/* Current antenna value should be 1,2,3. 0 is invalid value */
+				if (data[2] > 0)
+					printf("Current antenna is %d\n",
+					       data[2]);
+			}
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ * @brief      Get/Set system clock
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_sysclock(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	int data[65], i = 0;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: sysclock fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* GET operation */
+	if (argc == 3) {
+		memset(data, 0, sizeof(data));
+		memcpy(data, buffer, sizeof(data));
+		printf("sysclock = ");
+		for (i = 1; i <= data[0]; i++) {
+			printf("%d ", data[i]);
+		}
+		printf("\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Adhoc AES control
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_adhoc_aes(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: adhocaes fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* GET operation */
+	if (argc == 3)
+		printf("ad-hoc aes key is %s\n", buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Associate to a specific indexed entry in the ScanTable
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_associate_ssid_bssid(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+
+	if (argc == 3) {
+		printf("ERR: Invalid number of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: associate fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Set/Get Transmit beamforming configuration
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_tx_bf_cfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+
+	if (argc == 3) {
+		printf("ERR: Invalid number of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: httxbfcfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Control WPS Session Enable/Disable
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_wps_cfg(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+
+	if (argc < 3 && argc > 4) {
+		printf("ERR: Invalid number of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: wpssession fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	printf("%s\n", buffer);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Set/Get Port Control mode
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_port_ctrl(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+	int port_ctrl = 0;
+
+	if (argc < 3 && argc > 4) {
+		printf("ERR: Invalid number of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: port_ctrl fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	if (argc == 3) {
+		port_ctrl = (int)*buffer;
+		if (port_ctrl == 1)
+			printf("port_ctrl is Enabled\n");
+		else
+			printf("port_ctrl is Disabled\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Private IOCTL entry to get the By-passed TX packet from upper layer
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_bypassed_packet(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: pb_bypass fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      Control Coalescing status Enable/Disable
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_coalescing_status(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+	int status = 0;
+
+	if (argc < 3 && argc > 4) {
+		printf("ERR: Invalid number of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: coalesce_status fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	if (argc == 3) {
+		status = (int)*buffer;
+		if (status == 1)
+			printf("coalesce_status is Enabled\n");
+		else
+			printf("coalesce_status is Disabled\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/* #ifdef FW_WAKEUP_METHOD */
+/**
+ * @brief      Set/Get module configuration
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_fw_wakeup_method(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+	int fw_wakeup_method = 0;
+	int gpio_pin = 0;
+
+	if (argc < 3 || argc > 5) {
+		printf("ERR: Invalid number of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: fwwakeupmethod fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	if (argc == 3) {
+		fw_wakeup_method = (int)*buffer;
+		gpio_pin = (int)*(buffer + 4);
+		if (fw_wakeup_method == 1)
+			printf("FW wakeup method is interface\n");
+		else if (fw_wakeup_method == 2)
+			printf("FW wakeup method is gpio, GPIO Pin is %d\n",
+			       gpio_pin);
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/* #endif */
+
+/**
+ *  @brief SD comand53 read/write
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_sdcmd53rw(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int cmd_header_len = 0;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL;
+	t_u8 *pos = NULL;
+	int addr, mode, blklen, blknum, i, rw;
+	t_u16 cmd_len = 0;
+
+	if (argc < 8) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(argv[2]);
+
+	pos = buffer + cmd_header_len + sizeof(cmd_len);
+
+	if (argc == 8) {
+		rw = pos[0] = 0;	/* CMD53 read */
+	} else {
+		rw = pos[0] = 1;	/* CMD53 write */
+	}
+	pos[1] = atoval(argv[3]);	/* func (0/1/2) */
+	addr = atoval(argv[4]);	/* address */
+	pos[2] = addr & 0xff;
+	pos[3] = (addr >> 8) & 0xff;
+	pos[4] = (addr >> 16) & 0xff;
+	pos[5] = (addr >> 24) & 0xff;
+	mode = atoval(argv[5]);	/* byte mode/block mode (0/1) */
+	pos[6] = (t_u8)mode;
+	blklen = atoval(argv[6]);	/* block size */
+	pos[7] = blklen & 0xff;
+	pos[8] = (blklen >> 8) & 0xff;
+	blknum = atoval(argv[7]);	/* block number or byte number */
+	pos[9] = blknum & 0xff;
+	pos[10] = (blknum >> 8) & 0xff;
+	if (pos[0]) {
+		for (i = 0; i < (argc - 8); i++)
+			pos[11 + i] = atoval(argv[8 + i]);
+	}
+	cmd_len = 11 + i;
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(cmd_len));
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: sdcmd53rw fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (mode) {
+		fprintf(stderr, "CMD53rw blklen = %d, blknum = %d\n", blklen,
+			blknum);
+	} else {
+		blklen = 1;
+		fprintf(stderr, "CMD53rw bytelen = %d\n", blknum);
+	}
+	if (!rw)
+		hexdump("CMD53 data", buffer, blklen * blknum, ' ');
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+/**
+ * @brief      Set/Get P2P NoA (Notice of Absence) Or OPP-PS parameters
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_cfg_noa_opp_ps(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd;
+	struct ifreq ifr;
+	mlan_ds_wifi_direct_config *cfg;
+
+	if (argc < 3 || argc > 8) {
+		printf("ERR: Invalid number of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: noa_cfg fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+	if (argc == 3) {
+		cfg = (mlan_ds_wifi_direct_config *)buffer;
+		if (!cfg) {
+			printf("Err : Could not get P2P noa configuration\n");
+			if (cmd)
+				free(cmd);
+			if (buffer)
+				free(buffer);
+			return MLAN_STATUS_FAILURE;
+		}
+
+		if (cfg->flags & WIFI_DIRECT_NOA) {
+			printf("noa_enable : %d\n", cfg->noa_enable);
+			printf("index : %d\n", cfg->index);
+			printf("noa_count : %d\n", cfg->noa_count);
+			printf("noa_duration : %d\n", cfg->noa_duration);
+			printf("noa_interval : %d\n", cfg->noa_interval);
+		}
+		if (cfg->flags & WIFI_DIRECT_OPP_PS) {
+			printf("opp_ps_enable : %d\n", cfg->opp_ps_enable);
+			printf("ct_window : %d\n", cfg->ct_window);
+		}
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+#endif
+
+/**
+ *  @brief Issue a dscp map command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_dscpmap(int argc, char *argv[])
+{
+	int ret = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	unsigned int dscp, tid, idx;
+	t_u8 dscp_map[64];
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), argv[2], strlen(argv[2]));
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[dscpmap]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	memcpy(dscp_map, buffer, sizeof(dscp_map));
+
+	if ((argc == 4) && (strcmp(argv[3], "reset") == 0)) {
+		memset(dscp_map, 0xff, sizeof(dscp_map));
+	} else if (argc == (3 + sizeof(dscp_map))) {
+		/* Update the entire dscp table */
+		for (idx = 3; idx < (3 + sizeof(dscp_map)); idx++) {
+			tid = a2hex_or_atoi(argv[idx]);
+
+			if ((tid >= 0) && (tid < 8)) {
+				dscp_map[idx - 3] = tid;
+			}
+		}
+	} else if (argc > 3 && argc <= (3 + sizeof(dscp_map))) {
+		/* Update any dscp entries provided on the command line */
+		for (idx = 3; idx < argc; idx++) {
+			if ((sscanf(argv[idx], "%x=%x", &dscp, &tid) == 2)
+			    && (dscp < sizeof(dscp_map))
+			    && (tid >= 0)
+			    && (tid < 8)) {
+				dscp_map[dscp] = tid;
+			}
+		}
+	} else if (argc != 3) {
+		printf("Invalid number of arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(buffer, 0, BUFFER_LENGTH);
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), argv[2], strlen(argv[2]));
+	if (argc > 3)
+		memcpy(buffer + strlen(CMD_MARVELL) + strlen(argv[2]),
+		       dscp_map, sizeof(dscp_map));
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[dscpmap]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Display the active dscp -> TID mapping table */
+	if (cmd->used_len) {
+		printf("DscpMap:\n");
+		hexdump(NULL, buffer, cmd->used_len, ' ');
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Set/Get DF repeater mode parameters
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_dfs_repeater(int argc, char *argv[])
+{
+	int ret = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	dfs_repeater *dfs_rptr = NULL;
+
+	if (argc < 3 && argc > 4) {
+		printf("ERR: Invalid number of arguments\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: %s fail\n", __func__);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (argc == 3) {
+		dfs_rptr = (dfs_repeater *) buffer;
+		printf("DFS repeater mode: %s\n",
+		       (dfs_rptr->mode) ? "On" : "Off");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ *  @brief Set/Get miracast configuration parameters
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_miracastcfg(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int data[3];
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	if (argc < 3 && argc > 6) {
+		fprintf(stderr, "mlanutl: Invalid number of arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		fprintf(stderr, "mlanutl: Cannot allocate memory\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		fprintf(stderr,
+			"mlanutl: Cannot allocate buffer for command\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: miracastcfg fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(data, 0, sizeof(data));
+	/* Process result */
+	memcpy(data, buffer, sizeof(data));
+	if (argc == 3) {
+		/* GET operation */
+		printf("Miracast Configuration:\n");
+		printf("  Mode: %d\n", data[0]);
+		printf("  Scan time: %d\n", data[1]);
+		printf("  Scan channel gap: %d\n", data[2]);
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+#endif /* WIFI_DIRECT_SUPPORT */
+
+/**
+ * @brief      Set/get control to coex RX window size
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_coex_rx_winsize(int argc, char *argv[])
+{
+	int ret = 0;
+	int coex_rx_winsize = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 4)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR: Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR: Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: coex_rx_winsize fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (argc == 3) {
+		memcpy(&coex_rx_winsize, buffer, sizeof(coex_rx_winsize));
+		printf("COEX RX winsize is %s\n",
+		       coex_rx_winsize ? "enabled" : "disabled");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+static int
+process_txaggrctrl(int argc, char *argv[])
+{
+	int ret = 0;
+	int txaggrctrl = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 4)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR: Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR: Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: txaggrctrl fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (argc == 3) {
+		memcpy(&txaggrctrl, buffer, sizeof(txaggrctrl));
+		printf("TX AMPDU on infra link is %s\n",
+		       txaggrctrl ? "enabled" : "disabled");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ * @brief      Set/get control to enable/disable auto TDLS
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_auto_tdls(int argc, char *argv[])
+{
+	int ret = 0;
+	int autotdls = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Check if arguments are valid */
+	if ((argc != 3) && (argc != 4)) {
+		printf("ERR: Invalid arguments\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR: Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR: Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: autotdls fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (argc == 3) {
+		memcpy(&autotdls, buffer, sizeof(autotdls));
+		printf("Auto TDLS is %s\n", autotdls ? "enabled" : "disabled");
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+/**
+ * @brief      get SOC sensor temperature.
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_get_sensor_temp(int argc, char *argv[])
+{
+	int ret = 0;
+	t_u32 temp = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc != 3) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX get_sensor_temp\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], 0, NULL);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: temp_sensor fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	memcpy(&temp, buffer, sizeof(t_u32));
+	printf("SOC temperature is %u C \n", temp);
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return ret;
+}
+
+static int
+chanrpt_getValues(t_u8 chanNum, t_u16 startFreq,
+		  t_u32 duration, t_s16 *pAnpi, t_u8 *pLoadPercent,
+		  t_u8 chanWidth)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	t_u8 *pByte;
+	int respLen;
+	MrvlIEtypes_Data_t *pTlvHdr;
+	HostCmd_DS_GEN *hostcmd;
+	HostCmd_DS_CHAN_RPT_RSP *pChanRptRsp;
+	HostCmd_DS_CHAN_RPT_REQ *pChanRptReq;
+
+	MrvlIEtypes_ChanRptChanLoad_t *pLoadRpt;
+	MrvlIEtypes_ChanRptNoiseHist_t *pNoiseRpt;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(HostCmd_DS_CHAN_RPT_REQ);
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	pChanRptReq = (HostCmd_DS_CHAN_RPT_REQ *)pos;
+	pChanRptRsp = (HostCmd_DS_CHAN_RPT_RSP *)pos;
+
+	memset((void *)pChanRptReq, 0x00, sizeof(HostCmd_DS_CHAN_RPT_REQ));
+
+	pChanRptReq->chanDesc.chanNum = chanNum;
+	pChanRptReq->chanDesc.startFreq = cpu_to_le16(startFreq);
+	pChanRptReq->chanDesc.chanWidth = chanWidth;
+	pChanRptReq->millisecDwellTime = duration;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[chanrpt hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* TSF is a t_u64, some formatted printing libs have
+	 *   trouble printing long longs, so cast and dump as bytes
+	 */
+	pByte = (t_u8 *)&pChanRptRsp->startTsf;
+
+	pByte = pChanRptRsp->tlvBuffer;
+
+	respLen = le16_to_cpu(hostcmd->size) - sizeof(HostCmd_DS_GEN);
+
+	respLen -= sizeof(pChanRptRsp->commandResult);
+	respLen -= sizeof(pChanRptRsp->startTsf);
+	respLen -= sizeof(pChanRptRsp->duration);
+
+	pByte = pChanRptRsp->tlvBuffer;
+
+	while ((unsigned int)respLen >= sizeof(pTlvHdr->header)) {
+		pTlvHdr = (MrvlIEtypes_Data_t *)pByte;
+		pTlvHdr->header.len = le16_to_cpu(pTlvHdr->header.len);
+
+		switch (le16_to_cpu(pTlvHdr->header.type)) {
+		case TLV_TYPE_CHANRPT_CHAN_LOAD:
+			pLoadRpt = (MrvlIEtypes_ChanRptChanLoad_t *)pTlvHdr;
+			*pLoadPercent = (pLoadRpt->ccaBusyFraction * 100) / 255;
+			break;
+
+		case TLV_TYPE_CHANRPT_NOISE_HIST:
+			pNoiseRpt = (MrvlIEtypes_ChanRptNoiseHist_t *)pTlvHdr;
+			*pAnpi = pNoiseRpt->anpi;
+			break;
+
+		default:
+			break;
+		}
+
+		pByte += (pTlvHdr->header.len + sizeof(pTlvHdr->header));
+		respLen -= (pTlvHdr->header.len + sizeof(pTlvHdr->header));
+		respLen = (respLen > 0) ? respLen : 0;
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+static void
+chanrpt_print_xAxis(ChanRptInfo_t * pChanRpt, int numChans)
+{
+	int idx;
+
+	printf("   `-");
+
+	for (idx = 0; idx < numChans; idx++) {
+		printf("----");
+	}
+
+	printf("\n     ");
+
+	for (idx = 0; idx < numChans; idx++) {
+		printf("%03d ", (pChanRpt + idx)->chanNum);
+	}
+
+	printf("\n");
+}
+
+static void
+chanrpt_print_anpi(ChanRptInfo_t * pChanRpt, int numChans)
+{
+	int dumpIdx;
+	int yAxis;
+	int yPrint;
+
+	printf("\n");
+	printf("                  Average Noise Power Indicator\n");
+	printf("                  -----------------------------\n");
+
+	yPrint = 0;
+	for (yAxis = -55; yAxis >= -95; yAxis -= 2) {
+		if (yPrint % 2 == 1) {
+			printf("%2d| ", yAxis);
+		} else {
+			printf("   | ");
+		}
+
+		yPrint++;
+
+		for (dumpIdx = 0; dumpIdx < numChans; dumpIdx++) {
+			if ((pChanRpt + dumpIdx)->anpi >= yAxis) {
+				printf("### ");
+			} else if ((pChanRpt + dumpIdx)->anpi >= yAxis - 2) {
+				printf("%3d ", (pChanRpt + dumpIdx)->anpi);
+			} else {
+				printf("    ");
+			}
+		}
+
+		printf("\n");
+	}
+
+	chanrpt_print_xAxis(pChanRpt, numChans);
+}
+
+static void
+chanrpt_print_chanLoad(ChanRptInfo_t * pChanRpt, int numChans)
+{
+	int dumpIdx;
+	int yAxis;
+	int yPrint;
+
+	printf("\n");
+	printf("                         Channel Load\n");
+	printf("                         ------------\n");
+
+	yPrint = 0;
+	for (yAxis = 100; yAxis >= 0; yAxis -= 5) {
+		if (yPrint % 2 == 1) {
+			printf("%2d%%| ", yAxis);
+		} else {
+			printf("   | ");
+		}
+
+		yPrint++;
+
+		for (dumpIdx = 0; dumpIdx < numChans; dumpIdx++) {
+			if ((pChanRpt + dumpIdx)->chanLoad >= yAxis) {
+				printf("### ");
+			} else if ((pChanRpt + dumpIdx)->chanLoad >= yAxis - 5) {
+				printf("%2d%% ",
+				       (pChanRpt + dumpIdx)->chanLoad);
+			} else {
+				printf("    ");
+			}
+		}
+
+		printf("\n");
+	}
+	chanrpt_print_xAxis(pChanRpt, numChans);
+}
+
+static void
+chanrpt_graph(void)
+{
+	int idx;
+	ChanRptInfo_t chanRpt[14];
+
+	for (idx = 0; (unsigned int)idx < NELEMENTS(chanRpt); idx++) {
+		chanRpt[idx].chanNum = idx + 1;
+		chanrpt_getValues(idx + 1,
+				  0,
+				  100,
+				  &chanRpt[idx].anpi, &chanRpt[idx].chanLoad,
+				  0);
+	}
+
+	chanrpt_print_anpi(chanRpt, NELEMENTS(chanRpt));
+	chanrpt_print_chanLoad(chanRpt, NELEMENTS(chanRpt));
+}
+
+static void
+chanrpt_graph_loop(boolean loopOnLoad, boolean loopOnAnpi, int loops)
+{
+	int idx;
+	int loopsLeft;
+	ChanRptInfo_t chanRpt[14];
+	ChanRptInfo_t chanRptAvg[14];
+
+	for (idx = 0; (unsigned int)idx < NELEMENTS(chanRpt); idx++) {
+		chanRpt[idx].chanNum = idx + 1;
+		chanrpt_getValues(idx + 1,
+				  0,
+				  100,
+				  &chanRpt[idx].anpi, &chanRpt[idx].chanLoad,
+				  0);
+	}
+
+	idx = 0;
+	loopsLeft = loops;
+
+	while (loopsLeft) {
+		chanRpt[idx].chanNum = idx + 1;
+		chanrpt_getValues(idx + 1,
+				  0,
+				  75,
+				  &chanRpt[idx].anpi, &chanRpt[idx].chanLoad,
+				  0);
+
+		chanRptAvg[idx].chanNum = idx + 1;
+		chanRptAvg[idx].anpi
+			= (chanRptAvg[idx].anpi * (loops - loopsLeft)
+			   + chanRpt[idx].anpi) / (loops - loopsLeft + 1);
+
+		chanRptAvg[idx].chanLoad
+			= (chanRptAvg[idx].chanLoad * (loops - loopsLeft)
+			   + chanRpt[idx].chanLoad) / (loops - loopsLeft + 1);
+
+		if (loopOnAnpi) {
+			chanrpt_print_anpi(chanRpt, NELEMENTS(chanRpt));
+		}
+
+		if (loopOnLoad) {
+			chanrpt_print_chanLoad(chanRpt, NELEMENTS(chanRpt));
+		}
+
+		idx = (idx + 1) % NELEMENTS(chanRpt);
+
+		if (idx == 0) {
+			loopsLeft--;
+		}
+	}
+
+	if (loopOnAnpi) {
+		chanrpt_print_anpi(chanRptAvg, NELEMENTS(chanRptAvg));
+	}
+
+	if (loopOnLoad) {
+		chanrpt_print_chanLoad(chanRptAvg, NELEMENTS(chanRptAvg));
+	}
+}
+
+/**
+ *  @brief Issue a changraph command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_chan_graph(int argc, char *argv[])
+{
+	if (argc == 3) {
+		chanrpt_graph();
+	} else if (argc == 5) {
+		if (strcmp(argv[3], "load") == 0) {
+			chanrpt_graph_loop(TRUE, FALSE, atoi(argv[4]));
+		} else if (strcmp(argv[3], "anpi") == 0) {
+			chanrpt_graph_loop(FALSE, TRUE, atoi(argv[4]));
+		} else if (strcmp(argv[3], "anpiload") == 0) {
+			chanrpt_graph_loop(TRUE, TRUE, atoi(argv[4]));
+		} else {
+			printf("\nchangraph syntax:"
+			       " changraph <load | anpi | anpiload> <loops>\n\n");
+		}
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief      enable 11k  1->enable  0->disable
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_11k_cfg(int argc, char *argv[])
+{
+	int ret = 0, status;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc != 3 && argc != 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX 11k_enable [0/1]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], argc - 3, &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: 11k_enable fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process Get result */
+	if (argc == 3) {
+		memcpy(&status, buffer, sizeof(status));
+		if (status == 0) {
+			printf("802.11K is Disabled\n");
+		} else if (status == 1) {
+			printf("802.11K is Enabled\n");
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ * @brief      get neighbor list
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ * @Todo:  just support get current ESS now.
+ 		 need add one argu to get specific ESS.
+ 		 mlanutl mlanX get_nlist SSID
+ */
+static int
+process_11k_neighbor_report(int argc, char *argv[])
+{
+	int ret = 0;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc != 3) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX get_nlist \n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], argc - 3, &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: neighbor_report failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process result */
+	printf("neighbor_report set successfully, please open mlanevent to view nlist result \n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Process extended channel switch(ECSA)
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_extend_channel_switch(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: extended channel switch fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(SDIO_SUSPEND_RESUME)
+/**
+ * @brief      enable auto_arp  1->enable  0->disable
+ *
+ * @param argc Number of arguments
+ * @param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static int
+process_auto_arp(int argc, char *argv[])
+{
+	int ret = 0, status;
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	/* Sanity tests */
+	if (argc != 3 && argc != 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("mlanutl mlanX auto_arp [0/1]\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	prepare_buffer(buffer, argv[2], argc - 3, &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: auto_arp fail\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Process Get result */
+	if (argc == 3) {
+		memcpy(&status, buffer, sizeof(status));
+		if (status == 0) {
+			printf("Auto ARP is Disabled\n");
+		} else if (status == 1) {
+			printf("Auto ARP is Enabled\n");
+		}
+	}
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Issue a tsf command
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array
+ *
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+process_tsf(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int x;
+	struct ifreq ifr;
+	t_u8 *buffer = NULL, *pos = NULL;
+	t_u32 cmd_len = 0, cmd_header_len;
+	struct eth_priv_cmd *cmd = NULL;
+	HostCmd_DS_GEN *hostcmd;
+
+	cmd_header_len = strlen(CMD_MARVELL) + strlen(HOSTCMD);
+
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot alloc memory\n");
+		ret = ENOMEM;
+		goto done;
+	}
+	memset(buffer, 0, BUFFER_LENGTH);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = ENOMEM;
+		goto done;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* buffer = MRVL_CMD<cmd> */
+	strncpy((char *)buffer, CMD_MARVELL, strlen(CMD_MARVELL));
+	strncpy((char *)buffer + strlen(CMD_MARVELL), HOSTCMD, strlen(HOSTCMD));
+
+	/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
+	hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
+
+	/* Point after host command header */
+	pos = (t_u8 *)hostcmd + S_DS_GEN;
+
+	cmd_len = S_DS_GEN + sizeof(t_u64);
+
+	hostcmd->command = cpu_to_le16(HostCmd_CMD_GET_TSF);
+	hostcmd->size = cpu_to_le16(cmd_len);
+	hostcmd->seq_num = 0;
+	hostcmd->result = 0;
+
+	/* Put buffer length */
+	memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+	/* Perform ioctl */
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("ioctl[hostcmd]");
+		printf("ERR:Command sending failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	printf("TSF=");
+
+	for (x = 7; x >= 0; x--) {
+		printf("%02x", pos[x]);
+	}
+
+	puts("\n");
+
+done:
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+	return ret;
+}
+
+/**
+ *  @brief Process dynamic bandwidth set/get
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_dyn_bw(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	int dyn_bw = 0;
+
+	/* Check arguments */
+	if (argc < 3 || argc > 4) {
+		printf("ERR:Incorrect number of arguments!\n");
+		printf("Syntax: ./mlanutl mlanX dyn_bw <bw>\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: dyn_bw fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	dyn_bw = *(int *)buffer;
+	printf("Dynamic bandwidth: %d\n", dyn_bw);
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Process set/get deauth control when uap move to another channel
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int
+process_ctrldeauth(int argc, char *argv[])
+{
+	t_u8 *buffer = NULL;
+	struct eth_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+
+	/* Initialize buffer */
+	buffer = (t_u8 *)malloc(BUFFER_LENGTH);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
+
+	cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
+	if (!cmd) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Fill up buffer */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	memset(cmd, 0, sizeof(struct eth_priv_cmd));
+	memcpy(&cmd->buf, &buffer, sizeof(buffer));
+#else
+	cmd->buf = buffer;
+#endif
+	cmd->used_len = 0;
+	cmd->total_len = BUFFER_LENGTH;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
+		perror("mlanutl");
+		fprintf(stderr, "mlanutl: deauthctrl fail\n");
+		if (cmd)
+			free(cmd);
+		if (buffer)
+			free(buffer);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Process result */
+	printf("Deauth control: ");
+	if (buffer[0])
+		printf("enabled.\n");
+	else
+		printf("disabled.\n");
+
+	if (buffer)
+		free(buffer);
+	if (cmd)
+		free(cmd);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Entry function for mlanutl
+ *  @param argc     Number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return         MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+main(int argc, char *argv[])
+{
+	int ret = MLAN_STATUS_SUCCESS;
+
+	if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) {
+		fprintf(stdout, "Marvell mlanutl version %s\n", MLANUTL_VER);
+		exit(0);
+	}
+	if (argc < 3) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		display_usage();
+		exit(1);
+	}
+
+	strncpy(dev_name, argv[1], IFNAMSIZ - 1);
+
+	/*
+	 * Create a socket
+	 */
+	sockfd = socket(AF_INET, SOCK_STREAM, 0);
+	if (sockfd < 0) {
+		fprintf(stderr, "mlanutl: Cannot open socket.\n");
+		exit(1);
+	}
+
+	ret = process_command(argc, argv);
+
+	if (ret == MLAN_STATUS_NOTFOUND) {
+		ret = process_generic(argc, argv);
+
+		if (ret) {
+			fprintf(stderr, "Invalid command specified!\n");
+			display_usage();
+			ret = 1;
+		}
+	}
+
+	close(sockfd);
+	return ret;
+}
diff --git a/wlan_sd8897/mapp/mlanutl/mlanutl.h b/wlan_sd8897/mapp/mlanutl/mlanutl.h
new file mode 100644
index 0000000..4c83fa1
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/mlanutl.h
@@ -0,0 +1,2546 @@
+/** @file  mlanutl.h
+  *
+  * @brief This file contains definitions for application
+  *
+  * Copyright (C) 2011-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     11/26/2008: initial version
+************************************************************************/
+#ifndef _MLANUTL_H_
+#define _MLANUTL_H_
+
+/** Include header files */
+#include    <stdio.h>
+#include    <unistd.h>
+#include    <string.h>
+#include    <stdlib.h>
+#include    <ctype.h>
+#include    <sys/socket.h>
+#include    <sys/ioctl.h>
+#include    <errno.h>
+#include    <linux/if.h>
+#include    <linux/wireless.h>
+#include    <sys/types.h>
+#include    <sys/time.h>
+#include    <arpa/inet.h>
+
+/** Type definition: boolean */
+typedef enum { FALSE, TRUE } boolean;
+
+/** 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)))
+
+/** Convert to correct endian format */
+#ifdef BIG_ENDIAN_SUPPORT
+/** CPU to little-endian convert for 16-bit */
+#define     cpu_to_le16(x)  swap_byte_16(x)
+/** CPU to little-endian convert for 32-bit */
+#define     cpu_to_le32(x)  swap_byte_32(x)
+/** Little-endian to CPU convert for 16-bit */
+#define     le16_to_cpu(x)  swap_byte_16(x)
+/** Little-endian to CPU convert for 32-bit */
+#define     le32_to_cpu(x)  swap_byte_32(x)
+#else
+/** Do nothing */
+#define     cpu_to_le16(x)  (x)
+/** Do nothing */
+#define     cpu_to_le32(x)  (x)
+/** Do nothing */
+#define     le16_to_cpu(x)  (x)
+/** Do nothing */
+#define     le32_to_cpu(x)  (x)
+#endif
+
+/** TLV header */
+#define TLVHEADER       /** Tag */      \
+						t_u16 tag;      \
+						/** Length */   \
+						t_u16 length
+
+/** Length of TLV header */
+#define TLVHEADER_LEN  4
+
+/** Character, 1 byte */
+typedef signed char t_s8;
+/** Unsigned character, 1 byte */
+typedef unsigned char t_u8;
+
+/** Short integer */
+typedef signed short t_s16;
+/** Unsigned short integer */
+typedef unsigned short t_u16;
+
+/** Integer */
+typedef signed int t_s32;
+/** Unsigned integer */
+typedef unsigned int t_u32;
+
+/** Long long integer */
+typedef signed long long t_s64;
+/** Unsigned long long integer */
+typedef unsigned long long t_u64;
+
+/** Void pointer (4-bytes) */
+typedef void t_void;
+
+/** The attribute pack used for structure packing */
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__  __attribute__((packed))
+#endif
+
+/** Success */
+#define MLAN_STATUS_SUCCESS         (0)
+/** Failure */
+#define MLAN_STATUS_FAILURE         (-1)
+/** Not found */
+#define MLAN_STATUS_NOTFOUND        (1)
+
+/** IOCTL number */
+#define MLAN_ETH_PRIV               (SIOCDEVPRIVATE + 14)
+
+/** Command buffer max length */
+#define BUFFER_LENGTH       (2 * 1024)
+
+/** Find number of elements */
+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
+
+/** BIT value */
+#define MBIT(x)    (((t_u32)1) << (x))
+
+#ifndef MIN
+/** Find minimum value */
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+/** Length of ethernet address */
+#ifndef ETH_ALEN
+#define ETH_ALEN            6
+#endif
+
+/** Action field value : get */
+#define ACTION_GET  0
+/** Action field value : set */
+#define ACTION_SET  1
+
+/** Socket */
+extern t_s32 sockfd;
+
+/** Device name */
+extern char dev_name[IFNAMSIZ + 1];
+
+#define HOSTCMD             "hostcmd"
+
+/** Marvell private command identifier */
+#define CMD_MARVELL         "MRVL_CMD"
+
+struct command_node {
+	char *name;
+	int (*handler) (int, char **);
+};
+
+/** Private command structure */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+struct eth_priv_cmd {
+    /** Command buffer pointer */
+	t_u64 buf;
+    /** buffer updated by driver */
+	int used_len;
+    /** buffer sent by application */
+	int total_len;
+} __ATTRIB_PACK__;
+#else
+struct eth_priv_cmd {
+    /** Command buffer */
+	t_u8 *buf;
+    /** Used length */
+	int used_len;
+    /** Total length */
+	int total_len;
+};
+#endif
+
+#if defined(STA_SUPPORT)
+struct eth_priv_pmfcfg {
+	/* Management Frame Protection Capability */
+	t_u8 mfpc;
+	/* Management Frame Protection Required */
+	t_u8 mfpr;
+};
+#endif
+
+struct eth_priv_htcapinfo {
+	t_u32 ht_cap_info_bg;
+	t_u32 ht_cap_info_a;
+};
+
+struct eth_priv_addba {
+	t_u32 time_out;
+	t_u32 tx_win_size;
+	t_u32 rx_win_size;
+	t_u32 tx_amsdu;
+	t_u32 rx_amsdu;
+};
+
+/** data_structure for cmd vhtcfg */
+struct eth_priv_vhtcfg {
+    /** Band (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;
+};
+
+/** data_structure for cmd opermodecfg */
+struct eth_priv_opermodecfg {
+    /** channel width: 1-20MHz, 2-40MHz, 3-80MHz, 4-160MHz or 80+80MHz */
+	t_u8 bw;
+    /** Rx NSS */
+	t_u8 nss;
+};
+
+/** data structure for cmd getdatarate */
+struct eth_priv_data_rate {
+    /** Tx data rate */
+	t_u32 tx_data_rate;
+    /** Rx data rate */
+	t_u32 rx_data_rate;
+
+    /** Tx channel bandwidth */
+	t_u32 tx_bw;
+    /** Tx guard interval */
+	t_u32 tx_gi;
+    /** Rx channel bandwidth */
+	t_u32 rx_bw;
+    /** Rx guard interval */
+	t_u32 rx_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;
+};
+
+/** data structure for cmd bandcfg */
+struct eth_priv_bandcfg {
+    /** Infra band */
+	t_u32 config_bands;
+    /** Ad-hoc start band */
+	t_u32 adhoc_start_band;
+    /** Ad-hoc start channel */
+	t_u32 adhoc_channel;
+	t_u32 adhoc_chan_bandwidth;
+    /** fw supported band */
+	t_u32 fw_bands;
+};
+
+/** data structure for cmd txratecfg */
+struct eth_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;
+    /** Rate rate */
+	t_u32 rate;
+    /** NSS */
+	t_u32 nss;
+};
+
+/** data structure for cmd getlog */
+struct eth_priv_get_log {
+    /** 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;
+    /** 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];
+    /** CMACICV 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;
+};
+
+struct eth_priv_esuppmode_cfg {
+	/* RSN mode */
+	t_u16 rsn_mode;
+	/* Pairwise cipher */
+	t_u8 pairwise_cipher;
+	/* Group cipher */
+	t_u8 group_cipher;
+};
+
+/** MLAN MAC Address Length */
+#define MLAN_MAC_ADDR_LENGTH            6
+#ifdef UAP_SUPPORT
+/** Max clients supported by AP */
+#define MAX_AP_CLIENTS   10
+
+/** associated station info */
+struct ap_client_info {
+    /** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+};
+
+/** Type definition of eth_priv_getstalist */
+struct eth_priv_getstalist {
+    /** station count */
+	t_u16 sta_count;
+    /** station list */
+	struct ap_client_info client_info[MAX_AP_CLIENTS];
+};
+#endif
+
+#define COUNTRY_CODE_LEN                3
+/** Type definition of eth_priv_countrycode for CMD_COUNTRYCODE */
+struct eth_priv_countrycode {
+    /** Country Code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+};
+
+/** Type definition of mlan_ds_hs_cfg for MLAN_OID_PM_CFG_HS_CFG */
+struct eth_priv_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*/
+	t_u8 param_type_ind;
+    /** Indication GPIO pin number */
+	t_u32 ind_gpio;
+    /** Level on ind_GPIO pin for normal wakeup source */
+	t_u32 level;
+    /** Parameter type*/
+	t_u8 param_type_ext;
+    /** Force ignore events*/
+	t_u32 event_force_ignore;
+    /** Events use ext gap to wake up host*/
+	t_u32 event_use_ext_gap;
+    /** Ext gap*/
+	t_u8 ext_gap;
+    /** GPIO wave level*/
+	t_u8 gpio_wave;
+};
+
+typedef struct _eth_priv_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=0xff: management frames(assoc res/rsp,probe req/rsp,...)
+     ** 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;
+} eth_priv_mgmt_frame_wakeup;
+
+/** Type definition of eth_priv_scan_time_params */
+struct eth_priv_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;
+};
+
+/** Type definition of eth_priv_scan_cfg */
+struct eth_priv_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 */
+	struct eth_priv_scan_time_params scan_time;
+    /** Extended Scan */
+	t_u32 ext_scan;
+};
+
+enum _mlan_rate_format {
+	MLAN_RATE_FORMAT_LG = 0,
+	MLAN_RATE_FORMAT_HT,
+	MLAN_RATE_FORMAT_VHT,
+	MLAN_RATE_FORMAT_AUTO = 0xFF,
+};
+
+/** 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;
+/** Type definition of mlan_power group info */
+struct eth_priv_power_group {
+    /** rate format (LG rate: 0; HT rate: 1; VHT rate: 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;
+};
+
+/** max of power groups */
+#define MAX_POWER_GROUP    64
+/** Type definition of mlan_power_cfg_ext */
+struct eth_priv_power_cfg_ext {
+    /** number of power_groups */
+	t_u32 num_pwr_grp;
+    /** array of power groups */
+	struct eth_priv_power_group power_group[MAX_POWER_GROUP];
+};
+
+/** Type definition of eth_priv_ds_ps_cfg */
+struct eth_priv_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;
+    /** Adhoc awake period */
+	t_u32 adhoc_awake_period;
+    /** 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;
+};
+
+#ifdef STA_SUPPORT
+
+/** Maximum length of SSID */
+#define MRVDRV_MAX_SSID_LENGTH          32
+
+/** Maximum length of SSID list */
+#define MRVDRV_MAX_SSID_LIST_LENGTH         10
+
+/** Maximum number of channels that can be sent in a setuserscan ioctl */
+#define WLAN_IOCTL_USER_SCAN_CHAN_MAX  50
+
+/** Maximum channel scratch */
+#define MAX_CHAN_SCRATCH  100
+
+/** Maximum channel number for b/g band */
+#define MAX_CHAN_BG_BAND  14
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES        4
+
+/** Scan all the channels in specified band */
+#define BAND_SPECIFIED    0x80
+
+/** Maximum size of IEEE Information Elements */
+#define IEEE_MAX_IE_SIZE  256
+
+/** Maximum number of TID */
+#define MAX_NUM_TID       8
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} __ATTRIB_PACK__ mlan_wmm_ac_e;
+
+/** Enumeration for scan mode */
+enum {
+	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_UNCHANGED = 0,
+	MLAN_SCAN_TYPE_ACTIVE,
+	MLAN_SCAN_TYPE_PASSIVE
+};
+
+/** IEEE Type definitions  */
+typedef 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,
+	SUPPORTED_CHANNELS = 36,
+	CHANNEL_SWITCH_ANN = 37,
+	QUIET = 40,
+	IBSS_DFS = 41,
+	HT_CAPABILITY = 45,
+	HT_OPERATION = 61,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	EXT_CAPABILITY = 127,
+
+	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_IE = VENDOR_SPECIFIC_221,
+	RSN_IE = 48,
+} __ATTRIB_PACK__ IEEEtypes_ElementId_e;
+
+/** Capability Bit Map*/
+#ifdef BIG_ENDIAN_SUPPORT
+typedef struct _IEEEtypes_CapInfo_t {
+	t_u8 rsrvd1:2;
+	t_u8 dsss_ofdm:1;
+	t_u8 rsvrd2:2;
+	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;
+} __ATTRIB_PACK__ IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#else
+typedef 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;
+} __ATTRIB_PACK__ IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** IEEE IE header */
+typedef struct _IEEEtypes_Header_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+} __ATTRIB_PACK__ IEEEtypes_Header_t, *pIEEEtypes_Header_t;
+
+/** IEEE IE header */
+#define IEEE_HEADER_LEN   sizeof(IEEEtypes_Header_t)
+
+/** Vendor specific IE header */
+typedef 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;
+} __ATTRIB_PACK__ IEEEtypes_VendorHeader_t, *pIEEEtypes_VendorHeader_t;
+
+/** Vendor specific IE */
+typedef 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)];
+} __ATTRIB_PACK__ IEEEtypes_VendorSpecific_t, *pIEEEtypes_VendorSpecific_t;
+
+/** IEEE IE */
+typedef 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)];
+} __ATTRIB_PACK__ IEEEtypes_Generic_t, *pIEEEtypes_Generic_t;
+
+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;
+    /** TSF value from the firmware at packet reception */
+	t_u64 network_tsf;
+} wlan_get_scan_table_fixed;
+
+/**
+ *  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[1]; */
+} wlan_ioctl_get_scan_table_entry;
+
+/**
+ *  Structure to store BSS info (probe resp or beacon) & IEEE IE info for each
+ *  BSS returned in WLAN_GET_SCAN_RESP IOCTL
+ */
+typedef struct _wlan_ioctl_get_bss_info {
+	/**
+	 *  Length of the BSS Information (probe resp or beacon) that
+	 *    follows after the fixed_field
+	 */
+	t_u32 bss_info_length;
+
+	/**
+	 *  Probe response or beacon scanned for the BSS.
+	 *
+	 *  Field layout:
+	 */
+	/** TSF              8 octets */
+	t_u8 tsf[8];
+	/** Beacon Interval  2 octets */
+	t_u16 beacon_interval;
+	/** Capability Info  2 octets */
+	IEEEtypes_CapInfo_t cap_info;
+
+	/**
+	 *  IEEE Infomation Elements; variable number & length per 802.11 spec
+	 */
+	/** SSID */
+	char ssid[MRVDRV_MAX_SSID_LENGTH + 1];
+	/** SSID Length */
+	t_u32 ssid_len;
+	/** WMM Capability */
+	char wmm_cap;
+	/** WPS Capability */
+	char wps_cap;
+	/** Privacy Capability - WEP/WPA/RSN */
+	char priv_cap;
+	/** HT (11N) Capability */
+	char ht_cap;
+	/** VHT (11AC) Capability */
+	char vht_cap[2];
+	/* 802.11k Capability */
+	char dot11k_cap;
+	/** 802.11r Capability */
+	char dot11r_cap;
+} wlan_ioctl_get_bss_info;
+
+/**
+ *  Structure to save of scan table info for each BSS returned
+ * in WLAN_GET_SCAN_RESP IOCTL
+ */
+struct wlan_ioctl_get_scan_list {
+	/** fixed info */
+	wlan_ioctl_get_scan_table_entry fixed_buf;
+	/** variable info - BSS info (probe resp or beacon) & IEEE IE info */
+	wlan_ioctl_get_bss_info bss_info_buf;
+	/** pointer to next node in list */
+	struct wlan_ioctl_get_scan_list *next;
+	/** pointer to previous node in list */
+	struct wlan_ioctl_get_scan_list *prev;
+};
+
+/**
+ *  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;
+
+typedef struct {
+	t_u8 chan_number;
+		       /**< Channel Number to scan */
+	t_u8 radio_type;
+		       /**< Radio type: 'B/G' Band = 0, 'A' Band = 1 */
+	t_u8 scan_type;/**< Scan type: Active = 1, Passive = 2 */
+	t_u8 reserved;/**< Reserved */
+	t_u32 scan_time;
+		       /**< Scan duration in milliseconds; if 0 default used */
+} __ATTRIB_PACK__ wlan_ioctl_user_scan_chan;
+
+typedef struct {
+	char ssid[MRVDRV_MAX_SSID_LENGTH + 1];
+					    /**< SSID */
+	t_u8 max_len;			       /**< Maximum length of SSID */
+} __ATTRIB_PACK__ wlan_ioctl_user_scan_ssid;
+
+typedef struct {
+
+    /** Flag set to keep the previous scan table intact */
+	t_u8 keep_previous_scan;	/* Do not erase the existing scan results */
+
+    /** BSS mode to be sent in the firmware command */
+	t_u8 bss_mode;
+
+    /** Configure the number of probe requests for active chan scans */
+	t_u8 num_probes;
+
+    /** Reserved */
+	t_u8 reserved;
+
+    /** BSSID filter sent in the firmware command to limit the results */
+	t_u8 specific_bssid[ETH_ALEN];
+
+    /** SSID filter list used in the to limit the scan results */
+	wlan_ioctl_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH];
+
+    /** Variable number (fixed maximum) of channels to scan up */
+	wlan_ioctl_user_scan_chan chan_list[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
+
+    /** Gap between two scans */
+	t_u16 scan_chan_gap;
+	/** scan type: 0 legacy, 1: enhance scan*/
+	t_u8 ext_scan_type;
+
+} __ATTRIB_PACK__ wlan_ioctl_user_scan_cfg;
+
+/** Max Ie length */
+#define MAX_IE_SIZE             256
+
+/** custom IE */
+typedef 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[0];
+} __ATTRIB_PACK__ custom_ie;
+
+/** Convert character to integer */
+#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0'))
+
+/**
+ * Hex or Decimal to Integer
+ * @param   num string to convert into decimal or hex
+ */
+#define A2HEXDECIMAL(num)  \
+	(strncasecmp("0x", (num), 2) ? (unsigned int) strtoll((num), NULL, 0) : a2hex((num)))
+
+/** Convert TLV header from little endian format to CPU format */
+#define endian_convert_tlv_header_in(x)                 \
+	{                                               \
+		(x)->tag = le16_to_cpu((x)->tag);       \
+		(x)->length = le16_to_cpu((x)->length); \
+	}
+
+/** Convert TLV header to little endian format from CPU format */
+#define endian_convert_tlv_header_out(x)                \
+	{                                               \
+		(x)->tag = cpu_to_le16((x)->tag);       \
+		(x)->length = cpu_to_le16((x)->length); \
+	}
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW         4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX               16
+
+/** Private command ID to pass custom IE list */
+#define CUSTOM_IE_CFG          (SIOCDEVPRIVATE + 13)
+/* TLV Definitions */
+
+/** Maximum IE buffer length */
+#define MAX_IE_BUFFER_LEN 256
+
+/** TLV: Management IE list */
+#define MRVL_MGMT_IE_LIST_TLV_ID          (PROPRIETARY_TLV_BASE_ID + 0x69)	/* 0x0169 */
+
+/** TLV: Max Management IE */
+#define MRVL_MAX_MGMT_IE_TLV_ID           (PROPRIETARY_TLV_BASE_ID + 0xaa)	/* 0x01aa */
+
+/** custom IE info */
+typedef struct _custom_ie_info {
+    /** size of buffer */
+	t_u16 buf_size;
+    /** no of buffers of buf_size */
+	t_u16 buf_count;
+} __ATTRIB_PACK__ custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef 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[0];
+} __ATTRIB_PACK__ tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef struct _eth_priv_ds_misc_custom_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** IE data */
+	custom_ie ie_data[0];
+} __ATTRIB_PACK__ eth_priv_ds_misc_custom_ie;
+
+/*-----------------------------------------------------------------*/
+/** Register Memory Access Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for register type */
+enum _mlan_reg_type {
+	MLAN_REG_MAC = 1,
+	MLAN_REG_BBP,
+	MLAN_REG_RF,
+	MLAN_REG_CAU = 5,
+};
+
+/** Type definition of mlan_ds_reg_rw for MLAN_OID_REG_RW */
+struct eth_priv_ds_reg_rw {
+    /** Register type */
+	t_u32 type;
+    /** Offset */
+	t_u32 offset;
+    /** Value */
+	t_u32 value;
+};
+
+/** Maximum EEPROM data */
+#define MAX_EEPROM_DATA 256
+
+/** Type definition of mlan_ds_read_eeprom for MLAN_OID_EEPROM_RD */
+struct eth_priv_ds_read_eeprom {
+    /** Multiples of 4 */
+	t_u16 offset;
+    /** Number of bytes */
+	t_u16 byte_count;
+    /** Value */
+	t_u8 value[MAX_EEPROM_DATA];
+};
+
+/** Type definition of mlan_ds_mem_rw for MLAN_OID_MEM_RW */
+struct eth_priv_ds_mem_rw {
+    /** Address */
+	t_u32 addr;
+    /** Value */
+	t_u32 value;
+};
+
+/** Type definition of mlan_ds_reg_mem for MLAN_IOCTL_REG_MEM */
+struct eth_priv_ds_reg_mem {
+    /** Sub-command */
+	t_u32 sub_command;
+    /** Register memory access parameter */
+	union {
+	/** Register access for MLAN_OID_REG_RW */
+		struct eth_priv_ds_reg_rw reg_rw;
+	/** EEPROM access for MLAN_OID_EEPROM_RD */
+		struct eth_priv_ds_read_eeprom rd_eeprom;
+	/** Memory access for MLAN_OID_MEM_RW */
+		struct eth_priv_ds_mem_rw mem_rw;
+	} param;
+};
+
+/** Data structure of WMM QoS information */
+typedef 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 */
+} __ATTRIB_PACK__ IEEEtypes_WmmQosInfo_t;
+
+/** band BG */
+#define BAND_BG_TDLS   0
+/** band A */
+#define BAND_A_TDLS    1
+/** NO PERIODIC SWITCH */
+#define NO_PERIODIC_SWITCH      0
+/** Enable periodic channel switch */
+#define ENABLE_PERIODIC_SWITCH  1
+/** Min channel value for BG band */
+#define MIN_BG_CHANNEL 1
+/** Max channel value for BG band */
+#define MAX_BG_CHANNEL 14
+/** Max channel value for A band */
+#define MIN_A_CHANNEL 36
+/** Max channel value for A band */
+#define MAX_A_CHANNEL 252
+
+/** Host Command ioctl number */
+#define TDLS_IOCTL               (SIOCDEVPRIVATE + 5)
+/** TDLS action definitions */
+/** Action ID for TDLS config */
+#define ACTION_TDLS_CONFIG       0x0000
+/** Action ID for TDLS setinfo request */
+#define ACTION_TDLS_SETINFO      0x0001
+/** Action ID for TDLS Discovery request */
+#define ACTION_TDLS_DISCOVERY    0x0002
+/** Action ID for TDLS setup request */
+#define ACTION_TDLS_SETUP        0x0003
+/** Action ID for TDLS Teardown request */
+#define ACTION_TDLS_TEARDOWN     0x0004
+/** Action ID for TDLS power mode */
+#define ACTION_TDLS_POWER_MODE   0x0005
+/**Action ID for init TDLS Channel Switch*/
+#define ACTION_TDLS_INIT_CHAN_SWITCH     0x06
+/** Action ID for stop TDLS Channel Switch */
+#define ACTION_TDLS_STOP_CHAN_SWITCH     0x07
+/** Action ID for configure CS related parameters */
+#define ACTION_TDLS_CS_PARAMS            0x08
+/** Action ID for TDLS Disable Channel switch */
+#define ACTION_TDLS_CS_DISABLE          0x09
+/** Action ID for TDLS Link status */
+#define ACTION_TDLS_LINK_STATUS  0x000A
+/** Action ID for Host TDLS config uapsd and CS */
+#define ACTION_HOST_TDLS_CONFIG       0x000D
+/** Action ID for TDLS CS immediate return */
+#define ACTION_TDLS_DEBUG_CS_RET_IM 0xFFF7
+/** Action ID for TDLS Stop RX */
+#define ACTION_TDLS_DEBUG_STOP_RX 0xFFF8
+/** Action ID for TDLS Allow weak security */
+#define ACTION_TDLS_DEBUG_ALLOW_WEAK_SECURITY 0xFFF9
+/** Action ID for TDLS Ignore key lifetime expiry */
+#define ACTION_TDLS_DEBUG_IGNORE_KEY_EXPIRY 0xFFFA
+/** Action ID for TDLS Higher/Lower mac Test */
+#define ACTION_TDLS_DEBUG_HIGHER_LOWER_MAC 0xFFFB
+/** Action ID for TDLS Prohibited Test */
+#define ACTION_TDLS_DEBUG_SETUP_PROHIBITED 0xFFFC
+/** Action ID for TDLS Existing link Test */
+#define ACTION_TDLS_DEBUG_SETUP_SAME_LINK 0xFFFD
+/** Action ID for TDLS Fail Setup Confirm */
+#define ACTION_TDLS_DEBUG_FAIL_SETUP_CONFIRM 0xFFFE
+/** Action ID for TDLS WRONG BSS Test */
+#define ACTION_TDLS_DEBUG_WRONG_BSS 0xFFFF
+
+/** TLV type : Rates */
+#define TLV_TYPE_RATES                          0x0001
+/** TLV type : Domain */
+#define TLV_TYPE_DOMAIN                         0x0007
+/** TLV type : Supported channels */
+#define TLV_TYPE_SUPPORTED_CHANNELS             0x0024
+/** TLV type : HT Capabilities */
+#define TLV_TYPE_HT_CAP                         0x002d
+/** TLV type : Qos Info */
+#define TLV_TYPE_QOSINFO                        0x002e
+/** TLV type : RSN IE */
+#define TLV_TYPE_RSN_IE                         0x0030
+/** TLV type : extended supported rates */
+#define TLV_EXTENDED_SUPPORTED_RATES            0x0032
+/** TLV type :  timeout interval    */
+#define TLV_TIMEOUT_INTERVAL                    0x0038
+/** TLV type : Regulatory classes */
+#define TLV_TYPE_REGULATORY_CLASSES             0x003b
+/** TLV type : HT Information */
+#define TLV_TYPE_HT_INFO                        0x003d
+/** TLV type : 20/40 BSS Coexistence */
+#define TLV_TYPE_2040BSS_COEXISTENCE            0x0048
+/** TLv Type : Link identifier */
+#define TLV_LINK_IDENTIFIER                     0x0065
+
+/** Country code length */
+#define COUNTRY_CODE_LEN                        3
+/** Length of Group Cipher Suite */
+#define GROUP_CIPHER_SUITE_LEN     4
+/** Length of Pairwise Cipher Suite */
+#define PAIRWISE_CIPHER_SUITE_LEN  4
+/** Length of AKM Suite */
+#define AKM_SUITE_LEN          4
+/** PMKID length */
+#define PMKID_LEN              16
+/** Maximum number of pairwise_cipher_suite */
+#define MAX_PAIRWISE_CIPHER_SUITE_COUNT    2
+/** Maximum number of AKM suite */
+#define MAX_AKM_SUITE_COUNT    2
+/** Maximum number of PMKID list count */
+#define MAX_PMKID_COUNT    2
+/** Length of MCS set */
+#define MCS_SET_LEN    16
+/** Version in RSN IE */
+#define VERSION_RSN_IE    0x0001
+
+/** tdls setinfo */
+typedef struct _tdls_setinfo {
+    /** Action */
+	t_u16 action;
+    /** (TLV + capInfo) length */
+	t_u16 tlv_len;
+    /** Capability Info */
+	t_u16 cap_info;
+    /** tdls info */
+	t_u8 tlv_buffer[0];
+} __ATTRIB_PACK__ tdls_setinfo;
+
+/** tdls discovery */
+typedef struct _tdls_discovery {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+} __ATTRIB_PACK__ tdls_discovery;
+
+/** tdls link status */
+typedef struct _tdls_links_status {
+    /** Action */
+	t_u16 action;
+} __ATTRIB_PACK__ tdls_link_status;
+
+/** tdls discovery response */
+typedef struct _tdls_discovery_resp {
+    /** Action */
+	t_u16 action;
+    /** payload length */
+	t_u16 payload_len;
+    /** peer mac Address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** RSSI */
+	t_s8 rssi;
+    /** Cap Info */
+	t_u16 cap_info;
+    /** TLV buffer */
+	t_u8 tlv_buffer[0];
+} __ATTRIB_PACK__ tdls_discovery_resp;
+
+/** tdls each link rate information */
+typedef struct _tdls_link_rate_info {
+    /** Tx Data Rate */
+	t_u8 tx_data_rate;
+    /** Tx Rate HT info*/
+	t_u8 tx_rate_htinfo;
+} __ATTRIB_PACK__ tdls_link_rate_info;
+
+/** tdls each link status */
+typedef struct _tdls_each_link_status {
+    /** peer mac Address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** 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;
+	/** final rate value*/
+		t_u16 final_data_rate;
+	} u;
+    /** Security Method */
+	t_u8 security_method;
+    /** Key Lifetime */
+	t_u32 key_lifetime;
+    /** Key Length */
+	t_u8 key_length;
+    /** actual key */
+	t_u8 key[0];
+} __ATTRIB_PACK__ tdls_each_link_status;
+
+/** tdls link status response */
+typedef struct _tdls_link_status_resp {
+    /** Action */
+	t_u16 action;
+    /** payload length */
+	t_u16 payload_len;
+    /** number of links */
+	t_u8 active_links;
+    /** structure for link status */
+	tdls_each_link_status link_stats[1];
+} __ATTRIB_PACK__ tdls_link_status_resp;
+
+/** tdls setup */
+typedef struct _tdls_setup {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** Time to wait for response from peer*/
+	t_u32 wait_time;
+    /** Key Life Time */
+	t_u32 key_life_time;
+} __ATTRIB_PACK__ tdls_setup;
+
+/** tdls tear down */
+typedef struct _tdls_tear_down {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** Reason code */
+	t_u16 reason_code;
+} __ATTRIB_PACK__ tdls_teardown;
+
+/** tdls power mode */
+typedef struct _tdls_power_mode {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** Power mode */
+	t_u16 power_mode;
+} __ATTRIB_PACK__ tdls_powermode;
+
+/** tdls channel switch info */
+typedef struct _tdls_channel_switch {
+    /** Action */
+	t_u16 action;
+    /** peer mac Address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** 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*/
+	t_u16 switch_time;
+    /** Channel Switch timeout*/
+	t_u16 switch_timeout;
+    /** Channel Regulatory class*/
+	t_u8 regulatory_class;
+    /** Channel Switch periodicity*/
+	t_u8 periodicity;
+} __ATTRIB_PACK__ tdls_channel_switch;
+
+/** tdls stop channel switch */
+typedef struct _tdls_stop_chan_switch {
+    /** Action */
+	t_u16 action;
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+} __ATTRIB_PACK__ tdls_stop_chan_switch;
+
+/** tdls disable channel switch */
+typedef struct _tdls_disable_cs {
+    /** Action */
+	t_u16 action;
+    /** Data*/
+	t_u16 data;
+} __ATTRIB_PACK__ tdls_disable_cs, tdls_config;
+
+/** tdls channel switch parameters */
+typedef struct _tdls_cs_params {
+    /** Action */
+	t_u16 action;
+    /** 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;
+} __ATTRIB_PACK__ tdls_cs_params;
+
+/** Host tdls config */
+typedef struct _host_tdls_cfg {
+    /** Action */
+	t_u16 action;
+    /** support uapsd */
+	t_u8 uapsd_support;
+    /** channel_switch */
+	t_u8 cs_support;
+    /** TLV  length */
+	t_u16 tlv_len;
+    /** tdls info */
+	t_u8 tlv_buffer[0];
+} __ATTRIB_PACK__ host_tdls_cfg;
+
+/** tdls debug */
+typedef struct _tdls_debug {
+    /** Action */
+	t_u16 action;
+    /** Data */
+	t_u8 data[0];
+} __ATTRIB_PACK__ tdls_debug;
+
+/** TLV header */
+#define TLVHEADER       /** Tag */      \
+						t_u16 tag;      \
+						/** Length */   \
+						t_u16 length
+
+/** Length of TLV header */
+#define TLVHEADER_LEN  4
+
+/** Data structure for subband set */
+typedef struct _IEEEtypes_SubbandSet_t {
+    /** First channel */
+	t_u8 first_chan;
+    /** Number of channels */
+	t_u8 no_of_chan;
+    /** Maximum Tx power */
+	t_u8 max_tx_pwr;
+} __ATTRIB_PACK__ IEEEtypes_SubbandSet_t, *pIEEEtypes_SubbandSet_t;
+
+/** tlvbuf_DomainParamSet_t */
+typedef struct _tlvbuf_DomainParamSet {
+    /** Header */
+	TLVHEADER;
+    /** Country code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+    /** Set of subbands */
+	IEEEtypes_SubbandSet_t sub_band[0];
+} __ATTRIB_PACK__ tlvbuf_DomainParamSet_t;
+
+/** Qos Info TLV */
+typedef struct _tlvbuf_QosInfo_t {
+    /** Header */
+	TLVHEADER;
+    /** QosInfo */
+	union {
+	/** QosInfo bitfield */
+		IEEEtypes_WmmQosInfo_t qos_info;
+	/** QosInfo byte */
+		t_u8 qos_info_byte;
+	} u;
+} __ATTRIB_PACK__ tlvbuf_QosInfo_t;
+
+/** HT Capabilities Data */
+typedef struct _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;
+} __ATTRIB_PACK__ HTCap_t, *pHTCap_t;
+
+/** HT Information Data */
+typedef struct _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];
+} __ATTRIB_PACK__ HTInfo_t, *pHTInfo_t;
+
+/** 20/40 BSS Coexistence Data */
+typedef struct _BSSCo2040_t {
+    /** 20/40 BSS Coexistence value */
+	t_u8 bss_co_2040_value;
+} __ATTRIB_PACK__ BSSCo2040_t, *pBSSCo2040_t;
+
+/** HT Capabilities element */
+typedef struct _tlvbuf_HTCap_t {
+    /** Header */
+	TLVHEADER;
+    /** HTCap struct */
+	HTCap_t ht_cap;
+} __ATTRIB_PACK__ tlvbuf_HTCap_t;
+
+/** HT Information element */
+typedef struct _tlvbuf_HTInfo_t {
+    /** Header */
+	TLVHEADER;
+
+    /** HTInfo struct */
+	HTInfo_t ht_info;
+} __ATTRIB_PACK__ tlvbuf_HTInfo_t;
+
+/** 20/40 BSS Coexistence element */
+typedef struct _tlvbuf_2040BSSCo_t {
+    /** Header */
+	TLVHEADER;
+
+    /** BSSCo2040_t struct */
+	BSSCo2040_t bss_co_2040;
+} __ATTRIB_PACK__ tlvbuf_2040BSSCo_t;
+
+/** Extended Capabilities element */
+typedef struct _tlvbuf_ExtCap_t {
+    /** Header */
+	TLVHEADER;
+    /** ExtCap_t struct */
+	t_u8 ext_cap[0];
+} __ATTRIB_PACK__ tlvbuf_ExtCap_t;
+
+/** tlvbuf_RatesParamSet_t */
+typedef struct _tlvbuf_RatesParamSet_t {
+    /** Header */
+	TLVHEADER;
+    /** Rates */
+	t_u8 rates[0];
+} __ATTRIB_PACK__ tlvbuf_RatesParamSet_t;
+
+/*  IEEE Supported Channel sub-band description (7.3.2.19) */
+/*  Sub-band description used in the supported channels element. */
+typedef struct _IEEEtypes_SupportChan_Subband_t {
+	t_u8 start_chan;/**< Starting channel in the subband */
+	t_u8 num_chans;	/**< Number of channels in the subband */
+
+} __ATTRIB_PACK__ 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 struct _tlvbuf_SupportedChannels_t {
+    /** Header */
+	TLVHEADER;
+		 /**< IEEE Element ID = 36 */
+    /** Configured sub-bands information in the element */
+	IEEEtypes_SupportChan_Subband_t subband[0];
+} __ATTRIB_PACK__ tlvbuf_SupportedChannels_t;
+
+#define VHT_MCS_MAP_LEN                        2
+/** VHT MCS rate set field, refer to 802.11ac */
+typedef 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 */
+} __ATTRIB_PACK__ VHT_MCS_set_t, *pVHT_MCS_set_t;
+
+typedef struct _VHT_capa {
+	t_u32 vht_cap_info;
+	VHT_MCS_set_t mcs_sets;
+} __ATTRIB_PACK__ VHT_capa_t, *pVHT_capa_t;
+
+/** VHT Capabilities IE */
+typedef struct _IEEEtypes_VHTCap_t {
+    /** Header */
+	TLVHEADER;
+    /** VHTInfo struct */
+	VHT_capa_t vht_cap;
+} __ATTRIB_PACK__ tlvbuf_VHTCap_t, *ptlvbuf_VHTCap_t;
+
+/** VHT Operations IE */
+typedef struct _IEEEtypes_VHTOprat_t {
+    /** Header */
+	TLVHEADER;
+    /** VHTOpra struct */
+	t_u8 chan_width;
+	t_u8 chan_cf1;
+	t_u8 chan_cf2;
+    /** Basic MCS set map, each 2 bits stands for a Nss */
+	t_u8 basic_mcs_map[VHT_MCS_MAP_LEN];
+} __ATTRIB_PACK__ tlvbuf_VHTOpra_t, *ptlvbuf_VHTOpra_t;
+
+/*  IEEE Supported Regulatory Classes description (7.3.2.54) */
+typedef struct _IEEEtypes_RegulatoryClass_t {
+    /** current regulatory class */
+	t_u8 cur_regulatory_class;
+    /** supported regulatory class list */
+	t_u8 regulatory_classes_list[0];
+
+} __ATTRIB_PACK__ IEEEtypes_RegulatoryClass_t;
+
+/*  IEEE Supported Regulatory Classes TLV (7.3.2.54) */
+typedef struct _tlvbuf_RegulatoryClass_t {
+    /** Header */
+	TLVHEADER;
+		 /**< IEEE Element ID = 59 */
+    /** supported regulatory class */
+	IEEEtypes_RegulatoryClass_t regulatory_class;
+} __ATTRIB_PACK__ tlvbuf_RegulatoryClass_t;
+
+/** tlvbuf_RsnParamSet_t */
+typedef struct _tlvbuf_RsnParamSet_t {
+    /** Header */
+	TLVHEADER;
+    /** Version */
+	t_u16 version;
+    /** Group Cipher Suite */
+	t_u8 group_cipher_suite[4];
+    /** Pairwise Cipher Suite count */
+	t_u16 pairwise_cipher_count;
+    /** Pairwise Cipher Suite */
+	t_u8 pairwise_cipher_suite[0];
+    /** AKM Suite Sount */
+	t_u16 akm_suite_count;
+    /** AKM Suite */
+	t_u8 akm_suite[0];
+    /** RSN Capability */
+	t_u16 rsn_capability;
+    /** PMKID Count */
+	t_u16 pmkid_count;
+    /** PMKID list */
+	t_u8 pmkid_list[0];
+} __ATTRIB_PACK__ tlvbuf_RsnParamSet_t;
+
+/** Size of a TSPEC.  Used to allocate necessary buffer space in commands */
+#define WMM_TSPEC_SIZE              63
+
+/** Maximum number of AC QOS queues available in the driver/firmware */
+#define MAX_AC_QUEUES               4
+
+/** Maximum number of User Priorities */
+#define MAX_USER_PRIORITIES         8
+
+/** Extra IE bytes allocated in messages for appended IEs after a TSPEC */
+#define WMM_ADDTS_EXTRA_IE_BYTES    256
+
+/**
+ *  @brief Enumeration for the command result from an ADDTS or DELTS command
+ */
+typedef enum {
+	TSPEC_RESULT_SUCCESS = 0,
+	TSPEC_RESULT_EXEC_FAILURE = 1,
+	TSPEC_RESULT_TIMEOUT = 2,
+	TSPEC_RESULT_DATA_INVALID = 3,
+} __ATTRIB_PACK__ mlan_wmm_tspec_result_e;
+
+/**
+ *  @brief Enumeration for the action field in the Queue configure command
+ */
+typedef enum {
+	WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+
+	WMM_QUEUE_CONFIG_ACTION_MAX
+} __ATTRIB_PACK__ mlan_wmm_queue_config_action_e;
+
+/**
+ *   @brief Enumeration for the action field in the queue stats command
+ */
+typedef enum {
+	WMM_STATS_ACTION_START = 0,
+	WMM_STATS_ACTION_STOP = 1,
+	WMM_STATS_ACTION_GET_CLR = 2,
+	WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+
+	WMM_STATS_ACTION_MAX
+} __ATTRIB_PACK__ mlan_wmm_stats_action_e;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef 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
+} __ATTRIB_PACK__ IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef 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
+} __ATTRIB_PACK__ IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn;  /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;		    /**< Ecw */
+	t_u16 tx_op_limit;		    /**< Tx op limit */
+} __ATTRIB_PACK__ IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef 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;
+
+} __ATTRIB_PACK__ IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef 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];
+
+} __ATTRIB_PACK__ IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/**
+ *  @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 wlan_wmm_addts_req_ioctl
+ */
+typedef struct {
+	mlan_wmm_tspec_result_e commandResult;
+					   /**< Firmware execution result */
+
+	t_u32 timeout_ms;		/**< Timeout value in milliseconds */
+	t_u8 ieeeStatusCode;		/**< IEEE status code */
+
+	t_u32 ieDataLen;
+	t_u8 ieData[WMM_TSPEC_SIZE
+				 /**< TSPEC to send in the ADDTS */
+		    + WMM_ADDTS_EXTRA_IE_BYTES];
+					     /**< ADDTS 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 wlan_wmm_delts_req_ioctl
+ */
+typedef struct {
+	mlan_wmm_tspec_result_e commandResult;
+					    /**< Firmware execution result */
+	t_u8 ieeeReasonCode;	  /**< IEEE reason code sent, unused for WMM */
+
+	t_u32 ieDataLen;
+	t_u8 ieData[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.
+ *
+ *  - msduLifetimeExpiry is ignored if set to 0 on a set command
+ *
+ *  @sa wlan_wmm_queue_config_ioctl
+ */
+typedef struct {
+	mlan_wmm_queue_config_action_e action;
+					   /**< Set, Get, or Default */
+	mlan_wmm_ac_e accessCategory;	   /**< WMM_AC_BK(0) to WMM_AC_VO(3) */
+	t_u16 msduLifetimeExpiry;	   /**< lifetime expiry in TUs */
+	t_u8 supportedRates[10];	   /**< Not supported yet */
+} wlan_ioctl_wmm_queue_config_t;
+
+/** Number of bins in the histogram for the HostCmd_DS_WMM_QUEUE_STATS */
+#define WMM_STATS_PKTS_HIST_BINS  7
+
+/**
+ *  @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 wlan_wmm_queue_stats_ioctl
+ */
+typedef struct {
+	mlan_wmm_stats_action_e action;
+				     /**< Start, Stop, or Get  */
+	t_u8 userPriority;
+			 /**< User Priority (0 to 7) */
+	t_u16 pktCount;	 /**< Number of successful packets transmitted */
+	t_u16 pktLoss;	 /**< Packets lost; not included in pktCount   */
+	t_u32 avgQueueDelay;
+			 /**< Average Queue delay in microseconds */
+	t_u32 avgTxDelay;/**< Average Transmission delay in microseconds */
+	t_u16 usedTime;	 /**< Calculated used time - units of 32 microsec */
+	t_u16 policedTime;
+			 /**< Calculated 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 delayHistogram[WMM_STATS_PKTS_HIST_BINS];
+} wlan_ioctl_wmm_queue_stats_t;
+
+/**
+ *  @brief IOCTL and command sub structure for a Traffic stream status.
+ */
+typedef struct {
+	t_u8 tid;	    /**< TSID: Range: 0->7 */
+	t_u8 valid;	    /**< TSID specified is valid  */
+	t_u8 accessCategory;/**< AC TSID is active on */
+	t_u8 userPriority;  /**< UP specified for the TSID */
+
+	t_u8 psb;	    /**< Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 flowDir;	    /**< Upstream (0), Downlink(1), Bidirectional(3) */
+	t_u16 mediumTime;   /**< Medium time granted for the TSID */
+} __ATTRIB_PACK__ HostCmd_DS_WMM_TS_STATUS,
+	wlan_ioctl_wmm_ts_status_t, wlan_cmd_wmm_ts_status_t;
+
+/**
+ *  @brief IOCTL sub structure for a specific WMM AC Status
+ */
+typedef struct {
+    /** WMM Acm */
+	t_u8 wmmAcm;
+    /** Flow required flag */
+	t_u8 flowRequired;
+    /** Flow created flag */
+	t_u8 flowCreated;
+    /** Disabled flag */
+	t_u8 disabled;
+    /** delivery enabled */
+	t_u8 deliveryEnabled;
+    /** trigger enabled */
+	t_u8 triggerEnabled;
+} 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 wlan_wmm_queue_status_ioctl
+ */
+typedef struct {
+    /** WMM AC queue status */
+	wlan_ioctl_wmm_queue_status_ac_t acStatus[MAX_AC_QUEUES];
+} wlan_ioctl_wmm_queue_status_t;
+#endif /* STA_SUPPORT */
+
+/** 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 : Clear */
+#define HostCmd_ACT_GEN_CLEAR           0x0004
+/** General purpose action : Remove */
+#define HostCmd_ACT_GEN_REMOVE          0x0004
+
+/** TLV  type ID definition */
+#define PROPRIETARY_TLV_BASE_ID     0x0100
+
+/** MrvlIEtypesHeader_t */
+typedef struct MrvlIEtypesHeader {
+    /** Header type */
+	t_u16 type;
+    /** Header length */
+	t_u16 len;
+} __ATTRIB_PACK__ MrvlIEtypesHeader_t;
+
+/** MrvlIEtypes_Data_t */
+typedef struct MrvlIEtypes_Data_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Data */
+	t_u8 data[1];
+} __ATTRIB_PACK__ MrvlIEtypes_Data_t;
+
+/** HostCmd_DS_802_11_SUBSCRIBE_EVENT */
+typedef struct MAPP_HostCmd_DS_802_11_SUBSCRIBE_EVENT {
+    /** Action */
+	t_u16 action;
+    /** Events */
+	t_u16 events;
+} __ATTRIB_PACK__ HostCmd_DS_802_11_SUBSCRIBE_EVENT;
+
+/** MrvlIEtypes_RssiParamSet_t */
+typedef struct MrvlIEtypes_RssiThreshold {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** RSSI value */
+	t_u8 RSSI_value;
+    /** RSSI frequency */
+	t_u8 RSSI_freq;
+} __ATTRIB_PACK__ MrvlIEtypes_RssiThreshold_t;
+
+/** MrvlIEtypes_SnrThreshold_t */
+typedef struct MrvlIEtypes_SnrThreshold {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** SNR value */
+	t_u8 SNR_value;
+    /** SNR frequency */
+	t_u8 SNR_freq;
+} __ATTRIB_PACK__ MrvlIEtypes_SnrThreshold_t;
+
+/** MrvlIEtypes_FailureCount_t */
+typedef struct MrvlIEtypes_FailureCount {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Failure value */
+	t_u8 fail_value;
+    /** Failure frequency */
+	t_u8 fail_freq;
+} __ATTRIB_PACK__ MrvlIEtypes_FailureCount_t;
+
+/** MrvlIEtypes_BeaconsMissed_t */
+typedef struct MrvlIEtypes_BeaconsMissed {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Number of beacons missed */
+	t_u8 beacon_missed;
+    /** Reserved */
+	t_u8 reserved;
+} __ATTRIB_PACK__ MrvlIEtypes_BeaconsMissed_t;
+
+/** MrvlIEtypes_LinkQuality_t */
+typedef struct MrvlIEtypes_LinkQuality {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Link SNR threshold */
+	t_u16 link_SNR_thrs;
+    /** Link SNR frequency */
+	t_u16 link_SNR_freq;
+    /** Minimum rate value */
+	t_u16 min_rate_val;
+    /** Minimum rate frequency */
+	t_u16 min_rate_freq;
+    /** Tx latency value */
+	t_u32 tx_latency_val;
+    /** Tx latency threshold */
+	t_u32 tx_latency_thrs;
+} __ATTRIB_PACK__ MrvlIEtypes_LinkQuality_t;
+
+/** Host Command ID : 802.11 subscribe event */
+#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT       0x0075
+
+/** 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 : 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 :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 */
+
+/** MrvlIEtypes_PreBeaconLost_t */
+typedef struct MrvlIEtypes_PreBeaconLost {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Pre-Beacon Lost */
+	t_u8 pre_beacon_lost;
+    /** Reserved */
+	t_u8 reserved;
+} __ATTRIB_PACK__ MrvlIEtypes_PreBeaconLost_t;
+
+/** TLV type: Pre-Beacon Lost */
+#define TLV_TYPE_PRE_BEACON_LOST    (PROPRIETARY_TLV_BASE_ID + 0x49)	/* 0x0149 */
+
+/** TLV type : Extended capabilities */
+#define TLV_TYPE_EXTCAP                         0x007f
+
+/** AutoTx_MacFrame_t */
+typedef struct AutoTx_MacFrame {
+	t_u16 interval;	      /**< in seconds */
+	t_u8 priority;	      /**< User Priority: 0~7, ignored if non-WMM */
+	t_u8 reserved;	      /**< set to 0 */
+	t_u16 frame_len;       /**< Length of MAC frame payload */
+	t_u8 dest_mac_addr[MLAN_MAC_ADDR_LENGTH];	/**< Destination MAC address */
+	t_u8 src_mac_addr[MLAN_MAC_ADDR_LENGTH];	/**< Source MAC address */
+	t_u8 payload[];			  /**< Payload */
+} __ATTRIB_PACK__ AutoTx_MacFrame_t;
+
+/** MrvlIEtypes_AutoTx_t */
+typedef struct MrvlIEtypes_AutoTx {
+	MrvlIEtypesHeader_t header;	    /**< Header */
+	AutoTx_MacFrame_t auto_tx_mac_frame;  /**< Auto Tx MAC frame */
+} __ATTRIB_PACK__ MrvlIEtypes_AutoTx_t;
+
+/** HostCmd_DS_802_11_AUTO_TX */
+typedef struct MAPP_HostCmd_DS_802_11_AUTO_TX {
+    /** Action */
+	t_u16 action;		/* 0 = ACT_GET; 1 = ACT_SET; */
+	MrvlIEtypes_AutoTx_t auto_tx;	 /**< Auto Tx */
+} __ATTRIB_PACK__ HostCmd_DS_802_11_AUTO_TX;
+
+/** Host Command ID : 802.11 auto Tx */
+#define HostCmd_CMD_802_11_AUTO_TX          0x0082
+
+/** TLV type : Auto Tx */
+#define TLV_TYPE_AUTO_TX            (PROPRIETARY_TLV_BASE_ID + 0x18)	/* 0x0118 */
+
+/** HostCmd_DS_802_11_CFG_DATA */
+typedef struct MAPP_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;
+
+/** Host Command ID : Configuration data */
+#define HostCmd_CMD_CFG_DATA                  0x008f
+
+/** mlan_ioctl_11h_tpc_resp */
+typedef struct {
+	int status_code;
+		     /**< Firmware command result status code */
+	int tx_power;/**< Reported TX Power from the TPC Report */
+	int link_margin;
+		     /**< Reported Link margin from the TPC Report */
+	int rssi;    /**< RSSI of the received TPC Report frame */
+} __ATTRIB_PACK__ mlan_ioctl_11h_tpc_resp;
+
+/** Host Command ID : 802.11 TPC adapt req */
+#define HostCmd_CMD_802_11_TPC_ADAPT_REQ      0x0060
+
+/** HostCmd_DS_802_11_CRYPTO */
+typedef struct MAPP_HostCmd_DS_802_11_CRYPTO {
+	t_u16 encdec;	  /**< Decrypt=0, Encrypt=1 */
+	t_u16 algorithm;  /**< RC4=1 AES=2 , AES_KEY_WRAP=3 */
+	t_u16 key_IV_length;/**< Length of Key IV (bytes)   */
+	t_u8 keyIV[32];	  /**< Key IV */
+	t_u16 key_length;  /**< Length of Key (bytes) */
+	t_u8 key[32];	  /**< Key */
+	MrvlIEtypes_Data_t data;
+			       /**< Plain text if encdec=Encrypt, Ciphertext data if encdec=Decrypt*/
+} __ATTRIB_PACK__ HostCmd_DS_802_11_CRYPTO;
+
+/** HostCmd_DS_802_11_CRYPTO_AES_CCM */
+typedef struct MAPP_HostCmd_DS_802_11_CRYPTO_AES_CCM {
+	t_u16 encdec;	  /**< Decrypt=0, Encrypt=1 */
+	t_u16 algorithm;  /**< AES_CCM=4 */
+	t_u16 key_length;  /**< Length of Key (bytes)  */
+	t_u8 key[32];	  /**< Key  */
+	t_u16 nonce_length;/**< Length of Nonce (bytes) */
+	t_u8 nonce[14];	  /**< Nonce */
+	t_u16 AAD_length;  /**< Length of AAD (bytes) */
+	t_u8 AAD[32];	  /**< AAD */
+	MrvlIEtypes_Data_t data;
+			       /**< Plain text if encdec=Encrypt, Ciphertext data if encdec=Decrypt*/
+} __ATTRIB_PACK__ HostCmd_DS_802_11_CRYPTO_AES_CCM;
+
+/** AES CCM cipher test */
+#define CIPHER_TEST_AES_CCM (4)
+
+/** Host Command ID : 802.11 crypto */
+#define HostCmd_CMD_802_11_CRYPTO             0x0078
+/** Get the current TSF */
+#define HostCmd_CMD_GET_TSF          0x0080
+
+/** Read/Write Mac register */
+#define HostCmd_CMD_MAC_REG_ACCESS            0x0019
+/** Read/Write BBP register */
+#define HostCmd_CMD_BBP_REG_ACCESS            0x001a
+/** Read/Write RF register */
+#define HostCmd_CMD_RF_REG_ACCESS             0x001b
+
+/** Host Command ID : CAU register access */
+#define HostCmd_CMD_CAU_REG_ACCESS            0x00ed
+
+/** Host Command ID : Memory access */
+#define HostCmd_CMD_MEM_ACCESS                0x0086
+
+/** 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,
+};
+
+/** Band_Config_t */
+typedef 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
+} __ATTRIB_PACK__ Band_Config_t;
+
+/** Host Command ID : Channel report request */
+#define HostCmd_CMD_CHAN_REPORT_REQUEST             0x00dd
+/** TLV type : Chan Load */
+#define TLV_TYPE_CHANRPT_CHAN_LOAD      (PROPRIETARY_TLV_BASE_ID + 0x59)	/* 0x0159 */
+/** TLV type : Noise Historgram */
+#define TLV_TYPE_CHANRPT_NOISE_HIST     (PROPRIETARY_TLV_BASE_ID + 0x5a)	/* 0x015a */
+
+typedef struct {
+	t_u16 startFreq;
+	t_u8 chanWidth;
+	t_u8 chanNum;
+
+} __ATTRIB_PACK__ MrvlChannelDesc_t;
+
+typedef struct {
+	MrvlChannelDesc_t chanDesc;
+				 /**< Channel band, number */
+	t_u32 millisecDwellTime; /**< Channel dwell time in milliseconds */
+} __ATTRIB_PACK__ HostCmd_DS_CHAN_RPT_REQ;
+
+typedef struct {
+
+	t_u32 commandResult;
+			  /**< Rpt request command result (0 == SUCCESS) */
+	t_u64 startTsf;	  /**< TSF Measurement started */
+	t_u32 duration;	  /**< Duration of measurement in microsecs */
+
+	t_u8 tlvBuffer[1];
+			 /**< TLV Buffer */
+} __ATTRIB_PACK__ HostCmd_DS_CHAN_RPT_RSP;
+
+typedef struct {
+	MrvlIEtypesHeader_t Header;	 /**< Header */
+
+	t_u8 ccaBusyFraction;		   /**< Parts per 255 channel was busy */
+} __ATTRIB_PACK__ MrvlIEtypes_ChanRptChanLoad_t;
+
+typedef struct {
+	MrvlIEtypesHeader_t header;  /**< Header */
+
+	t_s16 anpi;		       /**< ANPI calculated from the histogram */
+    /** RPI histogram bins. The number of bins utilized is variable and must
+		be calculated by the header length */
+	t_u8 rpiDensities[11];
+} __ATTRIB_PACK__ MrvlIEtypes_ChanRptNoiseHist_t;
+
+/** Maximum length of lines in configuration file */
+#define MAX_CONFIG_LINE                 1024
+/** MAC BROADCAST */
+#define MAC_BROADCAST   0x1FF
+/** MAC MULTICAST */
+#define MAC_MULTICAST   0x1FE
+
+/** HostCmd_DS_REG */
+typedef struct MAPP_HostCmd_DS_REG {
+    /** Read or write */
+	t_u16 action;
+    /** Register offset */
+	t_u16 offset;
+    /** Value */
+	t_u32 value;
+} __ATTRIB_PACK__ HostCmd_DS_REG;
+
+/** HostCmd_DS_MEM */
+typedef struct MAPP_HostCmd_DS_MEM {
+    /** Read or write */
+	t_u16 action;
+    /** Reserved */
+	t_u16 reserved;
+    /** Address */
+	t_u32 addr;
+    /** Value */
+	t_u32 value;
+} __ATTRIB_PACK__ HostCmd_DS_MEM;
+
+typedef struct _HostCmd_DS_MEF_CFG {
+    /** Criteria */
+	t_u32 Criteria;
+    /** Number of entries */
+	t_u16 NumEntries;
+} __ATTRIB_PACK__ HostCmd_DS_MEF_CFG;
+
+typedef struct _MEF_CFG_DATA {
+    /** Size */
+	t_u16 size;
+    /** Data */
+	HostCmd_DS_MEF_CFG data;
+} __ATTRIB_PACK__ MEF_CFG_DATA;
+
+/** HostCmd_DS_GEN */
+typedef struct MAPP_HostCmd_DS_GEN {
+    /** Command */
+	t_u16 command;
+    /** Size */
+	t_u16 size;
+    /** Sequence number */
+	t_u16 seq_num;
+    /** Result */
+	t_u16 result;
+} __ATTRIB_PACK__ HostCmd_DS_GEN;
+
+/** Size of HostCmd_DS_GEN */
+#define S_DS_GEN    sizeof(HostCmd_DS_GEN)
+
+/** pkt_header */
+typedef struct _pkt_header {
+    /** pkt_len */
+	t_u32 pkt_len;
+    /** pkt_type */
+	t_u32 TxPktType;
+    /** tx control */
+	t_u32 TxControl;
+} pkt_header;
+
+/** eth_priv_802_11_header packet from FW with length */
+typedef struct _eth_priv_mgmt_frame_tx {
+    /** Packet Length */
+	t_u16 frm_len;
+    /** Frame Control */
+	t_u16 frm_ctl;
+    /** Duration ID */
+	t_u16 duration_id;
+    /** Address1 */
+	t_u8 addr1[ETH_ALEN];
+    /** Address2 */
+	t_u8 addr2[ETH_ALEN];
+    /** Address3 */
+	t_u8 addr3[ETH_ALEN];
+    /** Sequence Control */
+	t_u16 seq_ctl;
+    /** Address4 */
+	t_u8 addr4[ETH_ALEN];
+    /** Frame payload */
+	t_u8 payload[0];
+} __ATTRIB_PACK__ eth_priv_mgmt_frame_tx;
+
+/** frame tx ioctl number */
+#define FRAME_TX_IOCTL               (SIOCDEVPRIVATE + 12)
+
+typedef struct {
+	t_u32 timeSinceLastQuery_ms; /**< Duration of stats collection */
+
+	t_u16 bcnCnt;		     /**< Number of beacons received */
+	t_u16 bcnMiss;		     /**< Estimate of beacons missed */
+	t_s16 bcnRssiAvg;	     /**< Avg beacon RSSI */
+	t_s16 bcnSnrAvg;	     /**< Avg beacon SNR */
+
+	t_u32 rxPkts;		     /**< Number of packets received */
+	t_s16 rxRssiAvg;	     /**< Avg received packet RSSI */
+	t_s16 rxSnrAvg;		     /**< Avg received packet SNR */
+
+	t_u32 txPkts;		     /**< Number of packets transmitted */
+	t_u32 txAttempts;	     /**< Number of attempts made */
+	t_u32 txFailures;	     /**< Number of pkts that failed */
+	t_u8 txInitRate;	     /**< Current rate adaptation TX rateid */
+	t_u8 reserved[3];	     /**< Reserved */
+
+	t_u16 txQueuePktCnt[MAX_AC_QUEUES];
+					 /**< Number of packets per AC */
+	t_u32 txQueueDelay[MAX_AC_QUEUES];
+					 /**< Averge queue delay per AC*/
+} __ATTRIB_PACK__ HostCmd_DS_LINK_STATS_SUMMARY;
+
+#define HostCmd_CMD_LINK_STATS_SUMMARY    0x00d3
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef enum _wmm_ac {
+	AC_BE,
+	AC_BK,
+	AC_VI,
+	AC_VO,
+} wmm_ac;
+
+/** Data structure of Host command WMM_PARAM_CFG  */
+typedef 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 */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} __ATTRIB_PACK__ HostCmd_DS_WMM_PARAM_CONFIG;
+
+/** Host Command ID : Configure ADHOC_OVER_IP parameters */
+#define HostCmd_CMD_WMM_PARAM_CONFIG                0x023a
+
+/** TLV ID for multi chan info */
+#define MULTI_CHAN_INFO_TLV_ID              (PROPRIETARY_TLV_BASE_ID + 0xb7)
+/** TLV ID for multi chan group info */
+#define MULTI_CHAN_GROUP_INFO_TLV_ID        (PROPRIETARY_TLV_BASE_ID + 0xb8)
+/** BSS number mask */
+#define BSS_NUM_MASK                    0xf
+
+typedef struct _eth_priv_multi_chan_cfg {
+	/** Channel Time in us*/
+	t_u32 channel_time;
+	/** Buffer Weight */
+	t_u8 buffer_weight;
+	/** tlv len */
+	t_u16 tlv_len;
+	/** TLV Buffer */
+	t_u8 tlv_buf[0];
+} __ATTRIB_PACK__ eth_priv_multi_chan_cfg;
+
+typedef struct _eth_priv_drcs_cfg {
+	/** Channel Index*/
+	t_u16 chan_idx;
+	/** Channel time (in TU) for chan_idx*/
+	t_u8 chantime;
+	/** Channel swith time (in TU) for chan_idx*/
+	t_u8 switchtime;
+	/** Undoze time (in TU) for chan_idx*/
+	t_u8 undozetime;
+	/** Rx traffic control scheme when channel switch*/
+	/** only valid for GC/STA interface*/
+	t_u8 mode;
+} __ATTRIB_PACK__ eth_priv_drcs_cfg;
+
+typedef struct _ChannelBandInfo {
+	Band_Config_t bandcfg;
+	t_u8 chan_num;
+} __ATTRIB_PACK__ ChannelBandInfo;
+
+typedef struct _MrvlIETypes_multi_chan_group_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+	t_u8 chan_group_id;
+	t_u8 chan_buff_weight;
+	ChannelBandInfo chan_band_info;
+	t_u32 channel_time;
+	t_u32 reserved;
+	union {
+		t_u8 sdio_func_num;
+		t_u8 usb_epnum;
+	} __ATTRIB_PACK__ hid_num;
+	t_u8 num_intf;
+	t_u8 bss_type_numlist[0];
+} __ATTRIB_PACK__ MrvlIEtypes_multi_chan_group_info_t;
+
+typedef struct _MrvlIETypes_multi_chan_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** multi channel operation status */
+	t_u16 status;
+    /** Tlv buffer */
+	t_u8 tlv_buffer[0];
+} __ATTRIB_PACK__ MrvlIEtypes_multi_chan_info_t;
+
+#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
+
+/** DFS repeater mode configuration */
+typedef struct _dfs_repeater {
+    /** Enable DFS repeater mode */
+	t_u16 action;
+    /** 1 on and 0 off */
+	t_u16 mode;
+} dfs_repeater;
+
+#ifdef RX_PACKET_COALESCE
+/** RX packet coalesce tlv */
+typedef struct _tlvbuf_rx_pkt_coal_t {
+    /** threshold for rx packets */
+	t_u32 rx_pkt_count;
+    /** timeout for rx coalescing timer */
+	t_u16 delay;
+} tlvbuf_rx_pkt_coal_t;
+#endif
+
+/** Maximum SSID length */
+#define MAX_SSID_LENGTH         32
+/** Maximum SSID length */
+#define MIN_SSID_LENGTH         1
+/** Maximum WPA passphrase length */
+#define MAX_WPA_PASSPHRASE_LENGTH   64
+/** Minimum WPA passphrase length */
+#define MIN_WPA_PASSPHRASE_LENGTH   8
+
+/* CW_MODE_CTRL structure*/
+typedef struct {
+	t_u8 mode;
+	t_u8 channel;
+	t_u8 chanInfo;
+	t_u16 txPower;
+	t_u16 pktLength;
+	t_u32 rateInfo;
+} __ATTRIB_PACK__ cw_mode_ctrl;
+#endif /* _MLANUTL_H_ */
diff --git a/wlan_sd8897/mapp/mlanutl/timestamp.c b/wlan_sd8897/mapp/mlanutl/timestamp.c
new file mode 100644
index 0000000..e363ef0
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/timestamp.c
@@ -0,0 +1,413 @@
+/** @file  timestamp.c
+ *
+ * @brief Functions for timestamping feature
+ *
+ * Copyright (C) 2011-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include "timestamp.h"
+#include "time.h"
+
+/* GLobal Declarations */
+struct timespec send_time;
+struct interface_data inter;
+
+/**
+ *@brief      Receive Timestamps
+ *
+ *@param argc Number of arguments
+ *@param argv Pointer to the arguments array
+ *
+ * @return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ **/
+void
+receive_timestamp(int argc, char *argv[])
+{
+	int sockfd;
+	int sockopt;
+	char ifName[IFNAMSIZ];
+	struct ifreq if_ip;	/* get ip addr */
+	int so_timestamping_flags = 0;
+	int siocgstamp = 0;
+	int siocgstampns = 0;
+	struct timeval now;
+	int res;
+	struct ifreq if_idx;
+	struct ifreq if_mac;
+	fd_set readfs, errorfs;
+
+	/* Get interface name */
+	if (argc > 2)
+		strcpy(ifName, argv[1]);
+	else {
+		fprintf(stderr,
+			"invalid no. of arguments to receive_timestamp \n");
+		exit(1);
+	}
+
+	/* Header structures */
+	so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
+	so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
+	memset(&if_ip, 0, sizeof(struct ifreq));
+
+	/* Open PF_PACKET socket, listening for EtherType ETHER_TYPE */
+	if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_802_EX1))) == -1) {
+		perror("listener: socket");
+	}
+
+	/* Get the index of the interface to receive on */
+	memset(&if_idx, 0, sizeof(struct ifreq));
+	strncpy(if_idx.ifr_name, ifName, IFNAMSIZ - 1);
+	if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0)
+		perror("SIOCGIFINDEX");
+
+	/* Get the MAC address of the interface to receive on */
+	memset(&if_mac, 0, sizeof(struct ifreq));
+	strncpy(if_mac.ifr_name, ifName, IFNAMSIZ - 1);
+	if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0)
+		perror("SIOCGIFHWADDR");
+
+	/* Allow the socket to be reused - incase connection is closed prematurely */
+	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt,
+		       sizeof sockopt) == -1) {
+		perror("setsockopt");
+		close(sockfd);
+		exit(1);
+	}
+
+	/* Bind to device */
+	if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
+		       ifName, IFNAMSIZ - 1) == -1) {
+		perror("SO_BINDTODEVICE");
+		close(sockfd);
+		exit(1);
+	}
+
+	if (so_timestamping_flags &&
+	    setsockopt(sockfd, SOL_SOCKET, SO_TIMESTAMPING,
+		       &so_timestamping_flags,
+		       sizeof(so_timestamping_flags)) < 0)
+		perror("setsockopt SO_TIMESTAMPING");
+
+	while (1) {
+		FD_ZERO(&readfs);
+		FD_ZERO(&errorfs);
+		FD_SET(sockfd, &readfs);
+		FD_SET(sockfd, &errorfs);
+		gettimeofday(&now, NULL);
+		res = select(sockfd + 1, &readfs, 0, &errorfs, NULL);
+		if (res > 0) {
+			recvpacket(sockfd, 0, siocgstamp, siocgstampns);
+		}
+	}
+}
+
+/**
+ *@brief      Send Timestamps
+ *
+ *@param argc Number of arguments
+ *@param argv Pointer to the arguments array
+ *
+ *@return     MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ **/
+int
+send_timestamp(int argc, char *argv[])
+{
+	int sockfd;
+	struct ifreq if_idx;
+	struct ifreq if_mac;
+	int tx_len = 0, i;
+	char sendbuf[BUF_SIZ];
+	char buff[BUF_SIZ];
+	struct ether_header *eh = (struct ether_header *)sendbuf;
+	struct sockaddr_ll socket_address;
+	char ifName[IFNAMSIZ], ip[50];
+	struct timeval delta;
+	fd_set readfs, errorfs;
+	int res, siocgstamp = 1, siocgstampns = 1;
+	int so_timestamping_flags = SOF_TIMESTAMPING_TX_HARDWARE;
+	struct ifreq hwtstamp;
+	struct hwtstamp_config hwconfig;
+
+	so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
+	so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
+	so_timestamping_flags |= SOF_TIMESTAMPING_SYS_HARDWARE;
+
+	/* Get interface name */
+	if (argc > 4) {
+		strcpy(ifName, argv[1]);
+		strcpy(ip, argv[4]);
+	} else {
+		fprintf(stderr, "invalid no. of args for send_timestamp\n");
+		exit(1);
+	}
+
+	/* Open RAW socket to send on */
+	if ((sockfd = socket(PF_PACKET, SOCK_RAW, ETH_P_802_EX1)) == -1) {
+		perror("socket");
+	}
+
+	memset(&hwtstamp, 0, sizeof(hwtstamp));
+	strncpy(hwtstamp.ifr_name, ifName, sizeof(hwtstamp.ifr_name));
+	hwtstamp.ifr_data = (void *)&hwconfig;
+	memset(&hwconfig, 0, sizeof(hwconfig));
+
+	hwconfig.tx_type =
+		(so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
+		HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+
+	hwconfig.rx_filter =
+		(so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
+		HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
+
+	/* Get the index of the interface to send on */
+	memset(&if_idx, 0, sizeof(struct ifreq));
+	strncpy(if_idx.ifr_name, ifName, IFNAMSIZ - 1);
+	if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0)
+		perror("SIOCGIFINDEX");
+
+	/* Get the MAC address of the interface to send on */
+	memset(&if_mac, 0, sizeof(struct ifreq));
+	strncpy(if_mac.ifr_name, ifName, IFNAMSIZ - 1);
+	if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0)
+		perror("SIOCGIFHWADDR");
+
+	if (so_timestamping_flags &&
+	    setsockopt(sockfd, SOL_SOCKET, SO_TIMESTAMPING,
+		       &so_timestamping_flags,
+		       sizeof(so_timestamping_flags)) < 0)
+		perror("setsockopt SO_TIMESTAMPING");
+
+	if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
+		       ifName, IFNAMSIZ - 1) == -1) {
+		perror("bind");
+		exit(1);
+	}
+
+	/* Construct the Ethernet header */
+	memset(sendbuf, 0, BUF_SIZ);
+
+	/* Ethernet header */
+	memcpy(eh->ether_shost, (u_int8_t *) & if_mac.ifr_hwaddr.sa_data,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	eh->ether_type = htons(ETH_P_802_EX1);
+
+	tx_len += sizeof(struct ether_header);
+
+	get_mac(ifName, ip);
+	for (i = 0; i < MLAN_MAC_ADDR_LENGTH; i++) {
+		eh->ether_dhost[i] = (uint8_t) inter.mac[i];
+	}
+	/* Index of the network device */
+	socket_address.sll_ifindex = if_idx.ifr_ifindex;
+
+	/* Address length */
+	socket_address.sll_halen = ETH_ALEN;
+	memcpy(&socket_address.sll_addr, (uint8_t *) & inter.mac,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	clock_gettime(CLOCK_REALTIME, &send_time);
+	sprintf(buff, "%lld.%lld", (long long)send_time.tv_sec,
+		(long long)send_time.tv_nsec);
+	strcpy((sendbuf + tx_len), buff);
+
+	/* Send packet */
+	res = sendto(sockfd, sendbuf, tx_len + strlen(buff), 0,
+		     (struct sockaddr *)&socket_address,
+		     sizeof(struct sockaddr_ll));
+	if (res < 0)
+		perror("Send ");
+
+	fprintf(stdout, "Application time : %lld.%09lld (sent)\n",
+		(long long)send_time.tv_sec, (long long)send_time.tv_nsec);
+
+	delta.tv_sec = 5;
+	delta.tv_usec = 0;
+
+	FD_ZERO(&readfs);
+	FD_ZERO(&errorfs);
+	FD_SET(sockfd, &readfs);
+	FD_SET(sockfd, &errorfs);
+
+	res = select(sockfd + 1, &readfs, 0, &errorfs, &delta);
+	if (res > 0) {
+		recvpacket(sockfd, MSG_ERRQUEUE, siocgstamp, siocgstampns);
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *@brief    get destination mac address
+ *
+ *@param    ifc interface from which packet has to be sent
+ *@param    ip IP Address of destination
+ *
+ *@return   N/A
+ **/
+void
+get_mac(char *ifc, char *ip)
+{
+	char ipAddr[20];
+	char hwAddr[20];
+	char device[10], temp[3], in[50];
+	int i = 0, j = 0, k = 0, res = 0, retry = 0;
+	FILE *arpCache = fopen("/proc/net/arp", "r");
+	if (!arpCache) {
+		fprintf(stderr,
+			"Arp Cache: Failed to open file \"/proc/net/arp\"");
+	}
+
+	/* Ignore the first line, which contains the header */
+	char header[ARP_FILE_BUFFER_LEN];
+
+retry_again:
+
+	if (!fgets(header, sizeof(header), arpCache))
+		fprintf(stderr, "error getting mac from proc files");
+	while (3 == fscanf(arpCache, ARP_FORMAT, ipAddr, hwAddr, device)) {
+		if ((!strcmp(ipAddr, ip)) && (!strcmp(ifc, device))) {
+			printf("Sending Packet to Peer : %s\n", hwAddr);
+			strcpy(inter.ip, ipAddr);
+			strcpy(inter.interface, device);
+			while (hwAddr[i] != '\0') {
+				if (hwAddr[i] == ':') {
+					inter.mac[j++] = strtol(temp, NULL, 16);
+					i++;
+					k = 0;
+				} else
+					temp[k++] = hwAddr[i++];
+			}
+			inter.mac[j] = strtol(temp, NULL, 16);
+			res = 1;
+		}
+	}
+	if (res != 1 && retry == 0) {
+		sprintf(in, "ping -c 2 %s > /dev/null", ip);
+		system(in);
+		retry = 1;
+		rewind(arpCache);
+		goto retry_again;
+	} else if (res != 1 && retry == 1) {
+		printf("cannot find mac address for the specified ip\n");
+		fclose(arpCache);
+		exit(1);
+	}
+	fclose(arpCache);
+}
+
+/*
+ *@brief    Receive Sync Packets
+ *
+ *@param sock socket from which packet must be recieved
+ *@param recvmsg_flags flags for recvmsg
+ *@param siocgstamp timestamp flag
+ *@param siocgstampns timestamp flag for nano secs
+ *
+ *@return     N/A
+ **/
+void
+recvpacket(int sock, int recvmsg_flags, int siocgstamp, int siocgstampns)
+{
+	unsigned char data[256];
+	struct msghdr msg;
+	struct iovec entry;
+	struct sockaddr_in from_addr;
+	struct {
+		struct cmsghdr cm;
+		char control[512];
+	} control;
+	int res, i;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = &entry;
+	msg.msg_iovlen = 1;
+	entry.iov_base = data;
+	entry.iov_len = sizeof(data);
+	msg.msg_name = (caddr_t) & from_addr;
+	msg.msg_namelen = sizeof(from_addr);
+	msg.msg_control = &control;
+	msg.msg_controllen = sizeof(control);
+
+	res = recvmsg(sock, &msg, recvmsg_flags | MSG_DONTWAIT);
+	if (res < 0) {
+		fprintf(stderr, "%s %s: %s\n",
+			"recvmsg",
+			(recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
+			strerror(errno));
+	} else {
+		if (!(recvmsg_flags & MSG_ERRQUEUE)) {
+			printf("Received Packet from Peer : ");
+			for (i = 6; i < 12; i++)
+				printf("%02x:", data[i]);
+			printf("\n");
+		}
+		printpacket(&msg, res, sock, recvmsg_flags, siocgstamp,
+			    siocgstampns);
+	}
+}
+
+/**
+ * @brief      Prints Sent/Received Sync packets
+ *
+ * @param      msg msghdr structure variable
+ * @param      res result of recvmsg call
+ * @param      sock socket variable
+ * @param      recvmsg_flags  flags for receive message
+ * @param      siocgstamp timestamp flag
+ * @param      siocgstampns timestamp flag for nano secs
+ *
+ * @return     N/A
+ **/
+void
+printpacket(struct msghdr *msg, int res,
+	    int sock, int recvmsg_flags, int siocgstamp, int siocgstampns)
+{
+	struct cmsghdr *cmsg;
+	struct timespec now;
+	struct timespec *stamp;
+	clock_gettime(CLOCK_REALTIME, &now);
+	if (!(recvmsg_flags & MSG_ERRQUEUE)) {
+		printf("Application time : %ld.%09ld (received)\n",
+		       (long)now.tv_sec, (long)now.tv_nsec);
+	}
+
+	for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+		if (cmsg->cmsg_level == SOL_SOCKET &&
+		    cmsg->cmsg_type == SO_TIMESTAMPING) {
+			stamp = (struct timespec *)CMSG_DATA(cmsg);
+			stamp++;
+			/* skip deprecated HW transformed */
+			stamp++;
+			fprintf(stdout, "HW time : %ld.%09ld\n",
+				(long)stamp->tv_sec, (long)stamp->tv_nsec);
+			if (!(recvmsg_flags & MSG_ERRQUEUE))
+				fprintf(stdout, "Delta in nsecs= %lld\n",
+					((long long)(now.tv_sec -
+						     stamp->tv_sec) *
+					 1000000000L + now.tv_nsec) -
+					(stamp->tv_nsec));
+			else
+				fprintf(stdout, "Delta in nsecs= %lld",
+					((long long)(stamp->tv_sec -
+						     send_time.tv_sec) *
+					 1000000000L + (stamp->tv_nsec) -
+					 send_time.tv_nsec));
+		}
+	}
+	fprintf(stdout, "\n");
+}
diff --git a/wlan_sd8897/mapp/mlanutl/timestamp.h b/wlan_sd8897/mapp/mlanutl/timestamp.h
new file mode 100644
index 0000000..7635ae6
--- /dev/null
+++ b/wlan_sd8897/mapp/mlanutl/timestamp.h
@@ -0,0 +1,54 @@
+/** @file  timestamp.h
+ *
+ * @brief This file contains definitions used for application
+ *
+ * Copyright (C) 2011-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#ifndef _TIMESTAMP_H_
+#define _TIMESTAMP_H_
+
+#include  "mlanutl.h"
+#include  <linux/if_packet.h>
+#include  <netinet/ether.h>
+#include  <linux/net_tstamp.h>
+
+#define BUF_SIZ         1024
+#define ARP_FORMAT      "%s %*s %*s %s %*s %s"
+#define ARP_FILE_BUFFER_LEN  (1024)
+
+struct interface_data {
+	char ip[20];
+	int mac[20];
+	char interface[20];
+};
+
+/**
+ * 802.1 Local Experimental 1.
+ */
+#ifndef ETH_P_802_EX1
+#define ETH_P_802_EX1   0x88B5
+#endif
+
+void receive_timestamp(int argc, char *argv[]);
+int send_timestamp(int argc, char *argv[]);
+void get_mac(char *ifc, char *ip);
+void recvpacket(int sock, int recvmsg_flags, int siocgstamp, int siocgstampns);
+void printpacket(struct msghdr *msg, int res, int sock,
+		 int recvmsg_flags, int siocgstamp, int siocgstampns);
+
+#endif //_TIMESTAMP_H_
diff --git a/wlan_sd8897/mapp/uaputl/Makefile b/wlan_sd8897/mapp/uaputl/Makefile
new file mode 100644
index 0000000..cea69f3
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/Makefile
@@ -0,0 +1,53 @@
+# File : uaputl/Makefile
+#
+# Copyright (C) 2008-2017, Marvell International Ltd. All Rights Reserved
+
+# Path to the top directory of the wlan distribution
+PATH_TO_TOP = ../..
+
+# Determine how we should copy things to the install directory
+ABSPATH := $(filter /%, $(INSTALLDIR))
+RELPATH := $(filter-out /%, $(INSTALLDIR))
+INSTALLPATH := $(ABSPATH)
+ifeq ($(strip $(INSTALLPATH)),)
+INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH)
+endif
+
+# Override CFLAGS for application sources, remove __ kernel namespace defines
+CFLAGS := $(filter-out -D__%, $(ccflags-y))
+# remove KERNEL include dir
+CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS))
+
+
+#CFLAGS += -DAP22 -fshort-enums
+CFLAGS += -Wall
+#ECHO = @
+LIBS = -lrt
+
+.PHONY: default tags all
+
+OBJECTS = uaputl.o uapcmd.o uaphostcmd.o
+HEADERS = uaputl.h uapcmd.h
+
+TARGET = uaputl.exe
+
+build default: $(TARGET)
+	@cp -f $(TARGET) $(INSTALLPATH)
+	@cp -rf config $(INSTALLPATH)
+
+
+all : tags default
+
+$(TARGET): $(OBJECTS) $(HEADERS)
+	$(ECHO)$(CC) $(LIBS) -o $@ $(OBJECTS)
+
+%.o: %.c $(HEADERS)
+	$(ECHO)$(CC) $(CFLAGS) -c -o $@ $<
+
+tags:
+	ctags -R -f tags.txt
+
+distclean clean:
+	$(ECHO)$(RM) $(OBJECTS) $(TARGET)
+	$(ECHO)$(RM) tags.txt
+
diff --git a/wlan_sd8897/mapp/uaputl/config/80211d_domain.conf b/wlan_sd8897/mapp/uaputl/config/80211d_domain.conf
new file mode 100644
index 0000000..bb14e86
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/config/80211d_domain.conf
@@ -0,0 +1,45 @@
+/* Domain and country mapping are in this section */
+/* Domain name followed by supported countries */
+
+COUNTRY: DOMAIN_CODE_FCC AE AM AN AR AZ BH BL BN BR CL CN CR CS DZ EC EG GE HN HK ID IL IR JM JO KP KW KZ LB LK MA MO NP OM PE PG PH PK PT QA SA SG SV SY TH TT TN UY YE ZA ZW VN
+COUNTRY: DOMAIN_CODE_FCC1 US UZ CA CO DO GT MX PA PR TW NZ BO BZ VE
+COUNTRY: DOMAIN_CODE_MKK JP
+COUNTRY: DOMAIN_CODE_ETSI AL AD AT AU BY BE BA BG HR CY CZ DK EE FI FR MK DE GB 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
+COUNTRY: DOMAIN_CODE_IN IN
+COUNTRY: DOMAIN_CODE_MY MY
+
+
+/* Domain specific sub-band information */
+/* Domain name followed by set of triplets separated by comma */
+/* 1st number in triplet is First channel, */
+/* 2nd number in triplet is Number of channels followed from the First channel  */
+/* 3rd number in triplet is Max-TX-power in dbm */
+
+DOMAIN: DOMAIN_CODE_FCC     1 13 20
+DOMAIN: DOMAIN_CODE_FCC1    1 11 30
+DOMAIN: DOMAIN_CODE_ETSI    1 13 20
+DOMAIN: DOMAIN_CODE_MKK     1 14 23
+DOMAIN: DOMAIN_CODE_IN      1 11 30
+DOMAIN: DOMAIN_CODE_MY      1 13 20
+DOMAIN: DOMAIN_CODE_TEST    1 1 20, 2 1 16, 3 6 30, 11 1 10
+DOMAIN: DOMAIN_CODE_TEST1  1 11 30, 36 1 17, 40 1 17,  44 1 17,  48 1 17,  52 1 24,    56 1 24,  60 1 24,  64 1 24,  149 1 23,  153 1 23,  157 1 23,  161 1 23,  165 1 23,
+DOMAIN: DOMAIN_CODE_END
+
+/*
+ * Information for channels in A Band.
+ */
+
+*** 5GHz ***
+
+DOMAIN: DOMAIN_CODE_FCC     36 1 20, 40 1 20, 44 1 20, 48 1 20, 52 1 20, 56 1 20, 60 1 20, 64 1 20, 100 1 20, 104 1 20, 108 1 20, 112 1 20, 116 1 20, 120 1 20, 124 1 20, 128 1 20, 132 1 20, 136 1 20, 140 1 20, 144 1 20, 149 1 20, 153 1 20, 157 1 20, 161 1 20, 165 1 20,
+DOMAIN: DOMAIN_CODE_FCC1     36 1 30, 40 1 30, 44 1 30, 48 1 30, 52 1 30, 56 1 30, 60 1 30, 64 1 30, 100 1 30, 104 1 30, 108 1 30, 112 1 30, 116 1 30, 120 1 30, 124 1 30, 128 1 30, 132 1 30, 136 1 30, 140 1 30, 144 1 30, 149 1 30, 153 1 30, 157 1 30, 161 1 30, 165 1 30,
+
+DOMAIN: DOMAIN_CODE_MKK     8 1 24, 12 1 24, 16 1 24, 36 1 23, 40 1 23, 44 1 23, 48 1 23, 52 1 23, 56 1 23, 60 1 23, 64 1 23, 100 1 23, 104 1 23, 108 1 23, 112 1 23, 116 1 23, 120 1 23, 124 1 23, 128 1 23, 132 1 23, 136 1 23, 140 1 23,
+
+DOMAIN: DOMAIN_CODE_ETSI    36 1 20, 40 1 20, 44 1 20, 48 1 20, 52 1 20, 56 1 20, 60 1 20, 64 1 20, 100 1 20, 104 1 20, 108 1 20, 112 1 20, 116 1 20, 120 1 20, 124 1 20, 128 1 20, 132 1 20, 136 1 20, 140 1 20, 149 1 20, 153 1 20, 157 1 20, 161 1 20, 165 1 20,
+
+DOMAIN: DOMAIN_CODE_IN    36 1 30, 40 1 30, 44 1 30, 48 1 30, 52 1 30, 56 1 30, 60 1 30, 64 1 30, 149 1 30, 153 1 30, 157 1 30, 161 1 30, 165 1 30,
+
+DOMAIN: DOMAIN_CODE_MY    36 1 20, 40 1 20, 44 1 20, 48 1 20, 52 1 20, 56 1 20, 60 1 20, 64 1 20, 149 1 20, 153 1 20, 157 1 20, 161 1 20, 165 1 20,
+
+DOMAIN: DOMAIN_CODE_5G_END
diff --git a/wlan_sd8897/mapp/uaputl/config/embedded_dhcp.conf b/wlan_sd8897/mapp/uaputl/config/embedded_dhcp.conf
new file mode 100644
index 0000000..4417c5b
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/config/embedded_dhcp.conf
@@ -0,0 +1,9 @@
+#   File : embedded_dhcp.conf
+
+dhcp_config={
+    HostIPAddr=192.168.10.1
+    StartIPAddr=192.168.10.10
+    SubMask=255.255.255.0
+    LeaseTime=10000
+    LimitCount=5
+}
diff --git a/wlan_sd8897/mapp/uaputl/config/sample_cal_data_bg_8688.conf b/wlan_sd8897/mapp/uaputl/config/sample_cal_data_bg_8688.conf
new file mode 100644
index 0000000..e37f674
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/config/sample_cal_data_bg_8688.conf
@@ -0,0 +1,42 @@
+01 00 0c 00 58 02
+00 40 68 0c 00 00 00 40 00 00 00 00 00 11 00 00
+00 11 00 10 00 00 00 00 00 00 00 00 00 00 00 00
+10 12 00 10 10 86 40 89 01 03 02 00 01 02 05 00
+01 03 05 00 17 17 00 05 00 00 00 00 00 00 00 00
+00 30 1f 11 00 00 00 70 00 00 00 00 13 00 1e 01
+00 1e 5e 15 29 5e 15 13 5c 1d 0d 0b 1d 0d 0b 29
+0d 0b 29 5c 0b 29 5c 1d 00 5c 1d 0d 00 00 00 00
+00 5c c0 0e 00 00 00 cc 00 5f 00 00 07 01 04 00
+00 00 0e 0d 00 00 00 00 00 00 00 00 00 00 00 ff
+00 00 00 01 00 00 00 00 00 00 00 ff 00 00 00 01
+00 00 00 00 00 00 00 ff 00 00 00 01 00 00 00 00
+00 00 00 ff 00 00 00 01 00 00 00 00 06 3c 06 3d
+00 00 00 00 00 00 00 00 00 00 00 00
+00 5c dc 25 00 00 01 28 00 6f 00 00 07 01 04 00
+00 00 0e 0d 00 00 00 00 00 00 00 00 00 08 00 07
+00 00 00 09 00 00 00 00 00 08 00 07 00 00 00 09
+00 00 00 00 00 08 00 07 00 00 00 09 00 00 00 00
+00 08 00 07 00 00 00 09 00 00 00 00 06 3c 06 3d
+00 00 00 00 00 00 00 00 00 00 00 00
+00 14 9f 1f 00 00 01 3c 03 00 00 00 00 f1 0a f1
+00 fb 0d fb
+00 20 dd 28 00 00 01 5c 08 86 00 88 ff 06 b1 05
+24 24 3c 42 00 00 24 18 a4 24 bc bc 3d 00 a0 8f
+00 14 00 2a 00 00 01 70 00 00 30 00 01 05 1b 00
+00 00 00 01
+00 74 2c 10 00 00 01 e4 00 00 00 00 09 6a 09 b0
+0b 12 00 6c 04 0a 00 6c 03 03 00 6c 03 03 00 6c
+3f ff ff 00 3f ff ff 01 3f ff ff 02 3f ff ff 03
+15 00 00 04 17 00 00 05 19 00 00 06 1b 00 00 07
+1d 00 00 08 1f 00 00 09 21 00 00 0a 23 00 00 0b
+25 00 00 0c 28 00 00 0d 2a 00 00 0e 2d 00 00 0f
+2f 00 00 10 32 00 00 11 34 00 00 12 3f ff ff 13
+3f ff ff 14
+00 74 84 10 ff ff ff ff 01 00 00 00 09 b0 09 ba
+0a 0f 00 6c 04 09 00 6c 03 03 00 6c 03 03 00 6c
+3f ff ff 00 3f ff ff 01 3f ff ff 02 3f ff ff 03
+15 00 00 04 17 00 00 05 1a 00 00 06 1c 00 00 07
+1f 00 00 08 21 00 00 09 23 00 00 0a 26 00 00 0b
+2a 00 00 0c 2d 00 00 0d 31 00 00 0e 34 00 00 0f
+3f ff ff 10 3f ff ff 11 3f ff ff 12 3f ff ff 13
+3f ff ff 14
diff --git a/wlan_sd8897/mapp/uaputl/config/tdls_ext_cap.conf b/wlan_sd8897/mapp/uaputl/config/tdls_ext_cap.conf
new file mode 100644
index 0000000..79c9534
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/config/tdls_ext_cap.conf
@@ -0,0 +1,6 @@
+#   File : tdls_ext_cap.conf
+
+tdls_config={
+    tdls_prohibit=1
+    tdls_channel_switch_prohibit=1
+}
diff --git a/wlan_sd8897/mapp/uaputl/config/uapcoex.conf b/wlan_sd8897/mapp/uaputl/config/uapcoex.conf
new file mode 100644
index 0000000..40912f7
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/config/uapcoex.conf
@@ -0,0 +1,22 @@
+#   File : uapcoex.conf
+
+coex_config={
+    common_config={
+        bitmap=0x0                  # bit 0: override CTS2RTS protection
+        APBTCoex=0                  # enabled or not
+    }
+    sco_config={
+        protectionFromQTime0=1000
+        protectionFromQTime1=600
+        protectionFromQTime2=0
+        protectionFromQTime3=0
+        scoProtectionFromRate=9
+        aclFrequency=20
+    }
+    acl_config={
+        enabled=1
+        btTime=40
+        wlanTime=60
+        aclProtectionFromRate=1
+    }
+}
diff --git a/wlan_sd8897/mapp/uaputl/config/uaputl.conf b/wlan_sd8897/mapp/uaputl/config/uaputl.conf
new file mode 100644
index 0000000..8ddc436
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/config/uaputl.conf
@@ -0,0 +1,149 @@
+#   File : uaputl.conf
+
+
+ap_config={
+    SSID="Marvell Micro AP"         # SSID of Micro AP, use '\' as an escape character before '"' character in SSID
+    BeaconPeriod=100                # Beacon period in TU
+    Channel=6                       # Radio Channel	6
+#   Channel=0,1                     # auto channel select (MCS mode)
+#   Channel=6,2                     # primary channel 6, secondary channel above.
+#   Channel=6,4                     # primary channel 6, secondary channel below
+    ChanList=1,6,11                 # Scan channel list
+#   AP_MAC=00:34:22:77:46:41        # MAC address of AP
+    Band=0                          # 0 for 2.4GHz band
+                                    # 1 for 5GHz band
+    Rate=0x82,0x84,0x8b,0x96,0x0C,0x12,0x18,0x24,0x30,0x48,0x60,0x6c
+                                    # Set of data rate that a station
+                                    # in the BSS may use
+                                    # (in unit of 500 kilobit/s)
+    TxPowerLevel=13                 # Transmit power level in dBm
+    BroadcastSSID=1                 # Broadcast SSID feature
+                                    # 1: Enable  0:Disable
+    RTSThreshold=2347               # RTS threshold value
+    FragThreshold=2346              # Fragmentation threshold value
+    DTIMPeriod=1                    # DTIM period in beacon periods
+    MCBCdataRate=0                  # MCBC rate to use for packet transmission
+                                    # 0:auto
+                                    # >0 fix rate (in unit of 500 kilobit/s)
+#    TxBeaconRate=0                 # Beacon rate to use for Beacon transmission
+                                    # 0:auto
+                                    # >0 fix rate (in unit of 500 kilobit/s)
+    PktFwdCtl=1                     # Packet forwarding control
+                                    # 0: forward all packets to the host
+                                    # 1: firmware handles intr-BSS packets
+    StaAgeoutTimer=1800             # Inactive client station age out timer value
+                                    # in units of 100ms
+    PSStaAgeoutTimer=400            # Inactive client PS station age out timer value
+                                    # in units of 100ms
+    MaxStaNum=10                    # Max number of stations allowed to connect
+    Retrylimit=7                    # Retry limit to use for packet transmissions
+    AuthMode=0                      # 0:Open authentication
+                                    # 1:shared key authentication
+    Protocol=1                      # protocol to use
+                                    # 1: No security  	2: Static WEP
+                                    # 8: WPA	32: WPA2    40:WPA2 Mixed Mode
+    RSNReplayProtection=0           # RSN replay protection 0: disabled, 1: enabled
+    PairwiseUpdateTimeout=100       #Pairwise Handshake update timeout: 100ms
+    PairwiseHandshakeRetries=3      #Pairwise Handshake retries: 3
+    GroupwiseUpdateTimeout=100      #Groupwise Handshake update timeout: 100ms
+    GroupwiseHandshakeRetries=3           #Groupwise Handshake retries: 3
+
+# **** WEP security setting******
+#   KeyIndex=0                      # Index of WEP key to use (0 to 3)
+#   Sample Key configurations are
+#       Key_0="55555"
+#       Key_1=1234567890
+#       Key_2="1234567890123"
+#       Key_3=12345678901234567890123456
+
+# **** Pairwise Cipher setting******
+#    Configure both of the following for Protocol=40
+#    PwkCipherWPA=4                 # Pairwise cipher type
+                                    # 4: TKIP     8: AES CCMP
+                                    # 12: AES CCMP + TKIP
+#    PwkCipherWPA2=8                # Pairwise cipher type
+                                    # 4: TKIP     8: AES CCMP
+                                    # 12: AES CCMP + TKIP
+
+# **** Group Cipher setting******
+
+#    GwkCipher=4                    # group cipher type
+                                    # 4: TKIP     8: AES CCMP
+
+#    PSK="1234567890"               # WPA/WPA2 passphrase
+     GroupRekeyTime= 86400          # Group key re-key interval, in second.
+                                    # 0 mean never re-key
+
+    Enable11n=1                     # 1 to enable, 0 to disable
+    HTCapInfo=0x111c                # HTCapInfo
+                                    # Bit 15-13: Reserved set to 0
+                                    # Bit 12: DSS/CCK mode in 40MHz enable/disable
+                                    # Bit 11-10: Reserved set to 0
+                                    # Bit 9-8: Reserved set to 0x01
+                                    # Bit 7: Reserved set to 0
+                                    # Bit 6: Short GI in 40 Mhz enable/disable
+                                    # Bit 5: Short GI in 20 Mhz enable/disable
+                                    # Bit 4: Green field enable/disble
+                                    # Bit 3-2: Reserved set to 1
+                                    # Bit 1: 20/40 Mhz enable disable.
+                                    # Bit 0: Reserved set to 0
+    AMPDU=0x03                      # AMPDU
+                                    # Bit 7-5: Reserved set to 0
+                                    # Bit 4-2: Minimum MPDU Start spacing
+                                    #          Set to 0 for no restriction
+                                    #          Set to 1 for 1/4 us
+                                    #          Set to 2 for 1/2 us
+                                    #          Set to 3 for 1 us
+                                    #          Set to 4 for 2 us
+                                    #          Set to 5 for 4 us
+                                    #          Set to 6 for 8 us
+                                    #          Set to 7 for 16 us
+                                    # Bit 1-0: Max A-MPDU length
+     HT_MCS_MAP=0x0000ffff          # Bit 7-0: MCS_SET_0
+                                    # Bit 15-8:MCS_SET_1
+#    Enable2040Coex=1                #Enable 20/40 coex feature
+
+                                    #802.11D specific configuration
+    11d_enable=0                    # 0-disable 1-enable
+#   country=US                      # country information
+
+}
+
+
+
+ap_mac_filter={
+    FilterMode=0                    # Mode of filter table
+                                    # 0: filter table is disabled
+                                    # 1: allow MAC address in the filter table to associate
+                                    # 2: block MAC address in the filter table
+    Count=0                         # Number of entries in filter table,up to 16
+#Sample mac settings are
+#    mac_1=00:50:23:45:76:22         # mac address
+#    mac_2=00:34:22:77:46:34         # mac address
+}
+
+# Wmm param setting
+Wmm_parameters={
+    Qos_info=0x80
+    AC_BE
+    Aifsn=1
+    Ecw_max=1
+    Ecw_min=1
+    Tx_op=1
+    AC_BK
+    Aifsn=2
+    Ecw_max=2
+    Ecw_min=2
+    Tx_op=2
+    AC_VI
+    Aifsn=3
+    Ecw_max=3
+    Ecw_min=3
+    Tx_op=3
+    AC_VO
+    Aifsn=4
+    Ecw_max=4
+    Ecw_min=4
+    Tx_op=4
+}
+
diff --git a/wlan_sd8897/mapp/uaputl/config/uaputl_wifidirect.conf b/wlan_sd8897/mapp/uaputl/config/uaputl_wifidirect.conf
new file mode 100644
index 0000000..fa1017c
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/config/uaputl_wifidirect.conf
@@ -0,0 +1,80 @@
+#   File : uaputl_wifidirect.conf
+
+
+ap_config={
+    SSID="DIRECT-"               # SSID for WifiDirect
+    BeaconPeriod=100                # Beacon period in TU
+    Channel=6                       # Radio Channel	6
+#   Channel=0,1                     # auto channel select (MCS mode)
+#   Channel=6,2                     # primary channel 6, secondary channel above.
+#   Channel=6,4                     # primary channel 6, secondary channel below
+    ChanList=1,6,11                 # Scan channel list
+#   AP_MAC=00:34:22:77:46:41        # MAC address of AP
+    Rate=0x8C,0x12,0x18,0x24,0x30,0x48,0x60,0x6c
+                                    # Set of data rate that a station
+                                    # in the BSS may use
+                                    # (in unit of 500 kilobit/s)
+    TxPowerLevel=13                 # Transmit power level in dBm
+    BroadcastSSID=1                 # Broadcast SSID feature
+                                    # 1: Enable  0:Disable
+    RTSThreshold=2347               # RTS threshold value
+    FragThreshold=2346              # Fragmentation threshold value
+    DTIMPeriod=1                    # DTIM period in beacon periods
+    MCBCdataRate=0                  # MCBC rate to use for packet transmission
+                                    # 0:auto
+                                    # >0 fix rate (in unit of 500 kilobit/s)
+    PktFwdCtl=1                     # Packet forwarding control
+                                    # 0: forward all packets to the host
+                                    # 1: firmware handles intr-BSS packets
+    StaAgeoutTimer=1800             # Inactive client station age out timer value
+                                    # in units of 100ms
+    PSStaAgeoutTimer=400            # Inactive client PS station age out timer value
+                                    # in units of 100ms
+    MaxStaNum=7                     # Max number of stations allowed to connect
+    Retrylimit=7                    # Retry limit to use for packet transmissions
+    AuthMode=0                      # 0:Open authentication
+                                    # 1:shared key authentication
+    Protocol=32                     # protocol to use
+                                    # 1: No security  	2: Static WEP
+                                    # 8: WPA	32: WPA2    40:WPA2 Mixed Mode
+    RSNReplayProtection=0           # RSN replay protection 0: disabled, 1: enabled
+    PairwiseUpdateTimeout=2000       #Pairwise Handshake update timeout: 2000ms
+    PairwiseHandshakeRetries=3      #Pairwise Handshake retries: 3
+    GroupwiseUpdateTimeout=2000      #Groupwise Handshake update timeout: 2000ms
+    GroupwiseHandshakeRetries=3           #Groupwise Handshake retries: 3
+
+    PwkCipherWPA2=8                # Pairwise cipher type
+    GwkCipher=8                    # group cipher type
+    PSK="1234567890"               # WPA/WPA2 passphrase
+
+    GroupRekeyTime= 86400          # Group key re-key interval, in second.
+                                   # 0 mean never re-key
+
+    Enable11n=1                     # 1 to enable, 0 to disable
+    HTCapInfo=0x111c                # HTCapInfo
+                                    # Bit 15-13: Reserved set to 0
+                                    # Bit 12: DSS/CCK mode in 40MHz enable/disable
+                                    # Bit 11-10: Reserved set to 0
+                                    # Bit 9-8: Reserved set to 0x01
+                                    # Bit 7: Reserved set to 0
+                                    # Bit 6: Short GI in 40 Mhz enable/disable
+                                    # Bit 5: Short GI in 20 Mhz enable/disable
+                                    # Bit 4: Green field enable/disble
+                                    # Bit 3-2: Reserved set to 1
+                                    # Bit 1: 20/40 Mhz enable disable.
+                                    # Bit 0: Reserved set to 0
+    AMPDU=0x03                      # AMPDU
+                                    # Bit 7-5: Reserved set to 0
+                                    # Bit 4-2: Minimum MPDU Start spacing
+                                    #          Set to 0 for no restriction
+                                    #          Set to 1 for 1/4 us
+                                    #          Set to 2 for 1/2 us
+                                    #          Set to 3 for 1 us
+                                    #          Set to 4 for 2 us
+                                    #          Set to 5 for 4 us
+                                    #          Set to 6 for 8 us
+                                    #          Set to 7 for 16 us
+                                    # Bit 1-0: Max A-MPDU length
+                                    #802.11D specific configuration
+    11d_enable=0                    # 0-disable 1-enable
+}
diff --git a/wlan_sd8897/mapp/uaputl/uapcmd.c b/wlan_sd8897/mapp/uaputl/uapcmd.c
new file mode 100644
index 0000000..6225739
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/uapcmd.c
@@ -0,0 +1,7404 @@
+/** @file  uapcmd.c
+ *
+ *  @brief This file contains the handling of command.
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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/01/08: Initial creation
+****************************************************************************/
+
+/****************************************************************************
+        Header files
+****************************************************************************/
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include "uaputl.h"
+#include "uapcmd.h"
+
+extern struct option cmd_options[];
+/****************************************************************************
+        Local functions
+****************************************************************************/
+/**
+ *  @brief Show usage information for the sys_cfg_ap_mac_address
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_ap_mac_address_usage(void)
+{
+	printf("\nUsage : sys_cfg_ap_mac_address [AP_MAC_ADDRESS]\n");
+	printf("\nIf AP_MAC_ADDRESS is provided, a 'set' is performed, else a 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_ssid command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_ssid_usage(void)
+{
+	printf("\nUsage : sys_cfg_ssid [SSID]\n");
+	printf("\nIf SSID is provided, a 'set' is performed, else a 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_beacon_period
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_beacon_period_usage(void)
+{
+	printf("\nUsage : sys_cfg_beacon_period [BEACON_PERIOD]\n");
+	printf("\nIf BEACON_PERIOD is provided, a 'set' is performed, else a 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_dtim_period
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_dtim_period_usage(void)
+{
+	printf("\nUsage : sys_cfg_dtim_period [DTIM_PERIOD]\n");
+	printf("\nIf DTIM_PERIOD is provided, a 'set' is performed, else a 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the bss_status
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_bss_status_usage(void)
+{
+	printf("\nUsage : sys_cfg_bss_status\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_channel
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_channel_usage(void)
+{
+	printf("\nUsage : sys_cfg_channel [CHANNEL] [MODE]\n");
+	printf("\nIf CHANNEL is provided, a 'set' is performed, else a 'get' is performed.");
+	printf("\n MODE:  band config mode ");
+	printf("\n        Bit 0: ACS mode enable/disable");
+	printf("\n        Bit 1: secondary channel is above primary channel");
+	printf("\n        Bit 2: secondary channel is below primary channel");
+	printf("\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_channel
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_channel_ext_usage(void)
+{
+	printf("\nUsage : sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]\n");
+	printf("\nIf CHANNEL is provided, a 'set' is performed, else a 'get' is performed.");
+	printf("\n BAND:");
+	printf("\n        0 : 2.4GHz operation");
+	printf("\n        1 : 5GHz operation");
+	printf("\n MODE:  band config mode ");
+	printf("\n        Bit 0: ACS mode enable/disable");
+	printf("\n        Bit 1: secondary channel is above primary channel");
+	printf("\n        Bit 2: secondary channel is below primary channel");
+	printf("\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_scan_channels
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_scan_channels_usage(void)
+{
+	printf("\nUsage : sys_cfg_scan_channels [CHANNEL[.BAND]]\n");
+	printf("\nIf CHANNELS and BANDS are provided, a 'set' is performed, else a 'get' is performed.\n");
+	printf("\n BAND : band of operation");
+	printf("\n        0 : 2.4GHZ");
+	printf("\n        1 : 5GHZ\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_rates_ext command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_rates_ext_usage(void)
+{
+	printf("\nUsage : sys_cfg_rates_ext [rates RATES] [mbrate RATE]\n");
+	printf("\nIf 'Rate' provided, a 'set' is performed else a 'get' is performed");
+	printf("\nRATES is provided as a set of data rates, in unit of 500 kilobits");
+	printf("\nA rate with MSB bit is basic rate, i.e 0x82 is basic rate.\n");
+	printf("\nFollowing is the list of supported rates in units of 500 Kbps:");
+	printf("\nDecimal: (2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108)");
+	printf("\nHex: (0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c)");
+	printf("\nBasic rates: (0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc)\n");
+	printf("\nRates 2, 4, 11 and 22 (in units of 500 Kbps) must be present in either of basic or");
+	printf("\nnon-basic rates. If OFDM rates are enabled then 12, 24 and 48 (in units of 500 Kbps)");
+	printf("\nmust be present in either basic or non-basic rates");
+	printf("\nEach rate must be separated by a space.");
+	printf("\nrates followed by RATES for setting operational rates.");
+	printf("\nmbrate followed by RATE for setting multicast and broadcast rate.");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_rates command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_rates_usage(void)
+{
+	printf("\nUsage : sys_cfg_rates [RATES]\n");
+	printf("\n[RATES] is set of data rates in unit of 500 kbps and each rate can be");
+	printf("\nentered in hexadecimal or decimal format. Rates must be separated by");
+	printf("\nspace. Duplicate Rate  fields are not allowed");
+	printf("\nA rate with MSB bit is basic rate, i.e 0x82 is basic rate.");
+	printf("\nFollowing is the list of supported rates in units of 500 Kbps:");
+	printf("\nDecimal: (2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108)");
+	printf("\nHex: (0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c)");
+	printf("\nBasic rates: (0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc)\n");
+	return;
+}
+
+/**
+ *   @brief Show usage information for the sys_cfg_tx_power
+ *    command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_tx_power_usage(void)
+{
+	printf("\nUsage : sys_cfg_tx_power [TX_POWER]\n");
+	printf("\nIf TX_POWER is provided, a 'set' is performed, else a 'get' is performed.");
+	printf("\nTX_POWER is represented in dBm.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_bcast_ssid_ctl
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_bcast_ssid_ctl_usage(void)
+{
+	printf("\nUsage : sys_cfg_bcast_ssid_ctl [0|1]\n");
+	printf("\nOptions: 0     - send empty SSID (length=0) in beacon");
+	printf("\n         1     - Enable SSID broadcast");
+	printf("\n         2     - clear SSID (ACSII 0) in beacon, but keep the original length");
+	printf("\n         empty - Get current SSID broadcast setting\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_rsn_replay_prot
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_rsn_replay_prot_usage(void)
+{
+	printf("\nUsage : sys_cfg_rsn_replay_prot [0|1]\n");
+	printf("\nOptions: 0     - Disable RSN replay protection");
+	printf("\n         1     - Enable  RSN replay protection");
+	printf("\n         empty - Get current RSN replay protection setting\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_preamble_ctl
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_preamble_ctl_usage(void)
+{
+	printf("\nUsage : sys_cfg_preamble_ctl\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_antenna_ctl
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_antenna_ctl_usage(void)
+{
+	printf("\nUsage : sys_cfg_antenna_ctl <ANTENNA> [MODE]\n");
+	printf("\nOptions: ANTENNA : 0 - Rx antenna");
+	printf("\n                   1 - Tx antenna");
+	printf("\n         MODE    : 0       - Antenna A");
+	printf("\n                   1       - Antenna B");
+	printf("\n                   empty   - Get current antenna settings\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_rts_threshold
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_rts_threshold_usage(void)
+{
+	printf("\nUsage : sys_cfg_rts_threshold [RTS_THRESHOLD]\n");
+	printf("\nIf RTS_THRESHOLD is provided, a 'set' is performed, else a 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_frag_threshold
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_frag_threshold_usage(void)
+{
+	printf("\nUsage : sys_cfg_frag_threshold [FRAG_THRESHOLD]\n");
+	printf("\nIf FRAG_THRESHOLD is provided, a 'set' is performed, else a 'get' is performed.");
+	printf("\nFragment threshold should between 256 and 2346.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_tx_beacon_rate
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_tx_beacon_rates_usage(void)
+{
+	printf("\nUsage : sys_cfg_tx_beacon_rate [TX_DATA_RATE]\n");
+	printf("\nOptions: 0     - Auto rate");
+	printf("\n         >0    - Set specified beacon rate");
+	printf("\n         empty - Get current beacon rate");
+	printf("\nFollowing is the list of supported rates in units of 500 Kbps");
+	printf("\nDecimal: (2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108)");
+	printf("\nHex: (0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c)");
+	printf("\nOnly zero or rates currently configured are allowed.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_mcbc_data_rate
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_mcbc_data_rates_usage(void)
+{
+	printf("\nUsage : sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]\n");
+	printf("\nOptions: 0     - Auto rate");
+	printf("\n         >0    - Set specified MCBC data rate");
+	printf("\n         empty - Get current MCBC data rate");
+	printf("\nFollowing is the list of supported rates in units of 500 Kbps");
+	printf("\nDecimal: (2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108)");
+	printf("\nHex: (0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c)");
+	printf("\nOnly zero or one of the basic rates currently configured are allowed.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_auth command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_auth_usage(void)
+{
+	printf("\nUsage : sys_cfg_auth [AUTHMODE]\n");
+	printf("\nOptions: AUTHMODE :     0 - Open authentication");
+	printf("\n                        1 - Shared key authentication");
+	printf("\n                        255 - Auto (Open and Shared key) authentication");
+	printf("\n         empty - Get current authenticaton mode\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_pkt_fwd_ctl command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_pkt_fwd_ctl_usage(void)
+{
+	printf("\nUsage : sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]\n");
+	printf("\nPKT_FWD_CTRL: bit 0 -- Packet forwarding handled by Host (0) or Firmware (1)");
+	printf("\n         bit 1 -- Intra-BSS broadcast packets are allowed (0) or denied (1)");
+	printf("\n         bit 2 -- Intra-BSS unicast packets are allowed (0) or denied (1)");
+	printf("\n         bit 3 -- Inter-BSS unicast packets are allowed (0) or denied (1)");
+	printf("\n         empty - Get current packet forwarding setting\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_sta_ageout_timer
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_sta_ageout_timer_usage(void)
+{
+	printf("\nUsage : sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]\n");
+	printf("\nIf STA_AGEOUT_TIMER is provided, a 'set' is performed, else a 'get' is performed.");
+	printf("\nSTA_AGEOUT_TIMER is represented in units of 100 ms.");
+	printf("\nValue of 0 will mean that stations will never be aged out.");
+	printf("\nThe value should be between 100 and 864000.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_ps_sta_ageout_timer
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_ps_sta_ageout_timer_usage(void)
+{
+	printf("\nUsage : sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]\n");
+	printf("\nIf PS_STA_AGEOUT_TIMER is provided, a 'set' is performed, else a 'get' is performed.");
+	printf("\nPS_STA_AGEOUT_TIMER is represented in units of 100 ms.");
+	printf("\nValue of 0 will mean that stations will never be aged out.");
+	printf("\nThe value should be between 100 and 864000.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_protocol command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_protocol_usage(void)
+{
+	printf("\nUsage : sys_cfg_protocol [PROTOCOL] [AKM_SUITE]\n");
+	printf("\nOptions: PROTOCOL:        1 - No RSN");
+	printf("\n              2 - WEP Static");
+	printf("\n              8 - WPA");
+	printf("\n              32 - WPA2");
+	printf("\n              40 - WPA2 Mixed");
+	printf("\n              empty - Get current protocol");
+	printf("\n          AKM_SUITE: bit 0 - KEY_MGMT_EAP");
+	printf("\n              bit 1 - KEY_MGMT_PSK");
+	printf("\n              bit 2 - KEY_MGMT_NONE");
+	printf("\n              bit 8 - KEY_MGMT_PSK_SHA256\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_wep_key
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_wep_key_usage(void)
+{
+	printf("\nUsage : sys_cfg_wep_key ");
+	printf("[INDEX_0 IS_DEFAULT KEY_0] [INDEX_1 IS_DEFAULT KEY_1] [INDEX_2 IS_DEFAULT KEY_2] [INDEX_3 IS_DEFAULT KEY_3]\n");
+	printf("[Index_0] [Index_1] [Index_2] [Index_3]\n");
+	printf("\nOptions: INDEX_* :      0 - KeyIndex is 0");
+	printf("\n                        1 - KeyIndex is 1");
+	printf("\n                        2 - KeyIndex is 2");
+	printf("\n                        3 - KeyIndex is 3");
+	printf("\n         IS_DEFAULT :   0 - KeyIndex is not the default");
+	printf("\n                        1 - KeyIndex is the default transmit key");
+	printf("\n         KEY_* :        Key value");
+	printf("\n         Index_*:       0 - Get key 0 setting");
+	printf("\n                        1 - Get key 1 setting");
+	printf("\n                        2 - Get key 2 setting");
+	printf("\n                        3 - Get key 3 setting");
+	printf("\n         empty - Get current WEP key settings\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_cipher
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_cipher_usage(void)
+{
+	printf("\nUsage : sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]\n");
+	printf("\nOptions: PAIRWISE_CIPHER:  0 - NONE");
+	printf("\n                           4 - TKIP");
+	printf("\n                           8 - AES CCMP");
+	printf("\n                           12 - AES CCMP + TKIP");
+	printf("\n         GROUP_CIPHER :    0 - NONE");
+	printf("\n                           4 - TKIP");
+	printf("\n                           8 - AES CCMP");
+	printf("\n         empty - Get current cipher settings\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_pwk_cipher
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_pwk_cipher_usage(void)
+{
+	printf("\nUsage : sys_cfg_pwk_cipher [<PROTOCOL>] [PAIRWISE_CIPHER]\n");
+	printf("\nOptions: PROTOCOL :");
+	printf("\n                   8 - WPA");
+	printf("\n                   32 - WPA2");
+	printf("\n         PAIRWISE_CIPHER : ");
+	printf("\n                          4 - TKIP");
+	printf("\n                          8 - AES CCMP");
+	printf("\n                          12 - AES CCMP + TKIP");
+	printf("\n         WPA/TKIP cannot be used when uAP operates in 802.11n mode.\n");
+	printf("\n         If only PROTOCOL is given, pairwise cipher for that protocol is displayed\n");
+	printf("\n         empty - Get current protocol and pairwise cipher settings\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_gwk_cipher
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_gwk_cipher_usage(void)
+{
+	printf("\nUsage : sys_cfg_gwk_cipher [GROUP_CIPHER]\n");
+	printf("\n         GROUP_CIPHER :");
+	printf("\n                       4 - TKIP");
+	printf("\n                       8 - AES CCMP");
+	printf("\n         empty - Get current group cipher settings\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_group_rekey_timer command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_group_rekey_timer_usage(void)
+{
+	printf("\nUsage : sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]\n");
+	printf("\nOptions: GROUP_REKEY_TIME is represented in seconds");
+	printf("\n         empty - Get current group re-key time\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_wpa_passphrase
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_wpa_passphrase_usage(void)
+{
+	printf("\nUsage : sys_cfg_wpa_passphrase [PASSPHRASE]\n");
+	printf("\nIf PASSPHRASE is provided, a 'set' is performed, else a 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sta_filter_table command
+ *
+ *  $return         N/A
+ */
+void
+print_sta_filter_table_usage(void)
+{
+	printf("\nUsage : sta_filter_table <FILTERMODE> <MACADDRESS_LIST>\n");
+	printf("\nOptions: FILTERMODE : 0 - Disable filter table");
+	printf("\n                      1 - allow MAC addresses specified in the allowed list");
+	printf("\n                      2 - block MAC addresses specified in the banned list");
+	printf("\n         MACADDRESS_LIST is the list of MAC addresses to be acted upon. Each");
+	printf("\n                      MAC address must be separated with a space. Maximum of");
+	printf("\n                      16 MAC addresses are supported.");
+	printf("\n         empty - Get current mac filter settings\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_max_sta_num command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_max_sta_num_usage(void)
+{
+	printf("\nUsage : sys_cfg_max_sta_num [STA_NUM]\n");
+	printf("\nIf STA_NUM is provided, a 'set' is performed, else a 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_retry_limit command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_retry_limit_usage(void)
+{
+	printf("\nUsage : sys_cfg_retry_limit [RETRY_LIMIT]\n");
+	printf("\nIf RETRY_LIMIT is provided, a 'set' is performed, else a 'get' is performed.");
+	printf("\nRETRY_LIMIT should be greater than or equal to zero and less than or equal to 14\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_sticky_tim_config command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_sticky_tim_config_usage(void)
+{
+	printf("\nUsage : sys_cfg_sticky_tim_config [ENABLE] [<DURATION> <STICKY_BITMASK>]\n");
+	printf("\nOptions: ENABLE  0 - disable");
+	printf("\n                 1 - enable");
+	printf("\n                 2 - enable with previous values of DURATION and STICKY_BITMASK");
+	printf("\n         DURATION: duration for sticky TIM");
+	printf("\n         STICKY_BITMASK: Bitmask for sticky TIM configuartion");
+	printf("\n         empty - Get current sticky TIM configuration\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_sticky_tim_mac_addr command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_sticky_tim_sta_mac_addr_usage(void)
+{
+	printf("\nUsage : sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]\n");
+	printf("\nOptions: CONTROL: sticky TIM config for given station");
+	printf("\n         STA_MAC_ADDRESS: station MAC address");
+	printf("\n         if only STA_MAC_ADDRESS is given - Get sticky TIM configuration for that station\n");
+	printf("\n         empty - Get current sticky TIM configuration for all associated stations\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_2040_coex command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_2040_coex_usage(void)
+{
+	printf("\nUsage : sys_cfg_2040_coex [ENABLE]\n");
+	printf("\nOptions: ENABLE  0 - disable");
+	printf("\n                 1 - enable");
+	printf("\n         empty - Get current 20/40 BSS coexistence configuration\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_eapol_pwk_hsk command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_eapol_pwk_hsk_usage(void)
+{
+	printf("\nUsage : sys_cfg_eapol_pwk_hsk [<TIMEOUT> <RETRIES>]\n");
+	printf("\nIf TIMEOUT and number of RETRIES are both provided, a 'set' is performed.");
+	printf("\nIf no parameter is provided,a 'get' is performed.");
+	printf("\nTIMEOUT and number of RETRIES should be greater than or equal to zero\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_eapol_gwk_hsk command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_eapol_gwk_hsk_usage(void)
+{
+	printf("\nUsage : sys_cfg_eapol_gwk_hsk [<TIMEOUT> <RETRIES>]\n");
+	printf("\nIf TIMEOUT and number of RETRIES are both provided, a 'set' is performed.");
+	printf("\nIf no parameter is provided,a 'get' is performed.");
+	printf("\nTIMEOUT and number of RETRIES should be greater than or equal to zero\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the cfg_data command
+ *
+ *  $return         N/A
+ */
+void
+print_cfg_data_usage(void)
+{
+	printf("\nUsage : cfg_data <type> [*.conf]\n");
+	printf("\n        type : 2 -- cal data");
+	printf("\n        *.conf : file contain configuration data");
+	printf("\n                 empty - get current configuration data\n");
+	return;
+}
+
+/**
+ *  @brief  Get configured operational rates.
+ *
+ *  @param  rates   Operational rates allowed are
+ *                  stored at this pointer
+ *  @return         Number of basic rates allowed.
+ *                  -1 if a failure
+ */
+int
+get_sys_cfg_rates(t_u8 *rates)
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_rates *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len;
+	int ret = UAP_FAILURE;
+	int i = 0;
+	int rate_cnt = 0;
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_rates) +
+		MAX_DATA_RATES;
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return -1;
+	}
+	memset(buffer, 0, cmd_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_rates *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_RATES_TLV_ID;
+	cmd_buf->action = ACTION_GET;
+	tlv->length = MAX_DATA_RATES;
+
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_RATES_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return -1;
+		}
+
+		/* Copy response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			for (i = 0; i < tlv->length; i++) {
+				if (tlv->operational_rates[i] != 0) {
+					rates[rate_cnt++] =
+						tlv->operational_rates[i];
+				}
+			}
+		} else {
+			printf("ERR:Could not get operational rates!\n");
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return rate_cnt;
+}
+
+/**
+ *  @brief Check rate is valid or not.
+ *
+ *  @param  rate   Rate for check
+ *
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_tx_rate_valid(t_u8 rate)
+{
+	int rate_cnt = 0;
+	int i;
+	t_u8 rates[MAX_DATA_RATES];
+
+	rate_cnt = get_sys_cfg_rates((t_u8 *)&rates);
+	if (rate_cnt > 0) {
+		for (i = 0; i < rate_cnt; i++) {
+			if (rate == (rates[i] & ~BASIC_RATE_SET_BIT)) {
+				return UAP_SUCCESS;
+			}
+		}
+	}
+	return UAP_FAILURE;
+}
+
+/**
+ *  @brief Check mcbc rate is valid or not.
+ *
+ *  @param  rate   Rate for check
+ *
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_mcbc_rate_valid(t_u8 rate)
+{
+	int rate_cnt = 0;
+	int i;
+	t_u8 rates[MAX_DATA_RATES];
+
+	rate_cnt = get_sys_cfg_rates((t_u8 *)&rates);
+	if (rate_cnt > 0) {
+		for (i = 0; i < rate_cnt; i++) {
+			if (rates[i] & BASIC_RATE_SET_BIT) {
+				if (rate == (rates[i] & ~BASIC_RATE_SET_BIT)) {
+					return UAP_SUCCESS;
+				}
+			}
+		}
+	}
+	return UAP_FAILURE;
+}
+
+/****************************************************************************
+        Global functions
+****************************************************************************/
+/**
+ *  @brief Creates a sys_cfg request for AP MAC address
+ *   and sends to the driver
+ *
+ *  Usage: "sys_cfg_ap_mac_address [AP_MAC_ADDRESS]"
+ *          if AP_MAC_ADDRESS is provided, a 'set' is performed,
+ *          else a 'get' is performed.
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_ap_mac_address(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_ap_mac_address *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_ap_mac_address_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc > 1) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_cfg_ap_mac_address_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_ap_mac_address);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_ap_mac_address *)(buffer +
+					sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_AP_MAC_ADDRESS_TLV_ID;
+	tlv->length = ETH_ALEN;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		if ((ret = mac2raw(argv[0], tlv->ap_mac_addr)) != UAP_SUCCESS) {
+			printf("ERR: %s Address \n",
+			       ret == UAP_FAILURE ? "Invalid MAC" : ret ==
+			       UAP_RET_MAC_BROADCAST ? "Broadcast" :
+			       "Multicast");
+			free(buffer);
+			return UAP_FAILURE;
+		}
+	}
+	endian_convert_tlv_header_out(tlv);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_AP_MAC_ADDRESS_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("AP MAC address = ");
+				print_mac(tlv->ap_mac_addr);
+				printf("\n");
+			} else {
+				printf("AP MAC address setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get AP MAC address!\n");
+			} else {
+				printf("ERR:Could not set AP MAC address!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for SSID
+ *   and sends to the driver
+ *
+ *  Usage: "sys_cfg_ssid [SSID]"
+ *          if SSID is provided, a 'set' is performed
+ *          else a 'get' is performed
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_ssid(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_ssid *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	t_u8 ssid[33];
+
+	argc--;
+	argv++;
+
+	/* Check arguments */
+	if (argc > 1) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_cfg_ssid_usage();
+		return UAP_FAILURE;
+	}
+
+	if (argc == 0) {
+		/* Initialize the command length */
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_ssid) +
+			MAX_SSID_LENGTH;
+	} else {
+		if (strlen(argv[0]) > MAX_SSID_LENGTH) {
+			printf("ERR:SSID too long.\n");
+			return UAP_FAILURE;
+		}
+		/* Initialize the command length */
+		if (argv[0][1] == '"') {
+			argv[0]++;
+		}
+		if (argv[0][strlen(argv[0])] == '"') {
+			argv[0][strlen(argv[0])] = '\0';
+		}
+		if (!strlen(argv[0])) {
+			printf("ERR:NULL SSID not allowed.\n");
+			return UAP_FAILURE;
+		}
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_ssid) +
+			strlen(argv[0]);
+	}
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_ssid *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_SSID_TLV_ID;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+		tlv->length = MAX_SSID_LENGTH;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->length = strlen(argv[0]);
+		memcpy(tlv->ssid, argv[0], tlv->length);
+	}
+
+	endian_convert_tlv_header_out(tlv);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	endian_convert_tlv_header_in(tlv);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_SSID_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				memset(ssid, 0, sizeof(ssid));
+				memcpy(ssid, tlv->ssid, tlv->length);
+				printf("SSID = %s\n", ssid);
+			} else {
+				printf("SSID setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get SSID!\n");
+			} else {
+				printf("ERR:Could not set SSID!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for beacon period
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_beacon_period [BEACON_PERIOD]"
+ *           if BEACON_PERIOD is provided, a 'set' is performed
+ *           else a 'get' is performed.
+ *
+ *           BEACON_PERIOD is represented in ms
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_beacon_period(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_beacon_period *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_beacon_period_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc && is_input_valid(BEACONPERIOD, argc, argv) != UAP_SUCCESS) {
+		print_sys_cfg_beacon_period_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_beacon_period);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_beacon_period *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_BEACON_PERIOD_TLV_ID;
+	tlv->length = 2;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->beacon_period_ms = (t_u16)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->beacon_period_ms = uap_cpu_to_le16(tlv->beacon_period_ms);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->beacon_period_ms = uap_le16_to_cpu(tlv->beacon_period_ms);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_BEACON_PERIOD_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("Beacon period = %d\n",
+				       tlv->beacon_period_ms);
+			} else {
+				printf("Beacon period setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get beacon period!\n");
+			} else {
+				printf("ERR:Could not set beacon period!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for DTIM period
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_dtim_period [DTIM_PERIOD]"
+ *           if DTIM_PERIOD is provided, a 'set' is performed
+ *           else a 'get' is performed
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_dtim_period(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_dtim_period *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_dtim_period_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && (is_input_valid(DTIMPERIOD, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_dtim_period_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_dtim_period);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_dtim_period *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_DTIM_PERIOD_TLV_ID;
+	tlv->length = 1;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->dtim_period = (t_u8)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_DTIM_PERIOD_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("DTIM period = %d\n", tlv->dtim_period);
+			} else {
+				printf("DTIM period setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get DTIM period!\n");
+			} else {
+				printf("ERR:Could not set DTIM period!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for bss_status
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_bss_status"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_bss_status(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_bss_status *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_bss_status_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 0) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_cfg_bss_status_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_bss_status);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_bss_status *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_BSS_STATUS_TLV_ID;
+	tlv->length = 2;
+	cmd_buf->action = ACTION_GET;
+
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->bss_status = uap_le16_to_cpu(tlv->bss_status);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_BSS_STATUS_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("BSS status = %s\n",
+			       (tlv->bss_status == 0) ? "stopped" : "started");
+		} else {
+			printf("ERR:Could not get BSS status!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/** DFS Radar starting channel FCC */
+#define DFS_FCC_RADAR_CHANNEL_START      52
+/** DFS Radar ending channel FCC */
+#define DFS_FCC_RADAR_CHANNEL_END       140
+
+/** DFS Radar starting channel ETSI */
+#define DFS_ETSI_RADAR_CHANNEL_START     52
+/** DFS Radar ending channel ETSI */
+#define DFS_ETSI_RADAR_CHANNEL_END      140
+
+/** DFS Radar starting channel JAPAN */
+#define DFS_JAPAN_RADAR_CHANNEL_START    52
+/** DFS Radar ending channel JAPAN */
+#define DFS_JAPAN_RADAR_CHANNEL_END     140
+
+/** list of RegDomain values */
+typedef enum {
+	RegDomain_Null = 0x00,
+	RegDomain_FCC = 0x01,
+	RegDomain_ETSI = 0x02,
+	RegDomain_MIC = 0x03,
+	RegDomain_Other = 0xFF,
+} regdomain_e;
+
+/** mapping of region and domain code */
+typedef struct {
+    /** region */
+	t_u8 region[COUNTRY_CODE_LEN];
+    /** domain code */
+	regdomain_e code;
+} region_code_mapping_t;
+
+static region_code_mapping_t region_code_mapping[] = {
+	{"US ", RegDomain_FCC},	/* US FCC      0x10     */
+	{"SG ", RegDomain_FCC},	/* Singapore   0x10   */
+	{"EU ", RegDomain_ETSI},	/* ETSI        0x30      */
+	{"AU ", RegDomain_ETSI},	/* Australia   0x30  */
+	{"KR ", RegDomain_ETSI},	/* Republic Of Korea 0x30 */
+	{"JP ", RegDomain_MIC},	/* Japan       0x40 */
+	{"J1 ", RegDomain_MIC},	/* Japan1      0x41 */
+};
+
+/**
+ *  @brief This function converts region string to region code
+ *
+ *  @param region_string         Region string
+ *
+ *  @return     Region code
+ */
+regdomain_e
+region_string_2_region_code(char *region_string)
+{
+	t_u8 i;
+	t_u8 size = sizeof(region_code_mapping) / sizeof(region_code_mapping_t);
+
+	for (i = 0; i < COUNTRY_CODE_LEN && region_string[i]; i++) {
+		region_string[i] = toupper(region_string[i]);
+	}
+
+	for (i = 0; i < size; i++) {
+		if (!memcmp(region_string,
+			    region_code_mapping[i].region, COUNTRY_CODE_LEN)) {
+			return (region_code_mapping[i].code);
+		}
+	}
+
+	/* default is US */
+	return (region_code_mapping[0].code);
+}
+
+/**
+ *  @brief Checks if channel is dfs channel and allow only if 11h is enabled.
+ *
+ *  @param channel  Channel
+ *  @param country  Country
+ *  @return         UAP_FAILURE/UAP_SUCCESS
+ */
+int
+is_dfs_channel(int channel, char *country)
+{
+	regdomain_e region;
+	t_u8 DFS_RadarDetectChannelStart = DFS_FCC_RADAR_CHANNEL_START;
+	t_u8 DFS_RadarDetectChannelEnd = DFS_FCC_RADAR_CHANNEL_END;
+
+	region = region_string_2_region_code(country);
+	/* set radar start channel and end channel */
+	switch (region) {
+	default:		/* use FCC as default setting */
+	case RegDomain_FCC:
+		DFS_RadarDetectChannelStart = DFS_FCC_RADAR_CHANNEL_START;
+		DFS_RadarDetectChannelEnd = DFS_FCC_RADAR_CHANNEL_END;
+		break;
+	case RegDomain_ETSI:
+		DFS_RadarDetectChannelStart = DFS_ETSI_RADAR_CHANNEL_START;
+		DFS_RadarDetectChannelEnd = DFS_ETSI_RADAR_CHANNEL_END;
+		break;
+	case RegDomain_MIC:
+		DFS_RadarDetectChannelStart = DFS_JAPAN_RADAR_CHANNEL_START;
+		DFS_RadarDetectChannelEnd = DFS_JAPAN_RADAR_CHANNEL_END;
+		break;
+	}
+	if (channel < DFS_RadarDetectChannelStart
+	    || channel > DFS_RadarDetectChannelEnd) {
+		return UAP_FAILURE;
+	}
+
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Checks if channel is valid for given 11d domain.
+ *
+ *  @param channel  Channel
+ *  @param band     Band
+ *  @param set_domain Flag to indicate update domain info with this channel
+ *  @return         UAP_FAILURE/UAP_SUCCESS
+ */
+int
+check_channel_validity_11d(int channel, int band, int set_domain)
+{
+	apcmdbuf_cfg_80211d *cmd_buf = NULL;
+	ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS];
+	t_u8 *buf = NULL;
+	t_u16 cmd_len;
+	t_u16 buf_len = 0;
+	int ret = UAP_FAILURE;
+	int i, j, found = 0;
+	t_u8 no_of_sub_band = 0;
+	char country[4] = { ' ', ' ', 0, 0 };
+
+	buf_len = sizeof(apcmdbuf_cfg_80211d);
+	buf_len += MAX_SUB_BANDS * sizeof(ieeetypes_subband_set_t);
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_cfg_80211d *)buf;
+	cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t));
+
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->result = 0;
+	cmd_buf->seq_num = 0;
+	cmd_buf->action = ACTION_GET;
+	cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
+	cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
+
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf->result == CMD_SUCCESS) {
+			/* Check channel against US if country code is not set */
+			if (!
+			    (cmd_buf->domain.country_code[0] ||
+			     cmd_buf->domain.country_code[1] ||
+			     cmd_buf->domain.country_code[2])) {
+				country[0] = 'U';
+				country[1] = 'S';
+				country[2] = '\0';
+				/* Do not send this country code to FW though */
+				set_domain = 0;
+			} else {
+				country[0] = cmd_buf->domain.country_code[0];
+				country[1] = cmd_buf->domain.country_code[1];
+			}
+			if (cmd_buf->domain.country_code[2] == 'I') {
+				if ((channel != 36) && (channel != 40) &&
+				    (channel != 44) && (channel != 48)) {
+					printf("ERR: Channel not valid for indoor operation!\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+			}
+			if (is_dfs_channel(channel, country) == UAP_SUCCESS) {
+				printf("DFS channel selected.\n");
+			}
+			no_of_sub_band =
+				parse_domain_file(country, band, sub_bands,
+						  NULL);
+			/* copy third character of country code here as domain file cannot handle it */
+			country[2] = cmd_buf->domain.country_code[2];
+			if (no_of_sub_band == UAP_FAILURE) {
+				printf("Parsing of domain configuration file failed\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+
+			for (i = 0; i < no_of_sub_band; i++) {
+				for (j = 0; j < sub_bands[i].no_of_chan; j++) {
+					if (channel ==
+					    (sub_bands[i].first_chan + j)) {
+						found = 1;
+						break;
+					}
+				}
+				if (found)
+					break;
+			}
+
+			if (!found) {
+				printf("ERR:Invalid channel %d for given domain!\n", channel);
+				ret = UAP_FAILURE;
+				goto done;
+			}
+		} else {
+			printf("ERR:Command Response incorrect!\n");
+			ret = UAP_FAILURE;
+			goto done;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+		goto done;
+	}
+	if (found && set_domain) {
+		/*  If channel is valid then set domain_info with new band */
+		memset(buf, 0, buf_len);
+		buf_len =
+			sizeof(apcmdbuf_cfg_80211d) +
+			no_of_sub_band * sizeof(ieeetypes_subband_set_t);
+		cmd_buf = (apcmdbuf_cfg_80211d *)buf;
+		cmd_len = buf_len;
+		cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+		cmd_buf->result = 0;
+		cmd_buf->seq_num = 0;
+		cmd_buf->action = ACTION_SET;
+		cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
+		cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
+
+		cmd_buf->domain.tag = uap_cpu_to_le16(TLV_TYPE_DOMAIN);
+		cmd_buf->domain.length = uap_cpu_to_le16(sizeof(domain_param_t)
+							 - BUF_HEADER_SIZE +
+							 (no_of_sub_band *
+							  sizeof
+							  (ieeetypes_subband_set_t)));
+
+		memset(cmd_buf->domain.country_code, ' ',
+		       sizeof(cmd_buf->domain.country_code));
+		memcpy(cmd_buf->domain.country_code, country, strlen(country));
+		memcpy(cmd_buf->domain.subband, sub_bands,
+		       no_of_sub_band * sizeof(ieeetypes_subband_set_t));
+
+		ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+		if (ret == UAP_SUCCESS) {
+			if (cmd_buf->result == CMD_SUCCESS) {
+				ret = UAP_SUCCESS;
+			} else {
+				printf("ERR:Command Response incorrect!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+		} else {
+			printf("ERR:Command sending failed!\n");
+			ret = UAP_FAILURE;
+			goto done;
+		}
+	}
+done:
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for channel
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_channel [CHANNEL] [MODE]"
+ *           if CHANNEL is provided, a 'set' is performed
+ *           else a 'get' is performed
+ *           if MODE is provided, a 'set' is performed with
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_channel(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_channel_config *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	int mode = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_channel_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc && is_input_valid(CHANNEL, argc, argv) != UAP_SUCCESS) {
+		print_sys_cfg_channel_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_channel_config);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_channel_config *)(buffer +
+					sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_CHANNELCONFIG_TLV_ID;
+	tlv->length = sizeof(tlvbuf_channel_config) - TLVHEADER_LEN;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		if (argc == 1) {
+			tlv->chan_number = (t_u8)atoi(argv[0]);
+			memset(&(tlv->bandcfg), 0, sizeof(tlv->bandcfg));
+		} else {
+			mode = atoi(argv[1]);
+			memset(&(tlv->bandcfg), 0, sizeof(tlv->bandcfg));
+			if (mode & BITMAP_ACS_MODE) {
+				int mode;
+				if (uap_ioctl_dfs_repeater_mode(&mode) ==
+				    UAP_SUCCESS) {
+					if (mode) {
+						printf("ERR: ACS in DFS Repeater mode" " is not allowed\n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+				}
+				tlv->bandcfg.scanMode = SCAN_MODE_ACS;
+			}
+			if (mode & BITMAP_CHANNEL_ABOVE)
+				tlv->bandcfg.chan2Offset = SEC_CHAN_ABOVE;
+			if (mode & BITMAP_CHANNEL_BELOW)
+				tlv->bandcfg.chan2Offset = SEC_CHAN_BELOW;
+			tlv->chan_number = (t_u8)atoi(argv[0]);
+		}
+		if (atoi(argv[0]) > MAX_CHANNELS_BG) {
+			tlv->bandcfg.chanBand = BAND_5GHZ;
+		}
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_CHANNELCONFIG_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("Mode    = %s\n",
+				       (tlv->bandcfg.scanMode ==
+					SCAN_MODE_ACS) ? "ACS" : "Manual");
+				printf("Channel = %d\n", tlv->chan_number);
+				if (tlv->bandcfg.chan2Offset == SEC_CHAN_NONE)
+					printf("no secondary channel\n");
+				else if (tlv->bandcfg.chan2Offset ==
+					 SEC_CHAN_ABOVE)
+					printf("secondary channel is above primary channel\n");
+				else if (tlv->bandcfg.chan2Offset ==
+					 SEC_CHAN_BELOW)
+					printf("secondary channel is below primary channel\n");
+			} else {
+				printf("Channel setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get channel!\n");
+			} else {
+				printf("ERR:Could not set channel!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for channel
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]"
+ *           if CHANNEL is provided, a 'set' is performed
+ *           else a 'get' is performed
+ *           if BAND is provided, a 'set' is performed with band info(2.4GHz/5GHz)
+ *           if MODE is provided, a 'set' is performed with mode (ACS/secondary channel)
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_channel_ext(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_channel_config *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	int mode = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_channel_ext_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc && is_input_valid(CHANNEL_EXT, argc, argv) != UAP_SUCCESS) {
+		print_sys_cfg_channel_ext_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_channel_config);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_channel_config *)(buffer +
+					sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_CHANNELCONFIG_TLV_ID;
+	tlv->length = sizeof(tlvbuf_channel_config) - TLVHEADER_LEN;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->chan_number = (t_u8)atoi(argv[0]);
+		if (argc == 1) {
+			if (atoi(argv[0]) > MAX_CHANNELS_BG)
+				tlv->bandcfg.chanBand = BAND_5GHZ;
+		} else {
+			if (atoi(argv[1]) == 0) {
+				tlv->bandcfg.chanBand = BAND_2GHZ;
+			} else {
+				tlv->bandcfg.chanBand = BAND_5GHZ;
+			}
+			if (argc == 3) {
+				mode = atoi(argv[2]);
+				if (mode & BITMAP_ACS_MODE) {
+					int mode;
+					if (uap_ioctl_dfs_repeater_mode(&mode)
+					    == UAP_SUCCESS) {
+						if (mode) {
+							printf("ERR: ACS in DFS Repeater mode" " is not allowed\n");
+							ret = UAP_FAILURE;
+							goto done;
+						}
+					}
+					tlv->bandcfg.scanMode = SCAN_MODE_ACS;
+				}
+				if (mode & BITMAP_CHANNEL_ABOVE)
+					tlv->bandcfg.chan2Offset =
+						SEC_CHAN_ABOVE;
+				if (mode & BITMAP_CHANNEL_BELOW)
+					tlv->bandcfg.chan2Offset =
+						SEC_CHAN_BELOW;
+			}
+		}
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_CHANNELCONFIG_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("Mode    = %s\n",
+				       (tlv->bandcfg.scanMode ==
+					SCAN_MODE_ACS) ? "ACS" : "Manual");
+				printf("Channel = %d\n", tlv->chan_number);
+				printf("Band    = %s\n",
+				       (tlv->bandcfg.chanBand ==
+					BAND_5GHZ) ? "5GHz" : "2.4GHz");
+				if (tlv->bandcfg.chan2Offset == SEC_CHAN_NONE)
+					printf("no secondary channel\n");
+				else if (tlv->bandcfg.chan2Offset ==
+					 SEC_CHAN_ABOVE)
+					printf("secondary channel is above primary channel\n");
+				else if (tlv->bandcfg.chan2Offset ==
+					 SEC_CHAN_BELOW)
+					printf("secondary channel is below primary channel\n");
+			} else {
+				printf("Channel setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get channel!\n");
+			} else {
+				printf("ERR:Could not set channel!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for channel list
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_scan_channels [CHANNEL[.BAND]]"
+ *           if CHANNEL and BAND are provided, a 'set' is performed
+ *           else a 'get' is performed
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_scan_channels(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_channel_list *tlv = NULL;
+	channel_list *pchan_list = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_FAILURE;
+	int opt;
+	int i;
+	int scan_channels_band;
+	int chan_number = 0;
+	int band_flag = -1;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_scan_channels_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc && is_input_valid(SCANCHANNELS, argc, argv) != UAP_SUCCESS) {
+		print_sys_cfg_scan_channels_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	if (argc == 0)
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) +
+			sizeof(tlvbuf_channel_list) +
+			sizeof(channel_list) * MAX_CHANNELS;
+	else
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) +
+			sizeof(tlvbuf_channel_list) +
+			sizeof(channel_list) * argc;
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* LOCATE HEADERS */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_channel_list *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_CHANNELLIST_TLV_ID;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+		tlv->length = sizeof(channel_list) * MAX_CHANNELS;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->length = sizeof(channel_list) * argc;
+		pchan_list = tlv->chan_list;
+		for (i = 0; i < argc; i++) {
+			band_flag = -1;
+			sscanf(argv[i], "%d.%d", &chan_number, &band_flag);
+			pchan_list->chan_number = chan_number;
+			pchan_list->bandcfg.chanBand = BAND_2GHZ;
+			if (((band_flag != -1) && (band_flag)) ||
+			    (chan_number > MAX_CHANNELS_BG)) {
+				pchan_list->bandcfg.chanBand = BAND_5GHZ;
+			}
+			scan_channels_band = BAND_B | BAND_G;
+			if ((scan_channels_band != BAND_A) &&
+			    (pchan_list->bandcfg.chanBand == BAND_5GHZ)) {
+				scan_channels_band = BAND_A;
+			}
+
+			if (check_channel_validity_11d
+			    (pchan_list->chan_number, scan_channels_band,
+			     0) == UAP_FAILURE) {
+				return UAP_FAILURE;
+			}
+			pchan_list++;
+		}
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_CHANNELLIST_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("Channels List = ");
+				if (tlv->length % sizeof(channel_list)) {
+					printf("Error: Length mismatch\n");
+					free(buffer);
+					return UAP_FAILURE;
+				}
+				pchan_list = tlv->chan_list;
+				for (i = 0;
+				     (unsigned int)i <
+				     (tlv->length / sizeof(channel_list));
+				     i++) {
+					printf("\n%d\t%sGHz",
+					       pchan_list->chan_number,
+					       (pchan_list->bandcfg.chanBand ==
+						BAND_5GHZ) ? "5" : "2.4");
+					pchan_list++;
+				}
+				printf("\n");
+			} else {
+				printf("Scan Channel List setting successful\n");
+			}
+		} else {
+			printf("ERR:Could not %s scan channel list!\n",
+			       argc ? "SET" : "GET");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Parser for sys_cfg_rates_ext input
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @param output   Stores indexes for "rates, mbrate and urate"
+ *                  arguments
+ *
+ *                  e.g.,
+ *
+ *                  "rates 0x82 4 16 22 0x30 mbrate 2 urate 16"
+ *
+ *                  will have output array as
+ *
+ *                          start_index end_index
+ *                  rates       0           5
+ *                  mbrate      6           7
+ *                  urate       8           9
+ *
+ *  @return         NA
+ *
+ */
+void
+parse_input(int argc, char **argv, int output[3][2])
+{
+	int i, j, k = 0;
+	char *keywords[3] = { "rates", "mbrate", "urate" };
+
+	for (i = 0; i < 3; i++)
+		output[i][0] = -1;
+
+	for (i = 0; i < argc; i++) {
+		for (j = 0; j < 3; j++) {
+			if (strcmp(argv[i], keywords[j]) == 0) {
+				output[j][1] = output[j][0] = i;
+				k = j;
+				break;
+			}
+		}
+		output[k][1] += 1;
+	}
+}
+
+/**
+ *  @brief Creates a sys_cfg request for setting data_rates, MCBC and
+ *   TX data rates.
+ *
+ *   Usage: "sys_cfg_rates_ext  [RATES]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_rates_ext(int argc, char *argv[])
+{
+	int i, j = 0, found = 0;
+	int opt;
+	int rflag = 0, mflag = 0, uflag = 0;
+	char *argv_rate[14];
+	int argc_rate = 0;
+	char *argv_mrate[1];
+	int mrate_found = UAP_FAILURE;
+	t_u8 *tlv_buf = NULL;
+	tlvbuf_mcbc_data_rate *tlv_mrate = NULL;
+	tlvbuf_rates *tlv_rate = NULL;
+	t_u8 *buffer = NULL;
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	int ret = UAP_SUCCESS;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int output[3][2];
+	char *keywords[3] = { "rates", "mbrate" };
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_rates_ext_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc) {
+		/*
+		 * SET
+		 */
+		parse_input(argc, argv, output);
+
+		for (i = 0; i < 3; i++) {
+			if (output[i][0] == -1) {
+				for (j = 0; j < 3; j++) {
+					if (output[j][0] == 0)
+						found = 1;
+				}
+				if (!found) {
+					printf("%s keyword not specified!\n",
+					       keywords[i]);
+					ret = UAP_FAILURE;
+					goto done;
+				}
+			}
+		}
+		/*
+		 * Rate
+		 */
+		if ((output[0][0] != -1) && (output[0][1] > output[0][0])) {
+			rflag = 1;
+			i = 0;
+			for (j = (output[0][0] + 1); j < output[0][1]; j++) {
+				argv_rate[i] =
+					(char *)malloc(sizeof(char) *
+						       (strlen(argv[j]) + 1));
+				memset(argv_rate[i], 0,
+				       sizeof(char) * (strlen(argv[j]) + 1));
+				strncpy(argv_rate[i], argv[j], strlen(argv[j]));
+				argc_rate = ++i;
+			}
+		}
+
+		/*
+		 * mrate
+		 */
+
+		if ((output[1][0] != -1) && (output[1][1] > output[1][0])) {
+			if ((output[1][1] - output[1][0]) != 2) {
+				printf("\nERR: Invalid mrate input");
+				print_sys_cfg_rates_ext_usage();
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			mflag = 1;
+			argv_mrate[0] =
+				(char *)malloc(sizeof(char) *
+					       (strlen(argv[j]) + 1));
+			memset(argv_mrate[0], 0,
+			       sizeof(char) * (strlen(argv[j]) + 1));
+			strncpy(argv_mrate[0], argv[output[1][0] + 1],
+				strlen(argv[j]));
+		}
+		if (!rflag && !mflag & !uflag) {
+			printf("ERR: Invalid input\n");
+			print_sys_cfg_rates_ext_usage();
+			ret = UAP_FAILURE;
+			goto done;
+		}
+
+		if (rflag &&
+		    is_input_valid(RATE, argc_rate, argv_rate) != UAP_SUCCESS) {
+			printf("ERR: Invalid RATE\n");
+			print_sys_cfg_rates_ext_usage();
+			ret = UAP_FAILURE;
+			goto done;
+		}
+
+		if (mflag &&
+		    is_input_valid(MCBCDATARATE, 1,
+				   argv_mrate) != UAP_SUCCESS) {
+			printf("ERR: Invalid MCBC RATE\n");
+			print_sys_cfg_rates_ext_usage();
+			ret = UAP_FAILURE;
+			goto done;
+		}
+
+		if (!rflag && (mflag || uflag)) {
+			/*
+			 * Check mrate and urate wrt old Rates
+			 */
+			if (mflag && A2HEXDECIMAL(argv_mrate[0]) &&
+			    is_mcbc_rate_valid(A2HEXDECIMAL(argv_mrate[0])) !=
+			    UAP_SUCCESS) {
+				printf("ERR: invalid MCBC data rate.");
+				print_sys_cfg_rates_ext_usage();
+				ret = UAP_FAILURE;
+				goto done;
+			}
+		} else if (rflag && (mflag || uflag)) {
+			/*
+			 * Check mrate and urate wrt new Rates
+			 */
+			for (i = 0; i < argc_rate; i++) {
+				/*
+				 * MCBC rate must be from Basic rates
+				 */
+				if (mflag && !mrate_found &&
+				    A2HEXDECIMAL(argv_rate[i]) &
+				    BASIC_RATE_SET_BIT) {
+					if (A2HEXDECIMAL(argv_mrate[0]) ==
+					    (A2HEXDECIMAL(argv_rate[i]) &
+					     ~BASIC_RATE_SET_BIT)) {
+						mrate_found = UAP_SUCCESS;
+					}
+				}
+			}
+
+			if (mflag && A2HEXDECIMAL(argv_mrate[0]) &&
+			    !(mrate_found == UAP_SUCCESS)) {
+				printf("ERR: mrate not valid\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+		}
+		/* Post-parsing */
+		cmd_len = sizeof(apcmdbuf_sys_configure);
+		if (rflag)
+			cmd_len += sizeof(tlvbuf_rates) + argc_rate;
+		if (mflag)
+			cmd_len += sizeof(tlvbuf_mcbc_data_rate);
+	} else {
+		/* GET */
+		cmd_len = sizeof(apcmdbuf_sys_configure)
+			+ sizeof(tlvbuf_rates) + MAX_RATES +
+			sizeof(tlvbuf_mcbc_data_rate);
+	}
+
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Fill the command buffer */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = argc ? ACTION_SET : ACTION_GET;
+	tlv_buf = buffer + sizeof(apcmdbuf_sys_configure);
+	/* Locate headers */
+	if (rflag || (!argc)) {
+		tlv_rate =
+			(tlvbuf_rates *)(buffer +
+					 sizeof(apcmdbuf_sys_configure));
+		tlv_rate->tag = MRVL_RATES_TLV_ID;
+		tlv_rate->length = argc ? argc_rate : MAX_RATES;
+		for (i = 0; i < argc_rate; i++) {
+			tlv_rate->operational_rates[i] =
+				(t_u8)A2HEXDECIMAL(argv_rate[i]);
+		}
+		tlv_buf += tlv_rate->length + sizeof(tlvbuf_rates);
+		endian_convert_tlv_header_out(tlv_rate);
+	}
+	if (mflag || (!argc)) {
+		tlv_mrate = (tlvbuf_mcbc_data_rate *)tlv_buf;
+		tlv_mrate->tag = MRVL_MCBC_DATA_RATE_TLV_ID;
+		tlv_mrate->length = 2;
+		tlv_mrate->mcbc_datarate = 0;
+		if (mflag) {
+			tlv_mrate->mcbc_datarate =
+				(t_u16)A2HEXDECIMAL(argv_mrate[0])
+				& ~BASIC_RATE_SET_BIT;
+			tlv_mrate->mcbc_datarate =
+				uap_cpu_to_le16(tlv_mrate->mcbc_datarate);
+		}
+		tlv_buf += sizeof(tlvbuf_mcbc_data_rate);
+		endian_convert_tlv_header_out(tlv_mrate);
+	}
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	tlv_buf = buffer + sizeof(apcmdbuf_sys_configure);
+
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response! cmd_code=%x\n",
+			       cmd_buf->cmd_code);
+			ret = UAP_FAILURE;
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc) {
+				printf("Rates setting successful\n");
+			} else {
+				print_tlv((t_u8 *)tlv_buf,
+					  cmd_buf->size -
+					  sizeof(apcmdbuf_sys_configure) +
+					  BUF_HEADER_SIZE);
+			}
+		} else {
+			printf("ERR:Could not %s operational rates!\n",
+			       argc ? "set" : "get");
+			if (argc)
+				printf("operational rates only allow to set before bss start.\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (rflag) {
+		for (i = 0; i < argc_rate; i++) {
+			free(argv_rate[i]);
+		}
+	}
+	if (mflag)
+		free(argv_mrate[0]);
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for data rates
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_rates  [RATES]"
+ *
+ *           RATES is provided as a set of data rates, in
+ *           unit of 500 kilobits/s.
+ *           Maximum 12 rates can be provided.
+ *
+ *           if no RATE is provided, then it gets configured rates
+ *
+ *           Each rate must be separated by a space
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_rates(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_rates *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int i = 0;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_rates_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc && is_input_valid(RATE, argc, argv) != UAP_SUCCESS) {
+		print_sys_cfg_rates_usage();
+		return UAP_FAILURE;
+	}
+	if (argc == 0) {
+		/* Initialize the command length */
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_rates) +
+			MAX_RATES;
+	} else {
+		/* Initialize the command length */
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_rates) +
+			argc;
+	}
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_rates *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_RATES_TLV_ID;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+		tlv->length = MAX_RATES;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->length = argc;
+		for (i = 0; i < tlv->length; i++) {
+			tlv->operational_rates[i] = (t_u8)A2HEXDECIMAL(argv[i]);
+		}
+	}
+
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (uap_le16_to_cpu(tlv->tag) != MRVL_RATES_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, uap_le16_to_cpu(tlv->tag));
+			free(buffer);
+			return UAP_FAILURE;
+		}
+
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				print_rate(tlv);
+			} else {
+				printf("Rates setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get operational rates!\n");
+			} else {
+				printf("ERR:Could not set operational rates!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Checks if tx power is valid for given 11d domain.
+ *
+ *  @param tx_pwr  tx power
+ *  @return         UAP_FAILURE/UAP_SUCCESS
+ */
+int
+check_tx_pwr_validity_11d(t_u8 tx_pwr)
+{
+	apcmdbuf_sys_configure *cmd_buf1 = NULL;
+	apcmdbuf_cfg_80211d *cmd_buf2 = NULL;
+	tlvbuf_channel_config *tlv = NULL;
+	ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS];
+	t_u8 *buf = NULL;
+	t_u16 cmd_len;
+	t_u16 buf_len = 0;
+	int ret = UAP_FAILURE;
+	int i, found = 0, band = BAND_B | BAND_G;
+	t_u8 no_of_sub_band = 0, channel = 0;
+	char country[4] = { ' ', ' ', 0, 0 };
+
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_channel_config);
+
+	/* Initialize the command buffer */
+	buf = (t_u8 *)malloc(cmd_len);
+
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, cmd_len);
+
+	/* Locate headers */
+	cmd_buf1 = (apcmdbuf_sys_configure *)buf;
+	tlv = (tlvbuf_channel_config *)(buf + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf1->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf1->size = cmd_len;
+	cmd_buf1->seq_num = 0;
+	cmd_buf1->result = 0;
+	tlv->tag = MRVL_CHANNELCONFIG_TLV_ID;
+	tlv->length = sizeof(tlvbuf_channel_config) - TLVHEADER_LEN;
+	cmd_buf1->action = ACTION_GET;
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf1, &cmd_len, cmd_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf1->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_CHANNELCONFIG_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf1->cmd_code, tlv->tag);
+			free(buf);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf1->result == CMD_SUCCESS) {
+			channel = tlv->chan_number;
+		} else {
+			printf("ERR:Could not get channel!\n");
+			free(buf);
+			return UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+		free(buf);
+		return UAP_FAILURE;
+	}
+	/* free current buffer */
+	free(buf);
+
+	if (channel > MAX_CHANNELS_BG)
+		band = BAND_A;
+
+	/* initialize second command length and buffer */
+	buf_len = sizeof(apcmdbuf_cfg_80211d);
+	buf_len += MAX_SUB_BANDS * sizeof(ieeetypes_subband_set_t);
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+	/* Locate headers */
+	cmd_buf2 = (apcmdbuf_cfg_80211d *)buf;
+	cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t));
+
+	cmd_buf2->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf2->result = 0;
+	cmd_buf2->seq_num = 0;
+	cmd_buf2->action = ACTION_GET;
+	cmd_buf2->action = uap_cpu_to_le16(cmd_buf2->action);
+	cmd_buf2->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
+
+	ret = uap_ioctl((t_u8 *)cmd_buf2, &cmd_len, buf_len);
+
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf2->result == CMD_SUCCESS) {
+			if (cmd_buf2->domain.country_code[0] ||
+			    cmd_buf2->domain.country_code[1] ||
+			    cmd_buf2->domain.country_code[2]) {
+				country[0] = cmd_buf2->domain.country_code[0];
+				country[1] = cmd_buf2->domain.country_code[1];
+				if (cmd_buf2->domain.country_code[2] == 'I') {
+					if (tx_pwr > MAX_TX_PWR_INDOOR) {
+						printf("Transmit power invalid for indoor operation!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+				}
+				no_of_sub_band =
+					parse_domain_file(country, band,
+							  sub_bands, NULL);
+				if (no_of_sub_band == UAP_FAILURE) {
+					printf("Parsing of domain configuration file failed\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+
+				for (i = 0; i < no_of_sub_band; i++) {
+					if (tx_pwr <= (sub_bands[i].max_tx_pwr)) {
+						found = 1;
+						break;
+					}
+				}
+
+				if (!found) {
+					printf("ERR:Invalid transmit power for given domain!\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+			}
+		} else {
+			printf("ERR:Command Response incorrect!\n");
+			ret = UAP_FAILURE;
+			goto done;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for Tx power
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_tx_power [TX_POWER]"
+ *           if TX_POWER is provided, a 'set' is performed
+ *           else a 'get' is performed.
+ *
+ *           TX_POWER is represented in dBm
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_tx_power(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_tx_power *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	t_u8 state = 0;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_tx_power_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && is_input_valid(TXPOWER, argc, argv) != UAP_SUCCESS) {
+		print_sys_cfg_tx_power_usage();
+		return UAP_FAILURE;
+	}
+	/* Check if tx power is valid for given domain. */
+	if (argc) {
+		ret = sg_snmp_mib(ACTION_GET, OID_80211D_ENABLE, sizeof(state),
+				  &state);
+		if (state) {
+			ret = check_tx_pwr_validity_11d(atoi(argv[0]));
+			if (ret == UAP_FAILURE) {
+				print_sys_cfg_tx_power_usage();
+				return UAP_FAILURE;
+			}
+		}
+	}
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tx_power);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_tx_power *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_TX_POWER_TLV_ID;
+	tlv->length = 1;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		printf("Please check power calibration for board to see if this power\n" "setting is within calibrated range. Firmware may over-ride\n " "this setting if it is not within calibrated range, which can\n" "vary from board to board.\n");
+		cmd_buf->action = ACTION_SET;
+		tlv->tx_power_dbm = (t_u8)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_TX_POWER_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("Tx power = %d dBm\n",
+				       tlv->tx_power_dbm);
+			} else {
+				printf("Tx power setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get tx power!\n");
+			} else {
+				printf("ERR:Could not set tx power!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for SSID broadcast
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_bcast_ssid_ctl [0|1]"
+ *
+ *   Options: 0     - Disable SSID broadcast
+ *            1     - Enable SSID broadcast
+ *            empty - Get current SSID broadcast setting
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_bcast_ssid_ctl(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_bcast_ssid_ctl *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_bcast_ssid_ctl_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && is_input_valid(BROADCASTSSID, argc, argv) != UAP_SUCCESS) {
+		print_sys_cfg_bcast_ssid_ctl_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_bcast_ssid_ctl);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_bcast_ssid_ctl *)(buffer +
+					sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_BCAST_SSID_CTL_TLV_ID;
+	tlv->length = 1;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->bcast_ssid_ctl = (t_u8)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_BCAST_SSID_CTL_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("SSID broadcast is %s\n",
+				       (tlv->bcast_ssid_ctl ==
+					1) ? "enabled" : "disabled");
+			} else {
+				printf("SSID broadcast setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get SSID broadcast!\n");
+			} else {
+				printf("ERR:Could not set SSID broadcast!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for preamble settings
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_preamble_ctl"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_preamble_ctl(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_preamble_ctl *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_preamble_ctl_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 0) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_cfg_preamble_ctl_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_preamble_ctl);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_preamble_ctl *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_PREAMBLE_CTL_TLV_ID;
+	tlv->length = 1;
+	cmd_buf->action = ACTION_GET;
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_PREAMBLE_CTL_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS)
+			printf("Preamble type is %s\n",
+			       (tlv->preamble_type ==
+				0) ? "auto" : ((tlv->preamble_type ==
+						1) ? "short" : "long"));
+		else {
+			printf("ERR:Could not get preamble type!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for RTS threshold
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_rts_threshold [RTS_THRESHOLD]"
+ *           if RTS_THRESHOLD is provided, a 'set' is performed
+ *           else a 'get' is performed
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_rts_threshold(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_rts_threshold *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_rts_threshold_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && (is_input_valid(RTSTHRESH, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_rts_threshold_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_rts_threshold);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_rts_threshold *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_RTS_THRESHOLD_TLV_ID;
+	tlv->length = 2;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->rts_threshold = (t_u16)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->rts_threshold = uap_cpu_to_le16(tlv->rts_threshold);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->rts_threshold = uap_le16_to_cpu(tlv->rts_threshold);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_RTS_THRESHOLD_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("RTS threshold = %d\n",
+				       tlv->rts_threshold);
+			} else {
+				printf("RTS threshold setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get RTS threshold!\n");
+			} else {
+				printf("ERR:Could not set RTS threshold!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for Fragmentation threshold
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_frag_threshold [FRAG_THRESHOLD]"
+ *           if FRAG_THRESHOLD is provided, a 'set' is performed
+ *           else a 'get' is performed
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_frag_threshold(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_frag_threshold *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_frag_threshold_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && (is_input_valid(FRAGTHRESH, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_frag_threshold_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_frag_threshold);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_frag_threshold *)(buffer +
+					sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_FRAG_THRESHOLD_TLV_ID;
+	tlv->length = 2;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->frag_threshold = (t_u16)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->frag_threshold = uap_cpu_to_le16(tlv->frag_threshold);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->frag_threshold = uap_le16_to_cpu(tlv->frag_threshold);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_FRAG_THRESHOLD_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("Fragmentation threshold = %d\n",
+				       tlv->frag_threshold);
+			} else {
+				printf("Fragmentation threshold setting successful\n");
+			}
+		} else {
+			if (argc == 1) {
+				printf("ERR:Could not set Fragmentation threshold!\n");
+			} else {
+				printf("ERR:Could not get Fragmentation threshold!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for RSN replay protection
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_rsn_replay_prot [0|1]"
+ *
+ *   Options: 0     - Disable RSN replay protection
+ *            1     - Enable  RSN replay protection
+ *            empty - Get current RSN replay protection setting
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_rsn_replay_prot(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_rsn_replay_prot *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_rsn_replay_prot_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && is_input_valid(RSNREPLAYPROT, argc, argv) != UAP_SUCCESS) {
+		print_sys_cfg_rsn_replay_prot_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_rsn_replay_prot);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_rsn_replay_prot *)(buffer +
+					 sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_RSN_REPLAY_PROT_TLV_ID;
+	tlv->length = 1;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->rsn_replay_prot = (t_u8)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_RSN_REPLAY_PROT_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->Tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("RSN replay protection is %s\n",
+				       (tlv->rsn_replay_prot ==
+					1) ? "enabled" : "disabled");
+			} else {
+				printf("RSN replay protection setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get RSN replay protection !\n");
+			} else {
+				printf("ERR:Could not set RSN replay protection !\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for MCBC data rates
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]"
+ *
+ *   Options: 0     - Auto rate
+ *            >0    - Set specified MCBC data rate
+ *            empty - Get current MCBC data rate
+ *
+ *           MCBC_DATA_RATE is represented in units of 500 kbps
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_mcbc_data_rate(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_mcbc_data_rate *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_mcbc_data_rates_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc) {
+		if (is_input_valid(MCBCDATARATE, argc, argv) != UAP_SUCCESS) {
+			printf("ERR: Invalid input\n");
+			print_sys_cfg_mcbc_data_rates_usage();
+			return UAP_FAILURE;
+		}
+		if ((A2HEXDECIMAL(argv[0]) != 0) &&
+		    (is_mcbc_rate_valid(A2HEXDECIMAL(argv[0])) !=
+		     UAP_SUCCESS)) {
+			printf("ERR: invalid MCBC data rate.");
+			print_sys_cfg_mcbc_data_rates_usage();
+			return UAP_FAILURE;
+		}
+	}
+
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_mcbc_data_rate);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_mcbc_data_rate *)(buffer +
+					sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_MCBC_DATA_RATE_TLV_ID;
+	tlv->length = 2;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->mcbc_datarate = (t_u16)A2HEXDECIMAL(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->mcbc_datarate = uap_cpu_to_le16(tlv->mcbc_datarate);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->mcbc_datarate = uap_le16_to_cpu(tlv->mcbc_datarate);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_MCBC_DATA_RATE_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				if (tlv->mcbc_datarate == 0) {
+					printf("MCBC data rate is auto\n");
+				} else {
+					printf("MCBC data rate = 0x%x\n",
+					       tlv->mcbc_datarate);
+				}
+			} else {
+				printf("MCBC data rate setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get MCBC data rate!\n");
+			} else {
+				printf("ERR:Could not set MCBC data rate!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for Tx beacon rates
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_tx_beacon_rate [TX_BEACON_RATE]"
+ *
+ *   Options: 0     - Auto rate
+ *            >0    - Set specified data rate
+ *            empty - Get current data rate
+ *
+ *           TX_BEACON_RATE is represented in units of 500 kbps
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_tx_beacon_rate(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_tx_data_rate *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_tx_beacon_rates_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc) {
+		if (is_input_valid(TXBEACONRATE, argc, argv) != UAP_SUCCESS) {
+			printf("ERR: Invalid input\n");
+			return UAP_FAILURE;
+		} else if ((A2HEXDECIMAL(argv[0]) != 0) &&
+			   (is_tx_rate_valid(A2HEXDECIMAL(argv[0])) !=
+			    UAP_SUCCESS)) {
+			printf("ERR: invalid tx beacon rate.");
+			return UAP_FAILURE;
+		}
+	}
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tx_data_rate);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_tx_data_rate *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_TX_BEACON_RATE_TLV_ID;
+	tlv->length = 2;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->tx_data_rate = (t_u16)A2HEXDECIMAL(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->tx_data_rate = uap_cpu_to_le16(tlv->tx_data_rate);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->tx_data_rate = uap_le16_to_cpu(tlv->tx_data_rate);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_TX_BEACON_RATE_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				if (tlv->tx_data_rate == 0) {
+					printf("Tx beacon rate is auto\n");
+				} else {
+					printf("Tx beacon rate = 0x%x\n",
+					       tlv->tx_data_rate);
+				}
+			} else {
+				printf("Tx beacon rate setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get tx beacon rate!\n");
+			} else {
+				printf("ERR:Could not set tx beacon rate!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for packet forwarding
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]"
+ *
+ *   PKT_FWD_CTRL: bit 0 -- Packet forwarding handled by Host (0) or Firmware (1)
+ *            bit 1 -- Intra-BSS broadcast packets are allowed (0) or denied (1)
+ *            bit 2 -- Intra-BSS unicast packets are allowed (0) or denied (1)
+ *            bit 3 -- Inter-BSS unicast packets are allowed (0) or denied (1)
+ *            empty - Get current packet forwarding setting
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_pkt_fwd_ctl(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_pkt_fwd_ctl *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_pkt_fwd_ctl_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && (is_input_valid(PKTFWD, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_pkt_fwd_ctl_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_pkt_fwd_ctl);
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_pkt_fwd_ctl *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_PKT_FWD_CTL_TLV_ID;
+	tlv->length = 1;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->pkt_fwd_ctl = (t_u8)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_PKT_FWD_CTL_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("%s handles packet forwarding -\n",
+				       ((tlv->pkt_fwd_ctl & PKT_FWD_FW_BIT) ==
+					0) ? "Host" : "Firmware");
+				printf("\tIntra-BSS broadcast packets are %s\n",
+				       ((tlv->
+					 pkt_fwd_ctl & PKT_FWD_INTRA_BCAST) ==
+					0) ? "allowed" : "denied");
+				printf("\tIntra-BSS unicast packets are %s\n",
+				       ((tlv->
+					 pkt_fwd_ctl & PKT_FWD_INTRA_UCAST) ==
+					0) ? "allowed" : "denied");
+				printf("\tInter-BSS unicast packets are %s\n",
+				       ((tlv->
+					 pkt_fwd_ctl & PKT_FWD_INTER_UCAST) ==
+					0) ? "allowed" : "denied");
+			} else {
+				printf("Packet control logic setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get packet control logic!\n");
+			} else {
+				printf("ERR:Could not set packet control logic!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for STA ageout timer
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]"
+ *           if STA_AGEOUT_TIMER is provided, a 'set' is performed
+ *           else a 'get' is performed.
+ *           The value should between 100 and 864000
+ *
+ *           STA_AGEOUT_TIMER is represented in units of 100 ms
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_sta_ageout_timer(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_sta_ageout_timer *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_sta_ageout_timer_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && (is_input_valid(STAAGEOUTTIMER, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_sta_ageout_timer_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) +
+		sizeof(tlvbuf_sta_ageout_timer);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_sta_ageout_timer *)(buffer +
+					  sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_STA_AGEOUT_TIMER_TLV_ID;
+	tlv->length = 4;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->sta_ageout_timer_ms = (t_u32)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->sta_ageout_timer_ms = uap_cpu_to_le32(tlv->sta_ageout_timer_ms);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->sta_ageout_timer_ms = uap_le32_to_cpu(tlv->sta_ageout_timer_ms);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_STA_AGEOUT_TIMER_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("STA ageout timer value = %d\n",
+				       (int)tlv->sta_ageout_timer_ms);
+			} else {
+				printf("STA ageout timer setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get STA ageout timer!\n");
+			} else {
+				printf("ERR:Could not set STA ageout timer!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for PS STA ageout timer
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]"
+ *           if PS_STA_AGEOUT_TIMER is provided, a 'set' is performed
+ *           else a 'get' is performed.
+ *           The value should between 100 and 864000
+ *
+ *           PS_STA_AGEOUT_TIMER is represented in units of 100 ms
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_ps_sta_ageout_timer(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_ps_sta_ageout_timer *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_ps_sta_ageout_timer_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc &&
+	    (is_input_valid(PSSTAAGEOUTTIMER, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_ps_sta_ageout_timer_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) +
+		sizeof(tlvbuf_ps_sta_ageout_timer);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_ps_sta_ageout_timer *)(buffer +
+					     sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_PS_STA_AGEOUT_TIMER_TLV_ID;
+	tlv->length = 4;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->ps_sta_ageout_timer_ms = (t_u32)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->ps_sta_ageout_timer_ms =
+		uap_cpu_to_le32(tlv->ps_sta_ageout_timer_ms);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->ps_sta_ageout_timer_ms =
+		uap_le32_to_cpu(tlv->ps_sta_ageout_timer_ms);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_PS_STA_AGEOUT_TIMER_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("PS STA ageout timer value = %d\n",
+				       (int)tlv->ps_sta_ageout_timer_ms);
+			} else {
+				printf("PS STA ageout timer setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get PS STA ageout timer!\n");
+			} else {
+				printf("ERR:Could not set PS STA ageout timer!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for authentication mode
+ *   and sends to the driver
+ *
+ *   Usage: "Usage : sys_cfg_auth [AUTHMODE]"
+ *
+ *   Options: AUTHMODE :     0 - Open authentication
+ *                           1 - Shared key authentication
+ *            empty - Get current authentication mode
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_auth(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_auth_mode *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_auth_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && (is_input_valid(AUTHMODE, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_auth_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_auth_mode);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_auth_mode *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_AUTH_TLV_ID;
+	tlv->length = 1;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->auth_mode = (t_u8)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_AUTH_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				print_auth(tlv);
+			} else {
+				printf("authentication mode setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get authentication mode!\n");
+			} else {
+				printf("ERR:Could not set authentication mode!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for encryption protocol
+ *   and sends to the driver
+ *
+ *   Usage: "Usage : sys_cfg_protocol [PROTOCOL]"
+ *
+ *   Options: PROTOCOL    	     Bit 0 - No RSN
+ *		                     Bit 1 - WEP Static
+ *		                     Bit 3 - WPA
+ *	                             Bit 3 - WPA2
+ *            empty - Get current protocol
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_protocol(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_protocol *tlv = NULL;
+	tlvbuf_akmp *akmp_tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	t_u16 cmd_len = 0;
+	int ret = UAP_SUCCESS;
+	int opt;
+	int get_akm_val = 0;
+	int resend = 0;
+	t_u16 tlv_val_16 = 0;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_protocol_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc && (is_input_valid(PROTOCOL, argc, argv) != UAP_SUCCESS ||
+		     is_input_valid(AKM_SUITE, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_protocol_usage();
+		return UAP_FAILURE;
+	}
+
+	if ((argc == 1) &&
+	    ((atoi(argv[0]) == PROTOCOL_WPA) ||
+	     (atoi(argv[0]) == PROTOCOL_WPA2) ||
+	     (atoi(argv[0]) == PROTOCOL_WPA2_MIXED))) {
+		get_akm_val = 1;
+	}
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+
+	/* case such as ./uaputl.exe sys_cfg_protocol 8/32/40 */
+	/* Don't assume PSK in such cases, query FW and then set  */
+	do {
+		memset(buffer, 0, buf_len);
+
+		/* Initialize the command length */
+		if ((argc == 1) &&
+		    ((atoi(argv[0]) == PROTOCOL_NO_SECURITY) ||
+		     (atoi(argv[0]) == PROTOCOL_STATIC_WEP))) {
+			cmd_len =
+				sizeof(apcmdbuf_sys_configure) +
+				sizeof(tlvbuf_protocol);
+		} else {
+			cmd_len =
+				sizeof(apcmdbuf_sys_configure) +
+				sizeof(tlvbuf_protocol) + sizeof(tlvbuf_akmp);
+		}
+
+		/* Locate headers */
+		cmd_buf = (apcmdbuf_sys_configure *)buffer;
+		tlv = (tlvbuf_protocol *)(buffer +
+					  sizeof(apcmdbuf_sys_configure));
+		akmp_tlv =
+			(tlvbuf_akmp *)(buffer +
+					sizeof(apcmdbuf_sys_configure) +
+					sizeof(tlvbuf_protocol));
+		/* Fill the command buffer */
+		cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+		cmd_buf->size = cmd_len;
+		cmd_buf->seq_num = 0;
+		cmd_buf->result = 0;
+		tlv->tag = MRVL_PROTOCOL_TLV_ID;
+		tlv->length = 2;
+		if (argc == 0) {
+			cmd_buf->action = ACTION_GET;
+			akmp_tlv->tag = MRVL_AKMP_TLV_ID;
+			akmp_tlv->length = 4;	/* sizeof(tlvbuf_akmp) - TLVHEADER_LEN */
+		} else {
+			cmd_buf->action = ACTION_SET;
+			tlv->protocol = (t_u16)atoi(argv[0]);
+			printf("protocol: 0x%x\n", tlv->protocol);
+			if (tlv->protocol & (PROTOCOL_WPA | PROTOCOL_WPA2)) {
+				akmp_tlv->tag = MRVL_AKMP_TLV_ID;
+				akmp_tlv->length = 4;	/* sizeof(tlvbuf_akmp) - TLVHEADER_LEN */
+				if (argc == 2) {
+					akmp_tlv->key_mgmt =
+						(t_u16)A2HEXDECIMAL(argv[1]);
+				} else {
+					akmp_tlv->key_mgmt = tlv_val_16;	// AKM SUITE from FW in 2nd iteration
+					if (get_akm_val) {
+						/* Get AKM SUITE val from FW */
+						cmd_buf->action = ACTION_GET;
+						resend = 1;
+					} else
+						resend = 0;
+				}
+				printf("KeyMgmt: 0x%x\n", akmp_tlv->key_mgmt);
+				akmp_tlv->key_mgmt =
+					uap_cpu_to_le16(akmp_tlv->key_mgmt);
+			}
+		}
+		endian_convert_tlv_header_out(tlv);
+		if (cmd_len ==
+		    (sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_protocol) +
+		     sizeof(tlvbuf_akmp))) {
+			endian_convert_tlv_header_out(akmp_tlv);
+		}
+		tlv->protocol = uap_cpu_to_le16(tlv->protocol);
+
+		/* Send the command */
+		ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+		/* Process response */
+		if (ret == UAP_SUCCESS) {
+			/* Verify response */
+			if (cmd_buf->cmd_code !=
+			    (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) {
+				printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, uap_le16_to_cpu(tlv->tag));
+				free(buffer);
+				return UAP_FAILURE;
+			}
+			/* Print response */
+			if (cmd_buf->result == CMD_SUCCESS) {
+				if (argc == 0) {
+					print_tlv((t_u8 *)tlv,
+						  cmd_buf->size -
+						  sizeof(apcmdbuf_sys_configure)
+						  + BUF_HEADER_SIZE);
+				} else {
+					if (get_akm_val) {
+						get_akm_val = 0;
+						/* AKM Suite value from FW */
+						tlv_val_16 =
+							*(t_u8 *)&akmp_tlv->
+							key_mgmt;
+						tlv_val_16 |=
+							(*
+							 ((t_u8 *)&akmp_tlv->
+							  key_mgmt + 1) << 8);
+					} else
+						printf("protocol setting successful\n");
+				}
+			} else {
+				if (argc == 0) {
+					printf("ERR:Could not get protocol!\n");
+				} else {
+					printf("ERR:Could not set protocol!\n");
+				}
+				ret = UAP_FAILURE;
+			}
+		} else {
+			printf("ERR:Command sending failed!\n");
+		}
+	} while (resend && (ret == UAP_SUCCESS));
+
+	if (buffer)
+		free(buffer);
+
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for WEP keys settings
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_wep_key [INDEX_0 IS_DEFAULT KEY_0] [INDEX_1 IS_DEFAULT KEY_1] [INDEX_2 IS_DEFAULT KEY_2] [INDEX_3 IS_DEFAULT KEY_3]"
+ *
+ *   Options: INDEX_* :      0 - KeyIndex is 0
+ *                           1 - KeyIndex is 1
+ *                           2 - KeyIndex is 2
+ *                           3 - KeyIndex is 3
+ *            IS_DEFAUL :    0 - KeyIndex is not the default
+ *                           1 - KeyIndex is the default transmit key
+ *            KEY_* :        Key value
+ *            empty - Get current WEP key settings
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_wep_key(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_wep_key *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u8 *tmp_buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int key_len = -1;
+	int length = 0;
+	int number_of_keys = 0;
+	int i = 0;
+	int keyindex = -1;
+	int is_default = -1;
+	char *key = NULL;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_wep_key_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc > 12) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_cfg_wep_key_usage();
+		return UAP_FAILURE;
+	} else if ((argc > 1) && ((argc % 3) != 0)) {
+		printf("ERR:Illegal number of parameters.\n");
+		print_sys_cfg_wep_key_usage();
+		return UAP_FAILURE;
+	} else if (argc > 1) {
+
+		/* Find number of keys provided */
+		number_of_keys = argc / 3;
+		for (i = 0; i < number_of_keys; i++) {
+			if ((ISDIGIT(argv[(3 * i)]) == 0) ||
+			    (atoi(argv[(3 * i)]) < 0) ||
+			    (atoi(argv[(3 * i)]) > 3)) {
+				printf("ERR:Illegal INDEX %s. Must be either '0', '1', '2', or '3'.\n", argv[(3 * i)]);
+				print_sys_cfg_wep_key_usage();
+				return UAP_FAILURE;
+			}
+			if ((ISDIGIT(argv[(3 * i) + 1]) == 0) ||
+			    (atoi(argv[(3 * i) + 1]) < 0) ||
+			    (atoi(argv[(3 * i) + 1]) > 1)) {
+				printf("ERR:Illegal IS_DEFAULT %s. Must be either '0', or '1'.\n", argv[(3 * i) + 1]);
+				print_sys_cfg_wep_key_usage();
+				return UAP_FAILURE;
+			}
+			if ((strlen(argv[(3 * i) + 2]) != 5) &&
+			    (strlen(argv[(3 * i) + 2]) != 10)
+			    && (strlen(argv[(3 * i) + 2]) != 13) &&
+			    (strlen(argv[(3 * i) + 2]) != 26)) {
+				printf("ERR:Incorrect KEY_%d length %d\n",
+				       atoi(argv[(3 * i)]),
+				       (t_u32)strlen(argv[(3 * i) + 2]));
+				print_sys_cfg_wep_key_usage();
+				return UAP_FAILURE;
+			}
+			if ((strlen(argv[(3 * i) + 2]) == 10) ||
+			    (strlen(argv[(3 * i) + 2]) == 26)) {
+				if (UAP_FAILURE ==
+				    ishexstring(argv[(3 * i) + 2])) {
+					printf("ERR:Only hex digits are allowed when key length is 10 or 26\n");
+					print_sys_cfg_wep_key_usage();
+					return UAP_FAILURE;
+				}
+			}
+		}
+	} else if (argc == 1) {
+		if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+		    (atoi(argv[0]) > 3)) {
+			printf("ERR:Illegal INDEX %s. Must be either '0', '1', '2', or '3'.\n", argv[0]);
+			print_sys_cfg_wep_key_usage();
+			return UAP_FAILURE;
+		}
+	}
+
+	/* Initialize the command length */
+	if (argc == 0 || argc == 1) {
+		if (argc == 0)
+			cmd_len =
+				sizeof(apcmdbuf_sys_configure) +
+				sizeof(tlvbuf_header);
+		else
+			cmd_len =
+				sizeof(apcmdbuf_sys_configure) +
+				sizeof(tlvbuf_wep_key) - 1;
+	} else {
+		cmd_len = sizeof(apcmdbuf_sys_configure);
+	}
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	if (argc == 0 || argc == 1) {
+		cmd_buf->action = ACTION_GET;
+		tlv = (tlvbuf_wep_key *)(buffer +
+					 sizeof(apcmdbuf_sys_configure));
+		tlv->tag = MRVL_WEP_KEY_TLV_ID;
+		if (argc == 0)
+			tlv->length = 0;
+		else {
+			tlv->length = 1;
+			tlv->key_index = atoi(argv[0]);
+		}
+		endian_convert_tlv_header_out(tlv);
+	} else {
+		cmd_buf->action = ACTION_SET;
+	}
+	/* Add key TLVs */
+	for (i = 0; i < number_of_keys; i++) {
+		keyindex = atoi(argv[(3 * i)]);
+		is_default = atoi(argv[(3 * i) + 1]);
+		key = argv[(3 * i) + 2];
+		length = strlen(key);
+		switch (length) {
+		case 5:
+		case 10:
+			key_len = 5;
+			break;
+		case 13:
+		case 26:
+			key_len = 13;
+			break;
+		default:
+			key_len = 0;
+			break;
+		}
+		/* Adjust command buffer */
+		tmp_buffer =
+			realloc(buffer,
+				(cmd_len + sizeof(tlvbuf_wep_key) + key_len));
+		if (!tmp_buffer) {
+			printf("ERR:Cannot append WEP key configurations TLV!\n");
+			free(buffer);
+			return UAP_FAILURE;
+		} else {
+			buffer = tmp_buffer;
+			tmp_buffer = NULL;
+		}
+		/* Locate headers */
+		cmd_buf = (apcmdbuf_sys_configure *)buffer;
+		tlv = (tlvbuf_wep_key *)(buffer + cmd_len);
+		/* Adjust command length */
+		cmd_len += (sizeof(tlvbuf_wep_key) + key_len);
+		/* Set TLV fields */
+		tlv->tag = MRVL_WEP_KEY_TLV_ID;
+		tlv->length = 2 + key_len;
+		tlv->key_index = (t_u8)keyindex;
+		tlv->is_default = (t_u8)is_default;
+		/* Check if string or raw */
+		switch (length) {
+		case 5:
+		case 13:
+			memcpy(tlv->key, key, length);
+			break;
+		case 10:
+		case 26:
+			string2raw(key, tlv->key);
+			break;
+		default:
+			break;
+		}
+		endian_convert_tlv_header_out(tlv);
+	}
+
+	/* Update command length */
+	cmd_buf->size = cmd_len;
+	if ((argc != 0) && (argc != 1))
+		buf_len = cmd_len;
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if ((argc != 0) && (argc != 1)) {
+				printf("WEP key setting successful\n");
+			} else {
+				printf("query WEP key setting successful\n");
+				tlv = (tlvbuf_wep_key *)(buffer +
+							 sizeof
+							 (apcmdbuf_sys_configure));
+				print_tlv((t_u8 *)tlv,
+					  cmd_buf->size -
+					  sizeof(apcmdbuf_sys_configure) +
+					  BUF_HEADER_SIZE);
+			}
+		} else {
+			if ((argc != 0) && (argc != 1))
+				printf("ERR:Could not set WEP keys!\n");
+			else
+				printf("ERR:Could not get WEP keys!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for cipher configurations
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]"
+ *
+ *   Options: PAIRWISE_CIPHER : Bit 2 - TKIP
+ *                              Bit 3 - AES CCMP
+ *            GROUP_CIPHER :    Bit 2 - TKIP
+ *                              Bit 3 - AES CCMP
+ *            empty - Get current cipher settings
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_cipher(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_cipher *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_cipher_usage();
+			return UAP_FAILURE;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc != 0) && (argc != 2)) {
+		printf("ERR:wrong arguments.\n");
+		print_sys_cfg_cipher_usage();
+		return UAP_FAILURE;
+	}
+	if (argc == 2) {
+		if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)) {
+			print_sys_cfg_cipher_usage();
+			return UAP_FAILURE;
+		}
+		if (atoi(argv[0]) & ~CIPHER_BITMAP) {
+			printf("ERR:Illegal PAIRWISE_CIPHER parameter %s.\n",
+			       argv[0]);
+			print_sys_cfg_cipher_usage();
+			return UAP_FAILURE;
+		}
+		if (atoi(argv[1]) & ~CIPHER_BITMAP) {
+			printf("ERR:Illegal GROUP_CIPHER parameter %s.\n",
+			       argv[1]);
+			print_sys_cfg_cipher_usage();
+			return UAP_FAILURE;
+		}
+		if (is_cipher_valid(atoi(argv[0]), atoi(argv[1])) !=
+		    UAP_SUCCESS) {
+			printf("ERR:Wrong group and pairwise cipher combination!\n");
+			print_sys_cfg_cipher_usage();
+			return UAP_FAILURE;
+		}
+	}
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_cipher);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_cipher *)(buffer + sizeof(apcmdbuf_sys_configure));
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_CIPHER_TLV_ID;
+	tlv->length = 2;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->pairwise_cipher = (t_u8)atoi(argv[0]);
+		tlv->group_cipher = (t_u8)atoi(argv[1]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_CIPHER_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				print_cipher(tlv);
+			} else {
+				printf("cipher setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get cipher parameters!\n");
+			} else {
+				printf("ERR:Could not set cipher parameters!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for pairwise cipher configurations
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_pwk_cipher [<PROTOCOL>] [PAIRWISE_CIPHER]"
+ *
+ *   Options: PROTOCOL : Bit 3 - WPA
+ *                       Bit 5 - WPA2
+ *            PAIRWISE_CIPHER : Bit 2 - TKIP
+ *                              Bit 3 - AES CCMP
+ *            empty - Get current pairwise cipher settings
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_pwk_cipher(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_pwk_cipher *tlv = NULL;
+	HTCap_t htcap;
+	t_u16 proto = 0;
+	t_u8 *buffer = NULL;
+	t_u16 tlv_get_len = 0, protocol = 0, cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_pwk_cipher_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc) {
+		if (is_input_valid(PWK_CIPHER, argc, argv) != UAP_SUCCESS) {
+			print_sys_cfg_pwk_cipher_usage();
+			return UAP_FAILURE;
+		}
+		if ((argc == 2) && (atoi(argv[1]) == CIPHER_TKIP)) {
+			if (UAP_SUCCESS == get_sys_cfg_protocol(&proto)) {
+				/* Ok to have TKIP in mixed mode */
+				if (proto != PROTOCOL_WPA2_MIXED) {
+					memset(&htcap, 0, sizeof(htcap));
+					if (UAP_SUCCESS ==
+					    get_sys_cfg_11n(&htcap)) {
+						if (htcap.supported_mcs_set[0]) {
+							printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
+							print_sys_cfg_pwk_cipher_usage
+								();
+							return UAP_FAILURE;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_pwk_cipher);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_pwk_cipher *)(buffer + sizeof(apcmdbuf_sys_configure));
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_CIPHER_PWK_TLV_ID;
+	if (argc < 2) {
+		cmd_buf->action = ACTION_GET;
+		tlv->length = 0;
+		/* Adjust cmd_len for 0 payload */
+		cmd_len = cmd_len - (sizeof(tlvbuf_pwk_cipher) - TLVHEADER_LEN);
+		if (argc == 1)
+			protocol = atoi(argv[0]);
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->length = sizeof(tlvbuf_pwk_cipher) - TLVHEADER_LEN;
+		tlv->protocol = (t_u16)atoi(argv[0]);
+		tlv->pairwise_cipher = (t_u8)atoi(argv[1]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->protocol = uap_cpu_to_le16(tlv->protocol);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_CIPHER_PWK_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc < 2) {
+				tlv_get_len =
+					cmd_buf->size -
+					sizeof(apcmdbuf_sys_configure) +
+					BUF_HEADER_SIZE;
+				if ((!tlv_get_len) ||
+				    (tlv_get_len % sizeof(tlvbuf_pwk_cipher)) ||
+				    (tlv_get_len >
+				     (2 * sizeof(tlvbuf_pwk_cipher)))) {
+					printf("ERR:Corrupted response!\n");
+					free(buffer);
+					return UAP_FAILURE;
+				}
+				if (!proto)
+					get_sys_cfg_protocol(&proto);
+				if (proto & PROTOCOL_WPA ||
+				    proto & PROTOCOL_WPA2)
+					printf("Active Protocol = %s\n",
+					       (proto == PROTOCOL_WPA)
+					       ? "WPA" : (proto ==
+							  PROTOCOL_WPA2) ?
+					       "WPA2" : "WPA | WPA2");
+				while (tlv_get_len > 0) {
+					endian_convert_tlv_header_in(tlv);
+					tlv->protocol =
+						uap_le16_to_cpu(tlv->protocol);
+					if ((argc == 1) &&
+					    (protocol != tlv->protocol)) {
+						tlv_get_len -=
+							sizeof
+							(tlvbuf_pwk_cipher);
+						tlv++;
+						continue;
+					}
+					print_pwk_cipher(tlv);
+					tlv_get_len -=
+						sizeof(tlvbuf_pwk_cipher);
+					tlv++;
+				}
+			} else {
+				printf("protocol and pairwise cipher setting successful\n");
+			}
+		} else {
+			if (argc < 2) {
+				printf("ERR:Could not get pairwise cipher parameters!\n");
+			} else {
+				printf("ERR:Could not set pairwise cipher parameters!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for group cipher configurations
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_gwk_cipher [GROUP_CIPHER]"
+ *
+ *   Options: GROUP_CIPHER : Bit 2 - TKIP
+ *                           Bit 3 - AES CCMP
+ *            empty - Get current group cipher settings
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_gwk_cipher(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_gwk_cipher *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_gwk_cipher_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc) {
+		if (is_input_valid(GWK_CIPHER, argc, argv) != UAP_SUCCESS) {
+			print_sys_cfg_gwk_cipher_usage();
+			return UAP_FAILURE;
+		}
+	}
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_gwk_cipher);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_gwk_cipher *)(buffer + sizeof(apcmdbuf_sys_configure));
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_CIPHER_GWK_TLV_ID;
+	tlv->length = 2;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->group_cipher = (t_u8)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_CIPHER_GWK_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				print_gwk_cipher(tlv);
+			} else {
+				printf("group cipher setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get group cipher parameters!\n");
+			} else {
+				printf("ERR:Could not set group cipher parameters!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for group re-key timer
+ *   and sends to the driver
+ *
+ *   Usage: "Usage : sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]"
+ *
+ *   Options: GROUP_REKEY_TIME is represented in seconds
+ *            Get current group re-key timer
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_group_rekey_timer(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_group_rekey_timer *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_group_rekey_timer_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc &&
+	    (is_input_valid(GROUPREKEYTIMER, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_group_rekey_timer_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) +
+		sizeof(tlvbuf_group_rekey_timer);
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_group_rekey_timer *)(buffer +
+					   sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_GRP_REKEY_TIME_TLV_ID;
+	tlv->length = 4;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->group_rekey_time_sec = (t_u32)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->group_rekey_time_sec = uap_cpu_to_le32(tlv->group_rekey_time_sec);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->group_rekey_time_sec = uap_le32_to_cpu(tlv->group_rekey_time_sec);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_GRP_REKEY_TIME_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				if (tlv->group_rekey_time_sec > 0)
+					printf("Group rekey time is %d s\n",
+					       tlv->group_rekey_time_sec);
+				else
+					printf("Group rekey time is disabled\n");
+			} else {
+				printf("group re-key time setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get group re-key time!\n");
+			} else {
+				printf("ERR:Could not set group re-key time!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for WPA passphrase
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_wpa_passphrase [PASSPHRASE]"
+ *           if PASSPHRASE is provided, a 'set' is performed
+ *           else a 'get' is performed
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_wpa_passphrase(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_wpa_passphrase *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+
+	argc--;
+	argv++;
+
+	/* Check arguments */
+	if (argc > 1) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_cfg_wpa_passphrase_usage();
+		return UAP_FAILURE;
+	}
+	if ((argc == 1) && (strlen(argv[0]) > MAX_WPA_PASSPHRASE_LENGTH)) {
+		printf("ERR:PASSPHRASE too long.\n");
+		return UAP_FAILURE;
+	}
+	if ((argc == 1) && (strlen(argv[0]) < MIN_WPA_PASSPHRASE_LENGTH)) {
+		printf("ERR:PASSPHRASE too short.\n");
+		return UAP_FAILURE;
+	}
+	if ((argc == 1) && (strlen(argv[0]) == MAX_WPA_PASSPHRASE_LENGTH)) {
+		if (UAP_FAILURE == ishexstring(argv[0])) {
+			printf("ERR:Only hex digits are allowed when passphrase's length is 64\n");
+			return UAP_FAILURE;
+		}
+	}
+	/* Initialize the command length */
+	if (argc == 0)
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) +
+			sizeof(tlvbuf_wpa_passphrase) +
+			MAX_WPA_PASSPHRASE_LENGTH;
+	else
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) +
+			sizeof(tlvbuf_wpa_passphrase) + strlen(argv[0]);
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_wpa_passphrase *)(buffer +
+					sizeof(apcmdbuf_sys_configure));
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_WPA_PASSPHRASE_TLV_ID;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+		tlv->length = MAX_WPA_PASSPHRASE_LENGTH;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->length = strlen(argv[0]);
+		memcpy(tlv->passphrase, argv[0], tlv->length);
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_WPA_PASSPHRASE_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				if (tlv->length > 0)
+					printf("WPA passphrase = %s\n",
+					       tlv->passphrase);
+				else
+					printf("WPA passphrase: None\n");
+			} else {
+				printf("WPA passphrase setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get WPA passphrase!\n");
+			} else {
+				printf("ERR:Could not set WPA passphrase!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a STA filter request and sends to the driver
+ *
+ *   Usage: "sta_filter_table <FILTERMODE> <MACADDRESS_LIST>"
+ *
+ *   Options: FILTERMODE : 0 - Disable filter table
+ *                         1 - Allow mac address specified in the allwed list
+ *		           2 - Block MAC addresses specified in the  banned list
+ *            MACADDRESS_LIST is the list of MAC addresses to be acted upon. Each
+ *                         MAC address must be separated with a space. Maximum of
+ *                         16 MAC addresses are supported.
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sta_filter_table(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_sta_mac_addr_filter *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int i = 0;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sta_filter_table_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc > (MAX_MAC_ONESHOT_FILTER + 1)) {
+		printf("ERR:Too many arguments.\n");
+		print_sta_filter_table_usage();
+		return UAP_FAILURE;
+	}
+	if (argc > 0) {
+		if ((ISDIGIT(argv[0]) == 0) ||
+		    ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 2))) {
+			printf("ERR:Illegal FILTERMODE parameter %s. Must be either '0', '1', or '2'.\n", argv[1]);
+			print_sta_filter_table_usage();
+			return UAP_FAILURE;
+		}
+	}
+	/* Initialize the command length */
+	if (argc == 0) {
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) +
+			sizeof(tlvbuf_sta_mac_addr_filter) +
+			(MAX_MAC_ONESHOT_FILTER * ETH_ALEN);
+	} else {
+		if (argc == 1) {
+			cmd_len = sizeof(apcmdbuf_sys_configure) +
+				sizeof(tlvbuf_sta_mac_addr_filter) +
+				(MAX_MAC_ONESHOT_FILTER * ETH_ALEN);
+		} else {
+			cmd_len =
+				sizeof(apcmdbuf_sys_configure) +
+				sizeof(tlvbuf_sta_mac_addr_filter) + (argc -
+								      1) *
+				ETH_ALEN;
+		}
+	}
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_sta_mac_addr_filter *)(buffer +
+					     sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_STA_MAC_ADDR_FILTER_TLV_ID;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+		tlv->count = MAX_MAC_ONESHOT_FILTER;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->filter_mode = atoi(argv[0]);
+		tlv->count = argc - 1;
+		if (tlv->count) {
+			for (i = 0; i < tlv->count; i++) {
+				if ((ret =
+				     mac2raw(argv[i + 1],
+					     &tlv->mac_address[i *
+							       ETH_ALEN])) !=
+				    UAP_SUCCESS) {
+					printf("ERR: %s Address\n",
+					       ret ==
+					       UAP_FAILURE ? "Invalid MAC" : ret
+					       ==
+					       UAP_RET_MAC_BROADCAST ?
+					       "Broadcast" : "Multicast");
+					print_sta_filter_table_usage();
+					free(buffer);
+					return UAP_FAILURE;
+				}
+			}
+		} else {
+			memset(tlv->mac_address, 0,
+			       MAX_MAC_ONESHOT_FILTER * ETH_ALEN);
+		}
+	}
+	if (tlv->count) {
+		tlv->length = tlv->count * ETH_ALEN + 2;
+	} else {
+		tlv->length = MAX_MAC_ONESHOT_FILTER * ETH_ALEN + 2;
+	}
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_STA_MAC_ADDR_FILTER_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				print_mac_filter(tlv);
+			} else {
+				printf("MAC address filter table setting successful!\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get MAC address filter table settings!\n");
+			} else {
+				printf("ERR:Could not set MAC address filter table settings!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for max station number
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_max_sta_num [STA_NUM]"
+ *           if STA_NUM is provided, a 'set' is performed
+ *           else a 'get' is performed.
+ *
+ *           STA_NUM should not bigger than 8
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_max_sta_num(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_max_sta_num *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	t_u16 max_sta_num_supported = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_max_sta_num_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc && (is_input_valid(MAXSTANUM, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_max_sta_num_usage();
+		return UAP_FAILURE;
+	}
+	if (argc) {
+		if (get_max_sta_num_supported(&max_sta_num_supported) ==
+		    UAP_FAILURE) {
+			return UAP_FAILURE;
+		}
+		if (atoi(argv[0]) > max_sta_num_supported) {
+			printf("ERR: MAX_STA_NUM must be less than %d\n",
+			       max_sta_num_supported);
+			print_sys_cfg_max_sta_num_usage();
+			return UAP_FAILURE;
+		}
+	}
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_max_sta_num);
+	if (argc) {
+		cmd_len -= sizeof(tlv->max_sta_num_supported);
+	}
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_max_sta_num *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_MAX_STA_CNT_TLV_ID;
+	if (argc == 0) {
+		tlv->length = 4;
+		cmd_buf->action = ACTION_GET;
+	} else {
+		tlv->length = 2;
+		cmd_buf->action = ACTION_SET;
+		tlv->max_sta_num_configured = (t_u16)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->max_sta_num_configured =
+		uap_cpu_to_le16(tlv->max_sta_num_configured);
+	tlv->max_sta_num_supported =
+		uap_cpu_to_le16(tlv->max_sta_num_supported);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->max_sta_num_configured =
+		uap_le16_to_cpu(tlv->max_sta_num_configured);
+	tlv->max_sta_num_supported =
+		uap_le16_to_cpu(tlv->max_sta_num_supported);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_MAX_STA_CNT_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("configured max station count = %d\n",
+				       tlv->max_sta_num_configured);
+				if (tlv->length == 4) {
+					printf("max number of stations supported = %d\n", tlv->max_sta_num_supported);
+				}
+			} else {
+				printf("max station number setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get configured max station count and supported max station count!\n");
+			} else {
+				printf("ERR:Could not set max station number!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for retry limit
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_retry_limit [RETRY_LIMIT]"
+ *           if RETRY_LIMIT is provided, a 'set' is performed
+ *           else a 'get' is performed.
+ *
+ *           RETRY_LIMIT should not bigger than 14
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_retry_limit(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_retry_limit *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_retry_limit_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc && (is_input_valid(RETRYLIMIT, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_retry_limit_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_retry_limit);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_retry_limit *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_RETRY_LIMIT_TLV_ID;
+	tlv->length = 1;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->retry_limit = (t_u8)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_RETRY_LIMIT_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("retry limit = %d\n", tlv->retry_limit);
+			} else {
+				printf("retry limit setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get retry limit!\n");
+			} else {
+				printf("ERR:Could not set retry limit!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for sticky TIM configuration
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_sticky_tim_config [ENABLE] [<DURATION> <STICKY_BIT_MASK>]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_sticky_tim_config(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_sticky_tim_config *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_sticky_tim_config_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc &&
+	    (is_input_valid(STICKYTIMCONFIG, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_sticky_tim_config_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) +
+		sizeof(tlvbuf_sticky_tim_config);
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_sticky_tim_config *)(buffer +
+					   sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_STICKY_TIM_CONFIG_TLV_ID;
+	tlv->length = sizeof(tlvbuf_sticky_tim_config) - TLVHEADER_LEN;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->enable = (t_u16)atoi(argv[0]);
+		if (argc > 1) {
+			tlv->duration = (t_u16)atoi(argv[1]);
+			tlv->sticky_bitmask = (t_u16)atoi(argv[2]);
+		}
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->enable = uap_cpu_to_le16(tlv->enable);
+	if (argc > 1) {
+		tlv->duration = uap_cpu_to_le16(tlv->duration);
+		tlv->sticky_bitmask = uap_cpu_to_le16(tlv->sticky_bitmask);
+	}
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->enable = uap_le16_to_cpu(tlv->enable);
+	if (argc > 1) {
+		tlv->duration = uap_le16_to_cpu(tlv->duration);
+		tlv->sticky_bitmask = uap_le16_to_cpu(tlv->sticky_bitmask);
+	}
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_STICKY_TIM_CONFIG_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("Sticky TIM is %s\n",
+				       (tlv->enable ==
+					0) ? "disabled" : "enabled");
+				printf("Duration = %d beacons\n",
+				       tlv->duration);
+				printf("Sticky Bitmask = %x\n",
+				       tlv->sticky_bitmask);
+			} else {
+				printf("sticky TIM configuration successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get sticky TIM configuration!\n");
+			} else {
+				printf("ERR:Could not set sticky TIM configuration!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for sticky TIM station MAC address
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_sticky_tim_sta_mac_addr(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_sticky_tim_sta_mac_addr *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int tlv_get_len = 0;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_sticky_tim_sta_mac_addr_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc &&
+	    (is_input_valid(STICKYTIMSTAMACADDR, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_sticky_tim_sta_mac_addr_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) +
+		sizeof(tlvbuf_sticky_tim_sta_mac_addr);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_sticky_tim_sta_mac_addr *)(buffer +
+						 sizeof
+						 (apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_STICKY_TIM_STA_MAC_ADDR_TLV_ID;
+	tlv->length = sizeof(tlvbuf_sticky_tim_sta_mac_addr) - TLVHEADER_LEN;
+	if (argc < 2) {
+		cmd_buf->action = ACTION_GET;
+		if (argc == 0) {
+			tlv->length = 0;
+			cmd_len -=
+				sizeof(tlvbuf_sticky_tim_sta_mac_addr) -
+				TLVHEADER_LEN;
+		}
+		if ((argc == 1) &&
+		    mac2raw(argv[0], tlv->sta_mac_address) != UAP_SUCCESS) {
+			printf("ERR: Invalid MAC address %s \n", argv[0]);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->control = (t_u16)atoi(argv[0]);
+		if (mac2raw(argv[1], tlv->sta_mac_address) != UAP_SUCCESS) {
+			printf("ERR: Invalid MAC address %s \n", argv[1]);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+	}
+	endian_convert_tlv_header_out(tlv);
+	tlv->control = uap_cpu_to_le16(tlv->control);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->control = uap_le16_to_cpu(tlv->control);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_STICKY_TIM_STA_MAC_ADDR_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc < 2) {
+				tlv_get_len =
+					cmd_buf->size -
+					sizeof(apcmdbuf_sys_configure) +
+					BUF_HEADER_SIZE;
+				while (tlv_get_len > 0) {
+					printf("station MAC address = ");
+					print_mac(tlv->sta_mac_address);
+					printf("\ncontrol = %x\n",
+					       tlv->control);
+					tlv++;
+					tlv_get_len -=
+						sizeof
+						(tlvbuf_sticky_tim_sta_mac_addr);
+				}
+			} else {
+				printf("sticky TIM configuration for given station is successful\n");
+			}
+		} else {
+			if (argc < 2) {
+				printf("ERR:Could not get sticky TIM configuration for station(s)!\n");
+			} else {
+				printf("ERR:Could not set sticky TIM configuration for given station!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for 20/40 coex configuration
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_2040_coex [ENABLE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_2040_coex(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_2040_coex *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_2040_coex_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc && (is_input_valid(COEX2040CONFIG, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_2040_coex_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_2040_coex);
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_2040_coex *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_2040_BSS_COEX_CONTROL_TLV_ID;
+	tlv->length = sizeof(tlvbuf_2040_coex) - TLVHEADER_LEN;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->enable = (t_u8)atoi(argv[0]);
+	}
+	endian_convert_tlv_header_out(tlv);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_2040_BSS_COEX_CONTROL_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("20/40 BSS Co-existence is %s\n",
+				       (tlv->enable ==
+					0) ? "disabled" : "enabled");
+			} else {
+				printf("20/40 coex configuration successful\n");
+			}
+		} else {
+			printf("ERR:Could not %s 2040 coex configuration!\n",
+			       argc ? "set" : "get");
+			if (argc)
+				printf("20/40 coex configuration is allowed to set only before bss start.\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for setting pairwise key handshake timeout
+ *  and number of retries and sends to the driver
+ *
+ *   Usage: "sys_cfg_eapol_pwk_hsk [<TIMEOUT> <RETRIES>]"
+ *           If both TIMEOUT value and number of RETRIES are provided,
+ *           a 'set' is performed else a 'get' is performed.
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_eapol_pwk_hsk(int argc, char *argv[])
+{
+	int opt;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	t_u8 *tlv_buf = NULL;
+	t_u8 *buffer = NULL;
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_eapol_pwk_hsk_timeout *timeout_tlv = NULL;
+	tlvbuf_eapol_pwk_hsk_retries *retries_tlv = NULL;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_eapol_pwk_hsk_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check Arguments */
+	if (argc && (is_input_valid(EAPOL_PWK_HSK, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_eapol_pwk_hsk_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) +
+		sizeof(tlvbuf_eapol_pwk_hsk_timeout)
+		+ sizeof(tlvbuf_eapol_pwk_hsk_retries);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Fill the command buffer */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = argc ? ACTION_SET : ACTION_GET;
+	tlv_buf = buffer + sizeof(apcmdbuf_sys_configure);
+
+	/* Fill Timeout tlv */
+	timeout_tlv =
+		(tlvbuf_eapol_pwk_hsk_timeout *)(buffer +
+						 sizeof
+						 (apcmdbuf_sys_configure));
+	timeout_tlv->tag = MRVL_EAPOL_PWK_HSK_TIMEOUT_TLV_ID;
+	timeout_tlv->length = 4;
+	if (argv[0])
+		timeout_tlv->pairwise_update_timeout = (t_u32)atoi(argv[0]);
+	tlv_buf += sizeof(tlvbuf_eapol_pwk_hsk_timeout);
+	endian_convert_tlv_header_out(timeout_tlv);
+	timeout_tlv->pairwise_update_timeout =
+		uap_cpu_to_le32(timeout_tlv->pairwise_update_timeout);
+
+	/* Fill retries tlv */
+	retries_tlv = (tlvbuf_eapol_pwk_hsk_retries *)(tlv_buf);
+	retries_tlv->tag = MRVL_EAPOL_PWK_HSK_RETRIES_TLV_ID;
+	retries_tlv->length = 4;
+	if (argv[1])
+		retries_tlv->pwk_retries = (t_u32)atoi(argv[1]);
+	endian_convert_tlv_header_out(retries_tlv);
+	retries_tlv->pwk_retries = uap_cpu_to_le32(retries_tlv->pwk_retries);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	tlv_buf = buffer + sizeof(apcmdbuf_sys_configure);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response! cmd_code=%x\n",
+			       cmd_buf->cmd_code);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc) {
+				printf("PWK update timeout and retries setting successful\n");
+			} else {
+				print_tlv((t_u8 *)tlv_buf,
+					  cmd_buf->size -
+					  sizeof(apcmdbuf_sys_configure) +
+					  BUF_HEADER_SIZE);
+			}
+		} else {
+			printf("ERR:Could not %s pwk timeout and retries value!\n", argc ? "set" : "get");
+			if (argc)
+				printf("PWK timeout and retries are allowed to set only before bss start.\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for setting groupwise key handshake timeout
+ *  and number of retries and sends to the driver
+ *
+ *   Usage: "sys_cfg_eapol_gwk_hsk [<TIMEOUT> <RETRIES>]"
+ *           If both TIMEOUT value and number of RETRIES are provided,
+ *           a 'set' is performed else a 'get' is performed.
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_eapol_gwk_hsk(int argc, char *argv[])
+{
+	int opt;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	t_u8 *tlv_buf = NULL;
+	t_u8 *buffer = NULL;
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_eapol_gwk_hsk_timeout *timeout_tlv = NULL;
+	tlvbuf_eapol_gwk_hsk_retries *retries_tlv = NULL;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_eapol_gwk_hsk_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check Arguments */
+	if (argc && (is_input_valid(EAPOL_GWK_HSK, argc, argv) != UAP_SUCCESS)) {
+		print_sys_cfg_eapol_gwk_hsk_usage();
+		return UAP_FAILURE;
+	}
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) +
+		sizeof(tlvbuf_eapol_gwk_hsk_timeout) +
+		sizeof(tlvbuf_eapol_gwk_hsk_retries);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Fill the command buffer */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = argc ? ACTION_SET : ACTION_GET;
+	tlv_buf = buffer + sizeof(apcmdbuf_sys_configure);
+
+	/* Fill Timeout tlv */
+	timeout_tlv =
+		(tlvbuf_eapol_gwk_hsk_timeout *)(buffer +
+						 sizeof
+						 (apcmdbuf_sys_configure));
+	timeout_tlv->tag = MRVL_EAPOL_GWK_HSK_TIMEOUT_TLV_ID;
+	timeout_tlv->length = 4;
+	if (argv[0])
+		timeout_tlv->groupwise_update_timeout = (t_u32)atoi(argv[0]);
+	tlv_buf += sizeof(tlvbuf_eapol_gwk_hsk_timeout);
+	endian_convert_tlv_header_out(timeout_tlv);
+	timeout_tlv->groupwise_update_timeout =
+		uap_cpu_to_le32(timeout_tlv->groupwise_update_timeout);
+
+	/* Fill retries tlv */
+	retries_tlv = (tlvbuf_eapol_gwk_hsk_retries *)(tlv_buf);
+	retries_tlv->tag = MRVL_EAPOL_GWK_HSK_RETRIES_TLV_ID;
+	retries_tlv->length = 4;
+	if (argv[1])
+		retries_tlv->gwk_retries = (t_u32)atoi(argv[1]);
+	endian_convert_tlv_header_out(retries_tlv);
+	retries_tlv->gwk_retries = uap_cpu_to_le32(retries_tlv->gwk_retries);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	tlv_buf = buffer + sizeof(apcmdbuf_sys_configure);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response! cmd_code=%x\n",
+			       cmd_buf->cmd_code);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc) {
+				printf("GWK update timeout and retries setting successful\n");
+			} else {
+				print_tlv((t_u8 *)tlv_buf,
+					  cmd_buf->size -
+					  sizeof(apcmdbuf_sys_configure) +
+					  BUF_HEADER_SIZE);
+			}
+		} else {
+			printf("ERR:Could not %s gwk timeout and retries value!\n", argc ? "set" : "get");
+			if (argc)
+				printf("GWK timeout and retries are allowed to set only before bss start.\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Convert string to integer
+ *
+ *  @param ptr		A pointer to data buffer
+ *  @param chr 		A pointer to return integer
+ *  @return      	A pointer to next data field
+ */
+char *
+convert2hex(char *ptr, t_u8 *chr)
+{
+	t_u8 val;
+
+	for (val = 0; *ptr && isxdigit(*ptr); ptr++) {
+		val = (val * 16) + hexc2bin(*ptr);
+	}
+
+	*chr = val;
+
+	return ptr;
+}
+
+/**
+ *  @brief Parse hex data
+ *  @param fp 		A pointer to FILE stream
+ *  @param dst		A pointer to receive hex data
+ *  @return            	length of hex data
+ */
+int
+fparse_for_hex(FILE * fp, t_u8 *dst)
+{
+	char *ptr;
+	t_u8 *dptr;
+	char buf[256];
+
+	dptr = dst;
+	while (fgets(buf, sizeof(buf), fp)) {
+		ptr = buf;
+
+		while (*ptr) {
+			/* Skip leading spaces */
+			while (*ptr && (isspace(*ptr) || *ptr == '\t'))
+				ptr++;
+
+			/* Skip blank lines and lines beginning with '#' */
+			if (*ptr == '\0' || *ptr == '#')
+				break;
+
+			if (isxdigit(*ptr)) {
+				ptr = convert2hex(ptr, dptr++);
+			} else {
+				/* Invalid character on data line */
+				ptr++;
+			}
+		}
+	}
+
+	return (dptr - dst);
+}
+
+/**
+ *  @brief Creates a cfg_data request
+ *   and sends to the driver
+ *
+ *   Usage: "cfg_data <cfg_data.conf>"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_cfg_data(int argc, char *argv[])
+{
+	apcmdbuf_cfg_data *cmd_buf = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	FILE *fp = NULL;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_cfg_data_usage();
+			return UAP_FAILURE;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc == 0) || (argc > 2)) {
+		printf("ERR:wrong arguments.\n");
+		print_cfg_data_usage();
+		return UAP_FAILURE;
+	} else {
+		if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) != 2)) {
+			printf("ERR:Illegal type parameter %s. Must be '2'.\n",
+			       argv[0]);
+			print_cfg_data_usage();
+			return UAP_FAILURE;
+		}
+	}
+	buf = (t_u8 *)malloc(buf_len);
+	if (buf == NULL) {
+		printf("Error: allocate memory for hostcmd failed\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+	cmd_buf = (apcmdbuf_cfg_data *)buf;
+	if (argc == 2) {
+		/* Check if file exists */
+		fp = fopen(argv[1], "r");
+		if (fp == NULL) {
+			printf("\nERR:Config file can not open %s.\n", argv[1]);
+			free(buf);
+			return UAP_FAILURE;
+		}
+		cmd_buf->action = ACTION_SET;
+		cmd_buf->data_len = fparse_for_hex(fp, cmd_buf->data);
+		fclose(fp);
+		if (cmd_buf->data_len > MAX_CFG_DATA_SIZE) {
+			printf("ERR: Config file is too big %d\n",
+			       cmd_buf->data_len);
+			free(buf);
+			return UAP_FAILURE;
+		}
+	} else {
+		cmd_buf->action = ACTION_GET;
+		cmd_buf->data_len = 0;
+	}
+
+	cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
+	cmd_buf->type = atoi(argv[0]);
+	cmd_buf->type = uap_cpu_to_le16(cmd_buf->type);
+	cmd_buf->data_len = uap_cpu_to_le16(cmd_buf->data_len);
+
+	/* Fill the command buffer */
+	cmd_len =
+		uap_le16_to_cpu(cmd_buf->data_len) + sizeof(apcmdbuf_cfg_data);
+	cmd_buf->cmd_code = HostCmd_CMD_CFG_DATA;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		cmd_buf->action = uap_le16_to_cpu(cmd_buf->action);
+		cmd_buf->data_len = uap_le16_to_cpu(cmd_buf->data_len);
+		if (cmd_buf->action == ACTION_GET) {
+			hexdump_data("cfg_data", cmd_buf->data,
+				     cmd_buf->data_len, ' ');
+		} else
+			printf("download cfg data successful\n");
+	}
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_11n
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_11n_usage(void)
+{
+	printf("\nUsage : sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_MAP]\n");
+	printf("\nOptions: ENABLE  0 - disable");
+	printf("\n                 1 - enable");
+	printf("\n         HTCAP: HT Capabilities info");
+	printf("\n         AMPDU: A-MPDU Parameter");
+	printf("\n         TXBFCAP: TX Beamforming capabilities info");
+	printf("\n         HT_MCS_MAP: Bitmap for supported MCS rates\n");
+	printf("\n         empty - Get current 802.11n parameters\n");
+	return;
+}
+
+/**
+ *  @brief  Get Ht capability Info from firmware
+ *
+ *  @param  pHtCap  A pointer to HTCap_t structure
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+get_sys_cfg_11n(HTCap_t *pHtCap)
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_htcap_t *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len;
+	int ret = UAP_FAILURE;
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_htcap_t);
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return -1;
+	}
+	memset(buffer, 0, cmd_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_htcap_t *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = HT_CAPABILITY_TLV_ID;
+	cmd_buf->action = ACTION_GET;
+	tlv->length = sizeof(HTCap_t);
+
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != HT_CAPABILITY_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+
+		/* Copy response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			memcpy(pHtCap, &tlv->ht_cap, sizeof(HTCap_t));
+			pHtCap->ht_cap_info =
+				uap_le16_to_cpu(pHtCap->ht_cap_info);
+			pHtCap->tx_bf_cap = uap_le32_to_cpu(pHtCap->tx_bf_cap);
+			ret = UAP_SUCCESS;
+		} else {
+			ret = UAP_FAILURE;
+			printf("ERR:Could not get HT capability!\n");
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+		ret = UAP_FAILURE;
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+#ifdef RX_PACKET_COALESCE
+void
+print_rx_packet_coalesc_help()
+{
+	printf("\nUSAGE: rxpktcoal_cfg [PKT-THRESHOLD] [TIMEOUT]\n\n");
+	printf("OPTIONS:");
+	printf("PKT-THRESHOLD: count after which packets would be sent to host. Valid values 1-7\n");
+	printf("\tTIMEOUT: Time after which packets would be sent to host Valid values 1-4\n");
+	printf("\tCoalescing is disabled if both or either of PKT-THRESHOLD or TIMEOUT is zero\n\n");
+	printf("\tEmpty - Get current packet coalescing settings\n");
+}
+
+int
+apcmd_rx_pkt_coalesce(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_rx_pkt_coal_t *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_rx_packet_coalesc_help();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc) {
+		if (argc != 2) {
+			printf("ERR: Invalid no. of arguments.\n");
+			print_rx_packet_coalesc_help();
+			return UAP_FAILURE;
+		}
+		if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)) {
+			printf("ERR: Invalid arguments %s/%s. Both params must be digits.\n", argv[0], argv[1]);
+			print_rx_packet_coalesc_help();
+			return UAP_FAILURE;
+		}
+	}
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_rx_pkt_coal_t *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Initialize the command length */
+	if (argc) {
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) +
+			sizeof(tlvbuf_rx_pkt_coal_t);
+		cmd_buf->action = ACTION_SET;
+	} else {
+		cmd_len = sizeof(apcmdbuf_sys_configure) + TLVHEADER_LEN;
+		cmd_buf->action = ACTION_GET;
+	}
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	if (!argc) {
+		tlv->tag = MRVL_RX_PKT_COAL_TLV_ID;
+		tlv->length = 0;
+		//endian_convert_tlv_header_out(tlv);
+	} else {
+		tlv->length = sizeof(tlvbuf_rx_pkt_coal_t) - TLVHEADER_LEN;
+		tlv->tag = MRVL_RX_PKT_COAL_TLV_ID;
+		tlv->rx_pkt_count = uap_cpu_to_le32(atoi(argv[0]));
+		tlv->delay = uap_cpu_to_le16(atoi(argv[1]));
+	}
+
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response! cmd_code=%x\n",
+			       cmd_buf->cmd_code);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc) {
+				printf("Configure RX packet coalesce parameters successful\n");
+			} else {
+
+				print_tlv((t_u8 *)tlv, cmd_buf->size -
+					  sizeof(apcmdbuf_sys_configure) +
+					  BUF_HEADER_SIZE);
+			}
+
+		} else {
+			if (argc)
+				printf("ERR:Could not set RX packet coalesce parameters!\n");
+			else
+				printf("ERR: Could not get RX packet coalesce parameters!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+
+}
+#endif
+
+/**
+ *  @brief Creates a sys_cfg request for 11n parameters
+ *   and sends to the driver
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_11n(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_htcap_t *tlv = NULL;
+	tlvbuf_htinfo_t *ht_info_tlv = NULL;
+	HTCap_t htcap;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+	t_u32 supported_mcs_set = 0;
+	fw_info fw;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_11n_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc) {
+		if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+		    (atoi(argv[0]) > 1)) {
+			printf("ERR: Illegal ENABLE parameter %s. Must be either '0' or '1'.\n", argv[0]);
+			print_sys_cfg_11n_usage();
+			return UAP_FAILURE;
+		}
+		if (argc > 5) {
+			printf("ERR:wrong arguments.\n");
+			print_sys_cfg_11n_usage();
+			return UAP_FAILURE;
+		}
+		if (argc > 1) {
+			if (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) {
+				printf("ERR: Only Number values are allowed\n");
+				print_sys_cfg_11n_usage();
+				return UAP_FAILURE;
+			}
+			if ((((t_u16)A2HEXDECIMAL(argv[1])) &
+			     (~HT_CAP_CONFIG_MASK)) != HT_CAP_CHECK_MASK) {
+				printf("ERR: Invalid HTCAP value!\n");
+				print_sys_cfg_11n_usage();
+				return UAP_FAILURE;
+			}
+		}
+		if (argc > 2) {
+			if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) {
+				printf("ERR: Only Number values are allowed\n");
+				print_sys_cfg_11n_usage();
+				return UAP_FAILURE;
+			}
+			if ((A2HEXDECIMAL(argv[2])) > AMPDU_CONFIG_MASK) {
+				printf("ERR: Invalid AMPDU value!\n");
+				print_sys_cfg_11n_usage();
+				return UAP_FAILURE;
+			}
+		}
+		if (argc > 3) {
+			if (IS_HEX_OR_DIGIT(argv[3]) == UAP_FAILURE) {
+				printf("ERR: Only Number values are allowed\n");
+				print_sys_cfg_11n_usage();
+				return UAP_FAILURE;
+			}
+		}
+		if (argc > 4) {
+			if (IS_HEX_OR_DIGIT(argv[4]) == UAP_FAILURE) {
+				printf("ERR: Only Number values are allowed\n");
+				print_sys_cfg_11n_usage();
+				return UAP_FAILURE;
+			}
+			if (0 == get_fw_info(&fw)) {
+				/* Check upper nibble of MCS support value
+				 * and block MCS_SET_1 when 2X2 is not supported
+				 * by the underlying hardware */
+				if (((fw.hw_dev_mcs_support & 0xf0) <
+				     STREAM_2X2_MASK) &&
+				    (A2HEXDECIMAL(argv[4]) & MCS_SET_1_MASK)) {
+					printf("ERR: Invalid HT_MCS_MAP\n");
+					return UAP_FAILURE;
+				}
+			}
+		}
+		memset(&htcap, 0, sizeof(htcap));
+		if (UAP_FAILURE == get_sys_cfg_11n(&htcap)) {
+			printf("Fail to get 11n parameters from firmware\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_htcap_t *)(buffer + sizeof(apcmdbuf_sys_configure));
+	tlv->tag = HT_CAPABILITY_TLV_ID;
+
+	/* Initialize the command length */
+	if (argc) {
+		cmd_len =
+			sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_htcap_t);
+		cmd_buf->action = ACTION_SET;
+	} else {
+		cmd_len = sizeof(apcmdbuf_sys_configure) + 2 * TLVHEADER_LEN;
+		cmd_buf->action = ACTION_GET;
+	}
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	if (!argc) {
+		tlv->length = 0;
+		/* Append HT_INFO TLV only for GET */
+		ht_info_tlv =
+			(tlvbuf_htinfo_t *)(buffer +
+					    sizeof(apcmdbuf_sys_configure) +
+					    TLVHEADER_LEN);
+		ht_info_tlv->tag = HT_INFO_TLV_ID;
+		ht_info_tlv->length = 0;
+		endian_convert_tlv_header_out(ht_info_tlv);
+	} else {
+		tlv->length = sizeof(HTCap_t);
+		/* disable 802.11n */
+		if (atoi(argv[0]) == 0) {
+			if (argc > 1) {
+				printf("ERR:wrong arguments.\n");
+				print_sys_cfg_11n_usage();
+				free(buffer);
+				return UAP_FAILURE;
+			}
+			memcpy(&tlv->ht_cap, &htcap, sizeof(HTCap_t));
+			/* disable mcs rate */
+			tlv->ht_cap.supported_mcs_set[0] = 0;
+			tlv->ht_cap.supported_mcs_set[4] = 0;
+			tlv->ht_cap.supported_mcs_set[1] = 0;
+		} else {
+			t_u8 is_40MHz_supported = 0;
+			/* enable 802.11n */
+			memcpy(&tlv->ht_cap, &htcap, sizeof(HTCap_t));
+			if (0 == get_fw_info(&fw)) {
+				if ((fw.hw_dev_mcs_support & 0x0f) >= 2)
+					tlv->ht_cap.supported_mcs_set[1] =
+						DEFAULT_MCS_SET_1;
+			}
+			if (argc >= 2) {
+				tlv->ht_cap.ht_cap_info =
+					DEFAULT_HT_CAP_VALUE &
+					~HT_CAP_CONFIG_MASK;
+				tlv->ht_cap.ht_cap_info |=
+					(t_u16)A2HEXDECIMAL(argv[1]) &
+					HT_CAP_CONFIG_MASK;
+				tlv->ht_cap.ht_cap_info =
+					uap_cpu_to_le16(tlv->ht_cap.
+							ht_cap_info);
+				is_40MHz_supported =
+					tlv->ht_cap.ht_cap_info & MBIT(1);
+			}
+			/* enable mcs rate */
+			tlv->ht_cap.supported_mcs_set[0] = DEFAULT_MCS_SET_0;
+			/* enable MCS32 only in case of both 20/40 MHz support */
+			if (is_40MHz_supported)
+				tlv->ht_cap.supported_mcs_set[4] =
+					DEFAULT_MCS_SET_4;
+			else
+				tlv->ht_cap.supported_mcs_set[4] = 0;
+
+			if (argc >= 3)
+				tlv->ht_cap.ampdu_param =
+					(t_u8)A2HEXDECIMAL(argv[2]) &
+					AMPDU_CONFIG_MASK;
+			if (argc >= 4) {
+				tlv->ht_cap.tx_bf_cap =
+					(t_u32)A2HEXDECIMAL(argv[3]);
+				tlv->ht_cap.tx_bf_cap =
+					uap_cpu_to_le32(tlv->ht_cap.tx_bf_cap);
+			}
+			if (argc == 5) {
+				supported_mcs_set =
+					(t_u32)A2HEXDECIMAL(argv[4]);
+				supported_mcs_set =
+					uap_cpu_to_le32(supported_mcs_set);
+				memcpy(tlv->ht_cap.supported_mcs_set,
+				       &supported_mcs_set, sizeof(t_u32));
+			}
+		}
+	}
+
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response! cmd_code=%x\n",
+			       cmd_buf->cmd_code);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc) {
+				printf("Configure 802.11n parameters successful\n");
+			} else {
+				print_tlv((t_u8 *)tlv, cmd_buf->size -
+					  sizeof(apcmdbuf_sys_configure) +
+					  BUF_HEADER_SIZE);
+			}
+
+		} else {
+			if (argc)
+				printf("ERR:Could not set 802.11n parameters!\n");
+			else
+				printf("ERR: Could not get 802.11n parameters!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_wmm
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_wmm_usage(void)
+{
+	printf("\nUsage : sys_cfg_wmm  [qosinfo=<qos_info>] [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+	printf("\n                     [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+	printf("\n                     [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+	printf("\n                     [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+	printf("\nOptions: qosinfo - 0x80 or 0x00");
+	printf("\n         AC_BE - 0, AC_BK - 1");
+	printf("\n         AC_VI - 2, AC_VO - 3");
+	printf("\n         AIFSN - AIFSN value");
+	printf("\n         ECW_MAX: ECW max");
+	printf("\n         ECW_MIN: ECW min");
+	printf("\n         TX_OP: TXOP Limit");
+	printf("\n         empty - Get current wmm parameters\n");
+	return;
+}
+
+ /**
+@brief Show usage information for the sys_cfg_ap_wmm
+*   command
+*
+*  $return         N/A
+*/
+void
+print_sys_cfg_ap_wmm_usage(void)
+{
+	printf("\nUsage : sys_cfg_wmm  [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+	printf("\n                     [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+	printf("\n                     [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+	printf("\n                     [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]\n");
+	printf("\nOptions: AC_BE - 0, AC_BK - 1");
+	printf("\n         AC_VI - 2, AC_VO - 3");
+	printf("\n         AIFSN - AIFSN value");
+	printf("\n         ECW_MAX: ECW max");
+	printf("\n         ECW_MIN: ECW min");
+	printf("\n         TX_OP: TXOP Limit");
+	printf("\n         empty - Get current wmm parameters\n");
+	return;
+}
+
+/**
+ *  @brief  Get WMM parameters from firmware
+ *
+ *  @param  pWmm    A pointer to WmmParameter_t structure
+ *  @param  tlv_tag TLV ID
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+get_wmm_parameters(WmmParameter_t *pWmm, t_u16 tlv_tag)
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_wmm_para_t *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len;
+	t_u8 oui_type[4] = { 0x00, 0x50, 0xF2, 0x02 };
+
+	int ret = UAP_FAILURE;
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_wmm_para_t);
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return -1;
+	}
+	memset(buffer, 0, cmd_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_wmm_para_t *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = tlv_tag;
+	cmd_buf->action = ACTION_GET;
+	tlv->length = sizeof(WmmParameter_t);
+	memcpy(tlv->wmm_para.ouitype, oui_type, sizeof(oui_type));
+	tlv->wmm_para.ouisubtype = 1;
+	tlv->wmm_para.version = 1;
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != tlv_tag) ||
+		    (tlv->length != sizeof(WmmParameter_t))) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+
+		/* Copy response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			memcpy(pWmm, &tlv->wmm_para, sizeof(WmmParameter_t));
+			ret = UAP_SUCCESS;
+		} else {
+			ret = UAP_FAILURE;
+			printf("ERR:Could not get wmm parameters!\n");
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+		ret = UAP_FAILURE;
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for wmm parameters
+ *   and sends to the driver
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_wmm(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_wmm_para_t *tlv = NULL;
+	WmmParameter_t wmm_para;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int i;
+	int ret = UAP_SUCCESS;
+	int opt;
+	t_u8 ac = 0;
+	t_u8 wmm_disable = 1;
+	t_u8 qos_info = 0;
+	t_u8 flag = 0;
+	char str[13];
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_wmm_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	memset(&wmm_para, 0, sizeof(wmm_para));
+	if (UAP_FAILURE ==
+	    get_wmm_parameters(&wmm_para, VENDOR_SPECIFIC_IE_TLV_ID)) {
+		printf("Fail to get wmm parameters from firmware\n");
+		return UAP_FAILURE;
+	}
+
+	if (!argc) {
+		printf("wmm parameters:\n");
+		printf("\tqos_info = 0x%x\n", wmm_para.qos_info);
+		printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+		       wmm_para.ac_params[AC_BE].aci_aifsn.aifsn,
+		       wmm_para.ac_params[AC_BE].ecw.ecw_max,
+		       wmm_para.ac_params[AC_BE].ecw.ecw_min,
+		       uap_le16_to_cpu(wmm_para.ac_params[AC_BE].tx_op_limit));
+		printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+		       wmm_para.ac_params[AC_BK].aci_aifsn.aifsn,
+		       wmm_para.ac_params[AC_BK].ecw.ecw_max,
+		       wmm_para.ac_params[AC_BK].ecw.ecw_min,
+		       uap_le16_to_cpu(wmm_para.ac_params[AC_BK].tx_op_limit));
+		printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+		       wmm_para.ac_params[AC_VI].aci_aifsn.aifsn,
+		       wmm_para.ac_params[AC_VI].ecw.ecw_max,
+		       wmm_para.ac_params[AC_VI].ecw.ecw_min,
+		       uap_le16_to_cpu(wmm_para.ac_params[AC_VI].tx_op_limit));
+		printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+		       wmm_para.ac_params[AC_VO].aci_aifsn.aifsn,
+		       wmm_para.ac_params[AC_VO].ecw.ecw_max,
+		       wmm_para.ac_params[AC_VO].ecw.ecw_min,
+		       uap_le16_to_cpu(wmm_para.ac_params[AC_VO].tx_op_limit));
+		return UAP_SUCCESS;
+	}
+
+	if (strlen(argv[0]) > 8) {
+		if (strncmp(argv[0], "qosinfo=", 8) == 0) {
+			strncpy(str, argv[0], 12);
+			strncpy(str, strchr(str, '=') + 1, 4);
+			qos_info = A2HEXDECIMAL(str);
+			if ((qos_info != ENABLE_WMM_PS) &&
+			    (qos_info != DISABLE_WMM_PS)) {
+				printf("ERR:qos_info must be either 0x80 or 0x00\n");
+				print_sys_cfg_wmm_usage();
+				return UAP_FAILURE;
+			}
+			argc -= 1;
+			argv += 1;
+			flag = 1;
+		} else {
+			printf("ERR:Invalid argument!\n");
+			print_sys_cfg_wmm_usage();
+			return UAP_FAILURE;
+		}
+	}
+	/* Check arguments */
+	if ((argc != 1) && ((argc > 20) || ((argc > 0) && ((argc % 5) != 0)))) {
+		printf("ERR:Illegal number of parameters.\n");
+		print_sys_cfg_wmm_usage();
+		return UAP_FAILURE;
+	}
+	for (i = 0; i < argc; i++) {
+		if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) {
+			printf("ERR: Only Number values are allowed\n");
+			print_sys_cfg_wmm_usage();
+			return UAP_FAILURE;
+		}
+		if (A2HEXDECIMAL(argv[i]))
+			wmm_disable = 0;
+	}
+	if ((argc == 1) && A2HEXDECIMAL(argv[0])) {
+		printf("ERR: Only 0 is allowed to disable WMM using single parameter.\n");
+		print_sys_cfg_wmm_usage();
+		return UAP_FAILURE;
+	}
+	if (argc != 20 && argc != 1)
+		wmm_disable = 0;
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_wmm_para_t);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_wmm_para_t *)(buffer + sizeof(apcmdbuf_sys_configure));
+	tlv->tag = VENDOR_SPECIFIC_IE_TLV_ID;
+	tlv->length = sizeof(WmmParameter_t);
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = ACTION_SET;
+	endian_convert_tlv_header_out(tlv);
+
+	memcpy(&tlv->wmm_para, &wmm_para, sizeof(WmmParameter_t));
+	if (wmm_disable) {
+		/* clear AC parameters to disalbe wmm */
+		memset((t_u8 *)tlv->wmm_para.ac_params, 0,
+		       sizeof(IEEEtypes_WmmAcParameters_t) * MAX_AC_QUEUES);
+	} else {
+		if (flag) {
+			if (qos_info)
+				tlv->wmm_para.qos_info =
+					wmm_para.qos_info | qos_info;
+			else
+				tlv->wmm_para.qos_info =
+					wmm_para.qos_info & WMM_PS_MASK;
+		}
+		for (i = 0; i < (argc / 5); i++) {
+			ac = (t_u8)A2HEXDECIMAL(argv[i * 5]);
+			if (ac > AC_VO) {
+				printf("ERR: Invalid AC queue index, Only support AC_BE, AC_BK, AC_VI, AC_VO\n");
+				print_sys_cfg_wmm_usage();
+				free(buffer);
+				return UAP_FAILURE;
+			}
+			tlv->wmm_para.ac_params[ac].aci_aifsn.aifsn =
+				(t_u8)A2HEXDECIMAL(argv[i * 5 + 1]);
+			tlv->wmm_para.ac_params[ac].aci_aifsn.aci = (t_u8)ac;
+			tlv->wmm_para.ac_params[ac].ecw.ecw_max =
+				(t_u8)A2HEXDECIMAL(argv[i * 5 + 2]);
+			tlv->wmm_para.ac_params[ac].ecw.ecw_min =
+				(t_u8)A2HEXDECIMAL(argv[i * 5 + 3]);
+			tlv->wmm_para.ac_params[ac].tx_op_limit =
+				uap_cpu_to_le16((t_u16)
+						A2HEXDECIMAL(argv[i * 5 + 4]));
+		}
+	}
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != VENDOR_SPECIFIC_IE_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("Configure wmm parameters successful\n");
+
+		} else {
+			printf("ERR:Could not set wmm parameters!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+*  @param argc     Number of arguments
+*  @param argv     Pointer to the arguments
+*  @return         UAP_SUCCESS/UAP_FAILURE
+*/
+int
+apcmd_sys_cfg_ap_wmm(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_wmm_para_t *tlv = NULL;
+	WmmParameter_t wmm_para;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int i;
+	int opt;
+	t_u8 ac = 0;
+	t_u8 wmm_reset = 1;
+	int ret = UAP_SUCCESS;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_ap_wmm_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	memset(&wmm_para, 0, sizeof(wmm_para));
+	if (UAP_FAILURE ==
+	    get_wmm_parameters(&wmm_para, MRVL_AP_WMM_PARAM_TLV_ID)) {
+		printf("Fail to get ap wmm parameters from firmware\n");
+		return UAP_FAILURE;
+	}
+
+	if (!argc) {
+		printf("ap wmm parameters:\n");
+		printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+		       wmm_para.ac_params[AC_BE].aci_aifsn.aifsn,
+		       wmm_para.ac_params[AC_BE].ecw.ecw_max,
+		       wmm_para.ac_params[AC_BE].ecw.ecw_min,
+		       uap_le16_to_cpu(wmm_para.ac_params[AC_BE].tx_op_limit));
+		printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+		       wmm_para.ac_params[AC_BK].aci_aifsn.aifsn,
+		       wmm_para.ac_params[AC_BK].ecw.ecw_max,
+		       wmm_para.ac_params[AC_BK].ecw.ecw_min,
+		       uap_le16_to_cpu(wmm_para.ac_params[AC_BK].tx_op_limit));
+		printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+		       wmm_para.ac_params[AC_VI].aci_aifsn.aifsn,
+		       wmm_para.ac_params[AC_VI].ecw.ecw_max,
+		       wmm_para.ac_params[AC_VI].ecw.ecw_min,
+		       uap_le16_to_cpu(wmm_para.ac_params[AC_VI].tx_op_limit));
+		printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+		       wmm_para.ac_params[AC_VO].aci_aifsn.aifsn,
+		       wmm_para.ac_params[AC_VO].ecw.ecw_max,
+		       wmm_para.ac_params[AC_VO].ecw.ecw_min,
+		       uap_le16_to_cpu(wmm_para.ac_params[AC_VO].tx_op_limit));
+		return UAP_SUCCESS;
+	}
+
+	/* Check arguments */
+	if ((argc != 1) && ((argc > 20) || ((argc > 0) && ((argc % 5) != 0)))) {
+		printf("ERR:Illegal number of parameters.\n");
+		print_sys_cfg_ap_wmm_usage();
+		return UAP_FAILURE;
+	}
+	for (i = 0; i < argc; i++) {
+		if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) {
+			printf("ERR: Only Number values are allowed\n");
+			print_sys_cfg_ap_wmm_usage();
+			return UAP_FAILURE;
+		}
+		if (A2HEXDECIMAL(argv[i]))
+			wmm_reset = 0;
+	}
+	if ((argc == 1) && A2HEXDECIMAL(argv[0])) {
+		printf("ERR: Only 0 is allowed to reset AP WMM using single parameter.\n");
+		print_sys_cfg_ap_wmm_usage();
+		return UAP_FAILURE;
+	}
+	if (argc != 20 && argc != 1)
+		wmm_reset = 0;
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_wmm_para_t);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_wmm_para_t *)(buffer + sizeof(apcmdbuf_sys_configure));
+	tlv->tag = MRVL_AP_WMM_PARAM_TLV_ID;
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = ACTION_SET;
+	endian_convert_tlv_header_out(tlv);
+
+	memcpy(&tlv->wmm_para, &wmm_para, sizeof(WmmParameter_t));
+	if (wmm_reset) {
+		/* clear AC parameters to reset ap wmm */
+		memset((t_u8 *)tlv->wmm_para.ac_params, 0,
+		       sizeof(IEEEtypes_WmmAcParameters_t) * MAX_AC_QUEUES);
+	} else {
+		for (i = 0; i < (argc / 5); i++) {
+			ac = (t_u8)A2HEXDECIMAL(argv[i * 5]);
+			if (ac > AC_VO) {
+				printf("ERR: Invalid AC queue index, Only support AC_BE, AC_BK, AC_VI, AC_VO\n");
+				print_sys_cfg_ap_wmm_usage();
+				free(buffer);
+				return UAP_FAILURE;
+			}
+			tlv->wmm_para.ac_params[ac].aci_aifsn.aifsn =
+				(t_u8)A2HEXDECIMAL(argv[i * 5 + 1]);
+			tlv->wmm_para.ac_params[ac].aci_aifsn.aci = (t_u8)ac;
+			tlv->wmm_para.ac_params[ac].ecw.ecw_max =
+				(t_u8)A2HEXDECIMAL(argv[i * 5 + 2]);
+			tlv->wmm_para.ac_params[ac].ecw.ecw_min =
+				(t_u8)A2HEXDECIMAL(argv[i * 5 + 3]);
+			tlv->wmm_para.ac_params[ac].tx_op_limit =
+				uap_cpu_to_le16((t_u16)
+						A2HEXDECIMAL(argv[i * 5 + 4]));
+		}
+	}
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_AP_WMM_PARAM_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("Configure ap wmm parameters successful\n");
+		} else {
+			printf("ERR:Could not set ap wmm parameters!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_restrict_client_mode
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_restrict_client_mode_usage(void)
+{
+	printf("\nUsage : sys_cfg_restrict_client_mode [<ENABLE> [MODE_CONFIG]]\n");
+	printf("\nOptions:");
+	printf("\n        Bit 0: 1 �enable restricted client mode");
+	printf("\n               0 �disable restricted client mode");
+	printf("\n        Bits [1-7] : set to 0");
+	printf("\n        Bits [8:12]:");
+	printf("\n               Bit 8: B only Mode");
+	printf("\n               Bit 9: A only Mode");
+	printf("\n               Bit 10: G only Mode");
+	printf("\n               Bit 11: N only Mode");
+	printf("\n               Bit 12: AC only Mode");
+	printf("\n        Bits [13:15]: set to 0");
+	printf("\n");
+	printf("\n        Empty - Get current restricted client mode setting.\n");
+	return;
+}
+
+/**
+ *  @brief Creates a sys_cfg request to Set/Get restricted client mode
+ *  and sends to the driver
+ *
+ *   Usage: "sys_cfg_restrict_client_mode [<ENABLE> [MODE_CONFIG]]"
+ *           If arguments are provided, a 'set' is performed
+ *           else a 'get' is performed.
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_restrict_client_mode(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_restrict_client_mode *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_restrict_client_mode_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc &&
+	    is_input_valid(RESTRICT_CLIENT_MODE, argc, argv) != UAP_SUCCESS) {
+		print_sys_cfg_restrict_client_mode_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_restrict_client_mode *)(buffer +
+					      sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_RESTRICT_CLIENT_MODE_TLV_ID;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+		tlv->length = 0;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		tlv->length = sizeof(t_u16);
+		tlv->mode_config =
+			(t_u16)((tlv->
+				 mode_config | RESTRICT_CLIENT_MODE_ENABLE_MASK)
+				& atoi(argv[0]));
+		if (argc == 2) {
+			tlv->mode_config |= (t_u16)(A2HEXDECIMAL(argv[1]) << 8);
+		}
+		tlv->mode_config = uap_cpu_to_le16(tlv->mode_config);
+	}
+	cmd_buf->size =
+		sizeof(apcmdbuf_sys_configure) +
+		sizeof(tlvbuf_restrict_client_mode);
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) +
+		sizeof(tlvbuf_restrict_client_mode);
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_RESTRICT_CLIENT_MODE_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				tlv->mode_config =
+					uap_le16_to_cpu(tlv->mode_config);
+				printf("Restricted Client Mode: %s\n",
+				       (tlv->
+					mode_config &
+					RESTRICT_CLIENT_MODE_ENABLE_MASK) ?
+				       "Enabled" : "Disabled");
+				if (tlv->
+				    mode_config &
+				    RESTRICT_CLIENT_MODE_ENABLE_MASK) {
+					printf("Current client mode : ");
+					if (tlv->mode_config & B_ONLY_MASK)
+						printf("B Only\n");
+					else if (tlv->mode_config & A_ONLY_MASK)
+						printf("A Only\n");
+					else if (tlv->mode_config & G_ONLY_MASK)
+						printf("G Only\n");
+					else if (tlv->mode_config & N_ONLY_MASK)
+						printf("N Only\n");
+					else if (tlv->
+						 mode_config & AC_ONLY_MASK)
+						printf("AC Only\n");
+				}
+			} else {
+				printf("Restricted client mode setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get restrict client mode setting!\n");
+			} else {
+				printf("ERR:Could not set restrict client mode setting!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
diff --git a/wlan_sd8897/mapp/uaputl/uapcmd.h b/wlan_sd8897/mapp/uaputl/uapcmd.h
new file mode 100644
index 0000000..8ceacc0
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/uapcmd.h
@@ -0,0 +1,79 @@
+/** @file  uapcmd.h
+ *
+ *  @brief This file contains declaration referring to
+ *  functions defined in uapcmd.c
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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/01/08: Initial creation
+************************************************************************/
+
+#ifndef _UAPCMD_H
+#define _UAPCMD_H
+
+/** Function Prototype Declaration */
+int apcmd_sys_cfg_ap_mac_address(int argc, char *argv[]);
+int apcmd_sys_cfg_ssid(int argc, char *argv[]);
+int apcmd_sys_cfg_beacon_period(int argc, char *argv[]);
+int apcmd_sys_cfg_dtim_period(int argc, char *argv[]);
+int apcmd_sys_cfg_bss_status(int argc, char *argv[]);
+int apcmd_sys_cfg_channel(int argc, char *argv[]);
+int apcmd_sys_cfg_channel_ext(int argc, char *argv[]);
+int apcmd_sys_cfg_scan_channels(int argc, char *argv[]);
+int apcmd_sys_cfg_rates(int argc, char *argv[]);
+int apcmd_sys_cfg_rates_ext(int argc, char *argv[]);
+int apcmd_sys_cfg_tx_power(int argc, char *argv[]);
+int apcmd_sys_cfg_bcast_ssid_ctl(int argc, char *argv[]);
+int apcmd_sys_cfg_preamble_ctl(int argc, char *argv[]);
+int apcmd_sys_cfg_rts_threshold(int argc, char *argv[]);
+int apcmd_sys_cfg_frag_threshold(int argc, char *argv[]);
+int apcmd_sys_cfg_radio_ctl(int argc, char *argv[]);
+int apcmd_sys_cfg_rsn_replay_prot(int argc, char *argv[]);
+int apcmd_sys_cfg_tx_beacon_rate(int argc, char *argv[]);
+int apcmd_sys_cfg_mcbc_data_rate(int argc, char *argv[]);
+int apcmd_sys_cfg_pkt_fwd_ctl(int argc, char *argv[]);
+int apcmd_sys_cfg_sta_ageout_timer(int argc, char *argv[]);
+int apcmd_sys_cfg_ps_sta_ageout_timer(int argc, char *argv[]);
+int apcmd_sys_cfg_auth(int argc, char *argv[]);
+int apcmd_sys_cfg_protocol(int argc, char *argv[]);
+int apcmd_sys_cfg_wep_key(int argc, char *argv[]);
+int apcmd_sys_cfg_cipher(int argc, char *argv[]);
+int apcmd_sys_cfg_pwk_cipher(int argc, char *argv[]);
+int apcmd_sys_cfg_gwk_cipher(int argc, char *argv[]);
+int apcmd_sys_cfg_wpa_passphrase(int argc, char *argv[]);
+int apcmd_sys_cfg_group_rekey_timer(int argc, char *argv[]);
+int apcmd_sta_filter_table(int argc, char *argv[]);
+int apcmd_sys_cfg_max_sta_num(int argc, char *argv[]);
+int apcmd_sys_cfg_retry_limit(int argc, char *argv[]);
+int apcmd_sys_cfg_sticky_tim_config(int argc, char *argv[]);
+int apcmd_sys_cfg_sticky_tim_sta_mac_addr(int argc, char *argv[]);
+int apcmd_sys_cfg_eapol_pwk_hsk(int argc, char *argv[]);
+int apcmd_sys_cfg_eapol_gwk_hsk(int argc, char *argv[]);
+int apcmd_cfg_data(int argc, char *argv[]);
+int apcmd_sys_cfg_custom_ie(int argc, char *argv[]);
+int apcmd_sys_cfg_wmm(int argc, char *argv[]);
+int apcmd_sys_cfg_ap_wmm(int argc, char *argv[]);
+int apcmd_sys_cfg_11n(int argc, char *argv[]);
+#ifdef RX_PACKET_COALESCE
+int apcmd_rx_pkt_coalesce(int argc, char *argv[]);
+void print_rx_packet_coalesc_help(void);
+#endif
+int apcmd_sys_cfg_2040_coex(int argc, char *argv[]);
+int apcmd_sys_cfg_restrict_client_mode(int argc, char *argv[]);
+#endif /* _UAP_H */
diff --git a/wlan_sd8897/mapp/uaputl/uaphostcmd.c b/wlan_sd8897/mapp/uaputl/uaphostcmd.c
new file mode 100644
index 0000000..21c97e0
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/uaphostcmd.c
@@ -0,0 +1,335 @@
+/** @file  uaphostcmd.c
+  *
+  * @brief This file contains uAP hostcmd functions
+  *
+  * Copyright (C) 2010-2017, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/************************************************************************
+Change log:
+     11/26/2008: initial version
+************************************************************************/
+
+#include    <stdlib.h>
+#include    <stdio.h>
+#include    <string.h>
+#include    <ctype.h>
+#include	"uaputl.h"
+
+#ifndef MIN
+/** Find minimum value */
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+/*
+ *  @brief convert String to integer
+ *
+ *  @param value	A pointer to string
+ *  @return             integer
+ */
+static t_u32
+a2hex_or_atoi(char *value)
+{
+	if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) {
+		return a2hex(value + 2);
+	} else if (isdigit(*value)) {
+		return atoi(value);
+	} else {
+		return *value;
+	}
+}
+
+/**
+ *  @brief Get one line from the File
+ *
+ *  @param fp       File handler
+ *  @param str	    Storage location for data.
+ *  @param size 	Maximum number of characters to read.
+ *  @param lineno	A pointer to return current line number
+ *  @return         returns string or NULL
+ */
+char *
+mlan_config_get_line(FILE * fp, char *str, t_s32 size, int *lineno)
+{
+	char *start, *end;
+	int out, next_line;
+
+	if (!fp || !str)
+		return NULL;
+
+	do {
+read_line:
+		if (!fgets(str, size, fp))
+			break;
+		start = str;
+		start[size - 1] = '\0';
+		end = start + strlen(str);
+		(*lineno)++;
+
+		out = 1;
+		while (out && (start < end)) {
+			next_line = 0;
+			/* Remove empty lines and lines starting with # */
+			switch (start[0]) {
+			case ' ':	/* White space */
+			case '\t':	/* Tab */
+				start++;
+				break;
+			case '#':
+			case '\n':
+			case '\0':
+				next_line = 1;
+				break;
+			case '\r':
+				if (start[1] == '\n')
+					next_line = 1;
+				else
+					start++;
+				break;
+			default:
+				out = 0;
+				break;
+			}
+			if (next_line)
+				goto read_line;
+		}
+
+		/* Remove # comments unless they are within a double quoted
+		 * string. Remove trailing white space. */
+		if ((end = strstr(start, "\""))) {
+			if (!(end = strstr(end + 1, "\"")))
+				end = start;
+		} else
+			end = start;
+
+		if ((end = strstr(end + 1, "#")))
+			*end-- = '\0';
+		else
+			end = start + strlen(start) - 1;
+
+		out = 1;
+		while (out && (start < end)) {
+			switch (*end) {
+			case ' ':	/* White space */
+			case '\t':	/* Tab */
+			case '\n':
+			case '\r':
+				*end = '\0';
+				end--;
+				break;
+			default:
+				out = 0;
+				break;
+			}
+		}
+
+		if (start == '\0')
+			continue;
+
+		return start;
+	} while (1);
+
+	return NULL;
+}
+
+/**
+ *  @brief get hostcmd data
+ *
+ *  @param ln			A pointer to line number
+ *  @param buf			A pointer to hostcmd data
+ *  @param size			A pointer to the return size of hostcmd buffer
+ *  @return      		UAP_SUCCESS
+ */
+static int
+mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
+{
+	t_s32 errors = 0, i;
+	char line[256], *pos, *pos1, *pos2, *pos3;
+	t_u16 len;
+
+	while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
+		(*ln)++;
+		if (strcmp(pos, "}") == 0) {
+			break;
+		}
+
+		pos1 = strchr(pos, ':');
+		if (pos1 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos1++ = '\0';
+
+		pos2 = strchr(pos1, '=');
+		if (pos2 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+		*pos2++ = '\0';
+
+		len = a2hex_or_atoi(pos1);
+		if (len < 1 || len > MRVDRV_SIZE_OF_CMD_BUFFER) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
+			       pos);
+			errors++;
+			continue;
+		}
+
+		*size += len;
+
+		if (*pos2 == '"') {
+			pos2++;
+			if ((pos3 = strchr(pos2, '"')) == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln,
+				       pos);
+				errors++;
+				continue;
+			}
+			*pos3 = '\0';
+			memset(buf, 0, len);
+			memmove(buf, pos2, MIN(strlen(pos2), len));
+			buf += len;
+		} else if (*pos2 == '\'') {
+			pos2++;
+			if ((pos3 = strchr(pos2, '\'')) == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln,
+				       pos);
+				errors++;
+				continue;
+			}
+			*pos3 = ',';
+			for (i = 0; i < len; i++) {
+				if ((pos3 = strchr(pos2, ',')) != NULL) {
+					*pos3 = '\0';
+					*buf++ = (t_u8)a2hex_or_atoi(pos2);
+					pos2 = pos3 + 1;
+				} else
+					*buf++ = 0;
+			}
+		} else if (*pos2 == '{') {
+			t_u16 tlvlen = 0, tmp_tlvlen;
+			mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen);
+			tmp_tlvlen = tlvlen;
+			while (len--) {
+				*buf++ = (t_u8)(tmp_tlvlen & 0xff);
+				tmp_tlvlen >>= 8;
+			}
+			*size += tlvlen;
+			buf += tlvlen;
+		} else {
+			t_u32 value = a2hex_or_atoi(pos2);
+			while (len--) {
+				*buf++ = (t_u8)(value & 0xff);
+				value >>= 8;
+			}
+		}
+	}
+	return UAP_SUCCESS;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+
+/**
+ *  @brief Prepare host-command buffer
+ *  @param fname	path to the config file
+ *  @param cmd_name	Command name
+ *  @param buf		A pointer to comand buffer
+ *  @return      	UAP_SUCCESS--success, otherwise--fail
+ */
+int
+prepare_host_cmd_buffer(char *fname, char *cmd_name, t_u8 *buf)
+{
+	char line[256], cmdname[256], *pos, cmdcode[10];
+	apcmdbuf *hostcmd;
+	int ln = 0;
+	int cmdname_found = 0, cmdcode_found = 0;
+	FILE *config_fp;
+	int ret = UAP_SUCCESS;
+
+	config_fp = fopen(fname, "r");
+
+	if (!config_fp) {
+		printf("Unable to find %s. Exiting...\n", fname);
+		return UAP_FAILURE;
+	}
+
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	hostcmd = (apcmdbuf *)buf;
+	hostcmd->cmd_code = 0xffff;
+
+	snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name);
+	cmdname_found = 0;
+	while ((pos = mlan_config_get_line(config_fp, line, sizeof(line), &ln))) {
+		if (strcmp(pos, cmdname) == 0) {
+			cmdname_found = 1;
+			snprintf(cmdcode, sizeof(cmdcode), "CmdCode=");
+			cmdcode_found = 0;
+			while ((pos =
+				mlan_config_get_line(config_fp, line,
+						     sizeof(line), &ln))) {
+				if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) {
+					cmdcode_found = 1;
+					hostcmd->cmd_code =
+						a2hex_or_atoi(pos +
+							      strlen(cmdcode));
+					hostcmd->size =
+						sizeof(apcmdbuf) -
+						BUF_HEADER_SIZE;
+					mlan_get_hostcmd_data(config_fp, &ln,
+							      buf +
+							      sizeof(apcmdbuf),
+							      &hostcmd->size);
+					break;
+				}
+			}
+			if (!cmdcode_found) {
+				fprintf(stderr,
+					"uaputl: CmdCode not found in conf file\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			break;
+		}
+	}
+
+	if (!cmdname_found) {
+		fprintf(stderr,
+			"uaputl: cmdname '%s' is not found in conf file\n",
+			cmd_name);
+		ret = UAP_FAILURE;
+		goto done;
+	}
+done:
+	fclose(config_fp);
+	return ret;
+}
diff --git a/wlan_sd8897/mapp/uaputl/uaputl.c b/wlan_sd8897/mapp/uaputl/uaputl.c
new file mode 100644
index 0000000..184e9b0
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/uaputl.c
@@ -0,0 +1,14350 @@
+/** @file  uaputl.c
+ *
+ *  @brief Program to send AP commands to the driver/firmware of the uAP
+ *         driver.
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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/01/08: Initial creation
+****************************************************************************/
+
+/****************************************************************************
+        Header files
+****************************************************************************/
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include "uaputl.h"
+#include "uapcmd.h"
+
+/****************************************************************************
+        Definitions
+****************************************************************************/
+/** Default debug level */
+int debug_level = MSG_NONE;
+
+/** Enable or disable debug outputs */
+#define DEBUG   1
+
+/** Convert character to integer */
+#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0'))
+
+/** Supported stream modes */
+#define HT_STREAM_MODE_1X1   0x11
+#define HT_STREAM_MODE_2X2   0x22
+
+static int get_bss_config(t_u8 *buf);
+
+/****************************************************************************
+        Global variables
+****************************************************************************/
+/** Device name */
+static char dev_name[IFNAMSIZ + 1];
+/** Option for cmd */
+struct option cmd_options[] = {
+	{"help", 0, 0, 'h'},
+	{0, 0, 0, 0}
+};
+
+/** Flag to check if custom IE is present in sys_config response from FW */
+int custom_ie_present = 0;
+
+/** Flag to check if max mgmt IE is printed in sys_config response from FW */
+int max_mgmt_ie_print = 0;
+
+/** Flag to bypass re-route path */
+int uap_ioctl_no_reroute = 0;
+
+/****************************************************************************
+        Local functions
+****************************************************************************/
+/**
+ *    @brief Convert char to hex integer
+ *
+ *    @param chr          Char
+ *    @return             Hex integer
+ */
+unsigned char
+hexc2bin(char chr)
+{
+	if (chr >= '0' && chr <= '9')
+		chr -= '0';
+	else if (chr >= 'A' && chr <= 'F')
+		chr -= ('A' - 10);
+	else if (chr >= 'a' && chr <= 'f')
+		chr -= ('a' - 10);
+
+	return chr;
+}
+
+/**
+ *  @brief Check protocol is valid or not
+ *
+ *  @param protocol    	     Protocol
+ *
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_protocol_valid(int protocol)
+{
+	int ret = UAP_FAILURE;
+	switch (protocol) {
+	case PROTOCOL_NO_SECURITY:
+	case PROTOCOL_STATIC_WEP:
+	case PROTOCOL_WPA:
+	case PROTOCOL_WPA2:
+	case PROTOCOL_WPA2_MIXED:
+		ret = UAP_SUCCESS;
+		break;
+	default:
+		printf("ERR: Invalid Protocol: %d\n", protocol);
+		break;
+	}
+	return ret;
+}
+
+/**
+ *  @brief Function to check valid rate
+ *
+ *
+ *  @param  rate    Rate to verify
+ *
+ *  return 	    UAP_SUCCESS or UAP_FAILURE
+ **/
+int
+is_rate_valid(int rate)
+{
+	int ret = UAP_SUCCESS;
+	switch (rate) {
+	case 2:
+	case 4:
+	case 11:
+	case 22:
+	case 12:
+	case 18:
+	case 24:
+	case 48:
+	case 72:
+	case 96:
+	case 108:
+	case 36:
+		break;
+	default:
+		ret = UAP_FAILURE;
+		break;
+	}
+	return ret;
+}
+
+/**
+ *  @brief Check for mandatory rates
+ *
+ *
+ * 2, 4, 11, 22 must be present
+ *
+ * 6 12 and 24 must be present for ofdm
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_FAILURE or UAP_SUCCESS
+ *
+ */
+static int
+check_mandatory_rates(int argc, char **argv)
+{
+	int i;
+	int tmp;
+	t_u32 rate_bitmap = 0;
+	int cck_enable = 0;
+	int ofdm_enable = 0;
+#define BITMAP_RATE_1M         0x01
+#define BITMAP_RATE_2M         0x02
+#define BITMAP_RATE_5_5M       0x04
+#define BITMAP_RATE_11M        0x8
+#define B_RATE_MANDATORY       0x0f
+#define BITMAP_RATE_6M         0x10
+#define BITMAP_RATE_12M        0x20
+#define BITMAP_RATE_24M        0x40
+#define G_RATE_MANDATORY        0x70
+	for (i = 0; i < argc; i++) {
+		tmp = (A2HEXDECIMAL(argv[i]) & ~BASIC_RATE_SET_BIT);
+		switch (tmp) {
+		case 2:
+			cck_enable = 1;
+			rate_bitmap |= BITMAP_RATE_1M;
+			break;
+		case 4:
+			cck_enable = 1;
+			rate_bitmap |= BITMAP_RATE_2M;
+			break;
+		case 11:
+			cck_enable = 1;
+			rate_bitmap |= BITMAP_RATE_5_5M;
+			break;
+		case 22:
+			cck_enable = 1;
+			rate_bitmap |= BITMAP_RATE_11M;
+			break;
+		case 12:
+			ofdm_enable = 1;
+			rate_bitmap |= BITMAP_RATE_6M;
+			break;
+		case 24:
+			ofdm_enable = 1;
+			rate_bitmap |= BITMAP_RATE_12M;
+			break;
+		case 48:
+			ofdm_enable = 1;
+			rate_bitmap |= BITMAP_RATE_24M;
+			break;
+		case 18:
+		case 36:
+		case 72:
+		case 96:
+		case 108:
+			ofdm_enable = 1;
+			break;
+		}
+	}
+#ifdef WIFI_DIRECT_SUPPORT
+	if (strncmp(dev_name, "wfd", 3))
+#endif
+		if ((rate_bitmap & B_RATE_MANDATORY) != B_RATE_MANDATORY) {
+			if (cck_enable) {
+				printf("Basic Rates 2, 4, 11 and 22 (500K units) \n" "must be present in basic or non-basic rates\n");
+				return UAP_FAILURE;
+			}
+		}
+	if (ofdm_enable &&
+	    ((rate_bitmap & G_RATE_MANDATORY) != G_RATE_MANDATORY)) {
+		printf("OFDM Rates 12, 24 and 48 ( 500Kb units)\n"
+		       "must be present in basic or non-basic rates\n");
+		return UAP_FAILURE;
+	}
+	return UAP_SUCCESS;
+}
+
+/**
+ *    @brief Convert string to hex integer
+ *
+ *    @param s            A pointer string buffer
+ *    @return             Hex integer
+ */
+unsigned int
+a2hex(char *s)
+{
+	unsigned int val = 0;
+	if (!strncasecmp("0x", s, 2)) {
+		s += 2;
+	}
+	while (*s && isxdigit(*s)) {
+		val = (val << 4) + hexc2bin(*s++);
+	}
+	return val;
+}
+
+/**
+ *  @brief Dump hex data
+ *
+ *  @param prompt	A pointer prompt buffer
+ *  @param p		A pointer to data buffer
+ *  @param len		The len of data buffer
+ *  @param delim	Delim char
+ *  @return            	None
+ */
+void
+hexdump_data(char *prompt, void *p, int len, char delim)
+{
+	int i;
+	unsigned char *s = p;
+
+	if (prompt) {
+		printf("%s: len=%d\n", prompt, (int)len);
+	}
+	for (i = 0; i < len; i++) {
+		if (i != len - 1)
+			printf("%02x%c", *s++, delim);
+		else
+			printf("%02x\n", *s);
+		if ((i + 1) % 16 == 0)
+			printf("\n");
+	}
+	printf("\n");
+}
+
+#if DEBUG
+/**
+ * @brief           Conditional printf
+ *
+ * @param level     Severity level of the message
+ * @param fmt       Printf format string, followed by optional arguments
+ */
+void
+uap_printf(int level, char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	if (level <= debug_level) {
+		vprintf(fmt, ap);
+	}
+	va_end(ap);
+}
+
+/**
+ *  @brief Dump hex data
+ *
+ *  @param prompt	A pointer prompt buffer
+ *  @param p		A pointer to data buffer
+ *  @param len		The len of data buffer
+ *  @param delim	Delim char
+ *  @return            	None
+ */
+void
+hexdump(char *prompt, void *p, int len, char delim)
+{
+	if (debug_level < MSG_ALL)
+		return;
+	hexdump_data(prompt, p, len, delim);
+}
+#endif
+
+/**
+ *  @brief      Hex to number
+ *
+ *  @param c    Hex value
+ *  @return     Integer value or -1
+ */
+int
+hex2num(char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+
+	return -1;
+}
+
+/**
+ *  @brief Show usage information for the sys_info command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_info_usage(void)
+{
+	printf("\nUsage : sys_info\n");
+	return;
+}
+
+/**
+ *  @brief  Get Max sta num from firmware
+ *
+ *  @return     max number of stations
+ */
+int
+get_max_sta_num_supported(t_u16 *max_sta_num_supported)
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_max_sta_num *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_max_sta_num);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_max_sta_num *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_MAX_STA_CNT_TLV_ID;
+	tlv->length = 4;
+	cmd_buf->action = ACTION_GET;
+
+	endian_convert_tlv_header_out(tlv);
+	tlv->max_sta_num_configured =
+		uap_cpu_to_le16(tlv->max_sta_num_configured);
+	tlv->max_sta_num_supported =
+		uap_cpu_to_le16(tlv->max_sta_num_supported);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->max_sta_num_configured =
+		uap_le16_to_cpu(tlv->max_sta_num_configured);
+	tlv->max_sta_num_supported =
+		uap_le16_to_cpu(tlv->max_sta_num_supported);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_MAX_STA_CNT_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result != CMD_SUCCESS) {
+			printf("ERR:Could not get max station number!\n");
+			ret = UAP_FAILURE;
+		} else {
+			if (tlv->length == 4) {
+				*max_sta_num_supported =
+					tlv->max_sta_num_supported;
+			} else {
+				*max_sta_num_supported = MAX_STA_COUNT;
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Parse domain name for domain_code
+ *
+ *  @param dom_name  Domain name
+ *  @return domain_code / UAP_FAILURE
+ */
+static t_u8
+parse_domain_name(char *domain_name)
+{
+	t_u8 domain_code = UAP_FAILURE;
+
+	if (strstr(domain_name, "DOMAIN_CODE_")) {
+		domain_name += sizeof("DOMAIN_CODE_") - 1;
+
+		if (!(strncmp(domain_name, "FCC", sizeof("FCC") - 1)))
+			domain_code = DOMAIN_CODE_FCC;
+		else if (!(strcmp(domain_name, "ETSI")))
+			domain_code = DOMAIN_CODE_ETSI;
+		else if (!(strcmp(domain_name, "MKK")))
+			domain_code = DOMAIN_CODE_MKK;
+		else if (!(strcmp(domain_name, "IN")))
+			domain_code = DOMAIN_CODE_IN;
+		else if (!(strcmp(domain_name, "MY")))
+			domain_code = DOMAIN_CODE_MY;
+	}
+	return domain_code;
+}
+
+/**
+ *  @brief Parse domain file for country information
+ *
+ *  @param country  Country name
+ *  @param band    Band Info. 0x01 : B band, 0x02 : G band, 0x04 : A band.
+ *  @param sub_bands Band information
+ *  @param pdomain_code Pointer to receive domain_code
+ *  @return number of band/ UAP_FAILURE
+ */
+t_u8
+parse_domain_file(char *country, int band, ieeetypes_subband_set_t *sub_bands,
+		  t_u8 *pdomain_code)
+{
+	FILE *fp;
+	char str[64];
+	char domain_name[64];
+	int cflag = 0;
+	int dflag = 0;
+	int found = 0;
+	int skip = 0;
+	int j = -1, reset_j = 0;
+	t_u8 no_of_sub_band = 0;
+	char *strp = NULL;
+
+	fp = fopen("config/80211d_domain.conf", "r");
+	if (fp == NULL) {
+		printf("File opening Error\n");
+		return UAP_FAILURE;
+	}
+
+    /**
+     * Search specific domain name
+     */
+	memset(str, 0, 64);
+	while (!feof(fp)) {
+		fscanf(fp, "%63s", str);
+		if (cflag) {
+			strncpy(domain_name, str, sizeof(domain_name) - 1);
+			cflag = 0;
+		}
+		if (!strcmp(str, "COUNTRY:")) {
+	    /** Store next string to domain_name */
+			cflag = 1;
+		}
+
+		if (!strcmp(str, country)) {
+	    /** Country is matched ;)*/
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		printf("No match found for Country = %s in the 80211d_domain.conf \n", country);
+		fclose(fp);
+		found = 0;
+		return UAP_FAILURE;
+	}
+
+    /**
+     * Search domain specific information
+     */
+	while (!feof(fp)) {
+		fscanf(fp, "%63s", str);
+
+		if (feof(fp)
+			) {
+			break;
+		}
+
+		if (dflag && !strcmp(str, "DOMAIN:")) {
+
+			if ((band & BAND_A) == 0)
+				break;
+
+			/* parse next domain */
+			cflag = 0;
+			dflag = 0;
+			j = -1;
+			reset_j = 0;
+		}
+		if (dflag) {
+			j++;
+			if (strchr(str, ','))
+				reset_j = 1;
+
+			strp = strtok(str, ", ");
+
+			if (strp == NULL) {
+				if (reset_j) {
+					j = -1;
+					reset_j = 0;
+				}
+				continue;
+			} else {
+				strncpy(str, strp, (sizeof(str) - 1));
+			}
+
+			if (IS_HEX_OR_DIGIT(str) == UAP_FAILURE) {
+				printf("ERR: Only Number values are allowed\n");
+				fclose(fp);
+				return UAP_FAILURE;
+			}
+
+			switch (j) {
+			case 0:
+				sub_bands[no_of_sub_band].first_chan =
+					(t_u8)A2HEXDECIMAL(str);
+				break;
+			case 1:
+				sub_bands[no_of_sub_band].no_of_chan =
+					(t_u8)A2HEXDECIMAL(str);
+				break;
+			case 2:
+				sub_bands[no_of_sub_band++].max_tx_pwr =
+					(t_u8)A2HEXDECIMAL(str);
+				break;
+			default:
+				printf("ERR: Incorrect 80211d_domain.conf file\n");
+				fclose(fp);
+				return UAP_FAILURE;
+			}
+
+			if (reset_j) {
+				j = -1;
+				reset_j = 0;
+			}
+		}
+
+		if (cflag && !strcmp(str, domain_name)) {
+			/* Followed will be the band details */
+			cflag = 0;
+			if (band & (BAND_B | BAND_G) || skip)
+				dflag = 1;
+			else
+				skip = 1;
+		}
+		if (!dflag && !strcmp(str, "DOMAIN:")) {
+			cflag = 1;
+		}
+	}
+	fclose(fp);
+
+	if (pdomain_code && no_of_sub_band && (band & BAND_A)) {
+		*pdomain_code = parse_domain_name(domain_name);
+	}
+	return (no_of_sub_band);
+}
+
+/**
+ *
+ *  @brief Set/Get SNMP MIB
+ *
+ *  @param action 0-GET 1-SET
+ *  @param oid    Oid
+ *  @param size   Size of oid value
+ *  @param oid_buf  Oid value
+ *  @return UAP_FAILURE or UAP_SUCCESS
+ *
+ */
+int
+sg_snmp_mib(t_u16 action, t_u16 oid, t_u16 size, t_u8 *oid_buf)
+{
+	apcmdbuf_snmp_mib *cmd_buf = NULL;
+	tlvbuf_header *tlv = NULL;
+	int ret = UAP_FAILURE;
+	t_u8 *buf = NULL;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	t_u16 cmd_len;
+	int i;
+
+	cmd_len = sizeof(apcmdbuf_snmp_mib) + sizeof(tlvbuf_header) + size;
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return ret;
+	}
+	memset(buf, 0, buf_len);
+
+	/* Locate Headers */
+	cmd_buf = (apcmdbuf_snmp_mib *)buf;
+	tlv = (tlvbuf_header *)(buf + sizeof(apcmdbuf_snmp_mib));
+	cmd_buf->size = buf_len - BUF_HEADER_SIZE;
+	cmd_buf->result = 0;
+	cmd_buf->seq_num = 0;
+	cmd_buf->cmd_code = HostCmd_SNMP_MIB;
+
+	tlv->type = uap_cpu_to_le16(oid);
+	tlv->len = uap_cpu_to_le16(size);
+	for (i = 0; action && (i < size); i++) {
+		tlv->data[i] = oid_buf[i];
+	}
+
+	cmd_buf->action = uap_cpu_to_le16(action);
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (!action) {
+		/** Relocate the headers */
+				tlv = (tlvbuf_header *)((t_u8 *)cmd_buf +
+							sizeof
+							(apcmdbuf_snmp_mib));
+				for (i = 0;
+				     i < MIN(uap_le16_to_cpu(tlv->len), size);
+				     i++) {
+					oid_buf[i] = tlv->data[i];
+				}
+			}
+			ret = UAP_SUCCESS;
+		} else {
+			printf("ERR:Command Response incorrect!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_info request and sends to the driver
+ *
+ *  Usage: "sys_info"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_info(int argc, char *argv[])
+{
+	apcmdbuf_sys_info_request *cmd_buf = NULL;
+	apcmdbuf_sys_info_response *response_buf = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_info_usage();
+			return UAP_FAILURE;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 0) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_info_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Alloc buf for command */
+	buf = (t_u8 *)malloc(buf_len);
+
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+
+	/* Locate headers */
+	cmd_len = sizeof(apcmdbuf_sys_info_request);
+	cmd_buf = (apcmdbuf_sys_info_request *)buf;
+	response_buf = (apcmdbuf_sys_info_response *)buf;
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_INFO;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (response_buf->cmd_code !=
+		    (APCMD_SYS_INFO | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			free(buf);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (response_buf->result == CMD_SUCCESS) {
+			printf("System information = %s\n",
+			       response_buf->sys_info);
+		} else {
+			printf("ERR:Could not retrieve system information!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+
+	free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for deepsleep command
+ *
+ *  $return         N/A
+ */
+void
+print_deepsleep_usage(void)
+{
+	printf("\nUsage : deepsleep [MODE][IDLE_TIME]");
+	printf("\nOptions: MODE : 0 - Disable auto deep sleep mode");
+	printf("\n                1 - Enable auto deep sleep mode");
+	printf("\n         IDLE_TIME: Idle time in milliseconds, default value is 100 ms");
+	printf("\n         empty - get auto deep sleep mode\n");
+	return;
+}
+
+/**
+ *  @brief Creates deepsleep  request and send to driver
+ *
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_deepsleep(int argc, char *argv[])
+{
+	int opt;
+	deep_sleep_para param;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_deepsleep_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&param, 0, sizeof(param));
+	/* Check arguments */
+	if (argc > 2) {
+		printf("ERR:wrong arguments. Only support 2 arguments\n");
+		print_deepsleep_usage();
+		return UAP_FAILURE;
+	}
+	param.subcmd = UAP_DEEP_SLEEP;
+	if (argc) {
+		if (argc >= 1) {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
+			    ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 1))) {
+				printf("ERR: Only Number values are allowed\n");
+				print_deepsleep_usage();
+				return UAP_FAILURE;
+			}
+		}
+		param.action = 1;
+		param.deep_sleep = (t_u16)A2HEXDECIMAL(argv[0]);
+		param.idle_time = 0;
+		if (argc == 2) {
+			if (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) {
+				printf("ERR: Only Number values are allowed\n");
+				print_deepsleep_usage();
+				return UAP_FAILURE;
+			}
+			param.idle_time = (t_u16)A2HEXDECIMAL(argv[1]);
+		}
+	} else {
+		param.action = 0;
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		if (argc)
+			printf("ERR: deep sleep must be disabled before changing idle time\n");
+		else {
+			perror("");
+			printf("ERR:deep sleep failed\n");
+		}
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (!argc) {
+		if (param.deep_sleep == 1) {
+			printf("deep sleep mode: enabled\n");
+			printf("idle time = %dms\n", param.idle_time);
+		} else {
+			printf("deep sleep mode: disabled\n");
+		}
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for tx_data_pause command
+ *
+ *  $return         N/A
+ */
+void
+print_txdatapause_usage(void)
+{
+	printf("\nUsage : tx_data_pause [ENABLE][TX_BUF_CNT]");
+	printf("\nOptions: ENABLE : 0 - Disable Tx data pause events");
+	printf("\n                  1 - Enable Tx data pause events");
+	printf("\n         TX_BUF_CNT: Max number of TX buffer for PS clients");
+	printf("\n         empty - get Tx data pause settings\n");
+	return;
+}
+
+/**
+ *  @brief Set/get txpause setting
+ *
+ *  @param txpause  A pointer to the Tx data pause parameters structure
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+send_txpause_ioctl(tx_data_pause_para *txpause)
+{
+	struct ifreq ifr;
+	t_s32 sockfd;
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)txpause;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR:txpause is not supported by %s\n", dev_name);
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Creates tx_data_pause request and sends to driver
+ *
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_txdatapause(int argc, char *argv[])
+{
+	int opt;
+	tx_data_pause_para param;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_txdatapause_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&param, 0, sizeof(param));
+	/* Check arguments */
+	if (argc > 2) {
+		printf("ERR: Wrong number of arguments\n");
+		print_txdatapause_usage();
+		return UAP_FAILURE;
+	}
+	param.subcmd = UAP_TX_DATA_PAUSE;
+	if (argc) {
+		if (argc >= 1) {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
+			    ((atoi(argv[0]) < TX_DATA_PAUSE_DISABLE) ||
+			     (atoi(argv[0]) > TX_DATA_PAUSE_ENABLE))) {
+				printf("ERR: First argument can either be 0 or 1\n");
+				print_txdatapause_usage();
+				return UAP_FAILURE;
+			}
+		}
+		if (argc == 1) {
+			param.action = ACTION_GET;
+			if (UAP_FAILURE == send_txpause_ioctl(&param)) {
+				return UAP_FAILURE;
+			}
+		}
+		param.action = ACTION_SET;
+		param.txpause = (t_u16)A2HEXDECIMAL(argv[0]);
+		if (argc == 2) {
+			if (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) {
+				printf("ERR: Max buffer length must be numeric\n");
+				print_txdatapause_usage();
+				return UAP_FAILURE;
+			}
+			param.txbufcnt = (t_u16)A2HEXDECIMAL(argv[1]);
+		}
+	} else {
+		param.action = ACTION_GET;
+	}
+	if (UAP_FAILURE == send_txpause_ioctl(&param))
+		return UAP_FAILURE;
+	if ((argc == 2) && ((t_u16)A2HEXDECIMAL(argv[1]) != param.txbufcnt)) {
+		printf("Max number of TX buffer allowed for all PS client: %d\n", param.txbufcnt);
+		return UAP_FAILURE;
+	}
+	if (!argc) {
+		printf("Tx data pause: %s\n",
+		       (param.txpause == 1) ? "enabled" : "disabled");
+		printf("Max number of TX buffer allowed for all PS client: %d\n", param.txbufcnt);
+	}
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Process host_cmd
+ *
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         N/A
+ */
+int
+apcmd_hostcmd(int argc, char *argv[])
+{
+	apcmdbuf *hdr;
+	t_u8 *buffer = NULL;
+	int ret = UAP_SUCCESS;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	char cmdname[256];
+
+	if (argc <= 2) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./uaputl hostcmd <hostcmd.conf> <cmdname>\n");
+		return UAP_FAILURE;
+	}
+
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+
+	memset(buffer, 0, buf_len);
+	sprintf(cmdname, "%s", argv[2]);
+	ret = prepare_host_cmd_buffer(argv[1], cmdname, buffer);
+	if (ret == UAP_FAILURE)
+		goto _exit_;
+
+	/* Locate headers */
+	hdr = (apcmdbuf *)buffer;
+	cmd_len = hdr->size + BUF_HEADER_SIZE;
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)buffer, &cmd_len, buf_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		hdr->cmd_code &= HostCmd_CMD_ID_MASK;
+		if (!hdr->result) {
+			printf("UAPHOSTCMD: CmdCode=%#04x, Size=%#04x, SeqNum=%#04x, Result=%#04x\n", hdr->cmd_code, hdr->size, hdr->seq_num, hdr->result);
+			hexdump_data("payload",
+				     (void *)(buffer + APCMDHEADERLEN),
+				     hdr->size - (APCMDHEADERLEN -
+						  BUF_HEADER_SIZE), ' ');
+		} else
+			printf("UAPHOSTCMD failed: CmdCode=%#04x, Size=%#04x, SeqNum=%#04x, Result=%#04x\n", hdr->cmd_code, hdr->size, hdr->seq_num, hdr->result);
+	} else
+		printf("ERR:Command sending failed!\n");
+
+_exit_:
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for cmd52rw command
+ *
+ *  $return         N/A
+ */
+void
+print_cmd52rw_usage(void)
+{
+	printf("\nUsage : sdcmd52rw <FN no.> <address> [data]");
+	printf("\nOptions: FN no : SDIO function number.");
+	printf("\n         address: SDIO address");
+	printf("\n         data: data for SDIO write operation.");
+	printf("\n               Read is performed if data is not provided.");
+	return;
+}
+
+/**
+ *  @brief Process cmd52 read/write handler
+ *
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         N/A
+ */
+int
+apcmd_cmd52_readwrite(int argc, char *argv[])
+{
+	int opt;
+	sdcmd52_para param;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_cmd52rw_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&param, 0, sizeof(sdcmd52_para));
+	/* Check arguments */
+	if (argc < 2 || argc > 3) {
+		printf("ERR:wrong arguments.\n");
+		print_cmd52rw_usage();
+		return UAP_FAILURE;
+	}
+	if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
+	    (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE)) {
+		printf("ERR: Only Number values are allowed\n");
+		print_cmd52rw_usage();
+		return UAP_FAILURE;
+	}
+	param.cmd52_params[0] = (t_u8)A2HEXDECIMAL(argv[0]);
+	if (param.cmd52_params[0] > 7) {
+		printf("ERR: Invalid function number!\n");
+		return UAP_FAILURE;
+	}
+	param.cmd52_params[1] = (t_u8)A2HEXDECIMAL(argv[1]);
+	param.action = 0;
+	if (argc == 3) {
+		if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) {
+			printf("ERR: Only Number values are allowed\n");
+			print_cmd52rw_usage();
+			return UAP_FAILURE;
+		}
+		param.cmd52_params[2] = (t_u8)A2HEXDECIMAL(argv[2]);
+		param.action = 1;
+	}
+	param.subcmd = UAP_SDCMD52_RW;
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR:cmd52rw failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (argc == 2)
+		printf("Cmd52 read done. ");
+	else
+		printf("Cmd52 write done. ");
+	printf("func=%d, reg=%d, data=0x%02X\n",
+	       param.cmd52_params[0], param.cmd52_params[1],
+	       param.cmd52_params[2]);
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for addbapara command
+ *
+ *  $return         N/A
+ */
+void
+print_addbapara_usage(void)
+{
+	printf("\nUsage : addbapara [timeout txwinsize rxwinsize]");
+	printf("\nOptions: timeout : 0 - Disable");
+	printf("\n                   1 - 65535 : Block Ack Timeout in TU");
+	printf("\n         txwinsize: Buffer size for ADDBA request");
+	printf("\n         rxwinsize: Buffer size for ADDBA response");
+	printf("\n         txamsdu: amsdu for ADDBA request");
+	printf("\n         rxamsdu: amsdu for ADDBA response");
+	printf("\n         empty - get ADDBA parameters\n");
+	return;
+}
+
+/**
+ *  @brief Creates addbaparam request and send to driver
+ *
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_addbapara(int argc, char *argv[])
+{
+	int opt;
+	addba_param param;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_addbapara_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&param, 0, sizeof(param));
+	/* Check arguments */
+	if ((argc != 0) && (argc != 5)) {
+		printf("ERR:wrong arguments. Only support 0 or 5 arguments\n");
+		print_addbapara_usage();
+		return UAP_FAILURE;
+	}
+	param.subcmd = UAP_ADDBA_PARA;
+	if (argc) {
+		if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE)
+		    || (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE)
+		    || (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE)
+		    || (IS_HEX_OR_DIGIT(argv[3]) == UAP_FAILURE)
+		    || (IS_HEX_OR_DIGIT(argv[4]) == UAP_FAILURE)
+			) {
+			printf("ERR: Only Number values are allowed\n");
+			print_addbapara_usage();
+			return UAP_FAILURE;
+		}
+		param.action = 1;
+		param.timeout = (t_u32)A2HEXDECIMAL(argv[0]);
+		if (param.timeout > DEFAULT_BLOCK_ACK_TIMEOUT) {
+			printf("ERR: Block Ack timeout should be in range [1-65535]\n");
+			print_addbapara_usage();
+			return UAP_FAILURE;
+		}
+		param.txwinsize = (t_u32)A2HEXDECIMAL(argv[1]);
+		param.rxwinsize = (t_u32)A2HEXDECIMAL(argv[2]);
+		if (param.txwinsize > MAX_TXRX_WINDOW_SIZE ||
+		    param.rxwinsize > MAX_TXRX_WINDOW_SIZE) {
+			printf("ERR: Tx/Rx window size should not be greater than 1023\n");
+			print_addbapara_usage();
+			return UAP_FAILURE;
+		}
+		param.txamsdu = (t_u8)A2HEXDECIMAL(argv[3]);
+		param.rxamsdu = (t_u8)A2HEXDECIMAL(argv[4]);
+		if (param.txamsdu > 1 || param.rxamsdu > 1) {
+			printf("ERR: Tx/Rx amsdu should not be 0 or 1\n");
+			print_addbapara_usage();
+			return UAP_FAILURE;
+		}
+	} else {
+		param.action = 0;
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR:ADDBA PARA failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (!argc) {
+		printf("ADDBA parameters:\n");
+		printf("\ttimeout=%d\n", (int)param.timeout);
+		printf("\ttxwinsize=%d\n", (int)param.txwinsize);
+		printf("\trxwinsize=%d\n", (int)param.rxwinsize);
+		printf("\ttxamsdu=%d\n", (int)param.txamsdu);
+		printf("\trxamsdu=%d\n", (int)param.rxamsdu);
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for aggrpriotbl command
+ *
+ *  $return         N/A
+ */
+void
+print_aggrpriotbl_usage(void)
+{
+	printf("\nUsage : aggrpriotbl <m0> <n0> <m1> <n1> ... <m7> <n7>");
+	printf("\nOptions: <mx> : 0 - 7, 0xff to disable AMPDU aggregation.");
+	printf("\n         <nx> : 0 - 7, 0xff to disable AMSDU aggregation.");
+	printf("\n         empty - get the priority table\n");
+	return;
+}
+
+/**
+ *  @brief Creates aggrpriotbl request and send to driver
+ *
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_aggrpriotbl(int argc, char *argv[])
+{
+	int opt;
+	aggr_prio_tbl prio_tbl;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	t_u8 value;
+	int i;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_aggrpriotbl_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&prio_tbl, 0, sizeof(prio_tbl));
+	/* Check arguments */
+	if ((argc != 0) && (argc != 16)) {
+		printf("ERR:wrong arguments. Only support 0 or 16 arguments\n");
+		print_aggrpriotbl_usage();
+		return UAP_FAILURE;
+	}
+	prio_tbl.subcmd = UAP_AGGR_PRIOTBL;
+	if (argc) {
+		for (i = 0; i < argc; i++) {
+			if ((IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE)) {
+				printf("ERR: Only Number values are allowed\n");
+				print_aggrpriotbl_usage();
+				return UAP_FAILURE;
+			}
+			value = (t_u8)A2HEXDECIMAL(argv[i]);
+			if ((value > 7) && (value != 0xff)) {
+				printf("ERR: Invalid priority, Valid value 0-7, 0xff to disable aggregation.\n");
+				print_aggrpriotbl_usage();
+				return UAP_FAILURE;
+			}
+		}
+		prio_tbl.action = 1;
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			prio_tbl.ampdu[i] = (t_u8)A2HEXDECIMAL(argv[i * 2]);
+			prio_tbl.amsdu[i] = (t_u8)A2HEXDECIMAL(argv[i * 2 + 1]);
+		}
+	} else {
+		prio_tbl.action = 0;
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&prio_tbl;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: priority table failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (!argc) {
+		printf("AMPDU/AMSDU priority table:");
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			printf(" %d %d", prio_tbl.ampdu[i], prio_tbl.amsdu[i]);
+		}
+		printf("\n");
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for addbareject command
+ *
+ *  $return         N/A
+ */
+void
+print_addba_reject_usage(void)
+{
+	printf("\nUsage : addbareject <m0> <m1> ... <m7>");
+	printf("\nOptions: <mx> : 1 enables rejection of ADDBA request for TidX.");
+	printf("\n                0 would accept any ADDBAs for TidX.");
+	printf("\n         empty - get the addbareject table\n");
+	return;
+}
+
+/**
+ *  @brief Creates addbareject request and send to driver
+ *
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_addbareject(int argc, char *argv[])
+{
+	int opt;
+	addba_reject_para param;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	int i;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_addba_reject_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&param, 0, sizeof(param));
+	/* Check arguments */
+	if ((argc != 0) && (argc != 8)) {
+		printf("ERR:wrong arguments. Only support 0 or 8 arguments\n");
+		print_addba_reject_usage();
+		return UAP_FAILURE;
+	}
+	param.subcmd = UAP_ADDBA_REJECT;
+	if (argc) {
+		for (i = 0; i < argc; i++) {
+			if ((ISDIGIT(argv[i]) == UAP_FAILURE) ||
+			    (atoi(argv[i]) < 0) || (atoi(argv[i]) > 1)) {
+				printf("ERR: Only allow 0 or 1\n");
+				print_addba_reject_usage();
+				return UAP_FAILURE;
+			}
+		}
+		param.action = 1;
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			param.addba_reject[i] = (t_u8)atoi(argv[i]);
+		}
+	} else {
+		param.action = 0;
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: addba reject table failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (!argc) {
+		printf("addba reject table: ");
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			printf("%d ", param.addba_reject[i]);
+		}
+		printf("\n");
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Creates get_fw_info request and send to driver
+ *
+ *
+ *  @param pfw_info Pointer to FW information structure
+ *  @return         0--success, otherwise fail
+ */
+int
+get_fw_info(fw_info *pfw_info)
+{
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	memset(pfw_info, 0, sizeof(fw_info));
+	pfw_info->subcmd = UAP_FW_INFO;
+	pfw_info->action = 0;
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return -1;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)pfw_info;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: get fw info failed\n");
+		close(sockfd);
+		return -1;
+	}
+	/* Close socket */
+	close(sockfd);
+	return 0;
+}
+
+/**
+ *  @brief Show usage information for HT Tx command
+ *
+ *  $return         N/A
+ */
+void
+print_ht_tx_usage(void)
+{
+	printf("\nUsage : httxcfg [<txcfg>] [<band>]");
+	printf("\nOptions: txcfg : This is a bitmap and should be used as following");
+	printf("\n                      Bit 15-7: Reserved set to 0");
+	printf("\n                      Bit 6: Short GI in 40 Mhz enable/disable");
+	printf("\n                      Bit 5: Short GI in 20 Mhz enable/disable");
+	printf("\n                      Bit 4: Green field enable/disable");
+	printf("\n                      Bit 3-2: Reserved set to 0");
+	printf("\n                      Bit 1: 20/40 Mhz enable disable.");
+	printf("\n                      Bit 0: Reserved set to 0");
+	printf("\n          band : This is the band info for <txcfg> settings.");
+	printf("\n                      0: Settings for both 2.4G and 5G bands");
+	printf("\n                      1: Settings for 2.4G band");
+	printf("\n                      2: Settings for 5G band\n");
+	return;
+}
+
+/**
+ *  @brief Process HT Tx configuration
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+apcmd_sys_cfg_ht_tx(int argc, char *argv[])
+{
+	int opt;
+	ht_tx_cfg_para param;
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_ht_tx_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&param, 0, sizeof(param));
+	/* Check arguments */
+	if (argc == 0) {
+		param.action = ACTION_GET;
+	} else if (argc <= 2) {
+		param.action = ACTION_SET;
+		param.tx_cfg.httxcap = (t_u16)A2HEXDECIMAL(argv[0]);
+		if (argc == 2) {
+			if (atoi(argv[1]) != BAND_SELECT_BG &&
+			    atoi(argv[1]) != BAND_SELECT_A &&
+			    atoi(argv[1]) != BAND_SELECT_BOTH) {
+				printf("ERR:Invalid band selection\n");
+				return UAP_FAILURE;
+			}
+			param.tx_cfg.misc_cfg = (t_u32)A2HEXDECIMAL(argv[1]);
+		}
+	} else {
+		print_ht_tx_usage();
+		return UAP_FAILURE;
+	}
+	param.subcmd = UAP_HT_TX_CFG;
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: HT Tx configuration failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+
+	/* Handle response */
+	if (param.action == ACTION_GET) {
+		printf("HT Tx cfg: \n");
+		printf("    BG band:  0x%08x\n", param.tx_cfg.httxcap);
+		printf("    A band :  0x%08x\n", param.tx_cfg.misc_cfg);
+	}
+
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for vhtcfg command
+ *
+ *  $return         N/A
+ */
+void
+print_vht_usage(void)
+{
+	printf("\nUsage : vhtcfg <band> <txrx> <bwcfg> <vhtcap> <tx_mcs_map>"
+	       "<rx_mcs_map>");
+	printf("\nOption:  band : This is the band info for vhtcfg settings.");
+	printf("\n                      0: Settings for both 2.4G and 5G bands");
+	printf("\n                      1: Settings for 2.4G band");
+	printf("\n                      2: Settings for 5G band");
+	printf("\n         txrx : This parameter specifies the configuration of VHT" "operation for TX or/and VHT capabilities.");
+	printf("\n                      1: configuration of VHT capabilities tx");
+	printf("\n                      2: configuration of VHT capabilities rx");
+	printf("\n         bwcfg : This parameter specifies the bandwidth (BW)"
+	       "configuration applied to the vhtcfg.");
+	printf("\n                  If <txrx> is 1/3 (Tx operations)");
+	printf("\n                      0: Tx BW follows the BW (20/40 MHz) from" "11N CFG");
+	printf("\n                      1: Tx BW follows the BW (80/160/80+80 MHz)" "from VHT Capabilities.");
+	printf("\n         vhtcap : This parameter specifies the VHT capabilities info.");
+	printf("\n         tx_mcs_map : This parameter specifies the TX MCS map.");
+	printf("\n         rx_mcs_map : This parameter specifies the RX MCS map.\n");
+	return;
+}
+
+/**
+ *  @brief Handle response of the vhtcfg command
+ *
+ *  @param vhtcfg    Pointer to structure eth_priv_vhtcfg
+ *
+ *  $return         N/A
+ */
+void
+print_vht_response(struct eth_priv_vhtcfg *vhtcfg)
+{
+	/* GET operation */
+	/* Band */
+	if (vhtcfg->band == BAND_SELECT_BG)
+		printf("Band: 2.4G\n");
+	else
+		printf("Band: 5G\n");
+	/* BW confi9 */
+	if (vhtcfg->txrx & 0x3) {
+		if (vhtcfg->bwcfg == 0)
+			printf("    BW config: the 11N config\n");
+		else
+			printf("    BW config: the VHT Capabilities\n");
+	}
+	/* Tx/Rx */
+	if (vhtcfg->txrx & 0x1)
+		printf("    VHT operation for Tx: 0x%08x\n",
+		       vhtcfg->vht_cap_info);
+	if (vhtcfg->txrx & 0x2)
+		/* VHT capabilities */
+		printf("    VHT Capabilities Info: 0x%08x\n",
+		       vhtcfg->vht_cap_info);
+	/* MCS */
+	printf("    Tx MCS set: 0x%04x\n", vhtcfg->vht_tx_mcs);
+	printf("    Rx MCS set: 0x%04x\n", vhtcfg->vht_rx_mcs);
+}
+
+/**
+ *  @brief Set/Get 11AC configurations
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+apcmd_sys_cfg_vht(int argc, char *argv[])
+{
+	int opt, i = 0;
+	vht_cfg_para param;
+	struct eth_priv_vhtcfg vhtcfg;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	t_u8 *respbuf = NULL, num = 0;
+	fw_info fw;
+
+	if (0 == get_fw_info(&fw)) {
+		/*check whether support 802.11AC through BAND_AAC bit */
+		if (!(fw.fw_bands & BAND_AAC)) {
+			printf("ERR: No support 802 11AC.\n");
+			return UAP_FAILURE;
+		}
+	} else {
+		printf("ERR: get_fw_info fail\n");
+		return UAP_FAILURE;
+	}
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_vht_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	respbuf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!respbuf) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(respbuf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	/* Check arguments */
+	if ((argc > 6) || (argc < 2)) {
+		printf("ERR: Invalid number of arguments.\n");
+		print_vht_usage();
+		free(respbuf);
+		return UAP_FAILURE;
+	}
+	if ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 2)) {
+		printf("ERR: Invalid band selection.\n");
+		print_vht_usage();
+		free(respbuf);
+		return UAP_FAILURE;
+	} else {
+		param.vht_cfg.band = (t_u32)A2HEXDECIMAL(argv[0]);
+	}
+	if ((atoi(argv[1]) <= 0) || (atoi(argv[1]) > 3)) {
+		printf("ERR: Invalid Tx/Rx selection.\n");
+		print_vht_usage();
+		free(respbuf);
+		return UAP_FAILURE;
+	} else {
+		param.vht_cfg.txrx = (t_u32)A2HEXDECIMAL(argv[1]);
+	}
+	if (argc == 2) {
+		param.action = ACTION_GET;
+	} else if (argc > 2) {
+		param.vht_cfg.band = (t_u32)A2HEXDECIMAL(argv[0]);
+		param.vht_cfg.txrx = (t_u32)A2HEXDECIMAL(argv[1]);
+		if (argc == 3) {
+			printf("ERR: Invalid number of arguments.\n");
+			print_vht_usage();
+			free(respbuf);
+			return UAP_FAILURE;
+		}
+		if (argc >= 4) {
+			if ((atoi(argv[2]) < 0) || (atoi(argv[2]) > 1) ||
+			    ((atoi(argv[2]) == 1) &&
+			     (atoi(argv[0]) & BAND_SELECT_BG))) {
+				printf("ERR: Invalid BW cfg selection.\n");
+				print_vht_usage();
+				free(respbuf);
+				return UAP_FAILURE;
+			} else {
+				param.vht_cfg.bwcfg =
+					(t_u32)A2HEXDECIMAL(argv[2]);
+			}
+			param.vht_cfg.vht_cap_info =
+				(t_u32)A2HEXDECIMAL(argv[3]);
+			if (argc == 4) {
+				param.vht_cfg.vht_tx_mcs = 0xffffffff;
+				param.vht_cfg.vht_rx_mcs = 0xffffffff;
+			} else {
+				if (argc == 5) {
+					printf("ERR: Invalid number of arguments.\n");
+					print_vht_usage();
+					free(respbuf);
+					return UAP_FAILURE;
+				}
+				param.vht_cfg.vht_tx_mcs =
+					(t_u32)A2HEXDECIMAL(argv[4]);
+				param.vht_cfg.vht_rx_mcs =
+					(t_u32)A2HEXDECIMAL(argv[5]);
+			}
+		}
+		param.action = ACTION_SET;
+	} else {
+		print_vht_usage();
+		free(respbuf);
+		return UAP_FAILURE;
+	}
+	param.subcmd = UAP_VHT_CFG;
+	memcpy(respbuf, &param, sizeof(vht_cfg_para));
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		free(respbuf);
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)respbuf;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: 11ac VHT configuration failed\n");
+		close(sockfd);
+		free(respbuf);
+		return UAP_FAILURE;
+	}
+
+	/* Handle response */
+	if (param.action == ACTION_GET) {
+		/* Process result */
+		/* the first attribute is the number of vhtcfg entries */
+		num = *respbuf;
+		printf("11AC VHT Configuration: \n");
+		for (i = 0; i < num; i++) {
+			memcpy(&vhtcfg, respbuf + 1 + i * sizeof(vhtcfg),
+			       sizeof(vhtcfg));
+			print_vht_response(&vhtcfg);
+		}
+	} else
+		printf("11AC VHT Configuration success!\n");
+
+	/* Close socket */
+	close(sockfd);
+	if (respbuf)
+		free(respbuf);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for TX BF command
+ *
+ *  $return         N/A
+ */
+void
+print_tx_bf_usage(void)
+{
+	printf("\nUsage : httxbfcfg <ACTION> [ACT_DATA]");
+	printf("\nOptions: ACTION : 1 - Performs NDP Sounding for PEER");
+	printf("\n                  2 - TX BF interval in milliseconds");
+	printf("\n                  3 - Not to perform any sounding");
+	printf("\n                  4 - TX BF SNR Threshold for peer");
+	printf("\n         ACT_DATA : Specific data for the above actions");
+	printf("\n                    For 1: PEER MAC and status");
+	printf("\n                    For 2: TX BF interval");
+	printf("\n                    For 3: PEER MAC");
+	printf("\n                    For 4: PEER MAC and SNR");
+	printf("\n                    empty - get action specific settings\n");
+	return;
+}
+
+/**
+ *  @brief Handle response of the TX BF command
+ *
+ *  @param param    Pointer to structure tx_bf_cfg_para
+ *
+ *  $return         N/A
+ */
+void
+print_tx_bf_response(tx_bf_cfg_para *param)
+{
+	int i;
+	trigger_sound_args *bf_sound = param->body.bf_sound;
+	tx_bf_peer_args *tx_bf_peer = param->body.tx_bf_peer;
+	snr_thr_args *bf_snr = param->body.bf_snr;
+	bf_periodicity_args *bf_periodicity = param->body.bf_periodicity;
+	bf_global_cfg_args *bf_global = &param->body.bf_global_cfg;
+
+	switch (param->bf_action) {
+	case BF_GLOBAL_CONFIGURATION:
+		printf("Global BF Status :%s\n",
+		       bf_global->bf_enbl ? "ENABLED" : "DISABLED");
+		printf("Global Sounding Status :%s\n",
+		       bf_global->sounding_enbl ? "ENABLED" : "DISABLED");
+		printf("Default FB Type :%d\n", bf_global->fb_type);
+		printf("Default SNR Threshold :%d\n", bf_global->snr_threshold);
+		printf("Default Sounding Interval :%d\n",
+		       bf_global->sounding_interval);
+		printf("Beamforming Mode :%d\n", bf_global->bf_mode);
+		break;
+	case TRIGGER_SOUNDING_FOR_PEER:
+		printf("PEER MAC = %02X:%02X:%02X:%02X:%02X:%02X, STATUS = %s\n", bf_sound->peer_mac[0], bf_sound->peer_mac[1], bf_sound->peer_mac[2], bf_sound->peer_mac[3], bf_sound->peer_mac[4], bf_sound->peer_mac[5], bf_sound->status ? "Failure" : "Success");
+		break;
+	case SET_GET_BF_PERIODICITY:
+		printf("PEER MAC = %02x:%02x:%02x:%02x:%02x:%02x, Interval (ms) = %d\n", 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], bf_periodicity->interval);
+		break;
+	case TX_BF_FOR_PEER_ENBL:
+		for (i = 0; i < param->no_of_peers; i++) {
+			printf("PEER MAC = %02x:%02x:%02x:%02x:%02x:%02x\n",
+			       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]);
+			printf("BF Status : %s\n",
+			       tx_bf_peer->bf_enbl ? "ENABLED" : "DISABLED");
+			printf("Sounding Status : %s\n",
+			       tx_bf_peer->
+			       sounding_enbl ? "ENABLED" : "DISABLED");
+			printf("FB Type : %d\n", tx_bf_peer->fb_type);
+			tx_bf_peer++;
+		}
+		break;
+	case SET_SNR_THR_PEER:
+		for (i = 0; i < param->no_of_peers; i++) {
+			printf("PEER MAC = %02x:%02x:%02x:%02x:%02x:%02x, SNR = %d\n", 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], bf_snr->snr);
+			bf_snr++;
+		}
+		break;
+	}
+}
+
+/** 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 Creates TX BF request and send to driver
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_tx_bf(int argc, char *argv[])
+{
+	int opt, ret = UAP_FAILURE;
+	tx_bf_cfg_para param;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	t_u32 bf_action = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_tx_bf_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&param, 0, sizeof(param));
+	/* Check arguments */
+	if (argc < 1) {
+		printf("ERR: wrong arguments.\n");
+		print_tx_bf_usage();
+		return UAP_FAILURE;
+	}
+	if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
+	    ((atoi(argv[0]) < BF_GLOBAL_CONFIGURATION) ||
+	     (atoi(argv[0]) > SET_SNR_THR_PEER))) {
+		printf("ERR: Only Number values are allowed\n");
+		print_tx_bf_usage();
+		return UAP_FAILURE;
+	}
+	bf_action = (t_u32)A2HEXDECIMAL(argv[0]);
+	param.subcmd = UAP_TX_BF_CFG;
+	param.bf_action = bf_action;
+	switch (bf_action) {
+	case BF_GLOBAL_CONFIGURATION:
+		if (argc != 1 && argc != 7) {
+			printf("Invalid argument for Global BF Configuration\n");
+			return UAP_FAILURE;
+		}
+		if (argc == 1) {
+			param.bf_cmd_action = BF_CFG_ACT_GET;
+			param.action = ACTION_GET;
+		} else {
+			param.bf_cmd_action = BF_CFG_ACT_SET;
+			param.action = ACTION_SET;
+			param.body.bf_global_cfg.bf_enbl =
+				atoi(argv[BF_ENABLE_PARAM]);
+			param.body.bf_global_cfg.sounding_enbl =
+				atoi(argv[SOUND_ENABLE_PARAM]);
+			param.body.bf_global_cfg.fb_type =
+				atoi(argv[FB_TYPE_PARAM]);
+			param.body.bf_global_cfg.snr_threshold =
+				atoi(argv[SNR_THRESHOLD_PARAM]);
+			param.body.bf_global_cfg.sounding_interval =
+				atoi(argv[SOUND_INTVL_PARAM]);
+			param.body.bf_global_cfg.bf_mode =
+				atoi(argv[BF_MODE_PARAM]);
+		}
+		break;
+	case TRIGGER_SOUNDING_FOR_PEER:
+		if (argc != 2) {
+			printf("ERR: wrong arguments.\n");
+			print_tx_bf_usage();
+			return UAP_FAILURE;
+		}
+		if ((ret =
+		     mac2raw(argv[1],
+			     param.body.bf_sound[0].peer_mac)) != UAP_SUCCESS) {
+			printf("ERR: %s Address\n",
+			       ret == UAP_FAILURE ? "Invalid MAC" : ret ==
+			       UAP_RET_MAC_BROADCAST ? "Broadcast" :
+			       "Multicast");
+			return UAP_FAILURE;
+		}
+		param.bf_cmd_action = BF_CFG_ACT_SET;
+		param.action = ACTION_SET;
+		break;
+	case SET_GET_BF_PERIODICITY:
+		if (argc != 2 && argc != 3) {
+			printf("ERR: wrong arguments.\n");
+			print_tx_bf_usage();
+			return UAP_FAILURE;
+		}
+		if ((ret =
+		     mac2raw(argv[1],
+			     param.body.bf_periodicity[0].peer_mac)) !=
+		    UAP_SUCCESS) {
+			printf("ERR: %s Address\n",
+			       ret == UAP_FAILURE ? "Invalid MAC" : ret ==
+			       UAP_RET_MAC_BROADCAST ? "Broadcast" :
+			       "Multicast");
+			return UAP_FAILURE;
+		}
+
+		if (argc == 3) {
+			if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE)
+				return UAP_FAILURE;
+			param.body.bf_periodicity[0].interval =
+				(t_u32)A2HEXDECIMAL(argv[2]);
+			param.bf_cmd_action = BF_CFG_ACT_SET;
+			param.action = ACTION_SET;
+		} else {
+			param.bf_cmd_action = BF_CFG_ACT_GET;
+			param.action = ACTION_GET;
+		}
+		break;
+	case TX_BF_FOR_PEER_ENBL:
+		if (argc != 1 && argc != 5) {
+			printf("ERR: wrong arguments.\n");
+			print_tx_bf_usage();
+			return UAP_FAILURE;
+		}
+		if (argc == 1) {
+			param.bf_cmd_action = BF_CFG_ACT_GET;
+			param.action = ACTION_GET;
+		} else {
+			if ((ret =
+			     mac2raw(argv[1],
+				     param.body.tx_bf_peer[0].peer_mac)) !=
+			    UAP_SUCCESS) {
+				printf("ERR: %s Address\n",
+				       ret ==
+				       UAP_FAILURE ? "Invalid MAC" : ret ==
+				       UAP_RET_MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				return UAP_FAILURE;
+			}
+			param.body.tx_bf_peer->bf_enbl = atoi(argv[2]);
+			param.body.tx_bf_peer->sounding_enbl = atoi(argv[3]);
+			param.body.tx_bf_peer->fb_type = atoi(argv[4]);
+			param.bf_cmd_action = BF_CFG_ACT_SET;
+			param.action = ACTION_SET;
+		}
+		break;
+	case SET_SNR_THR_PEER:
+		if (argc != 1 && argc != 3) {
+			printf("ERR: wrong arguments.\n");
+			print_tx_bf_usage();
+			return UAP_FAILURE;
+		}
+		if (argc == 1) {
+			param.bf_cmd_action = BF_CFG_ACT_GET;
+			param.action = ACTION_GET;
+		} else {
+			if ((ret =
+			     mac2raw(argv[1],
+				     param.body.bf_snr[0].peer_mac)) !=
+			    UAP_SUCCESS) {
+				printf("ERR: %s Address\n",
+				       ret ==
+				       UAP_FAILURE ? "Invalid MAC" : ret ==
+				       UAP_RET_MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				return UAP_FAILURE;
+			}
+			if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE)
+				return UAP_FAILURE;
+			param.body.bf_snr[0].snr = (t_u8)A2HEXDECIMAL(argv[2]);
+			param.bf_cmd_action = BF_CFG_ACT_SET;
+			param.action = ACTION_SET;
+		}
+		break;
+	default:
+		return UAP_FAILURE;
+	}
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: TX BF configuration failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+
+	printf("TX BF configuration successful\n");
+	/* Handle response */
+	if (param.action == ACTION_GET)
+		print_tx_bf_response(&param);
+
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for hscfg command
+ *
+ *  $return         N/A
+ */
+void
+print_hscfg_usage(void)
+{
+	printf("\nUsage : hscfg [condition [[GPIO# [gap]]]]");
+	printf("\nOptions: condition : bit 0 = 1   -- broadcast data");
+	printf("\n                     bit 1 = 1   -- unicast data");
+	printf("\n                     bit 2 = 1   -- mac event");
+	printf("\n                     bit 3 = 1   -- multicast packet");
+	printf("\n                     bit 6 = 1   -- mgmt frame received");
+	printf("\n         GPIO: the pin number (e.g. 0-7) of GPIO used to wakeup the host");
+	printf("\n               or 0xff interface (e.g. SDIO) used to wakeup the host");
+	printf("\n         gap: time between wakeup signal and wakeup event (in milliseconds)");
+	printf("\n              or 0xff for special setting when GPIO is used to wakeup host");
+	printf("\n         empty - get current host sleep parameters\n");
+	return;
+}
+
+/**
+ *  @brief Creates host sleep parameter request and send to driver
+ *
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_hscfg(int argc, char *argv[])
+{
+	int opt;
+	int i = 0;
+	ds_hs_cfg hscfg;
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	if ((argc == 2) && strstr(argv[1], "-1"))
+		strcpy(argv[1], "0xffff");
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_hscfg_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&hscfg, 0, sizeof(hscfg));
+	hscfg.subcmd = UAP_HS_CFG;
+	/* Check arguments */
+	if (argc > 3) {
+		printf("ERR:wrong arguments.\n");
+		print_hscfg_usage();
+		return UAP_FAILURE;
+	}
+	if (argc) {
+		for (i = 0; i < argc; i++) {
+			if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) {
+				printf("ERR: Invalid argument %s\n", argv[i]);
+				print_hscfg_usage();
+				return UAP_FAILURE;
+			}
+		}
+	}
+
+	if (argc) {
+		hscfg.flags |= HS_CFG_FLAG_SET | HS_CFG_FLAG_CONDITION;
+		hscfg.conditions = (t_u32)A2HEXDECIMAL(argv[0]);
+		if (hscfg.conditions >= 0xffff)
+			hscfg.conditions = HS_CFG_CANCEL;
+		if ((hscfg.conditions != HS_CFG_CANCEL) &&
+		    (hscfg.conditions & ~HS_CFG_CONDITION_MASK)) {
+			printf("ERR:Illegal conditions 0x%x\n",
+			       hscfg.conditions);
+			print_hscfg_usage();
+			return UAP_FAILURE;
+		}
+		if (argc > 1) {
+			hscfg.flags |= HS_CFG_FLAG_GPIO;
+			hscfg.gpio = (t_u32)A2HEXDECIMAL(argv[1]);
+			if (hscfg.gpio > 255) {
+				printf("ERR:Illegal gpio 0x%x\n", hscfg.gpio);
+				print_hscfg_usage();
+				return UAP_FAILURE;
+			}
+		}
+		if (argc > 2) {
+			hscfg.flags |= HS_CFG_FLAG_GAP;
+			hscfg.gap = (t_u32)A2HEXDECIMAL(argv[2]);
+		}
+	} else {
+		hscfg.flags = HS_CFG_FLAG_GET;
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&hscfg;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR:UAP_HS_CFG failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (!argc) {
+		printf("Host sleep parameters:\n");
+		printf("\tconditions=%d\n", (int)hscfg.conditions);
+		printf("\tGPIO=%d\n", (int)hscfg.gpio);
+		printf("\tgap=%d\n", (int)hscfg.gap);
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for hssetpara command
+ *
+ *  $return         N/A
+ */
+void
+print_hssetpara_usage(void)
+{
+	printf("\nUsage : hssetpara condition [[GPIO# [gap]]]");
+	printf("\nOptions: condition : bit 0 = 1   -- broadcast data");
+	printf("\n                     bit 1 = 1   -- unicast data");
+	printf("\n                     bit 2 = 1   -- mac event");
+	printf("\n                     bit 3 = 1   -- multicast packet");
+	printf("\n                     bit 6 = 1   -- mgmt frame received");
+	printf("\n         GPIO: the pin number (e.g. 0-7) of GPIO used to wakeup the host");
+	printf("\n               or 0xff interface (e.g. SDIO) used to wakeup the host");
+	printf("\n         gap: time between wakeup signal and wakeup event (in milliseconds)");
+	printf("\n              or 0xff for special setting when GPIO is used to wakeup host\n");
+	return;
+}
+
+/**
+ *  @brief Creates host sleep parameter request and send to driver
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_hssetpara(int argc, char *argv[])
+{
+	int opt;
+	int i = 0;
+	ds_hs_cfg hscfg;
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	if ((argc == 2) && strstr(argv[1], "-1"))
+		strcpy(argv[1], "0xffff");
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_hssetpara_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&hscfg, 0, sizeof(hscfg));
+	hscfg.subcmd = UAP_HS_SET_PARA;
+	/* Check arguments */
+	if ((argc < 1) || (argc > 3)) {
+		printf("ERR:wrong arguments.\n");
+		print_hssetpara_usage();
+		return UAP_FAILURE;
+	}
+	for (i = 0; i < argc; i++) {
+		if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) {
+			printf("ERR: Invalid argument %s\n", argv[i]);
+			print_hssetpara_usage();
+			return UAP_FAILURE;
+		}
+	}
+
+	hscfg.flags |= HS_CFG_FLAG_SET | HS_CFG_FLAG_CONDITION;
+	hscfg.conditions = (t_u32)A2HEXDECIMAL(argv[0]);
+	if (hscfg.conditions >= 0xffff)
+		hscfg.conditions = HS_CFG_CANCEL;
+	if ((hscfg.conditions != HS_CFG_CANCEL) &&
+	    (hscfg.conditions & ~HS_CFG_CONDITION_MASK)) {
+		printf("ERR:Illegal conditions 0x%x\n", hscfg.conditions);
+		print_hssetpara_usage();
+		return UAP_FAILURE;
+	}
+	if (argc > 1) {
+		hscfg.flags |= HS_CFG_FLAG_GPIO;
+		hscfg.gpio = (t_u32)A2HEXDECIMAL(argv[1]);
+		if (hscfg.gpio > 255) {
+			printf("ERR:Illegal gpio 0x%x\n", hscfg.gpio);
+			print_hssetpara_usage();
+			return UAP_FAILURE;
+		}
+	}
+	if (argc > 2) {
+		hscfg.flags |= HS_CFG_FLAG_GAP;
+		hscfg.gap = (t_u32)A2HEXDECIMAL(argv[2]);
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)&hscfg;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR:UAP_HS_SET_PARA failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	printf("Host sleep parameters setting successful!\n");
+	printf("\tconditions=%d\n", (int)hscfg.conditions);
+	printf("\tGPIO=%d\n", (int)hscfg.gpio);
+	printf("\tgap=%d\n", (int)hscfg.gap);
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief get dfs repeater mode
+ *
+ *  @param mode    status of DFS repeater mode is returned here
+ *  @return        UAP_SUCCESS/UAP_FAILURE
+ */
+int
+uap_ioctl_dfs_repeater_mode(int *mode)
+{
+	struct ifreq ifr;
+	dfs_repeater_mode param;
+	t_s32 sockfd;
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	param.action = ACTION_GET;
+	param.subcmd = UAP_DFS_REPEATER_MODE;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		printf("ERR:UAP_DFS_REPEATER_MODE is not"
+		       "supported by %s\n", dev_name);
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	*mode = (int)param.mode;
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Get CAC timer status
+ *
+ *  @param mode    status of CAC timer is returned here
+ *  @return        UAP_SUCCESS/UAP_FAILURE
+ */
+int
+uap_ioctl_cac_timer_status(unsigned int *mode)
+{
+	struct ifreq ifr;
+	cac_timer_status param;
+	t_s32 sockfd;
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	param.action = ACTION_GET;
+	param.subcmd = UAP_CAC_TIMER_STATUS;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		printf("ERR:UAP_CAC_TIMER_STATUS is not"
+		       "supported by %s\n", dev_name);
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	*mode = (int)param.mode;
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Set/get power mode
+ *
+ *  @param pm      A pointer to ps_mgmt structure
+ *  @param flag    flag for query
+ *  @return        UAP_SUCCESS/UAP_FAILURE
+ */
+int
+send_power_mode_ioctl(ps_mgmt * pm, int flag)
+{
+	struct ifreq ifr;
+	t_s32 sockfd;
+	t_u32 result = 0;
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)pm;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_POWER_MODE, &ifr)) {
+		memcpy((void *)&result, (void *)pm, sizeof(result));
+		if (result == 1) {
+			printf("ERR:Power mode needs to be disabled before modifying it\n");
+		} else {
+			perror("");
+			printf("ERR:UAP_POWER_MODE is not supported by %s\n",
+			       dev_name);
+		}
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (flag) {
+		/* Close socket */
+		close(sockfd);
+		return UAP_SUCCESS;
+	}
+	switch (pm->ps_mode) {
+	case 0:
+		printf("power mode = Disabled\n");
+		break;
+	case 1:
+		printf("power mode = Periodic DTIM PS\n");
+		break;
+	case 2:
+		printf("power mode = Inactivity based PS \n");
+		break;
+	}
+	if (pm->flags & PS_FLAG_SLEEP_PARAM) {
+		printf("Sleep param:\n");
+		printf("\tctrl_bitmap=%d\n", (int)pm->sleep_param.ctrl_bitmap);
+		printf("\tmin_sleep=%d us\n", (int)pm->sleep_param.min_sleep);
+		printf("\tmax_sleep=%d us\n", (int)pm->sleep_param.max_sleep);
+	}
+	if (pm->flags & PS_FLAG_INACT_SLEEP_PARAM) {
+		printf("Inactivity sleep param:\n");
+		printf("\tinactivity_to=%d us\n",
+		       (int)pm->inact_param.inactivity_to);
+		printf("\tmin_awake=%d us\n", (int)pm->inact_param.min_awake);
+		printf("\tmax_awake=%d us\n", (int)pm->inact_param.max_awake);
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the pscfg command
+ *
+ *  $return         N/A
+ */
+void
+print_pscfg_usage(void)
+{
+	printf("\nUsage : pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE]");
+	printf("\nOptions: MODE :     0 - disable power mode");
+	printf("\n                    1 - periodic DTIM power save mode");
+	printf("\n                    2 - inactivity based power save mode");
+	printf("\n   PS PARAMS:");
+	printf("\n        CTRL:  0 - disable protection frame Tx before PS");
+	printf("\n               1 - enable protection frame Tx before PS");
+	printf("\n        INACTTO: Inactivity timeout in miroseconds");
+	printf("\n        MIN_SLEEP: Minimum sleep duration in microseconds");
+	printf("\n        MAX_SLEEP: Maximum sleep duration in miroseconds");
+	printf("\n        MIN_AWAKE: Minimum awake duration in microseconds");
+	printf("\n        MAX_AWAKE: Maximum awake duration in microseconds");
+	printf("\n        MIN_AWAKE,MAX_AWAKE only valid for inactivity based power save mode");
+	printf("\n        empty - get current power mode\n");
+	return;
+}
+
+/**
+ *  @brief Creates power mode request and send to driver
+ *   and sends to the driver
+ *
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_pscfg(int argc, char *argv[])
+{
+	int opt;
+	ps_mgmt pm;
+	int ret = UAP_SUCCESS;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_pscfg_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&pm, 0, sizeof(ps_mgmt));
+	/* Check arguments */
+	if ((argc > 7) ||
+	    ((argc != 0) && (argc != 1) && (argc != 5) && (argc != 7))) {
+		printf("ERR:wrong arguments.\n");
+		print_pscfg_usage();
+		return UAP_FAILURE;
+	}
+
+	if (argc) {
+		if (send_power_mode_ioctl(&pm, 1) == UAP_FAILURE)
+			return UAP_FAILURE;
+		if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+		    (atoi(argv[0]) > 2)) {
+			printf("ERR:Illegal power mode %s. Must be either '0' '1' or '2'.\n", argv[0]);
+			print_pscfg_usage();
+			return UAP_FAILURE;
+		}
+		pm.flags = PS_FLAG_PS_MODE;
+		pm.ps_mode = atoi(argv[0]);
+		if ((pm.ps_mode == PS_MODE_DISABLE) && (argc > 1)) {
+			printf("ERR: Illegal parameter for disable power mode\n");
+			print_pscfg_usage();
+			return UAP_FAILURE;
+		}
+		if ((pm.ps_mode != PS_MODE_INACTIVITY) && (argc > 5)) {
+			printf("ERR:Min awake period and Max awake period are valid only for inactivity based power save mode\n");
+			print_pscfg_usage();
+			return UAP_FAILURE;
+		}
+		if (argc >= 5) {
+			if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 0) ||
+			    (atoi(argv[1]) > 1)) {
+				printf("ERR:Illegal ctrl bitmap = %s. Must be either '0' or '1'.\n", argv[1]);
+				print_pscfg_usage();
+				return UAP_FAILURE;
+			}
+			pm.flags |=
+				PS_FLAG_SLEEP_PARAM | PS_FLAG_INACT_SLEEP_PARAM;
+			pm.sleep_param.ctrl_bitmap = atoi(argv[1]);
+			if ((ISDIGIT(argv[2]) == 0) || (ISDIGIT(argv[3]) == 0)
+			    || (ISDIGIT(argv[4]) == 0)) {
+				printf("ERR:Illegal parameter\n");
+				print_pscfg_usage();
+				return UAP_FAILURE;
+			}
+			pm.inact_param.inactivity_to = atoi(argv[2]);
+			pm.sleep_param.min_sleep = atoi(argv[3]);
+			pm.sleep_param.max_sleep = atoi(argv[4]);
+			if (pm.sleep_param.min_sleep > pm.sleep_param.max_sleep) {
+				printf("ERR: MIN_SLEEP value should be less than or equal to MAX_SLEEP\n");
+				return UAP_FAILURE;
+			}
+			if (pm.sleep_param.min_sleep < PS_SLEEP_PARAM_MIN ||
+			    ((pm.sleep_param.max_sleep > PS_SLEEP_PARAM_MAX) &&
+			     pm.sleep_param.ctrl_bitmap)) {
+				printf("ERR: Incorrect value of sleep period. Please check README\n");
+				return UAP_FAILURE;
+			}
+			if (argc == 7) {
+				if ((ISDIGIT(argv[5]) == 0) ||
+				    (ISDIGIT(argv[6]) == 0)) {
+					printf("ERR:Illegal parameter\n");
+					print_pscfg_usage();
+					return UAP_FAILURE;
+				}
+				pm.inact_param.min_awake = atoi(argv[5]);
+				pm.inact_param.max_awake = atoi(argv[6]);
+				if (pm.inact_param.min_awake >
+				    pm.inact_param.max_awake) {
+					printf("ERR: MIN_AWAKE value should be less than or equal to MAX_AWAKE\n");
+					return UAP_FAILURE;
+				}
+				if (pm.inact_param.min_awake <
+				    PS_AWAKE_PERIOD_MIN) {
+					printf("ERR: Incorrect value of MIN_AWAKE period.\n");
+					return UAP_FAILURE;
+				}
+			}
+		}
+	}
+	ret = send_power_mode_ioctl(&pm, 0);
+	return ret;
+}
+
+/**
+ *  @brief Get bss status started/stopped
+ *
+ *  @param          current bss status
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+static int
+get_bss_status(int *status)
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_bss_status *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_FAILURE;
+
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_bss_status);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_bss_status *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_BSS_STATUS_TLV_ID;
+	tlv->length = 2;
+	cmd_buf->action = ACTION_GET;
+
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	tlv->bss_status = uap_le16_to_cpu(tlv->bss_status);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_BSS_STATUS_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (tlv->bss_status == 0)
+				*status = UAP_BSS_STOP;
+			else
+				*status = UAP_BSS_START;
+		} else {
+			printf("ERR:Could not get BSS status!\n");
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief start/stop/reset bss
+ *
+ *  @param mode     bss control mode
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+send_bss_ctl_ioctl(int mode)
+{
+	struct ifreq ifr;
+	t_s32 sockfd;
+	t_u32 data = (t_u32)mode;
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&data;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_BSS_CTRL, &ifr)) {
+		printf("ERR:UAP_BSS_CTRL fail, result=%d\n", (int)data);
+		switch (mode) {
+		case UAP_BSS_START:
+			if (data == BSS_FAILURE_START_INVAL)
+				printf("ERR:Could not start BSS! Invalid BSS parameters.\n");
+			else
+				printf("ERR:Could not start BSS!\n");
+			break;
+		case UAP_BSS_STOP:
+			printf("ERR:Could not stop BSS!\n");
+			break;
+		case UAP_BSS_RESET:
+			printf("ERR:Could not reset system!\n");
+			break;
+		}
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+
+	switch (mode) {
+	case UAP_BSS_START:
+		printf("BSS start successful!\n");
+		break;
+	case UAP_BSS_STOP:
+		printf("BSS stop successful!\n");
+		break;
+	case UAP_BSS_RESET:
+		printf("System reset successful!\n");
+		break;
+	}
+
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the sys_reset command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_reset_usage(void)
+{
+	printf("\nUsage : sys_reset\n");
+	return;
+}
+
+/**
+ *  @brief Creates a sys_reset request and sends to the driver
+ *
+ *  Usage: "sys_reset"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_reset(int argc, char *argv[])
+{
+	int opt;
+	int ret = UAP_SUCCESS;
+	ps_mgmt pm;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_reset_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 0) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_reset_usage();
+		return UAP_FAILURE;
+	}
+	memset(&pm, 0, sizeof(ps_mgmt));
+	pm.flags = PS_FLAG_PS_MODE;
+	pm.ps_mode = PS_MODE_DISABLE;
+	if (send_power_mode_ioctl(&pm, 0) == UAP_FAILURE)
+		return UAP_FAILURE;
+	ret = send_bss_ctl_ioctl(UAP_BSS_RESET);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the bss_start command
+ *
+ *  $return         N/A
+ */
+void
+print_bss_start_usage(void)
+{
+	printf("\nUsage : bss_start\n");
+	return;
+}
+
+/**
+ *  @brief Creates a BSS start request and sends to the driver
+ *
+ *   Usage: "bss_start"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_bss_start(int argc, char *argv[])
+{
+	int opt;
+	t_u8 *buf = NULL;
+	t_u16 buf_len = 0;
+	int status = 0;
+	int ret = UAP_SUCCESS;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_bss_start_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 0) {
+		printf("ERR:Too many arguments.\n");
+		print_bss_start_usage();
+		return UAP_FAILURE;
+	}
+
+	if (get_bss_status(&status) != UAP_SUCCESS) {
+		printf("ERR:Cannot get current bss status!\n");
+		return UAP_FAILURE;
+	}
+
+	if (status == UAP_BSS_START) {
+		printf("ERR: Could not start BSS! BSS already started!\n");
+		return UAP_FAILURE;
+	}
+
+	/* Query BSS settings */
+
+	/* Alloc buf for command */
+	buf_len = sizeof(apcmdbuf_bss_configure) + sizeof(bss_config_t);
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset((char *)buf, 0, buf_len);
+
+	/* Get all parametes first */
+	if (get_bss_config(buf) == UAP_FAILURE) {
+		printf("ERR:Reading current bss configuration\n");
+		free(buf);
+		return UAP_FAILURE;
+	}
+
+	ret = check_bss_config(buf + sizeof(apcmdbuf_bss_configure));
+
+	if (ret == UAP_FAILURE) {
+		printf("ERR: Wrong bss configuration!\n");
+		goto done;
+	}
+
+	ret = send_bss_ctl_ioctl(UAP_BSS_START);
+
+done:
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the bss_stop command
+ *
+ *  $return         N/A
+ */
+void
+print_bss_stop_usage(void)
+{
+	printf("\nUsage : bss_stop\n");
+	return;
+}
+
+/**
+ *  @brief Creates a BSS stop request and sends to the driver
+ *
+ *   Usage: "bss_stop"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_bss_stop(int argc, char *argv[])
+{
+	int opt;
+	int status = 0;
+	int ret = UAP_SUCCESS;
+	unsigned int cac_timer = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_bss_stop_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;		/* Check arguments */
+
+	if (argc != 0) {
+		printf("ERR:Too many arguments.\n");
+		print_bss_stop_usage();
+		return UAP_FAILURE;
+	}
+	if (get_bss_status(&status) != UAP_SUCCESS) {
+		printf("ERR:Cannot get current bss status!\n");
+		return UAP_FAILURE;
+	}
+
+	if ((status != UAP_BSS_STOP)
+	    || ((uap_ioctl_cac_timer_status(&cac_timer) == UAP_SUCCESS)
+		&& (cac_timer))
+		)
+		ret = send_bss_ctl_ioctl(UAP_BSS_STOP);
+	else {
+		printf("ERR: Could not stop BSS! BSS already stopped!\n");
+		ret = UAP_FAILURE;
+	}
+	return ret;
+}
+
+void
+print_skip_cac_usage(void)
+{
+	printf("\nUsage : skip_cac [MODE]");
+	printf("\nOptions: MODE : 0 - Disable skip CAC mode");
+	printf("\n                1 - Enable skip CAC mode");
+	printf("\n         empty - get skip CAC mode\n");
+	return;
+}
+
+/**
+ *  @brief Skip CAC for next immediate BSS_START
+ *
+ *   Usage: "skip_cac [1/0]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_skip_cac(int argc, char *argv[])
+{
+	int opt;
+	skip_cac_para param;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_skip_cac_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&param, 0, sizeof(param));
+	/* Check arguments */
+	if (argc > 1) {
+		printf("ERR:wrong arguments. Only support 1 argument\n");
+		print_skip_cac_usage();
+		return UAP_FAILURE;
+	}
+	param.subcmd = UAP_SKIP_CAC;
+	if (argc) {
+		if (argc == 1) {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
+			    ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 1))) {
+				printf("ERR: Only Number values are allowed\n");
+				print_skip_cac_usage();
+				return UAP_FAILURE;
+			}
+		}
+		param.action = 1;
+		param.skip_cac = (t_u16)A2HEXDECIMAL(argv[0]);
+	} else {
+		param.action = 0;
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		if (argc)
+			printf("ERR:skip_cac set failed\n");
+		else {
+			perror("");
+			printf("ERR:skip_cac get failed\n");
+		}
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (!argc) {
+		if (param.skip_cac == 1) {
+			printf("skip CAC mode: enabled\n");
+		} else {
+			printf("skip CAC mode: disabled\n");
+		}
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the sta_list command
+ *
+ *  $return         N/A
+ */
+void
+print_sta_list_usage(void)
+{
+	printf("\nUsage : sta_list\n");
+	return;
+}
+
+/**
+ *  @brief Creates a STA list request and sends to the driver
+ *
+ *   Usage: "sta_list"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sta_list(int argc, char *argv[])
+{
+	struct ifreq ifr;
+	t_s32 sockfd;
+	sta_list list;
+	int i = 0;
+	int opt;
+	int rssi = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sta_list_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 0) {
+		printf("ERR:Too many arguments.\n");
+		print_sta_list_usage();
+		return UAP_FAILURE;
+	}
+	memset(&list, 0, sizeof(sta_list));
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&list;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_GET_STA_LIST, &ifr)) {
+		perror("");
+		printf("ERR:UAP_GET_STA_LIST is not supported by %s\n",
+		       dev_name);
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	printf("Number of STA = %d\n\n", list.sta_count);
+
+	for (i = 0; i < list.sta_count; i++) {
+		printf("STA %d information:\n", i + 1);
+		printf("=====================\n");
+		printf("MAC Address: ");
+		print_mac(list.info[i].mac_address);
+		printf("\nPower mfg status: %s\n",
+		       (list.info[i].power_mfg_status ==
+			0) ? "active" : "power save");
+		printf("Mode: %s\n",
+		       (list.info[i].bandmode ==
+			BAND_B) ? "11b," : (list.info[i].bandmode ==
+					    BAND_G) ? "11g," : (list.info[i].
+								bandmode ==
+								BAND_A) ? "11a,"
+		       : (list.info[i].bandmode ==
+			  BAND_GN) ? "2.4G_11n," : (list.info[i].bandmode ==
+						    BAND_AN) ? "5G_11n,"
+		       : (list.info[i].bandmode ==
+			  BAND_GAC) ? "2.4G_11ac," : (list.info[i].bandmode ==
+						      BAND_AAC) ? "5G_11ac," :
+		       "unkown");
+	/** On some platform, s8 is same as unsigned char*/
+		rssi = (int)list.info[i].rssi;
+		if (rssi > 0x7f)
+			rssi = -(256 - rssi);
+		printf("Rssi : %d dBm\n\n", rssi);
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the sta_deauth command
+ *
+ *  $return         N/A
+ */
+void
+print_sta_deauth_usage(void)
+{
+	printf("\nUsage : sta_deauth <STA_MAC_ADDRESS>\n");
+	return;
+}
+
+/**
+ *  @brief Creates a STA deauth request and sends to the driver
+ *
+ *   Usage: "sta_deauth <STA_MAC_ADDRESS>"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sta_deauth(int argc, char *argv[])
+{
+	APCMDBUF_STA_DEAUTH *cmd_buf = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_FAILURE;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sta_deauth_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 1) {
+		printf("ERR:wrong arguments! Must provide STA_MAC_ADDRESS.\n");
+		print_sta_deauth_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command length */
+	cmd_len = sizeof(APCMDBUF_STA_DEAUTH);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (APCMDBUF_STA_DEAUTH *)buffer;
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_STA_DEAUTH;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	if ((ret = mac2raw(argv[0], cmd_buf->sta_mac_address)) != UAP_SUCCESS) {
+		printf("ERR: %s Address\n", ret == UAP_FAILURE ? "Invalid MAC" :
+		       ret ==
+		       UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast");
+		free(buffer);
+		return UAP_FAILURE;
+	}
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code != (APCMD_STA_DEAUTH | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			free(buffer);
+			return UAP_FAILURE;
+		}
+
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("Deauthentication successful!\n");
+		} else {
+			printf("ERR:Deauthentication unsuccessful!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the sta_deauth_ext command
+ *
+ *  $return         N/A
+ */
+void
+print_sta_deauth_ext_usage(void)
+{
+	printf("\nUsage : sta_deauth <STA_MAC_ADDRESS> <REASCON_CODE>\n");
+	return;
+}
+
+/**
+ *  @brief Creates a STA deauth request and sends to the driver
+ *
+ *   Usage: "sta_deauth <STA_MAC_ADDRESS><REASON_CODE>"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sta_deauth_ext(int argc, char *argv[])
+{
+	int ret = UAP_SUCCESS;
+	int opt;
+	deauth_param param;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	t_u32 result = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sta_deauth_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 2) {
+		printf("ERR:wrong arguments! Must provide STA_MAC_ADDRESS, REASON_CODE.\n");
+		print_sta_deauth_ext_usage();
+		return UAP_FAILURE;
+	}
+	memset(&param, 0, sizeof(deauth_param));
+
+	if ((ret = mac2raw(argv[0], param.mac_addr)) != UAP_SUCCESS) {
+		printf("ERR: %s Address\n", ret == UAP_FAILURE ? "Invalid MAC" :
+		       ret ==
+		       UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast");
+		return UAP_FAILURE;
+	}
+
+	if ((IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) ||
+	    (atoi(argv[1]) > MAX_DEAUTH_REASON_CODE)) {
+		printf("ERR: Invalid input for reason code\n");
+		return UAP_FAILURE;
+	}
+	param.reason_code = (t_u16)A2HEXDECIMAL(argv[1]);
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_STA_DEAUTH, &ifr)) {
+		memcpy((void *)&result, (void *)&param, sizeof(result));
+		if (result == 1)
+			printf("ERR:UAP_STA_DEAUTH fail\n");
+		else
+			perror("");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	printf("Station deauth successful\n");
+	/* Close socket */
+	close(sockfd);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the radioctrl command
+ *
+ *  $return         N/A
+ */
+void
+print_radio_ctl_usage(void)
+{
+	printf("\nUsage : radioctrl [ 0 | 1 ]\n");
+	return;
+}
+
+/**
+ *  @brief Creates a Radio control request and sends to the driver
+ *
+ *   Usage: "radioctrl [0 | 1]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_radio_ctl(int argc, char *argv[])
+{
+	int opt;
+	int param[2] = { 0, 0 };	/* action (Set/Get), Control (ON/OFF) */
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_radio_ctl_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc > 1) {
+		printf("ERR:wrong arguments! Only 1 or 0 arguments are supported.\n");
+		print_radio_ctl_usage();
+		return UAP_FAILURE;
+	}
+	if (argc && (is_input_valid(RADIOCONTROL, argc, argv) != UAP_SUCCESS)) {
+		print_radio_ctl_usage();
+		return UAP_FAILURE;
+	}
+	if (argc) {
+		param[0] = ACTION_SET;
+		param[1] = atoi(argv[0]);
+	}
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_RADIO_CTL, &ifr)) {
+		printf("ERR:UAP_RADIO_CTL fail\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (argc)
+		printf("Radio setting successful\n");
+	else
+		printf("Radio is %s.\n", (param[1]) ? "on" : "off");
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the txratecfg command
+ *
+ *  $return         N/A
+ */
+void
+print_txratecfg_usage(void)
+{
+	printf("\nUsage : txratecfg <datarate index> Index should be one of the following.\n");
+	printf("\n  [l] is <format>");
+	printf("\n  <format> - This parameter specifies the data rate format used in this command");
+	printf("\n  0:    LG");
+	printf("\n  1:    HT");
+	printf("\n  2:    VHT");
+	printf("\n  0xff: Auto");
+	printf("\n");
+	printf("\n  [m] is <index>");
+	printf("\n  <index> - This parameter specifies the rate or MCS index");
+	printf("\n  If <format> is 0 (LG),");
+	printf("\n  0   1 Mbps");
+	printf("\n  1   2 Mbps");
+	printf("\n  2   5.5 Mbps");
+	printf("\n  3   11 Mbps");
+	printf("\n  4   6 Mbps");
+	printf("\n  5   9 Mbps");
+	printf("\n  6   12 Mbps");
+	printf("\n  7   18 Mbps");
+	printf("\n  8   24 Mbps");
+	printf("\n  9   36 Mbps");
+	printf("\n  10  48 Mbps");
+	printf("\n  11  54 Mbps");
+	printf("\n  If <format> is 1 (HT), ");
+	printf("\n  0   MCS0");
+	printf("\n  1   MCS1");
+	printf("\n  2   MCS2");
+	printf("\n  3   MCS3");
+	printf("\n  4   MCS4");
+	printf("\n  5   MCS5");
+	printf("\n  6   MCS6");
+	printf("\n  7   MCS7");
+	printf("\n  8   MCS8");
+	printf("\n  9   MCS9");
+	printf("\n  10  MCS10");
+	printf("\n  11  MCS11");
+	printf("\n  12  MCS12");
+	printf("\n  13  MCS13");
+	printf("\n  14  MCS14");
+	printf("\n  15  MCS15");
+	printf("\n  32  MCS32");
+	printf("\n  If <format> is 2 (VHT), ");
+	printf("\n  0   MCS0");
+	printf("\n  1   MCS1");
+	printf("\n  2   MCS2");
+	printf("\n  3   MCS3");
+	printf("\n  4   MCS4");
+	printf("\n  5   MCS5");
+	printf("\n  6   MCS6");
+	printf("\n  7   MCS7");
+	printf("\n  8   MCS8");
+	printf("\n  9   MCS9");
+	printf("\n  [n] is <nss>");
+	printf("\n  <nss> - This parameter specifies the NSS. It is valid only for VHT");
+	printf("\n  If <format> is 2 (VHT), ");
+	printf("\n  1   NSS1");
+	printf("\n  2   NSS2");
+	printf("\n");
+	return;
+}
+
+/**
+ *  @brief Creates a Tx Rate Config get request and sends to the driver
+ *  @param rate_config Tx rate config struct
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+static int
+get_tx_rate_cfg(tx_rate_cfg_t *rate_config)
+{
+	struct ifreq ifr;
+	t_s32 sockfd;
+	int ret = UAP_SUCCESS;
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(rate_config, 0, sizeof(tx_rate_cfg_t));
+	rate_config->subcmd = UAP_TX_RATE_CFG;
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)rate_config;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		printf("ERR:UAP_IOCTL_CMD fail\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	/* Close socket */
+	close(sockfd);
+	return ret;
+}
+
+static char *rate_format[3] = { "LG", "HT", "VHT" };
+
+static char *lg_rate[] = { "1 Mbps", "2 Mbps", "5.5 Mbps", "11 Mbps",
+	"6 Mbps", "9 Mbps", "12 Mbps", "18 Mbps",
+	"24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps"
+};
+
+/**
+ *  @brief Creates a Tx Rate Config request and sends to the driver
+ *
+ *   Usage: "txratecfg <datarate>"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_tx_rate_cfg(int argc, char *argv[])
+{
+	int opt;
+	int status = 0;
+	tx_rate_cfg_t tx_rate_config;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	HTCap_t htcap;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_txratecfg_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc > 3) {
+		printf("ERR:wrong arguments! Only 0~3 arguments are supported.\n");
+		print_txratecfg_usage();
+		return UAP_FAILURE;
+	}
+	if (argc && (is_input_valid(TXRATECFG, argc, argv) != UAP_SUCCESS)) {
+		print_txratecfg_usage();
+		return UAP_FAILURE;
+	}
+	memset(&tx_rate_config, 0, sizeof(tx_rate_cfg_t));
+	tx_rate_config.subcmd = UAP_TX_RATE_CFG;
+	if (argc) {
+		tx_rate_config.action = ACTION_SET;
+		tx_rate_config.rate_format = A2HEXDECIMAL(argv[0]);
+		if (argc >= 2)
+			tx_rate_config.rate = A2HEXDECIMAL(argv[1]);
+		if (argc == 3)
+			tx_rate_config.nss = A2HEXDECIMAL(argv[2]);
+		tx_rate_config.user_data_cnt = argc;
+		/* If bss is already started and uAP is in (short GI in 20 MHz + GF) mode, block MCS0-MCS7 rates */
+		if (get_bss_status(&status) != UAP_SUCCESS) {
+			printf("ERR:Cannot get current bss status!\n");
+			return UAP_FAILURE;
+		}
+		if (UAP_SUCCESS == get_sys_cfg_11n(&htcap)) {
+			if (htcap.supported_mcs_set[0] &&
+			    (status == UAP_BSS_START)) {
+				if (((tx_rate_config.rate >= 0) &&
+				     (tx_rate_config.rate <= 7))
+				    &&
+				    (IS_11N_20MHZ_SHORTGI_ENABLED
+				     (htcap.ht_cap_info) &&
+				     IS_11N_GF_ENABLED(htcap.ht_cap_info))) {
+					printf("ERR: Invalid rate for bss in (20MHz Short GI + Green Field) mode\n");
+					return UAP_FAILURE;
+				}
+				if ((tx_rate_config.rate == 32) &&
+				    (!(IS_11N_40MHZ_ENABLED
+				       (htcap.ht_cap_info)))) {
+					printf("ERR:uAP must be configured to operate in 40MHz if tx_rate is MCS32\n");
+					return UAP_FAILURE;
+				}
+			}
+		}
+	}
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)&tx_rate_config;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		printf("ERR:UAP_IOCTL_CMD fail\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (argc) {
+		printf("Transmit Rate setting successful\n");
+	} else {
+		/* GET operation */
+		printf("Tx Rate Configuration: \n");
+		/* format */
+		if (tx_rate_config.rate_format == 0xFF) {
+			printf("    Type:       0xFF (Auto)\n");
+		} else if (tx_rate_config.rate_format <= 2) {
+			printf("    Type:       %d (%s)\n",
+			       tx_rate_config.rate_format,
+			       rate_format[tx_rate_config.rate_format]);
+			if (tx_rate_config.rate_format == 0)
+				printf("    Rate Index: %d (%s)\n",
+				       tx_rate_config.rate,
+				       lg_rate[tx_rate_config.rate]);
+			else if (tx_rate_config.rate_format >= 1)
+				printf("    MCS Index:  %d\n",
+				       (int)tx_rate_config.rate);
+			if (tx_rate_config.rate_format == 2)
+				printf("    NSS:        %d\n",
+				       (int)tx_rate_config.nss);
+		} else {
+			printf("    Unknown rate format.\n");
+		}
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the antcfg
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_antcfg_usage(void)
+{
+	printf("\nUsage : antcfg [<TX_MODE> <RX_MODE>]\n");
+	printf("\n         MODE    : 1       - Antenna A");
+	printf("\n                   2       - Antenna B");
+	printf("\n                   3       - Antenna A+B");
+	printf("\n                   empty   - Get current antenna settings\n");
+	return;
+}
+
+/**
+ *  @brief Creates a RF Antenna Mode Config request and sends to the driver
+ *
+ *   Usage: "antcfg [MODE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_antcfg(int argc, char *argv[])
+{
+	int opt;
+	ant_cfg_t antenna_config;
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_antcfg_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc > 2) {
+		printf("ERR:wrong arguments!\n");
+		print_antcfg_usage();
+		return UAP_FAILURE;
+	}
+	if (argc) {
+		if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 1) ||
+		    (atoi(argv[0]) > 3)) {
+			printf("ERR:Illegal ANTENNA parameter %s. Must be either '1', '2' or '3'.\n", argv[0]);
+			print_antcfg_usage();
+			return UAP_FAILURE;
+		}
+		if (argc == 2) {
+			if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 1) ||
+			    (atoi(argv[1]) > 3)) {
+				printf("ERR:Illegal RX ANTENNA parameter %s. Must be either '1', '2' or '3'.\n", argv[1]);
+				print_antcfg_usage();
+				return UAP_FAILURE;
+			}
+		}
+	}
+	memset(&antenna_config, 0, sizeof(ant_cfg_t));
+	antenna_config.subcmd = UAP_ANTENNA_CFG;
+	if (argc) {
+		antenna_config.action = ACTION_SET;
+		if (argc == 1) {
+			antenna_config.tx_mode = atoi(argv[0]);
+			antenna_config.rx_mode = atoi(argv[0]);
+		} else {
+			antenna_config.tx_mode = atoi(argv[0]);
+			antenna_config.rx_mode = atoi(argv[1]);
+		}
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)&antenna_config;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		printf("ERR:UAP_IOCTL_CMD fail\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (argc) {
+		printf("Antenna mode setting successful\n");
+	} else {
+		printf("TX Antenna mode is %d.\n", antenna_config.tx_mode);
+		printf("RX Antenna mode is %d.\n", antenna_config.rx_mode);
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the htstreamcfg
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_htstreamcfg_usage(void)
+{
+	printf("\nUsage : htstreamcfg [<n>]\n");
+	printf("\n        Where  <n>  ");
+	printf("\n                 0x11: HT stream 1x1 mode");
+	printf("\n                 0x22: HT stream 2x2 mode\n");
+	return;
+}
+
+/**
+ *  @brief Set/get HT stream configurations
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_htstreamcfg(int argc, char *argv[])
+{
+	int opt;
+	htstream_cfg_t htstream_cfg;
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_htstreamcfg_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+
+	memset(&htstream_cfg, 0, sizeof(htstream_cfg));
+	if (argc == 0) {
+		htstream_cfg.action = ACTION_GET;
+	} else if (argc == 1) {
+		if ((t_u32)A2HEXDECIMAL(argv[0]) != HT_STREAM_MODE_1X1
+		    && (t_u32)A2HEXDECIMAL(argv[0]) != HT_STREAM_MODE_2X2) {
+			printf("ERR:Invalid argument\n");
+			return UAP_FAILURE;
+		}
+		htstream_cfg.action = ACTION_SET;
+		htstream_cfg.stream_cfg = (t_u32)A2HEXDECIMAL(argv[0]);
+	} else {
+		print_htstreamcfg_usage();
+		return UAP_FAILURE;
+	}
+	htstream_cfg.subcmd = UAP_HT_STREAM_CFG;
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&htstream_cfg;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: HT STREAM configuration failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+
+	/* Handle response */
+	if (htstream_cfg.action == ACTION_GET) {
+		if (htstream_cfg.stream_cfg == HT_STREAM_MODE_1X1)
+			printf("HT stream is in 1x1 mode\n");
+		else if (htstream_cfg.stream_cfg == HT_STREAM_MODE_2X2)
+			printf("HT stream is in 2x2 mode\n");
+		else
+			printf("HT stream is unknown mode\n");
+	}
+
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+static int
+get_802_11ac_cfg(struct eth_priv_vhtcfg *vhtcfg)
+{
+	t_u8 *buf = NULL;
+	t_u8 *pos = NULL;
+	mrvl_priv_cmd *cmd = NULL;
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buf) {
+		printf("ERR: cannot allocate buffer for command payload \n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd = (mrvl_priv_cmd *)malloc(sizeof(mrvl_priv_cmd));
+	if (!cmd) {
+		printf("ERR: cannot allocate buffer for cmd \n");
+		free(buf);
+		return UAP_FAILURE;
+	}
+
+	/*prepare command: mlanutl uap0 vhtcfg 2 3 , GET operation */
+	pos = buf;
+	strncpy((char *)pos, CMD_MARVELL, strlen(CMD_MARVELL));
+	pos += strlen(CMD_MARVELL);
+	strncpy((char *)pos, "vhtcfg2 3", strlen("vhtcfg2 3"));
+
+	/* fill up buffer */
+	cmd->buf = buf;
+	cmd->used_len = 0;
+	cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	/* Perform IOCTL */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)cmd;
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		if (cmd)
+			free(cmd);
+		if (buf)
+			free(buf);
+		return UAP_FAILURE;
+	}
+
+	if (ioctl(sockfd, MRVLPRIVCMD, &ifr)) {
+		if (cmd)
+			free(cmd);
+		if (buf)
+			free(buf);
+		return UAP_FAILURE;
+	}
+
+	/* Process result */
+	memcpy(vhtcfg, buf + 1, sizeof(struct eth_priv_vhtcfg));
+
+	close(sockfd);
+	free(cmd);
+	free(buf);
+
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the sys_config command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_config_usage(void)
+{
+	printf("\nUsage : sys_config [CONFIG_FILE]\n");
+	printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n");
+	printf("CONFIG_FILE is file contain all the Micro AP settings.\n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the rdeeprom command
+ *
+ *  $return         N/A
+ */
+void
+print_apcmd_read_eeprom_usage(void)
+{
+	printf("\nUsage: rdeeprom <offset> <bytecount>\n");
+	printf("    offset    : 0,4,8,..., multiple of 4\n");
+	printf("    bytecount : 4-20, multiple of 4\n");
+	return;
+}
+
+/**
+ *  @brief Show protocol tlv
+ *
+ *  @param protocol Protocol number
+ *
+ *  $return         N/A
+ */
+void
+print_protocol(t_u16 protocol)
+{
+	switch (protocol) {
+	case 0:
+	case PROTOCOL_NO_SECURITY:
+		printf("PROTOCOL = No security\n");
+		break;
+	case PROTOCOL_STATIC_WEP:
+		printf("PROTOCOL = Static WEP\n");
+		break;
+	case PROTOCOL_WPA:
+		printf("PROTOCOL = WPA \n");
+		break;
+	case PROTOCOL_WPA2:
+		printf("PROTOCOL = WPA2 \n");
+		break;
+	case PROTOCOL_WPA | PROTOCOL_WPA2:
+		printf("PROTOCOL = WPA/WPA2 \n");
+		break;
+	default:
+		printf("Unknown PROTOCOL: 0x%x \n", protocol);
+		break;
+	}
+}
+
+/**
+ *  @brief Show wep tlv
+ *
+ *  @param tlv     Pointer to wep tlv
+ *
+ *  $return         N/A
+ */
+void
+print_wep_key(tlvbuf_wep_key *tlv)
+{
+	int i;
+	t_u16 tlv_len;
+
+	tlv_len = *(t_u8 *)&tlv->length;
+	tlv_len |= (*((t_u8 *)&tlv->length + 1) << 8);
+
+	if (tlv_len <= 2) {
+		printf("wrong wep_key tlv: length=%d\n", tlv_len);
+		return;
+	}
+	printf("WEP KEY_%d = ", tlv->key_index);
+	for (i = 0; i < tlv_len - 2; i++)
+		printf("%02x ", tlv->key[i]);
+	if (tlv->is_default)
+		printf("\nDefault WEP Key = %d\n", tlv->key_index);
+	else
+		printf("\n");
+}
+
+/**
+ *  @brief Parses a command line
+ *
+ *  @param line     The line to parse
+ *  @param args     Pointer to the argument buffer to be filled in
+ *  @return         Number of arguments in the line or EOF
+ */
+static int
+parse_line(char *line, char *args[])
+{
+	int arg_num = 0;
+	int is_start = 0;
+	int is_quote = 0;
+	int is_escape = 0;
+	int length = 0;
+	int i = 0;
+	int j = 0;
+
+	arg_num = 0;
+	length = strlen(line);
+	/* Process line */
+
+	/* Find number of arguments */
+	is_start = 0;
+	is_quote = 0;
+	for (i = 0; i < length; i++) {
+		/* Ignore leading spaces */
+		if (is_start == 0) {
+			if (line[i] == ' ') {
+				continue;
+			} else if (line[i] == '\t') {
+				continue;
+			} else if (line[i] == '\n') {
+				break;
+			} else {
+				is_start = 1;
+				args[arg_num] = &line[i];
+				arg_num++;
+			}
+		}
+		if (is_start == 1) {
+			if ((line[i] == '\\') && (i < (length - 1))) {
+				if (line[i + 1] == '"') {
+					is_escape = 1;
+					for (j = i; j < length - 1; j++) {
+						line[j] = line[j + 1];
+					}
+					line[length - 1] = '\0';
+					continue;
+				}
+			}
+			/* Ignore comments */
+			if (line[i] == '#') {
+				if (is_quote == 0) {
+					line[i] = '\0';
+					arg_num--;
+				}
+				break;
+			}
+			/* Separate by '=' */
+			if (line[i] == '=') {
+				if (is_quote == 0) {
+					line[i] = '\0';
+					is_start = 0;
+					continue;
+				}
+			}
+			/* Separate by ',' */
+			if (line[i] == ',') {
+				if (is_quote == 0) {
+					line[i] = '\0';
+					is_start = 0;
+					continue;
+				}
+			}
+			/* Change ',' to ' ', but not inside quotes */
+			if ((line[i] == ',') && (is_quote == 0)) {
+				line[i] = ' ';
+				continue;
+			}
+		}
+		/* Remove newlines */
+		if (line[i] == '\n') {
+			line[i] = '\0';
+		}
+		/* Check for quotes */
+		if (line[i] == '"') {
+			if (is_escape) {
+				is_escape = 0;
+				/* no change in is_quote */
+			} else {
+				is_quote = (is_quote == 1) ? 0 : 1;
+			}
+			continue;
+		}
+		if (((line[i] == ' ') || (line[i] == '\t')) && (is_quote == 0)) {
+			line[i] = '\0';
+			is_start = 0;
+			continue;
+		}
+	}
+	return arg_num;
+}
+
+/**
+ *  @brief      Parse function for a configuration line
+ *
+ *  @param s        Storage buffer for data
+ *  @param size     Maximum size of data
+ *  @param stream   File stream pointer
+ *  @param line     Pointer to current line within the file
+ *  @param _pos     Output string or NULL
+ *  @return     String or NULL
+ */
+static char *
+config_get_line(char *s, int size, FILE * stream, int *line, char **_pos)
+{
+	*_pos = mlan_config_get_line(stream, s, size, line);
+	return *_pos;
+}
+
+/**
+ *  @brief Read the profile and sends to the driver
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+apcmd_sys_config_profile(int argc, char *argv[])
+{
+	FILE *config_file = NULL;
+	char *line = NULL;
+	int li = 0;
+	char *pos = NULL;
+	int arg_num = 0;
+	char *args[30];
+	int i;
+	int is_ap_config = 0;
+	int is_ap_mac_filter = 0;
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	HTCap_t htcap;
+	int enable_11n = -1;
+	t_u16 tlv_offset_11n = 0;
+	t_u32 supported_mcs_set = 0;
+	t_u8 *buffer = NULL;
+	t_u8 *tmp_buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 tlv_len = 0;
+	int keyindex = -1;
+	int protocol = -1;
+	int pwkcipher_wpa = -1;
+	int pwkcipher_wpa2 = -1;
+	int gwkcipher = -1;
+	tlvbuf_sta_mac_addr_filter *filter_tlv = NULL;
+	tlvbuf_channel_config *channel_band_tlv = NULL;
+	int filter_mac_count = -1;
+	int tx_data_rate = -1;
+	int tx_beacon_rate = -1;
+	int mcbc_data_rate = -1;
+	t_u8 rate[MAX_RATES];
+	int found = 0;
+	char country_80211d[4];
+	t_u8 state_80211d = 0;
+	int chan_mode = 0;
+	int band = 0;
+	int band_flag = 0;
+	int chan_number = 0;
+	t_u16 max_sta_num_supported = 0;
+	fw_info fw;
+	struct eth_priv_vhtcfg vhtcfg = { 0 };
+	int ret = UAP_SUCCESS;
+	memset(rate, 0, MAX_RATES);
+	/* Check if file exists */
+	config_file = fopen(argv[0], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return UAP_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		ret = UAP_FAILURE;
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+#if DEBUG
+		uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n",
+			   li, line);
+#endif
+		arg_num = parse_line(line, args);
+#if DEBUG
+		uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n",
+			   arg_num);
+		for (i = 0; i < arg_num; i++) {
+			uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1,
+				   args[i]);
+		}
+#endif
+		/* Check for end of AP configurations */
+		if (is_ap_config == 1) {
+			if (strcmp(args[0], "}") == 0) {
+				is_ap_config = 0;
+				if (tx_data_rate != -1) {
+					if ((!rate[0]) && (tx_data_rate) &&
+					    (is_tx_rate_valid
+					     ((t_u8)tx_data_rate) !=
+					     UAP_SUCCESS)) {
+						printf("ERR: Invalid Tx Data Rate \n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+					if (rate[0] && tx_data_rate) {
+						for (i = 0; rate[i] != 0; i++) {
+							if ((rate[i] &
+							     ~BASIC_RATE_SET_BIT)
+							    == tx_data_rate) {
+								found = 1;
+								break;
+							}
+						}
+						if (!found) {
+							printf("ERR: Invalid Tx Data Rate \n");
+							ret = UAP_FAILURE;
+							goto done;
+						}
+					}
+				}
+				if (tx_beacon_rate != -1) {
+					if ((!rate[0]) && (tx_beacon_rate) &&
+					    (is_tx_rate_valid
+					     ((t_u8)tx_beacon_rate) !=
+					     UAP_SUCCESS)) {
+						printf("ERR: Invalid Tx Beacon Rate \n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+					if (rate[0] && tx_beacon_rate) {
+						for (i = 0; rate[i] != 0; i++) {
+							if ((rate[i] &
+							     ~BASIC_RATE_SET_BIT)
+							    == tx_beacon_rate) {
+								found = 1;
+								break;
+							}
+						}
+						if (!found) {
+							printf("ERR: Invalid Tx Beacon Rate \n");
+							ret = UAP_FAILURE;
+							goto done;
+						}
+					}
+					/* Append a new TLV */
+					tlvbuf_tx_data_rate *tlv = NULL;
+					tlv_len = sizeof(tlvbuf_tx_data_rate);
+					tmp_buffer =
+						realloc(buffer,
+							cmd_len + tlv_len);
+					if (!tmp_buffer) {
+						printf("ERR:Cannot append tx beacon rate TLV!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					} else {
+						buffer = tmp_buffer;
+						tmp_buffer = NULL;
+					}
+					cmd_buf =
+						(apcmdbuf_sys_configure *)
+						buffer;
+					tlv = (tlvbuf_tx_data_rate *)(buffer +
+								      cmd_len);
+					cmd_len += tlv_len;
+					/* Set TLV fields */
+					tlv->tag = MRVL_TX_BEACON_RATE_TLV_ID;
+					tlv->length = 2;
+					tlv->tx_data_rate = tx_beacon_rate;
+					endian_convert_tlv_header_out(tlv);
+					tlv->tx_data_rate =
+						uap_cpu_to_le16(tlv->
+								tx_data_rate);
+				}
+				if (mcbc_data_rate != -1) {
+					if ((!rate[0]) && (mcbc_data_rate) &&
+					    (is_mcbc_rate_valid
+					     ((t_u8)mcbc_data_rate) !=
+					     UAP_SUCCESS)) {
+						printf("ERR: Invalid Tx Data Rate \n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+					if (rate[0] && mcbc_data_rate) {
+						for (i = 0; rate[i] != 0; i++) {
+							if (rate[i] &
+							    BASIC_RATE_SET_BIT)
+							{
+								if ((rate[i] &
+								     ~BASIC_RATE_SET_BIT)
+								    ==
+								    mcbc_data_rate)
+								{
+									found = 1;
+									break;
+								}
+							}
+						}
+						if (!found) {
+							printf("ERR: Invalid MCBC Data Rate \n");
+							ret = UAP_FAILURE;
+							goto done;
+						}
+					}
+
+					/* Append a new TLV */
+					tlvbuf_mcbc_data_rate *tlv = NULL;
+					tlv_len = sizeof(tlvbuf_mcbc_data_rate);
+					tmp_buffer =
+						realloc(buffer,
+							cmd_len + tlv_len);
+					if (!tmp_buffer) {
+						printf("ERR:Cannot append tx data rate TLV!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					} else {
+						buffer = tmp_buffer;
+						tmp_buffer = NULL;
+					}
+					cmd_buf =
+						(apcmdbuf_sys_configure *)
+						buffer;
+					tlv = (tlvbuf_mcbc_data_rate *)(buffer +
+									cmd_len);
+					cmd_len += tlv_len;
+					/* Set TLV fields */
+					tlv->tag = MRVL_MCBC_DATA_RATE_TLV_ID;
+					tlv->length = 2;
+					tlv->mcbc_datarate = mcbc_data_rate;
+					endian_convert_tlv_header_out(tlv);
+					tlv->mcbc_datarate =
+						uap_cpu_to_le16(tlv->
+								mcbc_datarate);
+				}
+				if ((protocol == PROTOCOL_STATIC_WEP) &&
+				    (enable_11n == 1)) {
+					printf("ERR:WEP cannot be used when AP operates in 802.11n mode.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				if ((protocol == PROTOCOL_WPA2_MIXED) &&
+				    ((pwkcipher_wpa < 0) ||
+				     (pwkcipher_wpa2 < 0))) {
+					printf("ERR:Both PwkCipherWPA and PwkCipherWPA2 should be defined for Mixed mode.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+
+				if (((pwkcipher_wpa >= 0) ||
+				     (pwkcipher_wpa2 >= 0)) &&
+				    (gwkcipher >= 0)) {
+					if ((protocol == PROTOCOL_WPA) ||
+					    (protocol == PROTOCOL_WPA2_MIXED)) {
+						if (enable_11n != -1) {
+							if (is_cipher_valid_with_11n(pwkcipher_wpa, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) {
+								printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
+								ret = UAP_FAILURE;
+								goto done;
+							}
+						} else if
+							(is_cipher_valid_with_proto
+							 (pwkcipher_wpa,
+							  gwkcipher,
+							  protocol) !=
+							 UAP_SUCCESS) {
+							printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
+							ret = UAP_FAILURE;
+							goto done;
+						}
+					}
+					if ((protocol == PROTOCOL_WPA2) ||
+					    (protocol == PROTOCOL_WPA2_MIXED)) {
+						if (enable_11n != -1) {
+							if (is_cipher_valid_with_11n(pwkcipher_wpa2, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) {
+								printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
+								ret = UAP_FAILURE;
+								goto done;
+							}
+						} else if
+							(is_cipher_valid_with_proto
+							 (pwkcipher_wpa2,
+							  gwkcipher,
+							  protocol) !=
+							 UAP_SUCCESS) {
+							printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
+							ret = UAP_FAILURE;
+							goto done;
+						}
+					}
+				}
+
+				if (0 == get_fw_info(&fw)) {
+					/*check whether support 802.11AC through BAND_AAC bit */
+					if (fw.fw_bands & BAND_AAC) {
+						ret = get_802_11ac_cfg(&vhtcfg);
+						if (ret != UAP_SUCCESS)
+							goto done;
+						if (enable_11n != -1) {
+							/* Note: When 11AC is disabled, FW sets vht_rx_mcs to 0xffff */
+							if ((vhtcfg.
+							     vht_rx_mcs !=
+							     0xffff) &&
+							    (!enable_11n)) {
+								printf("ERR: 11n must be enabled when AP operates in 11ac mode. \n");
+								ret = UAP_FAILURE;
+								goto done;
+							}
+						}
+					} else
+						printf("No support 802 11AC.\n");
+				} else {
+					printf("ERR: get_fw_info fail\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+
+				if (protocol != -1) {
+					tlvbuf_protocol *tlv = NULL;
+					/* Append a new TLV */
+					tlv_len = sizeof(tlvbuf_protocol);
+					tmp_buffer =
+						realloc(buffer,
+							cmd_len + tlv_len);
+					if (!tmp_buffer) {
+						printf("ERR:Cannot append protocol TLV!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					} else {
+						buffer = tmp_buffer;
+						tmp_buffer = NULL;
+					}
+					cmd_buf =
+						(apcmdbuf_sys_configure *)
+						buffer;
+					tlv = (tlvbuf_protocol *)(buffer +
+								  cmd_len);
+					cmd_len += tlv_len;
+					/* Set TLV fields */
+					tlv->tag = MRVL_PROTOCOL_TLV_ID;
+					tlv->length = 2;
+					tlv->protocol = protocol;
+					endian_convert_tlv_header_out(tlv);
+					tlv->protocol =
+						uap_cpu_to_le16(tlv->protocol);
+					if (protocol &
+					    (PROTOCOL_WPA | PROTOCOL_WPA2)) {
+						tlvbuf_akmp *tlv = NULL;
+						/* Append a new TLV */
+						tlv_len = sizeof(tlvbuf_akmp);
+						tmp_buffer =
+							realloc(buffer,
+								cmd_len +
+								tlv_len);
+						if (!tmp_buffer) {
+							printf("ERR:Cannot append AKMP TLV!\n");
+							ret = UAP_FAILURE;
+							goto done;
+						} else {
+							buffer = tmp_buffer;
+							tmp_buffer = NULL;
+						}
+						cmd_buf =
+							(apcmdbuf_sys_configure
+							 *)buffer;
+						tlv = (tlvbuf_akmp *)(buffer +
+								      cmd_len);
+						cmd_len += tlv_len;
+						/* Set TLV fields */
+						tlv->tag = MRVL_AKMP_TLV_ID;
+						tlv->length = 4;	/* sizeof(tlvbuf_akmp) - TLVHEADER */
+						tlv->key_mgmt = KEY_MGMT_PSK;
+						endian_convert_tlv_header_out
+							(tlv);
+						tlv->key_mgmt =
+							uap_cpu_to_le16(tlv->
+									key_mgmt);
+						tlv->key_mgmt_operation = 0;
+					}
+				}
+				if (pwkcipher_wpa >= 0) {
+					tlvbuf_pwk_cipher *tlv = NULL;
+					/* Append a new TLV */
+					tlv_len = sizeof(tlvbuf_pwk_cipher);
+					tmp_buffer =
+						realloc(buffer,
+							cmd_len + tlv_len);
+					if (!tmp_buffer) {
+						printf("ERR:Cannot append cipher TLV!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					} else {
+						buffer = tmp_buffer;
+						tmp_buffer = NULL;
+					}
+					cmd_buf =
+						(apcmdbuf_sys_configure *)
+						buffer;
+					tlv = (tlvbuf_pwk_cipher *)(buffer +
+								    cmd_len);
+					memset(tlv, 0, tlv_len);
+					cmd_len += tlv_len;
+					/* Set TLV fields */
+					tlv->tag = MRVL_CIPHER_PWK_TLV_ID;
+					tlv->length =
+						sizeof(tlvbuf_pwk_cipher) -
+						TLVHEADER_LEN;
+					tlv->pairwise_cipher = pwkcipher_wpa;
+					tlv->protocol = PROTOCOL_WPA;
+					endian_convert_tlv_header_out(tlv);
+					tlv->protocol =
+						uap_cpu_to_le16(tlv->protocol);
+				}
+
+				if (pwkcipher_wpa2 >= 0) {
+					tlvbuf_pwk_cipher *tlv = NULL;
+					/* Append a new TLV */
+					tlv_len = sizeof(tlvbuf_pwk_cipher);
+					tmp_buffer =
+						realloc(buffer,
+							cmd_len + tlv_len);
+					if (!tmp_buffer) {
+						printf("ERR:Cannot append cipher TLV!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					} else {
+						buffer = tmp_buffer;
+						tmp_buffer = NULL;
+					}
+					cmd_buf =
+						(apcmdbuf_sys_configure *)
+						buffer;
+					tlv = (tlvbuf_pwk_cipher *)(buffer +
+								    cmd_len);
+					memset(tlv, 0, tlv_len);
+					cmd_len += tlv_len;
+					/* Set TLV fields */
+					tlv->tag = MRVL_CIPHER_PWK_TLV_ID;
+					tlv->length =
+						sizeof(tlvbuf_pwk_cipher) -
+						TLVHEADER_LEN;
+					tlv->pairwise_cipher = pwkcipher_wpa2;
+					tlv->protocol = PROTOCOL_WPA2;
+					endian_convert_tlv_header_out(tlv);
+					tlv->protocol =
+						uap_cpu_to_le16(tlv->protocol);
+				}
+
+				if (gwkcipher >= 0) {
+					tlvbuf_gwk_cipher *tlv = NULL;
+					/* Append a new TLV */
+					tlv_len = sizeof(tlvbuf_gwk_cipher);
+					tmp_buffer =
+						realloc(buffer,
+							cmd_len + tlv_len);
+					if (!tmp_buffer) {
+						printf("ERR:Cannot append cipher TLV!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					} else {
+						buffer = tmp_buffer;
+						tmp_buffer = NULL;
+					}
+					cmd_buf =
+						(apcmdbuf_sys_configure *)
+						buffer;
+					tlv = (tlvbuf_gwk_cipher *)(buffer +
+								    cmd_len);
+					memset(tlv, 0, tlv_len);
+					cmd_len += tlv_len;
+					/* Set TLV fields */
+					tlv->tag = MRVL_CIPHER_GWK_TLV_ID;
+					tlv->length =
+						sizeof(tlvbuf_gwk_cipher) -
+						TLVHEADER_LEN;
+					tlv->group_cipher = gwkcipher;
+					endian_convert_tlv_header_out(tlv);
+				}
+
+				cmd_buf->size = cmd_len;
+				/* Send collective command */
+				if (uap_ioctl
+				    ((t_u8 *)cmd_buf, &cmd_len,
+				     cmd_len) == UAP_SUCCESS) {
+					if (cmd_buf->result != CMD_SUCCESS) {
+						printf("ERR: Failed to set the configuration!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+				} else {
+					printf("ERR: Command sending failed!\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				cmd_len = 0;
+				if (buffer) {
+					free(buffer);
+					buffer = NULL;
+				}
+				continue;
+			}
+		}
+
+		/* Check for beginning of AP configurations */
+		if (strcmp(args[0], "ap_config") == 0) {
+			is_ap_config = 1;
+			cmd_len = sizeof(apcmdbuf_sys_configure);
+			if (buffer) {
+				free(buffer);
+				buffer = NULL;
+			}
+			buffer = (t_u8 *)malloc(cmd_len);
+			if (!buffer) {
+				printf("ERR:Cannot allocate memory!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+			cmd_buf->size = cmd_len;
+			cmd_buf->seq_num = 0;
+			cmd_buf->result = 0;
+			cmd_buf->action = ACTION_SET;
+			continue;
+		}
+
+		/* Check for end of AP MAC address filter configurations */
+		if (is_ap_mac_filter == 1) {
+			if (strcmp(args[0], "}") == 0) {
+				is_ap_mac_filter = 0;
+				if (filter_tlv->count != filter_mac_count) {
+					printf("ERR:Number of MAC address provided does not match 'Count'\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				if (filter_tlv->count) {
+					filter_tlv->length =
+						(filter_tlv->count * ETH_ALEN) +
+						2;
+					cmd_len -=
+						(MAX_MAC_ONESHOT_FILTER -
+						 filter_mac_count) * ETH_ALEN;
+				} else {
+					filter_tlv->length =
+						(MAX_MAC_ONESHOT_FILTER *
+						 ETH_ALEN) + 2;
+					memset(filter_tlv->mac_address, 0,
+					       MAX_MAC_ONESHOT_FILTER *
+					       ETH_ALEN);
+				}
+				cmd_buf->size = cmd_len;
+				endian_convert_tlv_header_out(filter_tlv);
+				if (uap_ioctl
+				    ((t_u8 *)cmd_buf, &cmd_len,
+				     cmd_len) == UAP_SUCCESS) {
+					if (cmd_buf->result != CMD_SUCCESS) {
+						printf("ERR: Failed to set the configuration!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+				} else {
+					printf("ERR: Command sending failed!\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+
+				cmd_len = 0;
+				if (buffer) {
+					free(buffer);
+					buffer = NULL;
+				}
+				continue;
+			}
+		}
+
+		if (strcmp(args[0], "11d_enable") == 0) {
+			if (IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) {
+				printf("ERR: valid input for state are 0 or 1\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			state_80211d = (t_u8)A2HEXDECIMAL(args[1]);
+
+			if ((state_80211d != 0) && (state_80211d != 1)) {
+				printf("ERR: valid input for state are 0 or 1 \n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			if (sg_snmp_mib
+			    (ACTION_SET, OID_80211D_ENABLE,
+			     sizeof(state_80211d), &state_80211d)
+			    == UAP_FAILURE) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+		}
+
+		if (strcmp(args[0], "country") == 0) {
+			apcmdbuf_cfg_80211d *cmd_buf = NULL;
+			ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS];
+			t_u8 no_of_sub_band = 0;
+			t_u16 buf_len;
+			t_u16 cmdlen;
+			t_u8 *buf = NULL;
+
+			if ((strlen(args[1]) > 3) || (strlen(args[1]) == 0)) {
+				printf("In-correct country input\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			strncpy(country_80211d, args[1],
+				sizeof(country_80211d) - 1);
+			for (i = 0; (unsigned int)i < strlen(country_80211d);
+			     i++) {
+				if ((country_80211d[i] < 'A') ||
+				    (country_80211d[i] > 'z')) {
+					printf("Invalid Country Code\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				if (country_80211d[i] > 'Z')
+					country_80211d[i] =
+						country_80211d[i] - 'a' + 'A';
+			}
+			no_of_sub_band =
+				parse_domain_file(country_80211d, band,
+						  sub_bands, NULL);
+			if (no_of_sub_band == UAP_FAILURE) {
+				printf("Parsing Failed\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			buf_len = sizeof(apcmdbuf_cfg_80211d);
+			buf_len +=
+				no_of_sub_band *
+				sizeof(ieeetypes_subband_set_t);
+			buf = (t_u8 *)malloc(buf_len);
+			if (!buf) {
+				printf("ERR:Cannot allocate buffer from command!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			memset(buf, 0, buf_len);
+			cmd_buf = (apcmdbuf_cfg_80211d *)buf;
+			cmdlen = buf_len;
+			cmd_buf->size = cmdlen - BUF_HEADER_SIZE;
+			cmd_buf->result = 0;
+			cmd_buf->seq_num = 0;
+			cmd_buf->action = uap_cpu_to_le16(ACTION_SET);
+			cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
+			cmd_buf->domain.tag = uap_cpu_to_le16(TLV_TYPE_DOMAIN);
+			cmd_buf->domain.length =
+				uap_cpu_to_le16(sizeof(domain_param_t)
+						- BUF_HEADER_SIZE +
+						(no_of_sub_band *
+						 sizeof
+						 (ieeetypes_subband_set_t)));
+
+			memset(cmd_buf->domain.country_code, ' ',
+			       sizeof(cmd_buf->domain.country_code));
+			memcpy(cmd_buf->domain.country_code, country_80211d,
+			       strlen(country_80211d));
+			memcpy(cmd_buf->domain.subband, sub_bands,
+			       no_of_sub_band *
+			       sizeof(ieeetypes_subband_set_t));
+
+			/* Send the command */
+			if (uap_ioctl((t_u8 *)cmd_buf, &cmdlen, cmdlen) ==
+			    UAP_SUCCESS) {
+				if (cmd_buf->result != CMD_SUCCESS) {
+					printf("ERR: Failed to set the configuration!\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+			} else {
+				printf("ERR: Command sending failed!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+
+			if (buf)
+				free(buf);
+		}
+
+		/* Check for beginning of AP MAC address filter configurations */
+		if (strcmp(args[0], "ap_mac_filter") == 0) {
+			is_ap_mac_filter = 1;
+			cmd_len =
+				sizeof(apcmdbuf_sys_configure) +
+				sizeof(tlvbuf_sta_mac_addr_filter) +
+				(MAX_MAC_ONESHOT_FILTER * ETH_ALEN);
+			if (buffer) {
+				free(buffer);
+				buffer = NULL;
+			}
+			buffer = (t_u8 *)malloc(cmd_len);
+			if (!buffer) {
+				printf("ERR:Cannot allocate memory!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+			cmd_buf->size = cmd_len;
+			cmd_buf->seq_num = 0;
+			cmd_buf->result = 0;
+			cmd_buf->action = ACTION_SET;
+			filter_tlv =
+				(tlvbuf_sta_mac_addr_filter *)(buffer +
+							       sizeof
+							       (apcmdbuf_sys_configure));
+			filter_tlv->tag = MRVL_STA_MAC_ADDR_FILTER_TLV_ID;
+			filter_tlv->length = 2;
+			filter_tlv->count = 0;
+			filter_mac_count = 0;
+			continue;
+		}
+		if ((strcmp(args[0], "FilterMode") == 0) && is_ap_mac_filter) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) ||
+			    (atoi(args[1]) > 2)) {
+				printf("ERR:Illegal FilterMode paramter %d. Must be either '0', '1', or '2'.\n", atoi(args[1]));
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			filter_tlv->filter_mode = atoi(args[1]);
+			continue;
+		}
+		if ((strcmp(args[0], "Count") == 0) && is_ap_mac_filter) {
+			filter_tlv->count = atoi(args[1]);
+			if ((ISDIGIT(args[1]) == 0) ||
+			    (filter_tlv->count > MAX_MAC_ONESHOT_FILTER)) {
+				printf("ERR: Illegal Count parameter.\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+		}
+		if ((strncmp(args[0], "mac_", 4) == 0) && is_ap_mac_filter) {
+			if (filter_mac_count < MAX_MAC_ONESHOT_FILTER) {
+				if (mac2raw
+				    (args[1],
+				     &filter_tlv->mac_address[filter_mac_count *
+							      ETH_ALEN]) !=
+				    UAP_SUCCESS) {
+					printf("ERR: Invalid MAC address %s \n",
+					       args[1]);
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				filter_mac_count++;
+			} else {
+				printf("ERR: Filter table can not have more than %d MAC addresses\n", MAX_MAC_ONESHOT_FILTER);
+				ret = UAP_FAILURE;
+				goto done;
+			}
+		}
+
+		if (strcmp(args[0], "SSID") == 0) {
+			if (arg_num == 1) {
+				printf("ERR:SSID field is blank!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				tlvbuf_ssid *tlv = NULL;
+				if (args[1][0] == '"') {
+					args[1]++;
+				}
+				if (args[1][strlen(args[1]) - 1] == '"') {
+					args[1][strlen(args[1]) - 1] = '\0';
+				}
+				if ((strlen(args[1]) > MAX_SSID_LENGTH) ||
+				    (strlen(args[1]) == 0)) {
+					printf("ERR:SSID length out of range (%d to %d).\n", MIN_SSID_LENGTH, MAX_SSID_LENGTH);
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				/* Append a new TLV */
+				tlv_len = sizeof(tlvbuf_ssid) + strlen(args[1]);
+				tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot realloc SSID TLV!\n");
+					ret = UAP_FAILURE;
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				cmd_buf = (apcmdbuf_sys_configure *)buffer;
+				tlv = (tlvbuf_ssid *)(buffer + cmd_len);
+				cmd_len += tlv_len;
+				/* Set TLV fields */
+				tlv->tag = MRVL_SSID_TLV_ID;
+				tlv->length = strlen(args[1]);
+				memcpy(tlv->ssid, args[1], tlv->length);
+				endian_convert_tlv_header_out(tlv);
+			}
+		}
+		if (strcmp(args[0], "BeaconPeriod") == 0) {
+			if (is_input_valid(BEACONPERIOD, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_beacon_period *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_beacon_period);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot realloc beacon period TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_beacon_period *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_BEACON_PERIOD_TLV_ID;
+			tlv->length = 2;
+			tlv->beacon_period_ms = (t_u16)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->beacon_period_ms =
+				uap_cpu_to_le16(tlv->beacon_period_ms);
+		}
+		if (strcmp(args[0], "ChanList") == 0) {
+			if (is_input_valid(SCANCHANNELS, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+
+			tlvbuf_channel_list *tlv = NULL;
+			channel_list *pchan_list = NULL;
+			/* Append a new TLV */
+			tlv_len =
+				sizeof(tlvbuf_channel_list) +
+				((arg_num - 1) * sizeof(channel_list));
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append channel list TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_channel_list *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_CHANNELLIST_TLV_ID;
+			tlv->length = sizeof(channel_list) * (arg_num - 1);
+			pchan_list = (channel_list *) tlv->chan_list;
+			for (i = 0; i < (arg_num - 1); i++) {
+				band_flag = -1;
+				sscanf(args[i + 1], "%d.%d", &chan_number,
+				       &band_flag);
+				pchan_list->chan_number = chan_number;
+				pchan_list->bandcfg.chanBand = BAND_2GHZ;
+				if (((band_flag != -1) && (band_flag)) ||
+				    (chan_number > MAX_CHANNELS_BG)) {
+					pchan_list->bandcfg.chanBand =
+						BAND_5GHZ;
+				}
+				pchan_list++;
+			}
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "Channel") == 0) {
+			if (is_input_valid(CHANNEL, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_channel_config *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_channel_config);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append channel TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_channel_config *)(buffer + cmd_len);
+			channel_band_tlv = tlv;
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_CHANNELCONFIG_TLV_ID;
+			tlv->length =
+				sizeof(tlvbuf_channel_config) - TLVHEADER_LEN;
+			tlv->chan_number = (t_u8)atoi(args[1]);
+			if (tlv->chan_number > MAX_CHANNELS_BG)
+				band = BAND_A;
+			else
+				band = BAND_B | BAND_G;
+			if ((arg_num - 1) == 2) {
+				chan_mode = atoi(args[2]);
+				memset(&(tlv->bandcfg), 0,
+				       sizeof(tlv->bandcfg));
+				if (chan_mode & BITMAP_ACS_MODE) {
+					int mode;
+
+					if (uap_ioctl_dfs_repeater_mode(&mode)
+					    == UAP_SUCCESS) {
+						if (mode) {
+							printf("ERR: ACS in DFS Repeater mode" " is not allowed\n");
+							ret = UAP_FAILURE;
+							goto done;
+						}
+					}
+					tlv->bandcfg.scanMode = SCAN_MODE_ACS;
+				}
+				if (chan_mode & BITMAP_CHANNEL_ABOVE)
+					tlv->bandcfg.chan2Offset =
+						SEC_CHAN_ABOVE;
+				if (chan_mode & BITMAP_CHANNEL_BELOW)
+					tlv->bandcfg.chan2Offset =
+						SEC_CHAN_BELOW;
+			} else
+				memset(&(tlv->bandcfg), 0,
+				       sizeof(tlv->bandcfg));
+			if (tlv->chan_number > MAX_CHANNELS_BG) {
+				tlv->bandcfg.chanBand = BAND_5GHZ;
+			}
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "Band") == 0) {
+			if (is_input_valid(BAND, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			if (channel_band_tlv == NULL) {
+				printf("ERR: Channel parameter should be specified before Band\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			/* If band is provided, clear previous value of band */
+			channel_band_tlv->bandcfg.chanBand = BAND_2GHZ;
+			if (atoi(args[1]) == 0) {
+				band = BAND_B | BAND_G;
+			} else {
+				channel_band_tlv->bandcfg.chanBand = BAND_5GHZ;
+				band = BAND_A;
+			}
+		}
+		if (strcmp(args[0], "AP_MAC") == 0) {
+			tlvbuf_ap_mac_address *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_ap_mac_address);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append ap_mac TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_ap_mac_address *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			cmd_buf->action = ACTION_SET;
+			tlv->tag = MRVL_AP_MAC_ADDRESS_TLV_ID;
+			tlv->length = ETH_ALEN;
+			if ((ret =
+			     mac2raw(args[1],
+				     tlv->ap_mac_addr)) != UAP_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       UAP_FAILURE ? "Invalid MAC" : ret ==
+				       UAP_RET_MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			endian_convert_tlv_header_out(tlv);
+		}
+
+		if (strcmp(args[0], "Rate") == 0) {
+			if (is_input_valid(RATE, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				printf("ERR: Invalid Rate input\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_rates *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_rates) + arg_num - 1;
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append rates TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_rates *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_RATES_TLV_ID;
+			tlv->length = arg_num - 1;
+			for (i = 0; i < tlv->length; i++) {
+				rate[i] = tlv->operational_rates[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "TxPowerLevel") == 0) {
+			if (is_input_valid(TXPOWER, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				printf("ERR:Invalid TxPowerLevel \n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				tlvbuf_tx_power *tlv = NULL;
+				/* Append a new TLV */
+				tlv_len = sizeof(tlvbuf_tx_power);
+				tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot append tx power level TLV!\n");
+					ret = UAP_FAILURE;
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				cmd_buf = (apcmdbuf_sys_configure *)buffer;
+				tlv = (tlvbuf_tx_power *)(buffer + cmd_len);
+				cmd_len += tlv_len;
+				/* Set TLV fields */
+				tlv->tag = MRVL_TX_POWER_TLV_ID;
+				tlv->length = 1;
+				tlv->tx_power_dbm = (t_u8)atoi(args[1]);
+				endian_convert_tlv_header_out(tlv);
+			}
+		}
+		if (strcmp(args[0], "BroadcastSSID") == 0) {
+			if (is_input_valid(BROADCASTSSID, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_bcast_ssid_ctl *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_bcast_ssid_ctl);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append SSID broadcast control TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_bcast_ssid_ctl *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_BCAST_SSID_CTL_TLV_ID;
+			tlv->length = 1;
+			tlv->bcast_ssid_ctl = (t_u8)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "RTSThreshold") == 0) {
+			if (is_input_valid(RTSTHRESH, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_rts_threshold *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_rts_threshold);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append RTS threshold TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_rts_threshold *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_RTS_THRESHOLD_TLV_ID;
+			tlv->length = 2;
+			tlv->rts_threshold = (t_u16)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->rts_threshold =
+				uap_cpu_to_le16(tlv->rts_threshold);
+		}
+		if (strcmp(args[0], "FragThreshold") == 0) {
+			if (is_input_valid(FRAGTHRESH, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_frag_threshold *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_frag_threshold);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append Fragmentation threshold TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_frag_threshold *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_FRAG_THRESHOLD_TLV_ID;
+			tlv->length = 2;
+			tlv->frag_threshold = (t_u16)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->frag_threshold =
+				uap_cpu_to_le16(tlv->frag_threshold);
+		}
+		if (strcmp(args[0], "DTIMPeriod") == 0) {
+			if (is_input_valid(DTIMPERIOD, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_dtim_period *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_dtim_period);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append DTIM period TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_dtim_period *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_DTIM_PERIOD_TLV_ID;
+			tlv->length = 1;
+			tlv->dtim_period = (t_u8)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "RSNReplayProtection") == 0) {
+			if (is_input_valid(RSNREPLAYPROT, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_rsn_replay_prot *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_rsn_replay_prot);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append RSN replay protection TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_rsn_replay_prot *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_RSN_REPLAY_PROT_TLV_ID;
+			tlv->length = 1;
+			tlv->rsn_replay_prot = (t_u8)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "TxBeaconRate") == 0) {
+			if (is_input_valid(TXBEACONRATE, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tx_beacon_rate = (t_u16)A2HEXDECIMAL(args[1]);
+		}
+		if (strcmp(args[0], "MCBCdataRate") == 0) {
+			if (is_input_valid(MCBCDATARATE, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			mcbc_data_rate = (t_u16)A2HEXDECIMAL(args[1]);
+		}
+		if (strcmp(args[0], "PktFwdCtl") == 0) {
+			if (is_input_valid(PKTFWD, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_pkt_fwd_ctl *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_pkt_fwd_ctl);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append packet forwarding control TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_pkt_fwd_ctl *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_PKT_FWD_CTL_TLV_ID;
+			tlv->length = 1;
+			tlv->pkt_fwd_ctl = (t_u8)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "StaAgeoutTimer") == 0) {
+			if (is_input_valid
+			    (STAAGEOUTTIMER, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_sta_ageout_timer *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_sta_ageout_timer);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append STA ageout timer TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_sta_ageout_timer *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_STA_AGEOUT_TIMER_TLV_ID;
+			tlv->length = 4;
+			tlv->sta_ageout_timer_ms = (t_u32)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->sta_ageout_timer_ms =
+				uap_cpu_to_le32(tlv->sta_ageout_timer_ms);
+		}
+		if (strcmp(args[0], "PSStaAgeoutTimer") == 0) {
+			if (is_input_valid
+			    (PSSTAAGEOUTTIMER, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_ps_sta_ageout_timer *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_ps_sta_ageout_timer);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append PS STA ageout timer TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_ps_sta_ageout_timer *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_PS_STA_AGEOUT_TIMER_TLV_ID;
+			tlv->length = 4;
+			tlv->ps_sta_ageout_timer_ms = (t_u32)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->ps_sta_ageout_timer_ms =
+				uap_cpu_to_le32(tlv->ps_sta_ageout_timer_ms);
+		}
+		if (strcmp(args[0], "AuthMode") == 0) {
+			if (is_input_valid(AUTHMODE, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_auth_mode *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_auth_mode);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append auth mode TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_auth_mode *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_AUTH_TLV_ID;
+			tlv->length = 1;
+			tlv->auth_mode = (t_u8)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "KeyIndex") == 0) {
+			if (arg_num == 1) {
+				printf("KeyIndex is blank!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				if (ISDIGIT(args[1]) == 0) {
+					printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				keyindex = atoi(args[1]);
+				if ((keyindex < 0) || (keyindex > 3)) {
+					printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+			}
+		}
+		if (strncmp(args[0], "Key_", 4) == 0) {
+			if (arg_num == 1) {
+				printf("ERR:%s is blank!\n", args[0]);
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				tlvbuf_wep_key *tlv = NULL;
+				int key_len = 0;
+				if (args[1][0] == '"') {
+					if ((strlen(args[1]) != 2) &&
+					    (strlen(args[1]) != 7) &&
+					    (strlen(args[1]) != 15)) {
+						printf("ERR:Wrong key length!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+					key_len = strlen(args[1]) - 2;
+				} else {
+					if ((strlen(args[1]) != 0) &&
+					    (strlen(args[1]) != 10) &&
+					    (strlen(args[1]) != 26)) {
+						printf("ERR:Wrong key length!\n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+					if (UAP_FAILURE == ishexstring(args[1])) {
+						printf("ERR:Only hex digits are allowed when key length is 10 or 26\n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+					key_len = strlen(args[1]) / 2;
+				}
+
+				/* Append a new TLV */
+				tlv_len = sizeof(tlvbuf_wep_key) + key_len;
+				tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot append WEP key configurations TLV!\n");
+					ret = UAP_FAILURE;
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				cmd_buf = (apcmdbuf_sys_configure *)buffer;
+				tlv = (tlvbuf_wep_key *)(buffer + cmd_len);
+				cmd_len += tlv_len;
+				/* Set TLV fields */
+				tlv->tag = MRVL_WEP_KEY_TLV_ID;
+				tlv->length = key_len + 2;
+				if (strcmp(args[0], "Key_0") == 0) {
+					tlv->key_index = 0;
+				} else if (strcmp(args[0], "Key_1") == 0) {
+					tlv->key_index = 1;
+				} else if (strcmp(args[0], "Key_2") == 0) {
+					tlv->key_index = 2;
+				} else if (strcmp(args[0], "Key_3") == 0) {
+					tlv->key_index = 3;
+				}
+				if (keyindex == tlv->key_index) {
+					tlv->is_default = 1;
+				} else {
+					tlv->is_default = 0;
+				}
+				if (args[1][0] == '"') {
+					memcpy(tlv->key, &args[1][1],
+					       strlen(args[1]) - 2);
+				} else {
+					string2raw(args[1], tlv->key);
+				}
+				endian_convert_tlv_header_out(tlv);
+			}
+		}
+		if (strcmp(args[0], "PSK") == 0) {
+			if (arg_num == 1) {
+				printf("ERR:PSK is blank!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				tlvbuf_wpa_passphrase *tlv = NULL;
+				if (args[1][0] == '"') {
+					args[1]++;
+				}
+				if (args[1][strlen(args[1]) - 1] == '"') {
+					args[1][strlen(args[1]) - 1] = '\0';
+				}
+				tlv_len =
+					sizeof(tlvbuf_wpa_passphrase) +
+					strlen(args[1]);
+				if (strlen(args[1]) > MAX_WPA_PASSPHRASE_LENGTH) {
+					printf("ERR:PSK too long.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				if (strlen(args[1]) < MIN_WPA_PASSPHRASE_LENGTH) {
+					printf("ERR:PSK too short.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				if (strlen(args[1]) ==
+				    MAX_WPA_PASSPHRASE_LENGTH) {
+					if (UAP_FAILURE == ishexstring(args[1])) {
+						printf("ERR:Only hex digits are allowed when passphrase's length is 64\n");
+						ret = UAP_FAILURE;
+						goto done;
+					}
+				}
+				/* Append a new TLV */
+				tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot append WPA passphrase TLV!\n");
+					ret = UAP_FAILURE;
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				cmd_buf = (apcmdbuf_sys_configure *)buffer;
+				tlv = (tlvbuf_wpa_passphrase *)(buffer +
+								cmd_len);
+				cmd_len += tlv_len;
+				/* Set TLV fields */
+				tlv->tag = MRVL_WPA_PASSPHRASE_TLV_ID;
+				tlv->length = strlen(args[1]);
+				memcpy(tlv->passphrase, args[1], tlv->length);
+				endian_convert_tlv_header_out(tlv);
+			}
+		}
+		if (strcmp(args[0], "Protocol") == 0) {
+			if (is_input_valid(PROTOCOL, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			protocol = (t_u16)atoi(args[1]);
+		}
+		if ((strcmp(args[0], "PairwiseCipher") == 0) ||
+		    (strcmp(args[0], "GroupCipher") == 0)) {
+			printf("ERR:PairwiseCipher and GroupCipher are not supported.\n" "    Please configure pairwise cipher using parameters PwkCipherWPA or PwkCipherWPA2\n" "    and group cipher using GwkCipher in the config file.\n");
+			ret = UAP_FAILURE;
+			goto done;
+		}
+
+		if ((protocol == PROTOCOL_NO_SECURITY) ||
+		    (protocol == PROTOCOL_STATIC_WEP)) {
+			if ((strcmp(args[0], "PwkCipherWPA") == 0) ||
+			    (strcmp(args[0], "PwkCipherWPA2") == 0)
+			    || (strcmp(args[0], "GwkCipher") == 0)) {
+				printf("ERR:Pairwise cipher and group cipher should not be defined for Open and WEP mode.\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+		}
+
+		if (strcmp(args[0], "PwkCipherWPA") == 0) {
+			if (arg_num == 1) {
+				printf("ERR:PwkCipherWPA is blank!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				if (ISDIGIT(args[1]) == 0) {
+					printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				if (atoi(args[1]) & ~CIPHER_BITMAP) {
+					printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				pwkcipher_wpa = atoi(args[1]);
+				if (enable_11n &&
+				    protocol != PROTOCOL_WPA2_MIXED) {
+					memset(&htcap, 0, sizeof(htcap));
+					if (UAP_SUCCESS ==
+					    get_sys_cfg_11n(&htcap)) {
+						if (htcap.supported_mcs_set[0]
+						    && (atoi(args[1]) ==
+							CIPHER_TKIP)) {
+							printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
+							ret = UAP_FAILURE;
+							goto done;
+						}
+					}
+				}
+			}
+		}
+
+		if (strcmp(args[0], "PwkCipherWPA2") == 0) {
+			if (arg_num == 1) {
+				printf("ERR:PwkCipherWPA2 is blank!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				if (ISDIGIT(args[1]) == 0) {
+					printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				if (atoi(args[1]) & ~CIPHER_BITMAP) {
+					printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n");
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				pwkcipher_wpa2 = atoi(args[1]);
+				if (enable_11n &&
+				    protocol != PROTOCOL_WPA2_MIXED) {
+					memset(&htcap, 0, sizeof(htcap));
+					if (UAP_SUCCESS ==
+					    get_sys_cfg_11n(&htcap)) {
+						if (htcap.supported_mcs_set[0]
+						    && (atoi(args[1]) ==
+							CIPHER_TKIP)) {
+							printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
+							ret = UAP_FAILURE;
+							goto done;
+						}
+					}
+				}
+			}
+		}
+		if (strcmp(args[0], "GwkCipher") == 0) {
+			if (is_input_valid(GWK_CIPHER, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			gwkcipher = atoi(args[1]);
+		}
+		if (strcmp(args[0], "GroupRekeyTime") == 0) {
+			if (is_input_valid
+			    (GROUPREKEYTIMER, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_group_rekey_timer *tlv = NULL;
+
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_group_rekey_timer);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append group rekey timer TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_group_rekey_timer *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_GRP_REKEY_TIME_TLV_ID;
+			tlv->length = 4;
+			tlv->group_rekey_time_sec = (t_u32)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->group_rekey_time_sec =
+				uap_cpu_to_le32(tlv->group_rekey_time_sec);
+		}
+		if (strcmp(args[0], "MaxStaNum") == 0) {
+			if (is_input_valid(MAXSTANUM, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			if (get_max_sta_num_supported(&max_sta_num_supported) ==
+			    UAP_FAILURE) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			if (atoi(args[1]) > max_sta_num_supported) {
+				printf("ERR: MAX_STA_NUM must be less than %d\n", max_sta_num_supported);
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_max_sta_num *tlv = NULL;
+
+			/* Append a new TLV */
+			tlv_len =
+				sizeof(tlvbuf_max_sta_num) -
+				sizeof(tlv->max_sta_num_supported);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot realloc max station number TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_max_sta_num *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_MAX_STA_CNT_TLV_ID;
+			tlv->length = 2;
+			tlv->max_sta_num_configured = (t_u16)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->max_sta_num_configured =
+				uap_cpu_to_le16(tlv->max_sta_num_configured);
+		}
+		if (strcmp(args[0], "Retrylimit") == 0) {
+			if (is_input_valid(RETRYLIMIT, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_retry_limit *tlv = NULL;
+
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_retry_limit);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot realloc retry limit TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_retry_limit *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_RETRY_LIMIT_TLV_ID;
+			tlv->length = 1;
+			tlv->retry_limit = (t_u8)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "PairwiseUpdateTimeout") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_eapol_pwk_hsk_timeout *tlv = NULL;
+
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_eapol_pwk_hsk_timeout);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append pairwise update timeout TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_eapol_pwk_hsk_timeout *)(buffer +
+							       cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_EAPOL_PWK_HSK_TIMEOUT_TLV_ID;
+			tlv->length = 4;
+			tlv->pairwise_update_timeout = (t_u32)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->pairwise_update_timeout =
+				uap_cpu_to_le32(tlv->pairwise_update_timeout);
+		}
+		if (strcmp(args[0], "PairwiseHandshakeRetries") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_eapol_pwk_hsk_retries *tlv = NULL;
+
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_eapol_pwk_hsk_retries);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append pairwise handshake retries TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_eapol_pwk_hsk_retries *)(buffer +
+							       cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_EAPOL_PWK_HSK_RETRIES_TLV_ID;
+			tlv->length = 4;
+			tlv->pwk_retries = (t_u32)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->pwk_retries = uap_cpu_to_le32(tlv->pwk_retries);
+		}
+		if (strcmp(args[0], "GroupwiseUpdateTimeout") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_eapol_gwk_hsk_timeout *tlv = NULL;
+
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_eapol_gwk_hsk_timeout);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append groupwise update timeout TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_eapol_gwk_hsk_timeout *)(buffer +
+							       cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_EAPOL_GWK_HSK_TIMEOUT_TLV_ID;
+			tlv->length = 4;
+			tlv->groupwise_update_timeout = (t_u32)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->groupwise_update_timeout =
+				uap_cpu_to_le32(tlv->groupwise_update_timeout);
+		}
+		if (strcmp(args[0], "GroupwiseHandshakeRetries") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_eapol_gwk_hsk_retries *tlv = NULL;
+
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_eapol_gwk_hsk_retries);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append groupwise handshake retries TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_eapol_gwk_hsk_retries *)(buffer +
+							       cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_EAPOL_GWK_HSK_RETRIES_TLV_ID;
+			tlv->length = 4;
+			tlv->gwk_retries = (t_u32)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+			tlv->gwk_retries = uap_cpu_to_le32(tlv->gwk_retries);
+		}
+
+		if (strcmp(args[0], "Enable11n") == 0) {
+			if ((ISDIGIT(args[1]) != UAP_SUCCESS) ||
+			    (atoi(args[1]) < 0) || (atoi(args[1]) > 1)) {
+				printf("ERR: Invalid Enable11n value\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_htcap_t *tlv = NULL;
+			enable_11n = atoi(args[1]);
+
+			memset(&htcap, 0, sizeof(htcap));
+			if (UAP_SUCCESS != get_sys_cfg_11n(&htcap)) {
+				printf("ERR: Reading current 11n configuration.\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_htcap_t);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append HT Cap TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_htcap_t *)(buffer + cmd_len);
+			tlv_offset_11n = cmd_len;
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = HT_CAPABILITY_TLV_ID;
+			tlv->length = sizeof(HTCap_t);
+			memcpy(&tlv->ht_cap, &htcap, sizeof(HTCap_t));
+			if (enable_11n == 1) {
+				/* enable mcs rate */
+				tlv->ht_cap.supported_mcs_set[0] =
+					DEFAULT_MCS_SET_0;
+				tlv->ht_cap.supported_mcs_set[4] =
+					DEFAULT_MCS_SET_4;
+				if (0 == get_fw_info(&fw)) {
+					if ((fw.hw_dev_mcs_support & 0x0f) >= 2)
+						tlv->ht_cap.
+							supported_mcs_set[1] =
+							DEFAULT_MCS_SET_1;
+				}
+			} else {
+				/* disable mcs rate */
+				tlv->ht_cap.supported_mcs_set[0] = 0;
+				tlv->ht_cap.supported_mcs_set[4] = 0;
+				tlv->ht_cap.supported_mcs_set[1] = 0;
+			}
+			endian_convert_tlv_header_out(tlv);
+		}
+		if (strcmp(args[0], "HTCapInfo") == 0) {
+			if (enable_11n <= 0) {
+				printf("ERR: Enable11n parameter should be set before HTCapInfo.\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) ||
+			    ((((t_u16)A2HEXDECIMAL(args[1])) &
+			      (~HT_CAP_CONFIG_MASK)) != HT_CAP_CHECK_MASK)) {
+				printf("ERR: Invalid HTCapInfo value\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+
+			/* Find HT tlv pointer in buffer and set HTCapInfo */
+			tlvbuf_htcap_t *tlv = NULL;
+			tlv = (tlvbuf_htcap_t *)(buffer + tlv_offset_11n);
+			tlv->ht_cap.ht_cap_info =
+				DEFAULT_HT_CAP_VALUE & ~HT_CAP_CONFIG_MASK;
+			tlv->ht_cap.ht_cap_info |=
+				(t_u16)A2HEXDECIMAL(args[1]) &
+				HT_CAP_CONFIG_MASK;
+			tlv->ht_cap.ht_cap_info =
+				uap_cpu_to_le16(tlv->ht_cap.ht_cap_info);
+		}
+		if (strcmp(args[0], "AMPDU") == 0) {
+			if (enable_11n <= 0) {
+				printf("ERR: Enable11n parameter should be set before AMPDU.\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) ||
+			    ((A2HEXDECIMAL(args[1])) > AMPDU_CONFIG_MASK)) {
+				printf("ERR: Invalid AMPDU value\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+
+			/* Find HT tlv pointer in buffer and set AMPDU */
+			tlvbuf_htcap_t *tlv = NULL;
+			tlv = (tlvbuf_htcap_t *)(buffer + tlv_offset_11n);
+			tlv->ht_cap.ampdu_param =
+				(t_u8)A2HEXDECIMAL(args[1]) & AMPDU_CONFIG_MASK;
+		}
+		if (strcmp(args[0], "HT_MCS_MAP") == 0) {
+			if (enable_11n <= 0) {
+				printf("ERR: Enable11n parameter should be set before HT_MCS_MAP.\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			if (0 == get_fw_info(&fw)) {
+				/* Check upper nibble of MCS support value
+				 * and block MCS_SET_1 when 2X2 is not supported
+				 * by the underlying hardware */
+				if (((fw.hw_dev_mcs_support & 0xf0) <
+				     STREAM_2X2_MASK) &&
+				    (A2HEXDECIMAL(args[1]) & MCS_SET_1_MASK)) {
+					printf("ERR: Invalid HT_MCS_MAP\n");
+					goto done;
+				}
+			}
+
+			/* Find HT tlv pointer in buffer and set supported MCS set */
+			tlvbuf_htcap_t *tlv = NULL;
+			tlv = (tlvbuf_htcap_t *)(buffer + tlv_offset_11n);
+			supported_mcs_set = (t_u32)A2HEXDECIMAL(args[1]);
+			supported_mcs_set = uap_cpu_to_le32(supported_mcs_set);
+			memcpy(tlv->ht_cap.supported_mcs_set,
+			       &supported_mcs_set, sizeof(t_u32));
+		}
+		if (strcmp(args[0], "Enable2040Coex") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) ||
+			    (atoi(args[1]) > 1)) {
+				printf("ERR: Invalid Enable2040Coex value\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			tlvbuf_2040_coex *tlv = NULL;
+			/* Append a new TLV */
+			tlv_len = sizeof(tlvbuf_2040_coex);
+			tmp_buffer = realloc(buffer, cmd_len + tlv_len);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot append 2040 coex TLV!\n");
+				ret = UAP_FAILURE;
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			cmd_buf = (apcmdbuf_sys_configure *)buffer;
+			tlv = (tlvbuf_2040_coex *)(buffer + cmd_len);
+			cmd_len += tlv_len;
+			/* Set TLV fields */
+			tlv->tag = MRVL_2040_BSS_COEX_CONTROL_TLV_ID;
+			tlv->length = 1;
+			tlv->enable = (t_u8)atoi(args[1]);
+			endian_convert_tlv_header_out(tlv);
+		}
+#if DEBUG
+		if (cmd_len != 0) {
+			hexdump("Command Buffer", (void *)cmd_buf, cmd_len,
+				' ');
+		}
+#endif
+	}
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return ret;
+}
+
+/**
+ *  @brief Get band from current channel
+ *  @param         band
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+static int
+get_band(int *band)
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_channel_config *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len;
+	int ret = UAP_SUCCESS;
+
+	/* Initialize the command length */
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_channel_config);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(cmd_len);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		ret = UAP_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, cmd_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_channel_config *)(buffer +
+					sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_CHANNELCONFIG_TLV_ID;
+	tlv->length = sizeof(tlvbuf_channel_config) - TLVHEADER_LEN;
+	cmd_buf->action = ACTION_GET;
+
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len);
+	endian_convert_tlv_header_in(tlv);
+
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_CHANNELCONFIG_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			ret = UAP_FAILURE;
+			goto done;
+		}
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (tlv->chan_number > MAX_CHANNELS_BG)
+				*band = BAND_A;
+			else
+				*band = BAND_B | BAND_G;
+		} else {
+			printf("ERR:Could not get band!\n");
+			ret = UAP_FAILURE;
+			goto done;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+		ret = UAP_FAILURE;
+		goto done;
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the cfg_80211d command
+ *
+ *  $return         N/A
+ */
+void
+print_apcmd_cfg_80211d_usage(void)
+{
+	printf("\nUsage: cfg_80211d <state 0/1> <country Country_code> \n");
+	return;
+}
+
+/**
+ *  @brief Show usage information for the uap_stats command
+ *
+ *  $return         N/A
+ */
+void
+print_apcmd_uap_stats(void)
+{
+	printf("Usage: uap_stats \n");
+	return;
+}
+
+/**
+ *  SNMP MIB OIDs Table
+ */
+static oids_table snmp_oids[] = {
+	{0x0b, 4, "dot11LocalTKIPMICFailures"},
+	{0x0c, 4, "dot11CCMPDecryptErrors"},
+	{0x0d, 4, "dot11WEPUndecryptableCount"},
+	{0x0e, 4, "dot11WEPICVErrorCount"},
+	{0x0f, 4, "dot11DecryptFailureCount"},
+	{0x12, 4, "dot11FailedCount"},
+	{0x13, 4, "dot11RetryCount"},
+	{0x14, 4, "dot11MultipleRetryCount"},
+	{0x15, 4, "dot11FrameDuplicateCount"},
+	{0x16, 4, "dot11RTSSuccessCount"},
+	{0x17, 4, "dot11RTSFailureCount"},
+	{0x18, 4, "dot11ACKFailureCount"},
+	{0x19, 4, "dot11ReceivedFragmentCount"},
+	{0x1a, 4, "dot11MulticastReceivedFrameCount"},
+	{0x1b, 4, "dot11FCSErrorCount"},
+	{0x1c, 4, "dot11TransmittedFrameCount"},
+	{0x1d, 4, "dot11RSNATKIPCounterMeasuresInvoked"},
+	{0x1e, 4, "dot11RSNA4WayHandshakeFailures"},
+	{0x1f, 4, "dot11MulticastTransmittedFrameCount"}
+};
+
+/**
+ *  @brief Get uAP stats
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_uap_stats(int argc, char *argv[])
+{
+	t_u8 no_of_oids = sizeof(snmp_oids) / sizeof(snmp_oids[0]);
+	t_u16 i, j;
+	int size;
+	apcmdbuf_snmp_mib *cmd_buf = NULL;
+	t_u8 *buf = NULL;
+	tlvbuf_header *tlv = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int opt;
+	t_u16 oid_size, byte2 = 0;
+	t_u32 byte4 = 0;
+	int ret = UAP_SUCCESS;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_apcmd_uap_stats();
+			return UAP_SUCCESS;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	if (argc) {
+		printf("Error: Invalid Input\n");
+		print_apcmd_uap_stats();
+		return UAP_FAILURE;
+	}
+
+    /**  Command Header */
+	cmd_len += sizeof(apcmdbuf_snmp_mib);
+
+	for (i = 0; i < no_of_oids; i++) {
+	/**
+         * Size of Oid + Oid_value + Oid_size
+         */
+		cmd_len += snmp_oids[i].len + sizeof(tlvbuf_header);
+	}
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+
+	/* Locate Headers */
+	cmd_buf = (apcmdbuf_snmp_mib *)buf;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->result = 0;
+	cmd_buf->seq_num = 0;
+	cmd_buf->cmd_code = HostCmd_SNMP_MIB;
+	cmd_buf->action = uap_cpu_to_le16(ACTION_GET);
+
+	tlv = (tlvbuf_header *)((t_u8 *)cmd_buf + sizeof(apcmdbuf_snmp_mib));
+	/* Add oid, oid_size and oid_value for each OID */
+	for (i = 0; i < no_of_oids; i++) {
+	/** Copy Index as Oid */
+		tlv->type = uap_cpu_to_le16(snmp_oids[i].type);
+	/** Copy its size */
+		tlv->len = uap_cpu_to_le16(snmp_oids[i].len);
+	/** Next TLV */
+		tlv = (tlvbuf_header *)&(tlv->data[snmp_oids[i].len]);
+	}
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf->result == CMD_SUCCESS) {
+			tlv = (tlvbuf_header *)((t_u8 *)cmd_buf +
+						sizeof(apcmdbuf_snmp_mib));
+
+			size = cmd_buf->size - (sizeof(apcmdbuf_snmp_mib) -
+						BUF_HEADER_SIZE);
+
+			while ((unsigned int)size >= sizeof(tlvbuf_header)) {
+				tlv->type = uap_le16_to_cpu(tlv->type);
+				for (i = 0; i < no_of_oids; i++) {
+					if (snmp_oids[i].type == tlv->type) {
+						printf("%s: ",
+						       snmp_oids[i].name);
+						break;
+					}
+				}
+				oid_size = uap_le16_to_cpu(tlv->len);
+				switch (oid_size) {
+				case 1:
+					printf("%d",
+					       (unsigned int)tlv->data[0]);
+					break;
+				case 2:
+					memcpy(&byte2, &tlv->data[0],
+					       sizeof(oid_size));
+					printf("%d",
+					       (unsigned int)
+					       uap_le16_to_cpu(byte2));
+					break;
+				case 4:
+					memcpy(&byte4, &tlv->data[0],
+					       sizeof(oid_size));
+					printf("%d",
+					       (unsigned int)
+					       uap_le32_to_cpu(byte4));
+					break;
+				default:
+					for (j = 0; j < oid_size; j++) {
+						printf("%d ",
+						       (t_u8)tlv->data[j]);
+					}
+					break;
+				}
+		/** Next TLV */
+				tlv = (tlvbuf_header *)&(tlv->data[oid_size]);
+				size -= (sizeof(tlvbuf_header) + oid_size);
+				size = (size > 0) ? size : 0;
+				printf("\n");
+			}
+
+		} else {
+			printf("ERR:Command Response incorrect!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	free(buf);
+	return ret;
+}
+
+/**
+ *  @brief parser for sys_cfg_80211d input
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @param output   Stores indexes for "state, country"
+ *                  arguments
+ *
+ *  @return         NA
+ *
+ */
+static void
+parse_input_80211d(int argc, char **argv, int output[2][2])
+{
+	int i, j, k = 0;
+	char *keywords[2] = { "state", "country" };
+
+	for (i = 0; i < 2; i++)
+		output[i][0] = -1;
+
+	for (i = 0; i < argc; i++) {
+		for (j = 0; j < 2; j++) {
+			if (strcmp(argv[i], keywords[j]) == 0) {
+				output[j][1] = output[j][0] = i;
+				k = j;
+				break;
+			}
+		}
+		output[k][1] += 1;
+	}
+}
+
+/**
+ *  @brief Set/Get 802.11D country information
+ *
+ *  Usage: cfg_80211d state country_code
+ *
+ *  State 0 or 1
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_cfg_80211d(int argc, char *argv[])
+{
+	apcmdbuf_cfg_80211d *cmd_buf = NULL;
+	ieeetypes_subband_set_t *subband = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int output[2][2];
+	int ret = UAP_SUCCESS;
+	int opt;
+	int status = 0;
+	int i, j;
+	t_u8 state = 0;
+	char country[4] = { ' ', ' ', 0, 0 };
+	t_u8 sflag = 0, cflag = 0;
+	ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS];
+	t_u8 no_of_sub_band = 0;
+	int band;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_apcmd_cfg_80211d_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc) {
+		if (strcmp(argv[0], "state") && strcmp(argv[0], "country")) {
+			printf("ERR: Incorrect input. Either state or country is needed.");
+			print_apcmd_cfg_80211d_usage();
+			return UAP_FAILURE;
+		}
+	/** SET */
+		parse_input_80211d(argc, argv, output);
+
+	/** State */
+		if ((output[0][0] != -1) && (output[0][1] > output[0][0])) {
+			if ((output[0][1] - output[0][0]) != 2) {
+				printf("ERR: Invalid state inputs\n");
+				print_apcmd_cfg_80211d_usage();
+				return UAP_FAILURE;
+			}
+
+			if (IS_HEX_OR_DIGIT(argv[output[0][0] + 1]) ==
+			    UAP_FAILURE) {
+				printf("ERR: valid input for state are 0 or 1\n");
+				print_apcmd_cfg_80211d_usage();
+				return UAP_FAILURE;
+			}
+			state = (t_u8)A2HEXDECIMAL(argv[output[0][0] + 1]);
+
+			if ((state != 0) && (state != 1)) {
+				printf("ERR: valid input for state are 0 or 1 \n");
+				print_apcmd_cfg_80211d_usage();
+				return UAP_FAILURE;
+			}
+			sflag = 1;
+		}
+
+	/** Country */
+		if ((output[1][0] != -1) && (output[1][1] > output[1][0])) {
+			if ((output[1][1] - output[1][0]) != 2) {
+				printf("ERR: Invalid country inputs\n");
+				print_apcmd_cfg_80211d_usage();
+				return UAP_FAILURE;
+			}
+			if ((strlen(argv[output[1][0] + 1]) > 3) ||
+			    (strlen(argv[output[1][0] + 1]) == 0)) {
+				print_apcmd_cfg_80211d_usage();
+				return UAP_FAILURE;
+			}
+			/* Only 2 characters of country code are copied here as indoor/outdoor
+			 * conditions are not handled in domain file */
+			strncpy(country, argv[output[1][0] + 1], 2);
+
+			for (i = 0; (unsigned int)i < strlen(country); i++) {
+				if ((country[i] < 'A') || (country[i] > 'z')) {
+					printf("Invalid Country Code\n");
+					print_apcmd_cfg_80211d_usage();
+					return UAP_FAILURE;
+				}
+				if (country[i] > 'Z')
+					country[i] = country[i] - 'a' + 'A';
+			}
+
+			cflag = 1;
+			if (!get_band(&band)) {
+				printf("ERR:couldn't get band from channel!\n");
+				return UAP_FAILURE;
+			}
+	   /** Get domain information from the file */
+			no_of_sub_band =
+				parse_domain_file(country, band, sub_bands,
+						  NULL);
+			if (no_of_sub_band == UAP_FAILURE) {
+				printf("Parsing Failed\n");
+				return UAP_FAILURE;
+			}
+		}
+		if (get_bss_status(&status) != UAP_SUCCESS) {
+			printf("ERR:Cannot get current bss status!\n");
+			return UAP_FAILURE;
+		}
+		if (status == UAP_BSS_START) {
+			printf("ERR: 11d status can not be changed after BSS start!\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	if (argc && !cflag && !sflag) {
+		printf("ERR: Invalid input\n");
+		print_apcmd_cfg_80211d_usage();
+		return UAP_FAILURE;
+	}
+
+	if (sflag && !cflag) {
+	/**
+         * Update MIB only and return
+         */
+		if (sg_snmp_mib
+		    (ACTION_SET, OID_80211D_ENABLE, sizeof(state),
+		     &state) == UAP_SUCCESS) {
+			printf("802.11d %sd \n", state ? "enable" : "disable");
+			return UAP_SUCCESS;
+		} else {
+			return UAP_FAILURE;
+		}
+	}
+
+	cmd_len = sizeof(apcmdbuf_cfg_80211d);
+
+	if (cflag) {
+		cmd_len += no_of_sub_band * sizeof(ieeetypes_subband_set_t);
+	} else {
+	     /** Get */
+		cmd_len += MAX_SUB_BANDS * sizeof(ieeetypes_subband_set_t);
+	}
+
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_cfg_80211d *)buf;
+	cmd_len = argc ? cmd_len :
+		 /** Set */
+		(sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t));
+								/** Get */
+
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->result = 0;
+	cmd_buf->seq_num = 0;
+	cmd_buf->action = argc ? ACTION_SET : ACTION_GET;
+	cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
+	cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
+
+	if (cflag) {
+		/* third character of country code is copied here as indoor/outdoor
+		 * condition is not supported in domain file*/
+		strncpy(country, argv[output[1][0] + 1], sizeof(country) - 1);
+		for (i = 0; (unsigned int)i < strlen(country); i++) {
+			if ((country[i] < 'A') || (country[i] > 'z')) {
+				printf("Invalid Country Code\n");
+				print_apcmd_cfg_80211d_usage();
+				free(buf);
+				return UAP_FAILURE;
+			}
+			if (country[i] > 'Z')
+				country[i] = country[i] - 'a' + 'A';
+		}
+		cmd_buf->domain.tag = uap_cpu_to_le16(TLV_TYPE_DOMAIN);
+		cmd_buf->domain.length = uap_cpu_to_le16(sizeof(domain_param_t)
+							 - BUF_HEADER_SIZE
+							 +
+							 (no_of_sub_band *
+							  sizeof
+							  (ieeetypes_subband_set_t)));
+
+		memset(cmd_buf->domain.country_code, ' ',
+		       sizeof(cmd_buf->domain.country_code));
+		memcpy(cmd_buf->domain.country_code, country, strlen(country));
+		memcpy(cmd_buf->domain.subband, sub_bands,
+		       no_of_sub_band * sizeof(ieeetypes_subband_set_t));
+	}
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc) {
+				printf("Set executed successfully\n");
+				if (sflag) {
+					if (sg_snmp_mib
+					    (ACTION_SET, OID_80211D_ENABLE,
+					     sizeof(state),
+					     &state) == UAP_SUCCESS) {
+						printf("802.11d %sd \n",
+						       state ? "enable" :
+						       "disable");
+					}
+				}
+			} else {
+				j = uap_le16_to_cpu(cmd_buf->domain.length);
+				if (sg_snmp_mib
+				    (ACTION_GET, OID_80211D_ENABLE,
+				     sizeof(state), &state)
+				    == UAP_SUCCESS) {
+					printf("State = %sd\n",
+					       state ? "enable" : "disable");
+				}
+
+				if (cmd_buf->domain.country_code[0] ||
+				    cmd_buf->domain.country_code[1] ||
+				    cmd_buf->domain.country_code[2]) {
+					printf("Country string = %c%c%c",
+					       cmd_buf->domain.country_code[0],
+					       cmd_buf->domain.country_code[1],
+					       cmd_buf->domain.country_code[2]);
+					j -= sizeof(cmd_buf->domain.
+						    country_code);
+					subband =
+						(ieeetypes_subband_set_t *)
+						cmd_buf->domain.subband;
+					printf("\nSub-band info=");
+					printf("\t(1st, #chan, MAX-power) \n");
+					for (i = 0; i < (j / 3); i++) {
+						printf("\t\t(%d, \t%d, \t%d dbm)\n", subband->first_chan, subband->no_of_chan, subband->max_tx_pwr);
+						subband++;
+					}
+				}
+			}
+		} else {
+			printf("ERR:Command Response incorrect!\n");
+			if (argc)
+				printf("11d info is allowed to set only before bss start.\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_config request and sends to the driver
+ *
+ *  Usage: "Usage : sys_config [CONFIG_FILE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_config(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len;
+	t_u16 buf_len;
+	int ret = UAP_SUCCESS;
+	int opt;
+	char **argv_dummy = NULL;
+	ps_mgmt pm;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_config_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc > 1) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_config_usage();
+		return UAP_FAILURE;
+	}
+	if (argc == 1) {
+		/* Read profile and send command to firmware */
+		ret = apcmd_sys_config_profile(argc, argv);
+		return ret;
+	}
+
+    /** Query AP's setting */
+	buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+
+	/* Alloc buf for command */
+	buf = (t_u8 *)malloc(buf_len);
+
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+
+	/* Reset custom_ie_present flag */
+	custom_ie_present = 0;
+
+	/* Reset max_mgmt_ie_print flag */
+	max_mgmt_ie_print = 0;
+
+	/* Locate headers */
+	cmd_len = sizeof(apcmdbuf_sys_configure);
+	cmd_buf = (apcmdbuf_sys_configure *)buf;
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			free(buf);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("AP settings:\n");
+			print_tlv(buf + sizeof(apcmdbuf_sys_configure),
+				  cmd_buf->size -
+				  sizeof(apcmdbuf_sys_configure) +
+				  BUF_HEADER_SIZE);
+			if (apcmd_addbapara(1, argv_dummy) == UAP_FAILURE) {
+				printf("Couldn't get ADDBA parameters\n");
+				return UAP_FAILURE;
+			}
+			if (apcmd_aggrpriotbl(1, argv_dummy) == UAP_FAILURE) {
+				printf("Couldn't get AMSDU/AMPDU priority table\n");
+				return UAP_FAILURE;
+			}
+			if (apcmd_addbareject(1, argv_dummy) == UAP_FAILURE) {
+				printf("Couldn't get ADDBA reject table\n");
+				return UAP_FAILURE;
+			}
+			printf("\n802.11D setting:\n");
+			if (apcmd_cfg_80211d(1, argv_dummy) == UAP_FAILURE) {
+				return UAP_FAILURE;
+			}
+			if (!custom_ie_present) {
+				printf("\nCustom IE settings:\n");
+				if (apcmd_sys_cfg_custom_ie(1, argv_dummy) ==
+				    UAP_FAILURE) {
+					return UAP_FAILURE;
+				}
+			}
+		} else {
+			printf("ERR:Could not retrieve system configure\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	free(buf);
+	memset(&pm, 0, sizeof(ps_mgmt));
+	ret = send_power_mode_ioctl(&pm, 0);
+	return ret;
+}
+
+/** Update domain info with given country and band
+ *
+ * @param country_80211d   country to be set
+ * @param band      band of operation
+ * @return          UAP_SUCCESS/UAP_FAILURE
+ */
+static int
+update_domain_info(char *country_80211d, int band)
+{
+	apcmdbuf_cfg_80211d *cmd_buf = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS];
+	t_u8 no_of_sub_band = 0;
+	char country[4] = { ' ', ' ', 0, 0 };
+	int ret = UAP_SUCCESS;
+	t_u8 domain_code = 0;
+	rgn_dom_code_t *prgn_dom_code = NULL;
+
+	/* Get currently set country code from FW */
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_cfg_80211d *)buf;
+	cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t));
+
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->result = 0;
+	cmd_buf->seq_num = 0;
+	cmd_buf->action = ACTION_GET;
+	cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
+	cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
+
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	if ((ret == UAP_SUCCESS) && (cmd_buf->result == CMD_SUCCESS) &&
+	    (cmd_buf->domain.country_code[0] ||
+	     cmd_buf->domain.country_code[1] ||
+	     cmd_buf->domain.country_code[2])) {
+		country[0] = cmd_buf->domain.country_code[0];
+		country[1] = cmd_buf->domain.country_code[1];
+	} else {
+		/* country_80211d will only be used if country code is not already set */
+		country[0] = country_80211d[0];
+		country[1] = country_80211d[1];
+	}
+
+	if (band == BAND_A)
+		printf("Enabling 11d for 11h operation and setting country code to %s\n", country);
+	cmd_len = sizeof(apcmdbuf_cfg_80211d);
+    /** Get domain information from the file */
+	no_of_sub_band =
+		parse_domain_file(country, band, sub_bands, &domain_code);
+	if (no_of_sub_band == UAP_FAILURE) {
+		printf("Parsing Failed\n");
+		ret = UAP_FAILURE;
+		goto done;
+	}
+	/* Copy third character of country code here */
+	if (cmd_buf->domain.country_code[2]) {
+		country[2] = cmd_buf->domain.country_code[2];
+	} else {
+		country[2] = country_80211d[2];
+	}
+
+	/* Set domain for this country code */
+	memset(buf, 0, buf_len);
+	cmd_len += no_of_sub_band * sizeof(ieeetypes_subband_set_t);
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_cfg_80211d *)buf;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->result = 0;
+	cmd_buf->seq_num = 0;
+	cmd_buf->action = ACTION_SET;
+	cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
+	cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
+
+	cmd_buf->domain.tag = uap_cpu_to_le16(TLV_TYPE_DOMAIN);
+	cmd_buf->domain.length = uap_cpu_to_le16(sizeof(domain_param_t)
+						 - BUF_HEADER_SIZE
+						 +
+						 (no_of_sub_band *
+						  sizeof
+						  (ieeetypes_subband_set_t)));
+
+	memset(cmd_buf->domain.country_code, ' ',
+	       sizeof(cmd_buf->domain.country_code));
+	memcpy(cmd_buf->domain.country_code, country, strlen(country));
+	memcpy(cmd_buf->domain.subband, sub_bands,
+	       no_of_sub_band * sizeof(ieeetypes_subband_set_t));
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf->result != CMD_SUCCESS) {
+			printf("ERR:Command Response incorrect!\n");
+			printf("11d info is allowed to set only before bss start.\n");
+			ret = UAP_FAILURE;
+			goto done;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+
+	if ((band == BAND_A) && domain_code) {
+		/* Send 11D_CMD a second time, with reg_dom_code TLV appended.
+		 * Use hostcmd instead of re-route. */
+		cmd_len = cmd_buf->size + BUF_HEADER_SIZE;
+		prgn_dom_code = (rgn_dom_code_t *)((t_u8 *)cmd_buf + cmd_len);
+		cmd_len += sizeof(rgn_dom_code_t);
+		cmd_buf->size += sizeof(rgn_dom_code_t);
+#if DEBUG
+		uap_printf(MSG_DEBUG,
+			   "Adding Region Domain Code TLV.  Domain_code=%d\n",
+			   domain_code);
+#endif
+		prgn_dom_code->tag =
+			uap_cpu_to_le16(MRVL_REGION_DOMAIN_CODE_TLV_ID);
+		prgn_dom_code->length = uap_cpu_to_le16(sizeof(rgn_dom_code_t)
+							- BUF_HEADER_SIZE);
+		prgn_dom_code->domain_code = domain_code;
+
+		/* Send the command */
+		uap_ioctl_no_reroute = 1;
+		ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+		uap_ioctl_no_reroute = 0;
+
+		if (ret == UAP_SUCCESS) {
+			if (cmd_buf->result != CMD_SUCCESS) {
+				printf("ERR:Command Response incorrect!\n");
+				printf("11d info is allowed to set only before bss start.\n");
+				ret = UAP_FAILURE;
+				goto done;
+			}
+		} else {
+			printf("ERR:Command sending failed!\n");
+		}
+	}
+
+done:
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Covert MCS Rate Bitmap to MCS Rate index
+ *
+ *  @param rate_bitmap  Pointer to rate bitmap
+ *  @param size         Size of the bitmap array
+ *
+ *  @return             Rate index
+ */
+int
+get_rate_index_from_bitmap(t_u16 *rate_bitmap, int size)
+{
+	int i;
+
+	for (i = 0; i < size * 8; i++) {
+		if (rate_bitmap[i / 16] & (1 << (i % 16))) {
+			return i;
+		}
+	}
+	return 0;
+}
+
+/**
+ *  @brief Checks current system configuration
+ *
+ *  @param buf     pointer to TLV buffer
+ *  @param len     TLV buffer length
+ *  @return        UAP_SUCCESS/UAP_FAILURE
+ */
+int
+check_sys_config(t_u8 *buf, t_u16 len)
+{
+	tlvbuf_header *pcurrent_tlv = (tlvbuf_header *)buf;
+	int tlv_buf_left = len;
+	t_u16 tlv_type;
+	t_u16 tlv_len;
+	tlvbuf_channel_config *channel_tlv = NULL;
+	tlvbuf_channel_list *chnlist_tlv = NULL;
+	tlvbuf_pwk_cipher *pwk_cipher_tlv = NULL;
+	tlvbuf_gwk_cipher *gwk_cipher_tlv = NULL;
+	tlvbuf_auth_mode *auth_tlv = NULL;
+	tlvbuf_protocol *protocol_tlv = NULL;
+	tlvbuf_wep_key *wep_key_tlv = NULL;
+	tlvbuf_wpa_passphrase *passphrase_tlv = NULL;
+	tlvbuf_rates *rates_tlv = NULL;
+	tlvbuf_mcbc_data_rate *mcbc_data_rate_tlv = NULL;
+	t_u16 protocol = 0;
+	t_u16 mcbc_data_rate = 0;
+	t_u16 op_rates_len = 0;
+	t_u8 acs_mode_enabled = 0;
+	t_u8 *cbuf = NULL;
+	apcmdbuf_cfg_80211d *cmd_buf = NULL;
+	t_u16 buf_len, cmd_len;
+	char country_80211d[4] = { 'U', 'S', ' ', 0 };
+	t_u8 state_80211h = 0;
+	int channel_tlv_band = BAND_B | BAND_G;
+	t_u8 secondary_ch_set = 0;
+	int scan_channels_band = BAND_B | BAND_G;
+	t_u8 state_80211d = 0;
+	t_u8 rate = 0;
+	t_u32 rate_bitmap = 0;
+	tlvbuf_htcap_t *ht_cap_tlv = NULL;
+	t_u16 enable_40Mhz = 0;
+	t_u16 enable_20Mhz_sgi = 0;
+	t_u16 enable_gf = 0;
+	t_u8 enable_11n = 0;
+	int flag = 0;
+	fw_info fw;
+	channel_list *pchan_list;
+	tlvbuf_tx_power *txpower_tlv = NULL;
+	int i = 0, ret = UAP_SUCCESS;
+	int pairwise_cipher_wpa = -1;
+	int pairwise_cipher_wpa2 = -1;
+	int group_cipher = -1;
+	int chan_list_len = 0;
+	int key_set = 0;
+	t_u8 channel = 0;
+	tx_rate_cfg_t tx_rate_config;
+	t_u32 mcs_rate_index = 0;
+	struct eth_priv_vhtcfg vhtcfg = { 0 };
+
+#define BITMAP_RATE_1M         0x01
+#define BITMAP_RATE_2M         0x02
+#define BITMAP_RATE_5_5M       0x04
+#define BITMAP_RATE_11M        0x8
+#define B_RATE_MANDATORY       0x0f
+
+	if (pcurrent_tlv == NULL) {
+		printf("ERR: No TLV buffer available!\n");
+		return UAP_FAILURE;
+	}
+
+	ret = sg_snmp_mib(ACTION_GET, OID_80211D_ENABLE, sizeof(state_80211d),
+			  &state_80211d);
+
+	buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	cbuf = (t_u8 *)malloc(buf_len);
+	if (!cbuf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(cbuf, 0, buf_len);
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_cfg_80211d *)cbuf;
+	cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t));
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->action = uap_cpu_to_le16(ACTION_GET);
+	cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	if (ret == UAP_SUCCESS && cmd_buf->result == CMD_SUCCESS) {
+		if (cmd_buf->domain.country_code[0] ||
+		    cmd_buf->domain.country_code[1] ||
+		    cmd_buf->domain.country_code[2]) {
+			strncpy(country_80211d,
+				(char *)cmd_buf->domain.country_code,
+				COUNTRY_CODE_LEN);
+		}
+	}
+	free(cbuf);
+
+	/* get region code to handle special cases */
+	memset(&fw, 0, sizeof(fw));
+	if (get_fw_info(&fw)) {
+		printf("Could not get fw info!\n");
+		return UAP_FAILURE;
+	}
+
+	if (get_tx_rate_cfg(&tx_rate_config) == UAP_FAILURE) {
+		printf("Could not get tx_rate_cfg!\n");
+		return UAP_FAILURE;
+	}
+	while (tlv_buf_left >= (int)sizeof(tlvbuf_header) &&
+	       (ret != UAP_FAILURE)) {
+		tlv_type = *(t_u8 *)&pcurrent_tlv->type;
+		tlv_type |= (*((t_u8 *)&pcurrent_tlv->type + 1) << 8);
+		tlv_len = *(t_u8 *)&pcurrent_tlv->len;
+		tlv_len |= (*((t_u8 *)&pcurrent_tlv->len + 1) << 8);
+		if ((sizeof(tlvbuf_header) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			printf("wrong tlv: tlv_len=%d, tlv_buf_left=%d\n",
+			       tlv_len, tlv_buf_left);
+			break;
+		}
+		switch (tlv_type) {
+		case MRVL_CHANNELCONFIG_TLV_ID:
+			channel_tlv = (tlvbuf_channel_config *)pcurrent_tlv;
+			channel = channel_tlv->chan_number;
+
+			if ((!state_80211d) &&
+			    (channel_tlv->chan_number == MAX_CHANNELS_BG)
+			    &&
+			    (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1)
+			     == 0)
+				) {
+				printf("ERR: Invalid channel 14, 802.11d disabled, country code JP!\n");
+				return UAP_FAILURE;
+			}
+
+			if (channel_tlv->bandcfg.chanBand == BAND_5GHZ)
+				channel_tlv_band = BAND_A;
+			secondary_ch_set = channel_tlv->bandcfg.chan2Offset;
+			if (channel_tlv_band != BAND_A) {
+				/* When country code is not Japan, allow channels 5-11 for US and 5-13 for non-US
+				 * only for secondary channel below */
+				if (secondary_ch_set == SEC_CHAN_BELOW) {
+					if (!strncmp
+					    (country_80211d, "US",
+					     COUNTRY_CODE_LEN - 1)) {
+						if (channel_tlv->chan_number >
+						    DEFAULT_MAX_CHANNEL_BELOW) {
+							printf("ERR: Only channels 5-11 are allowed with secondary channel below for the US\n");
+							return UAP_FAILURE;
+						}
+					} else if (strncmp
+						   (country_80211d, "JP",
+						    COUNTRY_CODE_LEN - 1)) {
+						if (channel_tlv->chan_number >
+						    DEFAULT_MAX_CHANNEL_BELOW_NON_US)
+						{
+							printf("ERR: Only channels 5-13 are allowed with secondary channel below for" "non-Japan countries!\n");
+							return UAP_FAILURE;
+						}
+					}
+				}
+
+				/* When country code is not Japan, allow channels 1-7 for US and 1-9 for non-US
+				 * only for secondary channel above */
+				if (secondary_ch_set == SEC_CHAN_ABOVE) {
+					if (!strncmp
+					    (country_80211d, "US",
+					     COUNTRY_CODE_LEN - 1)) {
+						if (channel_tlv->chan_number >
+						    DEFAULT_MAX_CHANNEL_ABOVE) {
+							printf("ERR: Only channels 1-7 are allowed with secondary channel above for the US\n");
+							return UAP_FAILURE;
+						}
+					} else if (strncmp
+						   (country_80211d, "JP",
+						    COUNTRY_CODE_LEN - 1)) {
+						if (channel_tlv->chan_number >
+						    DEFAULT_MAX_CHANNEL_ABOVE_NON_US)
+						{
+							printf("ERR: Only channels 1-9 are allowed with secondary channel above for" "non-Japan countries!\n");
+							return UAP_FAILURE;
+						}
+					}
+				}
+			}
+			if (!(channel_tlv->bandcfg.scanMode == SCAN_MODE_ACS)) {
+				if (check_channel_validity_11d
+				    (channel_tlv->chan_number, channel_tlv_band,
+				     1) == UAP_FAILURE)
+					return UAP_FAILURE;
+				if (state_80211d) {
+					/* Set country code to JP if channel is 8 or 12 and band is 5GHZ */
+					if ((channel_tlv->chan_number <
+					     MAX_CHANNELS_BG) &&
+					    (channel_tlv_band == BAND_A))
+						strncpy(country_80211d, "JP ",
+							sizeof(country_80211d) -
+							1);
+				} else {
+					if ((channel_tlv_band == BAND_A) &&
+					    ((channel_tlv->chan_number == 8) ||
+					     (channel_tlv->chan_number ==
+					      12))) {
+						printf("ERR:Invalid band for given channel\n");
+						return UAP_FAILURE;
+					}
+				}
+			} else {
+				acs_mode_enabled = 1;
+			}
+#define JP_REGION_0xFE 0xFE
+			if (fw.region_code == JP_REGION_0xFE &&
+			    ((channel_tlv->chan_number == 12) ||
+			     (channel_tlv->chan_number == 13))) {
+				printf("ERR:Channel 12 or 13 is not allowed for region code 0xFE\n");
+				return UAP_FAILURE;
+			}
+			break;
+		case MRVL_CHANNELLIST_TLV_ID:
+			chnlist_tlv = (tlvbuf_channel_list *)pcurrent_tlv;
+			pchan_list =
+				(channel_list *) & (chnlist_tlv->chan_list);
+			if (tlv_len % sizeof(channel_list)) {
+				printf("ERR:Invalid Scan channel list TLV!\n");
+				return UAP_FAILURE;
+			}
+			chan_list_len = tlv_len / sizeof(channel_list);
+
+			for (i = 0; i < chan_list_len; i++) {
+				scan_channels_band = BAND_B | BAND_G;
+				if ((scan_channels_band != BAND_A) &&
+				    (pchan_list->bandcfg.chanBand ==
+				     BAND_5GHZ)) {
+					scan_channels_band = BAND_A;
+				}
+				if (check_channel_validity_11d
+				    (pchan_list->chan_number,
+				     scan_channels_band, 0) == UAP_FAILURE)
+					return UAP_FAILURE;
+				pchan_list++;
+			}
+			break;
+		case MRVL_TX_POWER_TLV_ID:
+			txpower_tlv = (tlvbuf_tx_power *)pcurrent_tlv;
+			if (state_80211d) {
+				if (check_tx_pwr_validity_11d
+				    (txpower_tlv->tx_power_dbm) == UAP_FAILURE)
+					return UAP_FAILURE;
+			}
+			break;
+		case MRVL_CIPHER_PWK_TLV_ID:
+			pwk_cipher_tlv = (tlvbuf_pwk_cipher *)pcurrent_tlv;
+			pwk_cipher_tlv->protocol =
+				uap_le16_to_cpu(pwk_cipher_tlv->protocol);
+			if (pwk_cipher_tlv->protocol == PROTOCOL_WPA)
+				pairwise_cipher_wpa =
+					pwk_cipher_tlv->pairwise_cipher;
+			else if (pwk_cipher_tlv->protocol == PROTOCOL_WPA2)
+				pairwise_cipher_wpa2 =
+					pwk_cipher_tlv->pairwise_cipher;
+			break;
+		case MRVL_CIPHER_GWK_TLV_ID:
+			gwk_cipher_tlv = (tlvbuf_gwk_cipher *)pcurrent_tlv;
+			group_cipher = gwk_cipher_tlv->group_cipher;
+			break;
+		case MRVL_AUTH_TLV_ID:
+			auth_tlv = (tlvbuf_auth_mode *)pcurrent_tlv;
+			break;
+		case MRVL_PROTOCOL_TLV_ID:
+			protocol_tlv = (tlvbuf_protocol *)pcurrent_tlv;
+			protocol = uap_le16_to_cpu(protocol_tlv->protocol);
+			break;
+		case MRVL_WPA_PASSPHRASE_TLV_ID:
+			passphrase_tlv = (tlvbuf_wpa_passphrase *)pcurrent_tlv;
+			break;
+		case MRVL_WEP_KEY_TLV_ID:
+			wep_key_tlv = (tlvbuf_wep_key *)pcurrent_tlv;
+			if (wep_key_tlv->is_default) {
+				key_set = 1;
+			}
+			break;
+		case HT_CAPABILITY_TLV_ID:
+			ht_cap_tlv = (tlvbuf_htcap_t *)pcurrent_tlv;
+			ht_cap_tlv->ht_cap.ht_cap_info =
+				uap_le16_to_cpu(ht_cap_tlv->ht_cap.ht_cap_info);
+			if (ht_cap_tlv->ht_cap.supported_mcs_set[0]) {
+				enable_11n = 1;
+				enable_40Mhz =
+					IS_11N_40MHZ_ENABLED(ht_cap_tlv->ht_cap.
+							     ht_cap_info);
+				enable_20Mhz_sgi =
+					IS_11N_20MHZ_SHORTGI_ENABLED
+					(ht_cap_tlv->ht_cap.ht_cap_info);
+				enable_gf =
+					IS_11N_GF_ENABLED(ht_cap_tlv->ht_cap.
+							  ht_cap_info);
+			}
+			break;
+		case MRVL_RATES_TLV_ID:
+			rates_tlv = (tlvbuf_rates *)pcurrent_tlv;
+			op_rates_len = tlv_len;
+			break;
+		case MRVL_MCBC_DATA_RATE_TLV_ID:
+			mcbc_data_rate_tlv =
+				(tlvbuf_mcbc_data_rate *)pcurrent_tlv;
+			mcbc_data_rate =
+				uap_le16_to_cpu(mcbc_data_rate_tlv->
+						mcbc_datarate);
+			if (mcbc_data_rate &&
+			    (is_mcbc_rate_valid((t_u8)mcbc_data_rate) !=
+			     UAP_SUCCESS)) {
+				printf("ERR: Invalid MCBC Data Rate \n");
+				return UAP_FAILURE;
+			}
+			break;
+		}
+		tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
+		pcurrent_tlv = (tlvbuf_header *)(pcurrent_tlv->data + tlv_len);
+	}
+
+	if ((protocol == PROTOCOL_STATIC_WEP) && !key_set) {
+		printf("ERR:WEP keys not set!\n");
+		return UAP_FAILURE;
+	}
+	if (auth_tlv == NULL) {
+		printf("ERR: No authentication found\n");
+		return UAP_FAILURE;
+	}
+	if ((auth_tlv->auth_mode == 1) && (protocol != PROTOCOL_STATIC_WEP)) {
+		printf("ERR:Shared key authentication is not allowed for Open/WPA/WPA2/Mixed mode\n");
+		return UAP_FAILURE;
+	}
+
+	if (passphrase_tlv == NULL) {
+		printf("ERR: No passphrase found\n");
+		return UAP_FAILURE;
+	}
+	if (((protocol == PROTOCOL_WPA) || (protocol == PROTOCOL_WPA2)
+	     || (protocol == PROTOCOL_WPA2_MIXED)) && !(passphrase_tlv->length)) {
+		printf("ERR:Passphrase must be set for WPA/WPA2/Mixed mode\n");
+		return UAP_FAILURE;
+	}
+	if ((protocol == PROTOCOL_WPA) || (protocol == PROTOCOL_WPA2_MIXED)) {
+		if (is_cipher_valid(pairwise_cipher_wpa, group_cipher) !=
+		    UAP_SUCCESS) {
+			printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
+			return UAP_FAILURE;
+		}
+	}
+	if ((protocol == PROTOCOL_WPA2) || (protocol == PROTOCOL_WPA2_MIXED)) {
+		if (is_cipher_valid(pairwise_cipher_wpa2, group_cipher) !=
+		    UAP_SUCCESS) {
+			printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	if (chnlist_tlv == NULL) {
+		printf("ERR: No channel list found\n");
+		return UAP_FAILURE;
+	}
+	if (acs_mode_enabled) {
+		pchan_list = (channel_list *) & (chnlist_tlv->chan_list);
+		for (i = 0; i < chan_list_len; i++) {
+			if ((!state_80211d) &&
+			    (pchan_list->chan_number == MAX_CHANNELS_BG)
+			    &&
+			    (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1)
+			     == 0)
+				) {
+				printf("ERR: Invalid scan channel 14, 802.11d disabled, country code JP!\n");
+				return UAP_FAILURE;
+			}
+
+			if (fw.region_code == JP_REGION_0xFE &&
+			    ((pchan_list->chan_number == 12) ||
+			     (pchan_list->chan_number == 13))) {
+				printf("ERR:Scan Channel 12 or 13 is not allowed for region code 0xFE\n");
+				return UAP_FAILURE;
+			}
+			pchan_list++;
+		}
+
+		if (!state_80211d) {
+			/* Block scan channels 8 and 12 in 5GHz band if 11d is not enabled and country code not set to JP */
+			pchan_list =
+				(channel_list *) & (chnlist_tlv->chan_list);
+			for (i = 0; i < chan_list_len; i++) {
+				if ((pchan_list->bandcfg.chanBand == BAND_5GHZ)
+				    && ((pchan_list->chan_number == 8) ||
+					(pchan_list->chan_number == 12))) {
+					printf("ERR: Invalid band for scan channel %d\n", pchan_list->chan_number);
+					return UAP_FAILURE;
+				}
+				pchan_list++;
+			}
+		}
+		if (state_80211d) {
+			/* Set default country code to US */
+			strncpy(country_80211d, "US ",
+				sizeof(country_80211d) - 1);
+			pchan_list =
+				(channel_list *) & (chnlist_tlv->chan_list);
+			for (i = 0; i < chan_list_len; i++) {
+				/* Set country code to JP if channel is 8 or 12 and band is 5GHZ */
+				if ((pchan_list->chan_number < MAX_CHANNELS_BG)
+				    && (scan_channels_band == BAND_A)) {
+					strncpy(country_80211d, "JP ",
+						sizeof(country_80211d) - 1);
+				}
+				if (check_channel_validity_11d
+				    (pchan_list->chan_number,
+				     scan_channels_band, 0) == UAP_FAILURE)
+					return UAP_FAILURE;
+				pchan_list++;
+			}
+			if (update_domain_info
+			    (country_80211d,
+			     scan_channels_band) == UAP_FAILURE) {
+				return UAP_FAILURE;
+			}
+		}
+	}
+#ifdef WIFI_DIRECT_SUPPORT
+	if (strncmp(dev_name, "wfd", 3))
+#endif
+		if ((!acs_mode_enabled &&
+		     (channel_tlv_band == (BAND_B | BAND_G)))
+		    || (acs_mode_enabled &&
+			(scan_channels_band == (BAND_B | BAND_G)))) {
+			if (rates_tlv == NULL) {
+				printf("ERR: No rates found\n");
+				return UAP_FAILURE;
+			}
+			for (i = 0; i < op_rates_len; i++) {
+				rate = rates_tlv->
+					operational_rates[i] &
+					~BASIC_RATE_SET_BIT;
+				switch (rate) {
+				case 2:
+					rate_bitmap |= BITMAP_RATE_1M;
+					break;
+				case 4:
+					rate_bitmap |= BITMAP_RATE_2M;
+					break;
+				case 11:
+					rate_bitmap |= BITMAP_RATE_5_5M;
+					break;
+				case 22:
+					rate_bitmap |= BITMAP_RATE_11M;
+					break;
+				}
+			}
+			if ((rate_bitmap & B_RATE_MANDATORY) !=
+			    B_RATE_MANDATORY) {
+				if (acs_mode_enabled)
+					printf("ERR: Rates/Scan channels do not match!\n");
+				else
+					printf("ERR: Rates/Channel do not match!\n");
+				return UAP_FAILURE;
+			}
+		}
+	if ((!acs_mode_enabled && (channel_tlv_band == BAND_A))
+	    || (acs_mode_enabled && (scan_channels_band == BAND_A))) {
+		if (rates_tlv == NULL) {
+			printf("ERR: No rates found\n");
+			return UAP_FAILURE;
+		}
+		for (i = 0; i < op_rates_len; i++) {
+			rate = rates_tlv->
+				operational_rates[i] & ~BASIC_RATE_SET_BIT;
+			switch (rate) {
+			case 2:
+			case 4:
+			case 11:
+			case 22:
+				if (acs_mode_enabled)
+					printf("ERR: Rates/Scan channels do not match!\n");
+				else
+					printf("ERR: Rates/Channel do not match!\n");
+				return UAP_FAILURE;
+			}
+		}
+		state_80211h = 1;
+		if (sg_snmp_mib
+		    (ACTION_SET, OID_80211H_ENABLE, sizeof(state_80211h),
+		     &state_80211h)
+		    == UAP_FAILURE) {
+			return UAP_FAILURE;
+		}
+		if (update_domain_info(country_80211d, BAND_A) == UAP_FAILURE) {
+			return UAP_FAILURE;
+		}
+	}
+#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17))
+#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24))
+
+	if (enable_40Mhz) {
+		if (!ISSUPP_CHANWIDTH40(fw.hw_dot_11n_dev_cap)) {
+			printf("ERR: It's not support HT40 from Hardware Cap\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	if (enable_11n) {
+		/*For protocol = Mixed, 11n enabled, only allow TKIP cipher for WPA protocol, not for WPA2 */
+		if ((protocol == PROTOCOL_WPA2_MIXED) &&
+		    (pairwise_cipher_wpa2 == CIPHER_TKIP)) {
+			printf("ERR: WPA2 pairwise cipher cannot be TKIP when AP operates in 802.11n Mixed mode.\n");
+			return UAP_FAILURE;
+		} else if (protocol == PROTOCOL_STATIC_WEP) {
+			printf("ERR: WEP cannot be used when AP operates in 802.11n mode.\n");
+			return UAP_FAILURE;
+		}
+	}
+	if ((tx_rate_config.rate == UAP_RATE_INDEX_MCS32) && !enable_40Mhz) {
+		printf("ERR:uAP must be configured to operate in 40MHz if tx_rate is MCS32\n");
+		return UAP_FAILURE;
+	}
+	if (enable_20Mhz_sgi && enable_gf) {
+		if ((tx_rate_config.rate >= UAP_RATE_INDEX_MCS0) &&
+		    (tx_rate_config.rate <= UAP_RATE_INDEX_MCS7)) {
+			printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n");
+			return UAP_FAILURE;
+		}
+	}
+	mcs_rate_index =
+		get_rate_index_from_bitmap(tx_rate_config.bitmap_rates,
+					   sizeof(tx_rate_config.bitmap_rates));
+	if ((mcs_rate_index >= UAP_RATE_BITMAP_MCS0) &&
+	    (mcs_rate_index <= UAP_RATE_BITMAP_MCS127)) {
+		mcs_rate_index -= (UAP_RATE_BITMAP_MCS0 - UAP_RATE_INDEX_MCS0);
+		if ((mcs_rate_index == UAP_RATE_INDEX_MCS32) & !enable_40Mhz) {
+			printf("ERR:uAP must be configured to operate in 40MHz if rate_bitmap contains MCS32\n");
+			return UAP_FAILURE;
+		}
+		if (enable_20Mhz_sgi && enable_gf) {
+			if ((mcs_rate_index >= UAP_RATE_INDEX_MCS0) &&
+			    (mcs_rate_index <= UAP_RATE_INDEX_MCS7)) {
+				printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n");
+				return UAP_FAILURE;
+			}
+		}
+	}
+
+	/* if 11d enabled, Channel 14, country code "JP", only B rates are allowed */
+	if ((channel == 14) && state_80211d &&
+	    (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) == 0)) {
+		if (rates_tlv == NULL) {
+			printf("ERR:No rates found\n");
+			return UAP_FAILURE;
+		}
+		if (enable_11n) {
+			printf("ERR:11n must be disabled and the only B rates are allowed if 11d enabled and country code is JP with channel 14.\n");
+			return UAP_FAILURE;
+		}
+		for (i = 0; i < op_rates_len; i++) {
+			rate = rates_tlv->
+				operational_rates[i] & ~BASIC_RATE_SET_BIT;
+			switch (rate) {
+			case 2:
+			case 4:
+			case 11:
+			case 22:
+				break;
+			default:
+				printf("ERR:If 11d enabled, channel 14 and country code is JP, the only B rates are allowed.\n");
+				return UAP_FAILURE;
+			}
+		}
+	}
+
+	/* Channels 14, 165 are not allowed to operate in 40MHz mode */
+	if (!acs_mode_enabled && enable_40Mhz) {
+		if ((channel == 14)
+		    || (channel == 165)
+			) {
+			printf("ERR:Invalid channel %d for 40MHz operation\n",
+			       channel);
+			return UAP_FAILURE;
+		} else if (!secondary_ch_set) {
+			printf("ERR:Secondary channel should be set when 40Mhz is enabled!\n");
+			return UAP_FAILURE;
+		}
+	}
+	/* Channels 14, 140, 165 are not allowed to operate in 40MHz mode */
+	if (acs_mode_enabled && enable_40Mhz) {
+		if (chnlist_tlv == NULL) {
+			printf("ERR: No channel list found\n");
+			return UAP_FAILURE;
+		}
+		pchan_list = (channel_list *) & (chnlist_tlv->chan_list);
+		for (i = 0; i < chan_list_len; i++) {
+			if ((pchan_list->chan_number != 14)
+			    && (pchan_list->chan_number != 140) &&
+			    (pchan_list->chan_number != 165)
+				) {
+				flag = 1;
+				break;
+			}
+			pchan_list++;
+		}
+		if (!flag) {
+			printf("ERR:Invalid channels in scan channel list for 40MHz operation\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	if (0 == get_fw_info(&fw)) {
+		/*check whether support 802.11AC through BAND_AAC bit */
+		if (fw.fw_bands & BAND_AAC) {
+			ret = get_802_11ac_cfg(&vhtcfg);
+			if (UAP_SUCCESS == ret) {
+				/* Note: When 11AC is disabled, FW sets vht_rx_mcs to 0xffff */
+				if ((vhtcfg.vht_rx_mcs != 0xffff) &&
+				    (!enable_11n)) {
+					printf("ERR: 11ac enable while 11n disable, it is forbidden! \n");
+					return UAP_FAILURE;
+				}
+			} else {
+				printf("Don't support 802.11AC \n");
+				return UAP_SUCCESS;
+			}
+		} else
+			printf("No support 802 11AC.\n");
+	} else {
+		printf("ERR: get_fw_info fail\n");
+		return UAP_FAILURE;
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief Checks current bss configuration
+ *
+ *  @param buf     pointer to bss_config_t
+ *  @return        UAP_SUCCESS/UAP_FAILURE
+ */
+int
+check_bss_config(t_u8 *buf)
+{
+	bss_config_t *bss_config = NULL;;
+	t_u8 acs_mode_enabled = 0;
+	t_u8 *cbuf = NULL;
+	apcmdbuf_cfg_80211d *cmd_buf = NULL;
+	t_u16 buf_len, cmd_len;
+	char country_80211d[4] = { 'U', 'S', ' ', 0 };
+	t_u8 state_80211h = 0;
+	int channel_tlv_band = BAND_B | BAND_G;
+	t_u8 secondary_ch_set = 0;
+	int scan_channels_band = BAND_B | BAND_G;
+	t_u8 state_80211d = 0;
+	t_u8 rate = 0;
+	t_u32 rate_bitmap = 0;
+	t_u16 enable_40Mhz = 0;
+	t_u16 enable_20Mhz_sgi = 0;
+	t_u16 enable_gf = 0;
+	t_u8 enable_11n = 0;
+	int flag = 0;
+	fw_info fw;
+	int i = 0, ret = UAP_SUCCESS;
+	tx_rate_cfg_t tx_rate_config;
+	t_u32 mcs_rate_index = 0;
+	struct eth_priv_vhtcfg vhtcfg = { 0 };
+
+#define BITMAP_RATE_1M         0x01
+#define BITMAP_RATE_2M         0x02
+#define BITMAP_RATE_5_5M       0x04
+#define BITMAP_RATE_11M        0x8
+#define B_RATE_MANDATORY       0x0f
+
+	if (NULL == buf) {
+		printf("ERR: No buffer for bss_configure!\n");
+		return UAP_FAILURE;
+	}
+
+	bss_config = (bss_config_t *)buf;
+
+	ret = sg_snmp_mib(ACTION_GET, OID_80211D_ENABLE, sizeof(state_80211d),
+			  &state_80211d);
+
+	buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	cbuf = (t_u8 *)malloc(buf_len);
+	if (!cbuf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(cbuf, 0, buf_len);
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_cfg_80211d *)cbuf;
+	cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t));
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->action = uap_cpu_to_le16(ACTION_GET);
+	cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	if (ret == UAP_SUCCESS && cmd_buf->result == CMD_SUCCESS) {
+		if (cmd_buf->domain.country_code[0] ||
+		    cmd_buf->domain.country_code[1] ||
+		    cmd_buf->domain.country_code[2]) {
+			strncpy(country_80211d,
+				(char *)cmd_buf->domain.country_code,
+				COUNTRY_CODE_LEN);
+		}
+	}
+	free(cbuf);
+
+	/* get region code to handle special cases */
+	memset(&fw, 0, sizeof(fw));
+	if (get_fw_info(&fw)) {
+		printf("Could not get fw info!\n");
+		return UAP_FAILURE;
+	}
+
+	if (get_tx_rate_cfg(&tx_rate_config) == UAP_FAILURE) {
+		printf("Could not get tx_rate_cfg!\n");
+		return UAP_FAILURE;
+	}
+
+	if ((fw.fw_bands & (BAND_B | BAND_G | BAND_GN | BAND_GAC))
+	    && !(fw.fw_bands & (BAND_A | BAND_AAC))
+		) {
+		if (bss_config->channel > MAX_CHANNELS_BG) {
+			printf("ERR: Invalid channel in 2.4GHz band!\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	if (!(fw.fw_bands & (BAND_B | BAND_G
+			     | BAND_GN
+			     | BAND_GAC)) && (fw.fw_bands & (BAND_A
+							     | BAND_AAC))) {
+		if (bss_config->channel < 36 ||
+		    bss_config->channel > MAX_CHANNELS) {
+			printf("ERR: Invalid channel in 5GHz band!\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	if ((!state_80211d) && (bss_config->channel == MAX_CHANNELS_BG)
+	    && (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) == 0)
+		) {
+		printf("ERR: Invalid channel 14, 802.11d disabled, country code JP!\n");
+		return UAP_FAILURE;
+	}
+
+	if (bss_config->bandcfg.chanBand == BAND_5GHZ)
+		channel_tlv_band = BAND_A;
+
+	secondary_ch_set = bss_config->bandcfg.chan2Offset;
+	if (channel_tlv_band != BAND_A) {
+		/* When country code is not Japan, allow channels 5-11 for US and 5-13 for non-US
+		 * only for secondary channel below */
+		if (secondary_ch_set == SEC_CHAN_BELOW) {
+			if (!strncmp
+			    (country_80211d, "US", COUNTRY_CODE_LEN - 1)) {
+				if (bss_config->channel >
+				    DEFAULT_MAX_CHANNEL_BELOW) {
+					printf("ERR: Only channels 5-11 are allowed with secondary channel below for the US\n");
+					return UAP_FAILURE;
+				}
+			} else if (strncmp
+				   (country_80211d, "JP",
+				    COUNTRY_CODE_LEN - 1)) {
+				if (bss_config->channel >
+				    DEFAULT_MAX_CHANNEL_BELOW_NON_US) {
+					printf("ERR: Only channels 5-13 are allowed with secondary channel below for" "non-Japan countries!\n");
+					return UAP_FAILURE;
+				}
+			}
+		}
+
+		/* When country code is not Japan, allow channels 1-7 for US and 1-9 for non-US
+		 * only for secondary channel above */
+		if (secondary_ch_set == SEC_CHAN_ABOVE) {
+			if (!strncmp
+			    (country_80211d, "US", COUNTRY_CODE_LEN - 1)) {
+				if (bss_config->channel >
+				    DEFAULT_MAX_CHANNEL_ABOVE) {
+					printf("ERR: Only channels 1-7 are allowed with secondary channel above for the US\n");
+					return UAP_FAILURE;
+				}
+			} else if (strncmp
+				   (country_80211d, "JP",
+				    COUNTRY_CODE_LEN - 1)) {
+				if (bss_config->channel >
+				    DEFAULT_MAX_CHANNEL_ABOVE_NON_US) {
+					printf("ERR: Only channels 1-9 are allowed with secondary channel above for" "non-Japan countries!\n");
+					return UAP_FAILURE;
+				}
+			}
+		}
+	}
+
+	if (!(bss_config->bandcfg.scanMode == SCAN_MODE_ACS)) {
+		if (check_channel_validity_11d
+		    (bss_config->channel, channel_tlv_band, 1) == UAP_FAILURE)
+			return UAP_FAILURE;
+		if (state_80211d) {
+			/* Set country code to JP if channel is 8 or 12 and band is 5GHZ */
+			if ((bss_config->channel < MAX_CHANNELS_BG) &&
+			    (channel_tlv_band == BAND_A))
+				strncpy(country_80211d, "JP ",
+					sizeof(country_80211d) - 1);
+		} else {
+			if ((channel_tlv_band == BAND_A) &&
+			    ((bss_config->channel == 8) ||
+			     (bss_config->channel == 12))) {
+				printf("ERR:Invalid band for given channel\n");
+				return UAP_FAILURE;
+			}
+		}
+	} else {
+		acs_mode_enabled = 1;
+	}
+
+#define JP_REGION_0xFE 0xFE
+	if (fw.region_code == JP_REGION_0xFE &&
+	    ((bss_config->channel == 12) || (bss_config->channel == 13))) {
+		printf("ERR:Channel 12 or 13 is not allowed for region code 0xFE\n");
+		return UAP_FAILURE;
+	}
+
+	for (i = 0; i < bss_config->num_of_chan; i++) {
+		scan_channels_band = BAND_B | BAND_G;
+		if ((scan_channels_band != BAND_A) &&
+		    (bss_config->chan_list[i].bandcfg.chanBand == BAND_5GHZ)) {
+			scan_channels_band = BAND_A;
+		}
+		if (check_channel_validity_11d
+		    (bss_config->chan_list[i].chan_number, scan_channels_band,
+		     0) == UAP_FAILURE)
+			return UAP_FAILURE;
+	}
+
+	if (state_80211d) {
+		if (check_tx_pwr_validity_11d(bss_config->tx_power_level) ==
+		    UAP_FAILURE)
+			return UAP_FAILURE;
+	}
+
+	if (bss_config->supported_mcs_set[0]) {
+		enable_11n = 1;
+		enable_40Mhz = IS_11N_40MHZ_ENABLED(bss_config->ht_cap_info);
+		enable_20Mhz_sgi =
+			IS_11N_20MHZ_SHORTGI_ENABLED(bss_config->ht_cap_info);
+		enable_gf = IS_11N_GF_ENABLED(bss_config->ht_cap_info);
+	}
+
+	if (bss_config->mcbc_data_rate &&
+	    (is_mcbc_rate_valid(bss_config->mcbc_data_rate) != UAP_SUCCESS)) {
+		printf("ERR: Invalid MCBC Data Rate \n");
+		return UAP_FAILURE;
+	}
+
+	if ((bss_config->protocol == PROTOCOL_STATIC_WEP)
+	    && (0 == bss_config->wep_cfg.key0.is_default)
+	    && (0 == bss_config->wep_cfg.key1.is_default)
+	    && (0 == bss_config->wep_cfg.key2.is_default)
+	    && (0 == bss_config->wep_cfg.key3.is_default)) {
+		printf("ERR:WEP keys not set!\n");
+		return UAP_FAILURE;
+	}
+
+	if ((bss_config->auth_mode == 1) &&
+	    (bss_config->protocol != PROTOCOL_STATIC_WEP)) {
+		printf("ERR:Shared key authentication is not allowed for Open/WPA/WPA2/Mixed mode\n");
+		return UAP_FAILURE;
+	}
+
+	if (((bss_config->protocol == PROTOCOL_WPA) ||
+	     (bss_config->protocol == PROTOCOL_WPA2)
+	     || (bss_config->protocol == PROTOCOL_WPA2_MIXED)) &&
+	    !(bss_config->wpa_cfg.length)) {
+		printf("ERR:Passphrase must be set for WPA/WPA2/Mixed mode\n");
+		return UAP_FAILURE;
+	}
+
+	if ((bss_config->protocol == PROTOCOL_WPA) ||
+	    (bss_config->protocol == PROTOCOL_WPA2_MIXED)) {
+		if (is_cipher_valid
+		    (bss_config->wpa_cfg.pairwise_cipher_wpa,
+		     bss_config->wpa_cfg.group_cipher) != UAP_SUCCESS) {
+			printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
+			return UAP_FAILURE;
+		}
+	}
+	if ((bss_config->protocol == PROTOCOL_WPA2) ||
+	    (bss_config->protocol == PROTOCOL_WPA2_MIXED)) {
+		if (is_cipher_valid
+		    (bss_config->wpa_cfg.pairwise_cipher_wpa2,
+		     bss_config->wpa_cfg.group_cipher) != UAP_SUCCESS) {
+			printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	if (0 == bss_config->num_of_chan) {
+		printf("ERR: No channel list found\n");
+		return UAP_FAILURE;
+	}
+
+	if (acs_mode_enabled) {
+		for (i = 0; i < bss_config->num_of_chan; i++) {
+			if ((!state_80211d) &&
+			    (bss_config->chan_list[i].chan_number ==
+			     MAX_CHANNELS_BG)
+			    &&
+			    (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1)
+			     == 0)
+				) {
+				printf("ERR: Invalid scan channel 14, 802.11d disabled, country code JP!\n");
+				return UAP_FAILURE;
+			}
+
+			if (fw.region_code == JP_REGION_0xFE &&
+			    ((bss_config->chan_list[i].chan_number == 12) ||
+			     (bss_config->chan_list[i].chan_number == 13))) {
+				printf("ERR:Scan Channel 12 or 13 is not allowed for region code 0xFE\n");
+				return UAP_FAILURE;
+			}
+		}
+
+		if (!state_80211d) {
+			/* Block scan channels 8 and 12 in 5GHz band if 11d is not enabled and country code not set to JP */
+			for (i = 0; i < bss_config->num_of_chan; i++) {
+				if ((bss_config->chan_list[i].bandcfg.
+				     chanBand == BAND_5GHZ)
+				    &&
+				    ((bss_config->chan_list[i].chan_number == 8)
+				     || (bss_config->chan_list[i].chan_number ==
+					 12))) {
+					printf("ERR: Invalid band for scan channel %d\n", bss_config->chan_list[i].chan_number);
+					return UAP_FAILURE;
+				}
+			}
+		}
+
+		if (state_80211d) {
+			/* Set default country code to US */
+			strncpy(country_80211d, "US ",
+				sizeof(country_80211d) - 1);
+			for (i = 0; i < bss_config->num_of_chan; i++) {
+				/* Set country code to JP if channel is 8 or 12 and band is 5GHZ */
+				if ((bss_config->chan_list[i].chan_number <
+				     MAX_CHANNELS_BG) &&
+				    (scan_channels_band == BAND_A)) {
+					strncpy(country_80211d, "JP ",
+						sizeof(country_80211d) - 1);
+				}
+				if (check_channel_validity_11d
+				    (bss_config->chan_list[i].chan_number,
+				     scan_channels_band, 0) == UAP_FAILURE)
+					return UAP_FAILURE;
+			}
+			if (update_domain_info
+			    (country_80211d,
+			     scan_channels_band) == UAP_FAILURE) {
+				return UAP_FAILURE;
+			}
+		}
+	}
+#ifdef WIFI_DIRECT_SUPPORT
+	if (strncmp(dev_name, "wfd", 3))
+#endif
+		if ((!acs_mode_enabled &&
+		     (channel_tlv_band == (BAND_B | BAND_G)))
+		    || (acs_mode_enabled &&
+			(scan_channels_band == (BAND_B | BAND_G)))) {
+			if (0 == bss_config->rates[0]) {
+				printf("ERR: No rates found\n");
+				return UAP_FAILURE;
+			}
+			for (i = 0; i < MAX_DATA_RATES && bss_config->rates[i];
+			     i++) {
+				rate = bss_config->
+					rates[i] & ~BASIC_RATE_SET_BIT;
+				switch (rate) {
+				case 2:
+					rate_bitmap |= BITMAP_RATE_1M;
+					break;
+				case 4:
+					rate_bitmap |= BITMAP_RATE_2M;
+					break;
+				case 11:
+					rate_bitmap |= BITMAP_RATE_5_5M;
+					break;
+				case 22:
+					rate_bitmap |= BITMAP_RATE_11M;
+					break;
+				}
+			}
+			if ((rate_bitmap & B_RATE_MANDATORY) !=
+			    B_RATE_MANDATORY) {
+				if (acs_mode_enabled)
+					printf("ERR: Rates/Scan channels do not match!\n");
+				else
+					printf("ERR: Rates/Channel do not match!\n");
+				return UAP_FAILURE;
+			}
+		}
+	if ((!acs_mode_enabled && (channel_tlv_band == BAND_A))
+	    || (acs_mode_enabled && (scan_channels_band == BAND_A))) {
+		if (0 == bss_config->rates[0]) {
+			printf("ERR: No rates found\n");
+			return UAP_FAILURE;
+		}
+		for (i = 0; i < MAX_DATA_RATES && bss_config->rates[i]; i++) {
+			rate = bss_config->rates[i] & ~BASIC_RATE_SET_BIT;
+			switch (rate) {
+			case 2:
+			case 4:
+			case 11:
+			case 22:
+				if (acs_mode_enabled)
+					printf("ERR: Rates/Scan channels do not match!\n");
+				else
+					printf("ERR: Rates/Channel do not match!\n");
+				return UAP_FAILURE;
+			}
+		}
+		state_80211h = 1;
+		if (sg_snmp_mib
+		    (ACTION_SET, OID_80211H_ENABLE, sizeof(state_80211h),
+		     &state_80211h)
+		    == UAP_FAILURE) {
+			return UAP_FAILURE;
+		}
+		if (update_domain_info(country_80211d, BAND_A) == UAP_FAILURE) {
+			return UAP_FAILURE;
+		}
+	}
+#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17))
+#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24))
+
+	if (enable_40Mhz) {
+		if (!ISSUPP_CHANWIDTH40(fw.hw_dot_11n_dev_cap)) {
+			printf("ERR: It's not support HT40 from Hardware Cap\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	if (enable_11n) {
+		/*For protocol = Mixed, 11n enabled, only allow TKIP cipher for WPA protocol, not for WPA2 */
+		if ((bss_config->protocol == PROTOCOL_WPA2_MIXED) &&
+		    (bss_config->wpa_cfg.pairwise_cipher_wpa2 == CIPHER_TKIP)) {
+			printf("ERR: WPA2 pairwise cipher cannot be TKIP when AP operates in 802.11n Mixed mode.\n");
+			return UAP_FAILURE;
+		} else if (bss_config->protocol == PROTOCOL_STATIC_WEP) {
+			printf("ERR: WEP cannot be used when AP operates in 802.11n mode.\n");
+			return UAP_FAILURE;
+		}
+	}
+	if ((tx_rate_config.rate == UAP_RATE_INDEX_MCS32) && !enable_40Mhz) {
+		printf("ERR:uAP must be configured to operate in 40MHz if tx_rate is MCS32\n");
+		return UAP_FAILURE;
+	}
+	if (enable_20Mhz_sgi && enable_gf) {
+		if ((tx_rate_config.rate >= UAP_RATE_INDEX_MCS0) &&
+		    (tx_rate_config.rate <= UAP_RATE_INDEX_MCS7)) {
+			printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n");
+			return UAP_FAILURE;
+		}
+	}
+	mcs_rate_index =
+		get_rate_index_from_bitmap(tx_rate_config.bitmap_rates,
+					   sizeof(tx_rate_config.bitmap_rates));
+	if ((mcs_rate_index >= UAP_RATE_BITMAP_MCS0) &&
+	    (mcs_rate_index <= UAP_RATE_BITMAP_MCS127)) {
+		mcs_rate_index -= (UAP_RATE_BITMAP_MCS0 - UAP_RATE_INDEX_MCS0);
+		if ((mcs_rate_index == UAP_RATE_INDEX_MCS32) & !enable_40Mhz) {
+			printf("ERR:uAP must be configured to operate in 40MHz if rate_bitmap contains MCS32\n");
+			return UAP_FAILURE;
+		}
+		if (enable_20Mhz_sgi && enable_gf) {
+			if ((mcs_rate_index >= UAP_RATE_INDEX_MCS0) &&
+			    (mcs_rate_index <= UAP_RATE_INDEX_MCS7)) {
+				printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n");
+				return UAP_FAILURE;
+			}
+		}
+	}
+
+/* if 11d enabled, Channel 14, country code "JP", only B rates are allowed*/
+	if ((bss_config->channel == 14) && state_80211d &&
+	    (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) == 0)) {
+		if (0 == bss_config->rates[0]) {
+			printf("ERR:No rates found\n");
+			return UAP_FAILURE;
+		}
+		if (enable_11n) {
+			printf("ERR:11n must be disabled and the only B rates are allowed if 11d enabled and country code is JP with channel 14.\n");
+			return UAP_FAILURE;
+		}
+		for (i = 0; i < MAX_DATA_RATES && bss_config->rates[i]; i++) {
+			rate = bss_config->rates[i] & ~BASIC_RATE_SET_BIT;
+			switch (rate) {
+			case 2:
+			case 4:
+			case 11:
+			case 22:
+				break;
+			default:
+				printf("ERR:If 11d enabled, channel 14 and country code is JP, the only B rates are allowed.\n");
+				return UAP_FAILURE;
+			}
+		}
+	}
+
+	/* Channels 14, 165 are not allowed to operate in 40MHz mode */
+	if (!acs_mode_enabled && enable_40Mhz) {
+		if ((bss_config->channel == 14)
+		    || (bss_config->channel == 165)
+			) {
+			printf("ERR:Invalid channel %d for 40MHz operation\n",
+			       bss_config->channel);
+			return UAP_FAILURE;
+		} else if (!secondary_ch_set) {
+			printf("ERR:Secondary channel should be set when 40Mhz is enabled!\n");
+			return UAP_FAILURE;
+		}
+	}
+/* Channels 14, 140, 165 are not allowed to operate in 40MHz mode */
+	if (acs_mode_enabled && enable_40Mhz) {
+		if (bss_config->num_of_chan == 0) {
+			printf("ERR: No channel list found\n");
+			return UAP_FAILURE;
+		}
+		for (i = 0; i < bss_config->num_of_chan; i++) {
+			if ((bss_config->chan_list[i].chan_number != 14)
+			    && (bss_config->chan_list[i].chan_number != 140) &&
+			    (bss_config->chan_list[i].chan_number != 165)
+				) {
+				flag = 1;
+				break;
+			}
+		}
+		if (!flag) {
+			printf("ERR:Invalid channels in scan channel list for 40MHz operation\n");
+			return UAP_FAILURE;
+		}
+	}
+
+	if (0 == get_fw_info(&fw)) {
+		/*check whether support 802.11AC through BAND_AAC bit */
+		if (fw.fw_bands & BAND_AAC) {
+			ret = get_802_11ac_cfg(&vhtcfg);
+			if (UAP_SUCCESS == ret) {
+				/* Note: When 11AC is disabled, FW sets vht_rx_mcs to 0xffff */
+				if ((vhtcfg.vht_rx_mcs != 0xffff) &&
+				    (!enable_11n)) {
+					printf("ERR: 11ac enable while 11n disable, it is forbidden! \n");
+					return UAP_FAILURE;
+				}
+			} else {
+				printf("Don't support 802.11AC \n");
+				return UAP_SUCCESS;
+			}
+		} else
+			printf("No support 802 11AC.\n");
+	} else {
+		printf("ERR: get_fw_info fail\n");
+		return UAP_FAILURE;
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief Send read/write command along with register details to the driver
+ *  @param reg      Reg type
+ *  @param offset   Pointer to register offset string
+ *  @param strvalue Pointer to value string
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+apcmd_regrdwr_process(int reg, char *offset, char *strvalue)
+{
+	apcmdbuf_reg_rdwr *cmd_buf = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	char *whichreg;
+
+	/* Alloc buf for command */
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+
+	/* Locate headers */
+	cmd_len = sizeof(apcmdbuf_reg_rdwr);
+	cmd_buf = (apcmdbuf_reg_rdwr *)buf;
+
+	/* Fill the command buffer */
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	switch (reg) {
+	case CMD_MAC:
+		whichreg = "MAC";
+		cmd_buf->cmd_code = HostCmd_CMD_MAC_REG_ACCESS;
+		break;
+	case CMD_BBP:
+		whichreg = "BBP";
+		cmd_buf->cmd_code = HostCmd_CMD_BBP_REG_ACCESS;
+		break;
+	case CMD_RF:
+		cmd_buf->cmd_code = HostCmd_CMD_RF_REG_ACCESS;
+		whichreg = "RF";
+		break;
+	default:
+		printf("Invalid register set specified.\n");
+		free(buf);
+		return UAP_FAILURE;
+	}
+	if (strvalue) {
+		cmd_buf->action = 1;	// WRITE
+	} else {
+		cmd_buf->action = 0;	// READ
+	}
+	cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
+	cmd_buf->offset = A2HEXDECIMAL(offset);
+	cmd_buf->offset = uap_cpu_to_le16(cmd_buf->offset);
+	if (strvalue) {
+		cmd_buf->value = A2HEXDECIMAL(strvalue);
+		cmd_buf->value = uap_cpu_to_le32(cmd_buf->value);
+	}
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("Successfully executed the command\n");
+			printf("%s[0x%04hx] = 0x%08x\n",
+			       whichreg, uap_le16_to_cpu(cmd_buf->offset),
+			       uap_le32_to_cpu(cmd_buf->value));
+		} else {
+			printf("ERR:Command sending failed!\n");
+			free(buf);
+			return UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+		free(buf);
+		return UAP_FAILURE;
+	}
+
+	free(buf);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Send read command for EEPROM
+ *
+ *  Usage: "Usage : rdeeprom <offset> <byteCount>"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_read_eeprom(int argc, char *argv[])
+{
+	apcmdbuf_eeprom_access *cmd_buf = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	t_u16 byte_count, offset;
+	int ret = UAP_SUCCESS;
+	int opt;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_apcmd_read_eeprom_usage();
+			return UAP_FAILURE;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (!argc ||
+	    (argc && is_input_valid(RDEEPROM, argc, argv) != UAP_SUCCESS)) {
+		print_apcmd_read_eeprom_usage();
+		return UAP_FAILURE;
+	}
+	offset = A2HEXDECIMAL(argv[0]);
+	byte_count = A2HEXDECIMAL(argv[1]);
+
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_eeprom_access *)buf;
+	cmd_len = sizeof(apcmdbuf_eeprom_access);
+
+	cmd_buf->size = sizeof(apcmdbuf_eeprom_access) - BUF_HEADER_SIZE;
+	cmd_buf->result = 0;
+	cmd_buf->seq_num = 0;
+	cmd_buf->action = 0;
+
+	cmd_buf->cmd_code = HostCmd_EEPROM_ACCESS;
+	cmd_buf->offset = uap_cpu_to_le16(offset);
+	cmd_buf->byte_count = uap_cpu_to_le16(byte_count);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("Successfully executed the command\n");
+			byte_count = uap_le16_to_cpu(cmd_buf->byte_count);
+			offset = uap_le16_to_cpu(cmd_buf->offset);
+			hexdump_data("EEPROM", (void *)cmd_buf->value,
+				     byte_count, ' ');
+		} else {
+			printf("ERR:Command Response incorrect!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+
+	free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the regrdwr command
+ *  command
+ *
+ *  $return         N/A
+ */
+void
+print_regrdwr_usage(void)
+{
+	printf("\nUsage : uaputl.exe regrdwr <TYPE> <OFFSET> [value]\n");
+	printf("\nTYPE Options: 1     - read/write MAC register");
+	printf("\n              2     - read/write BBP register");
+	printf("\n              3     - read/write RF register");
+	printf("\n");
+	return;
+
+}
+
+/**
+ *  @brief Provides interface to perform read/write operations on regsiters
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_regrdwr(int argc, char *argv[])
+{
+	int opt;
+	t_s32 reg;
+	int ret = UAP_SUCCESS;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_regrdwr_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc < 2) || (argc > 3)) {
+		printf("ERR:wrong arguments.\n");
+		print_regrdwr_usage();
+		return UAP_FAILURE;
+	}
+	if ((atoi(argv[0]) != 1) && (atoi(argv[0]) != 2) &&
+	    (atoi(argv[0]) != 3)) {
+		printf("ERR:Illegal register type %s. Must be either '1','2' or '3'.\n", argv[0]);
+		print_regrdwr_usage();
+		return UAP_FAILURE;
+	}
+	reg = atoi(argv[0]);
+	ret = apcmd_regrdwr_process(reg, argv[1], argc > 2 ? argv[2] : NULL);
+	return ret;
+}
+
+/**
+ *    @brief Show usage information for the memaccess command
+ *    command
+ *
+ *    $return         N/A
+ */
+void
+print_memaccess_usage(void)
+{
+	printf("\nUsage : uaputl.exe memaccess <ADDRESS> [value]\n");
+	printf("\nRead/Write memory location");
+	printf("\nADDRESS: Address of the memory location to be read/written");
+	printf("\nValue  : Value to be written at that address\n");
+	return;
+}
+
+/**
+ *  @brief Provides interface to perform read/write memory location
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_memaccess(int argc, char *argv[])
+{
+	int opt;
+	apcmdbuf_mem_access *cmd_buf = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	char *address = NULL;
+	char *value = NULL;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_memaccess_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc < 1) || (argc > 2)) {
+		printf("ERR:wrong arguments.\n");
+		print_memaccess_usage();
+		return UAP_FAILURE;
+	}
+
+	address = argv[0];
+	if (argc == 2)
+		value = argv[1];
+
+	/* Alloc buf for command */
+	buf = (t_u8 *)malloc(buf_len);
+
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+	/* Locate headers */
+	cmd_len = sizeof(apcmdbuf_mem_access);
+	cmd_buf = (apcmdbuf_mem_access *)buf;
+
+	/* Fill the command buffer */
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->cmd_code = HostCmd_CMD_MEM_ACCESS;
+
+	if (value)
+		cmd_buf->action = 1;	// WRITE
+	else
+		cmd_buf->action = 0;	// READ
+
+	cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
+	cmd_buf->address = A2HEXDECIMAL(address);
+	cmd_buf->address = uap_cpu_to_le32(cmd_buf->address);
+
+	if (value) {
+		cmd_buf->value = A2HEXDECIMAL(value);
+		cmd_buf->value = uap_cpu_to_le32(cmd_buf->value);
+	}
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("Successfully executed the command\n");
+			printf("[0x%04x] = 0x%08x\n",
+			       uap_le32_to_cpu(cmd_buf->address),
+			       uap_le32_to_cpu(cmd_buf->value));
+		} else {
+			printf("ERR:Command sending failed!\n");
+			free(buf);
+			return UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+		free(buf);
+		return UAP_FAILURE;
+	}
+	free(buf);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the bss_config command
+ *
+ *  $return         N/A
+ */
+void
+print_bss_config_usage(void)
+{
+	printf("\nUsage : bss_config [CONFIG_FILE]\n");
+	printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n");
+	printf("CONFIG_FILE is file containing all the BSS settings.\n");
+	return;
+}
+
+/**
+ *  @brief Read the BSS profile and populate structure
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @param bss      Pointer to BSS configuration buffer
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+parse_bss_config(int argc, char *argv[], bss_config_t *bss)
+{
+	FILE *config_file = NULL;
+	char *line = NULL;
+	int li = 0;
+	char *pos = NULL;
+	int arg_num = 0;
+	char *args[30];
+	int i;
+	int is_ap_config = 0;
+	int is_ap_mac_filter = 0;
+	int keyindex = -1;
+	int pwkcipher_wpa = -1;
+	int pwkcipher_wpa2 = -1;
+	int gwkcipher = -1;
+	int protocol = -1;
+	int tx_data_rate = -1;
+	int tx_beacon_rate = -1;
+	int mcbc_data_rate = -1;
+	int num_rates = 0;
+	int found = 0;
+	int filter_mac_count = -1;
+	int retval = UAP_SUCCESS;
+	int chan_mode = 0;
+	int band_flag = 0;
+	int chan_number = 0;
+	t_u16 max_sta_num_supported = 0;
+	fw_info fw;
+	HTCap_t htcap;
+	int enable_11n = -1;
+	t_u32 supported_mcs_set = 0;
+	int ac = 0;
+	int is_wmm_parameters = 0;
+	char oui_type[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	struct eth_priv_vhtcfg vhtcfg = { 0 };
+
+	/* Check if file exists */
+	config_file = fopen(argv[0], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return UAP_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		retval = UAP_FAILURE;
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+#if DEBUG
+		uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n",
+			   li, line);
+#endif
+		arg_num = parse_line(line, args);
+#if DEBUG
+		uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n",
+			   arg_num);
+		for (i = 0; i < arg_num; i++) {
+			uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1,
+				   args[i]);
+		}
+#endif
+		/* Check for end of AP configurations */
+		if (is_ap_config == 1) {
+			if (strcmp(args[0], "}") == 0) {
+				is_ap_config = 0;
+				if (tx_data_rate != -1) {
+					if ((!bss->rates[0]) && (tx_data_rate)
+					    &&
+					    (is_tx_rate_valid
+					     ((t_u8)tx_data_rate) !=
+					     UAP_SUCCESS)) {
+						printf("ERR: Invalid Tx Data Rate \n");
+						retval = UAP_FAILURE;
+						goto done;
+					}
+					if (bss->rates[0] && tx_data_rate) {
+						for (i = 0; bss->rates[i] != 0;
+						     i++) {
+							if ((bss->
+							     rates[i] &
+							     ~BASIC_RATE_SET_BIT)
+							    == tx_data_rate) {
+								found = 1;
+								break;
+							}
+						}
+						if (!found) {
+							printf("ERR: Invalid Tx Data Rate \n");
+							retval = UAP_FAILURE;
+							goto done;
+						}
+					}
+
+					/* Set Tx data rate field */
+					bss->tx_data_rate = tx_data_rate;
+				}
+				if (tx_beacon_rate != -1) {
+					if ((!bss->rates[0]) && (tx_beacon_rate)
+					    &&
+					    (is_tx_rate_valid
+					     ((t_u8)tx_beacon_rate) !=
+					     UAP_SUCCESS)) {
+						printf("ERR: Invalid Tx Beacon Rate \n");
+						retval = UAP_FAILURE;
+						goto done;
+					}
+					if (bss->rates[0] && tx_beacon_rate) {
+						for (i = 0; bss->rates[i] != 0;
+						     i++) {
+							if ((bss->
+							     rates[i] &
+							     ~BASIC_RATE_SET_BIT)
+							    == tx_beacon_rate) {
+								found = 1;
+								break;
+							}
+						}
+						if (!found) {
+							printf("ERR: Invalid Tx Beacon Rate \n");
+							retval = UAP_FAILURE;
+							goto done;
+						}
+					}
+
+					/* Set Tx beacon rate field */
+					bss->tx_beacon_rate = tx_beacon_rate;
+				}
+				if (mcbc_data_rate != -1) {
+					if ((!bss->rates[0]) && (mcbc_data_rate)
+					    &&
+					    (is_mcbc_rate_valid
+					     ((t_u8)mcbc_data_rate) !=
+					     UAP_SUCCESS)) {
+						printf("ERR: Invalid Tx Data Rate \n");
+						retval = UAP_FAILURE;
+						goto done;
+					}
+					if (bss->rates[0] && mcbc_data_rate) {
+						for (i = 0; bss->rates[i] != 0;
+						     i++) {
+							if (bss->
+							    rates[i] &
+							    BASIC_RATE_SET_BIT)
+							{
+								if ((bss->
+								     rates[i] &
+								     ~BASIC_RATE_SET_BIT)
+								    ==
+								    mcbc_data_rate)
+								{
+									found = 1;
+									break;
+								}
+							}
+						}
+						if (!found) {
+							printf("ERR: Invalid MCBC Data Rate \n");
+							retval = UAP_FAILURE;
+							goto done;
+						}
+					}
+
+					/* Set MCBC data rate field */
+					bss->mcbc_data_rate = mcbc_data_rate;
+				}
+				if ((protocol == PROTOCOL_STATIC_WEP) &&
+				    (enable_11n == 1)) {
+					printf("ERR:WEP cannot be used when AP operates in 802.11n mode.\n");
+					goto done;
+				}
+				if (0 == get_fw_info(&fw)) {
+					/*check whether support 802.11AC through BAND_AAC bit */
+					if (fw.fw_bands & BAND_AAC) {
+						retval = get_802_11ac_cfg
+							(&vhtcfg);
+						if (retval != UAP_SUCCESS)
+							goto done;
+						if ((enable_11n == 1) &&
+						    (vhtcfg.vht_rx_mcs !=
+						     0xffff)) {
+							printf("ERR: 11n must be enabled when AP operates in 11ac mode.\n");
+							retval = UAP_FAILURE;
+							goto done;
+						}
+					} else
+						printf("No support 802 11AC.\n");
+				} else {
+					printf("ERR: get_fw_info fail\n");
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				if ((protocol == PROTOCOL_WPA2_MIXED) &&
+				    ((pwkcipher_wpa < 0) ||
+				     (pwkcipher_wpa2 < 0))) {
+					printf("ERR:Both PwkCipherWPA and PwkCipherWPA2 should be defined for Mixed mode.\n");
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				if (protocol != -1) {
+					bss->protocol = protocol;
+					if (protocol &
+					    (PROTOCOL_WPA | PROTOCOL_WPA2)) {
+						/* Set key management field */
+						bss->key_mgmt = KEY_MGMT_PSK;
+						bss->key_mgmt_operation = 0;
+					}
+				}
+				if (((pwkcipher_wpa >= 0) ||
+				     (pwkcipher_wpa2 >= 0)) &&
+				    (gwkcipher >= 0)) {
+					if ((protocol == PROTOCOL_WPA) ||
+					    (protocol == PROTOCOL_WPA2_MIXED)) {
+						if (enable_11n != -1) {
+							if (is_cipher_valid_with_11n(pwkcipher_wpa, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) {
+								printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
+								retval = UAP_FAILURE;
+								goto done;
+							}
+						} else if
+							(is_cipher_valid_with_proto
+							 (pwkcipher_wpa,
+							  gwkcipher,
+							  protocol) !=
+							 UAP_SUCCESS) {
+							printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
+							retval = UAP_FAILURE;
+							goto done;
+						}
+					}
+					if ((protocol == PROTOCOL_WPA2) ||
+					    (protocol == PROTOCOL_WPA2_MIXED)) {
+						if (enable_11n != -1) {
+							if (is_cipher_valid_with_11n(pwkcipher_wpa2, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) {
+								printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
+								retval = UAP_FAILURE;
+								goto done;
+							}
+						} else if
+							(is_cipher_valid_with_proto
+							 (pwkcipher_wpa2,
+							  gwkcipher,
+							  protocol) !=
+							 UAP_SUCCESS) {
+							printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
+							retval = UAP_FAILURE;
+							goto done;
+						}
+					}
+					/* Set pairwise and group cipher fields */
+					bss->wpa_cfg.pairwise_cipher_wpa =
+						pwkcipher_wpa;
+					bss->wpa_cfg.pairwise_cipher_wpa2 =
+						pwkcipher_wpa2;
+					bss->wpa_cfg.group_cipher = gwkcipher;
+				}
+				continue;
+			}
+		}
+
+		/* Check for beginning of AP configurations */
+		if (strcmp(args[0], "ap_config") == 0) {
+			is_ap_config = 1;
+			continue;
+		}
+
+		/* Check for end of AP MAC address filter configurations */
+		if (is_ap_mac_filter == 1) {
+			if (strcmp(args[0], "}") == 0) {
+				is_ap_mac_filter = 0;
+				if (bss->filter.mac_count != filter_mac_count) {
+					printf("ERR:Number of MAC address provided does not match 'Count'\n");
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				if (bss->filter.filter_mode &&
+				    (bss->filter.mac_count == 0)) {
+					printf("ERR:Filter list can not be empty for %s Filter mode\n", (bss->filter.filter_mode == 1) ? "'Allow'" : "'Block'");
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				continue;
+			}
+		}
+
+		/* Check for beginning of AP MAC address filter configurations */
+		if (strcmp(args[0], "ap_mac_filter") == 0) {
+			is_ap_mac_filter = 1;
+			bss->filter.mac_count = 0;
+			filter_mac_count = 0;
+			continue;
+		}
+		if ((strcmp(args[0], "FilterMode") == 0) && is_ap_mac_filter) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) ||
+			    (atoi(args[1]) > 2)) {
+				printf("ERR:Illegal FilterMode paramter %d. Must be either '0', '1', or '2'.\n", atoi(args[1]));
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			bss->filter.filter_mode = atoi(args[1]);
+			continue;
+		}
+		if ((strcmp(args[0], "Count") == 0) && is_ap_mac_filter) {
+			bss->filter.mac_count = atoi(args[1]);
+			if ((ISDIGIT(args[1]) == 0) ||
+			    (bss->filter.mac_count > MAX_MAC_ONESHOT_FILTER)) {
+				printf("ERR: Illegal Count parameter.\n");
+				retval = UAP_FAILURE;
+				goto done;
+			}
+		}
+		if ((strncmp(args[0], "mac_", 4) == 0) && is_ap_mac_filter) {
+			if (filter_mac_count < MAX_MAC_ONESHOT_FILTER) {
+				if (mac2raw
+				    (args[1],
+				     bss->filter.mac_list[filter_mac_count]) !=
+				    UAP_SUCCESS) {
+					printf("ERR: Invalid MAC address %s \n",
+					       args[1]);
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				filter_mac_count++;
+			} else {
+				printf("ERR: Filter table can not have more than %d MAC addresses\n", MAX_MAC_ONESHOT_FILTER);
+				retval = UAP_FAILURE;
+				goto done;
+			}
+		}
+
+		/* Check for end of Wmm Parameters configurations */
+		if (is_wmm_parameters == 1) {
+			if (strcmp(args[0], "}") == 0) {
+				is_wmm_parameters = 0;
+				continue;
+			}
+		}
+		/* Check for beginning of Sticky Tim Sta MAC address Configurations */
+		if (strcmp(args[0], "Wmm_parameters") == 0) {
+			is_wmm_parameters = 1;
+			memset(&(bss->wmm_para), 0, sizeof(bss->wmm_para));
+			memcpy(bss->wmm_para.ouitype, oui_type,
+			       sizeof(oui_type));
+			bss->wmm_para.ouisubtype = 1;
+			bss->wmm_para.version = 1;
+			continue;
+		}
+		if ((strcmp(args[0], "Qos_info") == 0) && is_wmm_parameters) {
+			bss->wmm_para.qos_info = A2HEXDECIMAL(args[1]);
+			printf("wmm_para.qos_info = %2x\n",
+			       bss->wmm_para.qos_info);
+			if ((bss->wmm_para.qos_info != ENABLE_WMM_PS) &&
+			    (bss->wmm_para.qos_info != DISABLE_WMM_PS)) {
+				printf("ERR:qos_info must be either 0x80 or 0x00.\n");
+				retval = UAP_FAILURE;
+				goto done;
+			}
+		}
+		if ((strcmp(args[0], "AC_BE") == 0) && is_wmm_parameters) {
+			ac = 0;
+		}
+		if ((strcmp(args[0], "AC_BK") == 0) && is_wmm_parameters) {
+			ac = 1;
+		}
+		if ((strcmp(args[0], "AC_VI") == 0) && is_wmm_parameters) {
+			ac = 2;
+		}
+		if ((strcmp(args[0], "AC_VO") == 0) && is_wmm_parameters) {
+			ac = 3;
+		}
+		if ((strcmp(args[0], "Aifsn") == 0) && is_wmm_parameters) {
+			bss->wmm_para.ac_params[ac].aci_aifsn.aifsn =
+				(t_u8)A2HEXDECIMAL(args[1]);
+			printf("wmm_para.ac_params[%d].aci_aifsn.aifsn = %x\n",
+			       ac, bss->wmm_para.ac_params[ac].aci_aifsn.aifsn);
+			bss->wmm_para.ac_params[ac].aci_aifsn.aci = (t_u8)ac;
+			printf("wmm_para.ac_params[%d].aci_aifsn.aci = %x\n",
+			       ac, bss->wmm_para.ac_params[ac].aci_aifsn.aci);
+		}
+		if ((strcmp(args[0], "Ecw_max") == 0) && is_wmm_parameters) {
+			bss->wmm_para.ac_params[ac].ecw.ecw_max =
+				(t_u8)A2HEXDECIMAL(args[1]);
+			printf("wmm_para.ac_params[%d].ecw.ecw_max = %x\n", ac,
+			       bss->wmm_para.ac_params[ac].ecw.ecw_max);
+		}
+		if ((strcmp(args[0], "Ecw_min") == 0) && is_wmm_parameters) {
+			bss->wmm_para.ac_params[ac].ecw.ecw_min =
+				(t_u8)A2HEXDECIMAL(args[1]);
+			printf("wmm_para.ac_params[%d].ecw.ecw_min = %x\n", ac,
+			       bss->wmm_para.ac_params[ac].ecw.ecw_min);
+		}
+		if ((strcmp(args[0], "Tx_op") == 0) && is_wmm_parameters) {
+			bss->wmm_para.ac_params[ac].tx_op_limit =
+				(t_u8)A2HEXDECIMAL(args[1]);
+			printf("wmm_para.ac_params[%d].tx_op_limit = %x\n", ac,
+			       bss->wmm_para.ac_params[ac].tx_op_limit);
+		}
+
+		if (strcmp(args[0], "SSID") == 0) {
+			if (arg_num == 1) {
+				printf("ERR:SSID field is blank!\n");
+				retval = UAP_FAILURE;
+				goto done;
+			} else {
+				if (args[1][0] == '"') {
+					args[1]++;
+				}
+				if (args[1][strlen(args[1]) - 1] == '"') {
+					args[1][strlen(args[1]) - 1] = '\0';
+				}
+				if ((strlen(args[1]) > MAX_SSID_LENGTH) ||
+				    (strlen(args[1]) == 0)) {
+					printf("ERR:SSID length out of range (%d to %d).\n", MIN_SSID_LENGTH, MAX_SSID_LENGTH);
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				/* Set SSID field */
+				bss->ssid.ssid_len = strlen(args[1]);
+				memcpy(bss->ssid.ssid, args[1],
+				       bss->ssid.ssid_len);
+			}
+		}
+		if (strcmp(args[0], "BeaconPeriod") == 0) {
+			if (is_input_valid(BEACONPERIOD, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set beacon period field */
+			bss->beacon_period = (t_u16)atoi(args[1]);
+		}
+		if (strcmp(args[0], "ChanList") == 0) {
+			if (is_input_valid(SCANCHANNELS, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+
+			/* Set channel list field */
+			if ((arg_num - 1) < MAX_CHANNELS) {
+				bss->num_of_chan = arg_num - 1;
+			} else {
+				bss->num_of_chan = MAX_CHANNELS;
+			}
+			for (i = 0; (unsigned int)i < bss->num_of_chan; i++) {
+				sscanf(args[i + 1], "%d.%d", &chan_number,
+				       &band_flag);
+				bss->chan_list[i].chan_number = chan_number;
+				bss->chan_list[i].bandcfg.chanBand = BAND_2GHZ;
+				if (((band_flag != -1) && (band_flag)) ||
+				    (chan_number > MAX_CHANNELS_BG)) {
+					bss->chan_list[i].bandcfg.chanBand =
+						BAND_5GHZ;
+				}
+			}
+		}
+		if (strcmp(args[0], "Channel") == 0) {
+			if (is_input_valid(CHANNEL, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set channel field */
+			bss->channel = (t_u8)atoi(args[1]);
+			if ((arg_num - 1) == 2) {
+				chan_mode = atoi(args[2]);
+				memset(&(bss->bandcfg), 0,
+				       sizeof(bss->bandcfg));
+				if (chan_mode & BITMAP_ACS_MODE) {
+					int mode;
+
+					if (uap_ioctl_dfs_repeater_mode(&mode)
+					    == UAP_SUCCESS) {
+						if (mode) {
+							printf("ERR: ACS in DFS Repeater mode" " is not allowed\n");
+							retval = UAP_FAILURE;
+							goto done;
+						}
+					}
+
+					bss->bandcfg.scanMode = SCAN_MODE_ACS;
+				}
+				if (chan_mode & BITMAP_CHANNEL_ABOVE)
+					bss->bandcfg.chan2Offset =
+						SEC_CHAN_ABOVE;
+				if (chan_mode & BITMAP_CHANNEL_BELOW)
+					bss->bandcfg.chan2Offset =
+						SEC_CHAN_BELOW;
+			} else
+				memset(&(bss->bandcfg), 0,
+				       sizeof(bss->bandcfg));
+			if (bss->channel > MAX_CHANNELS_BG)
+				bss->bandcfg.chanBand = BAND_5GHZ;
+		}
+		if (strcmp(args[0], "Band") == 0) {
+			if (is_input_valid(BAND, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Clear previously set band */
+			bss->bandcfg.chanBand = BAND_2GHZ;
+			if (atoi(args[1]) == 1)
+				bss->bandcfg.chanBand = BAND_5GHZ;
+		}
+		if (strcmp(args[0], "AP_MAC") == 0) {
+			int ret;
+			if ((ret =
+			     mac2raw(args[1], bss->mac_addr)) != UAP_SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret ==
+				       UAP_FAILURE ? "Invalid MAC" : ret ==
+				       UAP_RET_MAC_BROADCAST ? "Broadcast" :
+				       "Multicast");
+				retval = UAP_FAILURE;
+				goto done;
+			}
+		}
+
+		if (strcmp(args[0], "Rate") == 0) {
+			if (is_input_valid(RATE, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				printf("ERR: Invalid Rate input\n");
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set rates field */
+			if ((arg_num - 1) < MAX_DATA_RATES) {
+				num_rates = arg_num - 1;
+			} else {
+				num_rates = MAX_DATA_RATES;
+			}
+			for (i = 0; i < num_rates; i++) {
+				bss->rates[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+		}
+		if (strcmp(args[0], "TxPowerLevel") == 0) {
+			if (is_input_valid(TXPOWER, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				printf("ERR:Invalid TxPowerLevel \n");
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set Tx power level field */
+			bss->tx_power_level = (t_u8)atoi(args[1]);
+		}
+		if (strcmp(args[0], "BroadcastSSID") == 0) {
+			if (is_input_valid(BROADCASTSSID, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set broadcast SSID control field */
+			bss->bcast_ssid_ctl = (t_u8)atoi(args[1]);
+		}
+		if (strcmp(args[0], "RTSThreshold") == 0) {
+			if (is_input_valid(RTSTHRESH, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set RTS threshold field */
+			bss->rts_threshold = (t_u16)atoi(args[1]);
+		}
+		if (strcmp(args[0], "FragThreshold") == 0) {
+			if (is_input_valid(FRAGTHRESH, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set Frag threshold field */
+			bss->frag_threshold = (t_u16)atoi(args[1]);
+		}
+		if (strcmp(args[0], "DTIMPeriod") == 0) {
+			if (is_input_valid(DTIMPERIOD, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set DTIM period field */
+			bss->dtim_period = (t_u8)atoi(args[1]);
+		}
+		if (strcmp(args[0], "RSNReplayProtection") == 0) {
+			if (is_input_valid(RSNREPLAYPROT, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set RSN replay protection field */
+			bss->wpa_cfg.rsn_protection = (t_u8)atoi(args[1]);
+		}
+		if (strcmp(args[0], "PairwiseUpdateTimeout") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set Pairwise Update Timeout field */
+			bss->pairwise_update_timeout = (t_u32)atoi(args[1]);
+		}
+		if (strcmp(args[0], "PairwiseHandshakeRetries") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set Pairwise Hanshake Retries */
+			bss->pwk_retries = (t_u32)atoi(args[1]);
+		}
+		if (strcmp(args[0], "GroupwiseUpdateTimeout") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set Groupwise Update Timeout field */
+			bss->groupwise_update_timeout = (t_u32)atoi(args[1]);
+		}
+		if (strcmp(args[0], "GroupwiseHandshakeRetries") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set Groupwise Hanshake Retries */
+			bss->gwk_retries = (t_u32)atoi(args[1]);
+		}
+		if (strcmp(args[0], "TxBeaconRate") == 0) {
+			if (is_input_valid(TXBEACONRATE, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			tx_beacon_rate = (t_u16)A2HEXDECIMAL(args[1]);
+		}
+		if (strcmp(args[0], "MCBCdataRate") == 0) {
+			if (is_input_valid(MCBCDATARATE, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			mcbc_data_rate = (t_u16)A2HEXDECIMAL(args[1]);
+		}
+		if (strcmp(args[0], "PktFwdCtl") == 0) {
+			if (is_input_valid(PKTFWD, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set packet forward control field */
+			bss->pkt_forward_ctl = (t_u8)atoi(args[1]);
+		}
+		if (strcmp(args[0], "StaAgeoutTimer") == 0) {
+			if (is_input_valid
+			    (STAAGEOUTTIMER, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set STA ageout timer field */
+			bss->sta_ageout_timer = (t_u32)atoi(args[1]);
+		}
+		if (strcmp(args[0], "PSStaAgeoutTimer") == 0) {
+			if (is_input_valid
+			    (PSSTAAGEOUTTIMER, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set PS STA ageout timer field */
+			bss->ps_sta_ageout_timer = (t_u32)atoi(args[1]);
+		}
+		if (strcmp(args[0], "AuthMode") == 0) {
+			if (is_input_valid(AUTHMODE, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set auth mode field */
+			bss->auth_mode = (t_u16)atoi(args[1]);
+		}
+		if (strcmp(args[0], "KeyIndex") == 0) {
+			if (arg_num == 1) {
+				printf("KeyIndex is blank!\n");
+				retval = UAP_FAILURE;
+				goto done;
+			} else {
+				if (ISDIGIT(args[1]) == 0) {
+					printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n");
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				keyindex = atoi(args[1]);
+				if ((keyindex < 0) || (keyindex > 3)) {
+					printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n");
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				switch (keyindex) {
+				case 0:
+					bss->wep_cfg.key0.is_default = 1;
+					break;
+				case 1:
+					bss->wep_cfg.key1.is_default = 1;
+					break;
+				case 2:
+					bss->wep_cfg.key2.is_default = 1;
+					break;
+				case 3:
+					bss->wep_cfg.key3.is_default = 1;
+					break;
+				}
+			}
+		}
+		if (strncmp(args[0], "Key_", 4) == 0) {
+			if (arg_num == 1) {
+				printf("ERR:%s is blank!\n", args[0]);
+				retval = UAP_FAILURE;
+				goto done;
+			} else {
+				int key_len = 0;
+				if (args[1][0] == '"') {
+					if ((strlen(args[1]) != 2) &&
+					    (strlen(args[1]) != 7) &&
+					    (strlen(args[1]) != 15)) {
+						printf("ERR:Wrong key length!\n");
+						retval = UAP_FAILURE;
+						goto done;
+					}
+					key_len = strlen(args[1]) - 2;
+				} else {
+					if ((strlen(args[1]) != 0) &&
+					    (strlen(args[1]) != 10) &&
+					    (strlen(args[1]) != 26)) {
+						printf("ERR:Wrong key length!\n");
+						retval = UAP_FAILURE;
+						goto done;
+					}
+					if (UAP_FAILURE == ishexstring(args[1])) {
+						printf("ERR:Only hex digits are allowed when key length is 10 or 26\n");
+						retval = UAP_FAILURE;
+						goto done;
+					}
+					key_len = strlen(args[1]) / 2;
+				}
+				/* Set WEP key fields */
+				if (strcmp(args[0], "Key_0") == 0) {
+					bss->wep_cfg.key0.key_index = 0;
+					bss->wep_cfg.key0.length = key_len;
+					if (args[1][0] == '"') {
+						memcpy(bss->wep_cfg.key0.key,
+						       &args[1][1],
+						       strlen(args[1]) - 2);
+					} else {
+						string2raw(args[1],
+							   bss->wep_cfg.key0.
+							   key);
+					}
+				} else if (strcmp(args[0], "Key_1") == 0) {
+					bss->wep_cfg.key1.key_index = 1;
+					bss->wep_cfg.key1.length = key_len;
+					if (args[1][0] == '"') {
+						memcpy(bss->wep_cfg.key1.key,
+						       &args[1][1],
+						       strlen(args[1]) - 2);
+					} else {
+						string2raw(args[1],
+							   bss->wep_cfg.key1.
+							   key);
+					}
+				} else if (strcmp(args[0], "Key_2") == 0) {
+					bss->wep_cfg.key2.key_index = 2;
+					bss->wep_cfg.key2.length = key_len;
+					if (args[1][0] == '"') {
+						memcpy(bss->wep_cfg.key2.key,
+						       &args[1][1],
+						       strlen(args[1]) - 2);
+					} else {
+						string2raw(args[1],
+							   bss->wep_cfg.key2.
+							   key);
+					}
+				} else if (strcmp(args[0], "Key_3") == 0) {
+					bss->wep_cfg.key3.key_index = 3;
+					bss->wep_cfg.key3.length = key_len;
+					if (args[1][0] == '"') {
+						memcpy(bss->wep_cfg.key3.key,
+						       &args[1][1],
+						       strlen(args[1]) - 2);
+					} else {
+						string2raw(args[1],
+							   bss->wep_cfg.key3.
+							   key);
+					}
+				}
+			}
+		}
+		if (strcmp(args[0], "PSK") == 0) {
+			if (arg_num == 1) {
+				printf("ERR:PSK is blank!\n");
+				retval = UAP_FAILURE;
+				goto done;
+			} else {
+				if (args[1][0] == '"') {
+					args[1]++;
+				}
+				if (args[1][strlen(args[1]) - 1] == '"') {
+					args[1][strlen(args[1]) - 1] = '\0';
+				}
+				if (strlen(args[1]) > MAX_WPA_PASSPHRASE_LENGTH) {
+					printf("ERR:PSK too long.\n");
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				if (strlen(args[1]) < MIN_WPA_PASSPHRASE_LENGTH) {
+					printf("ERR:PSK too short.\n");
+					retval = UAP_FAILURE;
+					goto done;
+				}
+				if (strlen(args[1]) ==
+				    MAX_WPA_PASSPHRASE_LENGTH) {
+					if (UAP_FAILURE == ishexstring(args[1])) {
+						printf("ERR:Only hex digits are allowed when passphrase's length is 64\n");
+						retval = UAP_FAILURE;
+						goto done;
+					}
+				}
+				/* Set WPA passphrase field */
+				bss->wpa_cfg.length = strlen(args[1]);
+				memcpy(bss->wpa_cfg.passphrase, args[1],
+				       bss->wpa_cfg.length);
+			}
+		}
+		if (strcmp(args[0], "Protocol") == 0) {
+			if (is_input_valid(PROTOCOL, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set protocol field */
+			protocol = (t_u16)atoi(args[1]);
+		}
+		if ((strcmp(args[0], "PairwiseCipher") == 0) ||
+		    (strcmp(args[0], "GroupCipher") == 0)) {
+			printf("ERR:PairwiseCipher and GroupCipher are not supported.\n" "    Please configure pairwise cipher using parameters PwkCipherWPA or PwkCipherWPA2\n" "    and group cipher using GwkCipher in the config file.\n");
+			goto done;
+		}
+
+		if ((protocol == PROTOCOL_NO_SECURITY) ||
+		    (protocol == PROTOCOL_STATIC_WEP)) {
+			if ((strcmp(args[0], "PwkCipherWPA") == 0) ||
+			    (strcmp(args[0], "PwkCipherWPA2") == 0)
+			    || (strcmp(args[0], "GwkCipher") == 0)) {
+				printf("ERR:Pairwise cipher and group cipher should not be defined for Open and WEP mode.\n");
+				goto done;
+			}
+		}
+
+		if (strcmp(args[0], "PwkCipherWPA") == 0) {
+			if (arg_num == 1) {
+				printf("ERR:PwkCipherWPA is blank!\n");
+				goto done;
+			} else {
+				if (ISDIGIT(args[1]) == 0) {
+					printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n");
+					goto done;
+				}
+				if (atoi(args[1]) & ~CIPHER_BITMAP) {
+					printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n");
+					goto done;
+				}
+				pwkcipher_wpa = atoi(args[1]);
+				if (enable_11n &&
+				    protocol != PROTOCOL_WPA2_MIXED) {
+					memset(&htcap, 0, sizeof(htcap));
+					if (UAP_SUCCESS ==
+					    get_sys_cfg_11n(&htcap)) {
+						if (htcap.supported_mcs_set[0]
+						    && (atoi(args[1]) ==
+							CIPHER_TKIP)) {
+							printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
+							return UAP_FAILURE;
+						}
+					}
+				}
+			}
+		}
+		if (strcmp(args[0], "PwkCipherWPA2") == 0) {
+			if (arg_num == 1) {
+				printf("ERR:PwkCipherWPA2 is blank!\n");
+				goto done;
+			} else {
+				if (ISDIGIT(args[1]) == 0) {
+					printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n");
+					goto done;
+				}
+				if (atoi(args[1]) & ~CIPHER_BITMAP) {
+					printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n");
+					goto done;
+				}
+				pwkcipher_wpa2 = atoi(args[1]);
+				if (enable_11n &&
+				    protocol != PROTOCOL_WPA2_MIXED) {
+					memset(&htcap, 0, sizeof(htcap));
+					if (UAP_SUCCESS ==
+					    get_sys_cfg_11n(&htcap)) {
+						if (htcap.supported_mcs_set[0]
+						    && (atoi(args[1]) ==
+							CIPHER_TKIP)) {
+							printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
+							return UAP_FAILURE;
+						}
+					}
+				}
+			}
+		}
+		if (strcmp(args[0], "GwkCipher") == 0) {
+			if (is_input_valid(GWK_CIPHER, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				goto done;
+			}
+			gwkcipher = atoi(args[1]);
+		}
+		if (strcmp(args[0], "GroupRekeyTime") == 0) {
+			if (is_input_valid
+			    (GROUPREKEYTIMER, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+
+			/* Set group rekey time field */
+			bss->wpa_cfg.gk_rekey_time = (t_u32)atoi(args[1]);
+		}
+		if (strcmp(args[0], "MaxStaNum") == 0) {
+			if (is_input_valid(MAXSTANUM, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			if (get_max_sta_num_supported(&max_sta_num_supported) ==
+			    UAP_FAILURE) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			if (atoi(args[1]) > max_sta_num_supported) {
+				printf("ERR: MAX_STA_NUM must be less than %d\n", max_sta_num_supported);
+				retval = UAP_FAILURE;
+				goto done;
+			}
+			/* Set max STA number field */
+			bss->max_sta_count = (t_u16)atoi(args[1]);
+		}
+		if (strcmp(args[0], "Retrylimit") == 0) {
+			if (is_input_valid(RETRYLIMIT, arg_num - 1, args + 1) !=
+			    UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+
+			/* Set retry limit field */
+			bss->retry_limit = (t_u16)atoi(args[1]);
+		}
+		if (strcmp(args[0], "PreambleType") == 0) {
+			if (is_input_valid(PREAMBLETYPE, arg_num - 1, args + 1)
+			    != UAP_SUCCESS) {
+				retval = UAP_FAILURE;
+				goto done;
+			}
+
+			/* Set preamble type field */
+			bss->preamble_type = (t_u8)atoi(args[1]);
+		}
+		if (strcmp(args[0], "Enable11n") == 0) {
+			if ((ISDIGIT(args[1]) != UAP_SUCCESS) ||
+			    (atoi(args[1]) < 0) || (atoi(args[1]) > 1)) {
+				printf("ERR: Invalid Enable11n value\n");
+				goto done;
+			}
+			enable_11n = atoi(args[1]);
+
+			memset(&htcap, 0, sizeof(htcap));
+			if (UAP_SUCCESS != get_sys_cfg_11n(&htcap)) {
+				printf("ERR: Reading current 11n configuration.\n");
+				goto done;
+			}
+			bss->ht_cap_info = htcap.ht_cap_info;
+			bss->ampdu_param = htcap.ampdu_param;
+			memcpy(bss->supported_mcs_set, htcap.supported_mcs_set,
+			       16);
+			bss->ht_ext_cap = htcap.ht_ext_cap;
+			bss->tx_bf_cap = htcap.tx_bf_cap;
+			bss->asel = htcap.asel;
+			if (enable_11n == 1) {
+				/* enable mcs rate */
+				bss->supported_mcs_set[0] = DEFAULT_MCS_SET_0;
+				bss->supported_mcs_set[4] = DEFAULT_MCS_SET_4;
+				if (0 == get_fw_info(&fw)) {
+					if ((fw.hw_dev_mcs_support & 0x0f) >= 2)
+						bss->supported_mcs_set[1] =
+							DEFAULT_MCS_SET_1;
+				}
+			} else {
+				/* disable mcs rate */
+				bss->supported_mcs_set[0] = 0;
+				bss->supported_mcs_set[4] = 0;
+				bss->supported_mcs_set[1] = 0;
+			}
+		}
+		if (strcmp(args[0], "HTCapInfo") == 0) {
+			if (enable_11n <= 0) {
+				printf("ERR: Enable11n parameter should be set before HTCapInfo.\n");
+				goto done;
+			}
+			if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) ||
+			    ((((t_u16)A2HEXDECIMAL(args[1])) &
+			      (~HT_CAP_CONFIG_MASK)) != HT_CAP_CHECK_MASK)) {
+				printf("ERR: Invalid HTCapInfo value\n");
+				goto done;
+			}
+			bss->ht_cap_info =
+				DEFAULT_HT_CAP_VALUE & ~HT_CAP_CONFIG_MASK;
+			bss->ht_cap_info |=
+				(t_u16)A2HEXDECIMAL(args[1]) &
+				HT_CAP_CONFIG_MASK;
+			bss->ht_cap_info = uap_cpu_to_le16(bss->ht_cap_info);
+		}
+		if (strcmp(args[0], "AMPDU") == 0) {
+			if (enable_11n <= 0) {
+				printf("ERR: Enable11n parameter should be set before AMPDU.\n");
+				goto done;
+			}
+			if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) ||
+			    ((A2HEXDECIMAL(args[1])) > AMPDU_CONFIG_MASK)) {
+				printf("ERR: Invalid AMPDU value\n");
+				goto done;
+			}
+			/* Find HT tlv pointer in buffer and set AMPDU */
+			bss->ampdu_param =
+				(t_u8)A2HEXDECIMAL(args[1]) & AMPDU_CONFIG_MASK;
+		}
+		if (strcmp(args[0], "HT_MCS_MAP") == 0) {
+			if (enable_11n <= 0) {
+				printf("ERR: Enable11n parameter should be set before HT_MCS_MAP.\n");
+				goto done;
+			}
+			if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE)) {
+				printf("ERR: Invalid HT_MCS_MAP value\n");
+				goto done;
+			}
+			if (0 == get_fw_info(&fw)) {
+				/* Check upper nibble of MCS support value
+				 * and block MCS_SET_1 when 2X2 is not supported
+				 * by the underlying hardware */
+				if (((fw.hw_dev_mcs_support & 0xf0) <
+				     STREAM_2X2_MASK) &&
+				    (A2HEXDECIMAL(args[1]) & MCS_SET_1_MASK)) {
+					printf("ERR: Invalid HT_MCS_MAP\n");
+					goto done;
+				}
+			}
+			supported_mcs_set = (t_u32)A2HEXDECIMAL(args[1]);
+			supported_mcs_set = uap_cpu_to_le32(supported_mcs_set);
+			memcpy(bss->supported_mcs_set, &supported_mcs_set,
+			       sizeof(t_u32));
+		}
+		if (strcmp(args[0], "Enable2040Coex") == 0) {
+			if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) ||
+			    (atoi(args[1]) > 1)) {
+				printf("ERR:Invalid Enable2040Coex value.\n");
+				goto done;
+			}
+			bss->enable_2040coex = (t_u8)atoi(args[1]);
+		}
+	}
+done:
+	fclose(config_file);
+	if (line)
+		free(line);
+	return retval;
+}
+
+/**
+ *  @brief Show all the BSS configuration in the buffer
+ *
+ *  @param buf     Pointer to BSS configuration buffer
+ *
+ *  $return         N/A
+ */
+void
+print_bss_config(bss_config_t *buf)
+{
+	int i = 0;
+	int flag = 0;
+
+	if (!buf) {
+		printf("ERR:Empty BSS config!\n");
+		return;
+	}
+
+	/* Print AP MAC address */
+	printf("AP MAC address = ");
+	print_mac(buf->mac_addr);
+	printf("\n");
+
+	/* Print SSID */
+	if (buf->ssid.ssid_len) {
+		printf("SSID = %s\n", buf->ssid.ssid);
+	}
+
+	/* Print broadcast SSID control */
+	printf("SSID broadcast = %s\n",
+	       (buf->bcast_ssid_ctl == 1) ? "enabled" : "disabled");
+
+	/* Print DTIM period */
+	printf("DTIM period = %d\n", buf->dtim_period);
+
+	/* Print beacon period */
+	printf("Beacon period = %d\n", buf->beacon_period);
+
+	/* Print rates */
+	printf("Basic Rates =");
+	for (i = 0; i < MAX_DATA_RATES; i++) {
+		if (!buf->rates[i])
+			break;
+		if (buf->rates[i] > (BASIC_RATE_SET_BIT - 1)) {
+			flag = flag ? : 1;
+			printf(" 0x%x", buf->rates[i]);
+		}
+	}
+	printf("%s\nNon-Basic Rates =", flag ? "" : " ( none ) ");
+	for (flag = 0, i = 0; i < MAX_DATA_RATES; i++) {
+		if (!buf->rates[i])
+			break;
+		if (buf->rates[i] < BASIC_RATE_SET_BIT) {
+			flag = flag ? : 1;
+			printf(" 0x%x", buf->rates[i]);
+		}
+	}
+	printf("%s\n", flag ? "" : " ( none ) ");
+
+	/* Print Tx data rate */
+	printf("Tx data rate = ");
+	if (buf->tx_data_rate == 0)
+		printf("auto\n");
+	else
+		printf("0x%x\n", buf->tx_data_rate);
+
+	/* Print MCBC data rate */
+	printf("MCBC data rate = ");
+	if (buf->mcbc_data_rate == 0)
+		printf("auto\n");
+	else
+		printf("0x%x\n", buf->mcbc_data_rate);
+
+	/* Print Tx power level */
+	printf("Tx power = %d dBm\n", buf->tx_power_level);
+
+	/* Print Tx antenna */
+	printf("Tx antenna = %s\n", (buf->tx_antenna) ? "B" : "A");
+
+	/* Print Rx antenna */
+	printf("Rx antenna = %s\n", (buf->rx_antenna) ? "B" : "A");
+
+	/* Print packet forward control */
+	printf("%s handles packet forwarding -\n",
+	       ((buf->pkt_forward_ctl & PKT_FWD_FW_BIT) ==
+		0) ? "Host" : "Firmware");
+	printf("\tIntra-BSS broadcast packets are %s\n",
+	       ((buf->pkt_forward_ctl & PKT_FWD_INTRA_BCAST) ==
+		0) ? "allowed" : "denied");
+	printf("\tIntra-BSS unicast packets are %s\n",
+	       ((buf->pkt_forward_ctl & PKT_FWD_INTRA_UCAST) ==
+		0) ? "allowed" : "denied");
+	printf("\tInter-BSS unicast packets are %s\n",
+	       ((buf->pkt_forward_ctl & PKT_FWD_INTER_UCAST) ==
+		0) ? "allowed" : "denied");
+
+	/* Print maximum STA count */
+	printf("Max Station Number configured = %d\n", buf->max_sta_count);
+
+	/* Print mgmt frame FWD control */
+	printf("MGMT frame Fwd Control = 0x%x\n", buf->mgmt_ie_passthru_mask);
+
+	/* Print MAC filter */
+	if (buf->filter.filter_mode == 0) {
+		printf("Filter Mode = Filter table is disabled\n");
+	} else {
+		if (buf->filter.filter_mode == 1) {
+			printf("Filter Mode = Allow MAC addresses specified in the allowed list\n");
+		} else if (buf->filter.filter_mode == 2) {
+			printf("Filter Mode = Block MAC addresses specified in the banned list\n");
+		} else {
+			printf("Filter Mode = Unknown\n");
+		}
+		for (i = 0; i < buf->filter.mac_count; i++) {
+			printf("MAC_%d = ", i);
+			print_mac(buf->filter.mac_list[i]);
+			printf("\n");
+		}
+	}
+
+	/* Print STA ageout timer */
+	printf("STA ageout timer = %d\n", buf->sta_ageout_timer);
+
+	/* Print PS STA ageout timer */
+	printf("PS STA ageout timer = %d\n", buf->ps_sta_ageout_timer);
+
+	/* Print RTS threshold */
+	printf("RTS threshold = %d\n", buf->rts_threshold);
+
+	/* Print Fragmentation threshold */
+	printf("Fragmentation threshold = %d\n", buf->frag_threshold);
+
+	/* Print retry limit */
+	printf("Retry Limit = %d\n", buf->retry_limit);
+
+	/* Print preamble type */
+	printf("Preamble type = %s\n", (buf->preamble_type == 0) ?
+	       "auto" : ((buf->preamble_type == 1) ? "short" : "long"));
+
+	/* Print channel */
+	printf("Channel = %d\n", buf->channel);
+	printf("Band = %s\n",
+	       (buf->bandcfg.chanBand == BAND_5GHZ) ? "5GHz" : "2.4GHz");
+	printf("Channel Select Mode = %s\n",
+	       (buf->bandcfg.scanMode == SCAN_MODE_ACS) ? "ACS" : "Manual");
+	if (buf->bandcfg.chan2Offset == SEC_CHAN_NONE)
+		printf("no secondary channel\n");
+	else if (buf->bandcfg.chan2Offset == SEC_CHAN_ABOVE)
+		printf("secondary channel is above primary channel\n");
+	else if (buf->bandcfg.chan2Offset == SEC_CHAN_BELOW)
+		printf("secondary channel is below primary channel\n");
+
+	/* Print channel list */
+	printf("Channels List = ");
+	for (i = 0; (unsigned int)i < buf->num_of_chan; i++) {
+		printf("\n%d\t%sGHz", buf->chan_list[i].chan_number,
+		       (buf->chan_list[i].bandcfg.chanBand ==
+			BAND_5GHZ) ? "5" : "2.4");
+	}
+	printf("\n");
+
+	/* Print auth mode */
+	switch (buf->auth_mode) {
+	case 0:
+		printf("AUTHMODE = Open authentication\n");
+		break;
+	case 1:
+		printf("AUTHMODE = Shared key authentication\n");
+		break;
+	case 255:
+		printf("AUTHMODE = Auto (open and shared key)\n");
+		break;
+	default:
+		printf("ERR: Invalid authmode=%d\n", buf->auth_mode);
+		break;
+	}
+
+	/* Print protocol */
+	switch (buf->protocol) {
+	case 0:
+	case PROTOCOL_NO_SECURITY:
+		printf("PROTOCOL = No security\n");
+		break;
+	case PROTOCOL_STATIC_WEP:
+		printf("PROTOCOL = Static WEP\n");
+		break;
+	case PROTOCOL_WPA:
+		printf("PROTOCOL = WPA \n");
+		break;
+	case PROTOCOL_WPA2:
+		printf("PROTOCOL = WPA2 \n");
+		break;
+	case PROTOCOL_WPA | PROTOCOL_WPA2:
+		printf("PROTOCOL = WPA/WPA2 \n");
+		break;
+	default:
+		printf("Unknown PROTOCOL: 0x%x \n", buf->protocol);
+		break;
+	}
+
+	/* Print key management */
+	if (buf->key_mgmt == KEY_MGMT_PSK)
+		printf("KeyMgmt = PSK\n");
+	else
+		printf("KeyMgmt = NONE\n");
+
+	/* Print WEP configurations */
+	if (buf->wep_cfg.key0.length) {
+		printf("WEP KEY_0 = ");
+		for (i = 0; i < buf->wep_cfg.key0.length; i++) {
+			printf("%02x ", buf->wep_cfg.key0.key[i]);
+		}
+		(buf->wep_cfg.key0.
+		 is_default) ? (printf("<Default>\n")) : (printf("\n"));
+	} else {
+		printf("WEP KEY_0 = NONE\n");
+	}
+	if (buf->wep_cfg.key1.length) {
+		printf("WEP KEY_1 = ");
+		for (i = 0; i < buf->wep_cfg.key1.length; i++) {
+			printf("%02x ", buf->wep_cfg.key1.key[i]);
+		}
+		(buf->wep_cfg.key1.
+		 is_default) ? (printf("<Default>\n")) : (printf("\n"));
+	} else {
+		printf("WEP KEY_1 = NONE\n");
+	}
+	if (buf->wep_cfg.key2.length) {
+		printf("WEP KEY_2 = ");
+		for (i = 0; i < buf->wep_cfg.key2.length; i++) {
+			printf("%02x ", buf->wep_cfg.key2.key[i]);
+		}
+		(buf->wep_cfg.key2.
+		 is_default) ? (printf("<Default>\n")) : (printf("\n"));
+	} else {
+		printf("WEP KEY_2 = NONE\n");
+	}
+	if (buf->wep_cfg.key3.length) {
+		printf("WEP KEY_3 = ");
+		for (i = 0; i < buf->wep_cfg.key3.length; i++) {
+			printf("%02x ", buf->wep_cfg.key3.key[i]);
+		}
+		(buf->wep_cfg.key3.
+		 is_default) ? (printf("<Default>\n")) : (printf("\n"));
+	} else {
+		printf("WEP KEY_3 = NONE\n");
+	}
+
+	/* Print WPA configurations */
+	if (buf->protocol & PROTOCOL_WPA) {
+		switch (buf->wpa_cfg.pairwise_cipher_wpa) {
+		case CIPHER_TKIP:
+			printf("PwkCipherWPA = TKIP\n");
+			break;
+		case CIPHER_AES_CCMP:
+			printf("PwkCipherWPA = AES CCMP\n");
+			break;
+		case CIPHER_TKIP | CIPHER_AES_CCMP:
+			printf("PwkCipherWPA = TKIP + AES CCMP\n");
+			break;
+		case CIPHER_NONE:
+			printf("PwkCipherWPA =  None\n");
+			break;
+		default:
+			printf("Unknown PwkCipherWPA 0x%x\n",
+			       buf->wpa_cfg.pairwise_cipher_wpa);
+			break;
+		}
+	}
+	if (buf->protocol & PROTOCOL_WPA2) {
+		switch (buf->wpa_cfg.pairwise_cipher_wpa2) {
+		case CIPHER_TKIP:
+			printf("PwkCipherWPA2 = TKIP\n");
+			break;
+		case CIPHER_AES_CCMP:
+			printf("PwkCipherWPA2 = AES CCMP\n");
+			break;
+		case CIPHER_TKIP | CIPHER_AES_CCMP:
+			printf("PwkCipherWPA2 = TKIP + AES CCMP\n");
+			break;
+		case CIPHER_NONE:
+			printf("PwkCipherWPA2 =  None\n");
+			break;
+		default:
+			printf("Unknown PwkCipherWPA2 0x%x\n",
+			       buf->wpa_cfg.pairwise_cipher_wpa2);
+			break;
+		}
+	}
+	switch (buf->wpa_cfg.group_cipher) {
+	case CIPHER_TKIP:
+		printf("GroupCipher = TKIP\n");
+		break;
+	case CIPHER_AES_CCMP:
+		printf("GroupCipher = AES CCMP\n");
+		break;
+	case CIPHER_NONE:
+		printf("GroupCipher = None\n");
+		break;
+	default:
+		printf("Unknown Group cipher 0x%x\n",
+		       buf->wpa_cfg.group_cipher);
+		break;
+	}
+	printf("RSN replay protection = %s\n",
+	       (buf->wpa_cfg.rsn_protection) ? "enabled" : "disabled");
+	printf("Pairwise Handshake timeout = %d\n",
+	       buf->pairwise_update_timeout);
+	printf("Pairwise Handshake Retries = %d\n", buf->pwk_retries);
+	printf("Groupwise Handshake timeout = %d\n",
+	       buf->groupwise_update_timeout);
+	printf("Groupwise Handshake Retries = %d\n", buf->gwk_retries);
+	if (buf->wpa_cfg.length > 0) {
+		printf("WPA passphrase = ");
+		for (i = 0; (unsigned int)i < buf->wpa_cfg.length; i++)
+			printf("%c", buf->wpa_cfg.passphrase[i]);
+		printf("\n");
+	} else {
+		printf("WPA passphrase = None\n");
+	}
+	if (buf->wpa_cfg.gk_rekey_time == 0)
+		printf("Group re-key time = disabled\n");
+	else
+		printf("Group re-key time = %d second\n",
+		       buf->wpa_cfg.gk_rekey_time);
+	printf("20/40 coex = %s\n",
+	       (buf->enable_2040coex) ? "enabled" : "disabled");
+	printf("wmm parameters:\n");
+	printf("\tqos_info = 0x%x\n", buf->wmm_para.qos_info);
+	printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+	       buf->wmm_para.ac_params[AC_BE].aci_aifsn.aifsn,
+	       buf->wmm_para.ac_params[AC_BE].ecw.ecw_max,
+	       buf->wmm_para.ac_params[AC_BE].ecw.ecw_min,
+	       buf->wmm_para.ac_params[AC_BE].tx_op_limit);
+	printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+	       buf->wmm_para.ac_params[AC_BK].aci_aifsn.aifsn,
+	       buf->wmm_para.ac_params[AC_BK].ecw.ecw_max,
+	       buf->wmm_para.ac_params[AC_BK].ecw.ecw_min,
+	       buf->wmm_para.ac_params[AC_BK].tx_op_limit);
+	printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+	       buf->wmm_para.ac_params[AC_VI].aci_aifsn.aifsn,
+	       buf->wmm_para.ac_params[AC_VI].ecw.ecw_max,
+	       buf->wmm_para.ac_params[AC_VI].ecw.ecw_min,
+	       buf->wmm_para.ac_params[AC_VI].tx_op_limit);
+	printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+	       buf->wmm_para.ac_params[AC_VO].aci_aifsn.aifsn,
+	       buf->wmm_para.ac_params[AC_VO].ecw.ecw_max,
+	       buf->wmm_para.ac_params[AC_VO].ecw.ecw_min,
+	       buf->wmm_para.ac_params[AC_VO].tx_op_limit);
+
+	return;
+}
+
+/**
+ *  @brief Send command to Read the BSS profile
+ *
+ *  @param buf      Pointer to bss command buffer for get
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+static int
+get_bss_config(t_u8 *buf)
+{
+	apcmdbuf_bss_configure *cmd_buf = NULL;
+	t_s32 sockfd;
+	struct ifreq ifr;
+
+	cmd_buf = (apcmdbuf_bss_configure *)buf;
+	cmd_buf->action = ACTION_GET;
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+#if DEBUG
+	/* Dump request buffer */
+	hexdump("Get Request buffer", (void *)buf,
+		sizeof(apcmdbuf_bss_configure)
+		+ sizeof(bss_config_t), ' ');
+#endif
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)cmd_buf;
+	if (ioctl(sockfd, UAP_BSS_CONFIG, &ifr)) {
+		printf("ERR:UAP_BSS_CONFIG is not supported by %s\n", dev_name);
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+#if DEBUG
+	/* Dump request buffer */
+	hexdump("Get Response buffer", (void *)buf,
+		sizeof(apcmdbuf_bss_configure)
+		+ sizeof(bss_config_t), ' ');
+#endif
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Creates a bss_config request and sends to the driver
+ *
+ *  Usage: "Usage : bss_config [CONFIG_FILE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_bss_config(int argc, char *argv[])
+{
+	apcmdbuf_bss_configure *cmd_buf = NULL;
+	bss_config_t *bss = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len;
+	t_u16 buf_len;
+	int ret = UAP_SUCCESS;
+	int opt;
+	t_s32 sockfd;
+	struct ifreq ifr;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_bss_config_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc > 1) {
+		printf("ERR:Too many arguments.\n");
+		print_bss_config_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Query BSS settings */
+
+	/* Alloc buf for command */
+	buf_len = sizeof(apcmdbuf_bss_configure) + sizeof(bss_config_t);
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset((char *)buf, 0, buf_len);
+
+	/* Locate headers */
+	cmd_len = sizeof(apcmdbuf_bss_configure);
+	cmd_buf = (apcmdbuf_bss_configure *)buf;
+	bss = (bss_config_t *)(buf + cmd_len);
+
+	/* Get all parametes first */
+	if (get_bss_config(buf) == UAP_FAILURE) {
+		printf("ERR:Reading current parameters\n");
+		free(buf);
+		return UAP_FAILURE;
+	}
+
+	if (argc == 1) {
+		/* Parse config file and populate structure */
+		ret = parse_bss_config(argc, argv, bss);
+		if (ret == UAP_FAILURE) {
+			free(buf);
+			return ret;
+		}
+		cmd_len += sizeof(bss_config_t);
+		cmd_buf->action = ACTION_SET;
+
+		/* Send the command */
+		/* Open socket */
+		if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+			printf("ERR:Cannot open socket\n");
+			free(buf);
+			return UAP_FAILURE;
+		}
+
+		/* Initialize the ifr structure */
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+		ifr.ifr_ifru.ifru_data = (void *)cmd_buf;
+#if DEBUG
+		/* Dump request buffer */
+		hexdump("Request buffer", (void *)buf, buf_len, ' ');
+#endif
+		if (ioctl(sockfd, UAP_BSS_CONFIG, &ifr)) {
+			perror("");
+			printf("ERR:UAP_BSS_CONFIG is not supported by %s\n",
+			       dev_name);
+			close(sockfd);
+			free(buf);
+			return UAP_FAILURE;
+		}
+#if DEBUG
+		/* Dump respond buffer */
+		hexdump("Respond buffer", (void *)buf, buf_len, ' ');
+#endif
+		close(sockfd);
+	} else {
+		/* Print response */
+		printf("BSS settings:\n");
+		print_bss_config(bss);
+	}
+
+	free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Read the profile and sends to the driver
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+apcmd_coex_config_profile(int argc, char *argv[])
+{
+	FILE *config_file = NULL;
+	char *line = NULL;
+	int i, index, li = 0;
+	int ret = UAP_SUCCESS;
+	char *pos = NULL;
+	int arg_num = 0;
+	char *args[30];
+	int is_coex_config = 0;
+	int is_coex_common_config = 0;
+	int is_coex_sco_config = 0;
+	int is_coex_acl_config = 0;
+	t_u8 *buf = NULL;
+	apcmdbuf_coex_config *cmd_buf = NULL;
+	tlvbuf_coex_common_cfg *coex_common_tlv;
+	tlvbuf_coex_sco_cfg *coex_sco_tlv;
+	tlvbuf_coex_acl_cfg *coex_acl_tlv;
+	t_u16 acl_enabled = 0;
+	t_u32 conf_bitmap = 0;
+	t_u32 ap_coex_enable = 0;
+	t_u16 cmd_len = 0, tlv_len = 0;
+	t_u16 sco_prot_qtime[4] = { 0, 0, 0, 0 }, sco_prot_rate =
+		0, sco_acl_freq = 0;
+	t_u16 acl_bt_time = 0, acl_wlan_time = 0, acl_prot_rate = 0;
+
+	/* Check if file exists */
+	config_file = fopen(argv[0], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return UAP_FAILURE;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		ret = UAP_FAILURE;
+		goto done;
+	}
+	bzero(line, MAX_CONFIG_LINE);
+
+	/* fixed command length */
+	cmd_len = sizeof(apcmdbuf_coex_config) + sizeof(tlvbuf_coex_common_cfg)
+		+ sizeof(tlvbuf_coex_sco_cfg) + sizeof(tlvbuf_coex_acl_cfg);
+	/* alloc buf for command */
+	buf = (t_u8 *)malloc(cmd_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		ret = UAP_FAILURE;
+		goto done;
+	}
+	bzero((char *)buf, cmd_len);
+
+	cmd_buf = (apcmdbuf_coex_config *)buf;
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = HostCmd_ROBUST_COEX;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = uap_cpu_to_le16(ACTION_SET);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+#if DEBUG
+		uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n",
+			   li, line);
+#endif
+		arg_num = parse_line(line, args);
+#if DEBUG
+		uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n",
+			   arg_num);
+		for (i = 0; i < arg_num; i++) {
+			uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1,
+				   args[i]);
+		}
+#endif
+		/* Check for end of Coex configurations */
+		if (is_coex_acl_config == 1) {
+			if (strcmp(args[0], "}") == 0) {
+				coex_acl_tlv =
+					(tlvbuf_coex_acl_cfg *)(cmd_buf->
+								tlv_buffer +
+								tlv_len);
+				coex_acl_tlv->tag = MRVL_BT_COEX_ACL_CFG_TLV_ID;
+				coex_acl_tlv->length =
+					sizeof(tlvbuf_coex_acl_cfg) -
+					sizeof(tlvbuf_header);
+				endian_convert_tlv_header_out(coex_acl_tlv);
+				coex_acl_tlv->enabled =
+					uap_cpu_to_le16(acl_enabled);
+				coex_acl_tlv->bt_time =
+					uap_cpu_to_le16(acl_bt_time);
+				coex_acl_tlv->wlan_time =
+					uap_cpu_to_le16(acl_wlan_time);
+				coex_acl_tlv->protection_rate =
+					uap_cpu_to_le16(acl_prot_rate);
+				tlv_len += sizeof(tlvbuf_coex_acl_cfg);
+				is_coex_acl_config = 0;
+			}
+		} else if (is_coex_sco_config == 1) {
+			if (strcmp(args[0], "}") == 0) {
+				coex_sco_tlv =
+					(tlvbuf_coex_sco_cfg *)(cmd_buf->
+								tlv_buffer +
+								tlv_len);
+				coex_sco_tlv->tag = MRVL_BT_COEX_SCO_CFG_TLV_ID;
+				coex_sco_tlv->length =
+					sizeof(tlvbuf_coex_sco_cfg) -
+					sizeof(tlvbuf_header);
+				endian_convert_tlv_header_out(coex_sco_tlv);
+				for (i = 0; i < 4; i++)
+					coex_sco_tlv->protection_qtime[i] =
+						uap_cpu_to_le16(sco_prot_qtime
+								[i]);
+				coex_sco_tlv->protection_rate =
+					uap_cpu_to_le16(sco_prot_rate);
+				coex_sco_tlv->acl_frequency =
+					uap_cpu_to_le16(sco_acl_freq);
+				tlv_len += sizeof(tlvbuf_coex_sco_cfg);
+				is_coex_sco_config = 0;
+			}
+		} else if (is_coex_common_config == 1) {
+			if (strcmp(args[0], "}") == 0) {
+				coex_common_tlv =
+					(tlvbuf_coex_common_cfg *)(cmd_buf->
+								   tlv_buffer +
+								   tlv_len);
+				coex_common_tlv->tag =
+					MRVL_BT_COEX_COMMON_CFG_TLV_ID;
+				coex_common_tlv->length =
+					sizeof(tlvbuf_coex_common_cfg) -
+					sizeof(tlvbuf_header);
+				endian_convert_tlv_header_out(coex_common_tlv);
+				coex_common_tlv->config_bitmap =
+					uap_cpu_to_le32(conf_bitmap);
+				coex_common_tlv->ap_bt_coex =
+					uap_cpu_to_le32(ap_coex_enable);
+				tlv_len += sizeof(tlvbuf_coex_common_cfg);
+				is_coex_common_config = 0;
+			}
+		} else if (is_coex_config == 1) {
+			if (strcmp(args[0], "}") == 0)
+				is_coex_config = 0;
+		}
+		if (strcmp(args[0], "coex_config") == 0) {
+			is_coex_config = 1;
+		} else if (strcmp(args[0], "common_config") == 0) {
+			is_coex_common_config = 1;
+		} else if (strcmp(args[0], "sco_config") == 0) {
+			is_coex_sco_config = 1;
+		} else if (strcmp(args[0], "acl_config") == 0) {
+			is_coex_acl_config = 1;
+		}
+		if ((strcmp(args[0], "bitmap") == 0) && is_coex_common_config) {
+			if (is_input_valid
+			    (COEX_COMM_BITMAP, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			conf_bitmap = (t_u32)A2HEXDECIMAL(args[1]);
+		} else if ((strcmp(args[0], "APBTCoex") == 0) &&
+			   is_coex_common_config) {
+			if (is_input_valid
+			    (COEX_COMM_AP_COEX, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			ap_coex_enable = (t_u32)A2HEXDECIMAL(args[1]);
+		} else if ((strncmp(args[0], "protectionFromQTime", 19) == 0) &&
+			   is_coex_sco_config) {
+			index = atoi(args[0] + strlen("protectionFromQTime"));
+			if (index < 0 || index > 3) {
+				printf("ERR:Incorrect index %d.\n", index);
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			if (is_input_valid(COEX_PROTECTION, arg_num, args) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			sco_prot_qtime[index] = (t_u16)atoi(args[1]);
+		} else if ((strcmp(args[0], "scoProtectionFromRate") == 0) &&
+			   is_coex_sco_config) {
+			if (is_input_valid(COEX_PROTECTION, arg_num, args) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			sco_prot_rate = (t_u16)atoi(args[1]);
+		} else if ((strcmp(args[0], "aclFrequency") == 0) &&
+			   is_coex_sco_config) {
+			if (is_input_valid
+			    (COEX_SCO_ACL_FREQ, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			sco_acl_freq = (t_u16)atoi(args[1]);
+		} else if ((strcmp(args[0], "enabled") == 0) &&
+			   is_coex_acl_config) {
+			if (is_input_valid
+			    (COEX_ACL_ENABLED, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			acl_enabled = (t_u16)atoi(args[1]);
+		} else if ((strcmp(args[0], "btTime") == 0) &&
+			   is_coex_acl_config) {
+			if (is_input_valid
+			    (COEX_ACL_BT_TIME, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			acl_bt_time = (t_u16)atoi(args[1]);
+		} else if ((strcmp(args[0], "wlanTime") == 0) &&
+			   is_coex_acl_config) {
+			if (is_input_valid
+			    (COEX_ACL_WLAN_TIME, arg_num - 1,
+			     args + 1) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			acl_wlan_time = (t_u16)atoi(args[1]);
+		} else if ((strcmp(args[0], "aclProtectionFromRate") == 0) &&
+			   is_coex_acl_config) {
+			if (is_input_valid(COEX_PROTECTION, arg_num, args) !=
+			    UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+				goto done;
+			}
+			acl_prot_rate = (t_u16)atoi(args[1]);
+		}
+	}
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			ret = UAP_FAILURE;
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("BT Coex settings sucessfully set.\n");
+		} else {
+			printf("ERR:Could not set coex configuration.\n");
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	fclose(config_file);
+	if (buf)
+		free(buf);
+	if (line)
+		free(line);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the coex_config command
+ *
+ *  $return         N/A
+ */
+void
+print_coex_config_usage(void)
+{
+	printf("\nUsage : coex_config [CONFIG_FILE]\n");
+	printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Creates a coex_config request and sends to the driver
+ *
+ *  Usage: "Usage : coex_config [CONFIG_FILE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+apcmd_coex_config(int argc, char *argv[])
+{
+	apcmdbuf_coex_config *cmd_buf = NULL;
+	tlvbuf_coex_common_cfg *coex_common_tlv;
+	tlvbuf_coex_sco_cfg *coex_sco_tlv;
+	tlvbuf_coex_acl_cfg *coex_acl_tlv;
+	tlvbuf_coex_stats *coex_stats_tlv;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_coex_config_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc > 1) {
+		printf("ERR:Too many arguments.\n");
+		print_coex_config_usage();
+		return UAP_FAILURE;
+	}
+	if (argc == 1) {
+		/* Read profile and send command to firmware */
+		ret = apcmd_coex_config_profile(argc, argv);
+		return ret;
+	}
+
+	/* fixed command length */
+	cmd_len = sizeof(apcmdbuf_coex_config) + sizeof(tlvbuf_coex_common_cfg)
+		+ sizeof(tlvbuf_coex_sco_cfg) + sizeof(tlvbuf_coex_acl_cfg)
+		+ sizeof(tlvbuf_coex_stats);
+	/* alloc buf for command */
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	bzero((char *)buf, buf_len);
+
+	cmd_buf = (apcmdbuf_coex_config *)buf;
+
+	coex_common_tlv = (tlvbuf_coex_common_cfg *)cmd_buf->tlv_buffer;
+	coex_common_tlv->tag = MRVL_BT_COEX_COMMON_CFG_TLV_ID;
+	coex_common_tlv->length =
+		sizeof(tlvbuf_coex_common_cfg) - sizeof(tlvbuf_header);
+	endian_convert_tlv_header_out(coex_common_tlv);
+
+	coex_sco_tlv = (tlvbuf_coex_sco_cfg *)(cmd_buf->tlv_buffer +
+					       sizeof(tlvbuf_coex_common_cfg));
+	coex_sco_tlv->tag = MRVL_BT_COEX_SCO_CFG_TLV_ID;
+	coex_sco_tlv->length =
+		sizeof(tlvbuf_coex_sco_cfg) - sizeof(tlvbuf_header);
+	endian_convert_tlv_header_out(coex_sco_tlv);
+
+	coex_acl_tlv = (tlvbuf_coex_acl_cfg *)(cmd_buf->tlv_buffer +
+					       sizeof(tlvbuf_coex_common_cfg) +
+					       sizeof(tlvbuf_coex_sco_cfg));
+	coex_acl_tlv->tag = MRVL_BT_COEX_ACL_CFG_TLV_ID;
+	coex_acl_tlv->length =
+		sizeof(tlvbuf_coex_acl_cfg) - sizeof(tlvbuf_header);
+	endian_convert_tlv_header_out(coex_acl_tlv);
+
+	coex_stats_tlv = (tlvbuf_coex_stats *)(cmd_buf->tlv_buffer +
+					       sizeof(tlvbuf_coex_common_cfg) +
+					       sizeof(tlvbuf_coex_sco_cfg)
+					       + sizeof(tlvbuf_coex_acl_cfg));
+	coex_stats_tlv->tag = MRVL_BT_COEX_STATS_TLV_ID;
+	coex_stats_tlv->length =
+		sizeof(tlvbuf_coex_stats) - sizeof(tlvbuf_header);
+	endian_convert_tlv_header_out(coex_stats_tlv);
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = HostCmd_ROBUST_COEX;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = uap_cpu_to_le16(ACTION_GET);
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			free(buf);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("BT Coex settings:\n");
+			print_tlv(buf + sizeof(apcmdbuf_coex_config),
+				  cmd_buf->size - sizeof(apcmdbuf_coex_config) +
+				  BUF_HEADER_SIZE);
+		} else {
+			printf("ERR:Could not retrieve coex configuration.\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_custom_ie
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_custom_ie_usage(void)
+{
+	printf("\nUsage : sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]");
+	printf("\n         empty - Get all IE settings\n");
+	printf("\n         INDEX:  0 - Get/Set IE index 0 setting");
+	printf("\n                 1 - Get/Set IE index 1 setting");
+	printf("\n                 2 - Get/Set IE index 2 setting");
+	printf("\n                 3 - Get/Set IE index 3 setting");
+	printf("\n                 .                             ");
+	printf("\n                 .                             ");
+	printf("\n                 .                             ");
+	printf("\n                -1 - Append/Delete IE automatically");
+	printf("\n                     Delete will delete the IE from the matching IE buffer");
+	printf("\n                     Append will append the IE to the buffer with the same mask");
+	printf("\n         MASK :  Management subtype mask value as per bit defintions");
+	printf("\n              :  Bit 0 - Association request.");
+	printf("\n              :  Bit 1 - Association response.");
+	printf("\n              :  Bit 2 - Reassociation request.");
+	printf("\n              :  Bit 3 - Reassociation response.");
+	printf("\n              :  Bit 4 - Probe request.");
+	printf("\n              :  Bit 5 - Probe response.");
+	printf("\n              :  Bit 8 - Beacon.");
+	printf("\n         MASK :  MASK = 0 to clear the mask and the IE buffer");
+	printf("\n         IEBuffer :  IE Buffer in hex (max 256 bytes)\n\n");
+	return;
+}
+
+/** custom IE, auto mask value */
+#define	UAP_CUSTOM_IE_AUTO_MASK	0xffff
+
+/**
+ *  @brief Get max management IE index
+ *  @param         max_mgmt_ie
+ *  @param         print flag
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+static int
+get_max_mgmt_ie(int *max_mgmt_ie, int flag)
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_max_mgmt_ie *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0, i = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+
+	*max_mgmt_ie = 0;
+	/* Initialize the command length */
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_max_mgmt_ie);
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_max_mgmt_ie *)(buffer + sizeof(apcmdbuf_sys_configure));
+
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_MAX_MGMT_IE_TLV_ID;
+	tlv->length = 0;
+	cmd_buf->action = ACTION_GET;
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_MAX_MGMT_IE_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			tlv->count = uap_le16_to_cpu(tlv->count);
+			for (i = 0; i < tlv->count; i++) {
+				tlv->info[i].buf_size =
+					uap_le16_to_cpu(tlv->info[i].buf_size);
+				tlv->info[i].buf_count =
+					uap_le16_to_cpu(tlv->info[i].buf_count);
+				*max_mgmt_ie += tlv->info[i].buf_count;
+				if (flag) {
+					printf("buf%d_size = %d\n", i,
+					       tlv->info[i].buf_size);
+					printf("number of buffers = %d\n",
+					       tlv->info[i].buf_count);
+					printf("\n");
+				}
+			}
+		} else {
+			printf("ERR:Could not get max_mgmt_ie_index!\n");
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for custom IE settings
+ *   and sends to the driver
+ *
+ *   Usage: "sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]"
+ *
+ *   Options: INDEX :      0 - Get/Set IE index 0 setting
+ *                         1 - Get/Set IE index 1 setting
+ *                         2 - Get/Set IE index 2 setting
+ *                         3 - Get/Set IE index 3 setting
+ *                         .
+ *                         .
+ *                         .
+ *            MASK  :      Management subtype mask value
+ *            IEBuffer:      IE Buffer in hex
+ *            empty - Get all IE settings
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_custom_ie(int argc, char *argv[])
+{
+	tlvbuf_custom_ie *tlv = NULL;
+	tlvbuf_max_mgmt_ie *max_mgmt_ie_tlv = NULL;
+	custom_ie *ie_ptr = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 buf_len = 0;
+	t_u16 mgmt_subtype_mask = 0;
+	int ie_buf_len = 0, ie_len = 0, i = 0, max_mgmt_ie = 0, print_flag = 0;
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	if (argc == 1 && max_mgmt_ie_print == 0) {
+		/* Print buffer sizes only if (argc == 1) i.e. get all indices one by one
+		 * && (max_mgmt_ie_print == 0) i.e. max mgmt IE is not printed via sys_config cmd */
+		print_flag = 1;
+	}
+
+	/* Reset the max_mgmt_ie_print for successive cmds */
+	max_mgmt_ie_print = 0;
+
+	if (!get_max_mgmt_ie(&max_mgmt_ie, print_flag)) {
+		printf("ERR:couldn't get max_mgmt_ie!\n");
+		return UAP_FAILURE;
+	}
+	if (max_mgmt_ie == 0) {
+		max_mgmt_ie = MAX_MGMT_IE_INDEX;
+#if DEBUG
+		uap_printf(MSG_DEBUG,
+			   "WARN: max_mgmt_ie=0, defaulting to MAX_MGMT_IE_INDEX\n");
+#endif
+	}
+
+	/* Check arguments */
+	if (argc > 4) {
+		printf("ERR:Too many arguments.\n");
+		print_sys_cfg_custom_ie_usage();
+		return UAP_FAILURE;
+	}
+
+	/* Error checks and initialize the command length */
+	if (argc >= 2) {
+		if (((IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) &&
+		     (atoi(argv[1]) != -1)) || (atoi(argv[1]) < -1)) {
+			printf("ERR:Illegal index %s\n", argv[1]);
+			print_sys_cfg_custom_ie_usage();
+			return UAP_FAILURE;
+		}
+	}
+	switch (argc) {
+	case 1:
+		buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+		break;
+	case 2:
+		if ((atoi(argv[1]) < 0) || (atoi(argv[1]) >= max_mgmt_ie)) {
+			printf("ERR:Illegal index %s. Must be either greater than or equal to 0 and less than %d for Get Operation \n", argv[1], max_mgmt_ie);
+			print_sys_cfg_custom_ie_usage();
+			return UAP_FAILURE;
+		}
+		buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+		break;
+	case 3:
+		if (UAP_FAILURE == ishexstring(argv[2]) ||
+		    A2HEXDECIMAL(argv[2]) != 0) {
+			printf("ERR: Mask value should be 0 to clear IEBuffers.\n");
+			print_sys_cfg_custom_ie_usage();
+			return UAP_FAILURE;
+		}
+		if (atoi(argv[1]) == -1) {
+			printf("ERR: Buffer should be provided for automatic deletion.\n");
+			print_sys_cfg_custom_ie_usage();
+			return UAP_FAILURE;
+		}
+		buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie);
+		break;
+	case 4:
+		/* This is to check negative numbers and special symbols */
+		if (UAP_FAILURE == IS_HEX_OR_DIGIT(argv[2])) {
+			printf("ERR:Mask value must be 0 or hex digits\n");
+			print_sys_cfg_custom_ie_usage();
+			return UAP_FAILURE;
+		}
+		/* If above check is passed and mask is not hex, then it must be 0 */
+		if ((ISDIGIT(argv[2]) == UAP_SUCCESS) && atoi(argv[2])) {
+			printf("ERR:Mask value must be 0 or hex digits\n ");
+			print_sys_cfg_custom_ie_usage();
+			return UAP_FAILURE;
+		}
+		if (UAP_FAILURE == ishexstring(argv[3])) {
+			printf("ERR:Only hex digits are allowed\n");
+			print_sys_cfg_custom_ie_usage();
+			return UAP_FAILURE;
+		}
+		ie_buf_len = strlen(argv[3]);
+		if (!strncasecmp("0x", argv[3], 2)) {
+			ie_len = (ie_buf_len - 2 + 1) / 2;
+			argv[3] += 2;
+		} else
+			ie_len = (ie_buf_len + 1) / 2;
+		if (ie_len > MAX_IE_BUFFER_LEN) {
+			printf("ERR:Incorrect IE length %d\n", ie_buf_len);
+			print_sys_cfg_custom_ie_usage();
+			return UAP_FAILURE;
+		}
+		mgmt_subtype_mask = (t_u16)A2HEXDECIMAL(argv[2]);
+		buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie) + ie_len;
+		break;
+	}
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+	tlv = (tlvbuf_custom_ie *)buffer;
+	tlv->tag = MRVL_MGMT_IE_LIST_TLV_ID;
+	if (argc == 1 || argc == 2) {
+		if (argc == 1)
+			tlv->length = 0;
+		else {
+			tlv->length = sizeof(t_u16);
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			ie_ptr->ie_index = (t_u16)(atoi(argv[1]));
+		}
+	} else {
+		/* Locate headers */
+		ie_ptr = (custom_ie *)(tlv->ie_data);
+		/* Set TLV fields */
+		tlv->length = sizeof(custom_ie) + ie_len;
+		ie_ptr->ie_index = atoi(argv[1]);
+		ie_ptr->mgmt_subtype_mask = mgmt_subtype_mask;
+		ie_ptr->ie_length = ie_len;
+		if (argc == 4)
+			string2raw(argv[3], ie_ptr->ie_buffer);
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		if (buffer)
+			free(buffer);
+		return UAP_FAILURE;
+	}
+	if (argc != 1) {
+		/* Initialize the ifr structure */
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+		ifr.ifr_ifru.ifru_data = (void *)buffer;
+		/* Perform ioctl */
+		if (ioctl(sockfd, UAP_CUSTOM_IE, &ifr)) {
+			if (errno < 0) {
+				perror("ioctl[UAP_CUSTOM_IE]");
+				printf("ERR:Command sending failed!\n");
+			} else {
+				printf("custom IE configuration failed!\n");
+			}
+			close(sockfd);
+			if (buffer)
+				free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (argc > 2) {
+			printf("custom IE setting successful\n");
+		} else {
+			printf("Querying custom IE successful\n");
+			tlv = (tlvbuf_custom_ie *)buffer;
+			ie_len = tlv->length;
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) {
+				while ((unsigned int)ie_len >=
+				       sizeof(custom_ie)) {
+					printf("Index [%d]\n",
+					       ie_ptr->ie_index);
+					if (ie_ptr->ie_length)
+						printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask == 0 ? UAP_CUSTOM_IE_AUTO_MASK : ie_ptr->mgmt_subtype_mask);
+					else
+						printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask);
+					hexdump_data("IE Buffer",
+						     (void *)ie_ptr->ie_buffer,
+						     (ie_ptr->ie_length), ' ');
+					ie_len -=
+						sizeof(custom_ie) +
+						ie_ptr->ie_length;
+					ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+							       sizeof(custom_ie)
+							       +
+							       ie_ptr->
+							       ie_length);
+				}
+			}
+			max_mgmt_ie_tlv =
+				(tlvbuf_max_mgmt_ie *)(buffer +
+						       sizeof(tlvbuf_custom_ie)
+						       + tlv->length);
+			if (max_mgmt_ie_tlv) {
+				if (max_mgmt_ie_tlv->tag ==
+				    MRVL_MAX_MGMT_IE_TLV_ID) {
+					for (i = 0; i < max_mgmt_ie_tlv->count;
+					     i++) {
+						printf("buf%d_size = %d\n", i,
+						       max_mgmt_ie_tlv->info[i].
+						       buf_size);
+						printf("number of buffers = %d\n", max_mgmt_ie_tlv->info[i].buf_count);
+						printf("\n");
+					}
+				}
+			}
+		}
+	}
+
+	/* Special handling for all indices: Get all IEs one-by-one */
+	if (argc == 1) {
+		for (i = 0; i < max_mgmt_ie; i++) {
+
+			tlv->length = sizeof(t_u16);
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			ie_ptr->ie_index = (t_u16)(i);
+
+			/* Initialize the ifr structure */
+			memset(&ifr, 0, sizeof(ifr));
+			strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+			ifr.ifr_ifru.ifru_data = (void *)buffer;
+			/* Perform ioctl */
+			if (ioctl(sockfd, UAP_CUSTOM_IE, &ifr)) {
+				if (errno < 0) {
+					perror("ioctl[UAP_CUSTOM_IE]");
+					printf("ERR:Command sending failed!\n");
+				} else {
+					printf("custom IE configuration failed!\n");
+				}
+				close(sockfd);
+				if (buffer)
+					free(buffer);
+				return UAP_FAILURE;
+			}
+			/* Print response */
+			tlv = (tlvbuf_custom_ie *)buffer;
+			ie_len = tlv->length;
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) {
+				while ((unsigned int)ie_len >=
+				       sizeof(custom_ie)) {
+					printf("Index [%d]\n",
+					       ie_ptr->ie_index);
+					if (ie_ptr->ie_length)
+						printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask == 0 ? UAP_CUSTOM_IE_AUTO_MASK : ie_ptr->mgmt_subtype_mask);
+					else
+						printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask);
+					hexdump_data("IE Buffer",
+						     (void *)ie_ptr->ie_buffer,
+						     (ie_ptr->ie_length), ' ');
+					ie_len -=
+						sizeof(custom_ie) +
+						ie_ptr->ie_length;
+					ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+							       sizeof(custom_ie)
+							       +
+							       ie_ptr->
+							       ie_length);
+				}
+			}
+		}
+		printf("Querying custom IE successful\n");
+	}
+
+	if (buffer)
+		free(buffer);
+
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ *  @brief Show usage information for the dfstesting command
+ *
+ *  $return         N/A
+ */
+void
+print_dfstesting_usage(void)
+{
+	printf("\nUsage : dfstesting [USER_CAC_PD  USER_NOP_PD  NO_CHAN_CHANGE  FIXED_CHAN_NUM]\n");
+	printf("\n         empty - Get all dfstesting settings\n");
+	printf("\n         USER_CAC_PD:  user configured Channel Availability Check period");
+	printf("\n                 0       - disable, use default (60000)");
+	printf("\n                 1-65535 - CAC period in msec");
+	printf("\n         USER_NOP_PD:  user configured Non-Occupancy Period");
+	printf("\n                 0       - disable, use default (1800)");
+	printf("\n                 1-65535 - NOP period in sec");
+	printf("\n         NO_CHAN_CHANGE:  user setting, don't change channel on radar");
+	printf("\n                 0        - disable, default behavior");
+	printf("\n                 non-zero - enable, overrides below setting");
+	printf("\n         FIXED_CHAN_NUM:  user fixed channel to change to on radar");
+	printf("\n                 0     - disable, use random channel [default]");
+	printf("\n                 1-255 - set fixed channel (not checked for validity)\n");
+	return;
+}
+
+/**
+ *  @brief user configuration of dfs testing settings
+ *
+ *   Usage: "dfstesting [USER_CAC_PD  USER_NOP_PD  NO_CHAN_CHANGE  FIXED_CHAN_NUM]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_dfstesting(int argc, char *argv[])
+{
+	int opt;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	t_u32 val;
+	dfs_testing_para dfs_test;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_dfstesting_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	memset(&dfs_test, 0x00, sizeof(dfs_test));
+
+	/* Check arguments */
+	if (argc == 0) {
+		dfs_test.action = ACTION_GET;
+	} else if (argc == 4) {
+		if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
+		    (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) ||
+		    (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) ||
+		    (IS_HEX_OR_DIGIT(argv[3]) == UAP_FAILURE)) {
+			printf("ERR: Only Number values are allowed\n");
+			print_dfstesting_usage();
+			return UAP_FAILURE;
+		}
+
+		val = A2HEXDECIMAL(argv[0]);
+		if (val > 0xfffff) {
+			printf("ERR: invalid user_cac_pd value!\n");
+			return UAP_FAILURE;
+		}
+		dfs_test.usr_cac_period = (t_u32)val;
+
+		val = A2HEXDECIMAL(argv[1]);
+		if (val > 0xffff) {
+			printf("ERR: invalid user_nop_pd value!\n");
+			return UAP_FAILURE;
+		}
+		dfs_test.usr_nop_period = (t_u16)val;
+
+		val = A2HEXDECIMAL(argv[2]);
+		dfs_test.no_chan_change = (t_u8)(val ? 1 : 0);
+
+		val = A2HEXDECIMAL(argv[3]);
+		if (val > 0xff) {
+			printf("ERR: invalid fixed_chan_num value!\n");
+			return UAP_FAILURE;
+		}
+		dfs_test.fixed_new_chan = (t_u8)val;
+		dfs_test.action = ACTION_SET;
+	} else {
+		printf("ERR: invalid number of arguments!  Must be 0 or 4.\n");
+		print_dfstesting_usage();
+		return UAP_FAILURE;
+	}
+	dfs_test.subcmd = UAP_DFS_TESTING;
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&dfs_test;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: UAP_DFS_TESTING is not supported by %s\n",
+		       dev_name);
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+
+	if (argc)
+		printf("DFS testing setting successful!\n");
+	else
+		printf("DFS testing settings:\n"
+		       "    user_cac_period   = %d msec\n"
+		       "    user_nop_period   = %d sec\n"
+		       "    no_channel_change = %d\n"
+		       "    fixed_channel_num = %d\n",
+		       dfs_test.usr_cac_period, dfs_test.usr_nop_period,
+		       dfs_test.no_chan_change, dfs_test.fixed_new_chan);
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+#endif /* DFS_SUPPORT && DFS_TESTING_SUPPORT */
+
+/**
+ *  @brief Show usage information for the cscount_cfg
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_cscount_cfg_usage(void)
+{
+	printf("\nUsage : cscount [<n>]");
+	printf("\n        Where  <n>  ");
+	printf("\n        5-20: No of beacons with Channel Switch Count IE\n");
+	return;
+}
+
+/**
+ *  @brief Set/get cs_count configuration
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_cscount_cfg(int argc, char *argv[])
+{
+	int opt;
+	cscount_cfg_t cscount_cfg;
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_cscount_cfg_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+
+	memset(&cscount_cfg, 0, sizeof(cscount_cfg));
+	if (argc == 0) {
+		cscount_cfg.action = ACTION_GET;
+	} else if (argc == 1) {
+		if ((t_u32)A2HEXDECIMAL(argv[0]) < 5
+		    && (t_u32)A2HEXDECIMAL(argv[0]) > 20) {
+			printf("ERR:Invalid Channel switch count value\n");
+			return UAP_FAILURE;
+		}
+		cscount_cfg.action = ACTION_SET;
+		cscount_cfg.cs_count = (t_u32)A2HEXDECIMAL(argv[0]);
+	} else {
+		print_cscount_cfg_usage();
+		return UAP_FAILURE;
+	}
+	cscount_cfg.subcmd = UAP_CHAN_SWITCH_COUNT_CFG;
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)&cscount_cfg;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: Channel switch count configuration failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+
+	/* Handle response */
+	if (cscount_cfg.action == ACTION_GET) {
+		printf("Channel Switch count = %d\n", cscount_cfg.cs_count);
+	}
+
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the mgmtframectrl command
+ *
+ *  $return         N/A
+ */
+void
+print_mgmtframectrl_usage(void)
+{
+	printf("\nUsage : mgmtframectrl [MASK]\n");
+	printf("         empty - Get management frame control mask\n");
+	printf("         MASK  - Set management frame control mask\n");
+}
+
+/**
+ *  @brief Creates management frame control request and send to driver
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_mgmt_frame_control(int argc, char *argv[])
+{
+	int opt;
+	mgmt_frame_ctrl param;	/* Action =0, Mask =0 */
+	struct ifreq ifr;
+	t_s32 sockfd;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_mgmtframectrl_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc > 1) {
+		printf("ERR:wrong arguments.\n");
+		print_mgmtframectrl_usage();
+		return UAP_FAILURE;
+	}
+
+	if ((argc) && (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE)) {
+		printf("ERR: Invalid argument %s\n", argv[0]);
+		print_mgmtframectrl_usage();
+		return UAP_FAILURE;
+	}
+
+	memset(&param, 0, sizeof(mgmt_frame_ctrl));
+	param.subcmd = UAP_MGMT_FRAME_CONTROL;
+	if (argc) {
+		param.action = ACTION_SET;
+		param.mask = (t_u16)A2HEXDECIMAL(argv[0]);
+	} else {
+		param.action = ACTION_GET;
+	}
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
+	ifr.ifr_ifru.ifru_data = (void *)&param;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR:UAP_IOCTL_CMD failed\n");
+		close(sockfd);
+		return UAP_FAILURE;
+	}
+	if (!argc) {
+		printf("Management Frame control mask = 0x%02x\n",
+		       (int)param.mask);
+	}
+	/* Close socket */
+	close(sockfd);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for the sys_cfg_tdls_ext_cap
+ *   command
+ *
+ *  $return         N/A
+ */
+void
+print_sys_cfg_tdls_ext_cap_usage(void)
+{
+	printf("\nUsage : sys_cfg_tdls_ext_cap [CONFIG_FILE] \n");
+	printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n");
+	printf("\n");
+	return;
+}
+
+/**
+ *  @brief  Get Extended capability info from firmware
+ *
+ *  @param  ext_cap  A pointer to tdls_ext_cap tlv
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+static int
+get_tdls_ext_cap(tlvbuf_tdls_ext_cap *ext_cap_tlv)
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_tdls_ext_cap *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = 0;
+	int ret = UAP_SUCCESS;
+
+	/* Initialize the buffer length */
+	buf_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tdls_ext_cap) +
+		MAX_TDLS_EXT_CAP_LEN;
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	/* Initialize the command buffer */
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_tdls_ext_cap *)(buffer + sizeof(apcmdbuf_sys_configure));
+	tlv->tag = MRVL_TDLS_EXT_CAP_TLV_ID;
+	/* Set TLV length to zero for GET request */
+	tlv->length = 0;
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tdls_ext_cap) +
+		tlv->length;
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = ACTION_GET;
+
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_TDLS_EXT_CAP_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+
+		/* Copy response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			memcpy(ext_cap_tlv, tlv,
+			       sizeof(tlvbuf_tdls_ext_cap) + tlv->length);
+		} else {
+			ret = UAP_FAILURE;
+			printf("ERR:Could not get TDLS extended capability!\n");
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+		ret = UAP_FAILURE;
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Read the TDLS parameters and populate structure
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @param bss      Pointer to BSS configuration buffer
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+static int
+parse_tdls_config(int argc, char *argv[], tlvbuf_tdls_ext_cap *ext_cap_tlv)
+{
+	FILE *config_file = NULL;
+	char *line = NULL;
+	char *pos = NULL;
+	char *args[30];
+	t_u8 *buffer = NULL;
+	tlvbuf_tdls_ext_cap *prev_ext_cap_tlv = NULL;
+	int li = 0, arg_num = 0, i = 0, is_tdls_config = 0;
+	int ret = UAP_SUCCESS;
+
+	/* Check if file exists */
+	config_file = fopen(argv[0], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return UAP_FAILURE;
+	}
+
+	buffer = (t_u8 *)malloc(MAX_TDLS_EXT_CAP_LEN);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory for buffer\n");
+		ret = UAP_FAILURE;
+		goto done;
+	}
+	memset(buffer, 0, MAX_TDLS_EXT_CAP_LEN);
+	prev_ext_cap_tlv = (tlvbuf_tdls_ext_cap *)buffer;
+	/* Get previous setting of extended capability from FW and copy it to ext_cap_tlv */
+	if (UAP_SUCCESS != get_tdls_ext_cap(prev_ext_cap_tlv)) {
+		printf("ERR: Couldn't get TDLS extended capability setting!\n");
+		return UAP_FAILURE;
+	}
+	memcpy(ext_cap_tlv, prev_ext_cap_tlv,
+	       sizeof(tlvbuf_tdls_ext_cap) + prev_ext_cap_tlv->length);
+
+	/* Parse file and process */
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		ret = UAP_FAILURE;
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+#if DEBUG
+		uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n",
+			   li, line);
+#endif
+		arg_num = parse_line(line, args);
+#if DEBUG
+		uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n",
+			   arg_num);
+		for (i = 0; i < arg_num; i++) {
+			uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1,
+				   args[i]);
+		}
+#endif
+		/* Check for end of TDLS configurations */
+		if (is_tdls_config == 1) {
+			if (strcmp(args[0], "}") == 0) {
+				is_tdls_config = 0;
+			}
+		}
+		/* Check for beginning of TDLS configurations */
+		if (strcmp(args[0], "tdls_config") == 0) {
+			is_tdls_config = 1;
+		}
+		if (is_tdls_config) {
+			if (strcmp(args[0], "tdls_prohibit") == 0) {
+				if ((ISDIGIT(args[1]) != UAP_SUCCESS) ||
+				    (atoi(args[1]) < 0) ||
+				    (atoi(args[1]) > 1)) {
+					printf("ERR: Invalid %s value!\n",
+					       args[0]);
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				ext_cap_tlv->ext_cap[4] &=
+					(~TDLS_PROHIBIT_MASK);
+				ext_cap_tlv->ext_cap[4] |=
+					(atoi(args[1]) << TDLS_PROHIBIT);
+			}
+			if (strcmp(args[0], "tdls_channel_switch_prohibit") ==
+			    0) {
+				if ((ISDIGIT(args[1]) != UAP_SUCCESS) ||
+				    (atoi(args[1]) < 0) ||
+				    (atoi(args[1]) > 1)) {
+					printf("ERR: Invalid %s value!\n",
+					       args[0]);
+					ret = UAP_FAILURE;
+					goto done;
+				}
+				ext_cap_tlv->ext_cap[4] &=
+					(~TDLS_CHANNEL_SWITCH_PROHIBIT_MASK);
+				ext_cap_tlv->ext_cap[4] |=
+					(atoi(args[1]) <<
+					 TDLS_CHANNEL_SWITCH_PROHIBIT);
+			}
+		}
+	}
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+	return ret;
+}
+
+/**
+ *  @brief Creates a sys_cfg request for setting extended capability for TDLS
+ *  and sends to the driver
+ *
+ *   Usage: "sys_cfg_tdls_ext_cap [CONFIG_FILE]"
+ *           If CONFIG_FILE is provided, a 'set' is performed
+ *           else a 'get' is performed.
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+apcmd_sys_cfg_tdls_ext_cap(int argc, char *argv[])
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_tdls_ext_cap *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_tdls_ext_cap_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc > 1) {
+		printf("ERR: Invalid arguments!\n");
+		return UAP_FAILURE;
+	}
+
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(buf_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buffer, 0, buf_len);
+
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_tdls_ext_cap *)(buffer + sizeof(apcmdbuf_sys_configure));
+	if (argc == 1) {
+		/* Get current TDLS extended capability setting from FW and
+		   parse new setting from config file */
+		if (UAP_SUCCESS != parse_tdls_config(argc, argv, tlv)) {
+			return UAP_FAILURE;
+		}
+	}
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv->tag = MRVL_TDLS_EXT_CAP_TLV_ID;
+	if (argc == 0) {
+		cmd_buf->action = ACTION_GET;
+		tlv->length = 0;
+	} else {
+		cmd_buf->action = ACTION_SET;
+	}
+	cmd_buf->size =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tdls_ext_cap) +
+		tlv->length;
+	cmd_len =
+		sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_tdls_ext_cap) +
+		tlv->length;
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+	endian_convert_tlv_header_in(tlv);
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if ((cmd_buf->cmd_code !=
+		     (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
+		    (tlv->tag != MRVL_TDLS_EXT_CAP_TLV_ID)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 0) {
+				printf("TDLS prohibited = %s\n",
+				       (tlv->
+					ext_cap[4] & TDLS_PROHIBIT_MASK) ? "YES"
+				       : "NO");
+				printf("TDLS Channel switch prohibited = %s\n",
+				       (tlv->
+					ext_cap[4] &
+					TDLS_CHANNEL_SWITCH_PROHIBIT_MASK) ?
+				       "YES" : "NO");
+			} else {
+				printf("TDLS setting successful\n");
+			}
+		} else {
+			if (argc == 0) {
+				printf("ERR:Could not get tdls setting!\n");
+			} else {
+				printf("ERR:Could not set tdls setting!\n");
+			}
+			ret = UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *    @brief Show usage information for the sys_cfg_pmf command
+ *    command
+ *
+ *    $return         N/A
+ */
+void
+print_sys_cfg_pmf(void)
+{
+	printf("\nUsage : uaputl.exe sys_cfg_pmf [MFPC] [MFPR]\n");
+	printf("\nSet/Get PMF capabilities");
+	printf("\n          empty - Get PMF capabilites\n");
+	printf("\n          MFPC: Management frames protection capable");
+	printf("\n              0 - Not capable");
+	printf("\n              1 - capable");
+	printf("\n          MFPR: Management frames protection required");
+	printf("\n          don't care if MFPC is set to 0");
+	printf("\n              0 - Not required");
+	printf("\n              1 - required\n");
+	return;
+}
+
+int
+apcmd_sys_cfg_pmf(int argc, char *argv[])
+{
+	int opt;
+	apcmdbuf_pmf_params *cmd_buf = NULL;
+	t_u8 *buf = NULL;
+	t_u16 cmd_len = 0;
+	t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	int ret = UAP_SUCCESS;
+	t_u8 mfpc = 0;
+	t_u8 mfpr = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_sys_cfg_pmf();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc > 2)) {
+		printf("ERR:wrong arguments.\n");
+		print_sys_cfg_pmf();
+		return UAP_FAILURE;
+	}
+
+	if (argc > 0)
+		mfpc = atoi(argv[0]);
+
+	if (mfpc && (argc == 1)) {
+		printf("ERR:wrong arguments.\n");
+		print_sys_cfg_pmf();
+		return UAP_FAILURE;
+	}
+
+	if (mfpc && (argc == 2))
+		mfpr = atoi(argv[1]);
+
+	/* Alloc buf for command */
+	buf = (t_u8 *)malloc(buf_len);
+
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer from command!\n");
+		return UAP_FAILURE;
+	}
+	memset(buf, 0, buf_len);
+
+	/* Locate headers */
+	cmd_len = sizeof(apcmdbuf_pmf_params);
+	cmd_buf = (apcmdbuf_pmf_params *) buf;
+
+	/* Fill the command buffer */
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->cmd_code = HostCmd_CMD_PMF_PARAMS;
+	if (argc == 0)
+		cmd_buf->action = ACTION_GET;
+	else
+		cmd_buf->action = ACTION_SET;
+	cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
+	cmd_buf->params.mfpc = mfpc;
+	cmd_buf->params.mfpr = mfpr;
+
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		if (cmd_buf->result == CMD_SUCCESS) {
+			printf("Successfully executed the command\n");
+			printf("mfpc: %d, mfpr: %d\n",
+			       cmd_buf->params.mfpc, cmd_buf->params.mfpr);
+		} else {
+			printf("ERR:Command sending failed!\n");
+			free(buf);
+			return UAP_FAILURE;
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+		free(buf);
+		return UAP_FAILURE;
+	}
+	free(buf);
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show usage information for uap operation control command
+ *
+ *  $return         N/A
+ */
+void
+print_uap_oper_ctrl_usage(void)
+{
+	printf("\nUsage : uap_oper_ctrl <control> <chanopt> <bandcfg> <channel> ");
+	printf("\n set/get uap operation when in-STA disconnected from ext-AP if multi channel is disabled");
+	printf("\n       control:    0: default, do nothing");
+	printf("\n                      2: uap stops and restart automatically");
+	printf("\n        chanopt : specify which channel should be used when uap restarts automatically");
+	printf("\n                      1: uap restarts on default 2.4G/channel 6");
+	printf("\n                      2: uap restart on band/channel configured by driver previously");
+	printf("\n                      3: uap restart on band/channel configured by parameter bandcfg/channel");
+	printf("\n         bandcfg : This parameter specifies the bandwidth (BW)");
+	printf("\n                      0: 20Mhz");
+	printf("\n                      2: 40Mhz");
+	printf("\n                      3: 80Mhz");
+	printf("\n         channel : This parameter specifies the channel will be used when chanopt is 3.");
+	return;
+}
+
+/**
+ *  @brief Set/Get uap operation when in-STA disconnected from ext-AP
+ *  @param argc   Number of arguments
+ *  @param argv   A pointer to arguments array
+ *  @return     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int
+apcmd_uap_oper_ctrl(int argc, char *argv[])
+{
+	int opt;
+	uap_operation_ctrl param;
+	struct eth_priv_uap_oper_ctrl *uap_oper = NULL;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	t_u8 *respbuf = NULL;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_uap_oper_ctrl_usage();
+			return UAP_SUCCESS;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	respbuf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!respbuf) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return UAP_FAILURE;
+	}
+	memset(respbuf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	/* Check arguments */
+	if (argc > 4) {
+		printf("ERR: Invalid number of arguments.\n");
+		print_uap_oper_ctrl_usage();
+		free(respbuf);
+		return UAP_FAILURE;
+	}
+
+	if (argc > 0) {
+		param.uap_oper.ctrl = (t_u16)A2HEXDECIMAL(argv[0]);
+		if (param.uap_oper.ctrl == 2)
+			param.uap_oper.chan_opt = (t_u16)A2HEXDECIMAL(argv[1]);
+
+		if (argc == 4 && param.uap_oper.chan_opt == 3) {
+			param.uap_oper.bandcfg = (t_u8)A2HEXDECIMAL(argv[2]);
+			param.uap_oper.channel = (t_u8)A2HEXDECIMAL(argv[3]);
+		}
+		param.action = ACTION_SET;
+	} else {
+		param.action = ACTION_GET;
+	}
+	param.subcmd = UAP_OPERATION_CTRL;
+
+	memcpy(respbuf, &param, sizeof(uap_operation_ctrl));
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		free(respbuf);
+		return UAP_FAILURE;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)respbuf;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		perror("");
+		printf("ERR: uap operation control set/get failed\n");
+		close(sockfd);
+		free(respbuf);
+		return UAP_FAILURE;
+	}
+
+	/* Handle response */
+	if (param.action == ACTION_GET) {
+		/* Process result */
+		uap_oper =
+			(struct eth_priv_uap_oper_ctrl *)(respbuf +
+							  2 * sizeof(t_u32));
+		printf("    uap operation control %x\n", uap_oper->ctrl);
+		printf("    uap channel operation %x\n", uap_oper->chan_opt);
+		if (uap_oper->chan_opt == 3) {
+			printf("    uap bandwidth %s\n",
+			       uap_oper->
+			       bandcfg ? ((uap_oper->bandcfg == 2) ? "40Mhz" :
+					  "80Mhz") : "20Mhz");
+			printf("    uap channel %d\n", uap_oper->channel);
+		}
+	} else
+		printf("uap operation control set success!\n");
+	/* Close socket */
+	close(sockfd);
+	if (respbuf)
+		free(respbuf);
+	return UAP_SUCCESS;
+}
+
+/** Structure of command table*/
+typedef struct {
+    /** Command name */
+	char *cmd;
+    /** Command function pointer */
+	int (*func) (int argc, char *argv[]);
+    /** Command usuage */
+	char *help;
+} command_table;
+
+/** AP command table */
+static command_table ap_command[] = {
+	{"sys_config", apcmd_sys_config, "\tSet/get uAP's profile"},
+	{"sys_info", apcmd_sys_info, "\tDisplay system info"},
+	{"sys_reset", apcmd_sys_reset, "\tReset uAP"},
+	{"bss_start", apcmd_bss_start, "\tStart the BSS"},
+	{"bss_stop", apcmd_bss_stop, "\tStop the BSS"},
+	{"skip_cac", apcmd_skip_cac, "\tSkip the CAC"},
+	{"sta_deauth", apcmd_sta_deauth, "\tDeauth client"},
+	{"sta_list", apcmd_sta_list, "\tDisplay list of clients"},
+	{"sys_cfg_ap_mac_address", apcmd_sys_cfg_ap_mac_address,
+	 "Set/get uAP mac address"},
+	{"sys_cfg_ssid", apcmd_sys_cfg_ssid, "\tSet/get uAP ssid"},
+	{"sys_cfg_beacon_period", apcmd_sys_cfg_beacon_period,
+	 "Set/get uAP beacon period"},
+	{"sys_cfg_dtim_period", apcmd_sys_cfg_dtim_period,
+	 "Set/get uAP dtim period"},
+	{"sys_cfg_bss_status", apcmd_sys_cfg_bss_status, "Get BSS status"},
+	{"sys_cfg_channel", apcmd_sys_cfg_channel,
+	 "\tSet/get uAP radio channel"},
+	{"sys_cfg_channel_ext", apcmd_sys_cfg_channel_ext,
+	 "\tSet/get uAP radio channel, band and mode"},
+	{"sys_cfg_scan_channels", apcmd_sys_cfg_scan_channels,
+	 "Set/get uAP radio channel list"},
+	{"sys_cfg_rates", apcmd_sys_cfg_rates, "\tSet/get uAP rates"},
+	{"sys_cfg_rates_ext", apcmd_sys_cfg_rates_ext, "\tSet/get uAP rates"},
+	{"sys_cfg_tx_power", apcmd_sys_cfg_tx_power, "Set/get uAP tx power"},
+	{"sys_cfg_bcast_ssid_ctl", apcmd_sys_cfg_bcast_ssid_ctl,
+	 "Set/get uAP broadcast ssid"},
+	{"sys_cfg_preamble_ctl", apcmd_sys_cfg_preamble_ctl,
+	 "Get uAP preamble"},
+	{"antcfg", apcmd_antcfg, "Set/get uAP tx/rx antenna"},
+	{"htstreamcfg", apcmd_htstreamcfg,
+	 "Set/get uAP HT stream configurations"},
+	{"sys_cfg_rts_threshold", apcmd_sys_cfg_rts_threshold,
+	 "Set/get uAP rts threshold"},
+	{"sys_cfg_frag_threshold", apcmd_sys_cfg_frag_threshold,
+	 "Set/get uAP frag threshold"},
+	{"radioctrl", apcmd_radio_ctl, "Set/get uAP radio on/off"},
+	{"sys_cfg_tx_beacon_rate", apcmd_sys_cfg_tx_beacon_rate,
+	 "Set/get uAP tx beacon rate"},
+	{"txratecfg", apcmd_tx_rate_cfg, "Set/get trasnmit data rate"},
+	{"sys_cfg_mcbc_data_rate", apcmd_sys_cfg_mcbc_data_rate,
+	 "Set/get uAP MCBC rate"},
+	{"sys_cfg_rsn_replay_prot", apcmd_sys_cfg_rsn_replay_prot,
+	 "Set/get RSN replay protection"},
+	{"sys_cfg_pkt_fwd_ctl", apcmd_sys_cfg_pkt_fwd_ctl,
+	 "Set/get uAP packet forwarding"},
+	{"sys_cfg_sta_ageout_timer", apcmd_sys_cfg_sta_ageout_timer,
+	 "Set/get station ageout timer"},
+	{"sys_cfg_ps_sta_ageout_timer", apcmd_sys_cfg_ps_sta_ageout_timer,
+	 "Set/get PS station ageout timer"},
+	{"sys_cfg_auth", apcmd_sys_cfg_auth,
+	 "\tSet/get uAP authentication mode"},
+	{"sys_cfg_protocol", apcmd_sys_cfg_protocol,
+	 "Set/get uAP security protocol"},
+	{"sys_cfg_wep_key", apcmd_sys_cfg_wep_key, "\tSet/get uAP wep key"},
+	{"sys_cfg_cipher", apcmd_sys_cfg_cipher,
+	 "\tSet/get uAP WPA/WPA2 cipher"},
+	{"sys_cfg_pwk_cipher", apcmd_sys_cfg_pwk_cipher,
+	 "\tSet/get uAP WPA/WPA2 pairwise cipher"},
+	{"sys_cfg_gwk_cipher", apcmd_sys_cfg_gwk_cipher,
+	 "\tSet/get uAP WPA/WPA2 group cipher"},
+	{"sys_cfg_wpa_passphrase", apcmd_sys_cfg_wpa_passphrase,
+	 "Set/get uAP WPA or WPA2 passphrase"},
+	{"sys_cfg_group_rekey_timer", apcmd_sys_cfg_group_rekey_timer,
+	 "Set/get uAP group re-key time"},
+	{"sys_cfg_max_sta_num", apcmd_sys_cfg_max_sta_num,
+	 "Set/get uAP max station number"},
+	{"sys_cfg_retry_limit", apcmd_sys_cfg_retry_limit,
+	 "Set/get uAP retry limit number"},
+	{"sys_cfg_sticky_tim_config", apcmd_sys_cfg_sticky_tim_config,
+	 "Set/get uAP sticky TIM configuration"},
+	{"sys_cfg_sticky_tim_sta_mac_addr",
+	 apcmd_sys_cfg_sticky_tim_sta_mac_addr,
+	 "Set/get uAP sticky TIM sta MAC address"},
+	{"sys_cfg_eapol_pwk_hsk", apcmd_sys_cfg_eapol_pwk_hsk,
+	 "Set/getuAP pairwise Handshake timeout value and retries"},
+	{"sys_cfg_eapol_gwk_hsk", apcmd_sys_cfg_eapol_gwk_hsk,
+	 "Set/getuAP groupwise Handshake timeout value and retries"},
+	{"sys_cfg_custom_ie", apcmd_sys_cfg_custom_ie,
+	 "\tSet/get custom IE configuration"},
+	{"sta_filter_table", apcmd_sta_filter_table, "Set/get uAP mac filter"},
+	{"regrdwr", apcmd_regrdwr, "\t\tRead/Write register command"},
+	{"memaccess", apcmd_memaccess,
+	 "\tRead/Write to a memory address command"},
+	{"rdeeprom", apcmd_read_eeprom, "\tRead EEPROM "},
+	{"cfg_data", apcmd_cfg_data,
+	 "\tGet/Set configuration file from/to firmware"},
+	{"sys_cfg_80211d", apcmd_cfg_80211d, "\tSet/Get 802.11D info"},
+	{"uap_stats", apcmd_uap_stats, "\tGet uAP stats"},
+	{"pscfg", apcmd_pscfg, "\t\tSet/get uAP power mode"},
+	{"bss_config", apcmd_bss_config, "\tSet/get BSS configuration"},
+	{"sta_deauth_ext", apcmd_sta_deauth_ext, "\tDeauth client"},
+	{"coex_config", apcmd_coex_config,
+	 "\tSet/get uAP BT coex configuration"},
+	{"hscfg", apcmd_hscfg, "\t\tSet/get uAP host sleep parameters."},
+	{"hssetpara", apcmd_hssetpara,
+	 "\t\tSet/get uAP host sleep parameters."},
+	{"addbapara", apcmd_addbapara, "\tSet/get uAP ADDBA parameters."},
+	{"aggrpriotbl", apcmd_aggrpriotbl,
+	 "\tSet/get uAP priority table for AMPDU/AMSDU."},
+	{"addbareject", apcmd_addbareject, "\tSet/get uAP addbareject table."},
+	{"sys_cfg_11n", apcmd_sys_cfg_11n, "\tSet/get uAP 802.11n parameters."},
+#ifdef RX_PACKET_COALESCE
+	{"rxpktcoal_cfg", apcmd_rx_pkt_coalesce,
+	 "\tSet/get RX Packet coalesing paramterts."},
+#endif
+	{"httxbfcfg", apcmd_sys_cfg_tx_bf, "\tSet/get uAP TX BF parameters."},
+	{"httxcfg", apcmd_sys_cfg_ht_tx, "\t\tSet/get uAP HT Tx parameters."},
+	{"vhtcfg", apcmd_sys_cfg_vht, "\t\tSet/get uAP VHT parameters."},
+	{"sys_cfg_wmm", apcmd_sys_cfg_wmm,
+	 "\tSet/get uAP beacon wmm parameters."},
+	{"sys_cfg_ap_wmm", apcmd_sys_cfg_ap_wmm,
+	 "\tSet/get uAP hardware wmm parameters."},
+	{"deepsleep", apcmd_deepsleep, "\tSet/get deepsleep mode."},
+	{"hostcmd", apcmd_hostcmd, "\t\tSet/get hostcmd"},
+	{"tx_data_pause", apcmd_txdatapause,
+	 "\tSet/get Tx data pause settings."},
+	{"sdcmd52rw", apcmd_cmd52_readwrite,
+	 "\tRead or write using sdio command 52."},
+	{"sys_cfg_2040_coex", apcmd_sys_cfg_2040_coex,
+	 "\tSet/get 20/40 coex settings."},
+#if defined(DFS_TESTING_SUPPORT)
+	{"dfstesting", apcmd_dfstesting, "\tConfigure DFS Testing settings."},
+#endif
+	{"cscount", apcmd_cscount_cfg, "\tConfigure DFS Channel Switch Count."},
+	{"mgmtframectrl", apcmd_mgmt_frame_control,
+	 "\tSpecifies mask indicating management frames to be sent from host."},
+	{"sys_cfg_tdls_ext_cap", apcmd_sys_cfg_tdls_ext_cap,
+	 "\tSet/get TDLS parameters in extended capabilities through config file."},
+	{"sys_cfg_restrict_client_mode", apcmd_sys_cfg_restrict_client_mode,
+	 "\tSet/get the mode in which client stations can connect to the uAP."},
+	{"sys_cfg_pmf", apcmd_sys_cfg_pmf, "\tSet/get PMF capabilities."},
+	{"uap_oper_ctrl", apcmd_uap_oper_ctrl,
+	 "\tSet/get uap operation control value."},
+	{NULL, NULL, 0}
+};
+
+/**
+ *  @brief Prints usage information of uaputl
+ *
+ *  @return          N/A
+ */
+static void
+print_tool_usage(void)
+{
+	int i;
+	printf("uaputl.exe - uAP utility ver %s\n", UAP_VERSION);
+	printf("Usage:\n"
+	       "\tuaputl.exe [options] <command> [command parameters]\n");
+	printf("Options:\n"
+	       "\t--help\tDisplay help\n"
+	       "\t-v\tDisplay version\n"
+	       "\t-i <interface>\n" "\t-d <debug_level=0|1|2>\n");
+	printf("Commands:\n");
+	for (i = 0; ap_command[i].cmd; i++)
+		printf("\t%-4s\t\t%s\n", ap_command[i].cmd, ap_command[i].help);
+	printf("\n"
+	       "For more information on the usage of each command use:\n"
+	       "\tuaputl.exe <command> --help\n");
+}
+
+/****************************************************************************
+        Global functions
+****************************************************************************/
+/** Option parameter*/
+static struct option ap_options[] = {
+	{"help", 0, NULL, 'h'},
+	{"interface", 1, NULL, 'i'},
+	{"debug", 1, NULL, 'd'},
+	{"version", 0, NULL, 'v'},
+	{NULL, 0, NULL, '\0'}
+};
+
+/**
+ * @brief Checks if given channel in 'a' band is valid or not.
+ *
+ * @param channel   Channel number
+ * @return          UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_valid_a_band_channel(int channel)
+{
+	int ret = UAP_SUCCESS;
+	switch (channel) {
+	case 16:
+	case 34:
+	case 36:
+	case 38:
+	case 40:
+	case 42:
+	case 44:
+	case 46:
+	case 48:
+	case 52:
+	case 56:
+	case 60:
+	case 64:
+	case 100:
+	case 104:
+	case 108:
+	case 112:
+	case 116:
+	case 120:
+	case 124:
+	case 128:
+	case 132:
+	case 136:
+	case 140:
+	case 144:
+	case 149:
+	case 153:
+	case 157:
+	case 161:
+	case 165:
+		break;
+	default:
+		ret = UAP_FAILURE;
+		break;
+	}
+	return ret;
+}
+
+/**
+ * @brief Checks if secondary channel can be set above given primary channel in 'a' band or not.
+ *
+ * @param channel   Channel number
+ * @return          UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_valid_a_band_channel_above(int channel)
+{
+	int ret = UAP_SUCCESS;
+	switch (channel) {
+	case 36:
+	case 44:
+	case 52:
+	case 60:
+	case 100:
+	case 108:
+	case 116:
+	case 124:
+	case 132:
+	case 140:
+	case 149:
+	case 157:
+		break;
+	default:
+		ret = UAP_FAILURE;
+		break;
+	}
+	return ret;
+}
+
+/**
+ * @brief Checks if secondary channel can be set below given primary channel in 'a' band or not.
+ *
+ * @param channel   Channel number
+ * @return          UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_valid_a_band_channel_below(int channel)
+{
+	int ret = UAP_SUCCESS;
+	switch (channel) {
+	case 40:
+	case 48:
+	case 56:
+	case 64:
+	case 104:
+	case 112:
+	case 120:
+	case 128:
+	case 136:
+	case 153:
+	case 161:
+		break;
+	default:
+		ret = UAP_FAILURE;
+		break;
+	}
+	return ret;
+}
+
+/**
+ *  @brief Checkes a particular input for validatation.
+ *
+ *  @param cmd      Type of input
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_input_valid(valid_inputs cmd, int argc, char *argv[])
+{
+	int i;
+	int chan_number = 0;
+	int band = 0;
+	int ch;
+	int ret = UAP_SUCCESS;
+	if (argc == 0)
+		return UAP_FAILURE;
+	switch (cmd) {
+	case RDEEPROM:
+		if (argc != 2) {
+			printf(" ERR: Argument count mismatch\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)
+			    || (A2HEXDECIMAL(argv[0]) & 0x03) ||
+			    ((int)(A2HEXDECIMAL(argv[0])) < 0) ||
+			    (A2HEXDECIMAL(argv[1]) & 0x03) ||
+			    (A2HEXDECIMAL(argv[1]) < 4) ||
+			    (A2HEXDECIMAL(argv[1]) > 20)) {
+				printf(" ERR: Invalid inputs for Read EEPROM\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case SCANCHANNELS:
+		if (argc > MAX_CHANNELS) {
+			printf("ERR: Invalid List of Channels\n");
+			ret = UAP_FAILURE;
+		} else {
+			for (i = 0; i < argc; i++) {
+				chan_number = -1;
+				band = -1;
+				sscanf(argv[i], "%d.%d", &chan_number, &band);
+				if ((chan_number == -1) || (chan_number < 1) ||
+				    (chan_number > MAX_CHANNELS)) {
+					printf("ERR: Channel must be in the range of 1 to %d\n", MAX_CHANNELS);
+					ret = UAP_FAILURE;
+					break;
+				}
+				if ((chan_number > MAX_CHANNELS_BG) &&
+				    !(is_valid_a_band_channel(chan_number))) {
+					printf("ERR: Invalid Channel in 'a' band!\n");
+					ret = UAP_FAILURE;
+					break;
+				}
+				if ((band < -1) || (band > 1)) {
+					printf("ERR:Band must be either 0 or 1\n");
+					ret = UAP_FAILURE;
+					break;
+				} else {
+					if (((chan_number < MAX_CHANNELS_BG) &&
+					     (chan_number != 8) &&
+					     (chan_number != 12) && (band == 1))
+					    || ((chan_number > MAX_CHANNELS_BG)
+						&& (band == 0))) {
+						printf("ERR:Invalid band for given channel\n");
+						ret = UAP_FAILURE;
+						break;
+					}
+				}
+			}
+			if ((ret != UAP_FAILURE) &&
+			    (has_dup_channel(argc, argv) != UAP_SUCCESS)) {
+				printf("ERR: Duplicate channel values entered\n");
+				ret = UAP_FAILURE;
+			}
+			if ((ret != UAP_FAILURE) &&
+			    (has_diff_band(argc, argv) != UAP_SUCCESS)) {
+				printf("ERR: Scan channel list should contain channels from only one band\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case TXPOWER:
+		if ((argc > 1) || (ISDIGIT(argv[0]) == 0)) {
+			printf("ERR:Invalid Transmit power\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((atoi(argv[0]) < MIN_TX_POWER) ||
+			    (atoi(argv[0]) > MAX_TX_POWER)) {
+				printf("ERR: TX Powar must be in the rage of %d to %d. \n", MIN_TX_POWER, MAX_TX_POWER);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case PROTOCOL:
+		if ((argc > 2) || (ISDIGIT(argv[0]) == 0)) {
+			printf("ERR:Invalid Protocol\n");
+			ret = UAP_FAILURE;
+		} else
+			ret = is_protocol_valid(atoi(argv[0]));
+		break;
+	case AKM_SUITE:
+		if (argc == 2) {
+			if (A2HEXDECIMAL(argv[1]) &
+			    ~(KEY_MGMT_PSK | KEY_MGMT_PSK_SHA256 | KEY_MGMT_EAP
+			      | KEY_MGMT_NONE)) {
+				printf("ERR: Invalid AKM suite\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case CHANNEL:
+		if ((argc != 1) && (argc != 2)) {
+			printf("ERR: Incorrect arguments for channel.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if (argc == 2) {
+				if ((ISDIGIT(argv[1]) == 0) ||
+				    (atoi(argv[1]) & ~CHANNEL_MODE_MASK)) {
+					printf("ERR: Invalid Mode\n");
+					ret = UAP_FAILURE;
+				}
+				if ((atoi(argv[1]) & BITMAP_ACS_MODE) &&
+				    (atoi(argv[0]) != 0)) {
+					printf("ERR: Channel must be 0 for ACS; MODE = 1.\n");
+					ret = UAP_FAILURE;
+				}
+				if ((atoi(argv[1]) & BITMAP_CHANNEL_ABOVE) &&
+				    (atoi(argv[1]) & BITMAP_CHANNEL_BELOW)) {
+					printf("ERR: secondary channel above and below both are enabled\n");
+					ret = UAP_FAILURE;
+				}
+			}
+			if ((argc == 1) || (!(atoi(argv[1]) & BITMAP_ACS_MODE))) {
+				if ((ISDIGIT(argv[0]) == 0) ||
+				    (atoi(argv[0]) < 1) ||
+				    (atoi(argv[0]) > MAX_CHANNELS)) {
+					printf("ERR: Channel must be in the range of 1 to %d\n", MAX_CHANNELS);
+					ret = UAP_FAILURE;
+				}
+				if ((atoi(argv[0]) > MAX_CHANNELS_BG) &&
+				    !(is_valid_a_band_channel(atoi(argv[0])))) {
+					printf("ERR: Invalid Channel in 'a' band!\n");
+					ret = UAP_FAILURE;
+				}
+				ch = atoi(argv[0]);
+				if (ch <= MAX_CHANNELS_BG) {
+					if ((argc == 2) &&
+					    (atoi(argv[1]) &
+					     BITMAP_CHANNEL_ABOVE) &&
+					    (atoi(argv[0]) >
+					     MAX_CHANNEL_ABOVE)) {
+						printf("ERR: only allow channel 1-9 for secondary channel above\n");
+						ret = UAP_FAILURE;
+					}
+					if ((argc == 2) &&
+					    (atoi(argv[1]) &
+					     BITMAP_CHANNEL_BELOW) &&
+					    ((atoi(argv[0]) < MIN_CHANNEL_BELOW)
+					     || (atoi(argv[0]) == 14))) {
+						printf("ERR: only allow channel 5-13 for secondary channel below\n");
+						ret = UAP_FAILURE;
+					}
+				} else {
+					if (argc == 2) {
+						if ((atoi(argv[1]) &
+						     BITMAP_CHANNEL_BELOW) &&
+						    !is_valid_a_band_channel_below
+						    (atoi(argv[0]))) {
+							printf("ERR: For given primary channel secondary channel can not be set below\n");
+							ret = UAP_FAILURE;
+						}
+						if ((atoi(argv[1]) &
+						     BITMAP_CHANNEL_ABOVE) &&
+						    !is_valid_a_band_channel_above
+						    (atoi(argv[0]))) {
+							printf("ERR: For given primary channel secondary channel can not be set above\n");
+							ret = UAP_FAILURE;
+						}
+					}
+				}
+			}
+		}
+		break;
+	case CHANNEL_EXT:
+		if (argc > 3) {
+			printf("ERR: Incorrect arguments for channel_ext.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if (argc == 3) {
+				if ((ISDIGIT(argv[2]) == 0) ||
+				    (atoi(argv[2]) & ~CHANNEL_MODE_MASK)) {
+					printf("ERR: Invalid Mode\n");
+					ret = UAP_FAILURE;
+				}
+				if ((atoi(argv[2]) & BITMAP_ACS_MODE) &&
+				    (atoi(argv[0]) != 0)) {
+					printf("ERR: Channel must be 0 for ACS; MODE = 1.\n");
+					ret = UAP_FAILURE;
+				}
+				if ((atoi(argv[2]) & BITMAP_CHANNEL_ABOVE) &&
+				    (atoi(argv[2]) & BITMAP_CHANNEL_BELOW)) {
+					printf("ERR: secondary channel above and below both are enabled\n");
+					ret = UAP_FAILURE;
+				}
+			}
+			if ((argc == 2) &&
+			    ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 0) ||
+			     atoi(argv[1]) > 1)) {
+				printf("ERR:Invalid band\n");
+				ret = UAP_FAILURE;
+			}
+			if ((argc == 1) ||
+			    ((argc == 3) &&
+			     !(atoi(argv[2]) & BITMAP_ACS_MODE))) {
+				if ((ISDIGIT(argv[0]) == 0) ||
+				    (atoi(argv[0]) < 1) ||
+				    (atoi(argv[0]) > MAX_CHANNELS)) {
+					printf("ERR: Channel must be in the range of 1 to %d\n", MAX_CHANNELS);
+					ret = UAP_FAILURE;
+				}
+				if ((atoi(argv[0]) > MAX_CHANNELS_BG) &&
+				    !(is_valid_a_band_channel(atoi(argv[0])))) {
+					printf("ERR: Invalid Channel in 'a' band!\n");
+					ret = UAP_FAILURE;
+				}
+				ch = atoi(argv[0]);
+				if (ch <= MAX_CHANNELS_BG) {
+					if ((argc == 3) &&
+					    (atoi(argv[2]) &
+					     BITMAP_CHANNEL_ABOVE) &&
+					    (atoi(argv[0]) >
+					     MAX_CHANNEL_ABOVE)) {
+						printf("ERR: only allow channel 1-9 for secondary channel above\n");
+						ret = UAP_FAILURE;
+					}
+					if ((argc == 3) &&
+					    (atoi(argv[2]) &
+					     BITMAP_CHANNEL_BELOW) &&
+					    ((atoi(argv[0]) < MIN_CHANNEL_BELOW)
+					     || (atoi(argv[0]) == 14))) {
+						printf("ERR: only allow channel 5-13 for secondary channel below\n");
+						ret = UAP_FAILURE;
+					}
+				} else {
+					if (argc == 3) {
+						if ((atoi(argv[2]) &
+						     BITMAP_CHANNEL_BELOW) &&
+						    !is_valid_a_band_channel_below
+						    (atoi(argv[0]))) {
+							printf("ERR: For given primary channel secondary channel can not be set below\n");
+							ret = UAP_FAILURE;
+						}
+						if ((atoi(argv[2]) &
+						     BITMAP_CHANNEL_ABOVE) &&
+						    !is_valid_a_band_channel_above
+						    (atoi(argv[0]))) {
+							printf("ERR: For given primary channel secondary channel can not be set above\n");
+							ret = UAP_FAILURE;
+						}
+					}
+				}
+			}
+		}
+		break;
+	case BAND:
+		if (argc > 1) {
+			printf("ERR: Incorrect number of BAND arguments.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			    (atoi(argv[0]) > 1)) {
+				printf("ERR: Invalid band.\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case RATE:
+		if (argc > MAX_RATES) {
+			printf("ERR: Incorrect number of RATES arguments.\n");
+			ret = UAP_FAILURE;
+		} else {
+			for (i = 0; i < argc; i++) {
+				if ((IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) ||
+				    (is_rate_valid
+				     (A2HEXDECIMAL(argv[i]) &
+				      ~BASIC_RATE_SET_BIT)
+				     != UAP_SUCCESS)) {
+					printf("ERR:Unsupported rate.\n");
+					ret = UAP_FAILURE;
+					break;
+				}
+			}
+			if ((ret != UAP_FAILURE) &&
+			    (has_dup_rate(argc, argv) != UAP_SUCCESS)) {
+				printf("ERR: Duplicate rate values entered\n");
+				ret = UAP_FAILURE;
+			}
+			if (check_mandatory_rates(argc, argv) != UAP_SUCCESS) {
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case BROADCASTSSID:
+		if (argc != 1) {
+			printf("ERR:wrong BROADCASTSSID arguments.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    ((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1) &&
+			     (atoi(argv[0]) != 2))) {
+				printf("ERR:Illegal parameter %s for BROADCASTSSID. Must be either '0', '1' or '2'.\n", argv[0]);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case RTSTHRESH:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for RTSTHRESHOLD\n");
+			ret = UAP_FAILURE;
+		} else if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			   (atoi(argv[0]) > MAX_RTS_THRESHOLD)) {
+			printf("ERR:Illegal RTSTHRESHOLD %s. The value must between 0 and %d\n", argv[0], MAX_RTS_THRESHOLD);
+			ret = UAP_FAILURE;
+		}
+		break;
+	case FRAGTHRESH:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for FRAGTHRESH\n");
+			ret = UAP_FAILURE;
+		} else if ((ISDIGIT(argv[0]) == 0) ||
+			   (atoi(argv[0]) < MIN_FRAG_THRESHOLD) ||
+			   (atoi(argv[0]) > MAX_FRAG_THRESHOLD)) {
+			printf("ERR:Illegal FRAGTHRESH %s. The value must between %d and %d\n", argv[0], MIN_FRAG_THRESHOLD, MAX_FRAG_THRESHOLD);
+			ret = UAP_FAILURE;
+		}
+		break;
+	case DTIMPERIOD:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for DTIMPERIOD\n");
+			ret = UAP_FAILURE;
+		} else if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 1) ||
+			   (atoi(argv[0]) > MAX_DTIM_PERIOD)) {
+			printf("ERR: DTIMPERIOD Value must be in range of 1 to %d\n", MAX_DTIM_PERIOD);
+			ret = UAP_FAILURE;
+		}
+		break;
+	case RSNREPLAYPROT:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for RSNREPLAYPROT\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			    (atoi(argv[0]) > 1)) {
+				printf("ERR:Illegal RSNREPLAYPROT parameter %s. Must be either '0' or '1'.\n", argv[0]);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case RADIOCONTROL:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for RADIOCONTROL\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			    (atoi(argv[0]) > 1)) {
+				printf("ERR:Illegal RADIOCONTROL parameter %s. Must be either '0' or '1'.\n", argv[0]);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case TXRATECFG:
+		if (argc > 3) {
+			printf("ERR:Incorrect number of arguments for DATARATE\n");
+			ret = UAP_FAILURE;
+		} else {
+			if (((argc >= 1) &&
+			     (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE)) ||
+			    ((argc >= 2) &&
+			     (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE))
+			    || ((argc >= 3) &&
+				(IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE))
+				) {
+				printf("ERR: invalid Tx data rate\n");
+				ret = UAP_FAILURE;
+			} else if (argc >= 1) {
+				if (A2HEXDECIMAL(argv[0]) == 0xFF) {
+					if (argc != 1) {
+						printf("ERR: invalid auto rate input\n");
+						ret = UAP_FAILURE;
+					}
+				} else {
+					if ((A2HEXDECIMAL(argv[0]) < 0) ||
+					    (A2HEXDECIMAL(argv[0]) > 2)
+						) {
+						printf("ERR: invalid format\n");
+						ret = UAP_FAILURE;
+					}
+					if (argc >= 2) {
+						if ((A2HEXDECIMAL(argv[1]) < 0)
+						    ||
+						    ((A2HEXDECIMAL(argv[0]) ==
+						      0) &&
+						     (A2HEXDECIMAL(argv[1]) >
+						      11)) ||
+						    ((A2HEXDECIMAL(argv[0]) ==
+						      1) &&
+						     (A2HEXDECIMAL(argv[1]) !=
+						      32) &&
+						     (A2HEXDECIMAL(argv[1]) >
+						      15)
+						    )) {
+							printf("ERR:Incorrect TxRate %s.\n", argv[1]);
+							ret = UAP_FAILURE;
+						}
+					}
+					if (argc == 3) {
+						if ((A2HEXDECIMAL(argv[0]) != 2)
+						    ||
+						    ((A2HEXDECIMAL(argv[2]) < 1)
+						     || (A2HEXDECIMAL(argv[2]) >
+							 2))) {
+							printf("ERR:Incorrect nss.\n");
+							ret = UAP_FAILURE;
+						}
+					}
+				}
+			}
+		}
+		break;
+	case MCBCDATARATE:
+	case TXBEACONRATE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for DATARATE\n");
+			ret = UAP_FAILURE;
+		} else {
+			if (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) {
+				printf("ERR: invalid data rate\n");
+				ret = UAP_FAILURE;
+			} else if ((A2HEXDECIMAL(argv[0]) != 0) &&
+				   (is_rate_valid
+				    (A2HEXDECIMAL(argv[0]) &
+				     ~BASIC_RATE_SET_BIT) != UAP_SUCCESS)) {
+				printf("ERR: invalid data rate\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case PKTFWD:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for PKTFWD.\n");
+			ret = UAP_FAILURE;
+		} else if ((ISDIGIT(argv[0]) == 0) ||
+			   ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 15))) {
+			printf("ERR:Illegal PKTFWD parameter %s. Must be within '0' and '15'.\n", argv[0]);
+			ret = UAP_FAILURE;
+		}
+		break;
+	case STAAGEOUTTIMER:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for STAAGEOUTTIMER.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) &&
+							((atoi(argv[0]) <
+							  MIN_STAGE_OUT_TIME) ||
+							 (atoi(argv[0]) >
+							  MAX_STAGE_OUT_TIME))))
+			{
+				printf("ERR:Illegal STAAGEOUTTIMER %s. Must be between %d and %d.\n", argv[0], MIN_STAGE_OUT_TIME, MAX_STAGE_OUT_TIME);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case PSSTAAGEOUTTIMER:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for PSSTAAGEOUTTIMER.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) &&
+							((atoi(argv[0]) <
+							  MIN_STAGE_OUT_TIME) ||
+							 (atoi(argv[0]) >
+							  MAX_STAGE_OUT_TIME))))
+			{
+				printf("ERR:Illegal PSSTAAGEOUTTIMER %s. Must be between %d and %d.\n", argv[0], MIN_STAGE_OUT_TIME, MAX_STAGE_OUT_TIME);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case AUTHMODE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for AUTHMODE\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) &&
+							(atoi(argv[0]) != 1) &&
+							(atoi(argv[0]) !=
+							 255))) {
+				printf("ERR:Illegal AUTHMODE parameter %s. Must be either '0','1' or 255''.\n", argv[0]);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case GROUPREKEYTIMER:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for GROUPREKEYTIMER.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			    (atoi(argv[0]) > MAX_GRP_TIMER)) {
+				printf("ERR: GROUPREKEYTIMER range is [0:%d] (0 for disable)\n", MAX_GRP_TIMER);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case MAXSTANUM:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for MAXSTANUM\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) <= 0)) {
+				printf("ERR:Invalid STA_NUM argument %s.\n",
+				       argv[0]);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case BEACONPERIOD:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of argument for BEACONPERIOD.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) < MIN_BEACON_PERIOD)
+			    || (atoi(argv[0]) > MAX_BEACON_PERIOD)) {
+				printf("ERR: BEACONPERIOD must be in range of %d to %d.\n", MIN_BEACON_PERIOD, MAX_BEACON_PERIOD);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case RETRYLIMIT:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for RETRY LIMIT\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_RETRY_LIMIT) ||
+			    (atoi(argv[0]) < 0)) {
+				printf("ERR:RETRY_LIMIT must be in the range of [0:%d]. The  input was %s.\n", MAX_RETRY_LIMIT, argv[0]);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case STICKYTIMCONFIG:
+		if ((argc != 1) && (argc != 3)) {
+			printf("ERR:Incorrect number of arguments for STICKY_TIM_CONFIG\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			    (atoi(argv[0]) > 2)) {
+				printf("ERR:Enable parameter must be 0, 1 or 2\n");
+				ret = UAP_FAILURE;
+				break;
+			}
+			if (((atoi(argv[0]) != 1) && (argc > 1))) {
+				printf("ERR: Invalid arguments\n");
+				ret = UAP_FAILURE;
+				break;
+			}
+			if ((atoi(argv[0]) == 1) && (argc != 3)) {
+				printf("ERR: Both duration and sticky bit mask must be provided for ENABLE = 1\n");
+				ret = UAP_FAILURE;
+				break;
+			}
+			if (argc > 1) {
+				if ((ISDIGIT(argv[1]) == 0)) {
+					printf("ERR: Invalid duration\n");
+					ret = UAP_FAILURE;
+					break;
+				}
+				if ((ISDIGIT(argv[2]) == 0) ||
+				    (atoi(argv[2]) < 1) ||
+				    (atoi(argv[2]) > 3)) {
+					printf("ERR:Invalid sticky bit mask\n");
+					ret = UAP_FAILURE;
+					break;
+				}
+			}
+		}
+		break;
+	case STICKYTIMSTAMACADDR:
+		if ((argc != 1) && (argc != 2)) {
+			printf("ERR:Incorrect number of STICKY_TIM_STA_MAC_ADDR arguments\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((argc == 2) &&
+			    ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			     (atoi(argv[0]) > 1))) {
+				printf("ERR:Invalid control parameter\n");
+				ret = UAP_FAILURE;
+				break;
+			}
+		}
+		break;
+	case COEX2040CONFIG:
+		if (argc != 1) {
+			printf("ERR: Incorrect number of 2040 COEX CONFIG arguments\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			    (atoi(argv[0]) > 1)) {
+				printf("ERR:Invalid enable parameter\n");
+				ret = UAP_FAILURE;
+				break;
+			}
+		}
+		break;
+	case EAPOL_PWK_HSK:
+		if (argc != 2) {
+			printf("ERR:Incorrect number of EAPOL_PWK_HSK arguments.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)
+			    || (atoi(argv[0]) < 0) || (atoi(argv[1]) < 0)) {
+				printf("ERR:Illegal parameters for EAPOL_PWK_HSK. Must be digits greater than equal to zero.\n");
+			}
+		}
+		break;
+	case EAPOL_GWK_HSK:
+		if (argc != 2) {
+			printf("ERR:Incorrect number of EAPOL_GWK_HSK arguments.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)
+			    || (atoi(argv[0]) < 0) || (atoi(argv[1]) < 0)) {
+				printf("ERR:Illegal parameters for EAPOL_GWK_HSK. Must be digits greater than equal to zero.\n");
+			}
+		}
+		break;
+	case PREAMBLETYPE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for PREAMBLE TYPE\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_PREAMBLE_TYPE) ||
+			    (atoi(argv[0]) < 0)) {
+				printf("ERR:PREAMBLE TYPE must be in the range of [0:%d]. The  input was %s.\n", MAX_PREAMBLE_TYPE, argv[0]);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+
+	case COEX_COMM_BITMAP:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of argument for Bitmap.\n");
+			ret = UAP_FAILURE;
+		} else {
+			/* Only bit 0 is supported now, hence check for 1 or 0 */
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) < 0) || (atoi(argv[0]) > 1)) {
+				printf("ERR: Bitmap must have value of 1 or 0.\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case COEX_COMM_AP_COEX:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of argument for APBTCoex.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) < 0) || (atoi(argv[0]) > 1)) {
+				printf("ERR: APBTCoex must have value of 1 or 0.\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case COEX_SCO_ACL_FREQ:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for aclFrequency.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR: Incorrect value for aclFrequency.\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case COEX_ACL_ENABLED:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for (acl) enabled.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			    (atoi(argv[0]) > 1)) {
+				printf("ERR: (acl) enabled must have value of 1 or 0.\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case COEX_ACL_BT_TIME:
+	case COEX_ACL_WLAN_TIME:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for bt/wlan time.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR: Incorrect value for bt/wlan time.\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case COEX_PROTECTION:
+		if (argc != 2) {
+			printf("ERR:Incorrect number of arguments for %s.\n",
+			       argv[0]);
+			ret = UAP_FAILURE;
+		} else {
+			if (ISDIGIT(argv[1]) == 0) {
+				printf("ERR: Incorrect value for %s.\n",
+				       argv[0]);
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case PWK_CIPHER:
+		if ((argc != 1) && (argc != 2)) {
+			printf("ERR:Incorrect number of arguments for pwk_cipher.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) & ~PROTOCOL_BITMAP)) {
+				printf("Invalid Protocol paramter.\n");
+				ret = UAP_FAILURE;
+			}
+			if (argc == 2) {
+				if ((ISDIGIT(argv[1]) == 0) ||
+				    (atoi(argv[1]) & ~CIPHER_BITMAP)) {
+					printf("Invalid pairwise cipher.\n");
+					ret = UAP_FAILURE;
+				}
+			}
+		}
+		break;
+	case GWK_CIPHER:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for gwk_cipher.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) & ~CIPHER_BITMAP) ||
+			    (atoi(argv[0]) == AES_CCMP_TKIP)) {
+				printf("Invalid group cipher.\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	case RESTRICT_CLIENT_MODE:
+		if ((argc != 1) && (argc != 2)) {
+			printf("ERR: Incorrect number of arguments.\n");
+			ret = UAP_FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || ((argc == 2) &&
+							((IS_HEX_OR_DIGIT
+							  (argv[1]) == 0) ||
+							 ((atoi(argv[0]) < 0) ||
+							  (atoi(argv[0]) >
+							   1))))) {
+				printf("ERR: Invalid arguments\n");
+				ret = UAP_FAILURE;
+			}
+			if ((atoi(argv[0]) == 1) && (argc == 1)) {
+				printf("ERR: Mode_config parameter must be provided to enable this feature.\n");
+				ret = UAP_FAILURE;
+			}
+			if ((argc == 2) &&
+			    (((A2HEXDECIMAL(argv[1]) << 8) != B_ONLY_MASK) &&
+			     ((A2HEXDECIMAL(argv[1]) << 8) != G_ONLY_MASK) &&
+			     ((A2HEXDECIMAL(argv[1]) << 8) != A_ONLY_MASK) &&
+			     ((A2HEXDECIMAL(argv[1]) << 8) != N_ONLY_MASK) &&
+			     ((A2HEXDECIMAL(argv[1]) << 8) != AC_ONLY_MASK))) {
+				printf("ERR: Exactly one mode can be enabled at a time.\n");
+				ret = UAP_FAILURE;
+			}
+		}
+		break;
+	default:
+		ret = UAP_FAILURE;
+		break;
+	}
+	return ret;
+}
+
+/**
+ *  @brief Converts colon separated MAC address to hex value
+ *
+ *  @param mac      A pointer to the colon separated MAC string
+ *  @param raw      A pointer to the hex data buffer
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ *                  UAP_RET_MAC_BROADCAST  - if broadcast mac
+ *                  UAP_RET_MAC_MULTICAST - if multicast mac
+ */
+int
+mac2raw(char *mac, t_u8 *raw)
+{
+	unsigned int temp_raw[ETH_ALEN];
+	int num_tokens = 0;
+	int i;
+	if (strlen(mac) != ((2 * ETH_ALEN) + (ETH_ALEN - 1))) {
+		return UAP_FAILURE;
+	}
+	num_tokens = sscanf(mac, "%2x:%2x:%2x:%2x:%2x:%2x",
+			    temp_raw + 0, temp_raw + 1, temp_raw + 2,
+			    temp_raw + 3, temp_raw + 4, temp_raw + 5);
+	if (num_tokens != ETH_ALEN) {
+		return UAP_FAILURE;
+	}
+	for (i = 0; i < num_tokens; i++)
+		raw[i] = (t_u8)temp_raw[i];
+
+	if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) {
+		return UAP_RET_MAC_BROADCAST;
+	} else if (raw[0] & 0x01) {
+		return UAP_RET_MAC_MULTICAST;
+	}
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Converts a string to hex value
+ *
+ *  @param str      A pointer to the string
+ *  @param raw      A pointer to the raw data buffer
+ *  @return         Number of bytes read
+ */
+int
+string2raw(char *str, unsigned char *raw)
+{
+	int len = (strlen(str) + 1) / 2;
+
+	do {
+		if (!isxdigit(*str)) {
+			return -1;
+		}
+		*str = toupper(*str);
+		*raw = CHAR2INT(*str) << 4;
+		++str;
+		*str = toupper(*str);
+		if (*str == '\0')
+			break;
+		*raw |= CHAR2INT(*str);
+		++raw;
+	} while (*++str != '\0');
+	return len;
+}
+
+/**
+ *  @brief Prints a MAC address in colon separated form from hex data
+ *
+ *  @param raw      A pointer to the hex data buffer
+ *  @return         N/A
+ */
+void
+print_mac(t_u8 *raw)
+{
+	printf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)raw[0],
+	       (unsigned int)raw[1], (unsigned int)raw[2], (unsigned int)raw[3],
+	       (unsigned int)raw[4], (unsigned int)raw[5]);
+	return;
+}
+
+/**
+ *  @brief 		Check hex string
+ *
+ *  @param hex		A pointer to hex string
+ *  @return      	UAP_SUCCESS or UAP_FAILURE
+ */
+int
+ishexstring(void *hex)
+{
+	int i, a;
+	char *p = hex;
+	int len = strlen(p);
+	if (!strncasecmp("0x", p, 2)) {
+		p += 2;
+		len -= 2;
+	}
+	for (i = 0; i < len; i++) {
+		a = hex2num(*p);
+		if (a < 0)
+			return UAP_FAILURE;
+		p++;
+	}
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Show auth tlv
+ *
+ *  @param tlv     Pointer to auth tlv
+ *
+ *  $return         N/A
+ */
+void
+print_auth(tlvbuf_auth_mode *tlv)
+{
+	switch (tlv->auth_mode) {
+	case 0:
+		printf("AUTHMODE = Open authentication\n");
+		break;
+	case 1:
+		printf("AUTHMODE = Shared key authentication\n");
+		break;
+	case 255:
+		printf("AUTHMODE = Auto (open and shared key)\n");
+		break;
+	default:
+		printf("ERR: Invalid authmode=%d\n", tlv->auth_mode);
+		break;
+	}
+}
+
+/**
+ *
+ *  @brief Show cipher tlv
+ *
+ *  @param tlv     Pointer to cipher tlv
+ *
+ *  $return         N/A
+ */
+void
+print_cipher(tlvbuf_cipher *tlv)
+{
+	switch (tlv->pairwise_cipher) {
+	case CIPHER_TKIP:
+		printf("PairwiseCipher = TKIP\n");
+		break;
+	case CIPHER_AES_CCMP:
+		printf("PairwiseCipher = AES CCMP\n");
+		break;
+	case CIPHER_TKIP | CIPHER_AES_CCMP:
+		printf("PairwiseCipher = TKIP + AES CCMP\n");
+		break;
+	case CIPHER_NONE:
+		printf("PairwiseCipher =  None\n");
+		break;
+	default:
+		printf("Unknown Pairwise cipher 0x%x\n", tlv->pairwise_cipher);
+		break;
+	}
+	switch (tlv->group_cipher) {
+	case CIPHER_TKIP:
+		printf("GroupCipher = TKIP\n");
+		break;
+	case CIPHER_AES_CCMP:
+		printf("GroupCipher = AES CCMP\n");
+		break;
+	case CIPHER_NONE:
+		printf("GroupCipher = None\n");
+		break;
+	default:
+		printf("Unknown Group cipher 0x%x\n", tlv->group_cipher);
+		break;
+	}
+}
+
+/**
+ *  @brief Show pairwise cipher tlv
+ *
+ *  @param tlv     Pointer to pairwise cipher tlv
+ *
+ *  $return         N/A
+ */
+void
+print_pwk_cipher(tlvbuf_pwk_cipher *tlv)
+{
+	switch (tlv->protocol) {
+	case PROTOCOL_WPA:
+		printf("Protocol WPA  : ");
+		break;
+	case PROTOCOL_WPA2:
+		printf("Protocol WPA2 : ");
+		break;
+	default:
+		printf("Unknown Protocol 0x%x\n", tlv->protocol);
+		break;
+	}
+
+	switch (tlv->pairwise_cipher) {
+	case CIPHER_TKIP:
+		printf("PairwiseCipher = TKIP\n");
+		break;
+	case CIPHER_AES_CCMP:
+		printf("PairwiseCipher = AES CCMP\n");
+		break;
+	case CIPHER_TKIP | CIPHER_AES_CCMP:
+		printf("PairwiseCipher = TKIP + AES CCMP\n");
+		break;
+	case CIPHER_NONE:
+		printf("PairwiseCipher =  None\n");
+		break;
+	default:
+		printf("Unknown Pairwise cipher 0x%x\n", tlv->pairwise_cipher);
+		break;
+	}
+}
+
+/**
+ *  @brief Show group cipher tlv
+ *
+ *  @param tlv     Pointer to group cipher tlv
+ *
+ *  $return         N/A
+ */
+void
+print_gwk_cipher(tlvbuf_gwk_cipher *tlv)
+{
+	switch (tlv->group_cipher) {
+	case CIPHER_TKIP:
+		printf("GroupCipher = TKIP\n");
+		break;
+	case CIPHER_AES_CCMP:
+		printf("GroupCipher = AES CCMP\n");
+		break;
+	case CIPHER_NONE:
+		printf("GroupCipher = None\n");
+		break;
+	default:
+		printf("Unknown Group cipher 0x%x\n", tlv->group_cipher);
+		break;
+	}
+}
+
+/**
+ *  @brief Show mac filter tlv
+ *
+ *  @param tlv     Pointer to filter tlv
+ *
+ *  $return         N/A
+ */
+void
+print_mac_filter(tlvbuf_sta_mac_addr_filter *tlv)
+{
+	int i;
+	switch (tlv->filter_mode) {
+	case 0:
+		printf("Filter Mode = Filter table is disabled\n");
+		return;
+	case 1:
+		if (!tlv->count) {
+			printf("No mac address is allowed to connect\n");
+		} else {
+			printf("Filter Mode = Allow mac address specified in the allowed list\n");
+		}
+		break;
+	case 2:
+		if (!tlv->count) {
+			printf("No mac address is blocked\n");
+		} else {
+			printf("Filter Mode = Block MAC addresses specified in the banned list\n");
+		}
+		break;
+	}
+	for (i = 0; i < tlv->count; i++) {
+		printf("MAC_%d = ", i);
+		print_mac(&tlv->mac_address[i * ETH_ALEN]);
+		printf("\n");
+	}
+}
+
+/**
+ *  @brief Show rate tlv
+ *
+ *  @param tlv      Pointer to rate tlv
+ *
+ *  $return         N/A
+ */
+void
+print_rate(tlvbuf_rates *tlv)
+{
+	int flag = 0;
+	int i;
+	t_u16 tlv_len;
+
+	tlv_len = *(t_u8 *)&tlv->length;
+	tlv_len |= (*((t_u8 *)&tlv->length + 1) << 8);
+
+	printf("Basic Rates =");
+	for (i = 0; i < tlv_len; i++) {
+		if (tlv->operational_rates[i] > (BASIC_RATE_SET_BIT - 1)) {
+			flag = flag ? : 1;
+			printf(" 0x%x", tlv->operational_rates[i]);
+		}
+	}
+	printf("%s\nNon-Basic Rates =", flag ? "" : " ( none ) ");
+	for (flag = 0, i = 0; i < tlv_len; i++) {
+		if (tlv->operational_rates[i] < BASIC_RATE_SET_BIT) {
+			flag = flag ? : 1;
+			printf(" 0x%x", tlv->operational_rates[i]);
+		}
+	}
+	printf("%s\n", flag ? "" : " ( none ) ");
+}
+
+/**
+ *  @brief Show all the tlv in the buf
+ *
+ *  @param buf     Pointer to tlv buffer
+ *  @param len     Tlv buffer len
+ *
+ *  $return         N/A
+ */
+void
+print_tlv(t_u8 *buf, t_u16 len)
+{
+	tlvbuf_header *pcurrent_tlv = (tlvbuf_header *)buf;
+	int tlv_buf_left = len;
+	t_u16 tlv_type;
+	t_u16 tlv_len;
+	t_u16 tlv_val_16;
+	t_u32 tlv_val_32;
+	t_u8 ssid[33];
+	int i = 0;
+	tlvbuf_ap_mac_address *mac_tlv;
+	tlvbuf_ssid *ssid_tlv;
+	tlvbuf_beacon_period *beacon_tlv;
+	tlvbuf_dtim_period *dtim_tlv;
+	tlvbuf_rates *rates_tlv;
+	tlvbuf_tx_power *txpower_tlv;
+	tlvbuf_bcast_ssid_ctl *bcast_tlv;
+	tlvbuf_preamble_ctl *preamble_tlv;
+	tlvbuf_bss_status *bss_status_tlv;
+	tlvbuf_rts_threshold *rts_tlv;
+	tlvbuf_mcbc_data_rate *mcbcrate_tlv;
+	tlvbuf_pkt_fwd_ctl *pkt_fwd_tlv;
+	tlvbuf_sta_ageout_timer *ageout_tlv;
+	tlvbuf_ps_sta_ageout_timer *ps_ageout_tlv;
+	tlvbuf_auth_mode *auth_tlv;
+	tlvbuf_protocol *proto_tlv;
+	tlvbuf_akmp *akmp_tlv;
+	tlvbuf_cipher *cipher_tlv;
+	tlvbuf_pwk_cipher *pwk_cipher_tlv;
+	tlvbuf_gwk_cipher *gwk_cipher_tlv;
+	tlvbuf_group_rekey_timer *rekey_tlv;
+	tlvbuf_wpa_passphrase *psk_tlv;
+	tlvbuf_coex_common_cfg *coex_common_tlv;
+	tlvbuf_coex_sco_cfg *coex_sco_tlv;
+	tlvbuf_coex_acl_cfg *coex_acl_tlv;
+	tlvbuf_coex_stats *coex_stats_tlv;
+	tlvbuf_wep_key *wep_tlv;
+	tlvbuf_frag_threshold *frag_tlv;
+	tlvbuf_sta_mac_addr_filter *filter_tlv;
+	tlvbuf_max_sta_num *max_sta_tlv;
+	tlvbuf_retry_limit *retry_limit_tlv;
+	tlvbuf_eapol_pwk_hsk_timeout *pwk_timeout_tlv;
+	tlvbuf_eapol_pwk_hsk_retries *pwk_retries_tlv;
+	tlvbuf_eapol_gwk_hsk_timeout *gwk_timeout_tlv;
+	tlvbuf_eapol_gwk_hsk_retries *gwk_retries_tlv;
+	tlvbuf_channel_config *channel_tlv;
+	tlvbuf_channel_list *chnlist_tlv;
+	channel_list *pchan_list;
+	t_u16 custom_ie_len;
+	tlvbuf_rsn_replay_prot *replay_prot_tlv;
+	tlvbuf_custom_ie *custom_ie_tlv;
+	custom_ie *custom_ie_ptr;
+	tlvbuf_max_mgmt_ie *max_mgmt_ie_tlv;
+	tlvbuf_wmm_para_t *wmm_para_tlv;
+	int flag = 0;
+	tlvbuf_htcap_t *ht_cap_tlv;
+	tlvbuf_htinfo_t *ht_info_tlv;
+	tlvbuf_2040_coex *coex_2040_tlv;
+
+#ifdef RX_PACKET_COALESCE
+	tlvbuf_rx_pkt_coal_t *rx_pkt_coal_tlv;
+#endif
+
+#if DEBUG
+	uap_printf(MSG_DEBUG, "tlv total len=%d\n", len);
+#endif
+	while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
+		tlv_type = *(t_u8 *)&pcurrent_tlv->type;
+		tlv_type |= (*((t_u8 *)&pcurrent_tlv->type + 1) << 8);
+		tlv_len = *(t_u8 *)&pcurrent_tlv->len;
+		tlv_len |= (*((t_u8 *)&pcurrent_tlv->len + 1) << 8);
+		if ((sizeof(tlvbuf_header) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			printf("wrong tlv: tlv_len=%d, tlv_buf_left=%d\n",
+			       tlv_len, tlv_buf_left);
+			break;
+		}
+		switch (tlv_type) {
+		case MRVL_AP_MAC_ADDRESS_TLV_ID:
+			mac_tlv = (tlvbuf_ap_mac_address *)pcurrent_tlv;
+			printf("AP MAC address = ");
+			print_mac(mac_tlv->ap_mac_addr);
+			printf("\n");
+			break;
+		case MRVL_SSID_TLV_ID:
+			memset(ssid, 0, sizeof(ssid));
+			ssid_tlv = (tlvbuf_ssid *)pcurrent_tlv;
+			memcpy(ssid, ssid_tlv->ssid, tlv_len);
+			printf("SSID = %s\n", ssid);
+			break;
+		case MRVL_BEACON_PERIOD_TLV_ID:
+			beacon_tlv = (tlvbuf_beacon_period *)pcurrent_tlv;
+			tlv_val_16 = *(t_u8 *)&beacon_tlv->beacon_period_ms;
+			tlv_val_16 |=
+				(*((t_u8 *)&beacon_tlv->beacon_period_ms + 1) <<
+				 8);
+			printf("Beacon period = %d\n", tlv_val_16);
+			break;
+		case MRVL_DTIM_PERIOD_TLV_ID:
+			dtim_tlv = (tlvbuf_dtim_period *)pcurrent_tlv;
+			printf("DTIM period = %d\n", dtim_tlv->dtim_period);
+			break;
+		case MRVL_CHANNELCONFIG_TLV_ID:
+			channel_tlv = (tlvbuf_channel_config *)pcurrent_tlv;
+			printf("Channel = %d\n", channel_tlv->chan_number);
+			printf("Band = %s\n",
+			       (channel_tlv->bandcfg.chanBand ==
+				BAND_5GHZ) ? "5GHz" : "2.4GHz");
+			printf("Channel Select Mode = %s\n",
+			       (channel_tlv->bandcfg.scanMode ==
+				SCAN_MODE_ACS) ? "ACS" : "Manual");
+			if (channel_tlv->bandcfg.chan2Offset == SEC_CHAN_NONE)
+				printf("no secondary channel\n");
+			else if (channel_tlv->bandcfg.chan2Offset ==
+				 SEC_CHAN_ABOVE)
+				printf("secondary channel is above primary channel\n");
+			else if (channel_tlv->bandcfg.chan2Offset ==
+				 SEC_CHAN_BELOW)
+				printf("secondary channel is below primary channel\n");
+			break;
+		case MRVL_CHANNELLIST_TLV_ID:
+			chnlist_tlv = (tlvbuf_channel_list *)pcurrent_tlv;
+			printf("Channels List = ");
+			pchan_list =
+				(channel_list *) & (chnlist_tlv->chan_list);
+			if (tlv_len % sizeof(channel_list)) {
+				break;
+			}
+			for (i = 0;
+			     (unsigned int)i < (tlv_len / sizeof(channel_list));
+			     i++) {
+				printf("\n%d\t%sGHz", pchan_list->chan_number,
+				       (pchan_list->bandcfg.chanBand ==
+					BAND_5GHZ) ? "5" : "2.4");
+				pchan_list++;
+			}
+			printf("\n");
+			break;
+		case MRVL_RSN_REPLAY_PROT_TLV_ID:
+			replay_prot_tlv =
+				(tlvbuf_rsn_replay_prot *)pcurrent_tlv;
+			printf("RSN replay protection = %s\n",
+			       replay_prot_tlv->
+			       rsn_replay_prot ? "enabled" : "disabled");
+			break;
+		case MRVL_RATES_TLV_ID:
+			rates_tlv = (tlvbuf_rates *)pcurrent_tlv;
+			print_rate(rates_tlv);
+			break;
+		case MRVL_TX_POWER_TLV_ID:
+			txpower_tlv = (tlvbuf_tx_power *)pcurrent_tlv;
+			printf("Tx power = %d dBm\n",
+			       txpower_tlv->tx_power_dbm);
+			break;
+		case MRVL_BCAST_SSID_CTL_TLV_ID:
+			bcast_tlv = (tlvbuf_bcast_ssid_ctl *)pcurrent_tlv;
+			printf("SSID broadcast = %s\n",
+			       (bcast_tlv->bcast_ssid_ctl ==
+				1) ? "enabled" : "disabled");
+			break;
+		case MRVL_PREAMBLE_CTL_TLV_ID:
+			preamble_tlv = (tlvbuf_preamble_ctl *)pcurrent_tlv;
+			printf("Preamble type = %s\n",
+			       (preamble_tlv->preamble_type ==
+				0) ? "auto" : ((preamble_tlv->preamble_type ==
+						1) ? "short" : "long"));
+			break;
+		case MRVL_BSS_STATUS_TLV_ID:
+			bss_status_tlv = (tlvbuf_bss_status *)pcurrent_tlv;
+			printf("BSS status = %s\n",
+			       (bss_status_tlv->bss_status ==
+				0) ? "stopped" : "started");
+			break;
+		case MRVL_RTS_THRESHOLD_TLV_ID:
+			rts_tlv = (tlvbuf_rts_threshold *)pcurrent_tlv;
+			tlv_val_16 = *(t_u8 *)&rts_tlv->rts_threshold;
+			tlv_val_16 |=
+				(*((t_u8 *)&rts_tlv->rts_threshold + 1) << 8);
+			printf("RTS threshold = %d\n", tlv_val_16);
+			break;
+		case MRVL_FRAG_THRESHOLD_TLV_ID:
+			frag_tlv = (tlvbuf_frag_threshold *)pcurrent_tlv;
+			tlv_val_16 = *(t_u8 *)&frag_tlv->frag_threshold;
+			tlv_val_16 |=
+				(*((t_u8 *)&frag_tlv->frag_threshold + 1) << 8);
+			printf("Fragmentation threshold = %d\n", tlv_val_16);
+			break;
+		case MRVL_MCBC_DATA_RATE_TLV_ID:
+			mcbcrate_tlv = (tlvbuf_mcbc_data_rate *)pcurrent_tlv;
+			tlv_val_16 = *(t_u8 *)&mcbcrate_tlv->mcbc_datarate;
+			tlv_val_16 |=
+				(*((t_u8 *)&mcbcrate_tlv->mcbc_datarate + 1) <<
+				 8);
+			if (mcbcrate_tlv->mcbc_datarate == 0)
+				printf("MCBC data rate = auto\n");
+			else
+				printf("MCBC data rate = 0x%x\n", tlv_val_16);
+			break;
+		case MRVL_PKT_FWD_CTL_TLV_ID:
+			pkt_fwd_tlv = (tlvbuf_pkt_fwd_ctl *)pcurrent_tlv;
+			printf("%s handles packet forwarding -\n",
+			       ((pkt_fwd_tlv->pkt_fwd_ctl & PKT_FWD_FW_BIT) ==
+				0) ? "Host" : "Firmware");
+			printf("\tIntra-BSS broadcast packets are %s\n",
+			       ((pkt_fwd_tlv->
+				 pkt_fwd_ctl & PKT_FWD_INTRA_BCAST) ==
+				0) ? "allowed" : "denied");
+			printf("\tIntra-BSS unicast packets are %s\n",
+			       ((pkt_fwd_tlv->
+				 pkt_fwd_ctl & PKT_FWD_INTRA_UCAST) ==
+				0) ? "allowed" : "denied");
+			printf("\tInter-BSS unicast packets are %s\n",
+			       ((pkt_fwd_tlv->
+				 pkt_fwd_ctl & PKT_FWD_INTER_UCAST) ==
+				0) ? "allowed" : "denied");
+			break;
+		case MRVL_STA_AGEOUT_TIMER_TLV_ID:
+			ageout_tlv = (tlvbuf_sta_ageout_timer *)pcurrent_tlv;
+			tlv_val_32 = *(t_u8 *)&ageout_tlv->sta_ageout_timer_ms;
+			tlv_val_32 |=
+				(*((t_u8 *)&ageout_tlv->sta_ageout_timer_ms + 1)
+				 << 8);
+			tlv_val_32 |=
+				(*((t_u8 *)&ageout_tlv->sta_ageout_timer_ms + 2)
+				 << 16);
+			tlv_val_32 |=
+				(*((t_u8 *)&ageout_tlv->sta_ageout_timer_ms + 3)
+				 << 24);
+			printf("STA ageout timer = %d\n", (int)tlv_val_32);
+			break;
+		case MRVL_PS_STA_AGEOUT_TIMER_TLV_ID:
+			ps_ageout_tlv =
+				(tlvbuf_ps_sta_ageout_timer *)pcurrent_tlv;
+			tlv_val_32 =
+				*(t_u8 *)&ps_ageout_tlv->ps_sta_ageout_timer_ms;
+			tlv_val_32 |=
+				(*
+				 ((t_u8 *)&ps_ageout_tlv->
+				  ps_sta_ageout_timer_ms + 1) << 8);
+			tlv_val_32 |=
+				(*
+				 ((t_u8 *)&ps_ageout_tlv->
+				  ps_sta_ageout_timer_ms + 2) << 16);
+			tlv_val_32 |=
+				(*
+				 ((t_u8 *)&ps_ageout_tlv->
+				  ps_sta_ageout_timer_ms + 3) << 24);
+			printf("PS STA ageout timer = %d\n", (int)tlv_val_32);
+			break;
+		case MRVL_AUTH_TLV_ID:
+			auth_tlv = (tlvbuf_auth_mode *)pcurrent_tlv;
+			print_auth(auth_tlv);
+			break;
+		case MRVL_PROTOCOL_TLV_ID:
+			proto_tlv = (tlvbuf_protocol *)pcurrent_tlv;
+			tlv_val_16 = *(t_u8 *)&proto_tlv->protocol;
+			tlv_val_16 |=
+				(*((t_u8 *)&proto_tlv->protocol + 1) << 8);
+			print_protocol(tlv_val_16);
+			break;
+		case MRVL_AKMP_TLV_ID:
+			akmp_tlv = (tlvbuf_akmp *)pcurrent_tlv;
+			tlv_val_16 = *(t_u8 *)&akmp_tlv->key_mgmt;
+			tlv_val_16 |= (*((t_u8 *)&akmp_tlv->key_mgmt + 1) << 8);
+			if (tlv_val_16 & (KEY_MGMT_PSK | KEY_MGMT_PSK_SHA256)) {
+				if (tlv_val_16 & KEY_MGMT_PSK)
+					printf("KeyMgmt = PSK\n");
+				if (tlv_val_16 & KEY_MGMT_PSK_SHA256)
+					printf("KeyMgmt = PSK_SHA256\n");
+				tlv_val_16 =
+					*(t_u8 *)&akmp_tlv->key_mgmt_operation;
+				if (tlv_len > sizeof(t_u16)) {
+					tlv_val_16 |=
+						(*
+						 ((t_u8 *)&akmp_tlv->
+						  key_mgmt_operation + 1) << 8);
+					printf("Key Exchange on : %s.\n",
+					       (tlv_val_16 & 0x01) ? "Host" :
+					       "Device");
+					printf("1x Authentication on : %s.\n",
+					       (tlv_val_16 & 0x10) ? "Host" :
+					       "Device");
+				}
+			}
+			if (tlv_val_16 & KEY_MGMT_EAP)
+				printf("KeyMgmt = EAP");
+			if (tlv_val_16 & KEY_MGMT_NONE)
+				printf("KeyMgmt = NONE");
+			break;
+		case MRVL_CIPHER_TLV_ID:
+			cipher_tlv = (tlvbuf_cipher *)pcurrent_tlv;
+			print_cipher(cipher_tlv);
+			break;
+		case MRVL_CIPHER_PWK_TLV_ID:
+			pwk_cipher_tlv = (tlvbuf_pwk_cipher *)pcurrent_tlv;
+			pwk_cipher_tlv->protocol =
+				uap_le16_to_cpu(pwk_cipher_tlv->protocol);
+			print_pwk_cipher(pwk_cipher_tlv);
+			break;
+		case MRVL_CIPHER_GWK_TLV_ID:
+			gwk_cipher_tlv = (tlvbuf_gwk_cipher *)pcurrent_tlv;
+			print_gwk_cipher(gwk_cipher_tlv);
+			break;
+		case MRVL_GRP_REKEY_TIME_TLV_ID:
+			rekey_tlv = (tlvbuf_group_rekey_timer *)pcurrent_tlv;
+			tlv_val_32 = *(t_u8 *)&rekey_tlv->group_rekey_time_sec;
+			tlv_val_32 |=
+				(*((t_u8 *)&rekey_tlv->group_rekey_time_sec + 1)
+				 << 8);
+			tlv_val_32 |=
+				(*((t_u8 *)&rekey_tlv->group_rekey_time_sec + 2)
+				 << 16);
+			tlv_val_32 |=
+				(*((t_u8 *)&rekey_tlv->group_rekey_time_sec + 3)
+				 << 24);
+			if (tlv_val_32 == 0)
+				printf("Group re-key time = disabled\n");
+			else
+				printf("Group re-key time = %d second\n",
+				       tlv_val_32);
+			break;
+		case MRVL_WPA_PASSPHRASE_TLV_ID:
+			psk_tlv = (tlvbuf_wpa_passphrase *)pcurrent_tlv;
+			if (tlv_len > 0) {
+				printf("WPA passphrase = ");
+				for (i = 0; i < tlv_len; i++)
+					printf("%c", psk_tlv->passphrase[i]);
+				printf("\n");
+			} else
+				printf("WPA passphrase = None\n");
+			break;
+		case MRVL_WEP_KEY_TLV_ID:
+			wep_tlv = (tlvbuf_wep_key *)pcurrent_tlv;
+			print_wep_key(wep_tlv);
+			break;
+		case MRVL_STA_MAC_ADDR_FILTER_TLV_ID:
+			filter_tlv = (tlvbuf_sta_mac_addr_filter *)pcurrent_tlv;
+			print_mac_filter(filter_tlv);
+			break;
+		case MRVL_MAX_STA_CNT_TLV_ID:
+			max_sta_tlv = (tlvbuf_max_sta_num *)pcurrent_tlv;
+			tlv_val_16 =
+				*(t_u8 *)&max_sta_tlv->max_sta_num_configured;
+			tlv_val_16 |=
+				(*
+				 ((t_u8 *)&max_sta_tlv->max_sta_num_configured +
+				  1) << 8);
+			printf("Max Station Number configured = %d\n",
+			       tlv_val_16);
+			if (max_sta_tlv->length == 4) {
+				tlv_val_16 =
+					*(t_u8 *)&max_sta_tlv->
+					max_sta_num_supported;
+				tlv_val_16 |=
+					(*
+					 ((t_u8 *)&max_sta_tlv->
+					  max_sta_num_supported + 1) << 8);
+				printf("Max Station Number supported = %d\n",
+				       tlv_val_16);
+			}
+			break;
+		case MRVL_RETRY_LIMIT_TLV_ID:
+			retry_limit_tlv = (tlvbuf_retry_limit *)pcurrent_tlv;
+			printf("Retry Limit = %d\n",
+			       retry_limit_tlv->retry_limit);
+			break;
+		case MRVL_EAPOL_PWK_HSK_TIMEOUT_TLV_ID:
+			pwk_timeout_tlv =
+				(tlvbuf_eapol_pwk_hsk_timeout *)pcurrent_tlv;
+			pwk_timeout_tlv->pairwise_update_timeout =
+				uap_le32_to_cpu(pwk_timeout_tlv->
+						pairwise_update_timeout);
+			printf("Pairwise handshake timeout = %d\n",
+			       pwk_timeout_tlv->pairwise_update_timeout);
+			break;
+		case MRVL_EAPOL_PWK_HSK_RETRIES_TLV_ID:
+			pwk_retries_tlv =
+				(tlvbuf_eapol_pwk_hsk_retries *)pcurrent_tlv;
+			pwk_retries_tlv->pwk_retries =
+				uap_le32_to_cpu(pwk_retries_tlv->pwk_retries);
+			printf("Pairwise handshake retries = %d\n",
+			       pwk_retries_tlv->pwk_retries);
+			break;
+		case MRVL_EAPOL_GWK_HSK_TIMEOUT_TLV_ID:
+			gwk_timeout_tlv =
+				(tlvbuf_eapol_gwk_hsk_timeout *)pcurrent_tlv;
+			gwk_timeout_tlv->groupwise_update_timeout =
+				uap_le32_to_cpu(gwk_timeout_tlv->
+						groupwise_update_timeout);
+			printf("Groupwise handshake timeout = %d\n",
+			       gwk_timeout_tlv->groupwise_update_timeout);
+			break;
+		case MRVL_EAPOL_GWK_HSK_RETRIES_TLV_ID:
+			gwk_retries_tlv =
+				(tlvbuf_eapol_gwk_hsk_retries *)pcurrent_tlv;
+			gwk_retries_tlv->gwk_retries =
+				uap_le32_to_cpu(gwk_retries_tlv->gwk_retries);
+			printf("Groupwise handshake retries = %d\n",
+			       gwk_retries_tlv->gwk_retries);
+			break;
+		case MRVL_MGMT_IE_LIST_TLV_ID:
+			custom_ie_tlv = (tlvbuf_custom_ie *)pcurrent_tlv;
+			custom_ie_len = tlv_len;
+			custom_ie_ptr = (custom_ie *)(custom_ie_tlv->ie_data);
+			while (custom_ie_len >= sizeof(custom_ie)) {
+				custom_ie_ptr->ie_index =
+					uap_le16_to_cpu(custom_ie_ptr->
+							ie_index);
+				custom_ie_ptr->ie_length =
+					uap_le16_to_cpu(custom_ie_ptr->
+							ie_length);
+				custom_ie_ptr->mgmt_subtype_mask =
+					uap_le16_to_cpu(custom_ie_ptr->
+							mgmt_subtype_mask);
+				printf("Index [%d]\n", custom_ie_ptr->ie_index);
+				if (custom_ie_ptr->ie_length)
+					printf("Management Subtype Mask = 0x%02x\n", custom_ie_ptr->mgmt_subtype_mask == 0 ? UAP_CUSTOM_IE_AUTO_MASK : custom_ie_ptr->mgmt_subtype_mask);
+				else
+					printf("Management Subtype Mask = 0x%02x\n", custom_ie_ptr->mgmt_subtype_mask);
+				hexdump_data("IE Buffer",
+					     (void *)custom_ie_ptr->ie_buffer,
+					     (custom_ie_ptr->ie_length), ' ');
+				custom_ie_len -=
+					sizeof(custom_ie) +
+					custom_ie_ptr->ie_length;
+				custom_ie_ptr =
+					(custom_ie *)((t_u8 *)custom_ie_ptr +
+						      sizeof(custom_ie) +
+						      custom_ie_ptr->ie_length);
+			}
+			custom_ie_present = 1;
+			break;
+		case MRVL_MAX_MGMT_IE_TLV_ID:
+			max_mgmt_ie_tlv = (tlvbuf_max_mgmt_ie *)pcurrent_tlv;
+			max_mgmt_ie_tlv->count =
+				uap_le16_to_cpu(max_mgmt_ie_tlv->count);
+			for (i = 0; i < max_mgmt_ie_tlv->count; i++) {
+				max_mgmt_ie_tlv->info[i].buf_size =
+					uap_le16_to_cpu(max_mgmt_ie_tlv->
+							info[i].buf_size);
+				max_mgmt_ie_tlv->info[i].buf_count =
+					uap_le16_to_cpu(max_mgmt_ie_tlv->
+							info[i].buf_count);
+				printf("buf%d_size = %d\n", i,
+				       max_mgmt_ie_tlv->info[i].buf_size);
+				printf("number of buffers = %d\n",
+				       max_mgmt_ie_tlv->info[i].buf_count);
+				printf("\n");
+			}
+			max_mgmt_ie_print = 1;
+			break;
+		case MRVL_BT_COEX_COMMON_CFG_TLV_ID:
+			printf("Coex common configuration:\n");
+			coex_common_tlv =
+				(tlvbuf_coex_common_cfg *)pcurrent_tlv;
+			printf("\tConfig Bitmap = 0x%02x\n",
+			       uap_le32_to_cpu(coex_common_tlv->config_bitmap));
+			printf("\tAP Coex Enabled = %d\n",
+			       uap_le32_to_cpu(coex_common_tlv->ap_bt_coex));
+			break;
+
+		case MRVL_BT_COEX_SCO_CFG_TLV_ID:
+			printf("Coex sco configuration:\n");
+			coex_sco_tlv = (tlvbuf_coex_sco_cfg *)pcurrent_tlv;
+			for (i = 0; i < 4; i++)
+				printf("\tQtime protection [%d] = %d usecs\n",
+				       i,
+				       uap_le16_to_cpu(coex_sco_tlv->
+						       protection_qtime[i]));
+			printf("\tProtection frame rate = %d\n",
+			       uap_le16_to_cpu(coex_sco_tlv->protection_rate));
+			printf("\tACL frequency = %d\n",
+			       uap_le16_to_cpu(coex_sco_tlv->acl_frequency));
+			break;
+
+		case MRVL_BT_COEX_ACL_CFG_TLV_ID:
+			printf("Coex acl configuration: ");
+			coex_acl_tlv = (tlvbuf_coex_acl_cfg *)pcurrent_tlv;
+			coex_acl_tlv->enabled =
+				uap_le16_to_cpu(coex_acl_tlv->enabled);
+			printf("%s\n",
+			       (coex_acl_tlv->
+				enabled) ? "enabled" : "disabled");
+			if (coex_acl_tlv->enabled) {
+				printf("\tBT time = %d usecs\n",
+				       uap_le16_to_cpu(coex_acl_tlv->bt_time));
+				printf("\tWLan time = %d usecs\n",
+				       uap_le16_to_cpu(coex_acl_tlv->
+						       wlan_time));
+				printf("\tProtection frame rate = %d\n",
+				       uap_le16_to_cpu(coex_acl_tlv->
+						       protection_rate));
+			}
+			break;
+
+		case MRVL_BT_COEX_STATS_TLV_ID:
+			printf("Coex statistics: \n");
+			coex_stats_tlv = (tlvbuf_coex_stats *)pcurrent_tlv;
+			printf("\tNull not sent = %d\n",
+			       uap_le32_to_cpu(coex_stats_tlv->null_not_sent));
+			printf("\tNull queued = %d\n",
+			       uap_le32_to_cpu(coex_stats_tlv->null_queued));
+			printf("\tNull not queued = %d\n",
+			       uap_le32_to_cpu(coex_stats_tlv->
+					       null_not_queued));
+			printf("\tCF End queued = %d\n",
+			       uap_le32_to_cpu(coex_stats_tlv->cf_end_queued));
+			printf("\tCF End not queued = %d\n",
+			       uap_le32_to_cpu(coex_stats_tlv->
+					       cf_end_not_queued));
+			printf("\tNull allocation failures = %d\n",
+			       uap_le32_to_cpu(coex_stats_tlv->
+					       null_alloc_fail));
+			printf("\tCF End allocation failures = %d\n",
+			       uap_le32_to_cpu(coex_stats_tlv->
+					       cf_end_alloc_fail));
+			break;
+		case HT_CAPABILITY_TLV_ID:
+			printf("\nHT Capability Info: \n");
+			ht_cap_tlv = (tlvbuf_htcap_t *)pcurrent_tlv;
+			if (!ht_cap_tlv->ht_cap.supported_mcs_set[0]) {
+				printf("802.11n is disabled\n");
+			} else {
+				printf("802.11n is enabled\n");
+				printf("ht_cap_info=0x%x, ampdu_param=0x%x tx_bf_cap=%#x\n", uap_le16_to_cpu(ht_cap_tlv->ht_cap.ht_cap_info), ht_cap_tlv->ht_cap.ampdu_param, uap_le32_to_cpu(ht_cap_tlv->ht_cap.tx_bf_cap));
+				printf("supported MCS set:\n");
+				for (i = 0; i < MCS_SET_LEN; i++) {
+					printf("0x%x ",
+					       ht_cap_tlv->ht_cap.
+					       supported_mcs_set[i]);
+				}
+				printf("\n");
+			}
+			break;
+		case HT_INFO_TLV_ID:
+			ht_info_tlv = (tlvbuf_htinfo_t *)pcurrent_tlv;
+			if (ht_info_tlv->length) {
+				printf("\nHT Information Element: \n");
+				printf("Primary channel = %d\n",
+				       ht_info_tlv->ht_info.pri_chan);
+				printf("Secondary channel offset = %d\n",
+				       (int)GET_SECONDARY_CHAN(ht_info_tlv->
+							       ht_info.field2));
+				printf("STA channel width = %dMHz\n",
+				       IS_CHANNEL_WIDTH_40(ht_info_tlv->ht_info.
+							   field2) ? 40 : 20);
+				printf("RIFS  %s\n",
+				       IS_RIFS_ALLOWED(ht_info_tlv->ht_info.
+						       field2) ? "Allowed" :
+				       "Prohibited");
+				ht_info_tlv->ht_info.field3 =
+					uap_le16_to_cpu(ht_info_tlv->ht_info.
+							field3);
+				ht_info_tlv->ht_info.field4 =
+					uap_le16_to_cpu(ht_info_tlv->ht_info.
+							field4);
+				printf("HT Protection = %d\n",
+				       (int)GET_HT_PROTECTION(ht_info_tlv->
+							      ht_info.field3));
+				printf("Non-Greenfield HT STAs present: %s\n",
+				       NONGF_STA_PRESENT(ht_info_tlv->ht_info.
+							 field3) ? "Yes" :
+				       "No");
+				printf("OBSS Non-HT STAs present: %s\n",
+				       OBSS_NONHT_STA_PRESENT(ht_info_tlv->
+							      ht_info.
+							      field3) ? "Yes" :
+				       "No");
+				for (i = 0; i < MCS_SET_LEN; i++) {
+					if (ht_info_tlv->ht_info.
+					    basic_mcs_set[i]) {
+						printf("Basic_mcs_set: \n");
+						flag = 1;
+						break;
+					}
+				}
+				if (flag) {
+					for (i = 0; i < MCS_SET_LEN; i++)
+						printf("%x ",
+						       ht_info_tlv->ht_info.
+						       basic_mcs_set[i]);
+					printf("\n");
+				}
+			}
+			break;
+		case MRVL_2040_BSS_COEX_CONTROL_TLV_ID:
+			coex_2040_tlv = (tlvbuf_2040_coex *)pcurrent_tlv;
+			printf("20/40 coex = %s\n",
+			       (coex_2040_tlv->
+				enable) ? "enabled" : "disabled");
+			break;
+		case VENDOR_SPECIFIC_IE_TLV_ID:
+			wmm_para_tlv = (tlvbuf_wmm_para_t *)pcurrent_tlv;
+			printf("wmm parameters:\n");
+			printf("\tqos_info = 0x%x\n",
+			       wmm_para_tlv->wmm_para.qos_info);
+			printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+			       wmm_para_tlv->wmm_para.ac_params[AC_BE].
+			       aci_aifsn.aifsn,
+			       wmm_para_tlv->wmm_para.ac_params[AC_BE].ecw.
+			       ecw_max,
+			       wmm_para_tlv->wmm_para.ac_params[AC_BE].ecw.
+			       ecw_min,
+			       uap_le16_to_cpu(wmm_para_tlv->wmm_para.
+					       ac_params[AC_BE].tx_op_limit));
+			printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+			       wmm_para_tlv->wmm_para.ac_params[AC_BK].
+			       aci_aifsn.aifsn,
+			       wmm_para_tlv->wmm_para.ac_params[AC_BK].ecw.
+			       ecw_max,
+			       wmm_para_tlv->wmm_para.ac_params[AC_BK].ecw.
+			       ecw_min,
+			       uap_le16_to_cpu(wmm_para_tlv->wmm_para.
+					       ac_params[AC_BK].tx_op_limit));
+			printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+			       wmm_para_tlv->wmm_para.ac_params[AC_VI].
+			       aci_aifsn.aifsn,
+			       wmm_para_tlv->wmm_para.ac_params[AC_VI].ecw.
+			       ecw_max,
+			       wmm_para_tlv->wmm_para.ac_params[AC_VI].ecw.
+			       ecw_min,
+			       uap_le16_to_cpu(wmm_para_tlv->wmm_para.
+					       ac_params[AC_VI].tx_op_limit));
+			printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
+			       wmm_para_tlv->wmm_para.ac_params[AC_VO].
+			       aci_aifsn.aifsn,
+			       wmm_para_tlv->wmm_para.ac_params[AC_VO].ecw.
+			       ecw_max,
+			       wmm_para_tlv->wmm_para.ac_params[AC_VO].ecw.
+			       ecw_min,
+			       uap_le16_to_cpu(wmm_para_tlv->wmm_para.
+					       ac_params[AC_VO].tx_op_limit));
+			break;
+#ifdef RX_PACKET_COALESCE
+		case MRVL_RX_PKT_COAL_TLV_ID:
+			rx_pkt_coal_tlv = (tlvbuf_rx_pkt_coal_t *)pcurrent_tlv;
+			printf("RX packet coalesce threshold=%d\n",
+			       uap_le32_to_cpu(rx_pkt_coal_tlv->rx_pkt_count));
+			printf("RX packet coalesce timeout in msec=%d\n",
+			       uap_le16_to_cpu(rx_pkt_coal_tlv->delay));
+			break;
+#endif
+		default:
+			break;
+		}
+		tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
+		pcurrent_tlv = (tlvbuf_header *)(pcurrent_tlv->data + tlv_len);
+	}
+	return;
+}
+
+/**
+ *  @brief  Checks if command requires driver handling, and if so,
+ *          repackage and send as regular command, instead of hostcmd.
+ *
+ *  @param cmd           Pointer to the command buffer
+ *  @param size          Pointer to the command size. This value is
+ *                       overwritten by the function with the size of the
+ *                       received response.
+ *  @param buf_size      Size of the allocated command buffer
+ *  @param reroute_ret   Pointer to return value of rerouted command
+ *  @return              UAP_SUCCESS (handled here, further processing not needed)
+ *                    or UAP_FAILURE (not handled here, proceed as usual)
+ */
+static int
+uap_ioctl_reroute(t_u8 *cmd, t_u16 *size, t_u16 buf_size, int *reroute_ret)
+{
+	t_u8 reroute = 0;
+	t_u16 cmd_code = 0;
+	t_u16 cmd_action = 0;
+	apcmdbuf_cfg_80211d *hcmd_domain = NULL;
+	apcmdbuf_snmp_mib *hcmd_snmp = NULL;
+	tlvbuf_header *tlv = NULL;
+	struct ifreq ifr;
+	t_s32 sockfd;
+	t_u8 *buf = NULL;
+	t_u16 buf_len = 0;
+	snmp_mib_param *snmp_param = NULL;
+	domain_info_param *domain_param = NULL;
+
+	/* assume input is a hostcmd */
+	cmd_code = ((apcmdbuf *)(cmd))->cmd_code;
+
+	/* just check if we need to re-route right now */
+	switch (cmd_code) {
+	case HostCmd_SNMP_MIB:
+		hcmd_snmp = (apcmdbuf_snmp_mib *)cmd;
+		tlv = (tlvbuf_header *)(cmd + sizeof(apcmdbuf_snmp_mib));
+		cmd_action = uap_le16_to_cpu(hcmd_snmp->action);
+		/* reroute CMD_SNMP_MIB: SET */
+		if (cmd_action == ACTION_SET) {
+			reroute = 1;
+			buf_len =
+				sizeof(snmp_mib_param) +
+				uap_le16_to_cpu(tlv->len);
+		}
+		break;
+	case HostCmd_CMD_802_11D_DOMAIN_INFO:
+		hcmd_domain = (apcmdbuf_cfg_80211d *)cmd;
+		cmd_action = uap_le16_to_cpu(hcmd_domain->action);
+		/* reroute CMD_DOMAIN_INFO: SET */
+		if (cmd_action == ACTION_SET) {
+			reroute = 1;
+			buf_len = sizeof(domain_info_param) + (*size
+							       -
+							       sizeof
+							       (apcmdbuf_cfg_80211d)
+							       +
+							       sizeof
+							       (domain_param_t));
+		}
+		break;
+	}
+
+	/* Exit early if not re-routing */
+	if (!reroute || uap_ioctl_no_reroute)
+		return UAP_FAILURE;
+
+	/* Prepare buffer */
+#if DEBUG
+	uap_printf(MSG_DEBUG, "DBG: rerouting CMD 0x%04x\n", cmd_code);
+#endif
+	buf = (t_u8 *)malloc(buf_len);
+	if (!buf) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		goto done_no_socket;
+	}
+	memset(buf, 0, buf_len);
+
+	/* Prepare param */
+	switch (cmd_code) {
+	case HostCmd_SNMP_MIB:
+		snmp_param = (snmp_mib_param *)buf;
+		snmp_param->subcmd = UAP_SNMP_MIB;
+		snmp_param->action = cmd_action;
+		snmp_param->oid = uap_le16_to_cpu(tlv->type);
+		snmp_param->oid_val_len = uap_le16_to_cpu(tlv->len);
+		memcpy(snmp_param->oid_value, tlv->data,
+		       MIN(sizeof(t_u32), snmp_param->oid_val_len));
+		break;
+	case HostCmd_CMD_802_11D_DOMAIN_INFO:
+		domain_param = (domain_info_param *)buf;
+		domain_param->subcmd = UAP_DOMAIN_INFO;
+		domain_param->action = cmd_action;
+		memcpy(domain_param->tlv, &hcmd_domain->domain,
+		       buf_len - sizeof(domain_info_param));
+		tlv = (tlvbuf_header *)domain_param->tlv;
+		tlv->type = uap_le16_to_cpu(tlv->type);
+		tlv->len = uap_le16_to_cpu(tlv->len);
+
+		break;
+	}
+#if DEBUG
+	/* Dump request buffer */
+	hexdump("Reroute Request buffer", buf, buf_len, ' ');
+#endif
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		goto done_no_socket;
+	}
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)buf;
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
+		*reroute_ret = UAP_FAILURE;
+		perror("");
+#if DEBUG
+		uap_printf(MSG_DEBUG, "ERR: reroute of CMD 0x%04x failed\n",
+			   cmd_code);
+#endif
+		goto done;
+	}
+	*reroute_ret = UAP_SUCCESS;
+
+done:
+	/* Close socket */
+	close(sockfd);
+done_no_socket:
+	if (buf)
+		free(buf);
+
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief Performs the ioctl operation to send the command to
+ *  the driver.
+ *
+ *  @param cmd           Pointer to the command buffer
+ *  @param size          Pointer to the command size. This value is
+ *                       overwritten by the function with the size of the
+ *                       received response.
+ *  @param buf_size      Size of the allocated command buffer
+ *  @return              UAP_SUCCESS or UAP_FAILURE
+ */
+int
+uap_ioctl(t_u8 *cmd, t_u16 *size, t_u16 buf_size)
+{
+	struct ifreq ifr;
+	apcmdbuf *header = NULL;
+	t_s32 sockfd;
+	int reroute_ret = 0;
+	mrvl_priv_cmd *mrvl_cmd = NULL;
+	t_u8 *buf = NULL, *temp = NULL;
+	t_u16 mrvl_header_len = 0;
+	int ret = UAP_SUCCESS;
+
+#ifdef WIFI_DIRECT_SUPPORT
+	if (strncmp(dev_name, "wfd", 3))
+#endif
+		if (uap_ioctl_reroute(cmd, size, buf_size, &reroute_ret) ==
+		    UAP_SUCCESS) {
+			return reroute_ret;
+		}
+
+	if (buf_size < *size) {
+		printf("buf_size should not less than cmd buffer size\n");
+		return UAP_FAILURE;
+	}
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return UAP_FAILURE;
+	}
+	*(t_u32 *)cmd = buf_size - BUF_HEADER_SIZE;
+
+	mrvl_header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_HOSTCMD);
+	buf = (unsigned char *)malloc(buf_size + sizeof(mrvl_priv_cmd) +
+				      mrvl_header_len);
+	if (buf == NULL)
+		return UAP_FAILURE;
+
+	memset(buf, 0, buf_size + sizeof(mrvl_priv_cmd) + mrvl_header_len);
+	/* Fill up buffer */
+	mrvl_cmd = (mrvl_priv_cmd *)buf;
+	mrvl_cmd->buf = buf + sizeof(mrvl_priv_cmd);
+	mrvl_cmd->used_len = 0;
+	mrvl_cmd->total_len = buf_size + mrvl_header_len;
+	/* Copy Marvell command string */
+	temp = mrvl_cmd->buf;
+	strncpy((char *)temp, CMD_MARVELL, strlen(CMD_MARVELL));
+	temp += (strlen(CMD_MARVELL));
+	/* Insert command string */
+	strncpy((char *)temp, PRIV_CMD_HOSTCMD, strlen(PRIV_CMD_HOSTCMD));
+	temp += (strlen(PRIV_CMD_HOSTCMD));
+
+	memcpy(temp, (t_u8 *)cmd, *size);
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)mrvl_cmd;
+	header = (apcmdbuf *)(buf + sizeof(mrvl_priv_cmd) + mrvl_header_len);
+	header->size = *size - BUF_HEADER_SIZE;
+	if (header->cmd_code == APCMD_SYS_CONFIGURE) {
+		apcmdbuf_sys_configure *sys_cfg;
+		sys_cfg = (apcmdbuf_sys_configure *)header;
+		sys_cfg->action = uap_cpu_to_le16(sys_cfg->action);
+	}
+	endian_convert_request_header(header);
+#if DEBUG
+	/* Dump request buffer */
+	hexdump("Request buffer", mrvl_cmd,
+		*size + sizeof(mrvl_priv_cmd) + mrvl_header_len, ' ');
+#endif
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, MRVLPRIVCMD, &ifr)) {
+		perror("");
+		printf("ERR:MRVLPRIVCMD is not supported by %s\n", dev_name);
+		ret = UAP_FAILURE;
+		goto done;
+	}
+	endian_convert_response_header(header);
+	header->cmd_code &= HostCmd_CMD_ID_MASK;
+	header->cmd_code |= APCMD_RESP_CHECK;
+	*size = header->size;
+
+	/* Validate response size */
+	if (*size > (buf_size - BUF_HEADER_SIZE)) {
+		printf("ERR:Response size (%d) greater than buffer size (%d)! Aborting!\n", *size, buf_size);
+		ret = UAP_FAILURE;
+		goto done;
+	}
+	memcpy(cmd, (t_u8 *)header, *size + BUF_HEADER_SIZE);
+#if DEBUG
+	/* Dump respond buffer */
+	hexdump("Respond buffer", mrvl_cmd,
+		*size + BUF_HEADER_SIZE + sizeof(mrvl_priv_cmd) +
+		mrvl_header_len, ' ');
+#endif
+
+done:
+	/* Close socket */
+	close(sockfd);
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+/**
+ *  @brief  Get protocol from the firmware
+ *
+ *  @param  proto   A pointer to protocol var
+ *  @return         UAP_SUCCESS/UAP_FAILURE
+ */
+int
+get_sys_cfg_protocol(t_u16 *proto)
+{
+	apcmdbuf_sys_configure *cmd_buf = NULL;
+	tlvbuf_protocol *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len;
+	int ret = UAP_FAILURE;
+
+	cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_protocol);
+	/* Initialize the command buffer */
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate buffer for command!\n");
+		return ret;
+	}
+	memset(buffer, 0, cmd_len);
+	/* Locate headers */
+	cmd_buf = (apcmdbuf_sys_configure *)buffer;
+	tlv = (tlvbuf_protocol *)(buffer + sizeof(apcmdbuf_sys_configure));
+	/* Fill the command buffer */
+	cmd_buf->cmd_code = APCMD_SYS_CONFIGURE;
+	cmd_buf->size = cmd_len;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = ACTION_GET;
+	tlv->tag = MRVL_PROTOCOL_TLV_ID;
+	tlv->length = 2;
+	endian_convert_tlv_header_out(tlv);
+	/* Send the command */
+	ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len);
+	endian_convert_tlv_header_in(tlv);
+
+	/* Process response */
+	if (ret == UAP_SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
+			free(buffer);
+			return UAP_FAILURE;
+		}
+
+		if (cmd_buf->result == CMD_SUCCESS) {
+			tlv->protocol = uap_le16_to_cpu(tlv->protocol);
+			memcpy(proto, &tlv->protocol, sizeof(tlv->protocol));
+		} else {
+			ret = UAP_FAILURE;
+		}
+	}
+	if (buffer)
+		free(buffer);
+	return ret;
+}
+
+/**
+ *  @brief Check cipher is valid or not
+ *
+ *  @param pairwisecipher    Pairwise cipher
+ *  @param groupcipher       Group cipher
+ *  @param protocol          Protocol
+ *  @param enable_11n        11n enabled or not.
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_cipher_valid_with_11n(int pairwisecipher, int groupcipher,
+			 int protocol, int enable_11n)
+{
+	if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE))
+		return UAP_SUCCESS;
+	if (pairwisecipher == CIPHER_TKIP) {
+		/* Ok to have TKIP in mixed mode */
+		if (enable_11n && protocol != PROTOCOL_WPA2_MIXED) {
+			printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
+			return UAP_FAILURE;
+		}
+	}
+	if ((pairwisecipher == CIPHER_TKIP) && (groupcipher == CIPHER_TKIP))
+		return UAP_SUCCESS;
+	if ((pairwisecipher == CIPHER_AES_CCMP) &&
+	    (groupcipher == CIPHER_AES_CCMP))
+		return UAP_SUCCESS;
+	if ((pairwisecipher == CIPHER_AES_CCMP) && (groupcipher == CIPHER_TKIP))
+		return UAP_SUCCESS;
+	if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP))
+		return UAP_SUCCESS;
+	return UAP_FAILURE;
+}
+
+/**
+ *  @brief Check cipher is valid or not based on proto
+ *
+ *  @param pairwisecipher    Pairwise cipher
+ *  @param groupcipher       Group cipher
+ *  @param protocol          Protocol
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_cipher_valid_with_proto(int pairwisecipher, int groupcipher, int protocol)
+{
+	HTCap_t htcap;
+
+	if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE))
+		return UAP_SUCCESS;
+	if (pairwisecipher == CIPHER_TKIP) {
+		/* Ok to have TKIP in mixed mode */
+		if (protocol != PROTOCOL_WPA2_MIXED) {
+			memset(&htcap, 0, sizeof(htcap));
+			if (UAP_SUCCESS == get_sys_cfg_11n(&htcap)) {
+				if (htcap.supported_mcs_set[0]) {
+					printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
+					return UAP_FAILURE;
+				}
+			}
+		}
+	}
+	if ((pairwisecipher == CIPHER_TKIP) && (groupcipher == CIPHER_TKIP))
+		return UAP_SUCCESS;
+	if ((pairwisecipher == CIPHER_AES_CCMP) &&
+	    (groupcipher == CIPHER_AES_CCMP))
+		return UAP_SUCCESS;
+	if ((pairwisecipher == CIPHER_AES_CCMP) && (groupcipher == CIPHER_TKIP))
+		return UAP_SUCCESS;
+	if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP))
+		return UAP_SUCCESS;
+	return UAP_FAILURE;
+}
+
+/**
+ *  @brief Check cipher is valid or not
+ *
+ *  @param pairwisecipher    Pairwise cipher
+ *  @param groupcipher       Group cipher
+ *  @return         UAP_SUCCESS or UAP_FAILURE
+ */
+int
+is_cipher_valid(int pairwisecipher, int groupcipher)
+{
+	HTCap_t htcap;
+	t_u16 proto = 0;
+
+	if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE))
+		return UAP_SUCCESS;
+	if (pairwisecipher == CIPHER_TKIP) {
+		if (UAP_SUCCESS == get_sys_cfg_protocol(&proto)) {
+			/* Ok to have TKIP in mixed mode */
+			if (proto != PROTOCOL_WPA2_MIXED) {
+				memset(&htcap, 0, sizeof(htcap));
+				if (UAP_SUCCESS == get_sys_cfg_11n(&htcap)) {
+					if (htcap.supported_mcs_set[0]) {
+						printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
+						return UAP_FAILURE;
+					}
+				}
+			}
+		}
+	}
+	if ((pairwisecipher == CIPHER_TKIP) && (groupcipher == CIPHER_TKIP))
+		return UAP_SUCCESS;
+	if ((pairwisecipher == CIPHER_AES_CCMP) &&
+	    (groupcipher == CIPHER_AES_CCMP))
+		return UAP_SUCCESS;
+	if ((pairwisecipher == CIPHER_AES_CCMP) && (groupcipher == CIPHER_TKIP))
+		return UAP_SUCCESS;
+	if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP))
+		return UAP_SUCCESS;
+	return UAP_FAILURE;
+}
+
+/**
+ *  @brief The main function
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         0 or 1
+ */
+int
+main(int argc, char *argv[])
+{
+	int opt, i;
+	int ret = 0;
+	memset(dev_name, 0, sizeof(dev_name));
+	strcpy(dev_name, DEFAULT_DEV_NAME);
+
+	/* Parse arguments */
+	while ((opt =
+		getopt_long(argc, argv, "+hi:d:v", ap_options, NULL)) != -1) {
+		switch (opt) {
+		case 'i':
+			if (strlen(optarg) < IFNAMSIZ) {
+				memset(dev_name, 0, sizeof(dev_name));
+				strncpy(dev_name, optarg, strlen(optarg));
+			}
+			printf("dev_name:%s\n", dev_name);
+			break;
+		case 'v':
+			printf("uaputl.exe - uAP utility ver %s\n",
+			       UAP_VERSION);
+			exit(0);
+		case 'd':
+			debug_level = strtoul(optarg, NULL, 10);
+#if DEBUG
+			uap_printf(MSG_DEBUG, "debug_level=%x\n", debug_level);
+#endif
+			break;
+		case 'h':
+		default:
+			print_tool_usage();
+			exit(0);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		print_tool_usage();
+		exit(1);
+	}
+
+	/* Process command */
+	for (i = 0; ap_command[i].cmd; i++) {
+		if (strncmp
+		    (ap_command[i].cmd, argv[0], strlen(ap_command[i].cmd)))
+			continue;
+		if (strlen(ap_command[i].cmd) != strlen(argv[0]))
+			continue;
+		ret = ap_command[i].func(argc, argv);
+		break;
+	}
+	if (!ap_command[i].cmd) {
+		printf("ERR: %s is not supported\n", argv[0]);
+		exit(1);
+	}
+	if (ret == UAP_FAILURE)
+		return -1;
+	else
+		return 0;
+}
diff --git a/wlan_sd8897/mapp/uaputl/uaputl.h b/wlan_sd8897/mapp/uaputl/uaputl.h
new file mode 100644
index 0000000..2d0b287
--- /dev/null
+++ b/wlan_sd8897/mapp/uaputl/uaputl.h
@@ -0,0 +1,2609 @@
+/** @file  uaputl.h
+ *
+ *  @brief Header file for uaputl application
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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/01/08: Initial creation
+************************************************************************/
+
+#ifndef _UAP_H
+#define _UAP_H
+
+/** uAP application version string */
+#define UAP_VERSION         "4.10"
+
+/** Character, 1 byte */
+typedef signed char t_s8;
+/** Unsigned character, 1 byte */
+typedef unsigned char t_u8;
+
+/** Short integer */
+typedef signed short t_s16;
+/** Unsigned short integer */
+typedef unsigned short t_u16;
+
+/** Integer */
+typedef signed int t_s32;
+/** Unsigned integer */
+typedef unsigned int t_u32;
+
+/** Long long integer */
+typedef signed long long t_s64;
+/** Unsigned long integer */
+typedef unsigned long long t_u64;
+
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#undef BIG_ENDIAN_SUPPORT
+#endif
+
+/** 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 from 16 bit little endian format to CPU format */
+#define uap_le16_to_cpu(x) swap_byte_16(x)
+/** Convert from 32 bit little endian format to CPU format */
+#define uap_le32_to_cpu(x) swap_byte_32(x)
+/** Convert from 64 bit little endian format to CPU format */
+#define uap_le64_to_cpu(x) swap_byte_64(x)
+/** Convert to 16 bit little endian format from CPU format */
+#define uap_cpu_to_le16(x) swap_byte_16(x)
+/** Convert to 32 bit little endian format from CPU format */
+#define uap_cpu_to_le32(x) swap_byte_32(x)
+/** Convert to 64 bit little endian format from CPU format */
+#define uap_cpu_to_le64(x) swap_byte_64(x)
+
+/** Convert APCMD header to little endian format from CPU format */
+#define endian_convert_request_header(x)                \
+    {                                                   \
+        (x)->cmd_code = uap_cpu_to_le16((x)->cmd_code);   \
+        (x)->size = uap_cpu_to_le16((x)->size);         \
+        (x)->seq_num = uap_cpu_to_le16((x)->seq_num);     \
+        (x)->result = uap_cpu_to_le16((x)->result);     \
+    }
+
+/** Convert APCMD header from little endian format to CPU format */
+#define endian_convert_response_header(x)               \
+    {                                                   \
+        (x)->cmd_code = uap_le16_to_cpu((x)->cmd_code);   \
+        (x)->size = uap_le16_to_cpu((x)->size);         \
+        (x)->seq_num = uap_le16_to_cpu((x)->seq_num);     \
+        (x)->result = uap_le16_to_cpu((x)->result);     \
+    }
+
+/** Convert TLV header to little endian format from CPU format */
+#define endian_convert_tlv_header_out(x)            \
+    {                                               \
+        (x)->tag = uap_cpu_to_le16((x)->tag);       \
+        (x)->length = uap_cpu_to_le16((x)->length); \
+    }
+
+/** Convert TLV header from little endian format to CPU format */
+#define endian_convert_tlv_header_in(x)             \
+    {                                               \
+        (x)->tag = uap_le16_to_cpu((x)->tag);       \
+        (x)->length = uap_le16_to_cpu((x)->length); \
+    }
+
+#else /* BIG_ENDIAN_SUPPORT */
+/** Do nothing */
+#define uap_le16_to_cpu(x) x
+/** Do nothing */
+#define uap_le32_to_cpu(x) x
+/** Do nothing */
+#define uap_le64_to_cpu(x) x
+/** Do nothing */
+#define uap_cpu_to_le16(x) x
+/** Do nothing */
+#define uap_cpu_to_le32(x) x
+/** Do nothing */
+#define uap_cpu_to_le64(x) x
+
+/** Do nothing */
+#define endian_convert_request_header(x)
+/** Do nothing */
+#define endian_convert_response_header(x)
+/** Do nothing */
+#define endian_convert_tlv_header_out(x)
+/** Do nothing */
+#define endian_convert_tlv_header_in(x)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** MRVL private command ioctl number */
+#define MRVLPRIVCMD          (SIOCDEVPRIVATE + 14)
+/** 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
+/** deep sleep subcommand */
+#define UAP_DEEP_SLEEP      3
+/** Tx data pause subcommand */
+#define UAP_TX_DATA_PAUSE    5
+/** sdcmd52 read write subcommand */
+#define UAP_SDCMD52_RW      6
+/** snmp mib subcommand */
+#define UAP_SNMP_MIB        7
+/** domain info subcommand */
+#define UAP_DOMAIN_INFO     8
+#if defined(DFS_TESTING_SUPPORT)
+/** dfs testing subcommand */
+#define UAP_DFS_TESTING     10
+#endif
+/** TX beamforming configuration */
+#define UAP_TX_BF_CFG       9
+/** 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
+/** Tx rate configuration */
+#define UAP_TX_RATE_CFG      14
+/** 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
+
+/** Config DFS channel switch count subcommand */
+#define UAP_CHAN_SWITCH_COUNT_CFG     23
+
+/** 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
+
+/** deauth station */
+#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)
+
+/** uap get station list */
+#define UAP_GET_STA_LIST    (SIOCDEVPRIVATE + 11)
+
+/** Private command ID to set/get custom IE buffer */
+#define UAP_CUSTOM_IE       (SIOCDEVPRIVATE + 13)
+
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX       12
+
+/** HS_CFG: Get flag */
+#define HS_CFG_FLAG_GET         0
+/** HS_CFG: Set flag */
+#define HS_CFG_FLAG_SET         1
+/** HS_CFG: condition flag */
+#define HS_CFG_FLAG_CONDITION   2
+/** HS_CFG: gpio flag */
+#define HS_CFG_FLAG_GPIO        4
+/** HS_CFG: gap flag */
+#define HS_CFG_FLAG_GAP         8
+/** HS_CFG: all flags */
+#define HS_CFG_FLAG_ALL         0x0f
+/** HS_CFG: condition mask */
+#define HS_CFG_CONDITION_MASK   0x4f
+
+/** Host sleep config conditions : Cancel */
+#define HS_CFG_CANCEL   0xffffffff
+
+/** 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;
+
+/** 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
+
+/** 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
+
+/** sleep parameter */
+#define SLEEP_PARAMETER                     1
+/** inactivity sleep parameter */
+#define INACTIVITY_SLEEP_PARAMETER          2
+
+/** sleep parameter : lower limit in micro-sec */
+#define PS_SLEEP_PARAM_MIN                  5000
+/** sleep parameter : upper limit in micro-sec */
+#define PS_SLEEP_PARAM_MAX                  32000
+/** power save awake period minimum value in micro-sec */
+#define PS_AWAKE_PERIOD_MIN                 2000
+
+/** ps_mgmt */
+typedef struct _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;
+} ps_mgmt;
+
+/** addba_param */
+typedef struct _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;
+} addba_param;
+
+/** Default block ACK timeout */
+#define DEFAULT_BLOCK_ACK_TIMEOUT   0xFFFF
+
+/** Default block ACK timeout */
+#define MAX_TXRX_WINDOW_SIZE        0x3FF
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID     8
+
+/** aggr_prio_tbl */
+typedef struct _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];
+} 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 _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;
+} fw_info;
+
+#ifndef ETH_ALEN
+/** MAC address length */
+#define ETH_ALEN    6
+#endif
+
+/** 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
+
+/* 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 _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;
+} bf_global_cfg_args;
+
+/** trigger sounding args */
+typedef struct _trigger_sound_args {
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** Status */
+	t_u8 status;
+} trigger_sound_args;
+
+/** bf periodicity args */
+typedef struct _bf_periodicity_args {
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** Current Tx BF Interval */
+	t_u16 interval;
+    /** Status */
+	t_u8 status;
+} bf_periodicity_args;
+
+/** tx bf peer args */
+typedef struct _tx_bf_peer_args {
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** Reserved */
+	t_u16 reserved;
+    /** Enable/Disable Beamforming */
+	t_u8 bf_enbl;
+    /** Enable/Disable sounding */
+	t_u8 sounding_enbl;
+    /** FB Type */
+	t_u8 fb_type;
+} tx_bf_peer_args;
+
+typedef struct _snr_thr_args {
+    /** Peer MAC address */
+	t_u8 peer_mac[ETH_ALEN];
+    /** SNR for peer */
+	t_u8 snr;
+} snr_thr_args;
+
+/** Type definition of tx_bf_cfg */
+typedef struct _tx_bf_cfg_para {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get
+     * Will be eliminatied on moal */
+	t_u32 action;
+    /** BF command id */
+	t_u16 bf_action;
+    /** Action Set/Get -
+     * this will be pssed to DNLD_CMD*/
+	t_u16 bf_cmd_action;
+    /** Number of peers */
+	t_u32 no_of_peers;
+	union {
+		bf_global_cfg_args bf_global_cfg;
+		trigger_sound_args bf_sound[MAX_PEER_MAC_TUPLES];
+		bf_periodicity_args bf_periodicity[MAX_PEER_MAC_TUPLES];
+		tx_bf_peer_args tx_bf_peer[MAX_PEER_MAC_TUPLES];
+		snr_thr_args bf_snr[MAX_PEER_MAC_TUPLES];
+	} body;
+} tx_bf_cfg_para;
+
+/** 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;
+
+/** 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;
+/** Default idle time for auto deep sleep */
+#define DEEP_SLEEP_IDLE_TIME	100
+
+/** 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;
+
+/** Tx data pause disable */
+#define TX_DATA_PAUSE_DISABLE   0
+/** Tx data pause enable */
+#define TX_DATA_PAUSE_ENABLE    1
+/** Default maximum Tx buffer for all PS clients */
+#define MAX_TX_BUF_CNT	        2
+
+/** snmp_mib parameters */
+typedef struct _snmp_mib_param {
+    /** 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[0];
+} snmp_mib_param;
+
+/** 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[0];
+} domain_info_param;
+
+#if defined(DFS_TESTING_SUPPORT)
+/** 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;
+} dfs_testing_para;
+#endif
+
+/** 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;
+
+/** mgmt_frame_ctrl */
+typedef struct _mgmt_frame_ctrl {
+    /** subcmd */
+	t_u32 subcmd;
+    /** Set/Get */
+	t_u32 action;
+    /** mask */
+	t_u32 mask;
+} mgmt_frame_ctrl;
+
+/* 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;
+
+/** Type definition of ht_tx_cfg */
+typedef struct _ht_tx_cfg {
+    /** HTTxCap */
+	t_u16 httxcap;
+    /** HTTxInfo */
+	t_u16 httxinfo;
+    /** Band selection */
+	t_u32 misc_cfg;
+} ht_tx_cfg;
+
+/** Type definition of ht_tx_cfg_para */
+typedef struct _ht_tx_cfg_para {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get
+     * Will be eliminatied on moal */
+	t_u32 action;
+	/* HT Tx configuration */
+	ht_tx_cfg tx_cfg;
+} ht_tx_cfg_para;
+
+/** Default device name */
+#define DEFAULT_DEV_NAME    "uap0"
+
+/** Success */
+#define UAP_SUCCESS     1
+/** Failure */
+#define UAP_FAILURE     0
+/** MAC BROADCAST */
+#define UAP_RET_MAC_BROADCAST   0x1FF
+/** MAC MULTICAST */
+#define UAP_RET_MAC_MULTICAST   0x1FE
+
+/** Command is successful */
+#define CMD_SUCCESS     0
+/** Command fails */
+#define CMD_FAILURE     -1
+
+/** BSS start error : Invalid parameters */
+#define BSS_FAILURE_START_INVAL     2
+
+/** Maximum line length for config file */
+#define MAX_LINE_LENGTH         240
+/** Maximum command length */
+#define MAX_CMD_LENGTH          100
+/** Size of command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS         MAX_STA_COUNT
+/** Maximum number of MAC addresses for one-shot filter modifications */
+#define MAX_MAC_ONESHOT_FILTER  16
+/** Maximum SSID length */
+#define MAX_SSID_LENGTH         32
+/** Maximum SSID length */
+#define MIN_SSID_LENGTH         1
+/** Maximum WPA passphrase length */
+#define MAX_WPA_PASSPHRASE_LENGTH   64
+/** Minimum WPA passphrase length */
+#define MIN_WPA_PASSPHRASE_LENGTH   8
+/** Maximum data rates */
+#define MAX_DATA_RATES          14
+/** Maximum length of lines in configuration file */
+#define MAX_CONFIG_LINE         240
+/** MSB bit is set if its a basic rate */
+#define BASIC_RATE_SET_BIT      0x80
+/** Maximum group key timer */
+#define MAX_GRP_TIMER           86400
+/** Maximum Retry Limit */
+#define MAX_RETRY_LIMIT         14
+/** Maximum preamble type value */
+#define MAX_PREAMBLE_TYPE       2
+
+/** Maximum TX Power Limit */
+#define MAX_TX_POWER    30
+/** Minimum TX Power Limit */
+#define MIN_TX_POWER    0
+
+/** Maximum channel number in bg mode */
+#define MAX_CHANNELS_BG 14
+/** Maximum channels */
+#define MAX_CHANNELS    165
+#define DEFAULT_MAX_VALID_CHANNEL_BG 11
+
+/** MAX station count */
+#define MAX_STA_COUNT   10
+
+/** Maximum RTS threshold */
+#define MAX_RTS_THRESHOLD   2347
+
+/** Maximum fragmentation threshold */
+#define MAX_FRAG_THRESHOLD 2346
+/** Minimum fragmentation threshold */
+#define MIN_FRAG_THRESHOLD 256
+
+/** Maximum stage out time */
+#define MAX_STAGE_OUT_TIME  864000
+/** Minimum stage out time */
+#define MIN_STAGE_OUT_TIME  300
+
+/** Maximum DTIM period */
+#define MAX_DTIM_PERIOD 100
+
+/** Maximum BEACON period */
+#define MAX_BEACON_PERIOD 4000
+
+/** Minimum BEACON period */
+#define MIN_BEACON_PERIOD 50
+
+/** Maximum IE buffer length */
+#define MAX_IE_BUFFER_LEN 256
+
+/** Maximum custom IE count */
+#define MAX_CUSTOM_IE_COUNT 4
+
+/** Maximum number of rates allowed at a time */
+#define MAX_RATES               12
+
+/** Default wait period in seconds */
+#define DEFAULT_WAIT_TIME       3
+
+/** Maximum valid value of Deauth reason code */
+#define MAX_DEAUTH_REASON_CODE     0xFFFF
+
+#ifdef __GNUC__
+/** Structure packing begins */
+#define PACK_START
+/** Structure packeing end */
+#define PACK_END  __attribute__ ((packed))
+#else
+/** Structure packing begins */
+#define PACK_START   __packed
+/** Structure packeing end */
+#define PACK_END
+#endif
+
+/** Action field value : get */
+#define ACTION_GET  0
+/** Action field value : set */
+#define ACTION_SET  1
+/**
+ * Hex or Decimal to Integer
+ * @param   num string to convert into decimal or hex
+ */
+#define A2HEXDECIMAL(num)  \
+    (strncasecmp("0x", (num), 2)?(unsigned int) strtoll((num),NULL,0):a2hex((num)))\
+
+/**
+ * Check of decimal or hex string
+ * @param   num string
+ */
+#define IS_HEX_OR_DIGIT(num) \
+    (strncasecmp("0x", (num), 2)?ISDIGIT((num)):ishexstring((num)))\
+
+/** Find minimum value */
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+/** Valid Input Commands */
+typedef enum {
+	RDEEPROM,
+	SCANCHANNELS,
+	TXPOWER,
+	PROTOCOL,
+	CHANNEL,
+	CHANNEL_EXT,
+	BAND,
+	RATE,
+	BROADCASTSSID,
+	RTSTHRESH,
+	FRAGTHRESH,
+	DTIMPERIOD,
+	RADIOCONTROL,
+	TXBEACONRATE,
+	MCBCDATARATE,
+	PKTFWD,
+	STAAGEOUTTIMER,
+	PSSTAAGEOUTTIMER,
+	AUTHMODE,
+	GROUPREKEYTIMER,
+	MAXSTANUM,
+	BEACONPERIOD,
+	RETRYLIMIT,
+	STICKYTIMCONFIG,
+	STICKYTIMSTAMACADDR,
+	COEX2040CONFIG,
+	TXRATECFG,
+	RSNREPLAYPROT,
+	PREAMBLETYPE,
+	EAPOL_PWK_HSK,
+	EAPOL_GWK_HSK,
+	COEX_COMM_BITMAP,
+	COEX_COMM_AP_COEX,
+	COEX_PROTECTION,
+	COEX_SCO_ACL_FREQ,
+	COEX_ACL_ENABLED,
+	COEX_ACL_BT_TIME,
+	COEX_ACL_WLAN_TIME,
+	PWK_CIPHER,
+	GWK_CIPHER,
+	RESTRICT_CLIENT_MODE,
+	AKM_SUITE,
+} valid_inputs;
+
+/** Message verbosity level */
+enum { MSG_NONE, MSG_DEBUG, MSG_ALL };
+
+/** oids_table */
+typedef struct {
+    /** oid type */
+	t_u16 type;
+    /** oid len */
+	t_u16 len;
+    /** oid name */
+	char *name;
+} oids_table;
+
+/** Marvell private command identifier */
+#define CMD_MARVELL         "MRVL_CMD"
+/** Marvell private command for hostcmd */
+#define PRIV_CMD_HOSTCMD    "hostcmd"
+
+/** 4 byte header to store buf len*/
+#define BUF_HEADER_SIZE     4
+
+/** TLV header length */
+#define TLVHEADER_LEN       4
+
+/** AP CMD header */
+#define APCMDHEADER     /** Buf Size */         \
+                        t_u32 buf_size;         \
+                        /** Command Code */     \
+                        t_u16 cmd_code;         \
+                        /** Size */             \
+                        t_u16 size;             \
+                        /** Sequence Number */  \
+                        t_u16 seq_num;          \
+                        /** Result */           \
+                        t_s16 result
+
+/** TLV header */
+#define TLVHEADER       /** Tag */      \
+                        t_u16 tag;      \
+                        /** Length */   \
+                        t_u16 length
+
+/* TLV Definitions */
+
+/** TLV buffer header*/
+typedef PACK_START struct _tlvbuf_header {
+    /** Header type */
+	t_u16 type;
+    /** Header length */
+	t_u16 len;
+    /** Data */
+	t_u8 data[0];
+} PACK_END tlvbuf_header;
+
+/** BITMAP for ACS mode */
+#define BITMAP_ACS_MODE         0x01
+
+/* 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
+
+/** BITMAP for secondary channel above */
+#define BITMAP_CHANNEL_ABOVE    0x02
+/** BITMAP for secondary channel below */
+#define BITMAP_CHANNEL_BELOW    0x04
+/** Channle mode mask */
+#define CHANNEL_MODE_MASK       0x07
+/** max primary channel support secondary channel above */
+#define MAX_CHANNEL_ABOVE       9
+/** Default max primary channel supporting secondary channel above when country code is not Japan */
+#define DEFAULT_MAX_CHANNEL_ABOVE       7
+/** min primary channel support secondary channel below */
+#define MIN_CHANNEL_BELOW       5
+/** Default max primary channel supporting secondary channel above when country code is not Japan and not US */
+#define DEFAULT_MAX_CHANNEL_ABOVE_NON_US       9
+/** Default max primary channel supporting secondary channel below when country code is not Japan */
+#define DEFAULT_MAX_CHANNEL_BELOW       11
+/** Default max primary channel supporting secondary channel below when country code is not Japan and not US */
+#define DEFAULT_MAX_CHANNEL_BELOW_NON_US       13
+
+/** 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,
+};
+
+/** Band_Config_t */
+typedef 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
+} PACK_END Band_Config_t;
+
+/** TLV buffer : Channel Config */
+typedef PACK_START struct _tlvbuf_channel_config {
+    /** Header */
+	TLVHEADER;
+    /** Band Configuration */
+	Band_Config_t bandcfg;
+    /** Channel number */
+	t_u8 chan_number;
+} PACK_END tlvbuf_channel_config;
+
+/** Channel List Entry */
+typedef PACK_START struct _channel_list {
+    /** Band Config */
+	Band_Config_t bandcfg;
+    /** Channel Number */
+	t_u8 chan_number;
+    /** Reserved */
+	t_u8 reserved1;
+    /** Reserved */
+	t_u16 reserved2;
+    /** Reserved */
+	t_u16 reserved3;
+} PACK_END channel_list;
+
+/** TLV buffer : Channel List */
+typedef PACK_START struct _tlvbuf_channel_list {
+    /** Header */
+	TLVHEADER;
+    /** Channel List */
+	channel_list chan_list[0];
+} PACK_END tlvbuf_channel_list;
+
+/** TLV buffer : TDLS extended capability config */
+typedef PACK_START struct _tlvbuf_tdls_ext_cap {
+    /** Header */
+	TLVHEADER;
+    /** Extended capability */
+	t_u8 ext_cap[0];
+} PACK_END tlvbuf_tdls_ext_cap;
+
+/** TLV buffer : AP MAC address */
+typedef PACK_START struct _tlvbuf_ap_mac_address {
+    /** Header */
+	TLVHEADER;
+    /** AP MAC address */
+	t_u8 ap_mac_addr[ETH_ALEN];
+} PACK_END tlvbuf_ap_mac_address;
+
+/** TLV buffer : SSID */
+typedef PACK_START struct _tlvbuf_ssid {
+    /** Header */
+	TLVHEADER;
+    /** SSID */
+	t_u8 ssid[0];
+} PACK_END tlvbuf_ssid;
+
+/** TLV buffer : Beacon period */
+typedef PACK_START struct _tlvbuf_beacon_period {
+    /** Header */
+	TLVHEADER;
+    /** Beacon period */
+	t_u16 beacon_period_ms;
+} PACK_END tlvbuf_beacon_period;
+
+/** TLV buffer : DTIM period */
+typedef PACK_START struct _tlvbuf_dtim_period {
+    /** Header */
+	TLVHEADER;
+    /** DTIM period */
+	t_u8 dtim_period;
+} PACK_END tlvbuf_dtim_period;
+
+/** TLV buffer : BSS status */
+typedef PACK_START struct _tlvbuf_bss_status {
+    /** Header */
+	TLVHEADER;
+    /** BSS status */
+	t_u16 bss_status;
+} PACK_END tlvbuf_bss_status;
+
+/** TLV buffer : Channel */
+typedef PACK_START struct _tlvbuf_phyparamdsset {
+    /** Header */
+	TLVHEADER;
+    /** Channel */
+	t_u8 channel;
+} PACK_END tlvbuf_phyparamdsset;
+
+/** TLV buffer : Operational rates */
+typedef PACK_START struct _tlvbuf_rates {
+    /** Header */
+	TLVHEADER;
+    /** Operational rates */
+	t_u8 operational_rates[0];
+} PACK_END tlvbuf_rates;
+
+/** TLV buffer : Tx power */
+typedef PACK_START struct _tlvbuf_tx_power {
+    /** Header */
+	TLVHEADER;
+    /** Tx power in dBm */
+	t_u8 tx_power_dbm;
+} PACK_END tlvbuf_tx_power;
+
+/** TLV buffer : SSID broadcast control */
+typedef PACK_START struct _tlvbuf_bcast_ssid_ctl {
+    /** Header */
+	TLVHEADER;
+    /** SSID broadcast control flag */
+	t_u8 bcast_ssid_ctl;
+} PACK_END tlvbuf_bcast_ssid_ctl;
+
+/** TLV buffer : RSN replay protection */
+typedef PACK_START struct _tlvbuf_rsn_replay_prot {
+    /** Header */
+	TLVHEADER;
+    /** RSN replay protection control flag */
+	t_u8 rsn_replay_prot;
+} PACK_END tlvbuf_rsn_replay_prot;
+
+/** TLV buffer : Preamble control */
+typedef PACK_START struct _tlvbuf_preamble_ctl {
+    /** Header */
+	TLVHEADER;
+    /** Preamble type */
+	t_u8 preamble_type;
+} PACK_END tlvbuf_preamble_ctl;
+
+/** ant_cfg structure */
+typedef PACK_START struct _ant_cfg_t {
+   /** Subcommand */
+	int subcmd;
+   /** Action */
+	int action;
+   /** TX mode configured */
+	int tx_mode;
+   /** RX mode configured */
+	int rx_mode;
+} PACK_END 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;
+
+/** TLV buffer : RTS threshold */
+typedef PACK_START struct _tlvbuf_rts_threshold {
+    /** Header */
+	TLVHEADER;
+    /** RTS threshold */
+	t_u16 rts_threshold;
+} PACK_END tlvbuf_rts_threshold;
+
+/** TLV buffer : Tx data rate */
+typedef PACK_START struct _tlvbuf_tx_data_rate {
+    /** Header */
+	TLVHEADER;
+    /** Tx data rate */
+	t_u16 tx_data_rate;
+} PACK_END tlvbuf_tx_data_rate;
+
+/** TLV buffer : MCBC Data Rate */
+typedef PACK_START struct _tlvbuf_mcbc_data_rate {
+    /** Header */
+	TLVHEADER;
+    /** MCBC data rate */
+	t_u16 mcbc_datarate;
+} PACK_END tlvbuf_mcbc_data_rate;
+
+/** 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
+/** TLV buffer : Packet forward control */
+typedef PACK_START struct _tlvbuf_pkt_fwd_ctl {
+    /** Header */
+	TLVHEADER;
+    /** Packet forwarding control flag */
+	t_u8 pkt_fwd_ctl;
+} PACK_END tlvbuf_pkt_fwd_ctl;
+
+/** 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;
+
+/** TLV buffer : STA MAC address filtering control */
+typedef PACK_START struct _tlvbuf_sta_mac_addr_filter {
+    /** Header */
+	TLVHEADER;
+    /** Filter mode */
+	t_u8 filter_mode;
+    /** Number of STA MACs */
+	t_u8 count;
+    /** STA MAC addresses buffer */
+	t_u8 mac_address[0];
+} PACK_END tlvbuf_sta_mac_addr_filter;
+
+/** TLV buffer : STA ageout timer */
+typedef PACK_START struct _tlvbuf_sta_ageout_timer {
+    /** Header */
+	TLVHEADER;
+    /** STA ageout timer in ms */
+	t_u32 sta_ageout_timer_ms;
+} PACK_END tlvbuf_sta_ageout_timer;
+
+/** TLV buffer : PS STA ageout timer */
+typedef PACK_START struct _tlvbuf_ps_sta_ageout_timer {
+    /** Header */
+	TLVHEADER;
+    /** PS STA ageout timer in ms */
+	t_u32 ps_sta_ageout_timer_ms;
+} PACK_END tlvbuf_ps_sta_ageout_timer;
+
+/** TLV buffer : max station number */
+typedef PACK_START struct _tlvbuf_max_sta_num {
+    /** Header */
+	TLVHEADER;
+    /** max station number configured*/
+	t_u16 max_sta_num_configured;
+    /** max station number supported*/
+	t_u16 max_sta_num_supported;
+} PACK_END tlvbuf_max_sta_num;
+
+/** TLV buffer : retry limit */
+typedef PACK_START struct _tlvbuf_retry_limit {
+    /** Header */
+	TLVHEADER;
+    /** Retry limit */
+	t_u8 retry_limit;
+} PACK_END tlvbuf_retry_limit;
+
+/** TLV buffer : sticky tim config */
+typedef PACK_START struct _tlvbuf_sticky_tim_config {
+    /** Header */
+	TLVHEADER;
+    /** Enable */
+	t_u16 enable;
+    /** Duration */
+	t_u16 duration;
+    /** Sticky Bitmask */
+	t_u16 sticky_bitmask;
+} PACK_END tlvbuf_sticky_tim_config;
+
+/** TLV buffer : sticky tim sta mac address */
+typedef PACK_START struct _tlvbuf_sticky_tim_sta_mac_addr {
+    /** Header */
+	TLVHEADER;
+    /** Control */
+	t_u16 control;
+    /** Station MAC address */
+	t_u8 sta_mac_address[ETH_ALEN];
+} PACK_END tlvbuf_sticky_tim_sta_mac_addr;
+
+/** TLV buffer : 2040 coex config */
+typedef PACK_START struct _tlvbuf_2040_coex {
+    /** Header */
+	TLVHEADER;
+    /** Enable */
+	t_u8 enable;
+} PACK_END tlvbuf_2040_coex;
+
+/** TLV buffer : pairwise key handshake timeout */
+typedef PACK_START struct _tlvbuf_eapol_pwk_hsk_timeout {
+    /** Header */
+	TLVHEADER;
+    /** pairwise update timeout in milliseconds */
+	t_u32 pairwise_update_timeout;
+} PACK_END tlvbuf_eapol_pwk_hsk_timeout;
+
+/** TLV buffer : pairwise key handshake number of retries */
+typedef PACK_START struct _tlvbuf_eapol_pwk_hsk_retries {
+    /** Header */
+	TLVHEADER;
+    /** pairwise key retries */
+	t_u32 pwk_retries;
+} PACK_END tlvbuf_eapol_pwk_hsk_retries;
+
+/** TLV buffer : groupwise key handshake timeout */
+typedef PACK_START struct _tlvbuf_eapol_gwk_hsk_timeout {
+    /** Header */
+	TLVHEADER;
+    /** groupwise update timeout in milliseconds */
+	t_u32 groupwise_update_timeout;
+} PACK_END tlvbuf_eapol_gwk_hsk_timeout;
+
+/** TLV buffer : groupwise key handshake number of retries */
+typedef PACK_START struct _tlvbuf_eapol_gwk_hsk_retries {
+    /** Header */
+	TLVHEADER;
+    /** groupwise key retries */
+	t_u32 gwk_retries;
+} PACK_END tlvbuf_eapol_gwk_hsk_retries;
+
+/** custom IE */
+typedef 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[0];
+} PACK_END custom_ie;
+
+/** TLV buffer : custom IE */
+typedef PACK_START struct _tlvbuf_custom_ie {
+    /** Header */
+	TLVHEADER;
+    /** custom IE data */
+	custom_ie ie_data[0];
+} PACK_END tlvbuf_custom_ie;
+
+/** custom IE info */
+typedef PACK_START struct _custom_ie_info {
+    /** size of buffer */
+	t_u16 buf_size;
+    /** no of buffers of buf_size */
+	t_u16 buf_count;
+} PACK_END custom_ie_info;
+
+/** TLV buffer : custom IE */
+typedef PACK_START struct _tlvbuf_max_mgmt_ie {
+    /** Header */
+	TLVHEADER;
+    /** No of tuples */
+	t_u16 count;
+    /** custom IE info tuples */
+	custom_ie_info info[0];
+} PACK_END tlvbuf_max_mgmt_ie;
+
+/* Bitmap for protocol to use */
+/** No security */
+#define PROTOCOL_NO_SECURITY        1
+/** Static WEP */
+#define PROTOCOL_STATIC_WEP         2
+/** WPA */
+#define PROTOCOL_WPA                8
+/** WPA2 */
+#define PROTOCOL_WPA2               32
+/** WP2 Mixed */
+#define PROTOCOL_WPA2_MIXED         40
+
+/* Bitmap for unicast/bcast cipher type */
+/** None */
+#define CIPHER_NONE                 0
+/** WEP 40 */
+#define CIPHER_WEP_40               1
+/** WEP 104 */
+#define CIPHER_WEP_104              2
+/** TKIP */
+#define CIPHER_TKIP                 4
+/** AES CCMP */
+#define CIPHER_AES_CCMP             8
+/** Valid cipher bitmap */
+#define CIPHER_BITMAP               0x0c
+/** Valid protocol bitmap */
+#define PROTOCOL_BITMAP             0x28
+/** AES CCMP + TKIP cipher */
+#define AES_CCMP_TKIP               12
+
+/** TLV buffer : Authentication Mode */
+typedef PACK_START struct _tlvbuf_auth_mode {
+    /** Header */
+	TLVHEADER;
+    /** Authentication Mode */
+	t_u8 auth_mode;
+} PACK_END tlvbuf_auth_mode;
+
+/** TLV buffer : Security Protocol */
+typedef PACK_START struct _tlvbuf_protocol {
+    /** Header */
+	TLVHEADER;
+    /** Security protocol */
+	t_u16 protocol;
+} PACK_END tlvbuf_protocol;
+
+/** TLV buffer : cipher */
+typedef PACK_START struct _tlvbuf_cipher {
+    /** Header */
+	TLVHEADER;
+    /** Pairwise cipher */
+	t_u8 pairwise_cipher;
+    /** Group cipher */
+	t_u8 group_cipher;
+} PACK_END tlvbuf_cipher;
+
+/** TLV buffer : Pairwise cipher */
+typedef PACK_START struct _tlvbuf_pwk_cipher {
+    /** Header */
+	TLVHEADER;
+    /** Protocol */
+	t_u16 protocol;
+    /** Pairwise cipher */
+	t_u8 pairwise_cipher;
+    /** Reserved */
+	t_u8 reserved;
+} PACK_END tlvbuf_pwk_cipher;
+
+/** TLV buffer : Group cipher */
+typedef PACK_START struct _tlvbuf_gwk_cipher {
+    /** Header */
+	TLVHEADER;
+    /** Group cipher */
+	t_u8 group_cipher;
+    /** Reserved*/
+	t_u8 reserved;
+} PACK_END tlvbuf_gwk_cipher;
+
+/** TLV buffer : Group re-key time */
+typedef PACK_START struct _tlvbuf_group_rekey_timer {
+    /** Header */
+	TLVHEADER;
+    /** Group rekey time in seconds */
+	t_u32 group_rekey_time_sec;
+} PACK_END tlvbuf_group_rekey_timer;
+
+/** Key_mgmt_none */
+#define KEY_MGMT_NONE   0x04
+/** Key_mgmt_psk */
+#define KEY_MGMT_PSK    0x02
+
+/** Key_mgmt_eap */
+#define KEY_MGMT_EAP     0x01
+/** Key_mgmt_psk_sha256 */
+#define KEY_MGMT_PSK_SHA256  0X100
+
+/** Wmm Max AC queues */
+#define MAX_AC_QUEUES   4
+
+/** TLV buffer : KeyMgmt */
+typedef PACK_START struct _tlvbuf_akmp {
+    /** Header */
+	TLVHEADER;
+    /** KeyMgmt */
+	t_u16 key_mgmt;
+    /** key management operation */
+	t_u16 key_mgmt_operation;
+} PACK_END tlvbuf_akmp;
+
+/** TLV buffer : Single WEP key */
+typedef PACK_START struct _tlvbuf_wep_key {
+    /** Header */
+	TLVHEADER;
+    /** Key index */
+	t_u8 key_index;
+    /** Default key flag */
+	t_u8 is_default;
+    /** Key */
+	t_u8 key[0];
+} PACK_END tlvbuf_wep_key;
+
+/** TLV buffer : WPA passphrase */
+typedef PACK_START struct _tlvbuf_wpa_passphrase {
+    /** Header */
+	TLVHEADER;
+    /** WPA passphrase */
+	t_u8 passphrase[0];
+} PACK_END tlvbuf_wpa_passphrase;
+
+/** TLV buffer : Fragmentation threshold */
+typedef PACK_START struct _tlvbuf_frag_threshold {
+    /** Header */
+	TLVHEADER;
+    /** Fragmentation threshold */
+	t_u16 frag_threshold;
+} PACK_END tlvbuf_frag_threshold;
+
+/** MRVL private CMD structure */
+typedef PACK_START struct _mrvl_priv_cmd {
+   /** Command buffer */
+	t_u8 *buf;
+    /** Used length */
+	t_u32 used_len;
+    /** Total length */
+	t_u32 total_len;
+} PACK_END mrvl_priv_cmd;
+
+/* APCMD definitions */
+/** APCMD buffer */
+typedef PACK_START struct _apcmdbuf {
+    /** Header */
+	APCMDHEADER;
+} PACK_END apcmdbuf;
+
+/** APCMD header length */
+#define APCMDHEADERLEN  (sizeof(apcmdbuf))
+
+/** APCMD buffer : sys_info request */
+typedef PACK_START struct _apcmdbuf_sys_info_request {
+    /** Header */
+	APCMDHEADER;
+} PACK_END apcmdbuf_sys_info_request;
+
+/** APCMD buffer : sys_info response */
+typedef PACK_START struct _apcmdbuf_sys_info_response {
+    /** Header */
+	APCMDHEADER;
+    /** System information buffer */
+	t_u8 sys_info[64];
+} PACK_END apcmdbuf_sys_info_response;
+
+/** APCMD buffer : sys_reset */
+typedef PACK_START struct _apcmdbuf_sys_reset {
+    /** Header */
+	APCMDHEADER;
+} PACK_END apcmdbuf_sys_reset;
+
+/** APCMD buffer : sys_configure */
+typedef PACK_START struct _apcmdbuf_sys_configure {
+    /** Header */
+	APCMDHEADER;
+    /** Action : GET or SET */
+	t_u16 action;
+} PACK_END apcmdbuf_sys_configure;
+
+/* Max transmit power for indoor operation */
+#define MAX_TX_PWR_INDOOR    17
+
+/** APCMD buffer : SNMP MIB */
+typedef PACK_START struct _apcmdbuf_snmp_mib {
+    /** Header */
+	APCMDHEADER;
+    /** Action : GET or SET */
+	t_u16 action;
+} PACK_END apcmdbuf_snmp_mib;
+/** APCMD buffer : bss_start */
+typedef PACK_START struct _apcmdbuf_bss_start {
+    /** Header */
+	APCMDHEADER;
+} PACK_END apcmdbuf_bss_start;
+
+/** APCMD buffer : bss_stop */
+typedef PACK_START struct _apcmdbuf_bss_stop {
+    /** Header */
+	APCMDHEADER;
+} PACK_END apcmdbuf_bss_stop;
+
+/** APCMD buffer : sta_deauth */
+typedef PACK_START struct _APCMDBUF_STA_DEAUTH {
+    /** Header */
+	APCMDHEADER;
+    /** STA MAC address to deauthenticate */
+	t_u8 sta_mac_address[ETH_ALEN];
+} PACK_END APCMDBUF_STA_DEAUTH;
+
+/** Reg TYPE*/
+enum reg_commands {
+	CMD_MAC = 1,
+	CMD_BBP,
+	CMD_RF
+};
+
+/** APCMD buffer: Regrdwr */
+typedef PACK_START struct _apcmdbuf_reg_rdwr {
+   /** Header */
+	APCMDHEADER;
+   /** Read or Write */
+	t_u16 action;
+   /** Register offset */
+	t_u16 offset;
+   /** Value */
+	t_u32 value;
+} PACK_END apcmdbuf_reg_rdwr;
+
+/** DOMAIN_CODEs for DFS regions */
+enum {
+	DOMAIN_CODE_FCC = 0x01,
+	DOMAIN_CODE_ETSI,
+	DOMAIN_CODE_MKK,
+	DOMAIN_CODE_IN,
+	DOMAIN_CODE_MY,
+};
+
+/** Region Domain Code */
+typedef PACK_START struct _rgn_dom_code {
+    /** Header */
+	TLVHEADER;
+    /** Domain Code */
+	t_u8 domain_code;
+    /** Reserved field */
+	t_u8 reserved;
+} PACK_END rgn_dom_code_t;
+
+/** sub-band type */
+typedef PACK_START struct _ieeetypes_subband_set {
+	t_u8 first_chan;    /**< First channel */
+	t_u8 no_of_chan;    /**< Number of channels */
+	t_u8 max_tx_pwr;    /**< Maximum Tx power */
+} PACK_END ieeetypes_subband_set_t;
+
+/** country code length  used for 802.11D */
+#define COUNTRY_CODE_LEN    3
+
+/** MAX domain SUB-BAND*/
+#define MAX_SUB_BANDS 40
+
+/** Max Multi Domain Entries for G */
+#define MAX_MULTI_DOMAIN_CAPABILITY_ENTRY_G 1
+
+/** Max Multi Domain Entries for A */
+#define MAX_MULTI_DOMAIN_CAPABILITY_ENTRY_A 31
+
+/** Country code and Sub-band */
+typedef PACK_START struct domain_param {
+    /** Header */
+	TLVHEADER;
+	t_u8 country_code[COUNTRY_CODE_LEN];	 /**< Country code */
+	ieeetypes_subband_set_t subband[0];	 /**< Set of subbands */
+} PACK_END domain_param_t;
+
+/** HostCmd_CFG_80211D */
+typedef PACK_START struct _apcmdbuf_cfg_80211d {
+    /** Header */
+	APCMDHEADER;
+    /** Action */
+	t_u16 action;		/* 0 = ACT_GET; 1 = ACT_SET; */
+    /** Domain parameters */
+	domain_param_t domain;
+} PACK_END apcmdbuf_cfg_80211d;
+
+/** HostCmd_MEM_ACCESS */
+typedef PACK_START struct _apcmdbuf_mem_access {
+    /** Header */
+	APCMDHEADER;
+    /** Action */
+	t_u16 action;		/* 0 = ACT_GET; 1 = ACT_SET; */
+    /** Reserved field */
+	t_u16 reserved;
+    /** Address */
+	t_u32 address;
+    /** Value */
+	t_u32 value;
+} PACK_END apcmdbuf_mem_access;
+
+/** HostCmd_EEPROM_ACCESS */
+typedef PACK_START struct _apcmdbuf_eeprom_access {
+    /** Header */
+	APCMDHEADER;
+    /** Action */
+	t_u16 action;		/* 0 = ACT_GET; */
+    /** Offset field */
+	t_u16 offset;		/* Multiples of 4 */
+    /** Byte count */
+	t_u16 byte_count;	/* Multiples of 4 */
+    /** Value */
+	t_u8 value[1];
+} PACK_END apcmdbuf_eeprom_access;
+
+/** TLV : BT Coex common configuration */
+typedef PACK_START struct _tlvbuf_coex_common_cfg {
+    /** Header */
+	TLVHEADER;
+    /** Configuration bitmap */
+	t_u32 config_bitmap;
+    /** AP Bt Coex Enabled or not */
+	t_u32 ap_bt_coex;
+    /** Reserved */
+	t_u32 reserved[3];
+} PACK_END tlvbuf_coex_common_cfg;
+
+/** TLV : BT Coex SCO configuration */
+typedef PACK_START struct _tlvbuf_coex_sco_cfg {
+    /** Header */
+	TLVHEADER;
+    /** Qtime protection */
+	t_u16 protection_qtime[4];
+    /** Rate protection */
+	t_u16 protection_rate;
+    /** ACL frequency */
+	t_u16 acl_frequency;
+    /** Reserved */
+	t_u32 reserved[4];
+} PACK_END tlvbuf_coex_sco_cfg;
+
+/** TLV : BT Coex ACL configuration */
+typedef PACK_START struct _tlvbuf_coex_acl_cfg {
+    /** Header */
+	TLVHEADER;
+    /** Enabled or not */
+	t_u16 enabled;
+    /** BT time */
+	t_u16 bt_time;
+    /** Wlan time */
+	t_u16 wlan_time;
+    /** Rate protection */
+	t_u16 protection_rate;
+    /** Reserved */
+	t_u32 reserved[4];
+} PACK_END tlvbuf_coex_acl_cfg;
+
+/** TLV : BT Coex statistics */
+typedef PACK_START struct _tlvbuf_coex_stats {
+    /** Header */
+	TLVHEADER;
+    /** Null not sent */
+	t_u32 null_not_sent;
+    /** Null queued */
+	t_u32 null_queued;
+    /** Null not queued */
+	t_u32 null_not_queued;
+    /** CF end queued */
+	t_u32 cf_end_queued;
+    /** CF end not queued */
+	t_u32 cf_end_not_queued;
+    /** Null allocation failures */
+	t_u32 null_alloc_fail;
+    /** CF end allocation failures */
+	t_u32 cf_end_alloc_fail;
+    /** Reserved */
+	t_u32 reserved[8];
+} PACK_END tlvbuf_coex_stats;
+
+/** APCMD buffer : BT Coex API extension */
+typedef PACK_START struct _apcmdbuf_coex_config {
+    /** Header */
+	APCMDHEADER;
+    /** Action : GET or SET */
+	t_u16 action;
+    /** Reserved for alignment */
+	t_u16 coex_reserved;
+    /** TLV buffer */
+	t_u8 tlv_buffer[0];
+} PACK_END apcmdbuf_coex_config;
+
+/** BIT value */
+#define MBIT(x)    (((t_u32)1) << (x))
+/** RadioType : Support for 40Mhz channel BW */
+#define IS_CHANNEL_WIDTH_40(Field2) (Field2 & MBIT(2))
+/** RadioType : Get secondary channel */
+#define GET_SECONDARY_CHAN(Field2) (Field2 & (MBIT(0) | MBIT(1)))
+/** RadioType : Is RIFS allowed */
+#define IS_RIFS_ALLOWED(Field2) (Field2 & MBIT(3))
+/** RadioType : Get HT Protection */
+#define GET_HT_PROTECTION(Field3) (Field3 & (MBIT(0) | MBIT(1)))
+/** RadioType : Are Non-GreenField STAs present */
+#define NONGF_STA_PRESENT(Field3) (Field3 & MBIT(2))
+/** RadioType : Are OBSS Non-HT STAs present */
+#define OBSS_NONHT_STA_PRESENT(Field3) (Field3 & MBIT(4))
+
+/** HT Capabilities Data */
+typedef struct 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;
+} PACK_END HTCap_t, *pHTCap_t;
+
+/** HT Information Data */
+typedef struct 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];
+} PACK_END HTInfo_t, *pHTInfo_t;
+
+/** MLAN 802.11 MAC Address */
+typedef t_u8 mlan_802_11_mac_addr[ETH_ALEN];
+
+/** mlan_802_11_ssid data structure */
+typedef struct _mlan_802_11_ssid {
+    /** SSID Length */
+	t_u32 ssid_len;
+    /** SSID information field */
+	t_u8 ssid[MAX_SSID_LENGTH];
+} mlan_802_11_ssid;
+
+/** scan_chan_list data structure */
+typedef struct _scan_chan_list {
+    /** Channel number*/
+	t_u8 chan_number;
+    /** Band config type */
+	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_ONESHOT_FILTER];
+} mac_filter;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef 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 */
+} PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef 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 */
+} PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef 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 */
+} PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM parameter IE  */
+typedef 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 */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} PACK_END WmmParameter_t, *pWmmParameter_t;
+
+/** 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 */
+	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;
+
+/** BSS config structure */
+typedef struct _bss_config_t {
+    /** 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 */
+	t_u8 tx_power_level;
+    /** Tx antenna */
+	t_u8 tx_antenna;
+    /** Rx anteena */
+	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 the unit of 100ms  */
+	t_u32 sta_ageout_timer;
+    /** PS station ageout timer in the 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
+	 */
+    /** 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 20/40 coex */
+	t_u8 enable_2040coex;
+    /** key managment operation */
+	t_u16 key_mgmt_operation;
+    /** BSS status */
+	t_u16 bss_status;
+#ifdef WIFI_DIRECT_SUPPORT
+	/* pre shared key */
+	t_u8 psk[32];
+#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[MAX_CHANNELS];
+    /** Wmm parameters */
+	WmmParameter_t wmm_para;
+} bss_config_t;
+
+/** 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,
+};
+
+/** station info */
+typedef struct _sta_info {
+    /** STA MAC address */
+	t_u8 mac_address[ETH_ALEN];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+    /** station bandmode */
+	t_u8 bandmode;
+} sta_info;
+
+/** sta_list structure */
+typedef struct _sta_list {
+    /** station count */
+	t_u16 sta_count;
+    /** station list */
+	sta_info info[MAX_NUM_CLIENTS];
+} sta_list;
+
+/** mlan_deauth_param */
+typedef struct _deauth_param {
+    /** STA mac addr */
+	t_u8 mac_addr[ETH_ALEN];
+    /** deauth reason */
+	t_u16 reason_code;
+} deauth_param;
+
+/** APCMD buffer : bss_configure */
+typedef PACK_START struct _apcmdbuf_bss_configure {
+    /** Action : GET or SET */
+	t_u32 action;
+} PACK_END apcmdbuf_bss_configure;
+
+/** Max EEPROM length */
+#define MAX_EEPROM_LEN         20
+
+/** Subcmd id for global flag */
+#define DEBUG_SUBCOMMAND_GMODE          1
+/** Subcmd id for Majorid mask */
+#define DEBUG_SUBCOMMAND_MAJOREVTMASK   2
+/** Subcmd id to trigger a scan */
+#define DEBUG_SUBCOMMAND_CHANNEL_SCAN   3
+
+/** Channel scan entry for each channel */
+typedef PACK_START struct _channel_scan_entry_t {
+    /** Channel Number */
+	t_u8 chan_num;
+    /** Number of APs */
+	t_u8 num_of_aps;
+    /** CCA count */
+	t_u32 cca_count;
+    /** Duration */
+	t_u32 duration;
+    /** Channel weight */
+	t_u32 channel_weight;
+} PACK_END channel_scan_entry_t;
+
+/** Channel scan entry */
+typedef PACK_START struct _channel_scan_entry {
+    /** Number of channels */
+	t_u8 num_channels;
+    /** Channel scan entry */
+	channel_scan_entry_t cst[0];
+} PACK_END channel_scan_entry;
+
+/** HostCmd_CFG_DATA */
+typedef PACK_START struct _apcmdbuf_cfg_data {
+    /** Header */
+	APCMDHEADER;
+    /** Action */
+	t_u16 action;
+    /** Type */
+	t_u16 type;
+    /** Data length */
+	t_u16 data_len;
+    /** Data */
+	t_u8 data[0];
+} PACK_END apcmdbuf_cfg_data;
+
+/** Maximum size of set/get configurations */
+#define MAX_CFG_DATA_SIZE   2000	/* less than MRVDRV_SIZE_OF_CMD_BUFFER */
+
+/** HostCmd_CMD_PMF_PARAMS */
+typedef PACK_START struct _apcmdbuf_pmf_params {
+    /** Header */
+	APCMDHEADER;
+    /** Action */
+	t_u16 action;		/* 0 = ACT_GET; 1 = ACT_SET; */
+    /** Params */
+	PACK_START struct {
+		t_u8 mfpc:1;	/* capable bit */
+		t_u8 mfpr:1;	/* required bit */
+		t_u8 rsvd:6;
+	} PACK_END params;
+} PACK_END apcmdbuf_pmf_params;
+
+/** Host Command ID bit mask (bit 11:0) */
+#define HostCmd_CMD_ID_MASK             0x0fff
+/** APCMD response check */
+#define APCMD_RESP_CHECK            0x8000
+
+/* AP CMD IDs */
+/** APCMD : sys_info */
+#define APCMD_SYS_INFO              0x00ae
+/** APCMD : sys_reset */
+#define APCMD_SYS_RESET             0x00af
+/** APCMD : sys_configure */
+#define APCMD_SYS_CONFIGURE         0x00b0
+/** APCMD : bss_start */
+#define APCMD_BSS_START             0x00b1
+/** APCMD : bss_stop */
+#define APCMD_BSS_STOP              0x00b2
+/** APCMD : sta_list */
+#define APCMD_STA_LIST              0x00b3
+/** APCMD : sta_deauth */
+#define APCMD_STA_DEAUTH            0x00b5
+/** SNMP MIB SET/GET */
+#define HostCmd_SNMP_MIB            0x0016
+/** Read/Write Mac register */
+#define HostCmd_CMD_MAC_REG_ACCESS  0x0019
+/** Read/Write BBP register */
+#define HostCmd_CMD_BBP_REG_ACCESS  0x001a
+/** Read/Write RF register */
+#define HostCmd_CMD_RF_REG_ACCESS   0x001b
+/** Host Command ID : EEPROM access */
+#define HostCmd_EEPROM_ACCESS       0x0059
+/** Host Command ID : Memory access */
+#define HostCmd_CMD_MEM_ACCESS      0x0086
+/** Host Command ID : 802.11D configuration */
+#define HostCmd_CMD_802_11D_DOMAIN_INFO      0x005b
+/** Host Command ID : Configuration data */
+#define HostCmd_CMD_CFG_DATA        0x008f
+
+/** Oid for 802.11D enable/disable */
+#define OID_80211D_ENABLE           0x0009
+/** Oid for 802.11H enable/disable */
+#define OID_80211H_ENABLE           0x000a
+
+/** Host Command ID:  ROBUST_COEX */
+#define HostCmd_ROBUST_COEX         0x00e0
+
+/** Host Command ID: PMF_PARAMS */
+#define HostCmd_CMD_PMF_PARAMS      0x0131
+
+/* TLV IDs */
+/** TLV : Base */
+#define PROPRIETARY_TLV_BASE_ID         0x0100
+
+/** TLV : SSID */
+#define MRVL_SSID_TLV_ID                0x0000
+/** TLV : Operational rates */
+#define MRVL_RATES_TLV_ID               0x0001
+/** TLV : Channel */
+#define MRVL_PHYPARAMDSSET_TLV_ID       0x0003
+/**TLV: Domain type */
+#define TLV_TYPE_DOMAIN                 0x0007
+
+/** TLV type : Scan Channels list */
+#define MRVL_CHANNELLIST_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 0x01)	//0x0101
+/** TLV type : Authentication type */
+#define MRVL_AUTH_TLV_ID                (PROPRIETARY_TLV_BASE_ID + 0x1f)	//0x011f
+/** TLV Id : Channel Config */
+#define MRVL_CHANNELCONFIG_TLV_ID       (PROPRIETARY_TLV_BASE_ID + 0x2a)	//0x012a
+/** TLV : AP MAC address */
+#define MRVL_AP_MAC_ADDRESS_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 0x2b)	//0x012b
+/** TLV : Beacon period */
+#define MRVL_BEACON_PERIOD_TLV_ID       (PROPRIETARY_TLV_BASE_ID + 0x2c)	//0x012c
+/** TLV : DTIM period */
+#define MRVL_DTIM_PERIOD_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 0x2d)	//0x012d
+/** TLV : Tx power */
+#define MRVL_TX_POWER_TLV_ID            (PROPRIETARY_TLV_BASE_ID + 0x2f)	//0x012f
+/** TLV : SSID broadcast control */
+#define MRVL_BCAST_SSID_CTL_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 0x30)	//0x0130
+/** TLV : Preamble control */
+#define MRVL_PREAMBLE_CTL_TLV_ID        (PROPRIETARY_TLV_BASE_ID + 0x31)	//0x0131
+/** TLV : RTS threshold */
+#define MRVL_RTS_THRESHOLD_TLV_ID       (PROPRIETARY_TLV_BASE_ID + 0x33)	//0x0133
+/** TLV : Packet forwarding control */
+#define MRVL_PKT_FWD_CTL_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 0x36)	//0x0136
+/** TLV : STA information */
+#define MRVL_STA_INFO_TLV_ID            (PROPRIETARY_TLV_BASE_ID + 0x37)	//0x0137
+/** TLV : STA MAC address filter */
+#define MRVL_STA_MAC_ADDR_FILTER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0x38)	//0x0138
+/** TLV : STA ageout timer */
+#define MRVL_STA_AGEOUT_TIMER_TLV_ID    (PROPRIETARY_TLV_BASE_ID + 0x39)	//0x0139
+/** TLV : WEP keys */
+#define MRVL_WEP_KEY_TLV_ID             (PROPRIETARY_TLV_BASE_ID + 0x3b)	//0x013b
+/** TLV : WPA passphrase */
+#define MRVL_WPA_PASSPHRASE_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 0x3c)	//0x013c
+/** TLV type : protocol TLV */
+#define MRVL_PROTOCOL_TLV_ID            (PROPRIETARY_TLV_BASE_ID + 0x40)	//0x0140
+/** TLV type : AKMP TLV */
+#define MRVL_AKMP_TLV_ID                (PROPRIETARY_TLV_BASE_ID + 0x41)	//0x0141
+/** TLV type : Cipher TLV */
+#define MRVL_CIPHER_TLV_ID              (PROPRIETARY_TLV_BASE_ID + 0x42)	//0x0142
+/** TLV : Fragment threshold */
+#define MRVL_FRAG_THRESHOLD_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 0x46)	//0x0146
+/** TLV : Group rekey timer */
+#define MRVL_GRP_REKEY_TIME_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 0x47)	//0x0147
+/**TLV: Max Station number */
+#define MRVL_MAX_STA_CNT_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 0x55)	//0x0155
+/**TLV: Retry limit */
+#define MRVL_RETRY_LIMIT_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 0x5d)	//0x015d
+/**TLV: MCBC data rate */
+#define MRVL_MCBC_DATA_RATE_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 0x62)	//0x0162
+/**TLV: RSN replay protection */
+#define MRVL_RSN_REPLAY_PROT_TLV_ID     (PROPRIETARY_TLV_BASE_ID + 0x64)	//0x0164
+/** TLV: Management IE list */
+#define MRVL_MGMT_IE_LIST_TLV_ID        (PROPRIETARY_TLV_BASE_ID + 0x69)	//0x0169
+/** TLV : Coex common configuration */
+#define MRVL_BT_COEX_COMMON_CFG_TLV_ID  (PROPRIETARY_TLV_BASE_ID + 0x6c)	//0x016c
+/** TLV : Coex SCO configuration */
+#define MRVL_BT_COEX_SCO_CFG_TLV_ID     (PROPRIETARY_TLV_BASE_ID + 0x6d)	//0x016d
+/** TLV : Coex ACL configuration */
+#define MRVL_BT_COEX_ACL_CFG_TLV_ID     (PROPRIETARY_TLV_BASE_ID + 0x6e)	//0x016e
+/** TLV : Coex stats configuration */
+#define MRVL_BT_COEX_STATS_TLV_ID       (PROPRIETARY_TLV_BASE_ID + 0x6f)	//0x016f
+/** TLV :Pairwise Handshake Timeout */
+#define MRVL_EAPOL_PWK_HSK_TIMEOUT_TLV_ID   (PROPRIETARY_TLV_BASE_ID + 0x75)	//0x0175
+/** TLV :Pairwise Handshake Retries */
+#define MRVL_EAPOL_PWK_HSK_RETRIES_TLV_ID   (PROPRIETARY_TLV_BASE_ID + 0x76)	//0x0176
+/** TLV :Groupwise Handshake Timeout */
+#define MRVL_EAPOL_GWK_HSK_TIMEOUT_TLV_ID   (PROPRIETARY_TLV_BASE_ID + 0x77)	//0x0177
+/** TLV :Groupwise Handshake Retries */
+#define MRVL_EAPOL_GWK_HSK_RETRIES_TLV_ID   (PROPRIETARY_TLV_BASE_ID + 0x78)	//0x0178
+/** TLV : PS STA ageout timer */
+#define MRVL_PS_STA_AGEOUT_TIMER_TLV_ID     (PROPRIETARY_TLV_BASE_ID + 0x7b)	//0x017b
+/** TLV : Pairwise Cipher */
+#define MRVL_CIPHER_PWK_TLV_ID              (PROPRIETARY_TLV_BASE_ID + 0x91)	//0x0191
+/** TLV : Group Cipher */
+#define MRVL_CIPHER_GWK_TLV_ID              (PROPRIETARY_TLV_BASE_ID + 0x92)	//0x0192
+/** TLV : BSS Status */
+#define MRVL_BSS_STATUS_TLV_ID              (PROPRIETARY_TLV_BASE_ID + 0x93)	//0x0193
+/** TLV : Restricted Client Mode */
+#define MRVL_RESTRICT_CLIENT_MODE_TLV_ID    (PROPRIETARY_TLV_BASE_ID + 0xC1)	//0x01C1
+/** TLV : Sticky TIM config */
+#define MRVL_STICKY_TIM_CONFIG_TLV_ID       (PROPRIETARY_TLV_BASE_ID + 0x96)	//0x0196
+/** TLV : Sticky TIM MAC address */
+#define MRVL_STICKY_TIM_STA_MAC_ADDR_TLV_ID       (PROPRIETARY_TLV_BASE_ID + 0x97)	//0x0197
+/** TLV : 20/40 coex config */
+#define MRVL_2040_BSS_COEX_CONTROL_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 0x98)	//0x0198
+/** TLV : Max Management IE */
+#define MRVL_MAX_MGMT_IE_TLV_ID             (PROPRIETARY_TLV_BASE_ID + 0xAA)	//0x01aa
+
+/** TLV : Region Domain Code */
+#define MRVL_REGION_DOMAIN_CODE_TLV_ID            (PROPRIETARY_TLV_BASE_ID + 0xAB)	//0x01ab
+
+#ifdef RX_PACKET_COALESCE
+#define MRVL_RX_PKT_COAL_TLV_ID             (PROPRIETARY_TLV_BASE_ID + 0xC9)
+#endif
+
+/** TLV : Tx beacon rate */
+#define MRVL_TX_BEACON_RATE_TLV_ID        (PROPRIETARY_TLV_BASE_ID + 288)	//0x0220
+
+#ifdef RX_PACKET_COALESCE
+/** RX packet coalesce tlv */
+typedef PACK_START struct _tlvbuf_rx_pkt_coal_t {
+    /** Header */
+	TLVHEADER;
+    /** threshold for rx packets */
+	t_u32 rx_pkt_count;
+    /** timeout for rx coalescing timer */
+	t_u16 delay;
+} PACK_END tlvbuf_rx_pkt_coal_t;
+#endif
+#define MRVL_AP_WMM_PARAM_TLV_ID            (PROPRIETARY_TLV_BASE_ID + 0xD0)
+
+/** TLV : TDLS Extended Capability  */
+#define MRVL_TDLS_EXT_CAP_TLV_ID                0x007f
+/** TDLS Prohibit bit mask */
+#define TDLS_PROHIBIT_MASK                            0x40
+/** TDLS Prohibit bit */
+#define TDLS_PROHIBIT                       6
+/** TDLS Channel Switch Prohibit bit mask */
+#define TDLS_CHANNEL_SWITCH_PROHIBIT_MASK             0x80
+/** TDLS Channel Switch Prohibit bit */
+#define TDLS_CHANNEL_SWITCH_PROHIBIT        7
+/** TDLS Maximum extended capability length */
+#define MAX_TDLS_EXT_CAP_LEN                64
+
+/** TLV: HT_CAPABILITY */
+#define HT_CAPABILITY_TLV_ID            0x2d
+/** TLV: HT_INFO */
+#define HT_INFO_TLV_ID                  0x3d
+/** config mask for HT_CAP */
+#define HT_CAP_CONFIG_MASK              0x10f3
+/** default htcap value */
+#define DEFAULT_HT_CAP_VALUE            0x117e
+/** HT_CAP validity check */
+#define HT_CAP_CHECK_MASK		0x10c
+/** config mask for ampdu parameter */
+#define AMPDU_CONFIG_MASK               0x1f
+
+/** Macro to check if 11n 40 Mhz is enabled */
+#define IS_11N_40MHZ_ENABLED(cap)  ((cap) & 0x002) >> 1
+/** Macro to check if 11n 20MHz with short GI is enabled */
+#define IS_11N_20MHZ_SHORTGI_ENABLED(cap)  ((cap) & 0x0020) >> 5
+/** Macro to check if 11n Green Field is enabled */
+#define IS_11N_GF_ENABLED(cap)  ((cap) & 0x0010) >> 4
+/** MCS set length */
+#define MCS_SET_LEN     16
+
+/** HT Capabilities tlv */
+typedef PACK_START struct _tlvbuf_htcap_t {
+    /** Header */
+	TLVHEADER;
+    /** HTCap struct */
+	HTCap_t ht_cap;
+} PACK_END tlvbuf_htcap_t;
+
+/** HT Information tlv */
+typedef PACK_START struct _tlvbuf_htinfo_t {
+    /** Header */
+	TLVHEADER;
+    /** HTCap struct */
+	HTInfo_t ht_info;
+} PACK_END tlvbuf_htinfo_t;
+
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE   18
+
+/** tx_rate_cfg structure */
+typedef PACK_START struct _tx_rate_cfg_t {
+   /** Action */
+	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];
+} PACK_END tx_rate_cfg_t;
+
+/** Mask for 2X2 support*/
+#define STREAM_2X2_MASK     0x20
+/** MCS_SET_1 Mask */
+#define MCS_SET_1_MASK      0x0000ff00
+/** MCS0-7 supported */
+#define DEFAULT_MCS_SET_0   0xff
+/** MCS8-15 support */
+#define DEFAULT_MCS_SET_1   0xff
+/** MCS32 supported */
+#define DEFAULT_MCS_SET_4   0x01
+/** Rate bitmap for MCS 0 */
+#define UAP_RATE_BITMAP_MCS0  32
+/** Rate bitmap for MCS 127 */
+#define UAP_RATE_BITMAP_MCS127 159
+/** Rate index for MCS 0 */
+#define UAP_RATE_INDEX_MCS0   12
+/** Rate index for MCS 7 */
+#define UAP_RATE_INDEX_MCS7   19
+/** Rate index for MCS 32 */
+#define UAP_RATE_INDEX_MCS32  44
+
+/* Mask to enable/disable restricted client mode */
+#define RESTRICT_CLIENT_MODE_ENABLE_MASK   0x01
+/* Mask for B Only mode */
+#define B_ONLY_MASK   0x0100
+/* Mask for A Only mode */
+#define A_ONLY_MASK   0x0200
+/* Mask for G Only mode */
+#define G_ONLY_MASK   0x0400
+/* Mask for N Only mode */
+#define N_ONLY_MASK   0x0800
+/* Mask for AC Only mode */
+#define AC_ONLY_MASK  0x1000
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef enum _wmm_ac {
+	AC_BE,
+	AC_BK,
+	AC_VI,
+	AC_VO,
+} wmm_ac;
+
+/** Restricted Client Mode tlv */
+typedef PACK_START struct _tlvbuf_restrict_client_mode {
+    /** Header */
+	TLVHEADER;
+    /** Mode Config
+     *  Bit 0: 1 enable restricted client mode
+     *         0 disable restricted client mode
+     *  Bits [1-7] : set to 0
+     *  Bits [8:12]
+     *         Bit 8: B only Mode
+     *         Bit 9: A only Mode
+     *         Bit 10: G only Mode
+     *         Bit 11: N only Mode
+     *         Bit 12: AC only Mode
+     *  Currently only one of the bits from [8-12] should be set
+     *  Bits [13:15]: set to 0
+     */
+	t_u16 mode_config;
+} PACK_END tlvbuf_restrict_client_mode;
+
+/** ID for VENDOR_SPECIFIC_IE */
+#define VENDOR_SPECIFIC_IE_TLV_ID   0xdd
+
+/** WMM_PS Mask */
+#define WMM_PS_MASK                 0x7f
+/** Enable WMM PS */
+#define ENABLE_WMM_PS               128
+/** Disable WMM PS */
+#define DISABLE_WMM_PS              0
+/** Maximum number of AC QOS queues available in the driver/firmware */
+#define MAX_AC_QUEUES               4
+
+/** wmm parameter tlv */
+typedef PACK_START struct _tlvbuf_wmm_para_t {
+    /** Header */
+	TLVHEADER;
+    /** Wmm parameter */
+	WmmParameter_t wmm_para;
+} PACK_END tlvbuf_wmm_para_t;
+
+/** data_structure for cmd vhtcfg */
+struct eth_priv_vhtcfg {
+    /** Band (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;
+};
+
+typedef struct _vht_cfg_para {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get
+     * Will be eliminatied on moal */
+	t_u32 action;
+	/* VHT configuration */
+	struct eth_priv_vhtcfg vht_cfg;
+} vht_cfg_para;
+
+/** data_structure for cmd uap operation control */
+struct eth_priv_uap_oper_ctrl {
+    /**operation control*/
+	t_u16 ctrl;
+    /**channel operation*/
+	t_u16 chan_opt;
+    /**band configuration*/
+	t_u8 bandcfg;
+    /**channel */
+	t_u8 channel;
+};
+
+typedef struct _uap_operation_ctrl {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+    /**uap operation control */
+	struct eth_priv_uap_oper_ctrl uap_oper;
+} uap_operation_ctrl;
+
+/** Function Prototype Declaration */
+int mac2raw(char *mac, t_u8 *raw);
+void print_mac(t_u8 *raw);
+int uap_ioctl(t_u8 *cmd, t_u16 *size, t_u16 buf_size);
+void print_auth(tlvbuf_auth_mode *tlv);
+void print_tlv(t_u8 *buf, t_u16 len);
+void print_cipher(tlvbuf_cipher *tlv);
+void print_pwk_cipher(tlvbuf_pwk_cipher *tlv);
+void print_gwk_cipher(tlvbuf_gwk_cipher *tlv);
+void print_rate(tlvbuf_rates *tlv);
+int string2raw(char *str, unsigned char *raw);
+void print_mac_filter(tlvbuf_sta_mac_addr_filter *tlv);
+int ishexstring(void *hex);
+unsigned int a2hex(char *s);
+int fparse_for_hex(FILE * fp, t_u8 *dst);
+int is_input_valid(valid_inputs cmd, int argc, char *argv[]);
+int is_cipher_valid(int pairwisecipher, int groupcipher);
+int is_cipher_valid_with_proto(int pairwisecipher, int groupcipher,
+			       int protocol);
+int get_sys_cfg_rates(t_u8 *rates);
+int is_tx_rate_valid(t_u8 rate);
+int is_mcbc_rate_valid(t_u8 rate);
+void hexdump_data(char *prompt, void *p, int len, char delim);
+unsigned char hexc2bin(char chr);
+int check_sys_config(t_u8 *buf, t_u16 len);
+int check_bss_config(t_u8 *buf);
+int get_max_sta_num_supported(t_u16 *max_sta_num_supported);
+int get_sys_cfg_protocol(t_u16 *proto);
+int is_cipher_valid_with_11n(int pairwisecipher, int groupcipher,
+			     int protocol, int enable_11n);
+int get_sys_cfg_11n(HTCap_t *pHtCap);
+int get_fw_info(fw_info *pfw_info);
+t_u8 parse_domain_file(char *country, int band,
+		       ieeetypes_subband_set_t *sub_bands, t_u8 *pdomain_code);
+int sg_snmp_mib(t_u16 action, t_u16 oid, t_u16 size, t_u8 *oid_buf);
+int check_channel_validity_11d(int channel, int band, int set_domain);
+int check_tx_pwr_validity_11d(t_u8 tx_pwr);
+int prepare_host_cmd_buffer(char *fname, char *cmd_name, t_u8 *buf);
+char *mlan_config_get_line(FILE * fp, char *s, t_s32 size, int *line);
+int uap_ioctl_dfs_repeater_mode(int *mode);
+/**
+ *    @brief isdigit for String.
+ *
+ *    @param x            Char string
+ *    @return             UAP_FAILURE for non-digit.
+ *                        UAP_SUCCESS for digit
+ */
+static inline int
+ISDIGIT(char *x)
+{
+	unsigned int i;
+	for (i = 0; i < strlen(x); i++)
+		if (isdigit(x[i]) == 0)
+			return UAP_FAILURE;
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief  Detects if band is different across the list of scan channels
+ *
+ *  @param  argc    Number of elements
+ *  @param  argv    Array of strings
+ *  @return UAP_FAILURE or UAP_SUCCESS
+ */
+static inline int
+has_diff_band(int argc, char *argv[])
+{
+	int i = 0;
+	int channel = 0;
+	int band[MAX_CHANNELS];
+	/* Check for different bands */
+	for (i = 0; i < argc; i++) {
+		band[i] = -1;
+		sscanf(argv[i], "%d.%d", &channel, &band[i]);
+		if (band[i] == -1) {
+			if (channel > MAX_CHANNELS_BG) {
+				band[i] = 1;
+			} else {
+				band[i] = 0;
+			}
+		}
+	}
+	for (i = 0; i <= (argc - 2); i++) {
+		if (band[i] != band[i + 1]) {
+			return UAP_FAILURE;
+		}
+	}
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief  Detects duplicates channel in array of strings
+ *
+ *  @param  argc    Number of elements
+ *  @param  argv    Array of strings
+ *  @return UAP_FAILURE or UAP_SUCCESS
+ */
+static inline int
+has_dup_channel(int argc, char *argv[])
+{
+	int i, j;
+	/* Check for duplicate */
+	for (i = 0; i < (argc - 1); i++) {
+		for (j = i + 1; j < argc; j++) {
+			if (atoi(argv[i]) == atoi(argv[j])) {
+				return UAP_FAILURE;
+			}
+		}
+	}
+	return UAP_SUCCESS;
+}
+
+/**
+ *  @brief  Detects duplicates rate in array of strings
+ *          Note that 0x82 and 0x2 are same for rate
+ *
+ *  @param  argc    Number of elements
+ *  @param  argv    Array of strings
+ *  @return UAP_FAILURE or UAP_SUCCESS
+ */
+static inline int
+has_dup_rate(int argc, char *argv[])
+{
+	int i, j;
+	/* Check for duplicate */
+	for (i = 0; i < (argc - 1); i++) {
+		for (j = i + 1; j < argc; j++) {
+			if ((A2HEXDECIMAL(argv[i]) & ~BASIC_RATE_SET_BIT) ==
+			    (A2HEXDECIMAL(argv[j]) & ~BASIC_RATE_SET_BIT)) {
+				return UAP_FAILURE;
+			}
+		}
+	}
+	return UAP_SUCCESS;
+}
+#endif /* _UAP_H */
diff --git a/wlan_sd8897/mapp/wifidirectutl/Makefile b/wlan_sd8897/mapp/wifidirectutl/Makefile
new file mode 100644
index 0000000..316c467
--- /dev/null
+++ b/wlan_sd8897/mapp/wifidirectutl/Makefile
@@ -0,0 +1,56 @@
+# File : wifidirectutl/Makefile
+#
+# Copyright (C) 2008-2017, Marvell International Ltd. All Rights Reserved
+
+# Path to the top directory of the wlan distribution
+PATH_TO_TOP = ../..
+
+# Determine how we should copy things to the install directory
+ABSPATH := $(filter /%, $(INSTALLDIR))
+RELPATH := $(filter-out /%, $(INSTALLDIR))
+INSTALLPATH := $(ABSPATH)
+ifeq ($(strip $(INSTALLPATH)),)
+INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH)
+endif
+
+# Override CFLAGS for application sources, remove __ kernel namespace defines
+CFLAGS := $(filter-out -D__%, $(ccflags-y))
+# remove KERNEL include dir
+CFLAGS := $(filter-out -I$(KERNELDIR)%, $(CFLAGS))
+
+
+CFLAGS += -Wall
+LIBS = -lrt
+
+.PHONY: default tags all
+
+OBJECTS = wifidirectutl.o
+HEADERS = wifidirectutl.h
+
+ifneq (,$(findstring DWIFI_DISPLAY_SUPPORT, $(CFLAGS)))
+OBJECTS += wifi_display.o
+HEADERS += wifi_display.h
+endif
+
+TARGET = wifidirectutl
+
+build default: $(TARGET)
+	@cp -f $(TARGET) $(INSTALLPATH)
+	@cp -rf config $(INSTALLPATH)
+
+
+all : tags default
+
+$(TARGET): $(OBJECTS) $(HEADERS)
+	$(ECHO)$(CC) $(LIBS) -o $@ $(OBJECTS)
+
+%.o: %.c $(HEADERS)
+	$(ECHO)$(CC) $(CFLAGS) -c -o $@ $<
+
+tags:
+	ctags -R -f tags.txt
+
+distclean clean:
+	$(ECHO)$(RM) $(OBJECTS) $(TARGET)
+	$(ECHO)$(RM) tags.txt
+
diff --git a/wlan_sd8897/mapp/wifidirectutl/config/wifidirect.conf b/wlan_sd8897/mapp/wifidirectutl/config/wifidirect.conf
new file mode 100644
index 0000000..70973b2
--- /dev/null
+++ b/wlan_sd8897/mapp/wifidirectutl/config/wifidirect.conf
@@ -0,0 +1,415 @@
+#	File : wifidirect.conf
+
+######################### WIFIDIRECT Configuration command ##################
+
+wifidirect_config={
+	# Arrange in order of subelement Ids
+    #
+	# WIFIDIRECT IE parameters.
+    #
+
+	Capability={
+		DeviceCapability=33
+		GroupCapability=8
+	}
+	GroupOwnerIntent={
+		Intent=5                       # 0-15. 15-> highest GO desire
+	}
+	Channel={                          # Listen channel attribute.
+		CountryString="US"
+		RegulatoryClass=81
+		ChannelNumber=6
+	}
+	InfrastructureManageabilityInfo={
+		Manageability=0
+	}
+	ChannelList={
+		CountryString="US"
+		# multiple attributes channel entry list
+		Regulatory_Class_1=81              # Regulatory class
+		NumofChannels_1=11                 # No of channels
+		ChanList_1=1,2,3,4,5,6,7,8,9,10,11 # Scan channel list
+		Regulatory_Class_2=115             # Regulatory class
+		NumofChannels_2=4                  # No of channels
+		ChanList_2=36,40,44,48             # Scan channel list
+		#Regulatory_Class_3=118            # Regulatory class
+		#NumofChannels_3=4                 # No of channels
+		#ChanList_3=52,56,60,64            # Scan channel list
+		#Regulatory_Class_4=121            # Regulatory class
+		#NumofChannels_4=11                # No of channels
+		#ChanList_4=100,104,108,112,116,120,124,128,132,136,140            # Scan channel list
+		# Enable only one of the country blocks at a time
+		#CountryString="JP"
+		# multiple attributes channel entry list
+		#Regulatory_Class_1=81              # Regulatory class
+		#NumofChannels_1=13                 # No of channels
+		#ChanList_1=1,2,3,4,5,6,7,8,9,10,11,12,13 # Scan channel list
+		#Regulatory_Class_2=115             # Regulatory class
+		#NumofChannels_2=4                  # No of channels
+		#ChanList_2=36,40,44,48             # Scan channel list
+		#Regulatory_Class_3=118            # Regulatory class
+		#NumofChannels_3=4                 # No of channels
+		#ChanList_3=52,56,60,64            # Scan channel list
+		#Regulatory_Class_4=121            # Regulatory class
+		#NumofChannels_4=11                # No of channels
+		#ChanList_4=100,104,108,112,116,120,124,128,132,136,140            # Scan channel list
+	}
+	NoticeOfAbsence={
+		NoA_Index=0                 # Instance of NoA timing
+		OppPS=1                     # Opportunistic Power save
+		CTWindow=10                 # Client Traffic Window
+		NoA_descriptor={
+			CountType_1=255           # Count for GO mode OR Type for client mode
+			Duration_1=51200            # Max absence duration for GO mode OR
+                                    # min acceptable presence period for client mode
+			Interval_1=102400
+			StartTime_1=0
+			#CountType_2=1           # Count for GO mode OR Type for client mode
+			#Duration_2=0            # Max absence duration for GO mode OR
+                                    # min acceptable presence period for client mode
+			#Interval_2=0
+			#StartTime_2=0
+			}
+	}
+	DeviceInfo={
+		DeviceAddress=00:50:43:00:00:00
+		# categ: 2 bytes, OUI: 4 bytes, subcateg: 2 bytes
+		PrimaryDeviceTypeCategory=1
+		PrimaryDeviceTypeOUI=0x00,0x50,0xF2,0x04
+		PrimaryDeviceTypeSubCategory=1
+		SecondaryDeviceCount=2
+		SecondaryDeviceType={
+		    SecondaryDeviceTypeCategory_1=6
+		    SecondaryDeviceTypeOUI_1=0x00,0x50,0xF2,0x04
+		    SecondaryDeviceTypeSubCategory_1=1
+		    SecondaryDeviceTypeCategory_2=4
+		    SecondaryDeviceTypeOUI_2=0x00,0x50,0xF2,0x04
+		    SecondaryDeviceTypeSubCategory_2=1
+		}
+		DeviceName="MRVL_DEFAULT_NAME"
+		# ConfigMethods USB= 0x01
+		# ConfigMethods Ethernet= 0x02
+		# ConfigMethods Label= 0x04
+		# ConfigMethods Display= 0x08
+		# ConfigMethods Ext_NFC_Token= 0x10
+		# ConfigMethods Int_NFC_Token= 0x20
+		# ConfigMethods NFC_Interface= 0x40
+		# ConfigMethods PushButton= 0x80
+		# ConfigMethods KeyPad= 0x100
+		WPSConfigMethods=0x188
+	}
+	GroupId={
+		GroupAddr=00:50:43:00:00:00
+		GroupSsId="DIRECT-"
+	}
+	GroupBSSId={
+                # using LAA for interface address by default
+		GroupBssId=02:50:43:00:00:00
+	}
+	DeviceId={
+		WIFIDIRECT_MAC=00:50:43:00:00:00      # MAC address of wifidirect device in Hex
+	}
+	Interface={
+                # using LAA for interface addresses by default
+		InterfaceAddress=02:50:43:00:00:00
+		InterfaceAddressCount=2
+		InterfaceAddressList=02:50:43:00:00:00,02:52:43:00:00:00
+	}
+	ConfigurationTimeout={
+        # units of 10 milliseconds
+		GroupConfigurationTimeout=250
+		ClientConfigurationTimeout=100
+	}
+	ExtendedListenTime={
+        # units of milliseconds
+		AvailabilityPeriod=1000
+		AvailabilityInterval=1500
+	}
+	IntendedIntfAddress={
+                # using LAA for interface address by default
+		GroupInterfaceAddress=02:50:43:00:00:00
+	}
+	OperatingChannel={                          # Operating channel attribute.
+		CountryString="US"
+		OpRegulatoryClass=81
+		OpChannelNumber=6
+	}
+	InvitationFlagBitmap={
+		InvitationFlag=0           # bit0: Invitation type:
+	}                                   # 0: request to reinvoke a persistent group
+                                            # 1: request to join an active WIFIDIRECT group
+
+
+    #Extra={
+       #Buffer=0x00,0x50,0x43,0x07,0x20,0xa1
+    #}
+
+    #
+	# WPS IE parameters.
+    #
+	WPSIE={
+		WPSVersion=0x10
+		WPSSetupState=0x1
+		WPSRequestType=0x0
+		WPSResponseType=0x0
+		WPSSpecConfigMethods=0x0188
+		WPSUUID=0x12,0x34,0x56,0x78,0x12,0x34,0x56,0x78,0x12,0x34,0x56,0x78,0x12,0x34,0x56,0x78
+		WPSPrimaryDeviceType=0x00,0x01,0x00,0x50,0xF2,0x04,0x00,0x01
+		WPSRFBand=0x01
+		WPSAssociationState=0x00
+		WPSConfigurationError=0x00
+		WPSDevicePassword=0x00
+		WPSDeviceName="MRVL_DEFAULT_NAME"
+		WPSManufacturer=Marvell
+		WPSModelName=SD-8787
+		WPSModelNumber=0x00,0x00,0x00,0x01
+		WPSSerialNumber=0x00,0x00,0x00,0x01
+		WPSVendorExtension=0x00,0x37,0x2A,0x00,0x01,0x20
+	}
+}
+
+
+######################### WIFIDIRECT Parameters configuration command #######
+
+wifidirect_param_config={
+	MinDiscoveryInterval=1
+	MaxDiscoveryInterval=7
+	EnableScan=1
+	#ScanPeerDeviceId=00:50:43:77:43:47
+	#ScanRequestDeviceType=0x01,0x00,0x50,0xF2,0x04,0x01,0x3C,0x10
+	DeviceState=4
+}
+
+######################### WIFIDIRECT Action Frame command ##################
+
+wifidirect_action_frame={
+	PeerAddr=00:50:43:00:00:00
+	Category=4         # 4 : Public action frame, 0x7F : Vendor specific
+	Action=0           # 0xDD : Vendor specific, Others : Reserved.
+	OUI=0x50,0x6F,0x9A
+	OUIType=9          # WFA wifidirect.
+	                   # 15 : WPSE.
+
+	# OUI SubType 0 : GO Negotiation Request
+	# OUI SubType 1 : GO Negotiation Response
+	# OUI SubType 2 : GO Negotiation Confirmation
+	# OUI SubType 3 : WIFIDIRECT Invitation Request
+	# OUI SubType 4 : WIFIDIRECT Invitation Response
+	# OUI SubType 5 : Device Discoverability Request
+	# OUI SubType 6 : Device Discoverability Response
+	# OUI SubType 7 : Provision Discovery Request
+	# OUI SubType 8 : Provision Discovery Response
+
+    #
+    # UPDATE LINE BELOW for APPROPRIATE SUB TYPE
+    #
+	OUISubType=0
+
+	DialogToken=1
+
+	# Arrange in order of subelement Ids
+    # Other parameters which can be configured from WIFIDIRECT config command.
+
+	#DeviceId={
+	#	WIFIDIRECT_MAC=00:50:43:77:46:41      # MAC address of wifidirect device in Hex
+	#}
+	#Interface={
+	#	InterfaceAddress=00:50:43:77:46:41
+	#	InterfaceAddressCount=2
+	#	InterfaceAddressList=00:50:43:77:46:41,00:50:43:78:47:42
+	#}
+}
+
+######################### WIFIDIRECT service discovery command ##################
+
+wifidirect_discovery_request={
+	PeerAddr=00:50:43:00:00:00
+	Category=4
+	Action=10
+	DialogToken=1
+	AdvertizementProtocolIE=0x6c,0x02,0x00,0x00
+                # octet 1: Element Id = 108 ( 0x6c)
+                # octer 2: Length of following fields
+                # octer 3: Bit7: PAME-BI ( Message Exchange BSSID independant)
+                #          Bits0-6: Query response length limit.
+                # octer 4: Advertizement Protocol ID
+	QueryRequestLen={
+	    InfoId=0xDD,0xDD
+        RequestLen={
+		    OUI=0x50,0x6F,0x9A
+		    OUISubType=9
+            ServiceUpdateIndicator=0
+		    VendorLen={
+				ServiceProtocol=0 # 0: All service protocol types
+                                  # 1: Bonjour, 2: uPnP, 3: WS-Discovery
+                                  # 255: Vendor specific
+				ServiceTransactionId=1
+                QueryData={
+                    ## Use Data below, if ServiceProtocol=1 (Bonjour).
+                    #
+                    ## DNSName can be string or hexadecimal sequence of bytes.
+                    #DNSName="_afpovertcp._tcp.local."
+                    # DNSName=0x07,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x0B,0x5F,0x61,0x66,0x70,0x6F,0x76,0x65,0x72,0x74,0x63,0x70,0xC0,0x0C
+                    #DNSType=12
+                    #BonjourVersion=1
+
+                    ## Use Data below, if ServiceProtocol=2 (uPnP).
+                    #
+                    #uPnPVersion=0x10
+                    #uPnPQueryValue="ssdp:all"         #   Searches for all UPnP devices and services
+                    #
+                    # OR any one of following values in WIFIDIRECT spec.
+                    #uPnPQueryValue="upnp:rootdevice"  #   Searches for all UPnP root devices
+                    #uPnPQueryValue="uuid:device-uuid" #   Searches for a particular device
+                    #uPnPQueryValue="urn:schemas-upnp-org:device:deviceType:ver"
+                                                  #   Searches for devices of the given type
+                    #uPnPQueryValue="urn:domain-name:device:deviceType:ver"
+                                                  #   Searches for devices with a vendor-specific type
+                    #uPnPQueryValue="urn:schemas-upnp-org:service:serviceType:ver"
+                                                  #   Searches for devices containing a service of the given type
+                    #uPnPQueryValue="urn:domain-name:service:serviceType:ver"
+                                                  #   Searches for devices containing a vendor-specific service
+			    }
+			}
+        }
+    }
+}
+
+wifidirect_discovery_response={
+	PeerAddr=00:50:43:00:00:00
+	Category=4
+	Action=11
+	DialogToken=1
+	StatusCode=0
+	GasComebackDelay=0x0000
+	AdvertizementProtocolIE=0x6c,0x02,0x7F,0x00
+                # octet 1: Element Id = 108 ( 0x6c)
+                # octer 2: Length of following fields
+                # octer 3: Bit7: PAME-BI ( Message Exchange BSSID independant)
+                #          Bits0-6: Query response length limit.
+                # octer 4: Advertizement Protocol ID
+	QueryResponseLen={
+		InfoId=0xDD,0xDD
+		ResponseLen={
+			OUI=0x50,0x6F,0x9A
+			OUISubType=9
+            ServiceUpdateIndicator=0
+			VendorLen={
+				ServiceProtocol=0 # 0: All service protocol types
+                                  # 1: Bonjour, 2: uPnP, 3: WS-Discovery
+                                  # 255: Vendor specific
+				ServiceTransactionId=1
+				ServiceStatus=0   # 0: Success
+                                  # 1: Service protocol type not available
+                                  # 2: Query data not available
+                                  # 3: Bad request.
+                ResponseData={
+                    ## Use Data below, if ServiceProtocol=1 (Bonjour).
+                    #
+                    ## DNSName can be string or hexadecimal sequence of bytes.
+
+                    DNSName="_afpovertcp._tcp.local."
+                    # DNSName=0x07,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x0B,0x5F,0x61,0x66,0x70,0x6F,0x76,0x65,0x72,0x74,0x63,0x70,0xC0,0x0C
+                    DNSType=12
+                    BonjourVersion=1
+                    ## RecordData can be string or hexadecimal sequence of bytes.
+                    # RecordData=""
+                    RecordData=0x00
+
+                    ## Use Data below, if ServiceProtocol=2 (uPnP).
+                    #
+                    #uPnPVersion=0x10
+                    #uPnPResponseValue="ssdp:all"         #   Searches for all UPnP devices and services
+                    #
+                    # OR any one of following values in WIFIDIRECT spec.
+                    #uPnPResponseValue="upnp:rootdevice"  #   Searches for all UPnP root devices
+                    #uPnPResponseValue="uuid:device-uuid" #   Searches for a particular device
+                    #uPnPResponseValue="urn:schemas-upnp-org:device:deviceType:ver"
+                                                      #   Searches for devices of the given type
+                    #uPnPResponseValue="urn:domain-name:device:deviceType:ver"
+                                                      #   Searches for devices with a vendor-specific type
+                    #uPnPResponseValue="urn:schemas-upnp-org:service:serviceType:ver"
+                                                      #   Searches for devices containing a service of the given type
+                    #uPnPResponseValue="urn:domain-name:service:serviceType:ver"
+                                                      #   Searches for devices containing a vendor-specific service
+                }
+			}
+		}
+	}
+}
+
+### GAS Comback request and response Frame ###
+
+wifidirect_gas_comeback_request={
+	PeerAddr=00:50:43:00:00:00
+	Category=4
+	Action=12
+	DialogToken=1
+}
+
+wifidirect_gas_comeback_response={
+	PeerAddr=00:50:43:00:00:00
+	Category=4
+	Action=13
+	DialogToken=1
+	StatusCode=0
+    GasResponseFragID=0x01
+        # Bit 7: More GAS fragments bit
+        # Bits 0-6: GAS query response fragment ID.
+        #           0 for initial frame and increments subsequently.
+	GasComebackDelay=0x0000
+	AdvertizementProtocolIE=0x6c,0x02,0x7F,0x00
+                # octet 1: Element Id = 108 ( 0x6c)
+                # octer 2: Length of following fields
+                # octer 3: Bit7: PAME-BI ( Message Exchange BSSID independant)
+                #          Bits0-6: Query response length limit.
+                # octer 4: Advertizement Protocol ID
+	QueryResponseLen={
+		InfoId=0xDD,0xDD
+		ResponseLen={
+			OUI=0x00,0x50,0xF2
+			OUISubType=9
+            ServiceUpdateIndicator=0
+			VendorLen={
+				ServiceProtocol=1 # 0: All service protocol types
+                                  # 1: Bonjour, 2: uPnP, 3: WS-Discovery
+                                  # 255: Vendor specific
+				ServiceTransactionId=1
+				ServiceStatus=0   # 0: Success
+                                  # 1: Service protocol type not available
+                                  # 2: Query data not available
+                                  # 3: Bad request.
+                ResponseData={
+                    ## Use Data below, if ServiceProtocol=1 (Bonjour).
+                    #
+                    ## DNSName can be string or hexadecimal sequence of bytes.
+
+                    # DNSName="_afpovertcp._tcp.local."
+                    DNSName=0x07,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x0B,0x5F,0x61,0x66,0x70,0x6F,0x76,0x65,0x72,0x74,0x63,0x70,0xC0,0x0C
+                    DNSType=12
+                    BonjourVersion=1
+                    ## RecordData can be string or hexadecimal sequence of bytes.
+                    # RecordData=""
+                    RecordData=0x00
+
+                    ## Use Data below, if ServiceProtocol=2 (uPnP).
+                    #
+                    #uPnPVersion=0x10
+                    #uPnPResponseValue="ssdp:all"         #   Searches for all UPnP devices and services
+                    #
+                    # OR any one of following values in WIFIDIRECT spec.
+                    #uPnPResponseValue="upnp:rootdevice"  #   Searches for all UPnP root devices
+                    #uPnPResponseValue="uuid:device-uuid" #   Searches for a particular device
+                    #uPnPResponseValue="urn:schemas-upnp-org:device:deviceType:ver"
+                                                      #   Searches for devices of the given type
+                    #uPnPResponseValue="urn:domain-name:device:deviceType:ver"
+                                                      #   Searches for devices with a vendor-specific type
+                    #uPnPResponseValue="urn:schemas-upnp-org:service:serviceType:ver"
+                                                      #   Searches for devices containing a service of the given type
+                    #uPnPResponseValue="urn:domain-name:service:serviceType:ver"
+                                                      #   Searches for devices containing a vendor-specific service
+                }
+			}
+		}
+	}
+}
diff --git a/wlan_sd8897/mapp/wifidirectutl/config/wifidisplay.conf b/wlan_sd8897/mapp/wifidirectutl/config/wifidisplay.conf
new file mode 100644
index 0000000..2927aac
--- /dev/null
+++ b/wlan_sd8897/mapp/wifidirectutl/config/wifidisplay.conf
@@ -0,0 +1,93 @@
+#	File : wifidisplay.conf
+
+######################### WiFiDisplay Configuration command ##################
+
+wifidisplay_config={
+	# Arrange in order of subelement Ids
+
+        display_dev_info={
+           device_info=19
+           mgmt_control_port=554
+           device_throuput=54
+        }
+        display_assoc_bssid={
+        }
+        display_coupled_sink={
+           coupled_sink_bitmap=0
+        }
+        display_session_info={
+        }
+        #display_alternate_mac={
+        #   alternate_mac=00:50:43:00:00:00
+        #}
+}
+
+######################### WIFIDIRECT service discovery command ##################
+
+wifidisplay_discovery_request={
+        PeerAddr=00:50:43:00:00:00
+        Category=4
+        Action=10
+        DialogToken=1
+        AdvertizementProtocolIE=0x6c,0x02,0x00,0x00
+                # octet 1: Element Id = 108 ( 0x6c)
+                # octer 2: Length of following fields
+                # octer 3: Bit7: PAME-BI ( Message Exchange BSSID independant)
+                #          Bits0-6: Query response length limit.
+                # octer 4: Advertizement Protocol ID
+        QueryRequestLen={
+            InfoId=0xDD,0xDD
+        RequestLen={
+                    OUI=0x50,0x6F,0x9A
+                    OUISubType=10
+                    ServiceUpdateIndicator=0
+                    VendorLen={
+                       ServiceProtocol=4 # 0: All service protocol types
+                       # 1: Bonjour, 2: uPnP, 3: WS-Discovery
+                       # 4: Wifi Display
+                       # 255: Vendor specific
+                       ServiceTransactionId=1
+                       QueryData={
+                       }
+                   }
+            }
+     }
+}
+
+wifidisplay_discovery_response={
+        PeerAddr=00:50:43:00:00:00
+        Category=4
+        Action=11
+        DialogToken=1
+        StatusCode=0
+        GasComebackDelay=0x0000
+        AdvertizementProtocolIE=0x6c,0x02,0x7F,0x00
+                # octet 1: Element Id = 108 ( 0x6c)
+                # octer 2: Length of following fields
+                # octer 3: Bit7: PAME-BI ( Message Exchange BSSID independant)
+                #          Bits0-6: Query response length limit.
+                # octer 4: Advertizement Protocol ID
+        QueryResponseLen={
+                InfoId=0xDD,0xDD
+                ResponseLen={
+                        OUI=0x50,0x6F,0x9A
+                        OUISubType=10
+                        ServiceUpdateIndicator=0
+                        VendorLen={
+                             ServiceProtocol=4 # 0: All service protocol types
+                             # 1: Bonjour, 2: uPnP, 3: WS-Discovery
+                             # 4: Wifi Display
+                             # 255: Vendor specific
+                             ServiceTransactionId=1
+                             ServiceStatus=0   # 0: Success
+                             # 1: Service protocol type not available
+                             # 2: Query data not available
+                             # 3: Bad request.
+                             ResponseData={
+                             }
+                       }
+                }
+        }
+}
+
+
diff --git a/wlan_sd8897/mapp/wifidirectutl/wifi_display.c b/wlan_sd8897/mapp/wifidirectutl/wifi_display.c
new file mode 100644
index 0000000..adf5709
--- /dev/null
+++ b/wlan_sd8897/mapp/wifidirectutl/wifi_display.c
@@ -0,0 +1,1332 @@
+/** @file  wifi_display.c
+ *
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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:
+  22/09/11: Initial creation
+ ****************************************************************************/
+
+/****************************************************************************
+  Header files
+ ****************************************************************************/
+
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <linux/wireless.h>
+
+#include "wifi_display.h"
+#include "wifidirectutl.h"
+
+/*
+ *  @brief Show usage information for the wifidisplay_config command
+ *
+ *  $return         N/A
+*/
+static void
+print_wifidisplay_config_usage(void)
+{
+	printf("\nUsage : wifidisplay_config [CONFIG_FILE]\n");
+	printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n");
+	printf("CONFIG_FILE contains all WiFiDisplay parameters.\n");
+	return;
+}
+
+/*
+ss and send ie config command
+ *  @param ie_index              A pointer to the IE buffer index
+ *  @param data_len_wifidisplay  Length of Wifidisplay data
+ *  @param buf                   Pointer to buffer to set.
+ *  @return                      SUCCESS--success, FAILURE--fail
+ */
+static int
+wifiDisplay_ie_config(t_s16 *ie_index, t_u16 data_len_wifidisplay, t_u8 *buf)
+{
+	struct iwreq iwr;
+	t_s32 sockfd;
+	int i, ret = SUCCESS;
+	tlvbuf_custom_ie *tlv = NULL;
+	custom_ie *ie_ptr = NULL;
+
+	tlv = (tlvbuf_custom_ie *)buf;
+	tlv->tag = MRVL_MGMT_IE_LIST_TLV_ID;
+	/* Locate headers */
+	ie_ptr = (custom_ie *)(tlv->ie_data);
+
+	/* Set TLV fields : WFD IE parameters */
+	if (data_len_wifidisplay) {
+		/* Set IE */
+#define DISPLAY_MASK 0xFFFF
+		ie_ptr->mgmt_subtype_mask = DISPLAY_MASK;
+		tlv->length = sizeof(custom_ie) + data_len_wifidisplay;
+		ie_ptr->ie_length = data_len_wifidisplay;
+		ie_ptr->ie_index = *ie_index;
+	} else {
+		/* Get WPS IE */
+		tlv->length = 0;
+	}
+
+	/* Locate headers */
+	ie_ptr = (custom_ie *)((t_u8 *)(tlv->ie_data) + sizeof(custom_ie) +
+			       data_len_wifidisplay);
+
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, (char *)dev_name, IFNAMSIZ);
+
+	iwr.u.data.pointer = (void *)buf;
+	iwr.u.data.length =
+		((2 * sizeof(custom_ie)) + sizeof(tlvbuf_custom_ie) +
+		 data_len_wifidisplay);
+	iwr.u.data.flags = 0;
+
+	/*
+	 *      * create a socket
+	 *           */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("Cannot open socket.\n");
+		ret = FAILURE;
+		goto _exit_;
+	}
+
+	if (ioctl(sockfd, CUSTOM_IE, &iwr)) {
+		perror("ioctl[CUSTOM_IE]");
+		printf("Failed to set/get/clear the IE buffer\n");
+		ret = FAILURE;
+		close(sockfd);
+		goto _exit_;
+	}
+	close(sockfd);
+
+	if (!data_len_wifidisplay) {
+		/* Get the IE buffer index number for MGMT_IE_LIST_TLV */
+		tlv = (tlvbuf_custom_ie *)buf;
+		*ie_index = -1;
+		if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) {
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			for (i = 0; i < MAX_MGMT_IE_INDEX; i++) {
+				// Index 0 and 1 are reserved for WFD in current implementation
+				if ((ie_ptr->mgmt_subtype_mask == DISPLAY_MASK)
+				    && (ie_ptr->ie_length) && (i != 0) &&
+				    (i != 1)) {
+					*ie_index = ie_ptr->ie_index;
+					break;
+				}
+				if (i < (MAX_MGMT_IE_INDEX - 1))
+					ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+							       sizeof(custom_ie)
+							       +
+							       ie_ptr->
+							       ie_length);
+			}
+		}
+		if (*ie_index == -1) {
+			printf("\nNo free IE buffer available\n");
+			ret = FAILURE;
+		}
+	}
+_exit_:
+
+	return ret;
+}
+
+/**
+ *  @brief Creates a wifidisplay_config request and sends to the driver
+ *
+ *  Usage: "Usage : wfd_config [CONFIG_FILE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+void
+wifidisplaycmd_config(int argc, char *argv[])
+{
+	t_u8 *buf = NULL;
+	t_u16 ie_len_wifidisplay = 0, ie_len;
+	t_s16 ie_index = -1;
+	int opt, ret = SUCCESS;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidisplay_config_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR:wrong number of arguments.\n");
+		print_wifidisplay_config_usage();
+		return;
+	}
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buf) {
+		printf("ERR:Cannot allocate memory!\n");
+		return;
+	}
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (argc >= 3) {
+		/* Read parameters and send command to firmware */
+		wifidisplay_file_params_config(argv[2], argv[1], buf
+					       + sizeof(tlvbuf_custom_ie) +
+					       sizeof(custom_ie),
+					       &ie_len_wifidisplay);
+		if (argc == 4) {
+			ie_index = atoi(argv[3]);
+			if (ie_index >= 4) {
+				printf("ERR:wrong argument %s.\n", argv[3]);
+				return;
+			}
+		}
+		if (ie_len_wifidisplay > MAX_SIZE_IE_BUFFER) {
+			printf("ERR:IE parameter size exceeds limit in %s.\n",
+			       argv[2]);
+			free(buf);
+			return;
+		}
+		ie_len = ie_len_wifidisplay + sizeof(tlvbuf_custom_ie) +
+			sizeof(custom_ie);
+		if (ie_len >= MRVDRV_SIZE_OF_CMD_BUFFER) {
+			printf("ERR:Too much data in configuration file %s.\n",
+			       argv[2]);
+			free(buf);
+			return;
+		}
+#ifdef DEBUG
+		hexdump(buf, ie_len, ' ');
+#endif
+		ret = wifiDisplay_ie_config(&ie_index, ie_len_wifidisplay, buf);
+		if (ret != SUCCESS) {
+			printf("ERR:Could not set wfd parameters\n");
+		}
+	}
+}
+
+/* *  @brief Read the wifidisplay parameters and sends to the driver
+ *
+ *  @param file_name File to open for configuration parameters.
+ *  @param cmd_name  Command Name for which parameters are read.
+ *  @param pbuf      Pointer to output buffer
+ *  @param ie_len_wfd Length of wifidisplay parameters to return
+ *  @return          SUCCESS or FAILURE
+ */
+#define DEVICE_DESCRIPTOR_LEN 24
+static const t_u8 wifidisplay_oui[] = { 0x50, 0x6F, 0x9A, 0x0A };
+
+void
+wifidisplay_file_params_config(char *file_name, char *cmd_name,
+			       t_u8 *pbuf, t_u16 *ie_len_wifidisplay)
+{
+	FILE *config_file = NULL;
+	char *line = NULL;
+	t_u8 *extra = NULL, *len_ptr = NULL;
+	t_u8 *buffer = pbuf;
+	char **args = NULL;
+	t_u16 cmd_len_wifidisplay = 0, tlv_len = 0;
+	tlvbuf_wifidisplay_ie_format *display_ie_buf = NULL;
+	int wifiDisplay_level = 0, ret = 0, coupled_sink_bitmap = 0;
+	t_u16 display_device_info, session_mgmt_control_port,
+		wfd_device_throuput;
+	t_u8 assoc_bssid[] = { 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE };
+	t_u8 alternate_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	t_u8 peer_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	t_u8 default_mac[] = { 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE };
+	char wfd_mac[20];
+	int li = 0, arg_num = 0;
+	char *pos = NULL;
+	t_u8 cmd_found = 0;
+	t_u16 temp;
+	t_u16 wfd_session_len;
+	t_u8 total_num_device_info __attribute__ ((__unused__));	/* For future use */
+	t_u8 curr_dev_info = 0;
+	t_u8 dev_info_dev_add[ETH_ALEN], dev_info_assoc_bssid[ETH_ALEN],
+		dev_info_coupled_add[ETH_ALEN];
+	t_u16 descriptor_display_device_info, descriptor_wfd_device_throuput;
+	t_u8 descriptor_wfd_coupled_sink_status;
+	t_u8 wfd_dev_descriptor_arr[120], device_info_desc_len, ind =
+		DEVICE_DESCRIPTOR_LEN;
+	/* Check if file exists */
+	config_file = fopen(file_name, "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return;
+	}
+
+	/* Memory allocations */
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	extra = (t_u8 *)malloc(MAX_CONFIG_LINE);
+	if (!extra) {
+		printf("ERR:Cannot allocate memory for extra\n");
+		goto done;
+	}
+	memset(extra, 0, MAX_CONFIG_LINE);
+
+	args = (char **)malloc(sizeof(char *) * MAX_ARGS_NUM);
+	if (!args) {
+		printf("ERR:Cannot allocate memory for args\n");
+		goto done;
+	}
+	memset(args, 0, (sizeof(char *) * MAX_ARGS_NUM));
+	display_ie_buf = (tlvbuf_wifidisplay_ie_format *)buffer;
+	display_ie_buf->ElemId = VENDOR_SPECIFIC_IE_TAG;
+	len_ptr = buffer + 1;
+	memcpy(&display_ie_buf->Oui[0], wifidisplay_oui,
+	       sizeof(wifidisplay_oui));
+	cmd_len_wifidisplay += 2 + sizeof(wifidisplay_oui);
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		arg_num = parse_line(line, args);
+		if (!cmd_found && (cmd_name != NULL)
+		    && strncmp(args[0], cmd_name, strlen(args[0])))
+			cmd_found = 1;
+		if (strcmp(args[0], "display_dev_info") == 0) {
+			wifiDisplay_level = DISPLAY_DEVICE_INFO;
+		} else if (strcmp(args[0], "display_assoc_bssid") == 0) {
+			wifiDisplay_level = DISPLAY_ASSOCIATED_BSSID;
+		} else if (strcmp(args[0], "display_coupled_sink") == 0) {
+			wifiDisplay_level = DISPLAY_COUPLED_SINK;
+		} else if (strcmp(args[0], "display_session_info") == 0) {
+			wifiDisplay_level = DISPLAY_SESSION_INFO;
+		} else if (strcmp(args[0], "display_alternate_mac") == 0) {
+			wifiDisplay_level = DISPLAY_ALTERNATE_MAC_ADDR;
+		} else if (strcmp(args[0], "device_info") == 0) {
+			if (is_wifidisplay_input_valid
+			    (WFD_DEVICE_INFO, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			display_device_info = (t_u16)atoi(args[1]);
+		} else if (strcmp(args[0], "mgmt_control_port") == 0) {
+			if (is_wifidisplay_input_valid
+			    (WFD_SESSION_MGMT_CONTROL_PORT, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			session_mgmt_control_port = (t_u16)atoi(args[1]);
+		} else if (strcmp(args[0], "device_throuput") == 0) {
+			if (is_wifidisplay_input_valid
+			    (WFD_DEVICE_THROUGHPUT, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			wfd_device_throuput = (t_u16)atoi(args[1]);
+		} else if (strcmp(args[0], "assoc_bssid") == 0) {
+			strncpy(wfd_mac, args[1], 20);
+			if ((ret = mac2raw(wfd_mac, assoc_bssid)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+		} else if (strcmp(args[0], "alternate_mac") == 0) {
+			strncpy(wfd_mac, args[1], 20);
+			if ((ret = mac2raw(wfd_mac, alternate_mac)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+		} else if (strcmp(args[0], "coupled_sink_bitmap") == 0) {
+			if (is_wifidisplay_input_valid
+			    (WFD_COUPLED_SINK, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			coupled_sink_bitmap = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "session_info_len") == 0) {
+			wfd_session_len = (t_u16)atoi(args[1]);
+			total_num_device_info =
+				(wfd_session_len / DEVICE_DESCRIPTOR_LEN);
+		} else if (strncmp(args[0], "device_info_descriptor_len", 26) ==
+			   0) {
+			device_info_desc_len = (t_u16)atoi(args[1]);
+		} else if (strncmp(args[0], "device_info_dev_id", 18) == 0) {
+			strncpy(wfd_mac, args[1], 20);
+			if ((ret =
+			     mac2raw(wfd_mac, dev_info_dev_add)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+		} else if (strncmp(args[0], "device_info_assoc_bssid", 18) == 0) {
+			strncpy(wfd_mac, args[1], 20);
+			if ((ret =
+			     mac2raw(wfd_mac,
+				     dev_info_assoc_bssid)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+		} else if (strncmp(args[0], "descriptor_device_info", 22) == 0) {
+			descriptor_display_device_info = (t_u16)atoi(args[1]);
+			temp = htons(descriptor_display_device_info);
+			memcpy(&descriptor_display_device_info, &temp, 2);
+		} else if (strncmp(args[0], "descriptor_device_throuput", 24) ==
+			   0) {
+			descriptor_wfd_device_throuput = (t_u16)atoi(args[1]);
+			temp = htons(descriptor_wfd_device_throuput);
+			memcpy(&descriptor_display_device_info, &temp, 2);
+		} else if (strncmp(args[0], "descriptor_cs_bitmap", 20) == 0) {
+			descriptor_wfd_coupled_sink_status =
+				(t_u8)atoi(args[1]);
+		} else if (strncmp(args[0], "device_info_coupled_address", 27)
+			   == 0) {
+			strncpy(wfd_mac, args[1], 20);
+			if ((ret =
+			     mac2raw(wfd_mac,
+				     dev_info_coupled_add)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+			if (curr_dev_info > 5) {
+				printf("ERR in device descriptor");
+				goto done;
+			}
+			memcpy(&wfd_dev_descriptor_arr[ind * curr_dev_info],
+			       &device_info_desc_len, sizeof(t_u8));
+			memcpy(&wfd_dev_descriptor_arr[ind * curr_dev_info + 1],
+			       &dev_info_dev_add, ETH_ALEN);
+			memcpy(&wfd_dev_descriptor_arr[ind * curr_dev_info + 7],
+			       &dev_info_assoc_bssid, ETH_ALEN);
+			memcpy(&wfd_dev_descriptor_arr
+			       [ind * curr_dev_info + 13],
+			       &descriptor_display_device_info, sizeof(t_u16));
+			memcpy(&wfd_dev_descriptor_arr
+			       [ind * curr_dev_info + 15],
+			       &descriptor_wfd_device_throuput, sizeof(t_u16));
+			memcpy(&wfd_dev_descriptor_arr
+			       [ind * curr_dev_info + 17],
+			       &descriptor_wfd_coupled_sink_status,
+			       sizeof(t_u8));
+			memcpy(&wfd_dev_descriptor_arr
+			       [ind * curr_dev_info + 18],
+			       &dev_info_coupled_add, ETH_ALEN);
+			curr_dev_info++;
+		} else if (strcmp(args[0], "}") == 0) {
+			switch (wifiDisplay_level) {
+			case DISPLAY_DEVICE_INFO:
+				{
+					tlvbuf_wfdisplay_device_info *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wfdisplay_device_info);
+					tlv = (tlvbuf_wfdisplay_device_info
+					       *)(buffer + cmd_len_wifidisplay);
+					cmd_len_wifidisplay += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDISPLAY_DEVICE_INFO;
+					tlv->length =
+						htons(tlv_len -
+						      (sizeof(t_u8) +
+						       sizeof(t_u16)));
+					*ie_len_wifidisplay =
+						cmd_len_wifidisplay;
+					temp = htons(display_device_info);
+					memcpy(&tlv->display_device_info, &temp,
+					       2);
+					temp = htons(session_mgmt_control_port);
+					memcpy(&tlv->session_mgmt_control_port,
+					       &temp, 2);
+					temp = htons(wfd_device_throuput);
+					memcpy(&tlv->wfd_device_throuput, &temp,
+					       2);
+					wifiDisplay_level = 0;
+					break;
+				}
+			case DISPLAY_ASSOCIATED_BSSID:
+				{
+					tlvbuf_wfdisplay_assoc_bssid *tlv =
+						NULL;
+					if (memcmp
+					    (default_mac, assoc_bssid,
+					     ETH_ALEN)) {
+						/* Append a new TLV */
+						tlv_len =
+							sizeof
+							(tlvbuf_wfdisplay_assoc_bssid);
+						tlv = (tlvbuf_wfdisplay_assoc_bssid *)(buffer + cmd_len_wifidisplay);
+						cmd_len_wifidisplay += tlv_len;
+						*ie_len_wifidisplay =
+							cmd_len_wifidisplay;
+						/* Set TLV fields */
+						tlv->tag =
+							TLV_TYPE_WIFIDISPLAY_ASSOC_BSSID;
+						tlv->length =
+							htons(tlv_len -
+							      (sizeof(t_u8) +
+							       sizeof(t_u16)));
+						memcpy(tlv->assoc_bssid,
+						       assoc_bssid, ETH_ALEN);
+
+						wifiDisplay_level = 0;
+					}
+					break;
+				}
+			case DISPLAY_COUPLED_SINK:
+				{
+					tlvbuf_wfdisplay_coupled_sink *tlv =
+						NULL;
+					tlv_len =
+						sizeof
+						(tlvbuf_wfdisplay_coupled_sink);
+					tlv = (tlvbuf_wfdisplay_coupled_sink
+					       *)(buffer + cmd_len_wifidisplay);
+					cmd_len_wifidisplay += tlv_len;
+					*ie_len_wifidisplay =
+						cmd_len_wifidisplay;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDISPLAY_COUPLED_SINK;
+					tlv->length =
+						htons(tlv_len -
+						      (sizeof(t_u8) +
+						       sizeof(t_u16)));
+					memcpy(tlv->peer_mac, peer_mac,
+					       ETH_ALEN);
+					tlv->coupled_sink = coupled_sink_bitmap;
+					wifiDisplay_level = 0;
+				}
+				break;
+			case DISPLAY_SESSION_INFO:
+				{
+					tlvbuf_wifi_display_session_info *tlv =
+						NULL;
+					if (curr_dev_info > 0) {
+						tlv_len =
+							DEVICE_DESCRIPTOR_LEN *
+							curr_dev_info + 2;
+						tlv = (tlvbuf_wifi_display_session_info *)(buffer + cmd_len_wifidisplay);
+						cmd_len_wifidisplay += tlv_len;
+						*ie_len_wifidisplay =
+							cmd_len_wifidisplay;
+						/* Set TLV fields */
+						tlv->tag =
+							TLV_TYPE_SESSION_INFO_SUBELEM;
+						tlv->length =
+							htons(tlv_len -
+							      (sizeof(t_u8) +
+							       sizeof(t_u16)));
+						memcpy((t_u8 *)&tlv->
+						       WFDDevInfoDesc,
+						       (t_u8 *)
+						       &wfd_dev_descriptor_arr,
+						       (tlv_len - 2));
+						wifiDisplay_level = 0;
+					}
+				}
+				break;
+			case DISPLAY_ALTERNATE_MAC_ADDR:
+				{
+					tlvbuf_wfdisplay_alternate_mac *tlv =
+						NULL;
+					if (memcmp
+					    (default_mac, alternate_mac,
+					     ETH_ALEN)) {
+						/* Append a new TLV */
+						tlv_len =
+							sizeof
+							(tlvbuf_wfdisplay_alternate_mac);
+						tlv = (tlvbuf_wfdisplay_alternate_mac *)(buffer + cmd_len_wifidisplay);
+						cmd_len_wifidisplay += tlv_len;
+						*ie_len_wifidisplay =
+							cmd_len_wifidisplay;
+						/* Set TLV fields */
+						tlv->tag =
+							TLV_TYPE_WIFIDISPLAY_ALTERNATE_MAC;
+						tlv->length =
+							htons(tlv_len -
+							      (sizeof(t_u8) +
+							       sizeof(t_u16)));
+						memcpy(tlv->alternate_mac,
+						       alternate_mac, ETH_ALEN);
+						wifiDisplay_level = 0;
+					}
+				}
+				break;
+			default:
+				break;
+			}
+		}
+	}
+	*len_ptr = cmd_len_wifidisplay - 2;
+done:
+	fclose(config_file);
+	if (line)
+		free(line);
+	if (extra)
+		free(extra);
+	if (args)
+		free(args);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidisplay_discovery commands
+ *
+ *  $return         N/A
+ */
+static void
+print_wifidisplay_discovery_usage(void)
+{
+	printf("\nUsage : wifidisplay_discovery_request/response [CONFIG_FILE]\n");
+	printf("CONFIG_FILE contains WIFIDISPLAY service discovery payload.\n");
+	return;
+}
+
+/*  @brief Creates a wifidirect_service_discovery request/response and
+ *         sends to the driver
+ *
+ *  Usage: "Usage : wifidirect_discovery_request/response [CONFIG_FILE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         SUCCESS or FAILURE
+ **/
+void
+wifidisplaycmd_service_discovery(int argc, char *argv[])
+{
+	wifidisplay_discovery_request *req_buf = NULL;
+	wifidisplay_discovery_response *resp_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int i, opt, li = 0, arg_num = 0, ret = 0, wifidirect_level = 0;
+	char *args[30], *pos = NULL, wifidisplay_mac[20], wifidisplay_cmd[32];
+	t_u8 dev_address[ETH_ALEN], cmd_found = 0;
+	t_u8 *buffer = NULL, *buf = NULL, *tmp_buffer = NULL;
+	t_u8 req_resp = 0;	/* req = 0, resp = 1 */
+	t_u16 cmd_len = 0, query_len = 0, vendor_len = 0, service_len = 0;
+	t_u16 ie_len_wifidisplay = 0;
+
+	strncpy(wifidisplay_cmd, argv[2], sizeof(wifidisplay_cmd) - 1);
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidisplay_discovery_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 3) {
+		printf("ERR:Incorrect number of arguments.\n");
+		print_wifidisplay_discovery_usage();
+		return;
+	}
+
+	/* Check if file exists */
+	config_file = fopen(argv[2], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buf) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	if (strcmp(args[0], "wifidisplay_discovery_response") == 0) {
+		t_u8 wfd_oui_header = 6;
+		wifidisplay_file_params_config(argv[2], NULL, buf,
+					       &ie_len_wifidisplay);
+		ie_len_wifidisplay += wfd_oui_header;
+		buf += wfd_oui_header;
+	} else {
+		buf[0] = 0x03;
+		buf[1] = TLV_TYPE_WIFIDISPLAY_DEVICE_INFO;
+		buf[2] = TLV_TYPE_SESSION_INFO_SUBELEM;
+		buf[3] = TLV_TYPE_WIFIDISPLAY_COUPLED_SINK;
+		ie_len_wifidisplay = 4;
+	}
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		arg_num = parse_line(line, args);
+		if (!cmd_found &&
+		    strncmp(args[0], wifidisplay_cmd, strlen(args[0])))
+			continue;
+		cmd_found = 1;
+		if (strcmp(args[0], "wifidisplay_discovery_request") == 0) {
+			wifidirect_level =
+				WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE;
+			/* For wifidirect_service_discovery, basic initialization here */
+			cmd_len = sizeof(wifidisplay_discovery_request);
+			buffer = (t_u8 *)malloc(cmd_len);
+			if (!buffer) {
+				printf("ERR:Cannot allocate memory!\n");
+				goto done;
+			}
+			req_buf = (wifidisplay_discovery_request *)buffer;
+			req_buf->cmd_code =
+				HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY;
+			req_buf->size = cmd_len;
+			req_buf->seq_num = 0;
+			req_buf->result = 0;
+		} else if (strcmp(args[0], "wifidisplay_discovery_response") ==
+			   0) {
+			wifidirect_level =
+				WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE;
+			req_resp = 1;
+			/* For wifidirect_service_discovery, basic initialization here */
+			cmd_len = sizeof(wifidisplay_discovery_response);
+			buffer = (t_u8 *)malloc(cmd_len);
+			if (!buffer) {
+				printf("ERR:Cannot allocate memory!\n");
+				goto done;
+			}
+			resp_buf = (wifidisplay_discovery_response *)buffer;
+			resp_buf->cmd_code =
+				HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY;
+			resp_buf->size = cmd_len;
+			resp_buf->seq_num = 0;
+			resp_buf->result = 0;
+
+		} else if (strcmp(args[0], "PeerAddr") == 0) {
+			strncpy(wifidisplay_mac, args[1], 20 - 1);
+			if ((ret =
+			     mac2raw(wifidisplay_mac,
+				     dev_address)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+			(!req_resp) ? memcpy(req_buf->peer_mac_addr,
+					     dev_address,
+					     ETH_ALEN) : memcpy(resp_buf->
+								peer_mac_addr,
+								dev_address,
+								ETH_ALEN);
+
+		} else if (strcmp(args[0], "Category") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_CATEGORY, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+
+			}
+			(!req_resp) ? (req_buf->category =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       category =
+							       (t_u8)
+							       atoi(args[1]));
+		} else if (strcmp(args[0], "Action") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_ACTION, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->action =
+				       (t_u8)A2HEXDECIMAL(args[1]))
+				: (resp_buf->action =
+				   (t_u8)A2HEXDECIMAL(args[1]));
+		} else if (strcmp(args[0], "DialogToken") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DIALOGTOKEN, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->dialog_taken =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       dialog_taken =
+							       (t_u8)
+							       atoi(args[1]));
+		} else if (strcmp(args[0], "StatusCode") == 0) {
+			resp_buf->status_code = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "GasComebackDelay") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_GAS_COMEBACK_DELAY, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->gas_reply = (t_u16)A2HEXDECIMAL(args[1]);
+			resp_buf->gas_reply = cpu_to_le16(resp_buf->gas_reply);
+		} else if (strcmp(args[0], "AdvertizementProtocolIE") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_ADPROTOIE, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			if (!req_resp) {
+				for (i = 0; i < arg_num - 1; i++)
+					req_buf->advertize_protocol_ie[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			} else {
+				for (i = 0; i < arg_num - 1; i++)
+					resp_buf->advertize_protocol_ie[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+		} else if (strcmp(args[0], "InfoId") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_INFOID, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			if (!req_resp) {
+				for (i = 0; i < arg_num - 1; i++)
+					req_buf->info_id[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			} else {
+				for (i = 0; i < arg_num - 1; i++)
+					resp_buf->info_id[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			query_len += arg_num - 1;
+		} else if (strcmp(args[0], "OUI") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_OUI, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			if (!req_resp) {
+				for (i = 0; i < arg_num - 1; i++)
+					req_buf->oui[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			} else {
+				for (i = 0; i < arg_num - 1; i++)
+					resp_buf->oui[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			service_len += arg_num - 1;
+			query_len += arg_num - 1;
+		} else if (strcmp(args[0], "OUISubType") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_OUISUBTYPE, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->oui_sub_type =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       oui_sub_type =
+							       (t_u8)
+							       atoi(args[1]));
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "QueryRequestLen") == 0 ||
+			   strcmp(args[0], "QueryResponseLen") == 0) {
+			wifidirect_level = WIFIDIRECT_DISCOVERY_QUERY;
+		} else if (strcmp(args[0], "RequestLen") == 0 ||
+			   strcmp(args[0], "ResponseLen") == 0) {
+			wifidirect_level = WIFIDIRECT_DISCOVERY_SERVICE;
+			query_len += 2;
+		} else if (strcmp(args[0], "VendorLen") == 0) {
+			wifidirect_level = WIFIDIRECT_DISCOVERY_VENDOR;
+			service_len += 2;
+			query_len += 2;
+		} else if (strcmp(args[0], "QueryData") == 0 ||
+			   strcmp(args[0], "ResponseData") == 0) {
+			wifidirect_level =
+				WIFIDIRECT_DISCOVERY_QUERY_RESPONSE_PER_PROTOCOL;
+			tmp_buffer =
+				realloc(buffer, cmd_len + ie_len_wifidisplay);
+			if (!tmp_buffer) {
+				printf("ERR:Cannot add DNS name to buffer!\n");
+				goto done;
+			} else {
+				buffer = tmp_buffer;
+				tmp_buffer = NULL;
+			}
+			if (!req_resp) {
+				for (i = 0; i < ie_len_wifidisplay; i++)
+					req_buf->disc_query[i] = (t_u8)buf[i];
+			} else {
+				resp_buf =
+					(wifidisplay_discovery_response *)
+					buffer;
+				for (i = 0; i < ie_len_wifidisplay; i++)
+					buffer[i + cmd_len] = (t_u8)buf[i];
+			}
+			cmd_len += (ie_len_wifidisplay);
+			vendor_len += (ie_len_wifidisplay);
+			service_len += (ie_len_wifidisplay);
+			query_len += (ie_len_wifidisplay);
+		} else if (strcmp(args[0], "ServiceProtocol") == 0) {
+			if (!req_resp) {
+				req_buf->service_protocol = (t_u8)atoi(args[1]);
+				/*
+				 * For uPnP, due to union allocation, a extra byte
+				 * is allocated reduce it here for uPnP
+				 */
+				if (req_buf->service_protocol == 2)
+					cmd_len--;
+			} else {
+				resp_buf->service_protocol =
+					(t_u8)atoi(args[1]);
+				if (resp_buf->service_protocol == 2)
+					cmd_len--;
+			}
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "ServiceUpdateIndicator") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_SERVICEUPDATE_INDICATOR, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->service_update_indicator =
+				       cpu_to_le16((t_u16)atoi(args[1]))) :
+				(resp_buf->service_update_indicator =
+				 cpu_to_le16((t_u16)atoi(args[1])));
+			service_len += 2;
+			query_len += 2;
+		} else if (strcmp(args[0], "ServiceTransactionId") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_SERVICETRANSACID, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->service_transaction_id =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       service_transaction_id
+							       =
+							       (t_u8)
+							       atoi(args[1]));
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "}") == 0) {
+			switch (wifidirect_level) {
+			case WIFIDIRECT_DISCOVERY_QUERY:
+				(!req_resp) ? (req_buf->query_len =
+					       cpu_to_le16(query_len))
+					: (resp_buf->query_len =
+					   cpu_to_le16(query_len));
+				break;
+			case WIFIDIRECT_DISCOVERY_SERVICE:
+				(!req_resp) ? (req_buf->request_len =
+					       cpu_to_le16(service_len))
+					: (resp_buf->response_len =
+					   cpu_to_le16(service_len));
+				break;
+			case WIFIDIRECT_DISCOVERY_VENDOR:
+				(!req_resp) ? (req_buf->vendor_len =
+					       cpu_to_le16(vendor_len))
+					: (resp_buf->vendor_len =
+					   cpu_to_le16(vendor_len));
+				break;
+			default:
+				break;
+			}
+			if (wifidirect_level) {
+				if (wifidirect_level ==
+				    WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE)
+					break;
+				wifidirect_level--;
+			}
+		}
+	}
+	/* Send collective command */
+	wifidirect_ioctl((t_u8 *)buffer, &cmd_len, cmd_len);
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+}
+
+/**
+ *  @brief Show usage information for the wfd display status command
+ *
+ *  $return         N/A
+ */
+static void
+print_wifi_display_status_usage(void)
+{
+	printf("\nUsage : wifi_display [STATUS]");
+	printf("\nOptions: STATUS :     0 - stop wfd display");
+	printf("\n                      1 - start wfd display");
+	printf("\n                  empty - get current wfd display status\n");
+	return;
+}
+
+/**
+ *  @brief Creates wfd display start or stop request and send to driver
+ *
+ *   Usage: "Usage : wifi_display [STATUS]"
+ *
+ *   Options: STATUS :     0 - start wfd status
+ *                         1 - stop  wfd status
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         N/A
+ */
+void
+wifidisplay_cmd_status(int argc, char *argv[])
+{
+	int opt, ret;
+	t_u16 data;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+	wifi_display_mode_config *cmd_buf = NULL;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifi_display_status_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR:wrong arguments.\n");
+		print_wifi_display_status_usage();
+		return;
+	}
+	if (argc == 3) {
+		if ((ISDIGIT(argv[2]) == 0) || (atoi(argv[2]) < 0) ||
+		    (atoi(argv[2]) > 3)) {
+			printf("ERR:Illegal wfd mode %s. Must be in range from '0' to '3'.\n", argv[2]);
+			print_wifi_display_status_usage();
+			return;
+		}
+		data = (t_u16)atoi(argv[2]);
+	}
+
+	/* send hostcmd now */
+	cmd_len = sizeof(wifi_display_mode_config);
+	buffer = (t_u8 *)malloc(cmd_len);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		return;
+	}
+
+	cmd_buf = (wifi_display_mode_config *)buffer;
+	cmd_buf->cmd_code = HostCmd_CMD_WFD_DISPLAY_MODE_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = ACTION_SET;
+		cmd_buf->mode = cpu_to_le16(data);
+	}
+	cmd_buf->action = cpu_to_le16(cmd_buf->action);
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len, cmd_len);
+	if (ret != SUCCESS) {
+		printf("Error executing wfd display_mode command\n");
+		free(buffer);
+		return;
+	}
+
+	data = le16_to_cpu(cmd_buf->mode);
+	switch (data) {
+	case 0:
+		printf("wfd display status = stopped\n");
+		break;
+	case 1:
+		printf("wfd display status = started\n");
+		break;
+	default:
+		printf("wfd display status = %d\n", data);
+		break;
+	}
+	free(buffer);
+	return;
+}
+
+/**
+ * @brief Checkes a particular input for validatation for wifidisplay.
+ *
+ * @param cmd      Type of input
+ * @param argc     Number of arguments
+ * @param argv     Pointer to the arguments
+ * @return         SUCCESS or FAILURE
+ */
+
+int
+is_wifidisplay_input_valid(display_valid_inputs cmd, int argc, char *argv[])
+{
+	if (argc == 0)
+		return FAILURE;
+	if (argc != 1) {
+		printf("ERR:Incorrect number of arguments\n");
+		return FAILURE;
+	}
+	switch (cmd) {
+	case WFD_DEVICE_INFO:
+		/*Bits 10-15 are reserved for device info */
+		if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0)
+		    || (atoi(argv[0]) > ((1 << 10) - 1))) {
+			printf("ERR:Coupled sink paramater must be > 0 and < %d", ((1 << 10) - 1));
+			return FAILURE;
+		}
+		/*bits 4 and 5 values 10 and 11 are reserved */
+		if ((atoi(argv[0]) & 48) > 16) {
+			printf("ERR:Coupled sink paramater must not have bit 4 and 5 equal to 10 or 11 ");
+			return FAILURE;
+		}
+		break;
+	case WFD_SESSION_MGMT_CONTROL_PORT:
+	case WFD_DEVICE_THROUGHPUT:
+		if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0)
+		    || (atoi(argv[0]) > ((1 << 16) - 1))) {
+			printf("ERR:Paramater must be > 0 and < %d",
+			       ((1 << 16) - 1));
+			return FAILURE;
+		}
+		break;
+	case WFD_COUPLED_SINK:
+		/*Maximum value of coupled sink is 2 */
+		if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0)
+		    || (atoi(argv[0]) > 2)) {
+			printf("ERR:Coupled sink paramater must be > 0 and < 3");
+			return FAILURE;
+		}
+		break;
+	}
+	return SUCCESS;
+}
+
+#define WFD_IE_HEADER_LEN 3
+/**
+ *  @brief Wifi display update custom ie command
+ *
+ *  $return         N/A
+*/
+void
+wifidisplay_update_custom_ie(int argc, char *argv[])
+{
+	t_s16 display_ie_index = -1;
+	t_u8 *buf;
+	int opt;
+	tlvbuf_custom_ie *tlv = NULL;
+	custom_ie *ie_ptr = NULL;
+	t_u16 len = 0, ie_len_wfd_org, ie_len_wfd, i = 0, new_wfd_dev_info = 0;
+	t_u8 *wfd_ptr;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			printf("ERR:Incorrect arguments.\n");
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR:wrong arguments.\n");
+		return;
+	}
+	if (argc == 3) {
+		if (ISDIGIT(argv[2]) == 0) {
+			printf("ERR:Illegal wfd mode %s. Must not be '0'.\n",
+			       argv[2]);
+			return;
+		}
+		new_wfd_dev_info = (t_u16)atoi(argv[2]);
+	}
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buf) {
+		printf("ERR:Cannot allocate memory!\n");
+		return;
+	}
+	wifiDisplay_ie_config(&display_ie_index, 0, buf);
+	/* Clear WPS IE */
+	if (display_ie_index < 0) {
+		free(buf);
+		return;
+	}
+	if (display_ie_index < (MAX_MGMT_IE_INDEX - 1)) {
+		tlv = (tlvbuf_custom_ie *)buf;
+
+		if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) {
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			/* Goto appropriate Ie Index */
+			for (i = 0; i < display_ie_index; i++) {
+				ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+						       sizeof(custom_ie) +
+						       ie_ptr->ie_length);
+			}
+			ie_len_wfd_org = ie_ptr->ie_length;
+			wfd_ptr = ie_ptr->ie_buffer;
+			ie_len_wfd = *(wfd_ptr + 1);
+			wfd_ptr += sizeof(t_u8) + sizeof(t_u8);
+			wfd_ptr += (WIFIDISPLAY_OUI_LEN + WIFIDISPLAY_OUI_TYPE);
+			while (ie_len_wfd > WFD_IE_HEADER_LEN) {
+				memcpy(&len, wfd_ptr + 1, sizeof(t_u16));
+				len = ntohs(len);
+				/* check capability type */
+				if (*wfd_ptr ==
+				    TLV_TYPE_WIFIDISPLAY_DEVICE_INFO) {
+					tlvbuf_wfdisplay_device_info *wfd_tlv =
+						(tlvbuf_wfdisplay_device_info *)
+						wfd_ptr;
+					new_wfd_dev_info =
+						ntohs(new_wfd_dev_info);
+					memcpy((t_u8 *)&wfd_tlv->
+					       display_device_info,
+					       (t_u8 *)&new_wfd_dev_info,
+					       sizeof(t_u16));
+					break;
+				}
+				wfd_ptr += len + WFD_IE_HEADER_LEN;
+				ie_len_wfd -= len + WFD_IE_HEADER_LEN;
+			}
+			/* Update New IE now */
+			wifiDisplay_ie_config((t_s16 *)&display_ie_index,
+					      ie_len_wfd_org,
+					      (t_u8 *)ie_ptr -
+					      sizeof(tlvbuf_custom_ie));
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief Wifi display update custom ie command
+ *
+ *  $return         N/A
+*/
+void
+wifidisplay_update_coupledsink_bitmap(int argc, char *argv[])
+{
+	t_s16 display_ie_index = -1;
+	t_u8 *buf;
+	int opt;
+	tlvbuf_custom_ie *tlv = NULL;
+	custom_ie *ie_ptr = NULL;
+	t_u16 len = 0, ie_len_wfd_org, ie_len_wfd, i = 0;
+	t_u8 new_wfd_coupled_sink_bitmap = 0;
+	t_u8 *wfd_ptr;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			printf("ERR:Incorrect arguments.\n");
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR:wrong arguments.\n");
+		return;
+	}
+	if (argc == 3) {
+		if (ISDIGIT(argv[2]) == 0) {
+			printf("ERR:Illegal wfd mode %s. Must not be '0'.\n",
+			       argv[2]);
+			return;
+		}
+		new_wfd_coupled_sink_bitmap = (t_u16)atoi(argv[2]);
+	}
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buf) {
+		printf("ERR:Cannot allocate memory!\n");
+		return;
+	}
+	wifiDisplay_ie_config(&display_ie_index, 0, buf);
+	/* Clear WPS IE */
+	if (display_ie_index < 0) {
+		free(buf);
+		return;
+	}
+	if (display_ie_index < (MAX_MGMT_IE_INDEX - 1)) {
+		tlv = (tlvbuf_custom_ie *)buf;
+
+		if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) {
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			/* Goto appropriate Ie Index */
+			for (i = 0; i < display_ie_index; i++) {
+				ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+						       sizeof(custom_ie) +
+						       ie_ptr->ie_length);
+			}
+			ie_len_wfd_org = ie_ptr->ie_length;
+			wfd_ptr = ie_ptr->ie_buffer;
+			ie_len_wfd = *(wfd_ptr + 1);
+			wfd_ptr += sizeof(t_u8) + sizeof(t_u8);
+			wfd_ptr += (WIFIDISPLAY_OUI_LEN + WIFIDISPLAY_OUI_TYPE);
+			while (ie_len_wfd > WFD_IE_HEADER_LEN) {
+				memcpy(&len, wfd_ptr + 1, sizeof(t_u16));
+				len = ntohs(len);
+				/* check capability type */
+				if (*wfd_ptr ==
+				    TLV_TYPE_WIFIDISPLAY_COUPLED_SINK) {
+					tlvbuf_wfdisplay_coupled_sink *wfd_tlv =
+						(tlvbuf_wfdisplay_coupled_sink
+						 *)wfd_ptr;
+					wfd_tlv->coupled_sink =
+						new_wfd_coupled_sink_bitmap;
+					break;
+				}
+				wfd_ptr += len + WFD_IE_HEADER_LEN;
+				ie_len_wfd -= len + WFD_IE_HEADER_LEN;
+			}
+			/* Update New IE now */
+			wifiDisplay_ie_config((t_s16 *)&display_ie_index,
+					      ie_len_wfd_org,
+					      (t_u8 *)ie_ptr -
+					      sizeof(tlvbuf_custom_ie));
+		}
+	}
+	free(buf);
+	return;
+}
diff --git a/wlan_sd8897/mapp/wifidirectutl/wifi_display.h b/wlan_sd8897/mapp/wifidirectutl/wifi_display.h
new file mode 100644
index 0000000..0e8ed4d
--- /dev/null
+++ b/wlan_sd8897/mapp/wifidirectutl/wifi_display.h
@@ -0,0 +1,256 @@
+/** @file  wifi_display.h
+ *
+ *  @brief Header file for wifidirectutl application
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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:
+    09/22/11: Initial creation
+************************************************************************/
+#ifndef _WIFIDISPLAY_H
+#define _WIFIDISPLAY_H
+
+#include "wifidirectutl.h"
+/* coupled sink capability*/
+#define MAX_COUPLED_SINK_CAPABILITY 2
+#define MAX_CLIENTS 5
+#define VENDOR_SPECIFIC_IE_TAG 0xDD
+/** TLV : WifiDisplay devie info sublement ID */
+#define TLV_TYPE_WIFIDISPLAY_DEVICE_INFO  0x00
+/** TLV : WifiDisplay Assoc BSSID sublement ID */
+#define TLV_TYPE_WIFIDISPLAY_ASSOC_BSSID  0x01
+/** TLV : WifiDisplay Coupled Sink sublement ID */
+#define TLV_TYPE_WIFIDISPLAY_COUPLED_SINK 0x06
+/** TLV : WifiDisplay Session Info sublement ID */
+#define TLV_TYPE_SESSION_INFO_SUBELEM     0x09
+/** TLV : WifiDisplay Alternate MAC sublement ID */
+#define TLV_TYPE_WIFIDISPLAY_ALTERNATE_MAC 0x10
+/** Host Command ID : wfd display mode config */
+#define HostCmd_CMD_WFD_DISPLAY_MODE_CONFIG         0x0106
+/** Maximum ie index creation allowed with custom ie commands */
+#define MAX_MGMT_IE_INDEX 12
+/** Define len of OUI for WFD */
+#define WIFIDISPLAY_OUI_LEN 3
+/** Define OUI type for WFD */
+#define WIFIDISPLAY_OUI_TYPE 1
+/** Level of wifidisplay parameters in the wifidisplay.conf file */
+typedef enum {
+	DISPLAY_DEVICE_INFO = 1,
+	DISPLAY_ASSOCIATED_BSSID,
+	DISPLAY_COUPLED_SINK,
+	DISPLAY_SESSION_INFO,
+	DISPLAY_ALTERNATE_MAC_ADDR,
+} display_param_level;
+/** Valid Wifi display input parameters */
+typedef enum {
+	WFD_DEVICE_INFO,
+	WFD_SESSION_MGMT_CONTROL_PORT,
+	WFD_DEVICE_THROUGHPUT,
+	WFD_COUPLED_SINK,
+} display_valid_inputs;
+
+/** AP CMD header */
+#define WIFI_DISPLAY_CMD_HEADER     /** Buf Size */         \
+                        t_u32 buf_size;         \
+                        /** Command Code */     \
+                        t_u16 cmd_code;         \
+                        /** Size */             \
+                        t_u16 size;             \
+                        /** Sequence Number */  \
+                        t_u16 seq_num;          \
+                        /** Result */           \
+                        t_s16 result
+
+/** TLV buffer : WifiDisplay device info parameters*/
+typedef PACK_START struct tlvbuf_wfdisplay_device_info {
+    /** Tag */
+	t_u8 tag;
+    /** Length */
+	t_u16 length;
+    /** action */
+    /** Device Info Bitmap */
+	t_u8 display_device_info[2];
+    /** Control Port for WFD communication */
+	t_u8 session_mgmt_control_port[2];
+    /** WFD Maximum Device Throuput */
+	t_u8 wfd_device_throuput[2];
+} PACK_END tlvbuf_wfdisplay_device_info;
+
+/** TLV buffer : WifiDisplay Assoc BSSID paramenters*/
+typedef PACK_START struct tlvbuf_wfdisplay_assoc_bssid {
+    /** Tag */
+	t_u8 tag;
+    /** Length */
+	t_u16 length;
+    /** associated BSSID */
+	t_u8 assoc_bssid[ETH_ALEN];
+} PACK_END tlvbuf_wfdisplay_assoc_bssid;
+
+/** TLV buffer : WifiDisplay Alaternate MAC paramenters*/
+typedef PACK_START struct tlvbuf_wfdisplay_alternate_mac {
+    /** Tag */
+	t_u8 tag;
+    /** Length */
+	t_u16 length;
+    /** Alternate MAC */
+	t_u8 alternate_mac[ETH_ALEN];
+} PACK_END tlvbuf_wfdisplay_alternate_mac;
+
+/** TLV buffer : WifiDisplay coupled sink parameters*/
+typedef PACK_START struct tlvbuf_wfdisplay_coupled_sink {
+    /** Tag */
+	t_u8 tag;
+    /** Length */
+	t_u16 length;
+    /** Coupled Sink Bitmap */
+	t_u8 coupled_sink;
+    /** Coupled Peer MAC */
+	t_u8 peer_mac[ETH_ALEN];
+} PACK_END tlvbuf_wfdisplay_coupled_sink;
+
+/** TLV buffer : WifiDirect Device Info parameters*/
+struct WifiDisplayDeviceInfoDesc {
+	t_u8 length;
+	t_u8 dev_address[ETH_ALEN];
+	t_u8 AssociatedBSSID[ETH_ALEN];
+	t_u8 dev_info[2];
+	t_u8 max_throughput[2];
+	t_u8 coupled_sink[7];
+};
+
+/** TLV buffer : WifiDirect Session Info parameters*/
+typedef PACK_START struct tlvbuf_wifi_display_session_info {
+    /** Tag */
+	t_u8 tag;
+    /** Length */
+	t_u16 length;
+    /** Device Info Descriptor pointer */
+	t_u8 *WFDDevInfoDesc;
+} PACK_END tlvbuf_wifi_display_session_info;
+/** TLV buffer : WifiDirect Wifi Display IE format*/
+typedef PACK_START struct tlvbuf_wifidisplay_ie_format {
+    /** Tag */
+	t_u8 ElemId;
+    /** Length */
+	t_u8 length;
+    /** Vendor Specific OUI */
+	t_u8 Oui[3];
+    /** Vendor Specific OUI */
+	t_u8 OuiType;
+    /** Vendor Specific OUI */
+	t_u8 wfd_ie[1];
+} PACK_END tlvbuf_wifidisplay_ie_format;
+
+/** HostCmd_CMD_WIFI_DISPLAY_MODE_CONFIG */
+typedef PACK_START struct _wifi_display_mode_config {
+	WIFI_DISPLAY_CMD_HEADER;
+    /** Action */
+	t_u16 action;		/* 0 = ACT_GET; 1 = ACT_SET; */
+    /** wifi display mode data */
+	t_u16 mode;
+} PACK_END wifi_display_mode_config;
+
+/** HostCmd_CMD_WIFIDISPLAY_SERVICE_DISCOVERY request */
+typedef PACK_START struct _wifidisplay_discovery_request {
+    /** Header */
+	WIFI_DISPLAY_CMD_HEADER;
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** Category */
+	t_u8 category;
+    /** Action */
+	t_u8 action;
+    /** Dialog taken */
+	t_u8 dialog_taken;
+    /** Advertize protocol IE */
+	t_u8 advertize_protocol_ie[4];
+    /** Query request Length */
+	t_u16 query_len;
+    /** Information identifier */
+	t_u8 info_id[2];
+    /** Request Length */
+	t_u16 request_len;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI sub type */
+	t_u8 oui_sub_type;
+    /** Service update indicator */
+	t_u16 service_update_indicator;
+    /** Vendor Length */
+	t_u16 vendor_len;
+    /** Service protocol */
+	t_u8 service_protocol;
+    /** Service transaction Id */
+	t_u8 service_transaction_id;
+    /** Query Data */
+	t_u8 disc_query[0];
+} PACK_END wifidisplay_discovery_request;
+
+/** HostCmd_CMD_WIFIDISPLAY_SERVICE_DISCOVERY response */
+typedef PACK_START struct _wifidisplay_discovery_response {
+    /** Header */
+	WIFI_DISPLAY_CMD_HEADER;
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** Category */
+	t_u8 category;
+    /** Action */
+	t_u8 action;
+    /** Dialog taken */
+	t_u8 dialog_taken;
+    /** Status code */
+	t_u16 status_code;
+    /** GAS comback reply */
+	t_u16 gas_reply;
+    /** Advertize protocol IE */
+	t_u8 advertize_protocol_ie[4];
+    /** Query response Length */
+	t_u16 query_len;
+    /** Information identifier */
+	t_u8 info_id[2];
+    /** Response Length */
+	t_u16 response_len;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI sub type */
+	t_u8 oui_sub_type;
+    /** Service update indicator */
+	t_u16 service_update_indicator;
+    /** Vendor Length */
+	t_u16 vendor_len;
+    /** Service protocol */
+	t_u8 service_protocol;
+    /** Service transaction Id */
+	t_u8 service_transaction_id;
+    /** Discovery status code */
+	t_u8 disc_status_code;
+    /** Response Data */
+	t_u8 disc_resp[0];
+} PACK_END wifidisplay_discovery_response;
+
+int is_wifidisplay_input_valid(display_valid_inputs cmd, int argc,
+			       char *argv[]);
+void wifidisplaycmd_config(int argc, char *argv[]);
+void wifidisplay_file_params_config(char *file_name, char *cmd_name,
+				    t_u8 *pbuf, t_u16 *ie_len_wifidisplay);
+void wifidisplay_cmd_status(int argc, char *argv[]);
+void wifidisplaycmd_service_discovery(int argc, char *argv[]);
+void wifidisplay_update_custom_ie(int argc, char *argv[]);
+void wifidisplay_update_coupledsink_bitmap(int argc, char *argv[]);
+#endif /* _WIFIDISPLAY_H */
diff --git a/wlan_sd8897/mapp/wifidirectutl/wifidirectutl.c b/wlan_sd8897/mapp/wifidirectutl/wifidirectutl.c
new file mode 100644
index 0000000..28cd362
--- /dev/null
+++ b/wlan_sd8897/mapp/wifidirectutl/wifidirectutl.c
@@ -0,0 +1,8218 @@
+/** @file  wifidirectutl.c
+ *
+ *  @brief Program to configure WifiDirect parameters.
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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:
+  07/10/09: Initial creation
+ ****************************************************************************/
+
+/****************************************************************************
+  Header files
+ ****************************************************************************/
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <linux/wireless.h>
+#include "wifidirectutl.h"
+#include "wifi_display.h"
+/****************************************************************************
+  Definitions
+ ****************************************************************************/
+
+/** Convert character to integer */
+#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0'))
+
+/** Uncomment this to enable DEBUG */
+/* #define DEBUG */
+
+/****************************************************************************
+  Global variables
+ ****************************************************************************/
+/** Device name */
+char dev_name[IFNAMSIZ + 1];
+/** Option for cmd */
+struct option cmd_options[] = {
+	{"help", 0, 0, 'h'},
+	{0, 0, 0, 0}
+};
+
+/****************************************************************************
+  Local functions
+ ***************************************************************************/
+/**
+ *  @brief Dump hex data
+ *
+ *  @param p        A pointer to data buffer
+ *  @param len      The len of data buffer
+ *  @param delim    Deliminator character
+ *  @return         Hex integer
+ */
+#ifdef DEBUG
+static void
+hexdump(void *p, t_s32 len, char delim)
+{
+	t_s32 i;
+	t_u8 *s = p;
+	printf("HexDump: len=%d\n", (int)len);
+	for (i = 0; i < len; i++) {
+		if (i != len - 1)
+			printf("%02x%c", *s++, delim);
+		else
+			printf("%02x\n", *s);
+		if ((i + 1) % 16 == 0)
+			printf("\n");
+	}
+}
+#endif
+
+static int
+wifidir_use_fixed_ie_indices(void)
+{
+#define WIFIDIR_USE_FIXED_IE_INDICES "WIFIDIR_USE_FIXED_IE_INDICES"
+	char *ret = getenv(WIFIDIR_USE_FIXED_IE_INDICES);
+
+	if (ret != NULL && *ret == '1') {
+		printf("Using fixed ie indices 0 and 1 for P2P and WPS IEs");
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+/**
+ *  @brief Converts a string to hex value
+ *
+ *  @param str      A pointer to the string
+ *  @param raw      A pointer to the raw data buffer
+ *  @return         Number of bytes read
+ */
+static int
+string2raw(char *str, unsigned char *raw)
+{
+	int len = (strlen(str) + 1) / 2;
+
+	do {
+		if (!isxdigit(*str)) {
+			return -1;
+		}
+		*str = toupper(*str);
+		*raw = CHAR2INT(*str) << 4;
+		++str;
+		*str = toupper(*str);
+		if (*str == '\0')
+			break;
+		*raw |= CHAR2INT(*str);
+		++raw;
+	} while (*++str != '\0');
+	return len;
+}
+
+/**
+ *    @brief Convert string to hex integer
+ *
+ *    @param s            A pointer string buffer
+ *    @return             Hex integer
+ */
+unsigned int
+a2hex(char *s)
+{
+	unsigned int val = 0;
+	if (!strncasecmp("0x", s, 2)) {
+		s += 2;
+	}
+	while (*s && isxdigit(*s)) {
+		val = (val << 4) + hexc2bin(*s++);
+	}
+	return val;
+}
+
+/**
+ *  @brief      Hex to number
+ *
+ *  @param c    Hex value
+ *  @return     Integer value or -1
+ */
+static int
+hex2num(char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+
+	return -1;
+}
+
+/**
+ *    @brief Convert char to hex integer
+ *
+ *    @param chr          Char
+ *    @return             Hex integer
+ */
+unsigned char
+hexc2bin(char chr)
+{
+	if (chr >= '0' && chr <= '9')
+		chr -= '0';
+	else if (chr >= 'A' && chr <= 'F')
+		chr -= ('A' - 10);
+	else if (chr >= 'a' && chr <= 'f')
+		chr -= ('a' - 10);
+
+	return chr;
+}
+
+/**
+ *  @brief              Check hex string
+ *
+ *  @param hex          A pointer to hex string
+ *  @return             SUCCESS or FAILURE
+ */
+static int
+ishexstring(void *hex)
+{
+	int i, a;
+	char *p = hex;
+	int len = strlen(p);
+	if (!strncasecmp("0x", p, 2)) {
+		p += 2;
+		len -= 2;
+	}
+	for (i = 0; i < len; i++) {
+		a = hex2num(*p);
+		if (a < 0)
+			return FAILURE;
+		p++;
+	}
+	return SUCCESS;
+}
+
+/**
+ *  @brief Prints a MAC address in colon separated form from hex data
+ *
+ *  @param raw      A pointer to the hex data buffer
+ *  @return         N/A
+ */
+static void
+print_mac(t_u8 *raw)
+{
+	printf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)raw[0],
+	       (unsigned int)raw[1], (unsigned int)raw[2], (unsigned int)raw[3],
+	       (unsigned int)raw[4], (unsigned int)raw[5]);
+	return;
+}
+
+/**
+ *  @brief Converts colon separated MAC address to hex value
+ *
+ *  @param mac      A pointer to the colon separated MAC string
+ *  @param raw      A pointer to the hex data buffer
+ *  @return         SUCCESS or FAILURE
+ *                  WIFIDIRECT_RET_MAC_BROADCAST  - if broadcast mac
+ *                  WIFIDIRECT_RET_MAC_MULTICAST - if multicast mac
+ */
+int
+mac2raw(char *mac, t_u8 *raw)
+{
+	unsigned int temp_raw[ETH_ALEN];
+	int num_tokens = 0;
+	int i;
+	if (strlen(mac) != ((2 * ETH_ALEN) + (ETH_ALEN - 1))) {
+		return FAILURE;
+	}
+	num_tokens = sscanf(mac, "%2x:%2x:%2x:%2x:%2x:%2x",
+			    temp_raw + 0, temp_raw + 1, temp_raw + 2,
+			    temp_raw + 3, temp_raw + 4, temp_raw + 5);
+	if (num_tokens != ETH_ALEN) {
+		return FAILURE;
+	}
+	for (i = 0; i < num_tokens; i++)
+		raw[i] = (t_u8)temp_raw[i];
+
+	if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) {
+		return WIFIDIRECT_RET_MAC_BROADCAST;
+	} else if (raw[0] & 0x01) {
+		return WIFIDIRECT_RET_MAC_MULTICAST;
+	}
+	return SUCCESS;
+}
+
+/**
+ *  @brief Prints usage information of wifidirectutl
+ *
+ *  @return          N/A
+ */
+static void
+print_tool_usage(void)
+{
+
+	printf("Usage:\n");
+	printf("./wifidirectutl <iface> wifidirect_mode [mode]\n"
+	       "./wifidirectutl <iface> wifidirect_config [*.conf]\n"
+	       "./wifidirectutl <iface> wifidirect_params_config [*.conf]\n"
+	       "./wifidirectutl <iface> wifidirect_action_frame <*.conf>|"
+	       "	<PeerAddr> <Category> <OuiSubtype> <DialogToken>\n"
+	       "./wifidirectutl <iface> wifidirect_discovery_request <*.conf>\n"
+	       "./wifidirectutl <iface> wifidirect_discovery_response <*.conf>\n"
+	       "./wifidirectutl <iface> wifidirect_gas_comeback_request <*.conf>\n"
+	       "./wifidirectutl <iface> wifidirect_gas_comeback_response <*.conf>\n"
+	       "./wifidirectutl <iface> wifidisplay_config [*.conf]\n"
+	       "./wifidirectutl <iface> wifidisplay_mode [enable/disable]\n"
+	       "./wifidirectutl <iface> wifidisplay_update_devinfo [value]\n"
+	       "./wifidirectutl <iface> wifidisplay_update_coupledsink_bitmap [value <= 255]\n"
+	       "./wifidirectutl <iface> wifidisplay_discovery_request [*.config]\n"
+	       "./wifidirectutl <iface> wifidisplay_discovery_response [*.config]\n");
+	printf("\nPlease see example configuration file config/wifidirect.conf\n\n");
+	printf("Configuration API:\n");
+	printf("./wifidirectutl <iface> wifidirect_cfg_discovery_period [<MinDiscPeriod> <MaxDiscPeriod>]\n" "./wifidirectutl <iface> wifidirect_cfg_intent [IntentValue]\n" "./wifidirectutl <iface> wifidirect_cfg_capability [<deviceCapability> <groupCapability>]\n" "./wifidirectutl <iface> wifidirect_cfg_noa <enable | disable> [<counttype> <duration> <interval>]\n" "./wifidirectutl <iface> wifidirect_cfg_opp_ps [<enable> <CTWindow>]\n" "./wifidirectutl <iface> wifidirect_cfg_invitation_list [mac_address]\n" "./wifidirectutl <iface> wifidirect_cfg_listen_channel [listenChannel]\n" "./wifidirectutl <iface> wifidirect_cfg_op_channel [operatingChannel]\n" "./wifidirecttul <iface> wifidirect_cfg_persistent_group_record [index] [role]\n" "	[<groupbss> <deviceId> <ssid> <psk>] [peermac1] [peermac2]\n" "./wifidirecttul <iface> wifidirect_cfg_persistent_group_invoke [index] | <cancel>\n" "./wifidirectutl <iface> wifidirect_cfg_presence_req_params [<type> <duration> <interval>]\n" "./wifidirectutl <iface> wifidirect_cfg_ext_listen_time [<duration> <interval>]\n");
+
+}
+
+/**
+ *  @brief Parses a command line
+ *
+ *  @param line     The line to parse
+ *  @param args     Pointer to the argument buffer to be filled in
+ *  @return         Number of arguments in the line or EOF
+ */
+int
+parse_line(char *line, char *args[])
+{
+	int arg_num = 0;
+	int is_start = 0;
+	int is_quote = 0;
+	int is_escape = 0;
+	int length = 0;
+	int i = 0;
+	int j = 0;
+
+	arg_num = 0;
+	length = strlen(line);
+	/* Process line */
+
+	/* Find number of arguments */
+	is_start = 0;
+	is_quote = 0;
+	for (i = 0; i < length; i++) {
+		/* Ignore leading spaces */
+		if (is_start == 0) {
+			if (line[i] == ' ') {
+				continue;
+			} else if (line[i] == '\t') {
+				continue;
+			} else if (line[i] == '\n') {
+				break;
+			} else {
+				is_start = 1;
+				args[arg_num] = &line[i];
+				arg_num++;
+			}
+		}
+		if (is_start == 1) {
+			if ((line[i] == '\\') && (i < (length - 1))) {
+				if (line[i + 1] == '"') {
+					is_escape = 1;
+					for (j = i; j < length - 1; j++) {
+						line[j] = line[j + 1];
+					}
+					line[length - 1] = '\0';
+					continue;
+				}
+			}
+			/* Ignore comments */
+			if (line[i] == '#') {
+				if (is_quote == 0) {
+					line[i] = '\0';
+					arg_num--;
+				}
+				break;
+			}
+			/* Separate by '=' */
+			if (line[i] == '=') {
+				if (is_quote == 0) {
+					line[i] = '\0';
+					is_start = 0;
+					continue;
+				}
+			}
+			/* Separate by ',' */
+			if (line[i] == ',') {
+				if (is_quote == 0) {
+					line[i] = '\0';
+					is_start = 0;
+					continue;
+				}
+			}
+			/* Change ',' to ' ', but not inside quotes */
+			if ((line[i] == ',') && (is_quote == 0)) {
+				line[i] = ' ';
+				continue;
+			}
+		}
+		/* Remove newlines */
+		if (line[i] == '\n') {
+			line[i] = '\0';
+		}
+		/* Check for quotes */
+		if (line[i] == '"') {
+			if (is_escape) {
+				is_escape = 0;
+				/* no change in is_quote */
+			} else {
+				is_quote = (is_quote == 1) ? 0 : 1;
+			}
+			continue;
+		}
+		if (((line[i] == ' ') || (line[i] == '\t')) && (is_quote == 0)) {
+			line[i] = '\0';
+			is_start = 0;
+			continue;
+		}
+	}
+	return arg_num;
+}
+
+/**
+ *  @brief      Parse function for a configuration line
+ *
+ *  @param s        Storage buffer for data
+ *  @param size     Maximum size of data
+ *  @param stream   File stream pointer
+ *  @param line     Pointer to current line within the file
+ *  @param _pos     Output string or NULL
+ *  @return     String or NULL
+ */
+char *
+config_get_line(char *s, int size, FILE * stream, int *line, char **_pos)
+{
+	char *pos, *end, *sstart;
+	while (fgets(s, size, stream)) {
+		(*line)++;
+		s[size - 1] = '\0';
+		pos = s;
+		/* Skip white space from the beginning of line. */
+		while (*pos == ' ' || *pos == '\t' || *pos == '\r')
+			pos++;
+		/* Skip comment lines and empty lines */
+		if (*pos == '#' || *pos == '\n' || *pos == '\0')
+			continue;
+		/*
+		 * Remove # comments unless they are within a double quoted
+		 * string.
+		 */
+		sstart = strchr(pos, '"');
+		if (sstart)
+			sstart = strrchr(sstart + 1, '"');
+		if (!sstart)
+			sstart = pos;
+		end = strchr(sstart, '#');
+		if (end)
+			*end-- = '\0';
+		else
+			end = pos + strlen(pos) - 1;
+		/* Remove trailing white space. */
+		while (end > pos &&
+		       (*end == '\n' || *end == ' ' || *end == '\t' ||
+			*end == '\r'))
+			*end-- = '\0';
+		if (*pos == '\0')
+			continue;
+		if (_pos)
+			*_pos = pos;
+		return pos;
+	}
+
+	if (_pos)
+		*_pos = NULL;
+	return NULL;
+}
+
+/**
+ *  @brief  Detects duplicates channel in array of strings
+ *
+ *  @param  argc    Number of elements
+ *  @param  argv    Array of strings
+ *  @return UAP_FAILURE or UAP_SUCCESS
+ */
+static inline int
+has_dup_channel(int argc, char *argv[])
+{
+	int i, j;
+	/* Check for duplicate */
+	for (i = 0; i < (argc - 1); i++) {
+		for (j = i + 1; j < argc; j++) {
+			if (atoi(argv[i]) == atoi(argv[j])) {
+				return FAILURE;
+			}
+		}
+	}
+	return SUCCESS;
+}
+
+/**
+ *  @brief Performs the ioctl operation to send the command to
+ *  the driver.
+ *
+ *  @param cmd           Pointer to the command buffer
+ *  @param size          Pointer to the command size. This value is
+ *                       overwritten by the function with the size of the
+ *                       received response.
+ *  @param buf_size      Size of the allocated command buffer
+ *  @return              SUCCESS or FAILURE
+ */
+int
+wifidirect_ioctl(t_u8 *cmd, t_u16 *size, t_u16 buf_size)
+{
+	struct ifreq ifr;
+	mrvl_priv_cmd *mrvl_cmd = NULL;
+	t_u8 *buf = NULL, *temp = NULL;
+	wifidirectcmdbuf *header = NULL;
+	t_s32 sockfd;
+	t_u16 mrvl_header_len = 0;
+	int ret = SUCCESS;
+
+	if (buf_size < *size) {
+		printf("buf_size should not less than cmd buffer size\n");
+		return FAILURE;
+	}
+
+	/* Open socket */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("ERR:Cannot open socket\n");
+		return FAILURE;
+	}
+	*(t_u32 *)cmd = buf_size - BUF_HEADER_SIZE;
+
+	mrvl_header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_HOSTCMD);
+	buf = (unsigned char *)malloc(buf_size + sizeof(mrvl_priv_cmd) +
+				      mrvl_header_len);
+	if (buf == NULL)
+		return FAILURE;
+
+	memset(buf, 0, buf_size + sizeof(mrvl_priv_cmd) + mrvl_header_len);
+	/* Fill up buffer */
+	mrvl_cmd = (mrvl_priv_cmd *)buf;
+	mrvl_cmd->buf = buf + sizeof(mrvl_priv_cmd);
+	mrvl_cmd->used_len = 0;
+	mrvl_cmd->total_len = buf_size + mrvl_header_len;
+	/* Copy Marvell command string */
+	temp = mrvl_cmd->buf;
+	strncpy((char *)temp, CMD_MARVELL, strlen(CMD_MARVELL));
+	temp += (strlen(CMD_MARVELL));
+	/* Insert command string */
+	strncpy((char *)temp, PRIV_CMD_HOSTCMD, strlen(PRIV_CMD_HOSTCMD));
+	temp += (strlen(PRIV_CMD_HOSTCMD));
+
+	memcpy(temp, (t_u8 *)cmd, *size);
+
+	/* Initialize the ifr structure */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
+	ifr.ifr_ifru.ifru_data = (void *)mrvl_cmd;
+	header = (wifidirectcmdbuf *)(buf + sizeof(mrvl_priv_cmd) +
+				      mrvl_header_len);
+	header->size = *size - BUF_HEADER_SIZE;
+#ifdef DEBUG
+	/* Debug print */
+	hexdump(mrvl_cmd, *size + sizeof(mrvl_priv_cmd) + mrvl_header_len, ' ');
+#endif
+	endian_convert_request_header(header);
+
+	/* Perform ioctl */
+	errno = 0;
+	if (ioctl(sockfd, MRVLPRIVCMD, &ifr)) {
+		perror("");
+		printf("ERR:MRVLPRIVCMD is not supported by %s\n", dev_name);
+		ret = FAILURE;
+		goto done;
+	}
+	endian_convert_response_header(header);
+	header->cmd_code &= HostCmd_CMD_ID_MASK;
+	header->cmd_code |= WIFIDIRECTCMD_RESP_CHECK;
+	*size = header->size;
+	memcpy(cmd, buf + sizeof(mrvl_priv_cmd) + mrvl_header_len,
+	       *size + BUF_HEADER_SIZE);
+#ifdef DEBUG
+	/* Debug print */
+	hexdump(mrvl_cmd,
+		*size + BUF_HEADER_SIZE + sizeof(mrvl_priv_cmd) +
+		mrvl_header_len, ' ');
+#endif
+
+	/* Validate response size */
+	if (*size > (buf_size - BUF_HEADER_SIZE)) {
+		printf("ERR:Response size (%d) greater than buffer size (%d)! Aborting!\n", *size, buf_size);
+		ret = FAILURE;
+		goto done;
+	}
+done:
+	/* Close socket */
+	close(sockfd);
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect_gas_comeback_discovery commands
+ *
+ *  $return         N/A
+ */
+static void
+print_wifidirect_gas_comeback_usage(void)
+{
+	printf("\nUsage : wifidirect_gas_comeback_request/response [CONFIG_FILE]\n");
+	printf("CONFIG_FILE contains WIFIDIRECT GAS comeback request/response payload.\n");
+	return;
+}
+
+/**
+ *  @brief Creates a wifidirect_gas_comeback_service_discovery request/response and
+ *         sends to the driver
+ *
+ *  Usage: "Usage : wifidirect_gas_comeback_request/response [CONFIG_FILE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         SUCCESS or FAILURE
+ **/
+static void
+wifidirectcmd_gas_comeback_discovery(int argc, char *argv[])
+{
+	wifidirect_gas_comeback_request *req_buf = NULL;
+	wifidirect_gas_comeback_response *resp_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int i, opt, li = 0, arg_num = 0, ret = 0, wifidirect_level = 0;
+	char *args[30], *pos = NULL, wifidirect_mac[20], wifidirect_cmd[40];
+	t_u8 dev_address[ETH_ALEN], cmd_found = 0;
+	t_u8 *buffer = NULL, *tmp_buffer = NULL;
+	t_u8 req_resp = 0;	/* req = 0, resp = 1 */
+	t_u16 cmd_len = 0, query_len = 0, vendor_len = 0, service_len = 0;
+	t_u16 dns_len = 0, record_len = 0, upnp_len = 0;
+
+	strncpy(wifidirect_cmd, argv[2], sizeof(wifidirect_cmd) - 1);
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_gas_comeback_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 3) {
+		printf("ERR:Incorrect number of arguments.\n");
+		print_wifidirect_gas_comeback_usage();
+		return;
+	}
+
+	/* Check if file exists */
+	config_file = fopen(argv[2], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		arg_num = parse_line(line, args);
+		if (!cmd_found &&
+		    strncmp(args[0], wifidirect_cmd, strlen(args[0])))
+			continue;
+		cmd_found = 1;
+
+		if (strcmp(args[0], "wifidirect_gas_comeback_request") == 0) {
+			wifidirect_level =
+				WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE;
+			/* For wifidirect_service_gas_comeback, basic initialization here */
+			/* Subtract extra two bytes added as a part of query request structure */
+			cmd_len = sizeof(wifidirect_gas_comeback_request) - 2;
+			buffer = (t_u8 *)malloc(cmd_len);
+			if (!buffer) {
+				printf("ERR:Cannot allocate memory!\n");
+				goto done;
+			}
+			req_buf = (wifidirect_gas_comeback_request *)buffer;
+			req_buf->cmd_code =
+				HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY;
+			req_buf->size = cmd_len;
+			req_buf->seq_num = 0;
+			req_buf->result = 0;
+
+		} else if (strcmp(args[0], "wifidirect_gas_comeback_response")
+			   == 0) {
+			wifidirect_level =
+				WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE;
+			req_resp = 1;
+			/* For wifidirect_service_discovery, basic initialization here */
+			/* Subtract extra two bytes added as a part of query response structure */
+			cmd_len = sizeof(wifidirect_gas_comeback_response) - 2;
+			buffer = (t_u8 *)malloc(cmd_len);
+			if (!buffer) {
+				printf("ERR:Cannot allocate memory!\n");
+				goto done;
+			}
+			resp_buf = (wifidirect_gas_comeback_response *)buffer;
+			resp_buf->cmd_code =
+				HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY;
+			resp_buf->size = cmd_len;
+			resp_buf->seq_num = 0;
+			resp_buf->result = 0;
+
+		} else if (strcmp(args[0], "PeerAddr") == 0) {
+			strncpy(wifidirect_mac, args[1], 20);
+			if ((ret =
+			     mac2raw(wifidirect_mac, dev_address)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+			(!req_resp) ? memcpy(req_buf->peer_mac_addr,
+					     dev_address,
+					     ETH_ALEN) : memcpy(resp_buf->
+								peer_mac_addr,
+								dev_address,
+								ETH_ALEN);
+
+		} else if (strcmp(args[0], "Category") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_CATEGORY, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+
+			}
+			(!req_resp) ? (req_buf->category =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       category =
+							       (t_u8)
+							       atoi(args[1]));
+		} else if (strcmp(args[0], "Action") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_ACTION, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->action =
+				       (t_u8)A2HEXDECIMAL(args[1]))
+				: (resp_buf->action =
+				   (t_u8)A2HEXDECIMAL(args[1]));
+		} else if (strcmp(args[0], "DialogToken") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DIALOGTOKEN, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->dialog_taken =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       dialog_taken =
+							       (t_u8)
+							       atoi(args[1]));
+		} else if (strcmp(args[0], "StatusCode") == 0) {
+			resp_buf->status_code = (t_u16)A2HEXDECIMAL(args[1]);
+			resp_buf->status_code =
+				cpu_to_le16(resp_buf->status_code);
+		} else if (strcmp(args[0], "GasComebackDelay") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_GAS_COMEBACK_DELAY, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->gas_reply = (t_u16)A2HEXDECIMAL(args[1]);
+			resp_buf->gas_reply = cpu_to_le16(resp_buf->gas_reply);
+		} else if (strcmp(args[0], "GasResponseFragID") == 0) {
+			resp_buf->gas_fragment_id = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "AdvertizementProtocolIE") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_ADPROTOIE, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < arg_num - 1; i++)
+				resp_buf->advertize_protocol_ie[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "InfoId") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_INFOID, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < arg_num - 1; i++)
+				resp_buf->info_id[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			query_len += arg_num - 1;
+		} else if (strcmp(args[0], "OUI") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_OUI, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < arg_num - 1; i++)
+				resp_buf->oui[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			service_len += arg_num - 1;
+			query_len += arg_num - 1;
+		} else if (strcmp(args[0], "OUISubType") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_OUISUBTYPE, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->oui_sub_type = (t_u8)atoi(args[1]);
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "QueryRequestLen") == 0 ||
+			   strcmp(args[0], "QueryResponseLen") == 0) {
+			wifidirect_level = WIFIDIRECT_DISCOVERY_QUERY;
+		} else if (strcmp(args[0], "RequestLen") == 0 ||
+			   strcmp(args[0], "ResponseLen") == 0) {
+			wifidirect_level = WIFIDIRECT_DISCOVERY_SERVICE;
+			query_len += 2;
+		} else if (strcmp(args[0], "VendorLen") == 0) {
+			wifidirect_level = WIFIDIRECT_DISCOVERY_VENDOR;
+			service_len += 2;
+			query_len += 2;
+		} else if (strcmp(args[0], "QueryData") == 0 ||
+			   strcmp(args[0], "ResponseData") == 0) {
+			wifidirect_level =
+				WIFIDIRECT_DISCOVERY_QUERY_RESPONSE_PER_PROTOCOL;
+		} else if (strcmp(args[0], "ServiceProtocol") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_SERVICEPROTO, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->service_protocol = (t_u8)atoi(args[1]);
+			vendor_len++;
+			service_len++;
+			query_len++;
+			/*
+			 * For uPnP, due to union allocation, a extra byte is allocated
+			 * reduce it here for uPnP
+			 */
+			cmd_len--;
+		} else if (strcmp(args[0], "ServiceUpdateIndicator") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_SERVICEUPDATE_INDICATOR, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->service_update_indicator =
+				cpu_to_le16((t_u16)atoi(args[1]));
+			service_len += 2;
+			query_len += 2;
+		} else if (strcmp(args[0], "ServiceTransactionId") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_SERVICETRANSACID, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->service_transaction_id = (t_u8)atoi(args[1]);
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "ServiceStatus") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_SERVICE_STATUS, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->disc_status_code = (t_u8)atoi(args[1]);
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "DNSName") == 0) {
+			if (args[1][0] == '"') {
+				args[1]++;
+				if (args[1][strlen(args[1]) - 1] == '"')
+					args[1][strlen(args[1]) - 1] = '\0';
+
+				dns_len = strlen(args[1]);
+				tmp_buffer = realloc(buffer, cmd_len + dns_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add DNS name to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				strncpy((char *)resp_buf->disc_resp.u.bonjour.
+					dns, args[1], strlen(args[1]));
+			} else {
+				/* HEX input */
+				dns_len = arg_num - 1;
+				tmp_buffer = realloc(buffer, cmd_len + dns_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add DNS name to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				for (i = 0; i < arg_num - 1; i++)
+					resp_buf->disc_resp.u.bonjour.dns[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			cmd_len += dns_len;
+			vendor_len += dns_len;
+			service_len += dns_len;
+			query_len += dns_len;
+		} else if (strcmp(args[0], "DNSType") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_DNSTYPE, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			*(&resp_buf->disc_resp.u.bonjour.dns_type + dns_len) =
+				(t_u8)A2HEXDECIMAL(args[1]);
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "BonjourVersion") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_BONJOUR_VERSION, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			*(&resp_buf->disc_resp.u.bonjour.version + dns_len) =
+				(t_u8)atoi(args[1]);
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "uPnPVersion") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_UPNP_VERSION, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->disc_resp.u.upnp.version =
+				(t_u8)A2HEXDECIMAL(args[1]);
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "uPnPQueryValue") == 0 ||
+			   strcmp(args[0], "uPnPResponseValue") == 0) {
+			if (args[1][0] == '"') {
+				args[1]++;
+				if (args[1][strlen(args[1]) - 1] == '"')
+					args[1][strlen(args[1]) - 1] = '\0';
+
+				upnp_len = strlen(args[1]);
+				tmp_buffer =
+					realloc(buffer, cmd_len + upnp_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add uPnP value to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				strncpy((char *)resp_buf->disc_resp.u.upnp.
+					value, args[1], upnp_len);
+			} else {
+				/* HEX input */
+				upnp_len = arg_num - 1;
+				tmp_buffer =
+					realloc(buffer, cmd_len + upnp_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add uPnP value to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				for (i = 0; i < arg_num - 1; i++)
+					resp_buf->disc_resp.u.upnp.value[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			cmd_len += upnp_len;
+			vendor_len += upnp_len;
+			service_len += upnp_len;
+			query_len += upnp_len;
+		} else if (strcmp(args[0], "RecordData") == 0) {
+			if (args[1][0] == '"') {
+				args[1]++;
+				if (args[1][strlen(args[1]) - 1] == '"')
+					args[1][strlen(args[1]) - 1] = '\0';
+
+				record_len = strlen(args[1]);
+				tmp_buffer =
+					realloc(buffer, cmd_len + record_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add Record name to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				if (!req_resp) {
+					printf("ERR:Cannot add Record name to buffer!\n");
+					goto done;
+				}
+				strncpy((char *)resp_buf->disc_resp.u.bonjour.
+					record, args[1], strlen(args[1]));
+			} else {
+				/* HEX input */
+				record_len = arg_num - 1;
+				tmp_buffer =
+					realloc(buffer, cmd_len + record_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add Record name to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				if (!req_resp) {
+					printf("ERR:Cannot add Record name to buffer!\n");
+					goto done;
+				}
+				for (i = 0; i < arg_num - 1; i++)
+					resp_buf->disc_resp.u.bonjour.
+						record[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+
+			}
+			cmd_len += record_len;
+			vendor_len += record_len;
+			service_len += record_len;
+			query_len += record_len;
+		} else if (strcmp(args[0], "}") == 0) {
+			switch (wifidirect_level) {
+			case WIFIDIRECT_DISCOVERY_QUERY:
+				resp_buf->query_len = cpu_to_le16(query_len);
+				break;
+			case WIFIDIRECT_DISCOVERY_SERVICE:
+				resp_buf->response_len =
+					cpu_to_le16(service_len);
+				break;
+			case WIFIDIRECT_DISCOVERY_VENDOR:
+				resp_buf->vendor_len = cpu_to_le16(vendor_len);
+				break;
+			default:
+				break;
+			}
+			if (wifidirect_level) {
+				if (wifidirect_level ==
+				    WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE)
+					break;
+				wifidirect_level--;
+			}
+		}
+	}
+	/* Send collective command */
+	wifidirect_ioctl((t_u8 *)buffer, &cmd_len, cmd_len);
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+}
+
+/**
+ *  @brief Show usage information for the wifidirect_discovery commands
+ *
+ *  $return         N/A
+ */
+static void
+print_wifidirect_discovery_usage(void)
+{
+	printf("\nUsage : wifidirect_discovery_request/response [CONFIG_FILE]\n");
+	printf("CONFIG_FILE contains WIFIDIRECT service discovery payload.\n");
+	return;
+}
+
+/**
+ *  @brief Creates a wifidirect_service_discovery request/response and
+ *         sends to the driver
+ *
+ *  Usage: "Usage : wifidirect_discovery_request/response [CONFIG_FILE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         SUCCESS or FAILURE
+ **/
+static void
+wifidirectcmd_service_discovery(int argc, char *argv[])
+{
+	wifidirect_discovery_request *req_buf = NULL;
+	wifidirect_discovery_response *resp_buf = NULL;
+	char *line = NULL;
+	FILE *config_file = NULL;
+	int i, opt, li = 0, arg_num = 0, ret = 0, wifidirect_level = 0;
+	char *args[30], *pos = NULL, wifidirect_mac[20], wifidirect_cmd[32];
+	t_u8 dev_address[ETH_ALEN], cmd_found = 0;
+	t_u8 *buffer = NULL, *tmp_buffer = NULL;
+	t_u8 req_resp = 0;	/* req = 0, resp = 1 */
+	t_u16 cmd_len = 0, query_len = 0, vendor_len = 0, service_len = 0;
+	t_u16 dns_len = 0, record_len = 0, upnp_len = 0;
+
+	strncpy(wifidirect_cmd, argv[2], sizeof(wifidirect_cmd) - 1);
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_discovery_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 3) {
+		printf("ERR:Incorrect number of arguments.\n");
+		print_wifidirect_discovery_usage();
+		return;
+	}
+
+	/* Check if file exists */
+	config_file = fopen(argv[2], "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return;
+	}
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		arg_num = parse_line(line, args);
+		if (!cmd_found &&
+		    strncmp(args[0], wifidirect_cmd, strlen(args[0])))
+			continue;
+		cmd_found = 1;
+
+		if (strcmp(args[0], "wifidirect_discovery_request") == 0) {
+			wifidirect_level =
+				WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE;
+			/* For wifidirect_service_discovery, basic initialization here */
+			cmd_len = sizeof(wifidirect_discovery_request);
+			buffer = (t_u8 *)malloc(cmd_len);
+			if (!buffer) {
+				printf("ERR:Cannot allocate memory!\n");
+				goto done;
+			}
+			req_buf = (wifidirect_discovery_request *)buffer;
+			req_buf->cmd_code =
+				HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY;
+			req_buf->size = cmd_len;
+			req_buf->seq_num = 0;
+			req_buf->result = 0;
+
+		} else if (strcmp(args[0], "wifidirect_discovery_response") ==
+			   0) {
+			wifidirect_level =
+				WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE;
+			req_resp = 1;
+			/* For wifidirect_service_discovery, basic initialization here */
+			cmd_len = sizeof(wifidirect_discovery_response);
+			buffer = (t_u8 *)malloc(cmd_len);
+			if (!buffer) {
+				printf("ERR:Cannot allocate memory!\n");
+				goto done;
+			}
+			resp_buf = (wifidirect_discovery_response *)buffer;
+			resp_buf->cmd_code =
+				HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY;
+			resp_buf->size = cmd_len;
+			resp_buf->seq_num = 0;
+			resp_buf->result = 0;
+
+		} else if (strcmp(args[0], "PeerAddr") == 0) {
+			strncpy(wifidirect_mac, args[1], 20 - 1);
+			if ((ret =
+			     mac2raw(wifidirect_mac, dev_address)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+			(!req_resp) ? memcpy(req_buf->peer_mac_addr,
+					     dev_address,
+					     ETH_ALEN) : memcpy(resp_buf->
+								peer_mac_addr,
+								dev_address,
+								ETH_ALEN);
+
+		} else if (strcmp(args[0], "Category") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_CATEGORY, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+
+			}
+			(!req_resp) ? (req_buf->category =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       category =
+							       (t_u8)
+							       atoi(args[1]));
+		} else if (strcmp(args[0], "Action") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_ACTION, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->action =
+				       (t_u8)A2HEXDECIMAL(args[1]))
+				: (resp_buf->action =
+				   (t_u8)A2HEXDECIMAL(args[1]));
+		} else if (strcmp(args[0], "DialogToken") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DIALOGTOKEN, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->dialog_taken =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       dialog_taken =
+							       (t_u8)
+							       atoi(args[1]));
+		} else if (strcmp(args[0], "StatusCode") == 0) {
+			resp_buf->status_code = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "GasComebackDelay") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_GAS_COMEBACK_DELAY, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->gas_reply = (t_u16)A2HEXDECIMAL(args[1]);
+			resp_buf->gas_reply = cpu_to_le16(resp_buf->gas_reply);
+		} else if (strcmp(args[0], "AdvertizementProtocolIE") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_ADPROTOIE, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			if (!req_resp) {
+				for (i = 0; i < arg_num - 1; i++)
+					req_buf->advertize_protocol_ie[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			} else {
+				for (i = 0; i < arg_num - 1; i++)
+					resp_buf->advertize_protocol_ie[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+		} else if (strcmp(args[0], "InfoId") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_INFOID, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			if (!req_resp) {
+				for (i = 0; i < arg_num - 1; i++)
+					req_buf->info_id[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			} else {
+				for (i = 0; i < arg_num - 1; i++)
+					resp_buf->info_id[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			query_len += arg_num - 1;
+		} else if (strcmp(args[0], "OUI") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_OUI, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			if (!req_resp) {
+				for (i = 0; i < arg_num - 1; i++)
+					req_buf->oui[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			} else {
+				for (i = 0; i < arg_num - 1; i++)
+					resp_buf->oui[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			service_len += arg_num - 1;
+			query_len += arg_num - 1;
+		} else if (strcmp(args[0], "OUISubType") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_OUISUBTYPE, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->oui_sub_type =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       oui_sub_type =
+							       (t_u8)
+							       atoi(args[1]));
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "QueryRequestLen") == 0 ||
+			   strcmp(args[0], "QueryResponseLen") == 0) {
+			wifidirect_level = WIFIDIRECT_DISCOVERY_QUERY;
+		} else if (strcmp(args[0], "RequestLen") == 0 ||
+			   strcmp(args[0], "ResponseLen") == 0) {
+			wifidirect_level = WIFIDIRECT_DISCOVERY_SERVICE;
+			query_len += 2;
+		} else if (strcmp(args[0], "VendorLen") == 0) {
+			wifidirect_level = WIFIDIRECT_DISCOVERY_VENDOR;
+			service_len += 2;
+			query_len += 2;
+		} else if (strcmp(args[0], "QueryData") == 0 ||
+			   strcmp(args[0], "ResponseData") == 0) {
+			wifidirect_level =
+				WIFIDIRECT_DISCOVERY_QUERY_RESPONSE_PER_PROTOCOL;
+		} else if (strcmp(args[0], "ServiceProtocol") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_SERVICEPROTO, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			if (!req_resp) {
+				req_buf->service_protocol = (t_u8)atoi(args[1]);
+				/*
+				 * For uPnP, due to union allocation, a extra byte
+				 * is allocated reduce it here for uPnP
+				 */
+				if (req_buf->service_protocol == 2)
+					cmd_len--;
+			} else {
+				resp_buf->service_protocol =
+					(t_u8)atoi(args[1]);
+				if (resp_buf->service_protocol == 2)
+					cmd_len--;
+			}
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "ServiceUpdateIndicator") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_SERVICEUPDATE_INDICATOR, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->service_update_indicator =
+				       cpu_to_le16((t_u16)atoi(args[1]))) :
+				(resp_buf->service_update_indicator =
+				 cpu_to_le16((t_u16)atoi(args[1])));
+			service_len += 2;
+			query_len += 2;
+		} else if (strcmp(args[0], "ServiceTransactionId") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_SERVICETRANSACID, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ? (req_buf->service_transaction_id =
+				       (t_u8)atoi(args[1])) : (resp_buf->
+							       service_transaction_id
+							       =
+							       (t_u8)
+							       atoi(args[1]));
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "ServiceStatus") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_SERVICE_STATUS, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			resp_buf->disc_status_code = (t_u8)atoi(args[1]);
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "DNSName") == 0) {
+			if (args[1][0] == '"') {
+				args[1]++;
+				if (args[1][strlen(args[1]) - 1] == '"')
+					args[1][strlen(args[1]) - 1] = '\0';
+
+				dns_len = strlen(args[1]);
+				tmp_buffer = realloc(buffer, cmd_len + dns_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add DNS name to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				(!req_resp) ?
+					(strncpy
+					 ((char *)req_buf->disc_query.u.bonjour.
+					  dns, args[1],
+					  strlen(args[1]))) : (strncpy((char *)
+								       resp_buf->
+								       disc_resp.
+								       u.
+								       bonjour.
+								       dns,
+								       args[1],
+								       strlen
+								       (args
+									[1])));
+			} else {
+				/* HEX input */
+				dns_len = arg_num - 1;
+				tmp_buffer = realloc(buffer, cmd_len + dns_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add DNS name to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				if (!req_resp) {
+					for (i = 0; i < arg_num - 1; i++)
+						req_buf->disc_query.u.bonjour.
+							dns[i] =
+							(t_u8)
+							A2HEXDECIMAL(args
+								     [i + 1]);
+				} else {
+					for (i = 0; i < arg_num - 1; i++)
+						resp_buf->disc_resp.u.bonjour.
+							dns[i] =
+							(t_u8)
+							A2HEXDECIMAL(args
+								     [i + 1]);
+				}
+			}
+			cmd_len += dns_len;
+			vendor_len += dns_len;
+			service_len += dns_len;
+			query_len += dns_len;
+		} else if (strcmp(args[0], "DNSType") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_DNSTYPE, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ?
+				(*
+				 (&req_buf->disc_query.u.bonjour.dns_type +
+				  dns_len) =
+				 (t_u8)A2HEXDECIMAL(args[1])) : (*(&resp_buf->
+								   disc_resp.u.
+								   bonjour.
+								   dns_type +
+								   dns_len) =
+								 (t_u8)
+								 A2HEXDECIMAL
+								 (args[1]));
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "BonjourVersion") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_BONJOUR_VERSION, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ?
+				(*
+				 (&req_buf->disc_query.u.bonjour.version +
+				  dns_len) =
+				 (t_u8)atoi(args[1])) : (*(&resp_buf->disc_resp.
+							   u.bonjour.version +
+							   dns_len) =
+							 (t_u8)atoi(args[1]));
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "uPnPVersion") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DISC_UPNP_VERSION, arg_num - 1,
+			     args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			(!req_resp) ?
+				(req_buf->disc_query.u.upnp.version =
+				 (t_u8)A2HEXDECIMAL(args[1])) : (resp_buf->
+								 disc_resp.u.
+								 upnp.version =
+								 (t_u8)
+								 A2HEXDECIMAL
+								 (args[1]));
+			vendor_len++;
+			service_len++;
+			query_len++;
+		} else if (strcmp(args[0], "uPnPQueryValue") == 0 ||
+			   strcmp(args[0], "uPnPResponseValue") == 0) {
+			if (args[1][0] == '"') {
+				args[1]++;
+				if (args[1][strlen(args[1]) - 1] == '"')
+					args[1][strlen(args[1]) - 1] = '\0';
+
+				upnp_len = strlen(args[1]);
+				tmp_buffer =
+					realloc(buffer, cmd_len + upnp_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add uPnP value to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				(!req_resp) ?
+					(strncpy
+					 ((char *)req_buf->disc_query.u.upnp.
+					  value, args[1],
+					  upnp_len)) : (strncpy((char *)
+								resp_buf->
+								disc_resp.u.
+								upnp.value,
+								args[1],
+								upnp_len));
+			} else {
+				/* HEX input */
+				upnp_len = arg_num - 1;
+				tmp_buffer =
+					realloc(buffer, cmd_len + upnp_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add uPnP value to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				if (!req_resp) {
+					for (i = 0; i < arg_num - 1; i++)
+						req_buf->disc_query.u.upnp.
+							value[i] =
+							(t_u8)
+							A2HEXDECIMAL(args
+								     [i + 1]);
+				} else {
+					for (i = 0; i < arg_num - 1; i++)
+						resp_buf->disc_resp.u.upnp.
+							value[i] =
+							(t_u8)
+							A2HEXDECIMAL(args
+								     [i + 1]);
+				}
+			}
+			cmd_len += upnp_len;
+			vendor_len += upnp_len;
+			service_len += upnp_len;
+			query_len += upnp_len;
+		} else if (strcmp(args[0], "RecordData") == 0) {
+			if (args[1][0] == '"') {
+				args[1]++;
+				if (args[1][strlen(args[1]) - 1] == '"')
+					args[1][strlen(args[1]) - 1] = '\0';
+
+				record_len = strlen(args[1]);
+				tmp_buffer =
+					realloc(buffer, cmd_len + record_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add Record name to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				if (!req_resp) {
+					printf("ERR:Cannot add Record name to buffer!\n");
+					goto done;
+				}
+				strncpy((char *)resp_buf->disc_resp.u.bonjour.
+					record + dns_len, args[1],
+					strlen(args[1]));
+			} else {
+				/* HEX input */
+				record_len = arg_num - 1;
+				tmp_buffer =
+					realloc(buffer, cmd_len + record_len);
+				if (!tmp_buffer) {
+					printf("ERR:Cannot add Record name to buffer!\n");
+					goto done;
+				} else {
+					buffer = tmp_buffer;
+					tmp_buffer = NULL;
+				}
+				if (!req_resp) {
+					printf("ERR:Cannot add Record name to buffer!\n");
+					goto done;
+				}
+				for (i = 0; i < arg_num - 1; i++)
+					*(&resp_buf->disc_resp.u.bonjour.
+					  record[i] + dns_len) =
+		 (t_u8)A2HEXDECIMAL(args[i + 1]);
+			}
+			cmd_len += record_len;
+			vendor_len += record_len;
+			service_len += record_len;
+			query_len += record_len;
+		} else if (strcmp(args[0], "}") == 0) {
+			switch (wifidirect_level) {
+			case WIFIDIRECT_DISCOVERY_QUERY:
+				(!req_resp) ? (req_buf->query_len =
+					       cpu_to_le16(query_len))
+					: (resp_buf->query_len =
+					   cpu_to_le16(query_len));
+				break;
+			case WIFIDIRECT_DISCOVERY_SERVICE:
+				(!req_resp) ? (req_buf->request_len =
+					       cpu_to_le16(service_len))
+					: (resp_buf->response_len =
+					   cpu_to_le16(service_len));
+				break;
+			case WIFIDIRECT_DISCOVERY_VENDOR:
+				(!req_resp) ? (req_buf->vendor_len =
+					       cpu_to_le16(vendor_len))
+					: (resp_buf->vendor_len =
+					   cpu_to_le16(vendor_len));
+				break;
+			default:
+				break;
+			}
+			if (wifidirect_level) {
+				if (wifidirect_level ==
+				    WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE)
+					break;
+				wifidirect_level--;
+			}
+		}
+	}
+	/* Send collective command */
+	wifidirect_ioctl((t_u8 *)buffer, &cmd_len, cmd_len);
+done:
+	fclose(config_file);
+	if (buffer)
+		free(buffer);
+	if (line)
+		free(line);
+}
+
+/**
+ *  @brief Show usage information for the wifidirect_config command
+ *
+ *  $return         N/A
+ */
+static void
+print_wifidirect_config_usage(void)
+{
+	printf("\nUsage : wifidirect_config [CONFIG_FILE]\n");
+	printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n");
+	printf("CONFIG_FILE contains all WIFIDIRECT parameters.\n");
+	return;
+}
+
+/**
+ *  @brief Read the wifidirect parameters and sends to the driver
+ *
+ *  @param file_name File to open for configuration parameters.
+ *  @param cmd_name  Command Name for which parameters are read.
+ *  @param pbuf      Pointer to output buffer
+ *  @param ie_len_wifidirect Length of wifidirect parameters to return
+ *  @param ie_len_wps Length of WPS parameters to return
+ *  @return          SUCCESS or FAILURE
+ */
+static const t_u8 wifidirect_oui[] = { 0x50, 0x6F, 0x9A, 0x09 };
+static const t_u8 wps_oui[] = { 0x00, 0x50, 0xF2, 0x04 };
+
+static void
+wifidirect_file_params_config(char *file_name, char *cmd_name, t_u8 *pbuf,
+			      t_u16 *ie_len_wifidirect, t_u16 *ie_len_wps)
+{
+	FILE *config_file = NULL;
+	char *line = NULL;
+	int i = 0, li = 0, arg_num = 0, ret = 0, wifidirect_level =
+		0, no_of_chan_entries = 0, no_of_noa = 0;
+	int secondary_index = -1, flag = 1, group_secondary_index = -1;
+	char **args = NULL;
+	char *pos = NULL;
+	char wifidirect_mac[20], country[4], wifidirect_ssid[33];
+	char WPS_manufacturer[33], WPS_modelname[33], WPS_devicename[33],
+		wifi_group_direct_ssid[33];
+	t_u8 dev_channels[MAX_CHANNELS];
+	t_u8 iface_list[ETH_ALEN * MAX_INTERFACE_ADDR_COUNT];
+	t_u8 dev_address[ETH_ALEN];
+	t_u8 group_dev_address[ETH_ALEN];
+	t_u8 *extra = NULL;
+	t_u8 *buffer = pbuf;
+	t_u16 cmd_len_wifidirect = 0, cmd_len_wps = 0, tlv_len = 0, extra_len =
+		0, temp = 0;
+	t_u16 wps_model_len = 0, wps_serial_len = 0, wps_vendor_len = 0;
+	t_u16 pri_category = 0, pri_sub_category = 0, config_methods = 0;
+	t_u16 sec_category = 0, sec_sub_category = 0, group_sec_sub_category =
+		0, group_sec_category = 0;
+	t_u16 avail_period = 0, avail_interval = 0;
+	t_u8 secondary_oui[4], group_secondary_oui[4];
+	t_u16 WPS_specconfigmethods = 0, WPS_associationstate = 0,
+		WPS_configurationerror = 0, WPS_devicepassword = 0;
+	t_u8 dev_capability = 0, group_capability = 0, cmd_found = 0,
+		group_owner_intent = 0, primary_oui[4], iface_count = 0,
+		regulatory_class = 0, channel_number = 0, manageability = 0,
+		op_regulatory_class = 0, op_channel_number =
+		0, invitation_flag = 0;
+	t_u8 WPS_version = 0, WPS_setupstate = 0, WPS_requesttype =
+		0, WPS_responsetype =
+		0, WPS_UUID[WPS_UUID_MAX_LEN],
+		WPS_primarydevicetype[WPS_DEVICE_TYPE_MAX_LEN], WPS_RFband =
+		0, WPS_modelnumber[32], WPS_serialnumber[32], WPS_VendorExt[32];
+	t_u8 go_config_timeout = 0, client_config_timeout = 0;
+	t_u8 secondary_dev_count = 0, group_secondary_dev_count = 0;
+	t_u16 temp16 = 0;
+	t_u8 secondary_dev_info[WPS_DEVICE_TYPE_LEN *
+				MAX_SECONDARY_DEVICE_COUNT];
+	t_u8 group_secondary_dev_info[WPS_DEVICE_TYPE_LEN *
+				      MAX_GROUP_SECONDARY_DEVICE_COUNT];
+	t_u8 wifidirect_client_dev_count = 0, wifidirect_client_dev_index =
+		0, temp8 = 0;
+	wifidirect_client_dev_info
+		wifidirect_client_dev_info_list[MAX_SECONDARY_DEVICE_COUNT];
+	t_u8 wifidirect_total_secondary_dev_count = 0;
+	t_u8 wifidirect_group_total_ssid_len = 0, tlv_offset =
+		0, temp_dev_size = 0;
+	t_u8 noa_index = 0, opp_ps = 0, ctwindow_opp_ps = 0, count_type = 0;
+	t_u32 duration = 0, interval = 0, start_time = 0;
+	t_u16 total_chan_len = 0;
+	t_u8 chan_entry_regulatory_class = 0, chan_entry_num_of_channels = 0;
+	t_u8 *chan_entry_list = NULL;
+	t_u8 *chan_buf = NULL;
+	noa_descriptor noa_descriptor_list[MAX_NOA_DESCRIPTORS];
+	/* Check if file exists */
+	config_file = fopen(file_name, "r");
+	if (config_file == NULL) {
+		printf("\nERR:Config file can not open.\n");
+		return;
+	}
+
+	/* Memory allocations */
+	line = (char *)malloc(MAX_CONFIG_LINE);
+	if (!line) {
+		printf("ERR:Cannot allocate memory for line\n");
+		goto done;
+	}
+	memset(line, 0, MAX_CONFIG_LINE);
+
+	extra = (t_u8 *)malloc(MAX_CONFIG_LINE);
+	if (!extra) {
+		printf("ERR:Cannot allocate memory for extra\n");
+		goto done;
+	}
+	memset(extra, 0, MAX_CONFIG_LINE);
+
+	args = (char **)malloc(sizeof(char *) * MAX_ARGS_NUM);
+	if (!args) {
+		printf("ERR:Cannot allocate memory for args\n");
+		goto done;
+	}
+	memset(args, 0, (sizeof(char *) * MAX_ARGS_NUM));
+
+	if (!wifidir_use_fixed_ie_indices()) {
+		special_mask_custom_ie_buf *wifidirect_ie_buf;
+		wifidirect_ie_buf = (special_mask_custom_ie_buf *)buffer;
+		memcpy(&wifidirect_ie_buf->Oui[0], wifidirect_oui,
+		       sizeof(wifidirect_oui));
+		cmd_len_wifidirect += sizeof(wifidirect_oui);
+	}
+	/* Parse file and process */
+	while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+		arg_num = parse_line(line, args);
+		if (!cmd_found && strncmp(args[0], cmd_name, strlen(args[0])))
+			continue;
+		cmd_found = 1;
+		if (strcmp(args[0], "wifidirect_config") == 0) {
+			wifidirect_level = WIFIDIRECT_PARAMS_CONFIG;
+		} else if (strcmp(args[0], "Capability") == 0) {
+			wifidirect_level = WIFIDIRECT_CAPABILITY_CONFIG;
+		} else if (strcmp(args[0], "GroupOwnerIntent") == 0) {
+			wifidirect_level = WIFIDIRECT_GROUP_OWNER_INTENT_CONFIG;
+		} else if (strcmp(args[0], "Channel") == 0) {
+			wifidirect_level = WIFIDIRECT_CHANNEL_CONFIG;
+		} else if (strcmp(args[0], "OperatingChannel") == 0) {
+			wifidirect_level = WIFIDIRECT_OPCHANNEL_CONFIG;
+		} else if (strcmp(args[0], "InfrastructureManageabilityInfo") ==
+			   0) {
+			wifidirect_level = WIFIDIRECT_MANAGEABILITY_CONFIG;
+		} else if (strcmp(args[0], "InvitationFlagBitmap") == 0) {
+			wifidirect_level = WIFIDIRECT_INVITATION_FLAG_CONFIG;
+		} else if (strcmp(args[0], "ChannelList") == 0) {
+			wifidirect_level = WIFIDIRECT_CHANNEL_LIST_CONFIG;
+		} else if (strcmp(args[0], "NoticeOfAbsence") == 0) {
+			wifidirect_level = WIFIDIRECT_NOTICE_OF_ABSENCE;
+		} else if (strcmp(args[0], "NoA_descriptor") == 0) {
+			wifidirect_level = WIFIDIRECT_NOA_DESCRIPTOR;
+		} else if (strcmp(args[0], "DeviceInfo") == 0) {
+			wifidirect_level = WIFIDIRECT_DEVICE_INFO_CONFIG;
+		} else if (strcmp(args[0], "SecondaryDeviceType") == 0) {
+			wifidirect_level = WIFIDIRECT_DEVICE_SEC_INFO_CONFIG;
+		} else if (strcmp(args[0], "GroupInfo") == 0) {
+			wifidirect_level = WIFIDIRECT_GROUP_INFO_CONFIG;
+		} else if (strcmp(args[0], "GroupSecondaryDeviceTypes") == 0) {
+			wifidirect_level = WIFIDIRECT_GROUP_SEC_INFO_CONFIG;
+		} else if (strcmp(args[0], "GroupWifiDirectDeviceTypes") == 0) {
+			wifidirect_level = WIFIDIRECT_GROUP_CLIENT_INFO_CONFIG;
+		} else if (strcmp(args[0], "GroupId") == 0) {
+			wifidirect_level = WIFIDIRECT_GROUP_ID_CONFIG;
+		} else if (strcmp(args[0], "GroupBSSId") == 0) {
+			wifidirect_level = WIFIDIRECT_GROUP_BSS_ID_CONFIG;
+		} else if (strcmp(args[0], "DeviceId") == 0) {
+			wifidirect_level = WIFIDIRECT_DEVICE_ID_CONFIG;
+		} else if (strcmp(args[0], "Interface") == 0) {
+			wifidirect_level = WIFIDIRECT_INTERFACE_CONFIG;
+		} else if (strcmp(args[0], "ConfigurationTimeout") == 0) {
+			wifidirect_level = WIFIDIRECT_TIMEOUT_CONFIG;
+		} else if (strcmp(args[0], "ExtendedListenTime") == 0) {
+			wifidirect_level = WIFIDIRECT_EXTENDED_TIME_CONFIG;
+		} else if (strcmp(args[0], "IntendedIntfAddress") == 0) {
+			wifidirect_level = WIFIDIRECT_INTENDED_ADDR_CONFIG;
+		} else if (strcmp(args[0], "WPSIE") == 0) {
+			wifidirect_level = WIFIDIRECT_WPSIE;
+		} else if (strcmp(args[0], "Extra") == 0) {
+			wifidirect_level = WIFIDIRECT_EXTRA;
+		} else if (strcmp(args[0], "WIFIDIRECT_MAC") == 0 ||
+			   strcmp(args[0], "GroupAddr") == 0 ||
+			   strcmp(args[0], "GroupBssId") == 0 ||
+			   strcmp(args[0], "InterfaceAddress") == 0 ||
+			   strcmp(args[0], "GroupInterfaceAddress") == 0 ||
+			   strcmp(args[0], "DeviceAddress") == 0) {
+			strncpy(wifidirect_mac, args[1], 20 - 1);
+			if ((ret =
+			     mac2raw(wifidirect_mac, dev_address)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+		} else if (strncmp(args[0], "GroupWifiDirectDeviceAddress", 21)
+			   == 0) {
+			strncpy(wifidirect_mac, args[1], 20 - 1);
+			if ((ret =
+			     mac2raw(wifidirect_mac,
+				     group_dev_address)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+			wifidirect_client_dev_index++;
+			if (wifidirect_client_dev_index >
+			    wifidirect_client_dev_count) {
+				printf("ERR: No of Client Dev count is less than no of client dev configs!!\n");
+				goto done;
+			}
+			group_secondary_index = 0;
+			tlv_offset =
+				wifidirect_group_total_ssid_len +
+				wifidirect_total_secondary_dev_count *
+				WPS_DEVICE_TYPE_LEN;
+			memcpy(wifidirect_client_dev_info_list
+			       [wifidirect_client_dev_index -
+				1].wifidirect_dev_address + tlv_offset,
+			       group_dev_address, ETH_ALEN);
+		} else if (strncmp(args[0], "GroupWifiDirectIntfAddress", 19) ==
+			   0) {
+			strncpy(wifidirect_mac, args[1], 20 - 1);
+			if ((ret =
+			     mac2raw(wifidirect_mac,
+				     group_dev_address)) != SUCCESS) {
+				printf("ERR: %s Address \n",
+				       ret == FAILURE ? "Invalid MAC" : ret ==
+				       WIFIDIRECT_RET_MAC_BROADCAST ?
+				       "Broadcast" : "Multicast");
+				goto done;
+			}
+			memcpy(wifidirect_client_dev_info_list
+			       [wifidirect_client_dev_index -
+				1].wifidirect_intf_address + tlv_offset,
+			       group_dev_address, ETH_ALEN);
+		} else if (strncmp(args[0], "GroupWifiDirectDeviceCapab", 19) ==
+			   0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DEVICECAPABILITY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			temp8 = (t_u8)atoi(args[1]);
+			memcpy(&wifidirect_client_dev_info_list
+			       [wifidirect_client_dev_index -
+				1].wifidirect_dev_capability + tlv_offset,
+			       &temp8, sizeof(temp8));
+		} else if (strncmp
+			   (args[0], "GroupWifiDirectWPSConfigMethods",
+			    24) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSCONFMETHODS, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			temp16 = (t_u16)A2HEXDECIMAL(args[1]);
+			memcpy(&wifidirect_client_dev_info_list
+			       [wifidirect_client_dev_index -
+				1].config_methods + tlv_offset, &temp16,
+			       sizeof(temp16));
+			(t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strncmp
+			   (args[0], "GroupPrimaryDeviceTypeCategory",
+			    30) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPECATEGORY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			pri_category = (t_u16)atoi(args[1]);
+			temp16 = htons(pri_category);
+			memcpy(&wifidirect_client_dev_info_list
+			       [wifidirect_client_dev_index -
+				1].primary_category + tlv_offset, &temp16,
+			       sizeof(temp16));
+		} else if (strncmp(args[0], "GroupPrimaryDeviceTypeOUI", 25) ==
+			   0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPEOUI, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < 4; i++) {
+				temp8 = (t_u8)A2HEXDECIMAL(args[i + 1]);
+				memcpy(&wifidirect_client_dev_info_list
+				       [wifidirect_client_dev_index -
+					1].primary_oui[i]
+				       + tlv_offset, &temp8, sizeof(temp8));
+			}
+		} else if (strncmp
+			   (args[0], "GroupPrimaryDeviceTypeSubCategory",
+			    33) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPESUBCATEGORY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			pri_sub_category = (t_u16)atoi(args[1]);
+			temp16 = htons(pri_sub_category);
+			memcpy(&wifidirect_client_dev_info_list
+			       [wifidirect_client_dev_index -
+				1].primary_subcategory + tlv_offset, &temp16,
+			       sizeof(temp16));
+		} else if (strncmp(args[0], "GroupSecondaryDeviceCount", 25) ==
+			   0) {
+			if (is_input_valid
+			    (WIFIDIRECT_GROUP_SECONDARYDEVCOUNT, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			group_secondary_dev_count = (t_u8)atoi(args[1]);
+			memcpy(&wifidirect_client_dev_info_list
+			       [wifidirect_client_dev_index -
+				1].wifidirect_secondary_dev_count + tlv_offset,
+			       &group_secondary_dev_count,
+			       sizeof(group_secondary_dev_count));
+			wifidirect_total_secondary_dev_count +=
+				group_secondary_dev_count;
+			if (group_secondary_dev_count)
+				memset(group_secondary_dev_info, 0,
+				       sizeof(group_secondary_dev_info));
+		} else if (strncmp
+			   (args[0], "GroupSecondaryDeviceTypeCategory",
+			    30) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPECATEGORY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			sec_category = (t_u16)atoi(args[1]);
+			group_sec_category = cpu_to_le16(sec_category);
+			group_secondary_index++;
+		} else if (strncmp(args[0], "GroupSecondaryDeviceTypeOUI", 27)
+			   == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPEOUI, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < 4; i++)
+				group_secondary_oui[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strncmp
+			   (args[0], "GroupSecondaryDeviceTypeSubCategory",
+			    35) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPESUBCATEGORY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			if (group_secondary_index < 0 ||
+			    group_secondary_index >=
+			    MAX_SECONDARY_DEVICE_COUNT) {
+				printf("Error in configuration file %s:%d",
+				       file_name, li);
+				goto done;
+			}
+			sec_sub_category = (t_u16)atoi(args[1]);
+			group_sec_sub_category =
+				cpu_to_le16(group_sec_sub_category);
+			if (group_secondary_dev_count) {
+				memcpy(&group_secondary_dev_info
+				       [(group_secondary_index -
+					 1) * WPS_DEVICE_TYPE_LEN],
+				       &group_sec_category, sizeof(t_u16));
+				memcpy(&group_secondary_dev_info
+				       [((group_secondary_index -
+					  1) * WPS_DEVICE_TYPE_LEN) + 2],
+				       group_secondary_oui,
+				       sizeof(secondary_oui));
+				memcpy(&group_secondary_dev_info
+				       [((group_secondary_index -
+					  1) * WPS_DEVICE_TYPE_LEN) + 6],
+				       &group_sec_sub_category, sizeof(t_u16));
+			}
+
+		} else if (strncmp(args[0], "GroupWifiDirectDeviceCount", 19) ==
+			   0) {
+			if (is_input_valid
+			    (WIFIDIRECT_SECONDARYDEVCOUNT, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			wifidirect_client_dev_count = (t_u8)atoi(args[1]);
+		} else if (strncmp(args[0], "GroupWifiDirectDeviceName", 18) ==
+			   0) {
+
+			if (is_input_valid
+			    (WIFIDIRECT_GROUP_WIFIDIRECT_DEVICE_NAME,
+			     arg_num - 1, args + 1) != SUCCESS) {
+				goto done;
+			}
+
+			strncpy(wifi_group_direct_ssid, args[1] + 1,
+				strlen(args[1]) - 2);
+			wifi_group_direct_ssid[strlen(args[1]) - 2] = '\0';
+			temp = htons(SC_Device_Name);
+			memcpy(((t_u8 *)
+				&wifidirect_client_dev_info_list
+				[wifidirect_client_dev_index -
+				 1].wifidirect_device_name_type + tlv_offset),
+			       &temp, sizeof(temp));
+			temp = htons(strlen(wifi_group_direct_ssid));
+			memcpy(((t_u8 *)
+				&wifidirect_client_dev_info_list
+				[wifidirect_client_dev_index -
+				 1].wifidirect_device_name_len + tlv_offset),
+			       &temp, sizeof(temp));
+			memset(((t_u8 *)
+				&wifidirect_client_dev_info_list
+				[wifidirect_client_dev_index -
+				 1].wifidirect_device_name + tlv_offset), 0,
+			       strlen(wifi_group_direct_ssid));
+			memcpy(((t_u8 *)
+				&wifidirect_client_dev_info_list
+				[wifidirect_client_dev_index -
+				 1].wifidirect_device_name + tlv_offset),
+			       &wifi_group_direct_ssid,
+			       strlen(wifi_group_direct_ssid));
+			wifidirect_group_total_ssid_len +=
+				strlen(wifi_group_direct_ssid);
+
+			if (wifidirect_client_dev_index - 1) {
+				temp_dev_size =
+					sizeof(wifidirect_client_dev_info) +
+					strlen(wifi_group_direct_ssid) +
+					group_secondary_dev_count *
+					WPS_DEVICE_TYPE_LEN;
+				memcpy(&wifidirect_client_dev_info_list
+				       [wifidirect_client_dev_index -
+					1].dev_length + (tlv_offset -
+							 (group_secondary_dev_count
+							  *
+							  WPS_DEVICE_TYPE_LEN)),
+				       &temp_dev_size, sizeof(temp_dev_size));
+			} else {
+
+				temp_dev_size =
+					sizeof(wifidirect_client_dev_info) +
+					strlen(wifi_group_direct_ssid) +
+					group_secondary_dev_count *
+					WPS_DEVICE_TYPE_LEN;
+				wifidirect_client_dev_info_list
+					[wifidirect_client_dev_index -
+					 1].dev_length =
+					sizeof(wifidirect_client_dev_info) +
+					strlen(wifi_group_direct_ssid) +
+					group_secondary_dev_count *
+					WPS_DEVICE_TYPE_LEN;
+			}
+		} else if (strcmp(args[0], "DeviceCapability") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DEVICECAPABILITY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			dev_capability = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "GroupCapability") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_GROUPCAPABILITY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			group_capability = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "Intent") == 0) {
+			/* Intent -> 0 - 15 */
+			if (is_input_valid
+			    (WIFIDIRECT_INTENT, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			group_owner_intent = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "RegulatoryClass") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_REGULATORYCLASS, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			regulatory_class = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "ChannelNumber") == 0) {
+			if (is_input_valid(CHANNEL, arg_num - 1, args + 1) !=
+			    SUCCESS) {
+				goto done;
+			}
+			channel_number = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "OpRegulatoryClass") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_REGULATORYCLASS, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			op_regulatory_class = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "OpChannelNumber") == 0) {
+			if (is_input_valid(CHANNEL, arg_num - 1, args + 1) !=
+			    SUCCESS) {
+				goto done;
+			}
+			op_channel_number = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "Manageability") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_MANAGEABILITY, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			manageability = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "InvitationFlag") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_INVITATIONFLAG, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			invitation_flag = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "CountryString") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_COUNTRY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			strncpy(country, args[1] + 1, 3);
+			country[strlen(args[1]) - 2] = '\0';
+		} else if (strncmp(args[0], "Regulatory_Class_", 17) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_REGULATORYCLASS, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			if (!no_of_chan_entries) {
+				chan_entry_list =
+					(t_u8 *)malloc(MAX_BUFFER_SIZE);
+				if (!chan_entry_list) {
+					printf("ERR:cannot allocate memory for chan_entry_list!\n");
+					goto done;
+				}
+				memset(chan_entry_list, 0, MAX_BUFFER_SIZE);
+				chan_buf = chan_entry_list;
+			}
+			no_of_chan_entries++;
+			chan_entry_regulatory_class = (t_u8)atoi(args[1]);
+		} else if (strncmp(args[0], "NumofChannels", 13) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_NO_OF_CHANNELS, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			chan_entry_num_of_channels = (t_u8)atoi(args[1]);
+		} else if (strncmp(args[0], "ChanList", 8) == 0) {
+			if (chan_entry_num_of_channels != (arg_num - 1)) {
+				printf("ERR:no of channels in ChanList and NumofChannels do not match!\n");
+				goto done;
+			}
+			if (is_input_valid(SCANCHANNELS, arg_num - 1, args + 1)
+			    != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < chan_entry_num_of_channels; i++)
+				dev_channels[i] = (t_u8)atoi(args[i + 1]);
+			total_chan_len += chan_entry_num_of_channels;
+			memcpy(chan_buf, &chan_entry_regulatory_class,
+			       sizeof(t_u8));
+			memcpy(chan_buf + 1, &chan_entry_num_of_channels,
+			       sizeof(t_u8));
+			memcpy(chan_buf + 2, dev_channels,
+			       chan_entry_num_of_channels);
+			chan_buf +=
+				sizeof(t_u8) + sizeof(t_u8) +
+				chan_entry_num_of_channels;
+		} else if (strcmp(args[0], "NoA_Index") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_NOA_INDEX, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			noa_index = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "OppPS") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_OPP_PS, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			opp_ps = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "CTWindow") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_CTWINDOW, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			if ((opp_ps != 0) && (atoi(args[1]) < 10)) {
+				printf("ERR: CTwindow should be greater than or equal to 10 if opp_ps is set!\n");
+				goto done;
+			}
+			ctwindow_opp_ps =
+				(t_u8)atoi(args[1]) | SET_OPP_PS(opp_ps);
+		} else if (strncmp(args[0], "CountType", 9) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_COUNT_TYPE, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			no_of_noa++;
+			if (no_of_noa > MAX_NOA_DESCRIPTORS) {
+				printf("Number of descriptors should not be greater than %d\n", MAX_NOA_DESCRIPTORS);
+				goto done;
+			}
+			count_type = (t_u8)atoi(args[1]);
+			noa_descriptor_list[no_of_noa - 1].count_type =
+				count_type;
+		} else if (strncmp(args[0], "Duration", 8) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_DURATION, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			duration = (t_u32)atoi(args[1]);
+			duration = cpu_to_le32(duration);
+			noa_descriptor_list[no_of_noa - 1].duration = duration;
+		} else if (strncmp(args[0], "Interval", 8) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_INTERVAL, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			interval = (t_u32)atoi(args[1]);
+			interval = cpu_to_le32(interval);
+			noa_descriptor_list[no_of_noa - 1].interval = interval;
+		} else if (strncmp(args[0], "StartTime", 9) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_START_TIME, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			start_time = (t_u32)atoi(args[1]);
+			start_time = cpu_to_le32(start_time);
+			noa_descriptor_list[no_of_noa - 1].start_time =
+				start_time;
+		} else if (strcmp(args[0], "PrimaryDeviceTypeCategory") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPECATEGORY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			pri_category = (t_u16)atoi(args[1]);
+		} else if (strcmp(args[0], "PrimaryDeviceTypeOUI") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPEOUI, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < 4; i++)
+				primary_oui[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "PrimaryDeviceTypeSubCategory") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPESUBCATEGORY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			pri_sub_category = (t_u16)atoi(args[1]);
+		} else if (strcmp(args[0], "SecondaryDeviceCount") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_SECONDARYDEVCOUNT, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			secondary_dev_count = (t_u8)atoi(args[1]);
+			if (secondary_dev_count)
+				memset(secondary_dev_info, 0,
+				       sizeof(secondary_dev_info));
+		} else if (strncmp(args[0], "SecondaryDeviceTypeCategory", 27)
+			   == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPECATEGORY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			sec_category = (t_u16)atoi(args[1]);
+			sec_category = htons(sec_category);
+			secondary_index++;
+		} else if (strncmp(args[0], "SecondaryDeviceTypeOUI", 22) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPEOUI, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < 4; i++)
+				secondary_oui[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strncmp
+			   (args[0], "SecondaryDeviceTypeSubCategory",
+			    30) == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_PRIDEVTYPESUBCATEGORY, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			if (secondary_index < 0 ||
+			    secondary_index >= MAX_SECONDARY_DEVICE_COUNT) {
+				printf("Error in configuration file %s:%d",
+				       file_name, li);
+				goto done;
+			}
+			sec_sub_category = (t_u16)atoi(args[1]);
+			sec_sub_category = htons(sec_sub_category);
+			if (secondary_dev_count) {
+				memcpy(&secondary_dev_info
+				       [secondary_index * WPS_DEVICE_TYPE_LEN],
+				       &sec_category, sizeof(t_u16));
+				memcpy(&secondary_dev_info
+				       [(secondary_index *
+					 WPS_DEVICE_TYPE_LEN) + 2],
+				       secondary_oui, sizeof(secondary_oui));
+				memcpy(&secondary_dev_info
+				       [(secondary_index *
+					 WPS_DEVICE_TYPE_LEN) + 6],
+				       &sec_sub_category, sizeof(t_u16));
+			}
+		} else if (strcmp(args[0], "InterfaceAddressCount") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_INTERFACECOUNT, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			iface_count = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "InterfaceAddressList") == 0) {
+			if (iface_count != (arg_num - 1)) {
+				printf("Incorrect address list for %d entries.\n", iface_count);
+				goto done;
+			}
+			for (i = 0;
+			     i < iface_count && i < MAX_INTERFACE_ADDR_COUNT;
+			     i++) {
+				if ((ret =
+				     mac2raw(args[i + 1],
+					     &iface_list[i * ETH_ALEN])) !=
+				    SUCCESS) {
+					printf("ERR: %s Address \n",
+					       ret ==
+					       FAILURE ? "Invalid MAC" : ret ==
+					       WIFIDIRECT_RET_MAC_BROADCAST ?
+					       "Broadcast" : "Multicast");
+					goto done;
+				}
+			}
+		} else if (strcmp(args[0], "GroupConfigurationTimeout") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_ATTR_CONFIG_TIMEOUT, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			go_config_timeout = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "ClientConfigurationTimeout") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_ATTR_CONFIG_TIMEOUT, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			client_config_timeout = (t_u8)atoi(args[1]);
+		} else if (strcmp(args[0], "AvailabilityPeriod") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_ATTR_EXTENDED_TIME, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			avail_period = (t_u16)atoi(args[1]);
+		} else if (strcmp(args[0], "AvailabilityInterval") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_ATTR_EXTENDED_TIME, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			avail_interval = (t_u16)atoi(args[1]);
+		} else if (strcmp(args[0], "WPSConfigMethods") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSCONFMETHODS, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			config_methods = (t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "DeviceName") == 0 ||
+			   strcmp(args[0], "GroupSsId") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSDEVICENAME, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			memset(wifidirect_ssid, 0, sizeof(wifidirect_ssid));
+			strncpy(wifidirect_ssid, args[1],
+				sizeof(wifidirect_ssid) - 1);
+		} else if (strcmp(args[0], "WPSVersion") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSVERSION, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			WPS_version = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "WPSSetupState") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSSETUPSTATE, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			WPS_setupstate = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "WPSDeviceName") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSDEVICENAME, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			memset(WPS_devicename, 0, sizeof(WPS_devicename));
+			strncpy(WPS_devicename, args[1],
+				sizeof(WPS_devicename) - 1);
+		} else if (strcmp(args[0], "WPSRequestType") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSREQRESPTYPE, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			WPS_requesttype = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "WPSResponseType") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSREQRESPTYPE, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			WPS_responsetype = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "WPSSpecConfigMethods") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSSPECCONFMETHODS, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			WPS_specconfigmethods = (t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "WPSUUID") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSUUID, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < WPS_UUID_MAX_LEN; i++)
+				WPS_UUID[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "WPSPrimaryDeviceType") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSPRIMARYDEVICETYPE, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < WPS_DEVICE_TYPE_MAX_LEN; i++)
+				WPS_primarydevicetype[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+		} else if (strcmp(args[0], "WPSRFBand") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSRFBAND, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			WPS_RFband = (t_u8)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "WPSAssociationState") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSASSOCIATIONSTATE, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			WPS_associationstate = (t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "WPSConfigurationError") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSCONFIGURATIONERROR, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			WPS_configurationerror = (t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "WPSDevicePassword") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSDEVICEPASSWORD, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			WPS_devicepassword = (t_u16)A2HEXDECIMAL(args[1]);
+		} else if (strcmp(args[0], "WPSManufacturer") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSMANUFACTURER, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			memset(WPS_manufacturer, 0, sizeof(WPS_manufacturer));
+			strncpy(WPS_manufacturer, args[1],
+				sizeof(WPS_manufacturer));
+		} else if (strcmp(args[0], "WPSModelName") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSMODELNAME, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			memset(WPS_modelname, 0, sizeof(WPS_modelname));
+			strncpy(WPS_modelname, args[1], sizeof(WPS_modelname));
+		} else if (strcmp(args[0], "WPSModelNumber") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSMODELNUMBER, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < arg_num - 1; i++)
+				WPS_modelnumber[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			wps_model_len = arg_num - 1;
+		} else if (strcmp(args[0], "WPSSerialNumber") == 0) {
+			if (is_input_valid
+			    (WIFIDIRECT_WPSSERIALNUMBER, arg_num - 1,
+			     args + 1) != SUCCESS) {
+				goto done;
+			}
+			for (i = 0; i < arg_num - 1; i++)
+				WPS_serialnumber[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			wps_serial_len = arg_num - 1;
+		} else if (strcmp(args[0], "WPSVendorExtension") == 0) {
+			for (i = 0; i < arg_num - 1; i++)
+				WPS_VendorExt[i] =
+					(t_u8)A2HEXDECIMAL(args[i + 1]);
+			wps_vendor_len = arg_num - 1;
+		} else if (strcmp(args[0], "Buffer") == 0) {
+			for (i = 0; i < arg_num - 1; i++)
+				extra[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
+			extra_len = arg_num - 1;
+		} else if (strcmp(args[0], "}") == 0) {
+			/* Based on level, populate appropriate struct */
+			switch (wifidirect_level) {
+			case WIFIDIRECT_DEVICE_ID_CONFIG:
+				{
+					tlvbuf_wifidirect_device_id *tlv = NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_device_id);
+					tlv = (tlvbuf_wifidirect_device_id
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_DEVICE_ID;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					memcpy(tlv->dev_mac_address,
+					       dev_address, ETH_ALEN);
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_CAPABILITY_CONFIG:
+				{
+					tlvbuf_wifidirect_capability *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_capability);
+					tlv = (tlvbuf_wifidirect_capability
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_CAPABILITY;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					tlv->dev_capability = dev_capability;
+					tlv->group_capability =
+						group_capability;
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_GROUP_OWNER_INTENT_CONFIG:
+				{
+					tlvbuf_wifidirect_group_owner_intent
+						*tlv = NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_group_owner_intent);
+					tlv = (tlvbuf_wifidirect_group_owner_intent *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_GROUPOWNER_INTENT;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					tlv->dev_intent = group_owner_intent;
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_MANAGEABILITY_CONFIG:
+				{
+					tlvbuf_wifidirect_manageability *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_manageability);
+					tlv = (tlvbuf_wifidirect_manageability
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_MANAGEABILITY;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					tlv->manageability = manageability;
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_INVITATION_FLAG_CONFIG:
+				{
+					tlvbuf_wifidirect_invitation_flag *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_invitation_flag);
+					tlv = (tlvbuf_wifidirect_invitation_flag
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_INVITATION_FLAG;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					tlv->invitation_flag |= invitation_flag;
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_CHANNEL_LIST_CONFIG:
+				{
+					tlvbuf_wifidirect_channel_list *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_channel_list)
+						+
+						no_of_chan_entries *
+						sizeof(chan_entry) +
+						total_chan_len;
+					tlv = (tlvbuf_wifidirect_channel_list
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_CHANNEL_LIST;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					memcpy(tlv->country_string, country, 3);
+					if (tlv->country_string[2] == 0)
+						tlv->country_string[2] =
+							WIFIDIRECT_COUNTRY_LAST_BYTE;
+					memcpy(tlv->wifidirect_chan_entry_list,
+					       chan_entry_list,
+					       (tlv->length - 3));
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_NOTICE_OF_ABSENCE:
+				{
+					tlvbuf_wifidirect_notice_of_absence *tlv
+						= NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_notice_of_absence)
+						+
+						no_of_noa *
+						sizeof(noa_descriptor);
+					tlv = (tlvbuf_wifidirect_notice_of_absence *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_NOTICE_OF_ABSENCE;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					tlv->noa_index = noa_index;
+					tlv->ctwindow_opp_ps = ctwindow_opp_ps;
+					memcpy(tlv->
+					       wifidirect_noa_descriptor_list,
+					       noa_descriptor_list,
+					       no_of_noa *
+					       sizeof(noa_descriptor));
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					flag = 1;
+					break;
+				}
+			case WIFIDIRECT_NOA_DESCRIPTOR:
+				{
+					wifidirect_level =
+						WIFIDIRECT_NOTICE_OF_ABSENCE;
+					flag = 0;
+					break;
+				}
+			case WIFIDIRECT_CHANNEL_CONFIG:
+				{
+					tlvbuf_wifidirect_channel *tlv = NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_channel);
+					tlv = (tlvbuf_wifidirect_channel
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag = TLV_TYPE_WIFIDIRECT_CHANNEL;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					memcpy(tlv->country_string, country, 3);
+					if (tlv->country_string[2] == 0)
+						tlv->country_string[2] =
+							WIFIDIRECT_COUNTRY_LAST_BYTE;
+					tlv->regulatory_class =
+						regulatory_class;
+					tlv->channel_number = channel_number;
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_OPCHANNEL_CONFIG:
+				{
+					tlvbuf_wifidirect_channel *tlv = NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_channel);
+					tlv = (tlvbuf_wifidirect_channel
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_OPCHANNEL;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					memcpy(tlv->country_string, country, 3);
+					if (tlv->country_string[2] == 0)
+						tlv->country_string[2] =
+							WIFIDIRECT_COUNTRY_LAST_BYTE;
+					tlv->regulatory_class =
+						op_regulatory_class;
+					tlv->channel_number = op_channel_number;
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+
+			case WIFIDIRECT_DEVICE_INFO_CONFIG:
+				{
+					tlvbuf_wifidirect_device_info *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_device_info)
+						+
+						secondary_dev_count *
+						WPS_DEVICE_TYPE_LEN +
+						strlen(wifidirect_ssid);
+					tlv = (tlvbuf_wifidirect_device_info
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_DEVICE_INFO;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					memcpy(tlv->dev_address, dev_address,
+					       ETH_ALEN);
+					tlv->config_methods =
+						htons(config_methods);
+					tlv->primary_category =
+						htons(pri_category);
+					memcpy(tlv->primary_oui, primary_oui,
+					       4);
+					tlv->primary_subcategory =
+						htons(pri_sub_category);
+					tlv->secondary_dev_count =
+						secondary_dev_count;
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					/* Parameters within secondary_dev_info are already htons'ed */
+					memcpy(tlv->secondary_dev_info,
+					       secondary_dev_info,
+					       secondary_dev_count *
+					       WPS_DEVICE_TYPE_LEN);
+					temp = htons(SC_Device_Name);
+					memcpy(((t_u8 *)(&tlv->
+							 device_name_type)) +
+					       secondary_dev_count *
+					       WPS_DEVICE_TYPE_LEN, &temp,
+					       sizeof(temp));
+					temp = htons(strlen(wifidirect_ssid));
+					memcpy(((t_u8 *)(&tlv->
+							 device_name_len)) +
+					       secondary_dev_count *
+					       WPS_DEVICE_TYPE_LEN, &temp,
+					       sizeof(temp));
+					memcpy(((t_u8 *)(&tlv->device_name)) +
+					       secondary_dev_count *
+					       WPS_DEVICE_TYPE_LEN,
+					       wifidirect_ssid,
+					       strlen(wifidirect_ssid));
+					flag = 1;
+					break;
+				}
+			case WIFIDIRECT_GROUP_INFO_CONFIG:
+				{
+					tlvbuf_wifidirect_group_info *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_offset =
+						wifidirect_group_total_ssid_len
+						+
+						wifidirect_total_secondary_dev_count
+						* WPS_DEVICE_TYPE_LEN;
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_group_info)
+						+
+						wifidirect_client_dev_count *
+						sizeof
+						(wifidirect_client_dev_info) +
+						tlv_offset;
+					tlv = (tlvbuf_wifidirect_group_info
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_GROUP_INFO;
+					tlv->length = tlv_len;
+					memcpy(tlv->wifidirect_client_dev_list,
+					       wifidirect_client_dev_info_list,
+					       wifidirect_client_dev_count *
+					       sizeof
+					       (wifidirect_client_dev_info) +
+					       tlv_offset);
+					/* Parameters within secondary_dev_info are already htons'ed */
+					//wps_hexdump(DEBUG_WLAN,"Group Info Hexdump:", (t_u8*)tlv, tlv_len);
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					flag = 1;
+					break;
+				}
+			case WIFIDIRECT_GROUP_SEC_INFO_CONFIG:
+				{
+					wifidirect_level =
+						WIFIDIRECT_GROUP_CLIENT_INFO_CONFIG;
+
+					if (wifidirect_client_dev_index &&
+					    group_secondary_index) {
+						memset(((t_u8 *)
+							&wifidirect_client_dev_info_list
+							[wifidirect_client_dev_index
+							 -
+							 1].
+							wifidirect_secondary_dev_info
+							+ tlv_offset), 0,
+						       group_secondary_index *
+						       WPS_DEVICE_TYPE_LEN);
+						memcpy(((t_u8 *)
+							&wifidirect_client_dev_info_list
+							[wifidirect_client_dev_index
+							 -
+							 1].
+							wifidirect_secondary_dev_info
+							+ tlv_offset),
+						       &group_secondary_dev_info,
+						       group_secondary_index *
+						       WPS_DEVICE_TYPE_LEN);
+					}
+					tlv_offset =
+						wifidirect_group_total_ssid_len
+						+
+						wifidirect_total_secondary_dev_count
+						* WPS_DEVICE_TYPE_LEN;
+					flag = 0;
+					break;
+				}
+			case WIFIDIRECT_GROUP_CLIENT_INFO_CONFIG:
+				{
+					wifidirect_level =
+						WIFIDIRECT_GROUP_INFO_CONFIG;
+					flag = 0;
+					break;
+				}
+			case WIFIDIRECT_DEVICE_SEC_INFO_CONFIG:
+				{
+					wifidirect_level =
+						WIFIDIRECT_DEVICE_INFO_CONFIG;
+					flag = 0;
+					break;
+				}
+			case WIFIDIRECT_GROUP_ID_CONFIG:
+				{
+					tlvbuf_wifidirect_group_id *tlv = NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_group_id) +
+						strlen(wifidirect_ssid);
+					tlv = (tlvbuf_wifidirect_group_id
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag = TLV_TYPE_WIFIDIRECT_GROUP_ID;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					memcpy(tlv->group_address, dev_address,
+					       ETH_ALEN);
+					memcpy(tlv->group_ssid, wifidirect_ssid,
+					       strlen(wifidirect_ssid));
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_GROUP_BSS_ID_CONFIG:
+				{
+					tlvbuf_wifidirect_group_bss_id *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_group_bss_id);
+					tlv = (tlvbuf_wifidirect_group_bss_id
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_GROUP_BSS_ID;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					memcpy(tlv->group_bssid, dev_address,
+					       ETH_ALEN);
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_INTERFACE_CONFIG:
+				{
+					tlvbuf_wifidirect_interface *tlv = NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_interface)
+						+ iface_count * ETH_ALEN;
+					tlv = (tlvbuf_wifidirect_interface
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_INTERFACE;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					memcpy(tlv->interface_id, dev_address,
+					       ETH_ALEN);
+					tlv->interface_count = iface_count;
+					memcpy(tlv->interface_idlist,
+					       iface_list,
+					       iface_count * ETH_ALEN);
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+
+			case WIFIDIRECT_TIMEOUT_CONFIG:
+				{
+					tlvbuf_wifidirect_config_timeout *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_config_timeout);
+					tlv = (tlvbuf_wifidirect_config_timeout
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_CONFIG_TIMEOUT;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					tlv->group_config_timeout =
+						go_config_timeout;
+					tlv->device_config_timeout =
+						client_config_timeout;
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_EXTENDED_TIME_CONFIG:
+				{
+					tlvbuf_wifidirect_ext_listen_time *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_ext_listen_time);
+					tlv = (tlvbuf_wifidirect_ext_listen_time
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_EXTENDED_LISTEN_TIME;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					tlv->availability_period =
+						le16_to_cpu(avail_period);
+					tlv->availability_interval =
+						le16_to_cpu(avail_interval);
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+			case WIFIDIRECT_INTENDED_ADDR_CONFIG:
+				{
+					tlvbuf_wifidirect_intended_addr *tlv =
+						NULL;
+					/* Append a new TLV */
+					tlv_len =
+						sizeof
+						(tlvbuf_wifidirect_intended_addr);
+					tlv = (tlvbuf_wifidirect_intended_addr
+					       *)(buffer + cmd_len_wifidirect);
+					cmd_len_wifidirect += tlv_len;
+					/* Set TLV fields */
+					tlv->tag =
+						TLV_TYPE_WIFIDIRECT_INTENDED_ADDRESS;
+					tlv->length =
+						tlv_len - (sizeof(t_u8) +
+							   sizeof(t_u16));
+					memcpy(tlv->group_address, dev_address,
+					       ETH_ALEN);
+					endian_convert_tlv_wifidirect_header_out
+						(tlv);
+					break;
+				}
+
+			case WIFIDIRECT_WPSIE:
+				{
+#ifdef DEBUG
+					/* Debug print */
+					hexdump(buffer, cmd_len_wifidirect,
+						' ');
+#endif
+					/* Append TLV for WPSVersion */
+					tlvbuf_wps_ie *tlv = NULL;
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_version);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+
+					if (!wifidir_use_fixed_ie_indices()) {
+						special_mask_custom_ie_buf
+							*wps_ie_buf;
+						wps_ie_buf =
+							(special_mask_custom_ie_buf
+							 *)tlv;
+						memcpy(&wps_ie_buf->Oui[0],
+						       wps_oui,
+						       sizeof(wps_oui));
+						cmd_len_wps += sizeof(wps_oui);
+					}
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Version;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					*(tlv->data) = WPS_version;
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSSetupState */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_setupstate);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Simple_Config_State;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					*(tlv->data) = WPS_setupstate;
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSRequestType */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_requesttype);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Request_Type;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					*(tlv->data) = WPS_requesttype;
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSResponseType */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_responsetype);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Response_Type;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					*(tlv->data) = WPS_responsetype;
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSSpecConfigMethods */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_specconfigmethods);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Config_Methods;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					temp = htons(WPS_specconfigmethods);
+					memcpy((t_u16 *)tlv->data, &temp,
+					       sizeof(temp));
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSUUID */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_UUID);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_UUID_E;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					memcpy(tlv->data, WPS_UUID,
+					       WPS_UUID_MAX_LEN);
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSPrimaryDeviceType */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_primarydevicetype);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Primary_Device_Type;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					memcpy(tlv->data, WPS_primarydevicetype,
+					       WPS_DEVICE_TYPE_MAX_LEN);
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSRFBand */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_RFband);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_RF_Band;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					*(tlv->data) = WPS_RFband;
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSAssociationState */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_associationstate);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Association_State;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					temp = htons(WPS_associationstate);
+					memcpy((t_u16 *)tlv->data, &temp,
+					       sizeof(temp));
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSConfigurationError */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_configurationerror);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Configuration_Error;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					temp = htons(WPS_configurationerror);
+					memcpy((t_u16 *)tlv->data, &temp,
+					       sizeof(temp));
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSDevicePassword */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						sizeof(WPS_devicepassword);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Device_Password_ID;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					temp = htons(WPS_devicepassword);
+					memcpy((t_u16 *)tlv->data, &temp,
+					       sizeof(temp));
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSDeviceName */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						strlen(WPS_devicename);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Device_Name;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					memcpy(tlv->data, WPS_devicename,
+					       strlen(WPS_devicename));
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSManufacturer */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						strlen(WPS_manufacturer);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Manufacturer;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					memcpy(tlv->data, WPS_manufacturer,
+					       strlen(WPS_manufacturer));
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSModelName */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						strlen(WPS_modelname);
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Model_Name;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					memcpy(tlv->data, WPS_modelname,
+					       strlen(WPS_modelname));
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSModelNumber */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						wps_model_len;
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Model_Number;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					memcpy(tlv->data, WPS_modelnumber,
+					       wps_model_len);
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSSerialNumber */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						wps_serial_len;
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Serial_Number;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					memcpy(tlv->data, WPS_serialnumber,
+					       wps_serial_len);
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+
+					/* Append TLV for WPSVendorExtension */
+					tlv_len =
+						sizeof(tlvbuf_wps_ie) +
+						wps_vendor_len;
+					tlv = (tlvbuf_wps_ie *)(buffer +
+								cmd_len_wifidirect
+								+
+								sizeof
+								(custom_ie) +
+								cmd_len_wps);
+					tlv->tag = SC_Vendor_Extension;
+					tlv->length =
+						tlv_len - 2 * sizeof(t_u16);
+					memcpy(tlv->data, WPS_VendorExt,
+					       wps_vendor_len);
+					endian_convert_tlv_wps_header_out(tlv);
+					cmd_len_wps += tlv_len;
+#ifdef DEBUG
+					/* Debug print */
+					hexdump(buffer + sizeof(custom_ie) +
+						cmd_len_wifidirect, cmd_len_wps,
+						' ');
+#endif
+					break;
+				}
+			case WIFIDIRECT_EXTRA:
+				{
+					memcpy(buffer + cmd_len_wifidirect,
+					       extra, extra_len);
+					cmd_len_wifidirect += extra_len;
+					break;
+				}
+			default:
+				*ie_len_wifidirect = cmd_len_wifidirect;
+				if (ie_len_wps)
+					*ie_len_wps = cmd_len_wps;
+				break;
+			}
+			memset(country, 0, sizeof(country));
+			if (wifidirect_level == 0)
+				cmd_found = 0;
+			if (flag)
+				wifidirect_level = 0;
+		}
+	}
+
+done:
+	fclose(config_file);
+	if (chan_entry_list)
+		free(chan_entry_list);
+	if (line)
+		free(line);
+	if (extra)
+		free(extra);
+	if (args)
+		free(args);
+	return;
+}
+
+/**
+ *  @brief Process and send ie config command
+ *  @param ie_index  A pointer to the IE buffer index
+ *  @param data_len_wifidirect  Length of WIFIDIRECT data, 0 to get, else set.
+ *  @param data_len_wps  Length of WPS data, 0 to get, else set.
+ *  @param buf      Pointer to buffer to set.
+ *  @return          SUCCESS--success, FAILURE--fail
+ */
+static int
+wifidirect_ie_config(t_u16 *ie_index, t_u16 data_len_wifidirect,
+		     t_u16 data_len_wps, t_u8 *buf)
+{
+	struct iwreq iwr;
+	t_s32 sockfd;
+	int i, ret = SUCCESS;
+	tlvbuf_custom_ie *tlv = NULL;
+	custom_ie *ie_ptr = NULL;
+
+	tlv = (tlvbuf_custom_ie *)buf;
+	tlv->tag = MRVL_MGMT_IE_LIST_TLV_ID;
+	/* Locate headers */
+	ie_ptr = (custom_ie *)(tlv->ie_data);
+
+	/* Set TLV fields : WIFIDIRECT IE parameters */
+	if (data_len_wifidirect) {
+		/* Set IE */
+#define MGMT_MASK_AUTO	0xffff
+		ie_ptr->mgmt_subtype_mask = MGMT_MASK_AUTO;
+		tlv->length = sizeof(custom_ie) + data_len_wifidirect;
+		ie_ptr->ie_length = data_len_wifidirect;
+		ie_ptr->ie_index = *ie_index;
+	} else {
+		/* Get WPS IE */
+		tlv->length = 0;
+	}
+
+	if (!wifidir_use_fixed_ie_indices()) {
+		if (*ie_index != 0xFFFF) {
+			(*ie_index)++;
+		}
+	} else {
+		(*ie_index)++;
+	}
+	/* Locate headers */
+	ie_ptr = (custom_ie *)((t_u8 *)(tlv->ie_data) + sizeof(custom_ie) +
+			       data_len_wifidirect);
+
+	/* Set WPS IE parameters */
+	if (data_len_wps) {
+		/* Set IE */
+		/* Firmware Handled IE - mask should be set to -1 */
+		ie_ptr->mgmt_subtype_mask = MGMT_MASK_AUTO;
+		tlv->length += sizeof(custom_ie) + data_len_wps;
+		ie_ptr->ie_length = data_len_wps;
+		ie_ptr->ie_index = *ie_index;
+	}
+
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, (char *)dev_name, IFNAMSIZ - 1);
+
+	iwr.u.data.pointer = (void *)buf;
+	iwr.u.data.length =
+		((2 * sizeof(custom_ie)) + sizeof(tlvbuf_custom_ie) +
+		 data_len_wifidirect + data_len_wps);
+	iwr.u.data.flags = 0;
+
+	/*
+	 * create a socket
+	 */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		printf("Cannot open socket.\n");
+		ret = FAILURE;
+		goto _exit_;
+	}
+
+	if (ioctl(sockfd, CUSTOM_IE, &iwr)) {
+		perror("ioctl[CUSTOM_IE]");
+		printf("Failed to set/get/clear the IE buffer\n");
+		ret = FAILURE;
+		close(sockfd);
+		goto _exit_;
+	}
+	close(sockfd);
+
+/** Max IE index */
+#define MAX_MGMT_IE_INDEX               12
+
+	if (!data_len_wifidirect) {
+		/* Get the IE buffer index number for MGMT_IE_LIST_TLV */
+		tlv = (tlvbuf_custom_ie *)buf;
+		*ie_index = 0xFFFF;
+		if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) {
+			ie_ptr = (custom_ie *)(tlv->ie_data);
+			for (i = 0; i < MAX_MGMT_IE_INDEX; i++) {
+				/* zero mask indicates a wps IE, return previous index */
+				if (ie_ptr->mgmt_subtype_mask == MGMT_MASK_AUTO
+				    && ie_ptr->ie_length) {
+					*ie_index = ie_ptr->ie_index;
+					break;
+				}
+				if (i < (MAX_MGMT_IE_INDEX - 1))
+					ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+							       sizeof(custom_ie)
+							       +
+							       ie_ptr->
+							       ie_length);
+			}
+		}
+		if (*ie_index == 0xFFFF) {
+			ret = FAILURE;
+		}
+	}
+_exit_:
+
+	return ret;
+}
+
+/**
+ *  @brief Creates a wifidirect_config request and sends to the driver
+ *
+ *  Usage: "Usage : wifidirect_config [CONFIG_FILE]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirectcmd_config(int argc, char *argv[])
+{
+	t_u8 *buf = NULL, *ptr, *dev_ptr, *array_ptr;
+	t_u16 ie_len_wifidirect = 0, ie_len_wps = 0, ie_len;
+	t_u16 ie_index, temp;
+	int i, opt, ret = SUCCESS;
+	tlvbuf_custom_ie *tlv = NULL;
+	custom_ie *ie_ptr = NULL;
+	t_u16 len = 0, len_wifidirect = 0;
+	t_u8 type = 0;
+	t_u16 wps_len = 0, wps_type = 0;
+
+	if (!wifidir_use_fixed_ie_indices()) {
+		ie_index = 0xFFFF;
+	} else {
+		ie_index = 0;
+	}
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_config_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR:wrong number of arguments.\n");
+		print_wifidirect_config_usage();
+		return;
+	}
+	buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buf) {
+		printf("ERR:Cannot allocate memory!\n");
+		return;
+	}
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (argc >= 3) {
+		/* Read parameters and send command to firmware */
+		wifidirect_file_params_config(argv[2], argv[1], buf
+					      + sizeof(tlvbuf_custom_ie) +
+					      sizeof(custom_ie),
+					      &ie_len_wifidirect, &ie_len_wps);
+		if (argc == 4) {
+			ie_index = atoi(argv[3]);
+			if (ie_index >= 4) {
+				printf("ERR:wrong argument %s.\n", argv[3]);
+				return;
+			}
+		}
+		if (ie_len_wifidirect > MAX_SIZE_IE_BUFFER ||
+		    ie_len_wps > MAX_SIZE_IE_BUFFER) {
+			printf("ERR:IE parameter size exceeds limit in %s.\n",
+			       argv[2]);
+			free(buf);
+			return;
+		}
+		ie_len = ie_len_wifidirect + ie_len_wps +
+			sizeof(tlvbuf_custom_ie) + (2 * sizeof(custom_ie));
+		if (ie_len >= MRVDRV_SIZE_OF_CMD_BUFFER) {
+			printf("ERR:Too much data in configuration file %s.\n",
+			       argv[2]);
+			free(buf);
+			return;
+		}
+#ifdef DEBUG
+		hexdump(buf, ie_len, ' ');
+#endif
+		ret = wifidirect_ie_config(&ie_index, ie_len_wifidirect,
+					   ie_len_wps, buf);
+		if (ret != SUCCESS) {
+			printf("ERR:Could not set wifidirect parameters\n");
+		}
+	} else {
+		ret = wifidirect_ie_config(&ie_index, 0, 0, buf);
+		/* Print response */
+		if (ret == SUCCESS && ie_index < 3) {
+			tlv = (tlvbuf_custom_ie *)buf;
+			if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) {
+				ie_ptr = (custom_ie *)(tlv->ie_data);
+				/* Goto appropriate Ie Index */
+				for (i = 0; i < ie_index; i++) {
+					ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+							       sizeof(custom_ie)
+							       +
+							       ie_ptr->
+							       ie_length);
+				}
+				ie_len_wifidirect = ie_ptr->ie_length;
+				ptr = ie_ptr->ie_buffer;
+				/* Locate headers */
+				printf("WIFIDIRECT settings:\n");
+				if (!wifidir_use_fixed_ie_indices()) {
+					while (memcmp
+					       (ptr, wifidirect_oui,
+						sizeof(wifidirect_oui))) {
+						ie_ptr = (custom_ie *)((t_u8 *)
+								       ie_ptr +
+								       sizeof
+								       (custom_ie)
+								       +
+								       ie_ptr->
+								       ie_length);
+						ie_len_wifidirect =
+							ie_ptr->ie_length;
+						ptr = ie_ptr->ie_buffer;
+					}
+					ptr += sizeof(wifidirect_oui);
+					ie_len_wifidirect -=
+						sizeof(wifidirect_oui);
+				}
+				while (ie_len_wifidirect >
+				       WIFIDIRECT_IE_HEADER_LEN) {
+					type = *ptr;
+					memcpy(&len, ptr + 1, sizeof(t_u16));
+					len = le16_to_cpu(len);
+					switch (type) {
+					case TLV_TYPE_WIFIDIRECT_DEVICE_ID:
+						{
+							tlvbuf_wifidirect_device_id
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_device_id
+								 *)ptr;
+							printf("\t Device ID - ");
+							print_mac
+								(wifidirect_tlv->
+								 dev_mac_address);
+							printf("\n");
+						}
+						break;
+
+					case TLV_TYPE_WIFIDIRECT_CAPABILITY:
+						{
+							tlvbuf_wifidirect_capability
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_capability
+								 *)ptr;
+							printf("\t Device capability = %d\n", (int)wifidirect_tlv->dev_capability);
+							printf("\t Group capability = %d\n", (int)wifidirect_tlv->group_capability);
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_GROUPOWNER_INTENT:
+						{
+							tlvbuf_wifidirect_group_owner_intent
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_group_owner_intent
+								 *)ptr;
+							printf("\t Group owner intent = %d\n", (int)wifidirect_tlv->dev_intent);
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_MANAGEABILITY:
+						{
+							tlvbuf_wifidirect_manageability
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_manageability
+								 *)ptr;
+							printf("\t Manageability = %d\n", (int)wifidirect_tlv->manageability);
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_CHANNEL_LIST:
+						{
+							tlvbuf_wifidirect_channel_list
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_channel_list
+								 *)ptr;
+							chan_entry *temp_ptr;
+							printf("\t Country String \"%c%c\"", wifidirect_tlv->country_string[0], wifidirect_tlv->country_string[1]);
+							if (isalpha
+							    (wifidirect_tlv->
+							     country_string[2]))
+								printf("\"%c\"",
+								       wifidirect_tlv->
+								       country_string
+								       [2]);
+							printf("\n");
+							temp_ptr =
+								(chan_entry *)
+								wifidirect_tlv->
+								wifidirect_chan_entry_list;
+							len_wifidirect =
+								le16_to_cpu
+								(wifidirect_tlv->
+								 length) -
+								(sizeof
+								 (tlvbuf_wifidirect_channel_list)
+								 -
+								 WIFIDIRECT_IE_HEADER_LEN);
+							if (len_wifidirect)
+								printf("\t Channel List :- \n");
+							while (len_wifidirect) {
+								printf("\t\t Regulatory_class = %d\n", (int)(temp_ptr->regulatory_class));
+								printf("\t\t No of channels = %d\n", (int)temp_ptr->num_of_channels);
+								printf("\t\t Channel list = ");
+								for (i = 0;
+								     i <
+								     temp_ptr->
+								     num_of_channels;
+								     i++) {
+									printf("%d ", *(temp_ptr->chan_list + i));
+								}
+								len_wifidirect
+									-=
+									sizeof
+									(chan_entry)
+									+
+									temp_ptr->
+									num_of_channels;
+								temp_ptr =
+									(chan_entry
+									 *)((t_u8 *)temp_ptr + sizeof(chan_entry) + temp_ptr->num_of_channels);
+								printf("\n");
+							}
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_NOTICE_OF_ABSENCE:
+						{
+							tlvbuf_wifidirect_notice_of_absence
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_notice_of_absence
+								 *)ptr;
+							noa_descriptor
+								*temp_ptr;
+							printf("\t Notice of Absence index = %d\n", (int)wifidirect_tlv->noa_index);
+							printf("\t CTWindow and opportunistic PS parameters = %d\n", (int)wifidirect_tlv->ctwindow_opp_ps);
+							temp_ptr =
+								(noa_descriptor
+								 *)
+								wifidirect_tlv->
+								wifidirect_noa_descriptor_list;
+							len_wifidirect =
+								le16_to_cpu
+								(wifidirect_tlv->
+								 length) -
+								(sizeof
+								 (tlvbuf_wifidirect_notice_of_absence)
+								 -
+								 WIFIDIRECT_IE_HEADER_LEN);
+							while (len_wifidirect) {
+								printf("\t Count or Type = %d\n", (int)temp_ptr->count_type);
+								printf("\t Duration = %dms\n", le32_to_cpu(temp_ptr->duration));
+								printf("\t Interval = %dms\n", le32_to_cpu(temp_ptr->interval));
+								printf("\t Start Time = %d\n", le32_to_cpu(temp_ptr->start_time));
+								printf("\n");
+								temp_ptr +=
+									sizeof
+									(noa_descriptor);
+								len_wifidirect
+									-=
+									sizeof
+									(noa_descriptor);
+							}
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_DEVICE_INFO:
+						{
+							tlvbuf_wifidirect_device_info
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_device_info
+								 *)ptr;
+							printf("\t Device address - ");
+							print_mac
+								(wifidirect_tlv->
+								 dev_address);
+							printf("\n");
+							/* display config_methods */
+							printf("\t Config methods - 0x%02X\n", ntohs(wifidirect_tlv->config_methods));
+							printf("\t Primary device type = %02d-%02X%02X%02X%02X-%02d\n", (int)ntohs(wifidirect_tlv->primary_category), (int)wifidirect_tlv->primary_oui[0], (int)wifidirect_tlv->primary_oui[1], (int)wifidirect_tlv->primary_oui[2], (int)wifidirect_tlv->primary_oui[3], (int)ntohs(wifidirect_tlv->primary_subcategory));
+							printf("\t Secondary Device Count = %d\n", (int)wifidirect_tlv->secondary_dev_count);
+							array_ptr =
+								wifidirect_tlv->
+								secondary_dev_info;
+							for (i = 0;
+							     i <
+							     wifidirect_tlv->
+							     secondary_dev_count;
+							     i++) {
+								memcpy(&temp,
+								       array_ptr,
+								       sizeof
+								       (t_u16));
+								printf("\t\t Secondary device type = %02d-", ntohs(temp));
+								array_ptr +=
+									sizeof
+									(temp);
+								printf("%02X%02X%02X%02X", array_ptr[0], array_ptr[1], array_ptr[2], array_ptr[3]);
+								array_ptr += 4;
+								memcpy(&temp,
+								       array_ptr,
+								       sizeof
+								       (t_u16));
+								printf("-%02d\n", ntohs(temp));
+								array_ptr +=
+									sizeof
+									(temp);
+							}
+							array_ptr =
+								wifidirect_tlv->
+								device_name +
+								wifidirect_tlv->
+								secondary_dev_count
+								*
+								WPS_DEVICE_TYPE_LEN;
+							dev_ptr =
+								(((t_u8
+								   *)
+								  (&wifidirect_tlv->
+								   device_name_len))
+								 +
+								 wifidirect_tlv->
+								 secondary_dev_count
+								 *
+								 WPS_DEVICE_TYPE_LEN);
+							if (*(t_u16 *)dev_ptr)
+								printf("\t Device Name =  ");
+							memcpy(&temp, dev_ptr,
+							       sizeof(t_u16));
+							for (i = 0;
+							     i < ntohs(temp);
+							     i++)
+								printf("%c",
+								       *array_ptr++);
+							printf("\n");
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_GROUP_INFO:
+						{
+							tlvbuf_wifidirect_group_info
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_group_info
+								 *)ptr;
+							t_u8 no_of_wifidirect_clients = 0, wifidirect_client_dev_length = 0;
+							wifidirect_client_dev_info
+								*temp_ptr;
+							temp_ptr =
+								(wifidirect_client_dev_info
+								 *)
+								wifidirect_tlv->
+								wifidirect_client_dev_list;
+							if (temp_ptr == NULL)
+								break;
+							wifidirect_client_dev_length
+								=
+								temp_ptr->
+								dev_length;
+							temp = le16_to_cpu
+								(wifidirect_tlv->
+								 length) -
+								wifidirect_client_dev_length;
+							while (temp) {
+
+								printf("\t Group WifiDirect Client Device address - ");
+								print_mac
+									(temp_ptr->
+									 wifidirect_dev_address);
+								printf("\n");
+								printf("\t Group WifiDirect Client Interface address - ");
+								print_mac
+									(temp_ptr->
+									 wifidirect_intf_address);
+								printf("\n");
+								printf("\t Group WifiDirect Client Device capability = %d\n", (int)temp_ptr->wifidirect_dev_capability);
+								printf("\t Group WifiDirect Client Config methods - 0x%02X\n", ntohs(temp_ptr->config_methods));
+								printf("\t Group WifiDirect Client Primay device type = %02d-%02X%02X%02X%02X-%02d\n", (int)ntohs(temp_ptr->primary_category), (int)temp_ptr->primary_oui[0], (int)temp_ptr->primary_oui[1], (int)temp_ptr->primary_oui[2], (int)temp_ptr->primary_oui[3], (int)ntohs(temp_ptr->primary_subcategory));
+								printf("\t Group WifiDirect Client Secondary Device Count = %d\n", (int)temp_ptr->wifidirect_secondary_dev_count);
+								array_ptr =
+									temp_ptr->
+									wifidirect_secondary_dev_info;
+								for (i = 0;
+								     i <
+								     temp_ptr->
+								     wifidirect_secondary_dev_count;
+								     i++) {
+									memcpy(&temp, array_ptr, sizeof(t_u16));
+									printf("\t Group WifiDirect Client Secondary device type = %02d-", ntohs(temp));
+									array_ptr
+										+=
+										sizeof
+										(temp);
+									printf("%02X%02X%02X%02X", array_ptr[0], array_ptr[1], array_ptr[2], array_ptr[3]);
+									array_ptr
+										+=
+										4;
+									memcpy(&temp, array_ptr, sizeof(t_u16));
+									printf("-%02d\n", ntohs(temp));
+									array_ptr
+										+=
+										sizeof
+										(temp);
+								}
+								/* display device name */
+								array_ptr =
+									temp_ptr->
+									wifidirect_device_name
+									+
+									temp_ptr->
+									wifidirect_secondary_dev_count
+									*
+									WPS_DEVICE_TYPE_LEN;
+								printf("\t Group WifiDirect Device Name =  ");
+								memcpy(&temp,
+								       (((t_u8
+									  *)
+									 (&temp_ptr->
+									  wifidirect_device_name_len))
+									+
+									temp_ptr->
+									wifidirect_secondary_dev_count
+									*
+									WPS_DEVICE_TYPE_LEN),
+								       sizeof
+								       (t_u16));
+								temp = ntohs
+									(temp);
+								for (i = 0;
+								     i < temp;
+								     i++)
+									printf("%c", *array_ptr++);
+								printf("\n");
+								temp_ptr +=
+									wifidirect_client_dev_length;
+								temp -= wifidirect_client_dev_length;
+								no_of_wifidirect_clients++;
+								if (temp_ptr)
+									wifidirect_client_dev_length
+										=
+										temp_ptr->
+										dev_length;
+							}
+							printf("\n");
+							printf("\t Group WifiDirect Client Devices count = %d\n", no_of_wifidirect_clients);
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_GROUP_ID:
+						{
+							tlvbuf_wifidirect_group_id
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_group_id
+								 *)ptr;
+							printf("\t Group address - ");
+							print_mac
+								(wifidirect_tlv->
+								 group_address);
+							printf("\n");
+							array_ptr =
+								wifidirect_tlv->
+								group_ssid;
+							printf("\t Group ssid =  ");
+							for (i = 0;
+							     (unsigned int)i <
+							     le16_to_cpu
+							     (wifidirect_tlv->
+							      length)
+							     -
+							     (sizeof
+							      (tlvbuf_wifidirect_group_id)
+							      -
+							      WIFIDIRECT_IE_HEADER_LEN);
+							     i++)
+								printf("%c",
+								       *array_ptr++);
+							printf("\n");
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_GROUP_BSS_ID:
+						{
+							tlvbuf_wifidirect_group_bss_id
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_group_bss_id
+								 *)ptr;
+							printf("\t Group BSS Id - ");
+							print_mac
+								(wifidirect_tlv->
+								 group_bssid);
+							printf("\n");
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_INTERFACE:
+						{
+							tlvbuf_wifidirect_interface
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_interface
+								 *)ptr;
+							printf("\t Interface Id - ");
+							print_mac
+								(wifidirect_tlv->
+								 interface_id);
+							printf("\t Interface count = %d", (int)wifidirect_tlv->interface_count);
+							for (i = 0;
+							     i <
+							     wifidirect_tlv->
+							     interface_count;
+							     i++) {
+								printf("\n\t Interface address [%d]", i + 1);
+								print_mac
+									(&wifidirect_tlv->
+									 interface_idlist
+									 [i *
+									  ETH_ALEN]);
+							}
+							printf("\n");
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_CHANNEL:
+						{
+							tlvbuf_wifidirect_channel
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_channel
+								 *)ptr;
+							printf("\t Listen Channel Country String \"%c%c\"", wifidirect_tlv->country_string[0], wifidirect_tlv->country_string[1]);
+							if (isalpha
+							    (wifidirect_tlv->
+							     country_string[2]))
+								printf("\"%c\"",
+								       wifidirect_tlv->
+								       country_string
+								       [2]);
+							printf("\n");
+							printf("\t Listern Channel regulatory class = %d\n", (int)wifidirect_tlv->regulatory_class);
+							printf("\t Listen Channel number = %d\n", (int)wifidirect_tlv->channel_number);
+						}
+						break;
+
+					case TLV_TYPE_WIFIDIRECT_OPCHANNEL:
+						{
+							tlvbuf_wifidirect_channel
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_channel
+								 *)ptr;
+							printf("\t Operating Channel Country String %c%c", wifidirect_tlv->country_string[0], wifidirect_tlv->country_string[1]);
+							if (isalpha
+							    (wifidirect_tlv->
+							     country_string[2]))
+								printf("%c",
+								       wifidirect_tlv->
+								       country_string
+								       [2]);
+							printf("\n");
+							printf("\t Operating Channel regulatory class = %d\n", (int)wifidirect_tlv->regulatory_class);
+							printf("\t Operating Channel number = %d\n", (int)wifidirect_tlv->channel_number);
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_INVITATION_FLAG:
+						{
+							tlvbuf_wifidirect_invitation_flag
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_invitation_flag
+								 *)ptr;
+							printf("\t Invitation flag = %d\n", (int)wifidirect_tlv->invitation_flag & INVITATION_FLAG_MASK);
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_CONFIG_TIMEOUT:
+						{
+							tlvbuf_wifidirect_config_timeout
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_config_timeout
+								 *)ptr;
+							printf("\t GO configuration timeout = %d msec\n", (int)wifidirect_tlv->group_config_timeout * 10);
+							printf("\t Client configuration timeout = %d msec\n", (int)wifidirect_tlv->device_config_timeout * 10);
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_EXTENDED_LISTEN_TIME:
+						{
+							tlvbuf_wifidirect_ext_listen_time
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_ext_listen_time
+								 *)ptr;
+							printf("\t Availability Period = %d msec\n", (int)wifidirect_tlv->availability_period);
+							printf("\t Availability Interval = %d msec\n", (int)wifidirect_tlv->availability_interval);
+						}
+						break;
+					case TLV_TYPE_WIFIDIRECT_INTENDED_ADDRESS:
+						{
+							tlvbuf_wifidirect_intended_addr
+								*wifidirect_tlv
+								=
+								(tlvbuf_wifidirect_intended_addr
+								 *)ptr;
+							printf("\t Intended Interface Address - ");
+							print_mac
+								(wifidirect_tlv->
+								 group_address);
+							printf("\n");
+						}
+						break;
+					default:
+						printf("unknown ie=0x%x, len=%d\n", type, len);
+						break;
+					}
+					ptr += len + WIFIDIRECT_IE_HEADER_LEN;
+					ie_len_wifidirect -=
+						len + WIFIDIRECT_IE_HEADER_LEN;
+				}
+
+				/* Goto next index, Locate headers */
+				printf("WPS settings:\n");
+				ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
+						       sizeof(custom_ie) +
+						       ie_ptr->ie_length);
+				ptr = ie_ptr->ie_buffer;
+				ie_len_wps = ie_ptr->ie_length;
+				if (!wifidir_use_fixed_ie_indices()) {
+					while (memcmp
+					       (ptr, wps_oui,
+						sizeof(wps_oui))) {
+						ie_ptr = (custom_ie *)((t_u8 *)
+								       ie_ptr +
+								       sizeof
+								       (custom_ie)
+								       +
+								       ie_ptr->
+								       ie_length);
+						ie_len_wps = ie_ptr->ie_length;
+						ptr = ie_ptr->ie_buffer;
+					}
+					ptr += sizeof(wps_oui);
+					ie_len_wifidirect -= sizeof(wps_oui);
+				}
+				while (ie_len_wps > sizeof(tlvbuf_wps_ie)) {
+					memcpy(&wps_type, ptr, sizeof(t_u16));
+					memcpy(&wps_len, ptr + 2,
+					       sizeof(t_u16));
+					endian_convert_tlv_wps_header_in
+						(wps_type, wps_len);
+					switch (wps_type) {
+					case SC_Version:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							printf("\t WPS Version = 0x%2x\n", *(wps_tlv->data));
+						}
+						break;
+					case SC_Simple_Config_State:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							printf("\t WPS setupstate = 0x%x\n", *(wps_tlv->data));
+						}
+						break;
+					case SC_Request_Type:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							printf("\t WPS RequestType = 0x%x\n", *(wps_tlv->data));
+						}
+						break;
+					case SC_Response_Type:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							printf("\t WPS ResponseType = 0x%x\n", *(wps_tlv->data));
+						}
+						break;
+					case SC_Config_Methods:
+						{
+							t_u16 wps_config_methods
+								= 0;
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							memcpy(&wps_config_methods, wps_tlv->data, sizeof(t_u16));
+							wps_config_methods =
+								ntohs
+								(wps_config_methods);
+							printf("\t WPS SpecConfigMethods = 0x%x\n", wps_config_methods);
+						}
+						break;
+					case SC_UUID_E:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							array_ptr =
+								wps_tlv->data;
+							printf("\t WPS UUID = ");
+							for (i = 0; i < wps_len;
+							     i++)
+								printf("%2X ",
+								       *array_ptr++);
+							printf("\n");
+						}
+						break;
+					case SC_Primary_Device_Type:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							array_ptr =
+								wps_tlv->data;
+							printf("\t WPS Primary Device Type = ");
+							for (i = 0; i < wps_len;
+							     i++)
+								printf("%02X ",
+								       *array_ptr++);
+							printf("\n");
+						}
+						break;
+					case SC_RF_Band:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							printf("\t WPS RF Band = 0x%x\n", *(wps_tlv->data));
+						}
+						break;
+					case SC_Association_State:
+						{
+							t_u16 wps_association_state = 0;
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							memcpy(&wps_association_state, wps_tlv->data, sizeof(t_u16));
+							printf("\t WPS Association State = 0x%x\n", wps_association_state);
+						}
+						break;
+					case SC_Configuration_Error:
+						{
+							t_u16 wps_configuration_error = 0;
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							memcpy(&wps_configuration_error, wps_tlv->data, sizeof(t_u16));
+							wps_configuration_error
+								=
+								ntohs
+								(wps_configuration_error);
+							printf("\t WPS Configuration Error = 0x%x\n", wps_configuration_error);
+						}
+						break;
+					case SC_Device_Password_ID:
+						{
+							t_u16 wps_device_password_id = 0;
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							memcpy(&wps_device_password_id, wps_tlv->data, sizeof(t_u16));
+							wps_device_password_id =
+								ntohs
+								(wps_device_password_id);
+							printf("\t WPS Device Password ID = 0x%x\n", wps_device_password_id);
+						}
+						break;
+					case SC_Device_Name:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							array_ptr =
+								wps_tlv->data;
+							printf("\t WPS Device Name = ");
+							for (i = 0; i < wps_len;
+							     i++)
+								printf("%c",
+								       *array_ptr++);
+							printf("\n");
+						}
+						break;
+					case SC_Manufacturer:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							array_ptr =
+								wps_tlv->data;
+							printf("\t WPS Manufacturer = ");
+							for (i = 0; i < wps_len;
+							     i++)
+								printf("%c",
+								       *array_ptr++);
+							printf("\n");
+						}
+						break;
+					case SC_Model_Name:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							array_ptr =
+								wps_tlv->data;
+							printf("\t WPS Model Name = ");
+							for (i = 0; i < wps_len;
+							     i++)
+								printf("%c",
+								       *array_ptr++);
+							printf("\n");
+						}
+						break;
+					case SC_Model_Number:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							array_ptr =
+								wps_tlv->data;
+							printf("\t WPS Model Number = ");
+							for (i = 0; i < wps_len;
+							     i++)
+								printf("%c",
+								       *array_ptr++);
+							printf("\n");
+						}
+						break;
+					case SC_Serial_Number:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							array_ptr =
+								wps_tlv->data;
+							printf("\t WPS Serial Number = ");
+							for (i = 0; i < wps_len;
+							     i++)
+								printf("%c",
+								       *array_ptr++);
+							printf("\n");
+						}
+						break;
+					case SC_Vendor_Extension:
+						{
+							tlvbuf_wps_ie *wps_tlv =
+								(tlvbuf_wps_ie
+								 *)ptr;
+							array_ptr =
+								wps_tlv->data;
+							printf("\t WPS Vendor Extension = ");
+							for (i = 0; i < wps_len;
+							     i++)
+								printf("0x%02x ", *array_ptr++);
+							printf("\n");
+						}
+						break;
+					default:
+						printf("unknown ie=0x%x, len=%d\n", wps_type, wps_len);
+						break;
+					}
+					ptr += wps_len + sizeof(tlvbuf_wps_ie);
+					ie_len_wps -=
+						wps_len + sizeof(tlvbuf_wps_ie);
+				}
+			}
+		} else {
+			printf("ERR:Could not retrieve wifidirect parameters\n");
+		}
+	}
+
+	free(buf);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect_params_config command
+ *
+ *  $return         N/A
+ */
+static void
+print_wifidirect_params_config_usage(void)
+{
+	printf("\nUsage : wifidirect_params_config <CONFIG_FILE>\n");
+	printf("\nIssue set or get request using parameters in the CONFIG_FILE.\n");
+	return;
+}
+
+/**
+ *  @brief Creates a wifidirect_params_config request and sends to the driver
+ *
+ *  Usage: "Usage : wifidirect_params_config <CONFIG_FILE>"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirectcmd_params_config(int argc, char *argv[])
+{
+	wifidirect_params_config *param_buf = NULL;
+	tlvbuf_wps_ie *new_tlv = NULL;
+	char *line = NULL, wifidirect_mac[20];
+	FILE *config_file = NULL;
+	int i, opt, li = 0, arg_num = 0, ret = 0;
+	char *args[30], *pos = NULL;
+	t_u8 dev_address[ETH_ALEN], enable_scan;
+	t_u8 *buffer = NULL, WPS_primarydevicetype[WPS_DEVICE_TYPE_MAX_LEN];
+	t_u16 device_state = 0, tlv_len =
+		0, max_disc_int, min_disc_int, cmd_len = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_params_config_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR:wrong number of arguments.\n");
+		print_wifidirect_params_config_usage();
+		return;
+	}
+
+	cmd_len = sizeof(wifidirect_params_config);
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	param_buf = (wifidirect_params_config *)buffer;
+	param_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	param_buf->seq_num = 0;
+	param_buf->result = 0;
+
+	if (argc >= 3) {
+		/* Check if file exists */
+		config_file = fopen(argv[2], "r");
+		if (config_file == NULL) {
+			printf("\nERR:Config file can not open.\n");
+			goto done;
+		}
+		line = (char *)malloc(MAX_CONFIG_LINE);
+		if (!line) {
+			printf("ERR:Cannot allocate memory for line\n");
+			goto done;
+		}
+		memset(line, 0, MAX_CONFIG_LINE);
+		param_buf->action = cpu_to_le16(ACTION_SET);
+
+		/* Parse file and process */
+		while (config_get_line
+		       (line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+			arg_num = parse_line(line, args);
+
+			if (strcmp(args[0], "EnableScan") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_ENABLE_SCAN, arg_num - 1,
+				     args + 1)
+				    != SUCCESS) {
+					goto done;
+
+				}
+				enable_scan = (t_u8)atoi(args[1]);
+				/* Append a new TLV */
+				tlv_len = sizeof(tlvbuf_wps_ie) + sizeof(t_u8);
+				new_tlv = (tlvbuf_wps_ie *)(buffer + cmd_len);
+				cmd_len += tlv_len;
+				/* Set TLV fields */
+				new_tlv->tag =
+					MRVL_WIFIDIRECT_SCAN_ENABLE_TLV_ID;
+				new_tlv->length = tlv_len - 2 * sizeof(t_u16);
+				memcpy(new_tlv->data, &enable_scan,
+				       sizeof(t_u8));
+				endian_convert_tlv_header_out(new_tlv);
+
+			} else if (strcmp(args[0], "ScanPeerDeviceId") == 0) {
+				strncpy(wifidirect_mac, args[1], 20 - 1);
+				if ((ret =
+				     mac2raw(wifidirect_mac,
+					     dev_address)) != SUCCESS) {
+					printf("ERR: %s Address \n",
+					       ret ==
+					       FAILURE ? "Invalid MAC" : ret ==
+					       WIFIDIRECT_RET_MAC_BROADCAST ?
+					       "Broadcast" : "Multicast");
+					goto done;
+				}
+				/* Append a new TLV */
+				tlv_len = sizeof(tlvbuf_wps_ie) + ETH_ALEN;
+				new_tlv = (tlvbuf_wps_ie *)(buffer + cmd_len);
+				cmd_len += tlv_len;
+				/* Set TLV fields */
+				new_tlv->tag =
+					MRVL_WIFIDIRECT_PEER_DEVICE_TLV_ID;
+				new_tlv->length = tlv_len - 2 * sizeof(t_u16);
+				memcpy(new_tlv->data, dev_address, ETH_ALEN);
+				endian_convert_tlv_header_out(new_tlv);
+
+			} else if (strcmp(args[0], "MinDiscoveryInterval") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_MINDISCOVERYINT, arg_num - 1,
+				     args + 1) != SUCCESS) {
+					goto done;
+				}
+				min_disc_int = cpu_to_le16(atoi(args[1]));
+			} else if (strcmp(args[0], "MaxDiscoveryInterval") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_MAXDISCOVERYINT, arg_num - 1,
+				     args + 1) != SUCCESS) {
+					goto done;
+				}
+				max_disc_int = cpu_to_le16(atoi(args[1]));
+
+				/* Append a new TLV */
+				tlv_len =
+					sizeof(tlvbuf_wps_ie) +
+					2 * sizeof(t_u16);
+				new_tlv = (tlvbuf_wps_ie *)(buffer + cmd_len);
+				cmd_len += tlv_len;
+				/* Set TLV fields */
+				new_tlv->tag =
+					MRVL_WIFIDIRECT_DISC_PERIOD_TLV_ID;
+				new_tlv->length = tlv_len - 2 * sizeof(t_u16);
+				memcpy(&new_tlv->data, &min_disc_int,
+				       sizeof(t_u16));
+				memcpy((((t_u8 *)&new_tlv->data) +
+					sizeof(t_u16)), &max_disc_int,
+				       sizeof(t_u16));
+				endian_convert_tlv_header_out(new_tlv);
+
+			} else if (strcmp(args[0], "ScanRequestDeviceType") ==
+				   0) {
+				if (is_input_valid
+				    (WIFIDIRECT_WPSPRIMARYDEVICETYPE,
+				     arg_num - 1, args + 1)
+				    != SUCCESS) {
+					goto done;
+				}
+				for (i = 0; i < WPS_DEVICE_TYPE_MAX_LEN; i++)
+					WPS_primarydevicetype[i] =
+						(t_u8)A2HEXDECIMAL(args[i + 1]);
+
+				/* Append a new TLV */
+				tlv_len =
+					sizeof(tlvbuf_wps_ie) +
+					WPS_DEVICE_TYPE_MAX_LEN;
+				new_tlv = (tlvbuf_wps_ie *)(buffer + cmd_len);
+				cmd_len += tlv_len;
+				/* Set TLV fields */
+				new_tlv->tag =
+					MRVL_WIFIDIRECT_SCAN_REQ_DEVICE_TLV_ID;
+				new_tlv->length = tlv_len - 2 * sizeof(t_u16);
+				memcpy(&new_tlv->data, WPS_primarydevicetype,
+				       WPS_DEVICE_TYPE_MAX_LEN);
+				endian_convert_tlv_header_out(new_tlv);
+
+			} else if (strcmp(args[0], "DeviceState") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_DEVICE_STATE, arg_num - 1,
+				     args + 1)
+				    != SUCCESS) {
+					goto done;
+				}
+				device_state =
+					cpu_to_le16((t_u16)atoi(args[1]));
+
+				/* Append a new TLV */
+				tlv_len = sizeof(tlvbuf_wps_ie) + sizeof(t_u16);
+				new_tlv = (tlvbuf_wps_ie *)(buffer + cmd_len);
+				cmd_len += tlv_len;
+				/* Set TLV fields */
+				new_tlv->tag =
+					MRVL_WIFIDIRECT_DEVICE_STATE_TLV_ID;
+				new_tlv->length = tlv_len - 2 * sizeof(t_u16);
+				memcpy(new_tlv->data, &device_state,
+				       sizeof(t_u16));
+				endian_convert_tlv_header_out(new_tlv);
+			}
+		}
+	}
+
+	param_buf->size = cmd_len;
+	/* Send collective command */
+	wifidirect_ioctl((t_u8 *)buffer, &cmd_len, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	/* Process response */
+	if (argc < 3) {
+		/* Verify response */
+		if (param_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (param_buf->result == CMD_SUCCESS) {
+			param_buf = (wifidirect_params_config *)buffer;
+			new_tlv = (tlvbuf_wps_ie *)param_buf->wifidirect_tlv;
+			tlv_len =
+				param_buf->size -
+				(sizeof(wifidirect_params_config) -
+				 BUF_HEADER_SIZE);
+			if (tlv_len > sizeof(tlvbuf_wps_ie))
+				printf("WifiDirect Parameter settings: \n");
+			else
+				printf("WifiDirect Parameter settings are not received.\n");
+			while (tlv_len > sizeof(tlvbuf_wps_ie)) {
+				endian_convert_tlv_header_in(new_tlv);
+				switch (new_tlv->tag) {
+				case MRVL_WIFIDIRECT_SCAN_ENABLE_TLV_ID:
+					{
+						enable_scan =
+							*((t_u8 *)&new_tlv->
+							  data);
+						printf("\t Scan %s\n",
+						       (enable_scan ==
+							1) ? "enabled." :
+						       "disabled.");
+					}
+					break;
+				case MRVL_WIFIDIRECT_PEER_DEVICE_TLV_ID:
+					{
+						memcpy(dev_address,
+						       new_tlv->data, ETH_ALEN);
+						printf("\t Peer Device ID : ");
+						print_mac(dev_address);
+						printf("\n");
+					}
+					break;
+				case MRVL_WIFIDIRECT_DISC_PERIOD_TLV_ID:
+					{
+						t_u16 temp;
+						memcpy(&temp, &new_tlv->data,
+						       sizeof(t_u16));
+						printf("\t Minimum Discovery Interval : %d\n", le16_to_cpu(temp));
+						memcpy(&temp,
+						       ((t_u8 *)&new_tlv->
+							data) + sizeof(t_u16),
+						       sizeof(t_u16));
+						printf("\t Maximum Discovery Interval : %d\n", le16_to_cpu(temp));
+					}
+					break;
+				case MRVL_WIFIDIRECT_SCAN_REQ_DEVICE_TLV_ID:
+					{
+						memcpy(WPS_primarydevicetype,
+						       &new_tlv->data,
+						       WPS_DEVICE_TYPE_MAX_LEN);
+						printf("\tType: %02x:%02x\n",
+						       (unsigned int)
+						       WPS_primarydevicetype[0],
+						       (unsigned int)
+						       WPS_primarydevicetype
+						       [1]);
+						printf("\tOUI: %02x:%02x:%02x:%02x\n", (unsigned int)WPS_primarydevicetype[2], (unsigned int)WPS_primarydevicetype[3], (unsigned int)WPS_primarydevicetype[4], (unsigned int)WPS_primarydevicetype[5]);
+						printf("\tSubType: %02x:%02x\n",
+						       (unsigned int)
+						       WPS_primarydevicetype[6],
+						       (unsigned int)
+						       WPS_primarydevicetype
+						       [7]);
+					}
+					break;
+				case MRVL_WIFIDIRECT_DEVICE_STATE_TLV_ID:
+					{
+						memcpy(&device_state,
+						       &new_tlv->data,
+						       sizeof(t_u16));
+						printf("\t Device State %d\n",
+						       le16_to_cpu
+						       (device_state));
+					}
+					break;
+				default:
+					printf("Unknown ie=0x%x, len=%d\n",
+					       new_tlv->tag, new_tlv->length);
+					break;
+				}
+				tlv_len -=
+					new_tlv->length + sizeof(tlvbuf_wps_ie);
+				new_tlv =
+					(tlvbuf_wps_ie *)(((t_u8 *)new_tlv) +
+							  new_tlv->length +
+							  sizeof
+							  (tlvbuf_wps_ie));
+			}
+		} else {
+			printf("ERR:Could not retrieve wifidirect parameters.\n");
+		}
+	}
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (line)
+		free(line);
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect_action_frame command
+ *
+ *  $return         N/A
+ */
+static void
+print_wifidirect_action_frame_usage(void)
+{
+	printf("\nUsage : wifidirect_action_frame <CONFIG_FILE> |"
+	       " [<PeerAddr> <Category> <OUISubtype> <DialogToken>]\n");
+	printf("\nAction frame is sent using parameters in the CONFIG_FILE "
+	       "or parameters specified on command line.\n");
+	return;
+}
+
+/**
+ *  @brief Creates a wifidirect_action_frame request and sends to the driver
+ *
+ *  Usage: "Usage : wifidirect_action_frame <CONFIG_FILE> |
+ *                  [<PeerAddr> <Category> <OUISubtype> <DialogToken>]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirectcmd_action_frame(int argc, char *argv[])
+{
+	wifidirect_action_frame *action_buf = NULL;
+	char *line = NULL, wifidirect_mac[20];
+	FILE *config_file = NULL;
+	int i, opt, li = 0, arg_num = 0, ret = 0, cmd_found = 0;
+	char *args[30], *pos = NULL;
+	t_u8 dev_address[ETH_ALEN];
+	t_u8 *buffer = NULL;
+	t_u16 ie_len = 0, cmd_len = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_action_frame_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc != 3) && (argc != 6)) {
+		printf("ERR:wrong number of arguments.\n");
+		print_wifidirect_action_frame_usage();
+		return;
+	}
+
+	cmd_len = sizeof(wifidirect_action_frame);
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	action_buf = (wifidirect_action_frame *)buffer;
+	action_buf->cmd_code = HostCmd_CMD_802_11_ACTION_FRAME;
+	action_buf->seq_num = 0;
+	action_buf->result = 0;
+
+	/* Check if file exists */
+	config_file = fopen(argv[2], "r");
+	if (config_file && argc == 3) {
+		line = (char *)malloc(MAX_CONFIG_LINE);
+		if (!line) {
+			printf("ERR:Cannot allocate memory for line\n");
+			goto done;
+		}
+
+		/* Parse file and process */
+		while (config_get_line
+		       (line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
+			arg_num = parse_line(line, args);
+
+			if (strcmp(args[0], argv[1]) == 0) {
+				cmd_found = 1;
+			}
+			if (cmd_found == 0)
+				continue;
+
+			if (strcmp(args[0], "}") == 0) {
+				cmd_found = 0;
+			} else if (strcmp(args[0], "Category") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_CATEGORY, arg_num - 1, args + 1)
+				    != SUCCESS) {
+					goto done;
+
+				}
+				action_buf->category = (t_u8)atoi(args[1]);
+
+			} else if (strcmp(args[0], "PeerAddr") == 0) {
+				strncpy(wifidirect_mac, args[1], 20);
+				if ((ret =
+				     mac2raw(wifidirect_mac,
+					     dev_address)) != SUCCESS) {
+					printf("ERR: %s Address \n",
+					       ret ==
+					       FAILURE ? "Invalid MAC" : ret ==
+					       WIFIDIRECT_RET_MAC_BROADCAST ?
+					       "Broadcast" : "Multicast");
+					goto done;
+				}
+				memcpy(action_buf->peer_mac_addr, dev_address,
+				       ETH_ALEN);
+			} else if (strcmp(args[0], "Action") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_ACTION, arg_num - 1, args + 1)
+				    != SUCCESS) {
+					goto done;
+				}
+				action_buf->action =
+					(t_u8)A2HEXDECIMAL(args[1]);
+
+			} else if (strcmp(args[0], "DialogToken") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_DIALOGTOKEN, arg_num - 1,
+				     args + 1)
+				    != SUCCESS) {
+					goto done;
+				}
+				action_buf->dialog_taken = (t_u8)atoi(args[1]);
+
+			} else if (strcmp(args[0], "OUI") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_OUI, arg_num - 1, args + 1)
+				    != SUCCESS) {
+					goto done;
+				}
+				for (i = 0; i < arg_num - 1; i++)
+					action_buf->oui[i] =
+						A2HEXDECIMAL(args[i + 1]);
+			} else if (strcmp(args[0], "OUIType") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_OUITYPE, arg_num - 1, args + 1)
+				    != SUCCESS) {
+					goto done;
+				}
+				action_buf->oui_type = (t_u8)atoi(args[1]);
+			} else if (strcmp(args[0], "OUISubType") == 0) {
+				if (is_input_valid
+				    (WIFIDIRECT_OUISUBTYPE, arg_num - 1,
+				     args + 1)
+				    != SUCCESS) {
+					goto done;
+				}
+				action_buf->oui_sub_type = (t_u8)atoi(args[1]);
+			}
+		}
+		fclose(config_file);
+		config_file = NULL;
+
+		/* Now, read IE parameters from file */
+		wifidirect_file_params_config(argv[2], argv[1],
+					      action_buf->ie_list, &ie_len,
+					      NULL);
+		if (ie_len >= MRVDRV_SIZE_OF_CMD_BUFFER) {
+			printf("ERR:Too much data in configuration file %s.\n",
+			       argv[2]);
+			free(buffer);
+			return;
+		}
+		cmd_len += ie_len;
+	} else {
+		if (argc == 3) {
+			printf("ERR:Can not open config file.\n");
+			goto done;
+		}
+		strncpy(wifidirect_mac, argv[2], 20);
+		if ((ret = mac2raw(wifidirect_mac, dev_address)) != SUCCESS) {
+			printf("ERR: %s Address \n",
+			       ret == FAILURE ? "Invalid MAC" : ret ==
+			       WIFIDIRECT_RET_MAC_BROADCAST ? "Broadcast" :
+			       "Multicast");
+			goto done;
+		}
+		memcpy(action_buf->peer_mac_addr, dev_address, ETH_ALEN);
+
+		if (is_input_valid(WIFIDIRECT_CATEGORY, 1, &argv[3])
+		    != SUCCESS) {
+			goto done;
+		}
+		action_buf->category = (t_u8)atoi(argv[3]);
+
+		if (is_input_valid(WIFIDIRECT_OUISUBTYPE, 1, &argv[4])
+		    != SUCCESS) {
+			goto done;
+		}
+		action_buf->oui_sub_type = (t_u8)atoi(argv[4]);
+
+		if (is_input_valid(WIFIDIRECT_DIALOGTOKEN, 1, &argv[5])
+		    != SUCCESS) {
+			goto done;
+		}
+		action_buf->dialog_taken = (t_u8)atoi(argv[5]);
+
+		action_buf->action = 0;
+		action_buf->oui[0] = 0x50;
+		action_buf->oui[1] = 0x6F;
+		action_buf->oui[2] = 0x9A;
+		action_buf->oui_type = OUI_TYPE_WFA_WIFIDIRECT;
+	}
+	action_buf->size = cmd_len;
+#ifdef DEBUG
+	/* Debug print */
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	/* Send collective command */
+	wifidirect_ioctl((t_u8 *)buffer, &cmd_len, cmd_len);
+
+done:
+	if (config_file)
+		fclose(config_file);
+	if (line)
+		free(line);
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect status command
+ *
+ *  $return         N/A
+ */
+static void
+print_wifidirect_status_usage(void)
+{
+	printf("\nUsage : wifidirect_mode [STATUS]");
+	printf("\nOptions: STATUS :     0 - stop wifidirect status");
+	printf("\n                      1 - start wifidirect status");
+	printf("\n                      2 - start wifidirect group owner mode");
+	printf("\n                      3 - start wifidirect client mode");
+	printf("\n                      4 - start wifidirect find phase");
+	printf("\n                      5 - stop  wifidirect find phase");
+	printf("\n                  empty - get current wifidirect status\n");
+	return;
+}
+
+/**
+ *  @brief Creates wifidirect mode start or stop request and send to driver
+ *
+ *   Usage: "Usage : wifidirect_mode [STATUS]"
+ *
+ *   Options: STATUS :     0 - start wifidirect status
+ *                         1 - stop  wifidirect status
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         N/A
+ */
+static void
+wifidirectcmd_status(int argc, char *argv[])
+{
+	int opt, ret;
+	t_u16 data;
+	t_u16 cmd_len = 0;
+	t_u8 *buffer = NULL;
+	wifidirect_mode_config *cmd_buf = NULL;
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_status_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR:wrong arguments.\n");
+		print_wifidirect_status_usage();
+		return;
+	}
+	if (argc == 3) {
+		if ((ISDIGIT(argv[2]) == 0) || (atoi(argv[2]) < 0) ||
+		    (atoi(argv[2]) >= 0xFF)) {
+			printf("ERR:Illegal wifidirect mode %s. Must be in range from '0' to '5'.\n", argv[2]);
+			print_wifidirect_status_usage();
+			return;
+		}
+		data = (t_u16)atoi(argv[2]);
+	}
+
+	/* send hostcmd now */
+	cmd_len = sizeof(wifidirect_mode_config);
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		return;
+	}
+
+	cmd_buf = (wifidirect_mode_config *)buffer;
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_MODE_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		cmd_buf->mode = cpu_to_le16(data);
+	}
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (ret != SUCCESS) {
+		printf("Error executing wifidirect mode command\n");
+		return;
+	}
+
+	data = le16_to_cpu(cmd_buf->mode);
+	switch (data) {
+	case 0:
+		printf("Wifidirect Device Mode = Not Configured\n");
+		break;
+	case 1:
+		printf("Wifidirect Device Mode = Device\n");
+		break;
+	case 2:
+		printf("Wifidirect Device Mode = Wifidirect Group Owner (GO)\n");
+		break;
+	case 3:
+		printf("Wifidirect Device Mode = Wifidirect Group Client (GC)\n");
+		break;
+	default:
+		printf("Wifidirect Device Mode = Not specified\n");
+		break;
+	}
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect discovery period command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_discovery_period_usage(void)
+{
+	printf("Usage : wifidirect_cfg_discovery_period [<MinDiscPeriod> <MaxDiscPeriod>]\n");
+	printf("For 'Set' both MinDiscPeriod and MaxDiscPeriod should be specified.\n");
+	printf("If no parameter is given, 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect discovery period
+ *
+ *  Usage: "Usage : wifidirect_cfg_discovery_period [<MinDiscPeriod> <MaxDiscPeriod>]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_discovery_period(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_discovery_period *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_discovery_period_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc != 2) && (argc != 4)) {
+		printf("ERR:wrong number of arguments.\n");
+		print_wifidirect_cfg_discovery_period_usage();
+		return;
+	} else if ((argc > 2) &&
+		   ((is_input_valid(WIFIDIRECT_MINDISCOVERYINT, 1, &argv[2]) !=
+		     SUCCESS) ||
+		    (is_input_valid(WIFIDIRECT_MAXDISCOVERYINT, 1, &argv[3]) !=
+		     SUCCESS))) {
+		print_wifidirect_cfg_discovery_period_usage();
+		return;
+	}
+
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_discovery_period);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_discovery_period *)(buffer +
+						     sizeof
+						     (wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_DISC_PERIOD_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_discovery_period) -
+		MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->min_disc_interval = cpu_to_le16((t_u16)atoi(argv[2]));
+		tlv->max_disc_interval = cpu_to_le16((t_u16)atoi(argv[3]));
+	}
+	endian_convert_tlv_header_out(tlv);
+
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				printf("Min Discovery period = %d\n",
+				       le16_to_cpu(tlv->min_disc_interval));
+				printf("Max discovery period = %d\n",
+				       le16_to_cpu(tlv->max_disc_interval));
+			} else {
+				printf("Discovery period setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get min and max discovery period!\n");
+			} else {
+				printf("ERR:Couldn't set min and max discovery period!\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect Intent command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_intent_usage(void)
+{
+	printf("Usage : wifidirect_cfg_intent [IntentValue]\n");
+	printf("If IntentValue parameter is provided, 'set' is performed otherwise 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect Intent
+ *
+ *  Usage: "Usage : wifidirect_cfg_intent [IntentValue]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_intent(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_intent *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_intent_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR: Wrong number of arguments!\n");
+		print_wifidirect_cfg_intent_usage();
+		return;
+	} else if ((argc > 2) &&
+		   (is_input_valid(WIFIDIRECT_INTENT, argc - 2, argv + 2) !=
+		    SUCCESS)) {
+		print_wifidirect_cfg_intent_usage();
+		return;
+	}
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_intent);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_intent *)(buffer +
+					   sizeof(wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_INTENT_TLV_ID;
+	tlv->length = sizeof(tlvbuf_wifidirect_intent) - MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->intent = (t_u8)atoi(argv[2]);
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				printf("Intent Value = %d\n", (int)tlv->intent);
+			} else {
+				printf("Intent value setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get Intent value!\n");
+			} else {
+				printf("ERR:Couldn't set Intent value!\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect Listen Channel command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_listen_channel_usage(void)
+{
+	printf("Usage : wifidirect_cfg_listen_channel [ListenChannel]\n");
+	printf("If ListenChannel parameter is provided, 'set' is performed otherwise 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect ListenChannel
+ *
+ *  Usage: "Usage : wifidirect_cfg_listen_channel [ListenChannel]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_listen_channel(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_listen_channel *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_listen_channel_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR: Wrong number of arguments!\n");
+		print_wifidirect_cfg_listen_channel_usage();
+		return;
+	} else if ((argc > 2) &&
+		   (is_input_valid(CHANNEL, argc - 2, argv + 2) != SUCCESS)) {
+		print_wifidirect_cfg_listen_channel_usage();
+		return;
+	}
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_listen_channel);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_listen_channel *)(buffer +
+						   sizeof
+						   (wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_LISTEN_CHANNEL_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_listen_channel) - MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->listen_channel = (t_u8)atoi(argv[2]);
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				printf("Listen Channel = %d\n",
+				       (int)tlv->listen_channel);
+			} else {
+				printf("Listen Channel setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get Listen Channel!\n");
+			} else {
+				printf("ERR:Couldn't set Listen Channel!\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect Operating Channel command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_op_channel_usage(void)
+{
+	printf("Usage : wifidirect_cfg_op_channel [OperatingChannel]\n");
+	printf("If OperatingChannel parameter is provided, 'set' is performed otherwise 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect OperatingChannel
+ *
+ *  Usage: "Usage : wifidirect_cfg_op_channel [OperatingChannel]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_op_channel(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_operating_channel *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_op_channel_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR: Wrong number of arguments!\n");
+		print_wifidirect_cfg_op_channel_usage();
+		return;
+	} else if ((argc > 2) &&
+		   (is_input_valid(CHANNEL, argc - 2, argv + 2) != SUCCESS)) {
+		print_wifidirect_cfg_op_channel_usage();
+		return;
+	}
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_operating_channel);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_operating_channel *)(buffer +
+						      sizeof
+						      (wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_OPERATING_CHANNEL_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_operating_channel) -
+		MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->operating_channel = (t_u8)atoi(argv[2]);
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				printf("Operating Channel = %d\n",
+				       (int)tlv->operating_channel);
+			} else {
+				printf("Operating Channel setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get Operating Channel!\n");
+			} else {
+				printf("ERR:Couldn't set Operating Channel!\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect Invitation List command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_invitation_list_usage(void)
+{
+	printf("\nUsage : wifidirect_cfg_invitation_list [mac_addr]");
+	printf("\nIf mac_addr parameter is provided, 'set' is performed otherwise 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect InvitationList
+ *
+ *  Usage: "Usage : wifidirect_cfg_invitation_list [mac_addr]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_invitation_list(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_invitation_list *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0, ctr = 1;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_invitation_list_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc < 2) || (argc > 3)) {
+		printf("ERR:Wrong number of arguments!\n");
+		print_wifidirect_cfg_invitation_list_usage();
+		return;
+	}
+
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_invitation_list);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_invitation_list *)(buffer +
+						    sizeof
+						    (wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_INVITATION_LIST_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_invitation_list) -
+		MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+		cmd_len += (WIFIDIRECT_INVITATION_LIST_MAX - 1) * ETH_ALEN;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		if ((ret = mac2raw(argv[2], tlv->inv_peer_addr)) != SUCCESS) {
+			printf("ERR:Invalid MAC address %s\n", argv[2]);
+			goto done;
+		}
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				/* reusing variable cmd_len */
+				cmd_len = tlv->length;
+				if (cmd_len > 0) {
+					printf("Invitation List =>");
+					while (cmd_len >= ETH_ALEN) {
+						if (memcmp
+						    (tlv->inv_peer_addr,
+						     "\x00\x00\x00\x00\x00\x00",
+						     ETH_ALEN)) {
+							printf("\n\t [%d] ",
+							       ctr++);
+							print_mac(tlv->
+								  inv_peer_addr);
+						}
+						cmd_len -= ETH_ALEN;
+						tlv = (tlvbuf_wifidirect_invitation_list *)(((t_u8 *)(tlv)) + ETH_ALEN);
+					}
+					if (ctr == 1)
+						printf(" empty.");
+				} else
+					printf("Invitation List is empty.\n");
+				printf("\n");
+			} else {
+				printf("Invitation List setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get Invitation List!\n");
+			} else {
+				printf("ERR:Couldn't set Invitation List!\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect noa config command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_noa_usage(void)
+{
+	printf("Usage : wifidirect_cfg_noa <enable|disable> <index> [<counttype> <duration> <interval>]\n");
+	printf("If NOA parameters are provided, 'set' is performed otherwise 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect NoA parameters
+ *
+ *  Usage: "Usage : wifidirect_cfg_noa <enable|disable> <index> [<counttype> <duration> <interval>]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_noa(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_noa_config *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_noa_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc != 2) && (argc != 4) && (argc != 7)) {
+		printf("ERR: Wrong number of arguments!\n");
+		print_wifidirect_cfg_noa_usage();
+		return;
+	}
+	if (argc > 2) {
+		if (argc == 4) {
+			if (strcmp(argv[2], "enable") == 0) {
+				printf("ERR: index, count_type, duration and interval must be" " specified if noa is enabled!\n");
+				print_wifidirect_cfg_noa_usage();
+				return;
+			} else if (strcmp(argv[2], "disable")) {
+				print_wifidirect_cfg_noa_usage();
+				return;
+			}
+			if (atoi(argv[3]) > WIFIDIRECT_NOA_DESC_MAX) {
+				print_wifidirect_cfg_noa_usage();
+				return;
+			}
+		} else {
+			if (atoi(argv[3]) > WIFIDIRECT_NOA_DESC_MAX ||
+			    (is_input_valid(WIFIDIRECT_COUNT_TYPE, 1, &argv[4])
+			     != SUCCESS) ||
+			    (is_input_valid(WIFIDIRECT_DURATION, 1, &argv[5]) !=
+			     SUCCESS) ||
+			    (is_input_valid(WIFIDIRECT_INTERVAL, 1, &argv[6]) !=
+			     SUCCESS)) {
+				print_wifidirect_cfg_noa_usage();
+				return;
+			}
+		}
+	}
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_noa_config);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_noa_config *)(buffer +
+					       sizeof
+					       (wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_NOA_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_noa_config) - MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+		cmd_len +=
+			(sizeof(tlvbuf_wifidirect_noa_config) -
+			 MRVL_TLV_HEADER_SIZE)
+			* (WIFIDIRECT_NOA_DESC_MAX - 1);
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		if (strcmp(argv[2], "disable")) {
+			/* enable case */
+			tlv->enable_noa = 1;
+			tlv->enable_noa = cpu_to_le16(tlv->enable_noa);
+		}
+		tlv->noa_index = (t_u8)atoi(argv[3]);
+
+		if (tlv->enable_noa) {
+			tlv->count_type = (t_u8)atoi(argv[4]);
+			tlv->duration = (t_u32)atoi(argv[5]);
+			tlv->duration = cpu_to_le32(tlv->duration);
+			tlv->interval = (t_u32)atoi(argv[6]);
+			tlv->interval = cpu_to_le32(tlv->interval);
+		}
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				if (tlv->length)
+					printf("NoA settings:\n");
+				else
+					printf("NoA parameters are not configured.\n");
+				if (tlv->length >=
+				    sizeof(tlvbuf_wifidirect_noa_config) -
+				    MRVL_TLV_HEADER_SIZE) {
+					tlv->enable_noa =
+						le16_to_cpu(tlv->enable_noa);
+					if (tlv->enable_noa) {
+						printf("[%d] NoA is enabled!\n",
+						       (int)tlv->noa_index);
+						printf("CountType = %d\n",
+						       (int)tlv->count_type);
+						printf("Duration = %dms\n",
+						       le32_to_cpu(tlv->
+								   duration));
+						printf("Interval = %dms\n",
+						       le32_to_cpu(tlv->
+								   interval));
+					} else {
+						printf("[%d] NoA is disabled!\n", (int)tlv->noa_index);
+					}
+				}
+			} else {
+				printf("NoA setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get NoA parameters!\n");
+			} else {
+				printf("ERR:Couldn't set NoA parameters!\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect opp_ps config command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_opp_ps_usage(void)
+{
+	printf("Usage : wifidirect_cfg_opp_ps <enable|disable> [<CTWindow>]\n");
+	printf("For 'set', both enable flag and CTWindow should be provided.\n");
+	printf("If no parameter is specified,'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect Opportunistic Power Save
+ *
+ *  Usage: "Usage : wifidirect_cfg_opp_ps <enable|disable> [<CTWindow>]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_opp_ps(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_opp_ps_config *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	t_u8 opp_ps = 0, ctwindow = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_opp_ps_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc < 2) || (argc > 4)) {
+		printf("ERR: Wrong number of arguments!\n");
+		print_wifidirect_cfg_opp_ps_usage();
+		return;
+	}
+	if (argc == 3) {
+		if (strcmp(argv[2], "enable") == 0) {
+			printf("ERR: If Opp PS is enabled, CTWindow must be specified!\n");
+			print_wifidirect_cfg_opp_ps_usage();
+			return;
+		} else if (strcmp(argv[2], "disable")) {
+			print_wifidirect_cfg_opp_ps_usage();
+			return;
+		}
+	}
+	if (argc == 4) {
+		if (strcmp(argv[2], "disable") == 0) {
+			printf("ERR: Extra parameter %s for disable command.\n",
+			       argv[3]);
+			return;
+		}
+		if (is_input_valid(WIFIDIRECT_CTWINDOW, 1, &argv[3]) != SUCCESS) {
+			print_wifidirect_cfg_opp_ps_usage();
+			return;
+		}
+	}
+
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_opp_ps_config);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_opp_ps_config *)(buffer +
+						  sizeof
+						  (wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_OPP_PS_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_opp_ps_config) - MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		if (strcmp(argv[2], "disable"))
+			opp_ps = 1;
+		if (argc == 4)
+			tlv->ctwindow_opp_ps =
+				(t_u8)atoi(argv[3]) | SET_OPP_PS(opp_ps);;
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				opp_ps = GET_OPP_PS(tlv->ctwindow_opp_ps);
+				if (opp_ps) {
+					ctwindow =
+						(tlv->
+						 ctwindow_opp_ps) &
+						CT_WINDOW_MASK;
+					printf("Opportunistic Power Save enabled!\n");
+					printf("CTWindow  = %d\n", ctwindow);
+				} else {
+					printf("Opportunistic Power Save disabled!\n");
+				}
+			} else {
+				printf("Opportunistic power save setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get Opportunistic power save and CTWindow!\n");
+			} else {
+				printf("ERR:Couldn't set Opportunistic power save and CTWindow!\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect capability config command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_capability_usage(void)
+{
+	printf("Usage : wifidirect_capability [<DeviceCapability> <GroupCapability>]\n");
+	printf("For 'set' both DeviceCapability and GroupCapability should be provided.\n");
+	printf("If no parameter is specified,'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect Capability
+ *
+ *  Usage: "Usage : wifidirect_cfg_capability [<DeviceCapability> <GroupCapability>]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_capability(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_capability_config *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_capability_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc < 2) || (argc > 4) || (argc == 3)) {
+		printf("ERR: Wrong number of arguments!\n");
+		print_wifidirect_cfg_capability_usage();
+		return;
+	}
+	if (argc == 4) {
+		if ((is_input_valid(WIFIDIRECT_DEVICECAPABILITY, 1, &argv[2]) !=
+		     SUCCESS) ||
+		    (is_input_valid(WIFIDIRECT_GROUPCAPABILITY, 1, &argv[3]) !=
+		     SUCCESS)) {
+			print_wifidirect_cfg_capability_usage();
+			return;
+		}
+	}
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_capability_config);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_capability_config *)(buffer +
+						      sizeof
+						      (wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_CAPABILITY_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_capability_config) -
+		MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->dev_capability = (t_u8)atoi(argv[2]);
+		tlv->group_capability = (t_u8)atoi(argv[3]);
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				printf("Device Capability = %d\n",
+				       (int)tlv->dev_capability);
+				printf("Group Capability = %d\n",
+				       (int)tlv->group_capability);
+			} else {
+				printf("Capability setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get Capability info!\n");
+			} else {
+				printf("ERR:Couldn't set Capability!\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect_cfg_persistent_group_record command
+ *
+ *  $return         N/A
+ */
+static void
+print_wifidirect_peristent_group_usage(void)
+{
+	printf("\nUsage : wifidirect_cfg_persistent_group_record [index] \
+            <role> <bssid> <groupdevid> <ssid> <psk>> \
+            [<peermac1> <peermac2> ]\n");
+	printf("\nIssue set or get request using appropriate parameters.\n");
+	return;
+}
+
+/**
+ *  @brief Creates a wifidirect_persistent group record request and
+ *         sends to the driver
+ *
+ *  Usage: "Usage : wifidirect_cfg_cmd_persistent_group_record [index] <
+ *                  <role> <bssid> <groupdevid> <ssid> <psk>>
+ *                  [<peermac1> <peermac2> ]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         SUCCESS or FAILURE
+ **/
+static void
+wifidirect_cfg_cmd_persistent_group_record(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_persistent_group *tlv = NULL;
+	t_u8 index = 0, role = 0, var_len = 0, psk_len = 0;
+	t_u8 *buffer = NULL;
+	int pi;
+	t_u16 cmd_len = 0, buf_len = 0;
+	int opt, ret;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_peristent_group_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 2 && argc != 3 && argc != 8 && argc != 9 && argc != 10) {
+		printf("ERR:wrong number of arguments.\n");
+		print_wifidirect_peristent_group_usage();
+		return;
+	}
+	/* error checks */
+	if (argc > 2) {
+		index = atoi(argv[2]);
+		if (index >= WIFIDIRECT_PERSISTENT_GROUP_MAX) {
+			printf("ERR:wrong index. Value values are [0-3]\n");
+			return;
+		}
+	}
+	if (argc > 3) {
+		role = atoi(argv[3]);
+		if ((role != 1) && (role != 2)) {
+			printf("ERR:Incorrect Role. Use 2 for client, 1 for group owner.\n");
+			return;
+		}
+		if (role == 1 && argc == 8) {
+			printf("ERR:Insufficient arguments. Please provide peer mac address(es) for group owner.\n");
+			return;
+		}
+	}
+
+	cmd_len = sizeof(wifidirect_params_config);
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	cmd_buf = (wifidirect_params_config *)buffer;
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	tlv = (tlvbuf_wifidirect_persistent_group *)(buffer +
+						     sizeof
+						     (wifidirect_params_config));
+
+	tlv->tag = MRVL_WIFIDIRECT_PERSISTENT_GROUP_TLV_ID;
+
+	/* parsing commands based on arguments */
+	switch (argc) {
+	case 2:
+		cmd_buf->action = ACTION_GET;
+		tlv->length = 0;
+		cmd_len += MRVL_TLV_HEADER_SIZE + tlv->length;
+		cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+		buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+		break;
+
+	case 3:
+		cmd_buf->action = ACTION_GET;
+		tlv->rec_index = index;
+		tlv->length = sizeof(index);
+		cmd_len += MRVL_TLV_HEADER_SIZE + tlv->length;
+		cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+		buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+		break;
+
+	default:
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->rec_index = index;
+		tlv->dev_role = role;
+		if ((ret = mac2raw(argv[4], tlv->group_bssid)) != SUCCESS) {
+			printf("ERR:Invalid MAC address %s\n", argv[4]);
+			goto done;
+		}
+		if ((ret = mac2raw(argv[5], tlv->dev_mac_address)) != SUCCESS) {
+			printf("ERR:Invalid MAC address %s\n", argv[5]);
+			goto done;
+		}
+
+		/* ssid */
+		tlv->group_ssid_len = strlen(argv[6]);
+		var_len += tlv->group_ssid_len;
+		memcpy(tlv->group_ssid, argv[6], tlv->group_ssid_len);
+
+		/* adjust pointer from here */
+		/* psk */
+		if (!strncasecmp("0x", argv[7], 2)) {
+			argv[7] += 2;
+			if (strlen(argv[7]) / 2 != WIFIDIRECT_PSK_LEN_MAX) {
+				printf("ERR:Incorrect PSK length %d. It should be %d.\n", (t_u32)strlen(argv[7]) / 2, WIFIDIRECT_PSK_LEN_MAX);
+				goto done;
+			}
+			string2raw(argv[7], tlv->psk + var_len);
+			*(&tlv->psk_len + var_len) = WIFIDIRECT_PSK_LEN_MAX;
+			var_len += WIFIDIRECT_PSK_LEN_MAX;
+		} else {
+			/* ascii */
+			psk_len = strlen(argv[7]);
+			if (psk_len < WIFIDIRECT_PASSPHRASE_LEN_MIN ||
+			    psk_len >= WIFIDIRECT_PSK_LEN_MAX) {
+				printf("ERR:Incorrect passphrase length %d. Valid range is [8-63]\n", psk_len);
+				goto done;
+			}
+			memcpy(tlv->psk + var_len, argv[7], psk_len);
+			*(&tlv->psk_len + var_len) = psk_len;
+			var_len += psk_len;
+		}
+
+		tlv->length =
+			sizeof(tlvbuf_wifidirect_persistent_group) -
+			MRVL_TLV_HEADER_SIZE + var_len;
+		*(&tlv->num_peers + var_len) = 0;
+
+		if (argc == 9 || argc == 10) {
+			if ((ret =
+			     mac2raw(argv[8], tlv->peer_mac_addrs[0] + var_len))
+			    != SUCCESS) {
+				printf("ERR:Invalid MAC address %s\n", argv[8]);
+				goto done;
+			}
+			*(&tlv->num_peers + var_len) = 1;
+		}
+		if (argc == 10) {
+			if ((ret =
+			     mac2raw(argv[9], tlv->peer_mac_addrs[1] + var_len))
+			    != SUCCESS) {
+				printf("ERR:Invalid MAC address %s\n", argv[8]);
+				goto done;
+			}
+			*(&tlv->num_peers + var_len) = 2;
+		}
+
+		tlv->length += *(&tlv->num_peers + var_len) * ETH_ALEN;
+		cmd_len += MRVL_TLV_HEADER_SIZE + tlv->length;
+		buf_len = cmd_len;
+		cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+		break;
+	}
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	endian_convert_tlv_header_out(tlv);
+
+	/* Send collective command */
+	wifidirect_ioctl((t_u8 *)buffer, &cmd_len, buf_len);
+
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+
+	if (argc == 2 || argc == 3) {
+		if (tlv->length > 0)
+			printf("Persistent group information =>\n");
+		else
+			printf("Persistent group information is empty.\n");
+		buf_len = tlv->length;
+		while (buf_len >
+		       (sizeof(tlvbuf_wifidirect_persistent_group) -
+			2 * ETH_ALEN)) {
+			printf("\n\t Index = [%d]\n", tlv->rec_index);
+			if (tlv->dev_role == 1)
+				printf("\t Role  = Group owner\n");
+			else
+				printf("\t Role  = Client\n");
+			printf("\t GroupBssId - ");
+			print_mac(tlv->group_bssid);
+			printf("\n\t DeviceId - ");
+			print_mac(tlv->dev_mac_address);
+			printf("\n\t SSID = ");
+			for (index = 0; index < tlv->group_ssid_len; index++)
+				printf("%c", tlv->group_ssid[index]);
+			var_len = tlv->group_ssid_len;
+			printf("\n\t PSK = ");
+			for (index = 0; index < *(&tlv->psk_len + var_len);
+			     index++) {
+				if (index == 16)
+					printf("\n\t       ");
+				printf("%02x ", *(&tlv->psk[index] + var_len));
+			}
+			var_len += *(&tlv->psk_len + var_len);
+			if (tlv->dev_role == 1) {
+				for (pi = 0; pi < *(&tlv->num_peers + var_len);
+				     pi++) {
+					printf("\n\t Peer Mac address(%d) = ",
+					       pi);
+					print_mac(tlv->peer_mac_addrs[pi] +
+						  var_len);
+				}
+				var_len +=
+					(*(&tlv->num_peers + var_len) *
+					 ETH_ALEN);
+			}
+			if (argc == 2)
+				printf("\n\t -----------------------------------------");
+			if (tlv->dev_role == 1) {
+				buf_len -=
+					sizeof
+					(tlvbuf_wifidirect_persistent_group) -
+					MRVL_TLV_HEADER_SIZE + var_len;
+				tlv = (tlvbuf_wifidirect_persistent_group
+				       *)(((t_u8 *)(tlv)) +
+					  (sizeof
+					   (tlvbuf_wifidirect_persistent_group)
+					   - MRVL_TLV_HEADER_SIZE + var_len));
+			} else {
+				/* num_peer field willnt be present */
+				buf_len -=
+					sizeof
+					(tlvbuf_wifidirect_persistent_group) -
+					MRVL_TLV_HEADER_SIZE - sizeof(t_u8) +
+					var_len;
+				tlv = (tlvbuf_wifidirect_persistent_group
+				       *)(((t_u8 *)(tlv)) +
+					  (sizeof
+					   (tlvbuf_wifidirect_persistent_group)
+					   - MRVL_TLV_HEADER_SIZE -
+					   sizeof(t_u8) + var_len));
+			}
+		}
+		printf("\n");
+	} else {
+		printf("Setting persistent group information successful!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect_cfg_persistent_group_invoke command
+ *
+ *  $return         N/A
+ */
+static void
+print_wifidirect_peristent_group_invoke_usage(void)
+{
+	printf("\nUsage : wifidirect_cfg_persistent_group_invoke [index] | <cancel>\n");
+	return;
+}
+
+/**
+ *  @brief Creates a wifidirect_persistent group Invoke request and
+ *         sends to the driver
+ *
+ *  Usage: "Usage : wifidirect_cfg_cmd_persistent_group_invoke [index] | <cancel>"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         SUCCESS or FAILURE
+ **/
+static void
+wifidirect_cfg_cmd_persistent_group_invoke(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_persistent_group *tlv = NULL;
+	t_u8 index;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_peristent_group_invoke_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc != 3) {
+		printf("ERR:wrong number of arguments.\n");
+		print_wifidirect_peristent_group_invoke_usage();
+		return;
+	}
+
+	cmd_len = sizeof(wifidirect_params_config);
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	cmd_buf = (wifidirect_params_config *)buffer;
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+	cmd_buf->action = cpu_to_le16(ACTION_SET);
+	tlv = (tlvbuf_wifidirect_persistent_group *)(buffer +
+						     sizeof
+						     (wifidirect_params_config));
+
+	tlv->tag = MRVL_WIFIDIRECT_PERSISTENT_GROUP_TLV_ID;
+	tlv->length = sizeof(index);
+
+	index = atoi(argv[2]);
+	if (index >= WIFIDIRECT_PERSISTENT_GROUP_MAX) {
+		printf("ERR:wrong index. Value values are [0-3]\n");
+		goto done;
+	}
+	if (!isdigit(argv[2][0])) {
+		if (strcmp(argv[2], "cancel")) {
+			printf("ERR:Incorrect input. Use index [0-3] or \"cancel\" \n");
+			goto done;
+		} else
+			index = WIFIDIRECT_PERSISTENT_RECORD_CANCEL;
+	}
+	tlv->rec_index = index;
+
+	cmd_len += MRVL_TLV_HEADER_SIZE + tlv->length;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	endian_convert_tlv_header_out(tlv);
+
+	/* Send collective command */
+	wifidirect_ioctl((t_u8 *)buffer, &cmd_len, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+
+	printf("Persistent group %s successful!\n",
+	       (index ==
+		WIFIDIRECT_PERSISTENT_RECORD_CANCEL) ? "cancel" : "invoke");
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect presence request parameters command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_presence_req_params_usage(void)
+{
+	printf("Usage : wifidirect_cfg_presence_req_params [<type> <duration> <interval>]\n");
+	printf("      : Type 1: preferred values, 2: acceptable values.\n");
+	printf("If presence request parameters are provided, "
+	       " 'set' is performed otherwise 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect presence request parameters
+ *
+ *  Usage: "Usage : wifidirect_cfg_presence_req_params [<type> <duration> <interval>]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_presence_req_params(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_presence_req_params *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_presence_req_params_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR: Wrong number of arguments!\n");
+		print_wifidirect_cfg_presence_req_params_usage();
+		return;
+	} else if ((argc > 2) && ((argc != 5)
+				  ||
+				  (is_input_valid
+				   (WIFIDIRECT_PRESENCE_REQ_TYPE, 1,
+				    &argv[2]) != SUCCESS)
+				  ||
+				  (is_input_valid
+				   (WIFIDIRECT_DURATION, 1,
+				    &argv[3]) != SUCCESS)
+				  ||
+				  (is_input_valid
+				   (WIFIDIRECT_INTERVAL, 1,
+				    &argv[4]) != SUCCESS))) {
+		print_wifidirect_cfg_presence_req_params_usage();
+		return;
+	}
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_presence_req_params);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_presence_req_params *)(buffer +
+							sizeof
+							(wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_PRESENCE_REQ_PARAMS_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_presence_req_params) -
+		MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->presence_req_type = (t_u8)atoi(argv[2]);
+		tlv->duration = (t_u32)atoi(argv[3]);
+		tlv->duration = cpu_to_le32(tlv->duration);
+		tlv->interval = (t_u32)atoi(argv[4]);
+		tlv->interval = cpu_to_le32(tlv->interval);
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				printf("Presence request type = %d\n",
+				       (int)tlv->presence_req_type);
+				printf("Duration of NoA descriptor = %d\n",
+				       le32_to_cpu(tlv->duration));
+				printf("Interval of NoA descriptor = %d\n",
+				       le32_to_cpu(tlv->interval));
+			} else {
+				printf("Presence request parameters setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get Presence request parameters!\n");
+			} else {
+				printf("ERR:Couldn't set Presence request parameters!\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect extended listen timing parameters command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_ext_listen_time_usage(void)
+{
+	printf("Usage : wifidirect_cfg_ext_listen_time [<duration> <interval>]\n");
+	printf("If extended listen timing parameters are provided, "
+	       "'set' is performed otherwise 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect extended listen time parameters
+ *
+ *  Usage: "Usage : wifidirect_cfg_ext_listen_time [<duration> <interval>]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_ext_listen_time(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_mrvl_ext_listen_time *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_ext_listen_time_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR: Wrong number of arguments!\n");
+		print_wifidirect_cfg_ext_listen_time_usage();
+		return;
+	} else if ((argc > 2) && ((argc != 4)
+				  ||
+				  (is_input_valid
+				   (WIFIDIRECT_ATTR_EXTENDED_TIME, 1,
+				    &argv[2]) != SUCCESS)
+				  ||
+				  (is_input_valid
+				   (WIFIDIRECT_ATTR_EXTENDED_TIME, 1,
+				    &argv[3]) != SUCCESS))) {
+		print_wifidirect_cfg_ext_listen_time_usage();
+		return;
+	}
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_mrvl_ext_listen_time);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_mrvl_ext_listen_time *)(buffer +
+							 sizeof
+							 (wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_EXTENDED_LISTEN_TIME_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_mrvl_ext_listen_time) -
+		MRVL_TLV_HEADER_SIZE;
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->duration = cpu_to_le16((t_u16)atoi(argv[2]));
+		tlv->interval = cpu_to_le16((t_u16)atoi(argv[3]));
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				printf("Availability Period = %d\n",
+				       le16_to_cpu(tlv->duration));
+				printf("Availability Interval = %d\n",
+				       le16_to_cpu(tlv->interval));
+			} else {
+				printf("Extended listen timing parameters setting successful!\n");
+			}
+		} else {
+			if (argc == 2)
+				printf("ERR:Couldn't get Extended listen time!\n");
+			else
+				printf("ERR:Couldn't set Extended listen time!\n");
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect provisioing parameters command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_provisioning_params_usage(void)
+{
+	printf("Usage : wifidirect_cfg_provisioning_params [<action> <configMethod> <devPassword>]\n");
+	printf("      : Action 1: Request parameters 2: Response parameters.\n");
+	printf("If provisioning protocol parameters are provided, "
+	       "'set' is performed otherwise 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect provisioning protocol related parameters
+ *
+ *  Usage: "Usage : wifidirect_cfg_provisioning_params [<action> <configMethod>
+ *                  <devPassword>]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_provisioning_params(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_provisioning_params *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_provisioning_params_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if (argc < 2) {
+		printf("ERR: Wrong number of arguments!\n");
+		print_wifidirect_cfg_provisioning_params_usage();
+		return;
+	} else if ((argc > 2) && (argc != 5)) {
+		print_wifidirect_cfg_provisioning_params_usage();
+		return;
+	}
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_provisioning_params);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_provisioning_params *)(buffer +
+							sizeof
+							(wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_PROVISIONING_PARAMS_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_provisioning_params) -
+		MRVL_TLV_HEADER_SIZE;
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->action = cpu_to_le16((t_u16)A2HEXDECIMAL(argv[2]));
+		tlv->config_methods = cpu_to_le16((t_u16)A2HEXDECIMAL(argv[3]));
+		tlv->dev_password = cpu_to_le16((t_u16)A2HEXDECIMAL(argv[4]));
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				printf("Action = %s %s\n",
+				       (le16_to_cpu(tlv->action)) ==
+				       1 ? "Request" : "Response",
+				       "parameters");
+				printf("Config Methods = %02X\n",
+				       le16_to_cpu(tlv->config_methods));
+				printf("Device Password ID = %02X\n",
+				       le16_to_cpu(tlv->dev_password));
+			} else {
+				printf("Provisioning protocol parameters setting successful!\n");
+			}
+		} else {
+			if (argc == 2)
+				printf("ERR:Couldn't get provisioing parameters!\n");
+			else
+				printf("ERR:Couldn't set provisioing parameters!\n");
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Show usage information for the wifidirect WPS params command
+ *
+ *  @return         N/A
+ */
+static void
+print_wifidirect_cfg_wps_params_usage(void)
+{
+	printf("\nUsage : wifidirect_cfg_wps_params [pin/pbc/none]");
+	printf("\nIf pin/pbc/none is provided, 'set' is performed"
+	       " otherwise 'get' is performed.\n");
+	return;
+}
+
+/**
+ *  @brief Set/get wifidirect WPS parametters
+ *
+ *  Usage: "Usage : wifidirect_cfg_wps_params [pin/pbc/none]"
+ *
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         None
+ */
+static void
+wifidirect_cfg_cmd_wps_params(int argc, char *argv[])
+{
+	wifidirect_params_config *cmd_buf = NULL;
+	tlvbuf_wifidirect_wps_params *tlv = NULL;
+	t_u8 *buffer = NULL;
+	t_u16 cmd_len = 0;
+	int opt, ret = 0, param = 0;
+
+	while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
+		switch (opt) {
+		default:
+			print_wifidirect_cfg_wps_params_usage();
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* Check arguments */
+	if ((argc < 2) || (argc > 3)) {
+		printf("ERR:Wrong number of arguments!\n");
+		print_wifidirect_cfg_wps_params_usage();
+		return;
+	}
+
+	cmd_len =
+		sizeof(wifidirect_params_config) +
+		sizeof(tlvbuf_wifidirect_wps_params);
+
+	buffer = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	if (!buffer) {
+		printf("ERR:Cannot allocate memory!\n");
+		goto done;
+	}
+
+	memset(buffer, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	cmd_buf = (wifidirect_params_config *)buffer;
+	tlv = (tlvbuf_wifidirect_wps_params *)(buffer +
+					       sizeof
+					       (wifidirect_params_config));
+
+	cmd_buf->cmd_code = HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG;
+	cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
+	cmd_buf->seq_num = 0;
+	cmd_buf->result = 0;
+
+	tlv->tag = MRVL_WIFIDIRECT_WPS_PARAMS_TLV_ID;
+	tlv->length =
+		sizeof(tlvbuf_wifidirect_wps_params) - MRVL_TLV_HEADER_SIZE;
+
+	if (argc == 2) {
+		cmd_buf->action = ACTION_GET;
+	} else {
+		if (strncmp(argv[2], "pin", 3) == 0)
+			param = 1;
+		else if (strncmp(argv[2], "pbc", 3) == 0)
+			param = 2;
+		else if (strncmp(argv[2], "none", 4)) {
+			printf("Invalid input, should be pin/pbc or none.\n");
+			goto done;
+		}
+		cmd_buf->action = cpu_to_le16(ACTION_SET);
+		tlv->action = cpu_to_le16(param);
+	}
+	endian_convert_tlv_header_out(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len, ' ');
+#endif
+	ret = wifidirect_ioctl((t_u8 *)buffer, &cmd_len,
+			       MRVDRV_SIZE_OF_CMD_BUFFER);
+	endian_convert_tlv_header_in(tlv);
+#ifdef DEBUG
+	hexdump(buffer, cmd_len + BUF_HEADER_SIZE, ' ');
+#endif
+	/* Process Response */
+	if (ret == SUCCESS) {
+		/* Verify response */
+		if (cmd_buf->cmd_code !=
+		    (HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG |
+		     WIFIDIRECTCMD_RESP_CHECK)) {
+			printf("ERR:Corrupted response!\n");
+			goto done;
+		}
+		/* Print response */
+		if (cmd_buf->result == CMD_SUCCESS) {
+			if (argc == 2) {
+				printf("WPS password parameter =>");
+				switch (le16_to_cpu(tlv->action)) {
+				case 1:
+					printf("Pin\n");
+					break;
+				case 2:
+					printf("PBC\n");
+					break;
+				default:
+					printf("None\n");
+					break;
+				}
+			} else {
+				printf("WPS parameter setting successful!\n");
+			}
+		} else {
+			if (argc == 2) {
+				printf("ERR:Couldn't get WPS parameters !\n");
+			} else {
+				printf("ERR:Couldn't set WPS parameters !\n");
+			}
+		}
+	} else {
+		printf("ERR:Command sending failed!\n");
+	}
+done:
+	if (buffer)
+		free(buffer);
+	return;
+}
+
+/**
+ *  @brief Checkes a particular input for validatation.
+ *
+ *  @param cmd      Type of input
+ *  @param argc     Number of arguments
+ *  @param argv     Pointer to the arguments
+ *  @return         SUCCESS or FAILURE
+ */
+int
+is_input_valid(valid_inputs cmd, int argc, char *argv[])
+{
+	int i;
+	int ret = SUCCESS;
+	char country[6] = { ' ', ' ', 0, 0, 0, 0 };
+	char wifidirect_dev_name[34];
+	if (argc == 0)
+		return FAILURE;
+	switch (cmd) {
+	case WIFIDIRECT_MINDISCOVERYINT:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for MinDiscoveryInterval\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) >= (1 << 16))) {
+				printf("ERR:MinDiscoveryInterval must be 2 bytes\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_MAXDISCOVERYINT:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for MaxDiscoveryInterval\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) >= (1 << 16))) {
+				printf("ERR:MaxDiscoveryInterval must be 2 bytes\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_DEVICECAPABILITY:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for DeviceCapability\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_DEV_CAPABILITY) ||
+			    (atoi(argv[0]) < 0)) {
+				printf("ERR:DeviceCapability must be in the range [0:%d]\n", MAX_DEV_CAPABILITY);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_GROUPCAPABILITY:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for GroupCapability\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_GRP_CAPABILITY) ||
+			    (atoi(argv[0]) < 0)) {
+				printf("ERR:GroupCapability must be in the range [0:%d]\n", MAX_GRP_CAPABILITY);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case CHANNEL:
+		if ((argc != 1) && (argc != 2)) {
+			printf("ERR: Incorrect arguments for channel.\n");
+			ret = FAILURE;
+		} else {
+			if (argc == 2) {
+				if ((ISDIGIT(argv[1]) == 0) ||
+				    (atoi(argv[1]) < 0) ||
+				    (atoi(argv[1]) > 1)) {
+					printf("ERR: MODE must be either 0 or 1\n");
+					ret = FAILURE;
+				}
+				if ((atoi(argv[1]) == 1) &&
+				    (atoi(argv[0]) != 0)) {
+					printf("ERR: Channel must be 0 for ACS; MODE = 1.\n");
+					ret = FAILURE;
+				}
+			}
+			if ((argc == 1) || (atoi(argv[1]) == 0)) {
+				if ((ISDIGIT(argv[0]) == 0) ||
+				    (atoi(argv[0]) < 1) ||
+				    (atoi(argv[0]) > MAX_CHANNELS)) {
+					printf("ERR: Channel must be in the range of 1 to %d, configured - %d\n", MAX_CHANNELS, atoi(argv[0]));
+					ret = FAILURE;
+				}
+			}
+		}
+		break;
+	case SCANCHANNELS:
+		if (argc > MAX_CHANNELS) {
+			printf("ERR: Invalid List of Channels\n");
+			ret = FAILURE;
+		} else {
+			for (i = 0; i < argc; i++) {
+				if ((ISDIGIT(argv[i]) == 0) ||
+				    (atoi(argv[i]) < 1) ||
+				    (atoi(argv[i]) > MAX_CHANNELS)) {
+					printf("ERR: Channel must be in the range of 1 to %d, configured - %d\n", MAX_CHANNELS, atoi(argv[i]));
+					ret = FAILURE;
+					break;
+				}
+			}
+			if ((ret != FAILURE) &&
+			    (has_dup_channel(argc, argv) != SUCCESS)) {
+				printf("ERR: Duplicate channel values entered\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_INTENT:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for intent\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_INTENT) ||
+			    (atoi(argv[0]) < 0)) {
+				printf("ERR:Intent must be in the range [0:%d]\n", MAX_INTENT);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_MANAGEABILITY:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for manageability\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			    (atoi(argv[0]) > 1)) {
+				printf("ERR:Manageability must be either 0 or 1\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_GROUP_WIFIDIRECT_DEVICE_NAME:
+		/* 2 extra characters for quotes around device name */
+		if ((strlen(argv[0]) > 34)) {
+			printf("ERR:WIFIDIRECT Device name string length must not be more than 32\n");
+			ret = FAILURE;
+		} else {
+			strncpy(wifidirect_dev_name, argv[0],
+				sizeof(wifidirect_dev_name) - 1);
+			if ((wifidirect_dev_name[0] != '"') ||
+			    (wifidirect_dev_name
+			     [strlen(wifidirect_dev_name) - 1] != '"')) {
+				printf("ERR:WIFIDIRECT Device name must be within double quotes!\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_COUNTRY:
+		/* 2 extra characters for quotes around country */
+		if ((strlen(argv[0]) > 5) || (strlen(argv[0]) < 4)) {
+			printf("ERR:Country string must have length 2 or 3\n");
+			ret = FAILURE;
+		} else {
+			strncpy(country, argv[0], sizeof(country) - 1);
+			if ((country[0] != '"') ||
+			    (country[strlen(country) - 1] != '"')) {
+				printf("ERR:country code must be within double quotes!\n");
+				ret = FAILURE;
+			} else {
+				for (i = 1; i < strlen(country) - 2; i++) {
+					if ((toupper(country[i]) < 'A') ||
+					    (toupper(country[i]) > 'Z')) {
+						printf("ERR:Invalid Country Code\n");
+						ret = FAILURE;
+					}
+				}
+			}
+		}
+		break;
+	case WIFIDIRECT_NO_OF_CHANNELS:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for num of channels\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_CHANNELS)) {
+				printf("ERR:Number of channels should be less than %d\n", MAX_CHANNELS);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_NOA_INDEX:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for NoA Index\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) < MIN_NOA_INDEX) ||
+			    (atoi(argv[0]) > MAX_NOA_INDEX)) {
+				printf("ERR:NoA index should be in the range [%d:%d]\n", MIN_NOA_INDEX, MAX_NOA_INDEX);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_OPP_PS:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Opp PS\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) &&
+							(atoi(argv[0]) != 1))) {
+				printf("ERR:Opp PS must be either 0 or 1\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_CTWINDOW:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for CTWindow\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_CTWINDOW) ||
+			    (atoi(argv[0]) < MIN_CTWINDOW)) {
+				printf("ERR:CT Window must be in the range [%d:%d]\n", MIN_CTWINDOW, MAX_CTWINDOW);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_COUNT_TYPE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Count/Type\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_COUNT_TYPE) ||
+			    (atoi(argv[0]) < MIN_COUNT_TYPE)) {
+				printf("ERR:Count/Type must be in the range [%d:%d] or 255\n", MIN_COUNT_TYPE, MAX_COUNT_TYPE);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_PRESENCE_REQ_TYPE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Presence request type\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 1)
+							&& (atoi(argv[0]) !=
+							    2))) {
+				printf("ERR:Presence Type must be 1 or 2.\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_DURATION:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Duration\n");
+			ret = FAILURE;
+		}
+		break;
+	case WIFIDIRECT_INTERVAL:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Interval\n");
+			ret = FAILURE;
+		}
+		break;
+	case WIFIDIRECT_START_TIME:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Start Time\n");
+			ret = FAILURE;
+		}
+		break;
+	case WIFIDIRECT_PRIDEVTYPEOUI:
+		if (argc > MAX_PRIMARY_OUI_LEN) {
+			printf("ERR: Incorrect number of PrimaryDeviceTypeOUI arguments.\n");
+			ret = FAILURE;
+			break;
+		}
+		for (i = 0; i < argc; i++) {
+			if (IS_HEX_OR_DIGIT(argv[i]) == FAILURE) {
+				printf("ERR:Unsupported OUI\n");
+				ret = FAILURE;
+				break;
+			}
+		}
+		if (!
+		    ((A2HEXDECIMAL(argv[0]) == 0x00) &&
+		     (A2HEXDECIMAL(argv[1]) == 0x50)
+		     && (A2HEXDECIMAL(argv[2]) == 0xF2) &&
+		     (A2HEXDECIMAL(argv[3]) == 0x04))) {
+			printf("ERR:Unsupported OUI\n");
+			ret = FAILURE;
+			break;
+		}
+		break;
+	case WIFIDIRECT_REGULATORYCLASS:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for RegulatoryClass\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_REG_CLASS) ||
+			    (atoi(argv[0]) < MIN_REG_CLASS)) {
+				printf("ERR:RegulatoryClass must be in the range [%d:%d] or 255\n", MIN_REG_CLASS, MAX_REG_CLASS);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_PRIDEVTYPECATEGORY:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for PrimaryDeviceTypeCategory\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_PRIDEV_TYPE_CAT) ||
+			    (atoi(argv[0]) < MIN_PRIDEV_TYPE_CAT)) {
+				printf("ERR:PrimaryDeviceTypeCategory must be in the range [%d:%d]\n", MIN_PRIDEV_TYPE_CAT, MAX_PRIDEV_TYPE_CAT);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_SECONDARYDEVCOUNT:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for SecondaryDeviceCount\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_SECONDARY_DEVICE_COUNT)) {
+				printf("ERR:SecondaryDeviceCount must be less than 15.\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_INTERFACECOUNT:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for InterfaceCount\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_INTERFACE_ADDR_COUNT)) {
+				printf("ERR:IntefaceCount must be in range.[0-41]\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_GROUP_SECONDARYDEVCOUNT:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for SecondaryDeviceCount\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) >
+			     MAX_GROUP_SECONDARY_DEVICE_COUNT)) {
+				printf("ERR:SecondaryDeviceCount must be less than 2.\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_ATTR_CONFIG_TIMEOUT:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Timeout Configuration\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) > 255)) {
+				printf("ERR:TimeoutConfig must be in the range [0:255]\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_ATTR_EXTENDED_TIME:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Extended time.\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) > 65535)
+			    || (atoi(argv[0]) < 1)) {
+				printf("ERR:Extended Time must be in the range [1:65535]\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+
+	case WIFIDIRECT_PRIDEVTYPESUBCATEGORY:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for PrimaryDeviceTypeSubCategory\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    (atoi(argv[0]) > MAX_PRIDEV_TYPE_SUBCATEGORY) ||
+			    (atoi(argv[0]) < MIN_PRIDEV_TYPE_SUBCATEGORY)) {
+				printf("ERR:PrimaryDeviceTypeSubCategory must be in the range [%d:%d]\n", MIN_PRIDEV_TYPE_SUBCATEGORY, MAX_PRIDEV_TYPE_SUBCATEGORY);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_INVITATIONFLAG:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for InvitationFlag\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
+			    (atoi(argv[0]) > 1)) {
+				printf("ERR:Invitation flag must be either 0 or 1\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSCONFMETHODS:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for WPSConfigMethods\n");
+			ret = FAILURE;
+		} else {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    (A2HEXDECIMAL(argv[0]) > MAX_WPS_CONF_METHODS) ||
+			    (A2HEXDECIMAL(argv[0]) < MIN_WPS_CONF_METHODS)) {
+				printf("ERR:WPSConfigMethods must be in the range [%d:%d]\n", MIN_WPS_CONF_METHODS, MAX_WPS_CONF_METHODS);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSVERSION:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for WPSVersion\n");
+			ret = FAILURE;
+		} else {
+			if ((A2HEXDECIMAL(argv[0]) < 0x10) &&
+			    (A2HEXDECIMAL(argv[0]) > 0x20)) {
+				printf("ERR:Incorrect WPS Version %s\n",
+				       argv[0]);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSSETUPSTATE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for WPSSetupState\n");
+			ret = FAILURE;
+		} else {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    ((A2HEXDECIMAL(argv[0]) != 0x01)
+			     && (A2HEXDECIMAL(argv[0]) != 0x02))) {
+				printf("ERR:Incorrect WPSSetupState %s\n",
+				       argv[0]);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSREQRESPTYPE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for WPSRequestType\n");
+			ret = FAILURE;
+		} else {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    (A2HEXDECIMAL(argv[0]) > WPS_MAX_REQUESTTYPE)) {
+				printf("ERR:Incorrect WPSRequestType %s\n",
+				       argv[0]);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSSPECCONFMETHODS:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for WPSSpecConfigMethods\n");
+			ret = FAILURE;
+		} else {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    ((t_u16)A2HEXDECIMAL(argv[0]) >
+			     WPS_MAX_SPECCONFMETHODS) ||
+			    ((t_u16)A2HEXDECIMAL(argv[0]) <
+			     WPS_MIN_SPECCONFMETHODS)) {
+				printf("ERR:WPSSpecConfigMethods must be in the range [%d:%d]\n", WPS_MIN_SPECCONFMETHODS, WPS_MAX_SPECCONFMETHODS);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSDEVICENAME:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments\n");
+			ret = FAILURE;
+		} else {
+			if (argv[0][0] == '"') {
+				argv[0]++;
+			}
+			if (argv[0][strlen(argv[0]) - 1] == '"') {
+				argv[0][strlen(argv[0]) - 1] = '\0';
+			}
+			if (strlen(argv[0]) > WPS_DEVICE_NAME_MAX_LEN) {
+				printf("ERR:Device name should contain"
+				       " less than 32 charactors.\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSMANUFACTURER:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments\n");
+			ret = FAILURE;
+		} else {
+			if (strlen(argv[0]) > WPS_MANUFACT_MAX_LEN) {
+				printf("ERR:Manufacturer name should contain"
+				       "less than 64 charactors.\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSMODELNAME:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments\n");
+			ret = FAILURE;
+		} else {
+			if (strlen(argv[0]) > WPS_MODEL_MAX_LEN) {
+				printf("ERR:Model name should contain"
+				       " less than 64 charactors.\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSUUID:
+		if (argc > WPS_UUID_MAX_LEN) {
+			printf("ERR: Incorrect number of WPSUUID arguments.\n");
+			ret = FAILURE;
+		} else {
+			for (i = 0; i < argc; i++) {
+				if (IS_HEX_OR_DIGIT(argv[i]) == FAILURE) {
+					printf("ERR:Unsupported UUID\n");
+					ret = FAILURE;
+					break;
+				}
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSPRIMARYDEVICETYPE:
+		if (argc > WPS_DEVICE_TYPE_MAX_LEN) {
+			printf("ERR: Incorrect number of WPSPrimaryDeviceType arguments.\n");
+			ret = FAILURE;
+			break;
+		}
+		for (i = 0; i < argc; i++) {
+			if (IS_HEX_OR_DIGIT(argv[i]) == FAILURE) {
+				printf("ERR:Unsupported primary device type\n");
+				ret = FAILURE;
+				break;
+			}
+		}
+		if (!
+		    ((A2HEXDECIMAL(argv[2]) == 0x00) &&
+		     (A2HEXDECIMAL(argv[3]) == 0x50)
+		     && (A2HEXDECIMAL(argv[4]) == 0xF2) &&
+		     (A2HEXDECIMAL(argv[5]) == 0x04))) {
+			printf("ERR:Unsupported OUI\n");
+			ret = FAILURE;
+			break;
+		}
+		break;
+	case WIFIDIRECT_WPSRFBAND:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for WPSRFBand\n");
+			ret = FAILURE;
+		} else {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    ((A2HEXDECIMAL(argv[0]) != 0x01)
+			     && (A2HEXDECIMAL(argv[0]) != 0x02))) {
+				printf("ERR:Incorrect WPSRFBand %s\n", argv[0]);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSASSOCIATIONSTATE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for WPSAssociationState\n");
+			ret = FAILURE;
+		} else {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    ((t_u16)A2HEXDECIMAL(argv[0]) >
+			     WPS_MAX_ASSOCIATIONSTATE) ||
+			    ((t_u16)A2HEXDECIMAL(argv[0]) <
+			     WPS_MIN_ASSOCIATIONSTATE)) {
+				printf("ERR:WPSAssociationState must be in the range [%d:%d]\n", WPS_MIN_ASSOCIATIONSTATE, WPS_MAX_ASSOCIATIONSTATE);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSCONFIGURATIONERROR:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for WPSConfigurationError\n");
+			ret = FAILURE;
+		} else {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    ((t_u16)A2HEXDECIMAL(argv[0]) >
+			     WPS_MAX_CONFIGURATIONERROR) ||
+			    ((t_u16)A2HEXDECIMAL(argv[0]) <
+			     WPS_MIN_CONFIGURATIONERROR)) {
+				printf("ERR:WPSConfigurationError must be in the range [%d:%d]\n", WPS_MIN_CONFIGURATIONERROR, WPS_MAX_CONFIGURATIONERROR);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSDEVICEPASSWORD:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for WPSDevicePassword\n");
+			ret = FAILURE;
+		} else {
+			if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
+			    ((t_u16)A2HEXDECIMAL(argv[0]) >
+			     WPS_MAX_DEVICEPASSWORD) ||
+			    ((t_u16)A2HEXDECIMAL(argv[0]) <
+			     WPS_MIN_DEVICEPASSWORD)) {
+				printf("ERR:WPSDevicePassword must be in the range [%d:%d]\n", WPS_MIN_DEVICEPASSWORD, WPS_MAX_DEVICEPASSWORD);
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSMODELNUMBER:
+		if (argc > WPS_MODEL_MAX_LEN) {
+			printf("ERR: Incorrect number of WPSModelNumber arguments.\n");
+			ret = FAILURE;
+		} else {
+			for (i = 0; i < argc; i++) {
+				if (IS_HEX_OR_DIGIT(argv[i]) == FAILURE) {
+					printf("ERR:Unsupported WPSModelNumber\n");
+					ret = FAILURE;
+					break;
+				}
+			}
+		}
+		break;
+	case WIFIDIRECT_WPSSERIALNUMBER:
+		if (argc > WPS_SERIAL_MAX_LEN) {
+			printf("ERR: Incorrect number of WPSSerialNumber arguments.\n");
+			ret = FAILURE;
+		} else {
+			for (i = 0; i < argc; i++) {
+				if (IS_HEX_OR_DIGIT(argv[i]) == FAILURE) {
+					printf("ERR:Unsupported WPSSerialNumber\n");
+					ret = FAILURE;
+					break;
+				}
+			}
+		}
+		break;
+	case WIFIDIRECT_CATEGORY:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Category\n");
+			ret = FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR:Category incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_ACTION:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Action\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) ||
+			    ((atoi(argv[0]) > 0x10) &&
+			     (atoi(argv[0]) != 0xDD))) {
+				printf("ERR:Action must be less than 0x10 or 0xDD\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_DIALOGTOKEN:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for DialogToken\n");
+			ret = FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR:DialogToken incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_GAS_COMEBACK_DELAY:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for GAS Comeback Delay\n");
+			ret = FAILURE;
+		}
+		break;
+	case WIFIDIRECT_DISC_ADPROTOIE:
+		if (argc > MAX_ADPROTOIE_LEN) {
+			printf("ERR: Incorrect number of AdvertisementProtocolIE arguments.\n");
+			ret = FAILURE;
+			break;
+		}
+		for (i = 0; i < argc; i++) {
+			if (IS_HEX_OR_DIGIT(argv[i]) == FAILURE) {
+				printf("ERR:Unsupported AdvertisementProtocolIE\n");
+				ret = FAILURE;
+				break;
+			}
+		}
+		break;
+	case WIFIDIRECT_DISC_INFOID:
+		if (argc > MAX_INFOID_LEN) {
+			printf("ERR: Incorrect number of DiscoveryInformationID arguments.\n");
+			ret = FAILURE;
+			break;
+		}
+		if (!
+		    ((A2HEXDECIMAL(argv[0]) == 0xDD) &&
+		     (A2HEXDECIMAL(argv[1]) == 0xDD)) &&
+		    !((A2HEXDECIMAL(argv[0]) == 0xDE) &&
+		      (A2HEXDECIMAL(argv[1]) == 0x92))) {
+			printf("ERR:Unsupported DiscoveryInformationID\n");
+			ret = FAILURE;
+		}
+		break;
+	case WIFIDIRECT_OUI:
+		if (argc > MAX_OUI_LEN) {
+			printf("ERR: Incorrect number of OUI arguments.\n");
+			ret = FAILURE;
+			break;
+		}
+		for (i = 0; i < argc; i++) {
+			if (IS_HEX_OR_DIGIT(argv[i]) == FAILURE) {
+				printf("ERR:Unsupported OUI\n");
+				ret = FAILURE;
+				break;
+			}
+		}
+		break;
+	case WIFIDIRECT_OUITYPE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for OUIType\n");
+			ret = FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR:OUIType incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_OUISUBTYPE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for OUISubtype\n");
+			ret = FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR:OUISubtype incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_DISC_SERVICEPROTO:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for DiscoveryServiceProtocol\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) >= 4) &&
+							(atoi(argv[0]) !=
+							 0xFF))) {
+				printf("ERR:DiscoveryServiceProtocol incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_SERVICEUPDATE_INDICATOR:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for ServiceUpdateIndicator\n");
+			ret = FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR:ServiceUpdateIndicator incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_DISC_SERVICETRANSACID:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for DiscoveryServiceTransactionID\n");
+			ret = FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR:DiscoveryServiceTransactionID incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_DISC_SERVICE_STATUS:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for ServiceStatus\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) >= 4)) {
+				printf("ERR:ServiceStatus incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_DISC_DNSTYPE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for DiscoveryDNSType\n");
+			ret = FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR:DiscoveryDNSType incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_DISC_BONJOUR_VERSION:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Version\n");
+			ret = FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR:Version incorrect value\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+	case WIFIDIRECT_DISC_UPNP_VERSION:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for Version\n");
+			ret = FAILURE;
+		}
+		break;
+	case WIFIDIRECT_ENABLE_SCAN:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for EnableScan\n");
+			ret = FAILURE;
+		} else {
+			if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) &&
+							(atoi(argv[0]) != 1))) {
+				printf("ERR:EnableScan must be 0 or 1.\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+
+	case WIFIDIRECT_DEVICE_STATE:
+		if (argc != 1) {
+			printf("ERR:Incorrect number of arguments for DeviceState\n");
+			ret = FAILURE;
+		} else {
+			if (ISDIGIT(argv[0]) == 0) {
+				printf("ERR:Incorrect DeviceState.\n");
+				ret = FAILURE;
+			}
+		}
+		break;
+
+	default:
+		printf("Parameter validity for %d ignored\n", cmd);
+		break;
+	}
+	return ret;
+}
+
+/** Structure of command table*/
+typedef struct {
+	/** Command name */
+	char *cmd;
+	/** Command function pointer */
+	void (*func) (int argc, char *argv[]);
+	/** Command usuage */
+	char *help;
+} command_table;
+
+/** WiFiDisplay command table */
+static command_table wifidisplay_command[] = {
+	{"wifidisplay_config", wifidisplaycmd_config,
+	 "\tSet/get wifidisplay configuration"},
+	{"wifidisplay_mode", wifidisplay_cmd_status,
+	 "\tSet/get WFD Display status"},
+	{"wifidisplay_update_devinfo", wifidisplay_update_custom_ie,
+	 "\tUpdate WFD device info bitmap"},
+	{"wifidisplay_update_coupledsink_bitmap",
+	 wifidisplay_update_coupledsink_bitmap,
+	 "\tUpdate WFD coupled sink bitmap"},
+	{"wifidisplay_discovery_request", wifidisplaycmd_service_discovery,
+	 "Send wifidisplay service discovery request"},
+	{"wifidisplay_discovery_response", wifidisplaycmd_service_discovery,
+	 "Send wifidisplay service discovery response"},
+	{NULL, NULL, 0},
+};
+
+/** WIFIDIRECT command table */
+static command_table wifidirect_command[] = {
+	{"wifidirect_config", wifidirectcmd_config,
+	 "\tSet/get wifidirect configuration"},
+	{"wifidirect_params_config", wifidirectcmd_params_config,
+	 "\tSet/get wifidirect parameter's configuration"},
+	{"wifidirect_action_frame", wifidirectcmd_action_frame,
+	 "\tSend wifidirect action frame."},
+	{"wifidirect_mode", wifidirectcmd_status,
+	 "\tSet/get WIFIDIRECT start/stop status"},
+	{"wifidirect_discovery_request", wifidirectcmd_service_discovery,
+	 "Send wifidirect service discovery request"},
+	{"wifidirect_discovery_response", wifidirectcmd_service_discovery,
+	 "Send wifidirect service discovery response"},
+	{"wifidirect_gas_comeback_request",
+	 wifidirectcmd_gas_comeback_discovery,
+	 "Send wifidirect GAS comeback request frame"},
+	{"wifidirect_gas_comeback_response",
+	 wifidirectcmd_gas_comeback_discovery,
+	 "Send wifidirect GAS comeback response frame"},
+	{"wifidirect_cfg_persistent_group_record",
+	 wifidirect_cfg_cmd_persistent_group_record,
+	 "Set/get information about a persistent group"},
+	{"wifidirect_cfg_persistent_group_invoke",
+	 wifidirect_cfg_cmd_persistent_group_invoke,
+	 "Invoke or disable a persistent group"},
+	{"wifidirect_cfg_discovery_period", wifidirect_cfg_cmd_discovery_period,
+	 "\tSet/get discovery period"},
+	{"wifidirect_cfg_intent", wifidirect_cfg_cmd_intent,
+	 "\tSet/get intent"},
+	{"wifidirect_cfg_capability", wifidirect_cfg_cmd_capability,
+	 "\tSet/get capability"},
+	{"wifidirect_cfg_noa", wifidirect_cfg_cmd_noa,
+	 "\tSet/get notice of absence"},
+	{"wifidirect_cfg_opp_ps", wifidirect_cfg_cmd_opp_ps,
+	 "\tSet/get Opportunistic PS"},
+	{"wifidirect_cfg_invitation_list", wifidirect_cfg_cmd_invitation_list,
+	 "\tSet/get invitation list"},
+	{"wifidirect_cfg_listen_channel", wifidirect_cfg_cmd_listen_channel,
+	 "\tSet/get listen channel"},
+	{"wifidirect_cfg_op_channel", wifidirect_cfg_cmd_op_channel,
+	 "\tSet/get operating channel"},
+	{"wifidirect_cfg_presence_req_params",
+	 wifidirect_cfg_cmd_presence_req_params,
+	 "\tSet/get presence request parameters"},
+	{"wifidirect_cfg_ext_listen_time", wifidirect_cfg_cmd_ext_listen_time,
+	 "Set/get extended listen timing parameters"},
+	{"wifidirect_cfg_provisioning_params",
+	 wifidirect_cfg_cmd_provisioning_params,
+	 "Set/get provisioning protocol related parameters"},
+	{"wifidirect_cfg_wps_params", wifidirect_cfg_cmd_wps_params,
+	 "Set/get WPS protocol related parameters"},
+	{NULL, NULL, 0}
+};
+
+/**
+ *  @brief Entry function for wifidirectutl
+ *  @param argc         number of arguments
+ *  @param argv     A pointer to arguments array
+ *  @return             SUCCESS or FAILURE
+ */
+int
+main(int argc, char *argv[])
+{
+	int i;
+
+	if (argc < 3) {
+		print_tool_usage();
+		exit(1);
+	}
+
+	strncpy(dev_name, argv[1], IFNAMSIZ);
+	/* Process command */
+	for (i = 0; wifidirect_command[i].cmd; i++) {
+		if (strncmp
+		    (wifidirect_command[i].cmd, argv[2],
+		     strlen(wifidirect_command[i].cmd)))
+			continue;
+		if (strlen(wifidirect_command[i].cmd) != strlen(argv[2]))
+			continue;
+		wifidirect_command[i].func(argc, argv);
+		break;
+	}
+	for (i = 0; wifidisplay_command[i].cmd; i++) {
+		if (strncmp
+		    (wifidisplay_command[i].cmd, argv[2],
+		     strlen(wifidisplay_command[i].cmd)))
+			continue;
+		if (strlen(wifidisplay_command[i].cmd) != strlen(argv[2]))
+			continue;
+		wifidisplay_command[i].func(argc, argv);
+		break;
+	}
+	if ((!wifidirect_command[i].cmd) && (!wifidisplay_command[i].cmd)) {
+		printf("ERR: %s is not supported\n", argv[2]);
+		exit(1);
+	}
+	return 0;
+
+}
diff --git a/wlan_sd8897/mapp/wifidirectutl/wifidirectutl.h b/wlan_sd8897/mapp/wifidirectutl/wifidirectutl.h
new file mode 100644
index 0000000..b964580
--- /dev/null
+++ b/wlan_sd8897/mapp/wifidirectutl/wifidirectutl.h
@@ -0,0 +1,1418 @@
+/** @file  wifidirectutl.h
+ *
+ *  @brief Header file for wifidirectutl application
+ *
+ * Copyright (C) 2008-2017, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.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:
+    07/10/09: Initial creation
+************************************************************************/
+#ifndef _WIFIDIRECT_H
+#define _WIFIDIRECT_H
+
+/** Character, 1 byte */
+typedef signed char t_s8;
+/** Unsigned character, 1 byte */
+typedef unsigned char t_u8;
+
+/** Short integer */
+typedef signed short t_s16;
+/** Unsigned short integer */
+typedef unsigned short t_u16;
+
+/** Integer */
+typedef signed int t_s32;
+/** Unsigned integer */
+typedef unsigned int t_u32;
+
+/** Long long integer */
+typedef signed long long t_s64;
+/** Unsigned long integer */
+typedef unsigned long long t_u64;
+
+/** Device name */
+extern char dev_name[IFNAMSIZ + 1];
+/** Option for cmd */
+extern struct option cmd_options[2];
+
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#undef BIG_ENDIAN_SUPPORT
+#endif
+
+/** 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) ))
+
+/** Set opp_ps by shifting 7 bits left */
+#define SET_OPP_PS(x) ((x) << 7)
+
+/** Get opp_ps by masking and shifting 7 bits right */
+#define GET_OPP_PS(x) ((x) >> 7)
+
+/** CT window mask from opp_ps_ct_window combination */
+#define CT_WINDOW_MASK      0x7F
+/** Invitation flag mask */
+#define INVITATION_FLAG_MASK 0x01
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert from 16 bit little endian format to CPU format */
+#define le16_to_cpu(x) swap_byte_16(x)
+/** Convert from 32 bit little endian format to CPU format */
+#define le32_to_cpu(x) swap_byte_32(x)
+/** Convert from 64 bit little endian format to CPU format */
+#define le64_to_cpu(x) swap_byte_64(x)
+/** Convert to 16 bit little endian format from CPU format */
+#define cpu_to_le16(x) swap_byte_16(x)
+/** Convert to 32 bit little endian format from CPU format */
+#define cpu_to_le32(x) swap_byte_32(x)
+/** Convert to 64 bit little endian format from CPU format */
+#define cpu_to_le64(x) swap_byte_64(x)
+
+/** Convert WIFIDIRECTCMD header to little endian format from CPU format */
+#define endian_convert_request_header(x)                \
+    {                                                   \
+        (x)->cmd_code = cpu_to_le16((x)->cmd_code);   \
+        (x)->size = cpu_to_le16((x)->size);         \
+        (x)->seq_num = cpu_to_le16((x)->seq_num);     \
+        (x)->result = cpu_to_le16((x)->result);     \
+    }
+
+/** Convert WIFIDIRECTCMD header from little endian format to CPU format */
+#define endian_convert_response_header(x)               \
+    {                                                   \
+        (x)->cmd_code = le16_to_cpu((x)->cmd_code);   \
+        (x)->size = le16_to_cpu((x)->size);         \
+        (x)->seq_num = le16_to_cpu((x)->seq_num);     \
+        (x)->result = le16_to_cpu((x)->result);     \
+    }
+
+/** Convert WIFIDIRECT header to little endian format from CPU format */
+#define endian_convert_tlv_wifidirect_header_out(x)            \
+    {                                               \
+        (x)->length = cpu_to_le16((x)->length); \
+    }
+
+/** Convert WIFIDIRECT header from little endian format to CPU format */
+#define endian_convert_tlv_wifidirect_header_in(x)             \
+    {                                               \
+        (x)->length = le16_to_cpu((x)->length); \
+    }
+
+/** Convert TLV header to little endian format from CPU format */
+#define endian_convert_tlv_header_out(x)            \
+    {                                               \
+        (x)->tag = cpu_to_le16((x)->tag);       \
+        (x)->length = cpu_to_le16((x)->length); \
+    }
+
+/** Convert TLV header from little endian format to CPU format */
+#define endian_convert_tlv_header_in(x)             \
+    {                                               \
+        (x)->tag = le16_to_cpu((x)->tag);       \
+        (x)->length = le16_to_cpu((x)->length); \
+    }
+
+#else /* BIG_ENDIAN_SUPPORT */
+/** Do nothing */
+#define le16_to_cpu(x) x
+/** Do nothing */
+#define le32_to_cpu(x) x
+/** Do nothing */
+#define le64_to_cpu(x) x
+/** Do nothing */
+#define cpu_to_le16(x) x
+/** Do nothing */
+#define cpu_to_le32(x) x
+/** Do nothing */
+#define cpu_to_le64(x) x
+
+/** Do nothing */
+#define endian_convert_request_header(x)
+/** Do nothing */
+#define endian_convert_response_header(x)
+/** Do nothing */
+#define endian_convert_tlv_wifidirect_header_out(x)
+/** Do nothing */
+#define endian_convert_tlv_wifidirect_header_in(x)
+/** Do nothing */
+#define endian_convert_tlv_header_out(x)
+/** Do nothing */
+#define endian_convert_tlv_header_in(x)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** Convert WPS TLV header to network order */
+#define endian_convert_tlv_wps_header_out(x)            \
+    {                                               \
+        (x)->tag = htons((x)->tag);       \
+        (x)->length = htons((x)->length); \
+    }
+
+/** Convert WPS TLV header from network to host order */
+#define endian_convert_tlv_wps_header_in(t,l)             \
+    {                                               \
+        (t) = ntohs(t);       \
+        (l) = ntohs(l);       \
+    }
+
+/** Private command ID to set/get custom IE buffer */
+#define CUSTOM_IE               (SIOCDEVPRIVATE + 13)
+
+/** TLV type ID definition */
+#define PROPRIETARY_TLV_BASE_ID              0x0100
+/** TLV: Management IE list */
+#define MRVL_MGMT_IE_LIST_TLV_ID             (PROPRIETARY_TLV_BASE_ID + 0x69)	//0x0169
+/** TLV: WifiDirect Discovery Period */
+#define MRVL_WIFIDIRECT_DISC_PERIOD_TLV_ID          (PROPRIETARY_TLV_BASE_ID + 0x7c)	//0x017c
+/** TLV: WifiDirect Scan Enable */
+#define MRVL_WIFIDIRECT_SCAN_ENABLE_TLV_ID          (PROPRIETARY_TLV_BASE_ID + 0x7d)	//0x017d
+/** TLV: WifiDirect Peer Device  */
+#define MRVL_WIFIDIRECT_PEER_DEVICE_TLV_ID          (PROPRIETARY_TLV_BASE_ID + 0x7e)	//0x017e
+/** TLV: WifiDirect Scan Request Peer Device  */
+#define MRVL_WIFIDIRECT_SCAN_REQ_DEVICE_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 0x7f)	//0x017f
+/** TLV: WifiDirect Device State */
+#define MRVL_WIFIDIRECT_DEVICE_STATE_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 0x80)	//0x0180
+/** TLV: WifiDirect Intent */
+#define MRVL_WIFIDIRECT_INTENT_TLV_ID               (PROPRIETARY_TLV_BASE_ID + 0x81)	//0x0181
+/** TLV: WifiDirect Capability */
+#define MRVL_WIFIDIRECT_CAPABILITY_TLV_ID           (PROPRIETARY_TLV_BASE_ID + 0x82)	//0x0182
+/** TLV: WifiDirect Notice of Absence */
+#define MRVL_WIFIDIRECT_NOA_TLV_ID                  (PROPRIETARY_TLV_BASE_ID + 0x83)	//0x0183
+/** TLV: WifiDirect Opportunistic Power Save */
+#define MRVL_WIFIDIRECT_OPP_PS_TLV_ID               (PROPRIETARY_TLV_BASE_ID + 0x84)	//0x0184
+/** TLV: WifiDirect Invitation list */
+#define MRVL_WIFIDIRECT_INVITATION_LIST_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 0x85)	//0x0185
+/** TLV: WifiDirect Listen channel */
+#define MRVL_WIFIDIRECT_LISTEN_CHANNEL_TLV_ID       (PROPRIETARY_TLV_BASE_ID + 0x86)	//0x0186
+/** TLV: WifiDirect Operating Channel */
+#define MRVL_WIFIDIRECT_OPERATING_CHANNEL_TLV_ID    (PROPRIETARY_TLV_BASE_ID + 0x87)	//0x0187
+/** TLV: WifiDirect Persistent Group */
+#define MRVL_WIFIDIRECT_PERSISTENT_GROUP_TLV_ID     (PROPRIETARY_TLV_BASE_ID + 0x88)	//0x0188
+/** TLV: WifiDirect Presence request parameters */
+#define MRVL_WIFIDIRECT_PRESENCE_REQ_PARAMS_TLV_ID  (PROPRIETARY_TLV_BASE_ID + 0x8d)	//0x018d
+/** TLV: WifiDirect Extended Listen Time */
+#define MRVL_WIFIDIRECT_EXTENDED_LISTEN_TIME_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0x8e)	//0x018e
+/** TLV: WifiDirect Provisioning parameters */
+#define MRVL_WIFIDIRECT_PROVISIONING_PARAMS_TLV_ID  (PROPRIETARY_TLV_BASE_ID + 0x8f)	//0x018f
+/** TLV: WifiDirect WPS parameters */
+#define MRVL_WIFIDIRECT_WPS_PARAMS_TLV_ID           (PROPRIETARY_TLV_BASE_ID + 0x90)	//0x0190
+
+/** Max Device capability */
+#define MAX_DEV_CAPABILITY                 255
+/** Max group capability */
+#define MAX_GRP_CAPABILITY                 255
+/** Max Intent */
+#define MAX_INTENT                        15
+/** Max length of Primary device type OUI */
+#define MAX_PRIMARY_OUI_LEN               4
+/** Min value of Regulatory class */
+#define MIN_REG_CLASS                      1
+/** Max value of Regulatory class */
+#define MAX_REG_CLASS                    255
+/** Min value of NoA index */
+#define MIN_NOA_INDEX                   0
+/** Max value of NoA index */
+#define MAX_NOA_INDEX                   255
+/** Min value of CTwindow */
+#define MIN_CTWINDOW                    0
+/** Max value of CTwindow */
+#define MAX_CTWINDOW                    63
+/** Min value of Count/Type */
+#define MIN_COUNT_TYPE                  1
+/** Max value of Count/Type */
+#define MAX_COUNT_TYPE                  255
+/** Min Primary Device type category */
+#define MIN_PRIDEV_TYPE_CAT                1
+/** Max Primary Device type category */
+#define MAX_PRIDEV_TYPE_CAT               11
+/** Min Primary Device type subcategory */
+#define MIN_PRIDEV_TYPE_SUBCATEGORY        1
+/** Max Primary Device type subcategory */
+#define MAX_PRIDEV_TYPE_SUBCATEGORY        9
+/** Min value of WPS config method */
+#define MIN_WPS_CONF_METHODS            0x01
+/** Max value of WPS config method */
+#define MAX_WPS_CONF_METHODS            0xffff
+/** Max length of Advertisement Protocol IE  */
+#define MAX_ADPROTOIE_LEN               4
+/** Max length of Discovery Information ID  */
+#define MAX_INFOID_LEN                  2
+/** Max length of OUI  */
+#define MAX_OUI_LEN                     3
+/** Max count of interface list */
+#define MAX_INTERFACE_ADDR_COUNT        41
+/** Max count of secondary device types */
+#define MAX_SECONDARY_DEVICE_COUNT      15
+/** Max count of group secondary device types*/
+#define MAX_GROUP_SECONDARY_DEVICE_COUNT 2
+/** Maximum length of lines in configuration file */
+#define MAX_CONFIG_LINE                 1024
+/** Maximum number of arguments in configuration file */
+#define MAX_ARGS_NUM                    256
+/** Maximum channels */
+#define MAX_CHANNELS    165
+/** Maximum number of NoA descriptors */
+#define MAX_NOA_DESCRIPTORS            8
+/** Maximum number of channel list entries */
+#define MAX_CHAN_LIST    8
+/** Maximum buffer size for channel entries */
+#define MAX_BUFFER_SIZE         64
+/** WPS Minimum version number */
+#define WPS_MIN_VERSION			0x10
+/** WPS Maximum version number */
+#define WPS_MAX_VERSION                 0x20
+/** WPS Minimum request type */
+#define WPS_MIN_REQUESTTYPE		0x00
+/** WPS Maximum request type */
+#define WPS_MAX_REQUESTTYPE		0x04
+/** WPS Minimum config methods */
+#define WPS_MIN_SPECCONFMETHODS		0x0001
+/** WPS Maximum config methods */
+#define WPS_MAX_SPECCONFMETHODS		0xFFFF
+/** WPS UUID maximum length */
+#define WPS_UUID_MAX_LEN                16
+/** WPS Device Type maximum length */
+#define WPS_DEVICE_TYPE_MAX_LEN         8
+/** WPS Minimum association state */
+#define WPS_MIN_ASSOCIATIONSTATE	0x0000
+/** WPS Maximum association state */
+#define WPS_MAX_ASSOCIATIONSTATE	0x0004
+/** WPS Minimum configuration error */
+#define WPS_MIN_CONFIGURATIONERROR	0x0000
+/** WPS Maximum configuration error */
+#define WPS_MAX_CONFIGURATIONERROR	0x0012
+/** WPS Minimum Device password ID */
+#define WPS_MIN_DEVICEPASSWORD		0x0000
+/** WPS Maximum Device password ID */
+#define WPS_MAX_DEVICEPASSWORD		0x000f
+/** WPS Device Name maximum length */
+#define WPS_DEVICE_NAME_MAX_LEN         32
+/** WPS Model maximum length */
+#define WPS_MODEL_MAX_LEN               32
+/** WPS Serial maximum length */
+#define WPS_SERIAL_MAX_LEN              32
+/** WPS Manufacturer maximum length */
+#define WPS_MANUFACT_MAX_LEN            64
+/** WPS Device Info OUI+Type+SubType Length */
+#define WPS_DEVICE_TYPE_LEN             8
+
+/** Maximum value of invitation list index */
+#define WIFIDIRECT_INVITATION_LIST_MAX         5
+/** Maximum value of persistent group index */
+#define WIFIDIRECT_PERSISTENT_GROUP_MAX        4
+/** Minimum length of Passphrase   */
+#define WIFIDIRECT_PASSPHRASE_LEN_MIN          8
+/** Maximum length of PSK  */
+#define WIFIDIRECT_PSK_LEN_MAX                 64
+/** Persistent group cancel command   */
+#define WIFIDIRECT_PERSISTENT_RECORD_CANCEL    0xFF
+/** Maximum value of noA descriptors */
+#define WIFIDIRECT_NOA_DESC_MAX                2
+/** Country string last byte 0x04 */
+#define WIFIDIRECT_COUNTRY_LAST_BYTE           0x04
+
+#ifdef __GNUC__
+/** Structure packing begins */
+#define PACK_START
+/** Structure packeing end */
+#define PACK_END  __attribute__ ((packed))
+#else
+/** Structure packing begins */
+#define PACK_START   __packed
+/** Structure packeing end */
+#define PACK_END
+#endif
+
+#ifndef ETH_ALEN
+/** MAC address length */
+#define ETH_ALEN    6
+#endif
+
+/** Action field value : get */
+#define ACTION_GET  0
+/** Action field value : set */
+#define ACTION_SET  1
+
+/** Success */
+#define SUCCESS     1
+/** Failure */
+#define FAILURE     0
+/** MAC BROADCAST */
+#define WIFIDIRECT_RET_MAC_BROADCAST   0x1FF
+/** MAC MULTICAST */
+#define WIFIDIRECT_RET_MAC_MULTICAST   0x1FE
+
+/** Command is successful */
+#define CMD_SUCCESS     0
+/** Command fails */
+#define CMD_FAILURE     -1
+
+/**
+ * Hex or Decimal to Integer
+ * @param   num string to convert into decimal or hex
+ */
+#define A2HEXDECIMAL(num)  \
+    (strncasecmp("0x", (num), 2)?(unsigned int) strtoll((num),NULL,0):a2hex((num)))\
+
+/**
+ * Check of decimal or hex string
+ * @param   num string
+ */
+#define IS_HEX_OR_DIGIT(num) \
+    (strncasecmp("0x", (num), 2)?ISDIGIT((num)):ishexstring((num)))\
+
+/** Find minimum value */
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+/** Level of wifidirect parameters in the wifidirect.conf file */
+typedef enum {
+	WIFIDIRECT_PARAMS_CONFIG = 1,
+	WIFIDIRECT_CAPABILITY_CONFIG,
+	WIFIDIRECT_GROUP_OWNER_INTENT_CONFIG,
+	WIFIDIRECT_CHANNEL_CONFIG,
+	WIFIDIRECT_MANAGEABILITY_CONFIG,
+	WIFIDIRECT_CHANNEL_LIST_CONFIG,
+	WIFIDIRECT_NOTICE_OF_ABSENCE,
+	WIFIDIRECT_NOA_DESCRIPTOR,
+	WIFIDIRECT_DEVICE_INFO_CONFIG,
+	WIFIDIRECT_GROUP_INFO_CONFIG,
+	WIFIDIRECT_GROUP_SEC_INFO_CONFIG,
+	WIFIDIRECT_GROUP_CLIENT_INFO_CONFIG,
+	WIFIDIRECT_DEVICE_SEC_INFO_CONFIG,
+	WIFIDIRECT_GROUP_ID_CONFIG,
+	WIFIDIRECT_GROUP_BSS_ID_CONFIG,
+	WIFIDIRECT_DEVICE_ID_CONFIG,
+	WIFIDIRECT_INTERFACE_CONFIG,
+	WIFIDIRECT_TIMEOUT_CONFIG,
+	WIFIDIRECT_EXTENDED_TIME_CONFIG,
+	WIFIDIRECT_INTENDED_ADDR_CONFIG,
+	WIFIDIRECT_OPCHANNEL_CONFIG,
+	WIFIDIRECT_INVITATION_FLAG_CONFIG,
+	WIFIDIRECT_WPSIE,
+	WIFIDIRECT_DISCOVERY_REQUEST_RESPONSE = 0x20,
+	WIFIDIRECT_DISCOVERY_QUERY,
+	WIFIDIRECT_DISCOVERY_SERVICE,
+	WIFIDIRECT_DISCOVERY_VENDOR,
+	WIFIDIRECT_DISCOVERY_QUERY_RESPONSE_PER_PROTOCOL,
+	WIFIDIRECT_EXTRA,
+} wifidirect_param_level;
+
+/** Valid Input Commands */
+typedef enum {
+	SCANCHANNELS,
+	CHANNEL,
+	WIFIDIRECT_DEVICECAPABILITY,
+	WIFIDIRECT_GROUPCAPABILITY,
+	WIFIDIRECT_INTENT,
+	WIFIDIRECT_REGULATORYCLASS,
+	WIFIDIRECT_MANAGEABILITY,
+	WIFIDIRECT_COUNTRY,
+	WIFIDIRECT_NO_OF_CHANNELS,
+	WIFIDIRECT_NOA_INDEX,
+	WIFIDIRECT_OPP_PS,
+	WIFIDIRECT_CTWINDOW,
+	WIFIDIRECT_COUNT_TYPE,
+	WIFIDIRECT_DURATION,
+	WIFIDIRECT_INTERVAL,
+	WIFIDIRECT_START_TIME,
+	WIFIDIRECT_PRIDEVTYPECATEGORY,
+	WIFIDIRECT_PRIDEVTYPEOUI,
+	WIFIDIRECT_PRIDEVTYPESUBCATEGORY,
+	WIFIDIRECT_SECONDARYDEVCOUNT,
+	WIFIDIRECT_GROUP_SECONDARYDEVCOUNT,
+	WIFIDIRECT_GROUP_WIFIDIRECT_DEVICE_NAME,
+	WIFIDIRECT_INTERFACECOUNT,
+	WIFIDIRECT_ATTR_CONFIG_TIMEOUT,
+	WIFIDIRECT_ATTR_EXTENDED_TIME,
+	WIFIDIRECT_WPSCONFMETHODS,
+	WIFIDIRECT_WPSVERSION,
+	WIFIDIRECT_WPSSETUPSTATE,
+	WIFIDIRECT_WPSREQRESPTYPE,
+	WIFIDIRECT_WPSSPECCONFMETHODS,
+	WIFIDIRECT_WPSUUID,
+	WIFIDIRECT_WPSPRIMARYDEVICETYPE,
+	WIFIDIRECT_WPSRFBAND,
+	WIFIDIRECT_WPSASSOCIATIONSTATE,
+	WIFIDIRECT_WPSCONFIGURATIONERROR,
+	WIFIDIRECT_WPSDEVICENAME,
+	WIFIDIRECT_WPSDEVICEPASSWORD,
+	WIFIDIRECT_WPSMANUFACTURER,
+	WIFIDIRECT_WPSMODELNAME,
+	WIFIDIRECT_WPSMODELNUMBER,
+	WIFIDIRECT_WPSSERIALNUMBER,
+	WIFIDIRECT_CATEGORY,
+	WIFIDIRECT_ACTION,
+	WIFIDIRECT_DIALOGTOKEN,
+	WIFIDIRECT_DISC_ADPROTOIE,
+	WIFIDIRECT_GAS_COMEBACK_DELAY,
+	WIFIDIRECT_DISC_INFOID,
+	WIFIDIRECT_OUI,
+	WIFIDIRECT_OUITYPE,
+	WIFIDIRECT_OUISUBTYPE,
+	WIFIDIRECT_SERVICEUPDATE_INDICATOR,
+	WIFIDIRECT_DISC_SERVICEPROTO,
+	WIFIDIRECT_DISC_SERVICETRANSACID,
+	WIFIDIRECT_DISC_SERVICE_STATUS,
+	WIFIDIRECT_MINDISCOVERYINT,
+	WIFIDIRECT_MAXDISCOVERYINT,
+	WIFIDIRECT_ENABLE_SCAN,
+	WIFIDIRECT_DEVICE_STATE,
+	WIFIDIRECT_INVITATIONFLAG,
+	WIFIDIRECT_DISC_DNSTYPE,
+	WIFIDIRECT_DISC_BONJOUR_VERSION,
+	WIFIDIRECT_DISC_UPNP_VERSION,
+	WIFIDIRECT_PRESENCE_REQ_TYPE,
+} valid_inputs;
+
+/** WIFIDIRECT IE header len */
+#define WIFIDIRECT_IE_HEADER_LEN                   3
+
+/** AP CMD header */
+#define WIFIDIRECT_CMD_HEADER     /** Buf Size */         \
+                        t_u32 buf_size;         \
+                        /** Command Code */     \
+                        t_u16 cmd_code;         \
+                        /** Size */             \
+                        t_u16 size;             \
+                        /** Sequence Number */  \
+                        t_u16 seq_num;          \
+                        /** Result */           \
+                        t_s16 result
+
+/**  TLV header size */
+#define MRVL_TLV_HEADER_SIZE   4
+
+/** Marvell private command identifier */
+#define CMD_MARVELL         "MRVL_CMD"
+/** Marvell private command for hostcmd */
+#define PRIV_CMD_HOSTCMD    "hostcmd"
+
+/** WIFIDIRECTCMD buffer */
+typedef PACK_START struct _wifidirectcmdbuf {
+    /** Header */
+	WIFIDIRECT_CMD_HEADER;
+} PACK_END wifidirectcmdbuf;
+
+/** MRVL private CMD structure */
+typedef PACK_START struct _mrvl_priv_cmd {
+   /** Command buffer */
+	t_u8 *buf;
+    /** Used length */
+	t_u32 used_len;
+    /** Total length */
+	t_u32 total_len;
+} PACK_END mrvl_priv_cmd;
+
+/** TLV buffer : WifiDirect Custom IE Buffer Format*/
+typedef PACK_START struct special_mask_custom_ie_buf {
+    /** Vendor Specific OUI */
+	t_u8 Oui[4];
+    /** Vendor Specific Buffer */
+	t_u8 wfd_ie[0];
+} PACK_END special_mask_custom_ie_buf;
+
+/** TLV buffer : WifiDirect IE device Id */
+typedef PACK_START struct _tlvbuf_wifidirect_device_id {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT device MAC address */
+	t_u8 dev_mac_address[ETH_ALEN];
+} PACK_END tlvbuf_wifidirect_device_id;
+
+/** TLV buffer : WifiDirect IE capability */
+typedef PACK_START struct _tlvbuf_wifidirect_capability {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT device capability */
+	t_u8 dev_capability;
+    /** WIFIDIRECT group capability */
+	t_u8 group_capability;
+} PACK_END tlvbuf_wifidirect_capability;
+
+/** TLV buffer : WifiDirect IE Group owner intent */
+typedef PACK_START struct _tlvbuf_wifidirect_group_owner_intent {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT device group owner intent */
+	t_u8 dev_intent;
+} PACK_END tlvbuf_wifidirect_group_owner_intent;
+
+/** TLV buffer : WifiDirect IE channel */
+typedef PACK_START struct _tlvbuf_wifidirect_channel {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT country string */
+	t_u8 country_string[3];
+    /** WIFIDIRECT regulatory class */
+	t_u8 regulatory_class;
+    /** WIFIDIRECT channel number */
+	t_u8 channel_number;
+} PACK_END tlvbuf_wifidirect_channel;
+
+/** TLV buffer : WifiDirect IE invitation flag */
+typedef PACK_START struct _tlvbuf_wifidirect_invitation_flag {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT invitation flag */
+	t_u8 invitation_flag;
+} PACK_END tlvbuf_wifidirect_invitation_flag;
+
+/** Channel Entry */
+typedef PACK_START struct _chan_entry {
+    /** WIFIDIRECT regulatory class */
+	t_u8 regulatory_class;
+    /** WIFIDIRECT no of channels */
+	t_u8 num_of_channels;
+    /** WIFIDIRECT channel number */
+	t_u8 chan_list[0];
+} PACK_END chan_entry;
+
+/** NoA Descriptor */
+typedef PACK_START struct _noa_descriptor {
+    /** WIFIDIRECT count OR type */
+	t_u8 count_type;
+    /** WIFIDIRECT duration */
+	t_u32 duration;
+    /** WIFIDIRECT interval */
+	t_u32 interval;
+    /** WIFIDIRECT start time */
+	t_u32 start_time;
+} PACK_END noa_descriptor;
+
+/** TLV buffer : WifiDirect IE channel list */
+typedef PACK_START struct _tlvbuf_wifidirect_channel_list {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT country string */
+	t_u8 country_string[3];
+    /** WIFIDIRECT channel entry list */
+	chan_entry wifidirect_chan_entry_list[0];
+} PACK_END tlvbuf_wifidirect_channel_list;
+
+/** TLV buffer : WifiDirect IE Manageability */
+typedef PACK_START struct _tlvbuf_wifidirect_manageability {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT Manageability */
+	t_u8 manageability;
+} PACK_END tlvbuf_wifidirect_manageability;
+
+/** TLV buffer : WifiDirect IE Notice of Absence */
+typedef PACK_START struct _tlvbuf_wifidirect_notice_of_absence {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT NoA Index */
+	t_u8 noa_index;
+    /** WIFIDIRECT CTWindow and OppPS parameters */
+	t_u8 ctwindow_opp_ps;
+    /** WIFIDIRECT NoA Descriptor list */
+	noa_descriptor wifidirect_noa_descriptor_list[0];
+} PACK_END tlvbuf_wifidirect_notice_of_absence;
+
+/** TLV buffer : WifiDirect IE device Info */
+typedef PACK_START struct _tlvbuf_wifidirect_device_info {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT device address */
+	t_u8 dev_address[ETH_ALEN];
+    /** WPS config methods */
+	t_u16 config_methods;
+    /** Primary device type : category */
+	t_u16 primary_category;
+    /** Primary device type : OUI */
+	t_u8 primary_oui[4];
+    /** Primary device type : sub-category */
+	t_u16 primary_subcategory;
+    /** Secondary Device Count */
+	t_u8 secondary_dev_count;
+    /** Secondary Device Info */
+	t_u8 secondary_dev_info[0];
+    /** WPS Device Name Tag */
+	t_u16 device_name_type;
+    /** WPS Device Name Length */
+	t_u16 device_name_len;
+    /** Device name */
+	t_u8 device_name[0];
+} PACK_END tlvbuf_wifidirect_device_info;
+
+/** TLV buffer : wifidirect IE WIFIDIRECT Group Info- Client Dev Info */
+typedef PACK_START struct _wifidirect_client_dev_info {
+    /** Length of each device */
+	t_u8 dev_length;
+    /** WIFIDIRECT device address */
+	t_u8 wifidirect_dev_address[ETH_ALEN];
+    /** WIFIDIRECT Interface  address */
+	t_u8 wifidirect_intf_address[ETH_ALEN];
+    /** WIFIDIRECT Device capability*/
+	t_u8 wifidirect_dev_capability;
+    /** WPS config methods */
+	t_u16 config_methods;
+    /** Primary device type : category */
+	t_u16 primary_category;
+    /** Primary device type : OUI */
+	t_u8 primary_oui[4];
+    /** Primary device type : sub-category */
+	t_u16 primary_subcategory;
+    /** Secondary Device Count */
+	t_u8 wifidirect_secondary_dev_count;
+    /** Secondary Device Info */
+	t_u8 wifidirect_secondary_dev_info[0];
+    /** WPS WIFIDIRECT Device Name Tag */
+	t_u16 wifidirect_device_name_type;
+    /** WPS WIFIDIRECT Device Name Length */
+	t_u16 wifidirect_device_name_len;
+    /** WIFIDIRECT Device name */
+	t_u8 wifidirect_device_name[0];
+} PACK_END wifidirect_client_dev_info;
+
+/** TLV buffer : wifidirect IE WIFIDIRECT Group Info */
+typedef PACK_START struct _tlvbuf_wifidirect_group_info {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** Secondary Device Info */
+	t_u8 wifidirect_client_dev_list[0];
+} PACK_END tlvbuf_wifidirect_group_info;
+
+/** TLV buffer : WifiDirect IE group Id */
+typedef PACK_START struct _tlvbuf_wifidirect_group_id {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT group MAC address */
+	t_u8 group_address[ETH_ALEN];
+    /** WIFIDIRECT group SSID */
+	t_u8 group_ssid[0];
+} PACK_END tlvbuf_wifidirect_group_id;
+
+/** TLV buffer : WifiDirect IE group BSS Id */
+typedef PACK_START struct _tlvbuf_wifidirect_group_bss_id {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT group Bss Id */
+	t_u8 group_bssid[ETH_ALEN];
+} PACK_END tlvbuf_wifidirect_group_bss_id;
+
+/** TLV buffer : WifiDirect IE Interface */
+typedef PACK_START struct _tlvbuf_wifidirect_interface {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT interface Id */
+	t_u8 interface_id[ETH_ALEN];
+    /** WIFIDIRECT interface count */
+	t_u8 interface_count;
+    /** WIFIDIRECT interface addresslist */
+	t_u8 interface_idlist[0];
+} PACK_END tlvbuf_wifidirect_interface;
+
+/** TLV buffer : WifiDirect configuration timeout */
+typedef PACK_START struct _tlvbuf_wifidirect_config_timeout {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** Group configuration timeout */
+	t_u8 group_config_timeout;
+    /** Device configuration timeout */
+	t_u8 device_config_timeout;
+} PACK_END tlvbuf_wifidirect_config_timeout;
+
+/** TLV buffer : WifiDirect extended listen time */
+typedef PACK_START struct _tlvbuf_wifidirect_ext_listen_time {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** Availability period */
+	t_u16 availability_period;
+    /** Availability interval */
+	t_u16 availability_interval;
+} PACK_END tlvbuf_wifidirect_ext_listen_time;
+
+/** TLV buffer : WifiDirect Intended Interface Address */
+typedef PACK_START struct _tlvbuf_wifidirect_intended_addr {
+    /** TLV Header tag */
+	t_u8 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT Group interface address */
+	t_u8 group_address[ETH_ALEN];
+} PACK_END tlvbuf_wifidirect_intended_addr;
+
+/** TLV buffer : WifiDirect WPS IE */
+typedef PACK_START struct _tlvbuf_wifidirect_wps_ie {
+    /** TLV Header tag */
+	t_u16 tag;
+    /** TLV Header length */
+	t_u16 length;
+    /** WIFIDIRECT WPS IE data */
+	t_u8 data[0];
+} PACK_END tlvbuf_wps_ie;
+
+/** HostCmd_CMD_WIFIDIRECT_MODE_CONFIG */
+typedef PACK_START struct _wifidirect_mode_config {
+    /** Header */
+	WIFIDIRECT_CMD_HEADER;
+    /** Action */
+	t_u16 action;		/* 0 = ACT_GET; 1 = ACT_SET; */
+    /** wifidirect mode data */
+	t_u16 mode;
+} PACK_END wifidirect_mode_config;
+
+/** HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG */
+typedef PACK_START struct _wifidirect_params_config {
+    /** Header */
+	WIFIDIRECT_CMD_HEADER;
+    /** Action */
+	t_u16 action;		/* 0 = ACT_GET; 1 = ACT_SET; */
+    /** TLV data */
+	t_u8 wifidirect_tlv[0];
+} PACK_END wifidirect_params_config;
+
+/** Internal WIFIDIRECT structure for Query Data */
+typedef PACK_START struct wifidirect_query_data {
+	union {
+		PACK_START struct upnp_specific_query {
+	    /** version field */
+			t_u8 version;
+	    /** value */
+			t_u8 value[0];
+		} PACK_END upnp;
+
+		PACK_START struct bonjour_specific_query {
+	    /** DNS name */
+			t_u8 dns[0];
+	    /** DNS type */
+			t_u8 dns_type;
+	    /** version field */
+			t_u8 version;
+		} PACK_END bonjour;
+	} u;
+} PACK_END wifidirect_query_data;
+
+/** Internal WIFIDIRECT structure for Response Data */
+typedef PACK_START struct wifidirect_Response_data {
+	union {
+		PACK_START struct upnp_specific_response {
+	    /** version field */
+			t_u8 version;
+	    /** value */
+			t_u8 value[0];
+		} PACK_END upnp;
+
+		PACK_START struct bonjour_specific_response {
+	    /** DNS name */
+			t_u8 dns[0];
+	    /** DNS type */
+			t_u8 dns_type;
+	    /** version field */
+			t_u8 version;
+	    /** DNS name */
+			t_u8 record[0];
+		} PACK_END bonjour;
+	} u;
+} PACK_END wifidirect_response_data;
+
+/** HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY request */
+typedef PACK_START struct _wifidirect_discovery_request {
+    /** Header */
+	WIFIDIRECT_CMD_HEADER;
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** Category */
+	t_u8 category;
+    /** Action */
+	t_u8 action;
+    /** Dialog taken */
+	t_u8 dialog_taken;
+    /** Advertize protocol IE */
+	t_u8 advertize_protocol_ie[4];
+    /** Query request Length */
+	t_u16 query_len;
+    /** Information identifier */
+	t_u8 info_id[2];
+    /** Request Length */
+	t_u16 request_len;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI sub type */
+	t_u8 oui_sub_type;
+    /** Service update indicator */
+	t_u16 service_update_indicator;
+    /** Vendor Length */
+	t_u16 vendor_len;
+    /** Service protocol */
+	t_u8 service_protocol;
+    /** Service transaction Id */
+	t_u8 service_transaction_id;
+    /** Query Data */
+	wifidirect_query_data disc_query;
+} PACK_END wifidirect_discovery_request;
+
+/** HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY response */
+typedef PACK_START struct _wifidirect_discovery_response {
+    /** Header */
+	WIFIDIRECT_CMD_HEADER;
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** Category */
+	t_u8 category;
+    /** Action */
+	t_u8 action;
+    /** Dialog taken */
+	t_u8 dialog_taken;
+    /** Status code */
+	t_u16 status_code;
+    /** GAS comback reply */
+	t_u16 gas_reply;
+    /** Advertize protocol IE */
+	t_u8 advertize_protocol_ie[4];
+    /** Query response Length */
+	t_u16 query_len;
+    /** Information identifier */
+	t_u8 info_id[2];
+    /** Response Length */
+	t_u16 response_len;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI sub type */
+	t_u8 oui_sub_type;
+    /** Service update indicator */
+	t_u16 service_update_indicator;
+    /** Vendor Length */
+	t_u16 vendor_len;
+    /** Service protocol */
+	t_u8 service_protocol;
+    /** Service transaction Id */
+	t_u8 service_transaction_id;
+    /** Discovery status code */
+	t_u8 disc_status_code;
+    /** Response Data */
+	wifidirect_response_data disc_resp;
+} PACK_END wifidirect_discovery_response;
+
+/** HostCmd_CMD_WIFIDIRECT_GAS_COMEBACK_SERVICE request */
+typedef PACK_START struct _wifidirect_gas_comeback_request {
+    /** Header */
+	WIFIDIRECT_CMD_HEADER;
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** Category */
+	t_u8 category;
+    /** Action */
+	t_u8 action;
+    /** Dialog taken */
+	t_u8 dialog_taken;
+} PACK_END wifidirect_gas_comeback_request;
+
+/** HostCmd_CMD_WIFIDIRECT_GAS_COMEBACK_SERVICE response */
+typedef PACK_START struct _wifidirect_gas_comeback_response {
+    /** Header */
+	WIFIDIRECT_CMD_HEADER;
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** Category */
+	t_u8 category;
+    /** Action */
+	t_u8 action;
+    /** Dialog taken */
+	t_u8 dialog_taken;
+    /** Status code */
+	t_u16 status_code;
+    /** Gas response fragment ID */
+	t_u8 gas_fragment_id;
+    /** GAS comback reply */
+	t_u16 gas_reply;
+    /** Advertize protocol IE */
+	t_u8 advertize_protocol_ie[4];
+    /** Query response Length */
+	t_u16 query_len;
+    /** Information identifier */
+	t_u8 info_id[2];
+    /** Response Length */
+	t_u16 response_len;
+    /** Response status code */
+	t_u8 resp_status_code;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI sub type */
+	t_u8 oui_sub_type;
+    /** Service update indicator */
+	t_u16 service_update_indicator;
+    /** Vendor Length */
+	t_u16 vendor_len;
+    /** Service protocol */
+	t_u8 service_protocol;
+    /** Service transaction Id */
+	t_u8 service_transaction_id;
+    /** Discovery status code */
+	t_u8 disc_status_code;
+    /** Response Data */
+	wifidirect_response_data disc_resp;
+} PACK_END wifidirect_gas_comeback_response;
+
+/** HostCmd_CMD_WIFIDIRECT_ACTION_FRAME request */
+typedef PACK_START struct _wifidirect_action_frame {
+    /** Header */
+	WIFIDIRECT_CMD_HEADER;
+    /** Peer mac address */
+	t_u8 peer_mac_addr[ETH_ALEN];
+    /** Category */
+	t_u8 category;
+    /** Action */
+	t_u8 action;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI type */
+	t_u8 oui_type;
+    /** OUI sub type */
+	t_u8 oui_sub_type;
+    /** Dialog taken */
+	t_u8 dialog_taken;
+    /** IE List of TLVs */
+	t_u8 ie_list[0];
+} PACK_END wifidirect_action_frame;
+
+/** custom IE */
+typedef 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[0];
+} PACK_END custom_ie;
+
+/** TLV buffer : custom IE */
+typedef PACK_START struct _tlvbuf_custom_ie {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** custom IE data */
+	custom_ie ie_data[0];
+} PACK_END tlvbuf_custom_ie;
+
+/** TLV buffer : persistent group */
+typedef PACK_START struct _tlvbuf_wifidirect_persistent_group {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Record Index */
+	t_u8 rec_index;
+    /** Device Role */
+	t_u8 dev_role;
+    /** wifidirect group Bss Id */
+	t_u8 group_bssid[ETH_ALEN];
+    /** wifidirect device MAC address */
+	t_u8 dev_mac_address[ETH_ALEN];
+    /** wifidirect group SSID length */
+	t_u8 group_ssid_len;
+    /** wifidirect group SSID */
+	t_u8 group_ssid[0];
+    /** wifidirect PSK length */
+	t_u8 psk_len;
+    /** wifidirect PSK */
+	t_u8 psk[0];
+    /** Num of PEER MAC Addresses */
+	t_u8 num_peers;
+    /** PEER MAC Addresses List */
+	t_u8 peer_mac_addrs[0][ETH_ALEN];
+} PACK_END tlvbuf_wifidirect_persistent_group;
+
+/** TLV buffer : WifiDirect discovery period */
+typedef PACK_START struct _tlvbuf_wifidirect_discovery_period {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Min discovery interval */
+	t_u16 min_disc_interval;
+    /** Max discovery interval */
+	t_u16 max_disc_interval;
+} PACK_END tlvbuf_wifidirect_discovery_period;
+
+/** TLV buffer : WifiDirect Intent */
+typedef PACK_START struct _tlvbuf_wifidirect_intent {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Intent value */
+	t_u8 intent;
+} PACK_END tlvbuf_wifidirect_intent;
+
+/** TLV buffer : WifiDirect Invitation List */
+typedef PACK_START struct _tlvbuf_wifidirect_invitation_list {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Invitation peer address*/
+	t_u8 inv_peer_addr[ETH_ALEN];
+} PACK_END tlvbuf_wifidirect_invitation_list;
+
+/** TLV buffer : WifiDirect Listen Channel */
+typedef PACK_START struct _tlvbuf_wifidirect_listen_channel {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Country str */
+	t_u8 country_str[3];
+    /** operating class */
+	t_u8 operating_class;
+    /** Listen Channel */
+	t_u8 listen_channel;
+} PACK_END tlvbuf_wifidirect_listen_channel;
+
+/** TLV buffer : WifiDirect Operating Channel */
+typedef PACK_START struct _tlvbuf_wifidirect_operating_channel {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Country str */
+	t_u8 country_str[3];
+    /** operating class */
+	t_u8 operating_class;
+    /** Operating Channel */
+	t_u8 operating_channel;
+} PACK_END tlvbuf_wifidirect_operating_channel;
+
+/** TLV buffer : WifiDirect NoA config */
+typedef PACK_START struct _tlvbuf_wifidirect_noa_config {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Enable/Disable NoA */
+	t_u16 enable_noa;
+    /** Index */
+	t_u8 noa_index;
+    /** CountType */
+	t_u8 count_type;
+    /** Duration */
+	t_u32 duration;
+    /** Interval */
+	t_u32 interval;
+} PACK_END tlvbuf_wifidirect_noa_config;
+
+/** TLV buffer : wifidirect OppPS config */
+typedef PACK_START struct _tlvbuf_opp_ps_config {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** CTWindow and OppPS*/
+	t_u8 ctwindow_opp_ps;
+} PACK_END tlvbuf_wifidirect_opp_ps_config;
+
+/** TLV buffer : wifidirect capability config */
+typedef PACK_START struct _tlvbuf_capability_config {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Device capability */
+	t_u8 dev_capability;
+    /** Group capability */
+	t_u8 group_capability;
+} PACK_END tlvbuf_wifidirect_capability_config;
+
+/** TLV buffer : WifiDirect Presence Request Parameters */
+typedef PACK_START struct _tlvbuf_wifidirect_presence_req_params {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Presence Request Type */
+	t_u8 presence_req_type;
+    /** Duration */
+	t_u32 duration;
+    /** Interval */
+	t_u32 interval;
+} PACK_END tlvbuf_wifidirect_presence_req_params;
+
+/** TLV buffer : WifiDirect Extended Listen Timing parameters*/
+typedef PACK_START struct _tlvbuf_mrvl_wifidirect_ext_listen_time {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** Duration */
+	t_u16 duration;
+    /** Interval */
+	t_u16 interval;
+} PACK_END tlvbuf_wifidirect_mrvl_ext_listen_time;
+
+/** TLV buffer : WifiDirect Provisioning parameters*/
+typedef PACK_START struct _tlvbuf_wifidirect_provisioning_params {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** action */
+	t_u16 action;
+    /** config methods */
+	t_u16 config_methods;
+    /** config methods */
+	t_u16 dev_password;
+} PACK_END tlvbuf_wifidirect_provisioning_params;
+
+/** TLV buffer : WifiDirect WPS parameters*/
+typedef PACK_START struct _tlvbuf_wifidirect_wps_params {
+    /** Tag */
+	t_u16 tag;
+    /** Length */
+	t_u16 length;
+    /** action */
+	t_u16 action;
+} PACK_END tlvbuf_wifidirect_wps_params;
+
+/** Max size of custom IE buffer */
+#define MAX_SIZE_IE_BUFFER              (256)
+/** Size of command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+/** Maximum size of set/get configurations */
+#define MAX_CFG_DATA_SIZE   2000	/* less than MRVDRV_SIZE_OF_CMD_BUFFER */
+/** 4 byte header to store buf len*/
+#define BUF_HEADER_SIZE     4
+/** OUI Type WFA WIFIDIRECT */
+#define OUI_TYPE_WFA_WIFIDIRECT    9
+
+/** MRVL private command ioctl number */
+#define MRVLPRIVCMD          (SIOCDEVPRIVATE + 14)
+/** Host Command ID bit mask (bit 11:0) */
+#define HostCmd_CMD_ID_MASK             0x0fff
+/** WIFIDIRECTCMD response check */
+#define WIFIDIRECTCMD_RESP_CHECK                0x8000
+
+#ifdef WIFI_DISPLAY
+/** Host Command ID : wfd display mode config */
+#define HostCmd_CMD_WFD_DISPLAY_MODE_CONFIG         0x0106
+#endif
+
+/** Host Command ID : wifidirect mode config */
+#define HostCmd_CMD_WIFIDIRECT_MODE_CONFIG         0x00eb
+/** Host Command ID:  WIFIDIRECT_SET_PARAMS */
+#define HostCmd_CMD_WIFIDIRECT_PARAMS_CONFIG       0x00ea
+/** Host Command ID:  WIFIDIRECT_SERVICE_DISCOVERY */
+#define HostCmd_CMD_WIFIDIRECT_SERVICE_DISCOVERY   0x00ec
+/** Host Command ID:  WIFIDIRECT_ACTION_FRAME */
+#define HostCmd_CMD_802_11_ACTION_FRAME             0x00f4
+
+/** TLV : WifiDirect param capability */
+#define TLV_TYPE_WIFIDIRECT_CAPABILITY           0x0002
+/** TLV : WifiDirect param device Id */
+#define TLV_TYPE_WIFIDIRECT_DEVICE_ID            0x0003
+/** TLV : WifiDirect param group owner intent */
+#define TLV_TYPE_WIFIDIRECT_GROUPOWNER_INTENT    0x0004
+/** TLV : WifiDirect param config timeout */
+#define TLV_TYPE_WIFIDIRECT_CONFIG_TIMEOUT       0x0005
+/** TLV : WifiDirect param channel */
+#define TLV_TYPE_WIFIDIRECT_CHANNEL              0x0006
+/** TLV : WifiDirect param group bssId */
+#define TLV_TYPE_WIFIDIRECT_GROUP_BSS_ID         0x0007
+/** TLV : WifiDirect param extended listen time */
+#define TLV_TYPE_WIFIDIRECT_EXTENDED_LISTEN_TIME 0x0008
+/** TLV : WifiDirect param intended address */
+#define TLV_TYPE_WIFIDIRECT_INTENDED_ADDRESS     0x0009
+/** TLV : WifiDirect param manageability */
+#define TLV_TYPE_WIFIDIRECT_MANAGEABILITY        0x000a
+/** TLV : WifiDirect param channel list */
+#define TLV_TYPE_WIFIDIRECT_CHANNEL_LIST         0x000b
+/** TLV : WifiDirect Notice of Absence */
+#define TLV_TYPE_WIFIDIRECT_NOTICE_OF_ABSENCE    0x000c
+/** TLV : WifiDirect param device Info */
+#define TLV_TYPE_WIFIDIRECT_DEVICE_INFO          0x000d
+/** TLV : WifiDirect param Group Info */
+#define TLV_TYPE_WIFIDIRECT_GROUP_INFO           0x000e
+/** TLV : WifiDirect param group Id */
+#define TLV_TYPE_WIFIDIRECT_GROUP_ID             0x000f
+/** TLV : WifiDirect param interface */
+#define TLV_TYPE_WIFIDIRECT_INTERFACE            0x0010
+/** TLV : WifiDirect param operating channel */
+#define TLV_TYPE_WIFIDIRECT_OPCHANNEL            0x0011
+/** TLV : WifiDirect param invitation flag */
+#define TLV_TYPE_WIFIDIRECT_INVITATION_FLAG      0x0012
+
+/** enum : WPS attribute type */
+typedef enum {
+	SC_AP_Channel = 0x1001,
+	SC_Association_State = 0x1002,
+	SC_Authentication_Type = 0x1003,
+	SC_Authentication_Type_Flags = 0x1004,
+	SC_Authenticator = 0x1005,
+	SC_Config_Methods = 0x1008,
+	SC_Configuration_Error = 0x1009,
+	SC_Confirmation_URL4 = 0x100A,
+	SC_Confirmation_URL6 = 0x100B,
+	SC_Connection_Type = 0x100C,
+	SC_Connection_Type_Flags = 0x100D,
+	SC_Credential = 0x100E,
+	SC_Device_Name = 0x1011,
+	SC_Device_Password_ID = 0x1012,
+	SC_E_Hash1 = 0x1014,
+	SC_E_Hash2 = 0x1015,
+	SC_E_SNonce1 = 0x1016,
+	SC_E_SNonce2 = 0x1017,
+	SC_Encrypted_Settings = 0x1018,
+	SC_Encryption_Type = 0X100F,
+	SC_Encryption_Type_Flags = 0x1010,
+	SC_Enrollee_Nonce = 0x101A,
+	SC_Feature_ID = 0x101B,
+	SC_Identity = 0X101C,
+	SC_Identity_Proof = 0X101D,
+	SC_Key_Wrap_Authenticator = 0X101E,
+	SC_Key_Identifier = 0X101F,
+	SC_MAC_Address = 0x1020,
+	SC_Manufacturer = 0x1021,
+	SC_Message_Type = 0x1022,
+	SC_Model_Name = 0x1023,
+	SC_Model_Number = 0x1024,
+	SC_Network_Index = 0x1026,
+	SC_Network_Key = 0x1027,
+	SC_Network_Key_Index = 0x1028,
+	SC_New_Device_Name = 0x1029,
+	SC_New_Password = 0x102A,
+	SC_OOB_Device_Password = 0X102C,
+	SC_OS_Version = 0X102D,
+	SC_Power_Level = 0X102F,
+	SC_PSK_Current = 0x1030,
+	SC_PSK_Max = 0x1031,
+	SC_Public_Key = 0x1032,
+	SC_Radio_Enabled = 0x1033,
+	SC_Reboot = 0x1034,
+	SC_Registrar_Current = 0x1035,
+	SC_Registrar_Established = 0x1036,
+	SC_Registrar_List = 0x1037,
+	SC_Registrar_Max = 0x1038,
+	SC_Registrar_Nonce = 0x1039,
+	SC_Request_Type = 0x103A,
+	SC_Response_Type = 0x103B,
+	SC_RF_Band = 0X103C,
+	SC_R_Hash1 = 0X103D,
+	SC_R_Hash2 = 0X103E,
+	SC_R_SNonce1 = 0X103F,
+	SC_R_SNonce2 = 0x1040,
+	SC_Selected_Registrar = 0x1041,
+	SC_Serial_Number = 0x1042,
+	SC_Simple_Config_State = 0x1044,
+	SC_SSID = 0x1045,
+	SC_Total_Networks = 0x1046,
+	SC_UUID_E = 0x1047,
+	SC_UUID_R = 0x1048,
+	SC_Vendor_Extension = 0x1049,
+	SC_Version = 0x104A,
+	SC_X_509_Certificate_Request = 0x104B,
+	SC_X_509_Certificate = 0x104C,
+	SC_EAP_Identity = 0x104D,
+	SC_Message_Counter = 0x104E,
+	SC_Public_Key_Hash = 0x104F,
+	SC_Rekey_Key = 0x1050,
+	SC_Key_Lifetime = 0x1051,
+	SC_Permitted_Config_Methods = 0x1052,
+	SC_SelectedRegistrarConfigMethods = 0x1053,
+	SC_Primary_Device_Type = 0x1054,
+	SC_Secondary_Device_Type_List = 0x1055,
+	SC_Portable_Device = 0x1056,
+	SC_AP_Setup_Locked = 0x1057,
+	SC_Application_List = 0x1058,
+	SC_EAP_Type = 0x1059,
+	SC_Initialization_Vector = 0x1060,
+	SC_Key_Provided_Auto = 0x1061,
+	SC_8021x_Enabled = 0x1062,
+	SC_App_Session_key = 0x1063,
+	SC_WEP_Transmit_Key = 0x1064,
+} wps_simple_config_attribute;
+
+/** Function Prototype Declaration */
+int is_input_valid(valid_inputs cmd, int argc, char *argv[]);
+unsigned char hexc2bin(char chr);
+
+char *config_get_line(char *s, int size, FILE * stream, int *line, char **_pos);
+int parse_line(char *line, char *args[]);
+int mac2raw(char *mac, t_u8 *raw);
+int wifidirect_ioctl(t_u8 *cmd, t_u16 *size, t_u16 buf_size);
+unsigned int a2hex(char *s);
+
+/**
+ *    @brief isdigit for String.
+ *
+ *    @param x            Char string
+ *    @return             FAILURE for non-digit.
+ *                        SUCCESS for digit
+ */
+static inline int
+ISDIGIT(char *x)
+{
+	unsigned int i;
+	for (i = 0; i < strlen(x); i++)
+		if (isdigit(x[i]) == 0)
+			return FAILURE;
+	return SUCCESS;
+}
+#endif /* _WIFIDIRECT_H */
diff --git a/wlan_sd8897/mlan/mlan.h b/wlan_sd8897/mlan/mlan.h
new file mode 100644
index 0000000..2afcb54
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan.h
@@ -0,0 +1,35 @@
+/** @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 (C) 2008-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+/******************************************************
+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_sd8897/mlan/mlan_11ac.c b/wlan_sd8897/mlan/mlan_11ac.c
new file mode 100644
index 0000000..986e799
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11ac.c
@@ -0,0 +1,1383 @@
+/** @file mlan_11ac.c
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *  Copyright (C) 2011-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+
+#define NO_NSS_SUPPORT 0x3
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+t_u16 wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u8 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(IN mlan_private *pmpriv,
+			 IN t_u8 band, IN t_u32 pri_chan, IN 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;
+			}
+		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;
+			}
+		case 100:
+		case 104:
+		case 108:
+		case 112:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 106;
+				break;
+			}
+		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;
+			}
+		case 132:
+		case 136:
+		case 140:
+		case 144:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 138;
+				break;
+			}
+		case 149:
+		case 153:
+		case 157:
+		case 161:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 155;
+				break;
+			}
+		case 165:
+		case 169:
+		case 173:
+		case 177:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 171;
+				break;
+			}
+		case 184:
+		case 188:
+		case 192:
+		case 196:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 190;
+				break;
+			}
+
+		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 number of nss which supports VHT mcs
+ *
+ *  @param mcs_map_set  VHT mcs map
+ *
+ *  @return             Number of supported nss
+ */
+static t_u8
+wlan_get_nss_num_vht_mcs(t_u16 mcs_map_set)
+{
+	t_u8 nss, nss_num = 0;
+	for (nss = 1; nss <= 8; nss++) {
+		if (GET_VHTNSSMCS(mcs_map_set, nss) != NO_NSS_SUPPORT)
+			nss_num++;
+	}
+	PRINTM(MCMND, "Supported nss:%d\n", nss_num);
+	return nss_num;
+}
+
+/**
+ *  @brief This function fills the cap info
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_fill_cap_info(mlan_private *priv, VHT_capa_t *vht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11ac_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_bg;
+
+	vht_cap->vht_cap_info = usr_dot_11ac_dev_cap;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Set/get 11ac configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_11ac_ioctl_vhtcfg(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_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;
+
+	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) {
+			/* 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 ((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 ((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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+				  IN 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(pmadapter, cfg->param.supported_mcs_set, mcs_set, NUM_MCS_SUPP);
+
+#endif
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function prints the 802.11ac device capability
+ *
+ *  @param pmadapter     A pointer to mlan_adapter structure
+ *  @param cap           Capability value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_dot11acdevcap(pmlan_adapter pmadapter, t_u32 cap)
+{
+	ENTER();
+
+	switch (GET_VHTCAP_MAXMPDULEN(cap)) {
+	case 0x0:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MSDU length = 3895 octets\n");
+		break;
+	case 0x1:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MSDU length = 7991 octets\n");
+		break;
+	case 0x2:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MSDU length = 11454 octets\n");
+		break;
+	default:
+		PRINTM(MINFO, "Unsupport value\n");
+		break;
+	}
+
+	PRINTM(MINFO, "GET_HW_SPEC: HTC-VHT %s\n",
+	       (ISSUPP_11ACVHTHTCVHT(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: VHT TXOP PS %s\n",
+	       (ISSUPP_11ACVHTTXOPPS(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: MU RX beamformee %s\n",
+	       (ISSUPP_11ACMURXBEAMFORMEE(cap) ? "supported" :
+		"not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: MU TX beamformee %s\n",
+	       (ISSUPP_11ACMUTXBEAMFORMEE(cap) ? "supported" :
+		"not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: SU RX Beamformee %s\n",
+	       (ISSUPP_11ACSUBEAMFORMEE(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: SU TX Beamformer %s\n",
+	       (ISSUPP_11ACSUBEAMFORMER(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n",
+	       (ISSUPP_11ACRXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n",
+	       (ISSUPP_11ACTXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 160MHz BW\n",
+	       (ISSUPP_11ACSGI160(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 80MHz BW\n",
+	       (ISSUPP_11ACSGI80(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: LDPC coding %s\n",
+	       (ISSUPP_11ACLDPC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160/80+80 MHz %s\n",
+	       (ISSUPP_11ACBW8080(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160 MHz %s\n",
+	       (ISSUPP_11ACBW160(cap) ? "supported" : "not supported"));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function prints the 802.11ac device MCS
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param support   Support value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_dot11acmcssupport(pmlan_adapter pmadapter, t_u32 support)
+{
+	ENTER();
+
+	PRINTM(MINFO, "GET_HW_SPEC: MCSs for %2dx%2d MIMO\n",
+	       GET_DEVRXMCSMAP(support), GET_DEVTXMCSMAP(support));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function converts the 2-bit MCS map to the highest long GI
+ *  VHT PPDU data rate
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param bands        Supported bands
+ *  @param mcs_map      2-bit MCS map
+ *
+ *  @return             the max data rate for long GI
+ */
+t_u16
+wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u8 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
+ *  @return             N/A
+ */
+void
+wlan_fill_vht_cap_tlv(mlan_private *priv,
+		      MrvlIETypes_VHTCap_t *pvht_cap, t_u8 bands, t_u8 flag)
+{
+	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;
+
+	ENTER();
+
+	/* Fill VHT cap info */
+	wlan_fill_cap_info(priv, &pvht_cap->vht_cap, bands);
+	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);
+	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));
+	}
+	/* 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 ((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_u8 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 append the 802_11AC 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;
+	MrvlIETypes_VHTOprat_t *pvht_op;
+	t_u8 supp_chwd_set;
+	t_u32 usr_vht_cap_info;
+	int ret_len = 0;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (pbss_desc->bss_band & BAND_A)
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_bg;
+
+	/* 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(pmadapter,
+		       (t_u8 *)pvht_cap + sizeof(MrvlIEtypesHeader_t),
+		       (t_u8 *)pbss_desc->pvht_cap + sizeof(IEEEtypes_Header_t),
+		       pvht_cap->header.len);
+
+		wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pbss_desc->bss_band,
+				      MTRUE);
+
+		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;
+	}
+
+	/* VHT Operation IE */
+	if (pbss_desc->pvht_oprat) {
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+			pvht_op = (MrvlIETypes_VHTOprat_t *)*ppbuffer;
+			memset(pmadapter, pvht_op, 0,
+			       sizeof(MrvlIETypes_VHTOprat_t));
+			pvht_op->header.type = wlan_cpu_to_le16(VHT_OPERATION);
+			pvht_op->header.len = sizeof(MrvlIETypes_VHTOprat_t) -
+				sizeof(MrvlIEtypesHeader_t);
+			memcpy(pmadapter,
+			       (t_u8 *)pvht_op + sizeof(MrvlIEtypesHeader_t),
+			       (t_u8 *)pbss_desc->pvht_oprat +
+			       sizeof(IEEEtypes_Header_t), pvht_op->header.len);
+
+			/* negotiate the channel width and central freq */
+			/* and keep the central freq as the peer suggests */
+			supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
+			if (supp_chwd_set == VHT_CAP_CHWD_80MHZ)
+				pvht_op->chan_width = MIN(VHT_OPER_CHWD_80MHZ,
+							  pbss_desc->
+							  pvht_oprat->
+							  chan_width);
+			else if (supp_chwd_set == VHT_CAP_CHWD_160MHZ)
+				pvht_op->chan_width = MIN(VHT_OPER_CHWD_160MHZ,
+							  pbss_desc->
+							  pvht_oprat->
+							  chan_width);
+			else if (supp_chwd_set == VHT_CAP_CHWD_80_80MHZ)
+				pvht_op->chan_width =
+					MIN(VHT_OPER_CHWD_80_80MHZ,
+					    pbss_desc->pvht_oprat->chan_width);
+			else
+				pvht_op->chan_width = VHT_OPER_CHWD_20_40MHZ;
+	    /** current region don't allow bandwidth 80 */
+			if (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_80MHZ)
+				pvht_op->chan_width = VHT_OPER_CHWD_20_40MHZ;
+			HEXDUMP("VHT_OPERATION IE", (t_u8 *)pvht_op,
+				sizeof(MrvlIETypes_VHTOprat_t));
+			*ppbuffer += sizeof(MrvlIETypes_VHTOprat_t);
+			ret_len += sizeof(MrvlIETypes_VHTOprat_t);
+			pvht_op->header.len =
+				wlan_cpu_to_le16(pvht_op->header.len);
+		}
+	}
+	/* 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);
+
+		mcs_map_user =
+			GET_DEVRXMCSMAP(pmpriv->usr_dot_11ac_mcs_support);
+		nss = wlan_get_nss_num_vht_mcs(mcs_map_user);
+		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(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *cmd,
+		  IN t_u16 cmd_action, IN 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;
+	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(pmadapter, &vhtcfg->vht_supp_mcs_set[0],
+	       &vht_cfg->vht_rx_mcs, sizeof(t_u32));
+	vht_cfg->vht_tx_mcs = wlan_cpu_to_le32(vht_cfg->vht_tx_mcs);
+	memcpy(pmadapter, &vhtcfg->vht_supp_mcs_set[4],
+	       &vht_cfg->vht_tx_mcs, sizeof(t_u32));
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of 11ac 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_11ac_cfg(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *resp, IN 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(pmadapter, &cfg->param.vht_cfg.vht_rx_mcs,
+		       &vhtcfg->vht_supp_mcs_set[0], sizeof(t_u32));
+		cfg->param.vht_cfg.vht_rx_mcs =
+			wlan_le32_to_cpu(cfg->param.vht_cfg.vht_rx_mcs);
+		memcpy(pmadapter, &cfg->param.vht_cfg.vht_tx_mcs,
+		       &vhtcfg->vht_supp_mcs_set[4], 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_u8 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_sd8897/mlan/mlan_11ac.h b/wlan_sd8897/mlan/mlan_11ac.h
new file mode 100644
index 0000000..f935ebc
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11ac.h
@@ -0,0 +1,55 @@
+/** @file mlan_11ac.h
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *  Copyright (C) 2011-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+#ifndef _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_u8 bands,
+				     t_u16 mcs_map);
+void wlan_fill_vht_cap_tlv(mlan_private *priv, MrvlIETypes_VHTCap_t *pvht_cap,
+			   t_u8 bands, t_u8 flag);
+void wlan_fill_vht_cap_ie(mlan_private *priv, IEEEtypes_VHTCap_t *pvht_cap,
+			  t_u8 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_u8 bss_band);
+
+mlan_status wlan_cmd_11ac_cfg(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_11ac_cfg(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN mlan_ioctl_req *pioctl_buf);
+
+#endif /* _MLAN_11AC_H_ */
diff --git a/wlan_sd8897/mlan/mlan_11d.c b/wlan_sd8897/mlan/mlan_11d.c
new file mode 100644
index 0000000..a5d5332
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11d.c
@@ -0,0 +1,1599 @@
+/** @file mlan_11d.c
+ *
+ *  @brief This file contains functions for 802.11D.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+/********************************************************
+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 */
+};
+
+/** Universal region code */
+#define UNIVERSAL_REGION_CODE   0xff
+#endif
+
+/** Default Tx power */
+#define TX_PWR_DEFAULT  10
+
+/* Following two structures define the supported channels */
+/** Channels for 802.11b/g */
+static chan_freq_power_t channel_freq_power_UN_BG[] = {
+	{1, 2412, TX_PWR_DEFAULT},
+	{2, 2417, TX_PWR_DEFAULT},
+	{3, 2422, TX_PWR_DEFAULT},
+	{4, 2427, TX_PWR_DEFAULT},
+	{5, 2432, TX_PWR_DEFAULT},
+	{6, 2437, TX_PWR_DEFAULT},
+	{7, 2442, TX_PWR_DEFAULT},
+	{8, 2447, TX_PWR_DEFAULT},
+	{9, 2452, TX_PWR_DEFAULT},
+	{10, 2457, TX_PWR_DEFAULT},
+	{11, 2462, TX_PWR_DEFAULT},
+	{12, 2467, TX_PWR_DEFAULT},
+	{13, 2472, TX_PWR_DEFAULT},
+	{14, 2484, TX_PWR_DEFAULT}
+};
+
+/** Channels for 802.11a/j */
+static chan_freq_power_t channel_freq_power_UN_AJ[] = {
+	{8, 5040, TX_PWR_DEFAULT},
+	{12, 5060, TX_PWR_DEFAULT},
+	{16, 5080, TX_PWR_DEFAULT},
+	{34, 5170, TX_PWR_DEFAULT},
+	{38, 5190, TX_PWR_DEFAULT},
+	{42, 5210, TX_PWR_DEFAULT},
+	{46, 5230, TX_PWR_DEFAULT},
+	{36, 5180, TX_PWR_DEFAULT},
+	{40, 5200, TX_PWR_DEFAULT},
+	{44, 5220, TX_PWR_DEFAULT},
+	{48, 5240, TX_PWR_DEFAULT},
+	{52, 5260, TX_PWR_DEFAULT},
+	{56, 5280, TX_PWR_DEFAULT},
+	{60, 5300, TX_PWR_DEFAULT},
+	{64, 5320, TX_PWR_DEFAULT},
+	{100, 5500, TX_PWR_DEFAULT},
+	{104, 5520, TX_PWR_DEFAULT},
+	{108, 5540, TX_PWR_DEFAULT},
+	{112, 5560, TX_PWR_DEFAULT},
+	{116, 5580, TX_PWR_DEFAULT},
+	{120, 5600, TX_PWR_DEFAULT},
+	{124, 5620, TX_PWR_DEFAULT},
+	{128, 5640, TX_PWR_DEFAULT},
+	{132, 5660, TX_PWR_DEFAULT},
+	{136, 5680, TX_PWR_DEFAULT},
+	{140, 5700, TX_PWR_DEFAULT},
+	{149, 5745, TX_PWR_DEFAULT},
+	{153, 5765, TX_PWR_DEFAULT},
+	{157, 5785, TX_PWR_DEFAULT},
+	{161, 5805, TX_PWR_DEFAULT},
+	{165, 5825, TX_PWR_DEFAULT},
+/*  {240, 4920, TX_PWR_DEFAULT},
+    {244, 4940, TX_PWR_DEFAULT},
+    {248, 4960, TX_PWR_DEFAULT},
+    {252, 4980, TX_PWR_DEFAULT},
+channels for 11J JP 10M channel gap */
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function converts integer code to region string
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param code         Region code
+ *
+ *  @return             Region string
+ */
+static t_u8 *
+wlan_11d_code_2_region(pmlan_adapter pmadapter, t_u8 code)
+{
+	t_u8 i;
+
+	ENTER();
+
+	/* Look for code in mapping table */
+	for (i = 0; i < NELEMENTS(region_code_mapping); i++) {
+		if (region_code_mapping[i].code == code) {
+			LEAVE();
+			return region_code_mapping[i].region;
+		}
+	}
+
+	LEAVE();
+	/* Default is US */
+	return region_code_mapping[0].region;
+}
+
+/**
+ *  @brief This function Checks if channel txpwr is learned from AP/IBSS
+ *
+ *  @param pmadapter            A pointer to mlan_adapter structure
+ *  @param band                 Band number
+ *  @param chan                 Channel number
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     MTRUE or MFALSE
+ */
+static t_u8
+wlan_11d_channel_known(pmlan_adapter pmadapter,
+		       t_u8 band,
+		       t_u8 chan, parsed_region_chan_11d_t *parsed_region_chan)
+{
+	chan_power_11d_t *pchan_pwr = parsed_region_chan->chan_pwr;
+	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+	t_u8 i = 0;
+	t_u8 ret = MFALSE;
+	mlan_private *pmpriv;
+
+	ENTER();
+
+	HEXDUMP("11D: parsed_region_chan", (t_u8 *)pchan_pwr,
+		sizeof(chan_power_11d_t) * no_of_chan);
+
+	/* Search channel */
+	for (i = 0; i < no_of_chan; i++) {
+		if (chan == pchan_pwr[i].chan && band == pchan_pwr[i].band) {
+			PRINTM(MINFO, "11D: Found channel:%d (band:%d)\n", chan,
+			       band);
+			ret = MTRUE;
+
+			if (band & BAND_A) {
+				/* If chan is a DFS channel, we need to see an AP on it */
+				pmpriv = wlan_get_priv(pmadapter,
+						       MLAN_BSS_ROLE_STA);
+				if (pmpriv &&
+				    wlan_11h_radar_detect_required(pmpriv,
+								   chan)) {
+					PRINTM(MINFO,
+					       "11H: DFS channel %d, and ap_seen=%d\n",
+					       chan, pchan_pwr[i].ap_seen);
+					ret = pchan_pwr[i].ap_seen;
+				}
+			}
+
+			LEAVE();
+			return ret;
+		}
+	}
+
+	PRINTM(MINFO, "11D: Could not find channel:%d (band:%d)\n", chan, band);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function generates parsed_region_chan from Domain Info
+ *           learned from AP/IBSS
+ *
+ *  @param pmadapter            Pointer to mlan_adapter structure
+ *  @param region_chan          Pointer to region_chan_t
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     N/A
+ */
+static t_void
+wlan_11d_generate_parsed_region_chan(pmlan_adapter pmadapter,
+				     region_chan_t *region_chan,
+				     parsed_region_chan_11d_t
+				     *parsed_region_chan)
+{
+	chan_freq_power_t *cfp;
+	t_u8 i;
+
+	ENTER();
+
+	/* Region channel must be provided */
+	if (!region_chan) {
+		PRINTM(MWARN, "11D: region_chan is MNULL\n");
+		LEAVE();
+		return;
+	}
+
+	/* Get channel-frequency-power trio */
+	cfp = region_chan->pcfp;
+	if (!cfp) {
+		PRINTM(MWARN, "11D: cfp equal MNULL\n");
+		LEAVE();
+		return;
+	}
+
+	/* Set channel, band and power */
+	for (i = 0; i < region_chan->num_cfp; i++, cfp++) {
+		parsed_region_chan->chan_pwr[i].chan = (t_u8)cfp->channel;
+		parsed_region_chan->chan_pwr[i].band = region_chan->band;
+		parsed_region_chan->chan_pwr[i].pwr = (t_u8)cfp->max_tx_power;
+		PRINTM(MINFO, "11D: Chan[%d] Band[%d] Pwr[%d]\n",
+		       parsed_region_chan->chan_pwr[i].chan,
+		       parsed_region_chan->chan_pwr[i].band,
+		       parsed_region_chan->chan_pwr[i].pwr);
+	}
+	parsed_region_chan->no_of_chan = region_chan->num_cfp;
+
+	PRINTM(MINFO, "11D: no_of_chan[%d]\n", parsed_region_chan->no_of_chan);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function generates domain_info from parsed_region_chan
+ *
+ *  @param pmadapter            Pointer to mlan_adapter structure
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11d_generate_domain_info(pmlan_adapter pmadapter,
+			      parsed_region_chan_11d_t *parsed_region_chan)
+{
+	t_u8 no_of_sub_band = 0;
+	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+	t_u8 no_of_parsed_chan = 0;
+	t_u8 first_chan = 0, next_chan = 0, max_pwr = 0;
+	t_u8 i, flag = MFALSE;
+	wlan_802_11d_domain_reg_t *domain_info = &pmadapter->domain_reg;
+
+	ENTER();
+
+	/* Should be only place that clear domain_reg (besides init) */
+	memset(pmadapter, domain_info, 0, sizeof(wlan_802_11d_domain_reg_t));
+
+	/* Set country code */
+	memcpy(pmadapter, domain_info->country_code,
+	       wlan_11d_code_2_region(pmadapter, (t_u8)pmadapter->region_code),
+	       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(pmadapter, parsed_region_chan,
+		       &region_chan, 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(pmadapter, pdomain->country_code, country_code,
+	       COUNTRY_CODE_LEN);
+	pdomain->band = band;
+	pdomain->no_of_sub_band = num_sub_band;
+	memcpy(pmadapter, pdomain->sub_band, sub_band_list,
+	       MIN(MRVDRV_MAX_SUBBAND_802_11D,
+		   num_sub_band) * 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) ? 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;
+
+	ENTER();
+
+	PRINTM(MINFO, "11D: number of sub-band=0x%x\n", no_of_sub_band);
+
+	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(pmadapter, domain->country_code,
+	       pmadapter->domain_reg.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(pmadapter, domain->sub_band,
+		       pmadapter->domain_reg.sub_band,
+		       MIN(MRVDRV_MAX_SUBBAND_802_11D,
+			   no_of_sub_band) * 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(pmadapter, &region_chan,
+		       &pmadapter->parsed_region_chan,
+		       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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			 IN 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();
+
+	cfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+	domain_info = &cfg_11d->param.domain_info;
+	memcpy(pmadapter, pmadapter->country_code, domain_info->country_code,
+	       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_bg && cfp_a && (cfp_bg == cfp_a))
+		pmadapter->region_code = cfp_a;
+	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_bg && cfp_a && (cfp_bg == cfp_a))
+			pmadapter->region_code = cfp_a;
+		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(pmadapter, pmadapter->country_code, pdomain_tlv->country_code,
+	       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_sd8897/mlan/mlan_11h.c b/wlan_sd8897/mlan/mlan_11h.c
new file mode 100644
index 0000000..6e0f8ed
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11h.c
@@ -0,0 +1,3991 @@
+/** @file mlan_11h.c
+ *
+ *  @brief This file contains functions for 802.11H.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+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 = 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 Marvell
+ *         proprietary format
+ *
+ *  @param pmadapter Pointer to mlan_adapter
+ *  @param pout_buf Output parameter: Buffer to output Marvell formatted IE
+ *  @param pin_ie   Pointer to IEEE IE to be converted to Marvell 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 Marvell 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(pmadapter, ptmp_buf, &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(pmadapter, ptmp_buf, pin_ie + 2, 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(adapter, pdfs->dfs_owner, priv->curr_addr,
+	       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;
+		}
+	}
+
+	/*
+	 * 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(priv->adapter, &pcmd_ptr->params.tpc_req, pinfo_buf,
+	       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(priv->adapter, &pcmd_ptr->params.chan_sw_ann, pch_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)
+{
+	const 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;
+
+	/*
+	 * 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;
+
+	ENTER();
+	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(priv->adapter, &pcmd_ptr->params.chan_rpt_req, pchan_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);
+	}
+
+	/* 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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, &sup_chan_ie, 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(adapter, dfs_elem.dfs_owner,
+		       p11h_bss_info->ibss_dfs.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, OUT 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(IN 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 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(IN mlan_adapter *pmadapter,
+				  OUT mlan_ioctl_req **ppioctl_req,
+				  IN t_bool is_adding_ie)
+{
+	mlan_ioctl_req *pioctl_req = MNULL;
+	mlan_ds_misc_cfg *pds_misc_cfg = MNULL;
+	custom_ie *pcust_chansw_ie = MNULL;
+	IEEEtypes_ChanSwitchAnn_t *pchansw_ie = MNULL;
+	mlan_status ret;
+	IEEEtypes_Header_t *pChanSwWrap_ie = MNULL;
+	IEEEtypes_WideBWChanSwitch_t *pbwchansw_ie = MNULL;
+	IEEEtypes_VhtTpcEnvelope_t *pvhttpcEnv_ie = MNULL;
+	t_u8 index;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	if (pmadapter == MNULL || ppioctl_req == MNULL) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* allocate buffer for mlan_ioctl_req and mlan_ds_misc_cfg */
+	/* FYI - will be freed as part of cmd_response handler */
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(mlan_ioctl_req) +
+					       sizeof(mlan_ds_misc_cfg),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pioctl_req);
+	if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+		PRINTM(MERROR, "%s(): Could not allocate ioctl req\n",
+		       __func__);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pds_misc_cfg = (mlan_ds_misc_cfg *)((t_u8 *)pioctl_req +
+					    sizeof(mlan_ioctl_req));
+
+	/* prepare mlan_ioctl_req */
+	memset(pmadapter, pioctl_req, 0x00, sizeof(mlan_ioctl_req));
+	pioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	pioctl_req->action = MLAN_ACT_SET;
+	pioctl_req->pbuf = (t_u8 *)pds_misc_cfg;
+	pioctl_req->buf_len = sizeof(mlan_ds_misc_cfg);
+
+	/* prepare mlan_ds_misc_cfg */
+	memset(pmadapter, pds_misc_cfg, 0x00, sizeof(mlan_ds_misc_cfg));
+	pds_misc_cfg->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	pds_misc_cfg->param.cust_ie.type = TLV_TYPE_MGMT_IE;
+	pds_misc_cfg->param.cust_ie.len = (sizeof(custom_ie) - MAX_IE_SIZE);
+
+	/* configure custom_ie api settings */
+	pcust_chansw_ie =
+		(custom_ie *)&pds_misc_cfg->param.cust_ie.ie_data_list[0];
+	pcust_chansw_ie->ie_index = 0xffff;	/* Auto index */
+	pcust_chansw_ie->ie_length = sizeof(IEEEtypes_ChanSwitchAnn_t);
+	pcust_chansw_ie->mgmt_subtype_mask = (is_adding_ie)
+		? MBIT(8) | MBIT(5)	/* add IE for BEACON | PROBE_RSP */
+		: 0;		/* remove IE */
+
+	/* prepare CHAN_SW IE inside ioctl */
+	pchansw_ie = (IEEEtypes_ChanSwitchAnn_t *)pcust_chansw_ie->ie_buffer;
+	pchansw_ie->element_id = CHANNEL_SWITCH_ANN;
+	pchansw_ie->len =
+		sizeof(IEEEtypes_ChanSwitchAnn_t) - sizeof(IEEEtypes_Header_t);
+	pchansw_ie->chan_switch_mode = 1;	/* STA should not transmit */
+	pchansw_ie->new_channel_num = pmadapter->state_rdh.new_channel;
+
+	pchansw_ie->chan_switch_count = pmadapter->dfs_cs_count;
+	PRINTM(MCMD_D, "New Channel = %d Channel switch count = %d\n",
+	       pmadapter->state_rdh.new_channel, pchansw_ie->chan_switch_count);
+
+	for (index = 0; index < pmadapter->state_rdh.priv_list_count; index++) {
+		pmpriv = pmadapter->state_rdh.priv_list[index];
+		/*find the first AP interface */
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+			if (pmpriv->is_11ac_enabled) {
+
+				pChanSwWrap_ie =
+					(IEEEtypes_Header_t *)((t_u8 *)
+							       pchansw_ie +
+							       sizeof
+							       (IEEEtypes_ChanSwitchAnn_t));
+				pChanSwWrap_ie->element_id = EXT_POWER_CONSTR;
+				/*will have multiple sub IEs */
+				pChanSwWrap_ie->len = 0;
+
+				/* prepare the Wide Bandwidth Channel Switch IE
+				 * Channel Switch IE */
+				pbwchansw_ie =
+					(IEEEtypes_WideBWChanSwitch_t
+					 *)((t_u8 *)pChanSwWrap_ie +
+					    sizeof(IEEEtypes_Header_t));
+				pbwchansw_ie->ieee_hdr.element_id =
+					BW_CHANNEL_SWITCH;
+				pbwchansw_ie->ieee_hdr.len =
+					sizeof(IEEEtypes_WideBWChanSwitch_t) -
+					sizeof(IEEEtypes_Header_t);
+				/*fix 80MHZ now */
+				pbwchansw_ie->new_channel_width =
+					VHT_OPER_CHWD_80MHZ;
+				pbwchansw_ie->new_channel_center_freq0 =
+					wlan_11h_get_channel_freq_idx
+					(pmadapter->state_rdh.new_channel);
+				pbwchansw_ie->new_channel_center_freq1 =
+					wlan_11h_get_channel_freq_idx
+					(pmadapter->state_rdh.new_channel);
+				pChanSwWrap_ie->len +=
+					sizeof(IEEEtypes_WideBWChanSwitch_t);
+
+				/*prepare the VHT Transmit Power Envelope IE */
+				pvhttpcEnv_ie =
+					(IEEEtypes_VhtTpcEnvelope_t *)((t_u8 *)
+								       pChanSwWrap_ie
+								       +
+								       sizeof
+								       (IEEEtypes_Header_t)
+								       +
+								       sizeof
+								       (IEEEtypes_WideBWChanSwitch_t));
+				pvhttpcEnv_ie->ieee_hdr.element_id =
+					VHT_TX_POWER_ENV;
+				pvhttpcEnv_ie->ieee_hdr.len =
+					sizeof(IEEEtypes_VhtTpcEnvelope_t) -
+					sizeof(IEEEtypes_Header_t);
+				/* Local Max TX Power Count= 3,
+				 * Local TX Power Unit Inter=EIP(0) */
+				pvhttpcEnv_ie->tpc_info = 3;
+				pvhttpcEnv_ie->local_max_tp_20mhz = 0xff;
+				pvhttpcEnv_ie->local_max_tp_40mhz = 0xff;
+				pvhttpcEnv_ie->local_max_tp_80mhz = 0xff;
+				pChanSwWrap_ie->len +=
+					sizeof(IEEEtypes_VhtTpcEnvelope_t);
+
+				pcust_chansw_ie->ie_length +=
+					sizeof(IEEEtypes_WideBWChanSwitch_t)
+					+ sizeof(IEEEtypes_VhtTpcEnvelope_t)
+					+ sizeof(IEEEtypes_Header_t);
+
+				PRINTM(MINFO,
+				       "Append Wide Bandwidth Channel Switch IE\n");
+				break;
+			}
+		}
+	}
+
+	pds_misc_cfg->param.cust_ie.len += pcust_chansw_ie->ie_length;
+	DBG_HEXDUMP(MCMD_D, "11h: custom_ie containing CHAN_SW IE",
+		    (t_u8 *)pcust_chansw_ie, pds_misc_cfg->param.cust_ie.len);
+
+	/* assign output pointer before returning */
+	*ppioctl_req = pioctl_req;
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef UAP_SUPPORT
+/** Bits 2,3 of band config define the band width */
+#define UAP_BAND_WIDTH_MASK 0x0C
+
+/**
+ *  @brief Check if start channel 165 is allowed to operate in
+ *  previous uAP channel's band config
+ *
+ *  @param start_chn     Random Start channel choosen after radar detection
+ *  @param uap_band_cfg  Private driver uAP band configuration information structure
+ *
+ *  @return MFALSE if the channel is not allowed in given band
+ */
+static t_bool
+wlan_11h_is_band_valid(t_u8 start_chn, Band_Config_t uap_band_cfg)
+{
+
+	/* if band width is not 20MHZ (either 40 or 80MHz)
+	 * return MFALSE, 165 is not allowed in bands other than 20MHZ
+	 */
+	if (start_chn == 165 && (uap_band_cfg.chanWidth != CHAN_BW_20MHZ)) {
+		return MFALSE;
+	}
+	return MTRUE;
+}
+
+/**
+ *  @brief Retrieve a randomly selected starting channel if needed for 11h
+ *
+ *  If 11h is enabled and 5GHz band is selected in band_config
+ *    return a random channel in A band, else one from BG band.
+ *
+ *  @param priv          Private driver information structure
+ *  @param uap_band_cfg  Private driver information structure
+ *
+ *  @return      Starting channel
+ */
+static t_u8
+wlan_11h_get_uap_start_channel(mlan_private *priv, Band_Config_t uap_band_cfg)
+{
+	t_u8 start_chn;
+	mlan_adapter *adapter = priv->adapter;
+	t_u32 region;
+	t_u32 rand_entry;
+	region_chan_t *chn_tbl;
+	t_u8 rand_tries = 0;
+
+	/*TODO:  right now mostly a copy of wlan_11h_get_adhoc_start_channel.
+	 *       Improve to be more specfic to UAP, e.g.
+	 *       1. take into account COUNTRY_CODE -> region_code
+	 *       2. check domain_info for value channels
+	 */
+	ENTER();
+
+	/*
+	 * Set start_chn to the Default.
+	 * Used if 11h is disabled or the band
+	 * does not require 11h support.
+	 */
+	start_chn = DEFAULT_AD_HOC_CHANNEL;
+
+	/*
+	 * Check that we are looking for a channel in the A Band
+	 */
+	if (uap_band_cfg.chanBand == BAND_5GHZ) {
+		/*
+		 * Set default to the A Band default.
+		 * Used if random selection fails
+		 * or if 11h is not enabled
+		 */
+		start_chn = DEFAULT_AD_HOC_CHANNEL_A;
+
+		/*
+		 * Check that 11h is enabled in the driver
+		 */
+		if (wlan_11h_is_enabled(priv)) {
+			/*
+			 * Search the region_channel tables for a channel table
+			 * that is marked for the A Band.
+			 */
+			for (region = 0; (region < MAX_REGION_CHANNEL_NUM);
+			     region++) {
+				chn_tbl = &adapter->region_channel[region];
+
+				/* Check if table is valid and marked for A Band */
+				if (chn_tbl->valid
+				    && chn_tbl->region == adapter->region_code
+				    && chn_tbl->band & BAND_A) {
+					/*
+					 * Set the start channel.  Get a random
+					 * number and use it to pick an entry
+					 * in the table between 0 and the number
+					 * of channels in the table (NumCFP).
+					 */
+					rand_entry =
+						wlan_11h_get_random_num(adapter)
+						% chn_tbl->num_cfp;
+					start_chn =
+						(t_u8)chn_tbl->pcfp[rand_entry].
+						channel;
+					/* Loop until a non-dfs channel is found with compatible band
+					 * bounded by chn_tbl->num_cfp entries in the channel table
+					 */
+					while ((wlan_11h_is_channel_under_nop
+						(adapter, start_chn) ||
+						((adapter->state_rdh.stage ==
+						  RDH_GET_INFO_CHANNEL) &&
+						 wlan_11h_radar_detect_required
+						 (priv, start_chn)) ||
+						!(wlan_11h_is_band_valid
+						  (start_chn, uap_band_cfg))) &&
+					       (++rand_tries <
+						chn_tbl->num_cfp)) {
+						rand_entry++;
+						rand_entry =
+							rand_entry %
+							chn_tbl->num_cfp;
+						start_chn =
+							(t_u8)chn_tbl->
+							pcfp[rand_entry].
+							channel;
+						PRINTM(MINFO,
+						       "start chan=%d rand_entry=%d\n",
+						       start_chn, rand_entry);
+					}
+
+					if (rand_tries == chn_tbl->num_cfp) {
+						PRINTM(MERROR,
+						       "Failed to get UAP start channel\n");
+						start_chn = 0;
+					}
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMD_D, "11h: UAP Get Start Channel %d\n", start_chn);
+	LEAVE();
+	return start_chn;
+}
+#endif /* UAP_SUPPORT */
+
+#ifdef DEBUG_LEVEL1
+static const char *DFS_TS_REPR_STRINGS[] = { "",
+	"NOP_start",
+	"CAC_completed"
+};
+#endif
+
+/**
+ *  @brief Search for a dfs timestamp in the list with desired channel.
+ *
+ *  Assumes there will only be one timestamp per channel in the list.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param channel    Channel number
+ *
+ *  @return           Pointer to timestamp if found, or MNULL
+ */
+static wlan_dfs_timestamp_t *
+wlan_11h_find_dfs_timestamp(mlan_adapter *pmadapter, t_u8 channel)
+{
+	wlan_dfs_timestamp_t *pts = MNULL, *pts_found = MNULL;
+
+	ENTER();
+	pts = (wlan_dfs_timestamp_t *)util_peek_list(pmadapter->pmoal_handle,
+						     &pmadapter->state_dfs.
+						     dfs_ts_head, MNULL, MNULL);
+
+	while (pts &&
+	       pts !=
+	       (wlan_dfs_timestamp_t *)&pmadapter->state_dfs.dfs_ts_head) {
+		PRINTM(MINFO,
+		       "dfs_timestamp(@ %p) - chan=%d, repr=%d(%s),"
+		       " time(sec.usec)=%lu.%06lu\n", pts, pts->channel,
+		       pts->represents, DFS_TS_REPR_STRINGS[pts->represents],
+		       pts->ts_sec, pts->ts_usec);
+
+		if (pts->channel == channel) {
+			pts_found = pts;
+			break;
+		}
+		pts = pts->pnext;
+	}
+
+	LEAVE();
+	return pts_found;
+}
+
+/**
+ *  @brief Removes dfs timestamp from list.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param pdfs_ts    Pointer to dfs_timestamp to remove
+ */
+static t_void
+wlan_11h_remove_dfs_timestamp(mlan_adapter *pmadapter,
+			      wlan_dfs_timestamp_t *pdfs_ts)
+{
+	ENTER();
+	/* dequeue and delete timestamp */
+	util_unlink_list(pmadapter->pmoal_handle,
+			 &pmadapter->state_dfs.dfs_ts_head,
+			 (pmlan_linked_list)pdfs_ts, MNULL, MNULL);
+	pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pdfs_ts);
+	LEAVE();
+}
+
+/**
+ *  @brief Add a dfs timestamp to the list
+ *
+ *  Assumes there will only be one timestamp per channel in the list,
+ *  and that timestamp modes (represents) are mutually exclusive.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param repr       Timestamp 'represents' value (see _dfs_timestamp_repr_e)
+ *  @param channel    Channel number
+ *
+ *  @return           Pointer to timestamp if found, or MNULL
+ */
+static mlan_status
+wlan_11h_add_dfs_timestamp(mlan_adapter *pmadapter, t_u8 repr, t_u8 channel)
+{
+	wlan_dfs_timestamp_t *pdfs_ts = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	pdfs_ts = wlan_11h_find_dfs_timestamp(pmadapter, channel);
+
+	if (!pdfs_ts) {
+		/* need to allocate new timestamp */
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       sizeof
+						       (wlan_dfs_timestamp_t),
+						       MLAN_MEM_DEF,
+						       (t_u8 **)&pdfs_ts);
+		if ((ret != MLAN_STATUS_SUCCESS) || !pdfs_ts) {
+			PRINTM(MERROR, "%s(): Could not allocate dfs_ts\n",
+			       __func__);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		memset(pmadapter, (t_u8 *)pdfs_ts, 0,
+		       sizeof(wlan_dfs_timestamp_t));
+
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &pmadapter->state_dfs.dfs_ts_head,
+				       (pmlan_linked_list)pdfs_ts, MNULL,
+				       MNULL);
+		pdfs_ts->channel = channel;
+	}
+	/* (else, use existing timestamp for channel; see assumptions above) */
+
+	/* update params */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pdfs_ts->ts_sec,
+						  &pdfs_ts->ts_usec);
+	pdfs_ts->represents = repr;
+
+	PRINTM(MCMD_D, "11h: add/update dfs_timestamp - chan=%d, repr=%d(%s),"
+	       " time(sec.usec)=%lu.%06lu\n", pdfs_ts->channel,
+	       pdfs_ts->represents, DFS_TS_REPR_STRINGS[pdfs_ts->represents],
+	       pdfs_ts->ts_sec, pdfs_ts->ts_usec);
+
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global functions
+********************************************************/
+
+/**
+ *  @brief Return whether the device has activated master radar detection.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return
+ *    - MTRUE if master radar detection is enabled in firmware
+ *    - MFALSE otherwise
+ */
+t_bool
+wlan_11h_is_master_radar_det_active(mlan_private *priv)
+{
+	ENTER();
+	LEAVE();
+	return priv->adapter->state_11h.is_master_radar_det_active;
+}
+
+/**
+ *  @brief Configure master radar detection.
+ *  Call wlan_11h_check_update_radar_det_state() afterwards
+ *    to push this to firmware.
+ *
+ *  @param priv  Private driver information structure
+ *  @param enable Whether to enable or disable master radar detection
+ *
+ *  @return  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ *  @sa wlan_11h_check_update_radar_det_state
+ */
+mlan_status
+wlan_11h_config_master_radar_det(mlan_private *priv, t_bool enable)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	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;
+
+	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);
+
+	/*
+	 * 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;
+#ifdef DFS_TESTING_SUPPORT
+	wlan_dfs_testing_settings_t *pdfs_test = &adapter->dfs_test_params;
+#endif
+
+	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;
+
+#ifdef DFS_TESTING_SUPPORT
+	/* 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;
+#endif
+
+	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)
+	    || (adapter->adhoc_start_band & BAND_AN)
+		) {
+		/*
+		 * 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;
+}
+
+/**
+ *  @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;
+			}
+		}
+#ifdef DFS_TESTING_SUPPORT
+		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;
+		}
+#endif
+
+		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)
+		|| (adapter->adhoc_start_band & BAND_AN)
+	    )
+		) {
+		if (!wlan_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_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(priv->adapter, priv->adapter->curr_cmd->pdata_buf,
+		       &resp->params.tpc_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_cancel_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(pmadapter, &p11h_bss_info->power_constraint, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->power_capability, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->tpc_report, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->chan_switch_ann, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->quiet, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->ibss_dfs, pelement,
+		       MIN((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;
+
+	ENTER();
+	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(priv->adapter, deauth_param.mac_addr,
+	       &priv->curr_bss_params.bss_descriptor.mac_address,
+	       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;
+}
+
+#ifdef DFS_TESTING_SUPPORT
+/**
+ *  @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;
+	} 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;
+	}
+
+	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) {
+		ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+		ch_nop_info = &ds_11hcfg->param.ch_nop_info;
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+		if (pioctl_req->action == MLAN_ACT_GET) {
+			ch_nop_info->chan_under_nop =
+				wlan_11h_is_channel_under_nop(pmadapter,
+							      ch_nop_info->
+							      curr_chan);
+			if (ch_nop_info->chan_under_nop) {
+				wlan_11h_switch_non_dfs_chan(pmpriv,
+							     &ch_nop_info->
+							     new_chan.channel);
+				if (ch_nop_info->chan_width == CHAN_BW_80MHZ ||
+				    ch_nop_info->chan_width == CHAN_BW_40MHZ)
+					wlan_11h_update_bandcfg(&ch_nop_info->
+								new_chan.
+								bandcfg,
+								ch_nop_info->
+								new_chan.
+								channel);
+				if (ch_nop_info->chan_width == CHAN_BW_80MHZ)
+					ch_nop_info->new_chan.center_chan =
+						wlan_get_center_freq_idx(pmpriv,
+									 BAND_AAC,
+									 ch_nop_info->
+									 new_chan.
+									 channel,
+									 ch_nop_info->
+									 chan_width);
+			}
+		}
+		ret = MLAN_STATUS_SUCCESS;
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif /* DFS_TESTING_SUPPORT */
+
+/**
+ *  @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 cancel 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_cancel_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);
+#ifdef DFS_TESTING_SUPPORT
+		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
+#endif
+		{
+			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)
+{
+	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;
+
+	ENTER();
+	pchan_rpt_rsp = (HostCmd_DS_CHAN_RPT_RSP *)&pevent->event_buf;
+	DBG_HEXDUMP(MCMD_D, "11h: Event ChanRptReady (HostCmd_DS_CHAN_RPT_RSP)",
+		    (t_u8 *)pchan_rpt_rsp, pevent->event_len);
+
+	if (wlan_le32_to_cpu(pchan_rpt_rsp->cmd_result) ==
+	    MLAN_CMD_RESULT_SUCCESS) {
+		pbuffer = (t_u8 *)&pchan_rpt_rsp->tlv_buffer;
+		evt_len = pevent->event_len;
+		evt_len -=
+			sizeof(HostCmd_DS_CHAN_RPT_RSP) -
+			sizeof(pchan_rpt_rsp->tlv_buffer);
+
+		while (evt_len >= sizeof(MrvlIEtypesHeader_t)) {
+			ptlv = (MrvlIEtypes_Data_t *)pbuffer;
+			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+
+			switch (wlan_le16_to_cpu(ptlv->header.type)) {
+			case TLV_TYPE_CHANRPT_11H_BASIC:
+				pmeas_rpt_basic =
+					(MeasRptBasicMap_t *)&ptlv->data;
+				if (pmeas_rpt_basic->radar) {
+					pstate_dfs->dfs_radar_found = MTRUE;
+					PRINTM(MMSG,
+					       "RADAR Detected on channel %d!\n",
+					       pstate_dfs->dfs_check_channel);
+					/* add channel to NOP list */
+					wlan_11h_add_dfs_timestamp(priv->
+								   adapter,
+								   DFS_TS_REPR_NOP_START,
+								   pstate_dfs->
+								   dfs_check_channel);
+				}
+				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;
+	}
+
+	/* Update DFS structure. */
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &sec,
+						      &usec);
+	pstate_dfs->dfs_report_time_sec = sec;
+	pstate_dfs->dfs_check_pending = MFALSE;
+	pstate_dfs->dfs_check_priv = MNULL;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 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;
+}
+
+/**
+ *  @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(IN Band_Config_t *uap_band_cfg, IN t_u8 new_channel)
+{
+	t_u8 chan_offset;
+	ENTER();
+
+	/* Update the channel offset for 20MHz, 40MHz and 80MHz
+	 * Clear the channel bandwidth for 20MHz
+	 * since channel switch could be happening from 40/80MHz to 20MHz
+	 */
+	chan_offset = wlan_get_second_channel_offset(new_channel);
+	uap_band_cfg->chan2Offset = chan_offset;
+
+	if (!chan_offset) {	/* 40MHz/80MHz */
+		PRINTM(MCMD_D, "20MHz channel, clear channel bandwidth\n");
+		uap_band_cfg->chanWidth = CHAN_BW_20MHZ;
+	}
+	LEAVE();
+}
+
+/**
+ * @brief Get priv current index -- this is used to enter correct rdh_state during radar handling
+ *
+ * @param pmpriv           Pointer to mlan_private
+ * @param pstate_rdh       Pointer to radar detected state handler
+ *
+ * @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_get_priv_curr_idx(mlan_private *pmpriv,
+			   wlan_radar_det_hndlg_state_t *pstate_rdh)
+{
+	t_bool found = MFALSE;
+	ENTER();
+
+	PRINTM(MINFO, "%s:pmpriv =%p\n", __func__, pmpriv);
+	while ((++pstate_rdh->priv_curr_idx) < pstate_rdh->priv_list_count) {
+		if (pmpriv == pstate_rdh->priv_list[pstate_rdh->priv_curr_idx]) {
+			PRINTM(MINFO, "found matching priv: priv_idx=%d\n",
+			       pstate_rdh->priv_curr_idx);
+			found = MTRUE;
+			break;
+		}
+	}
+	return (found == MTRUE) ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Driver handling for 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 TO NEXT STAGE */
+
+	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 TO NEXT STAGE */
+
+	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
+		}
+#ifdef DFS_TESTING_SUPPORT
+		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;
+		}
+#endif
+		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 TO NEXT STAGE */
+
+	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 TO NEXT STAGE */
+
+	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 - firmware will accept on any interface, and apply to all */
+		if (pstate_rdh->priv_curr_idx == RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
+			mlan_ioctl_req *pioctl_req = MNULL;
+
+			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 */
+			}
+
+			PRINTM(MMSG,
+			       "11h: Radar Detected - adding CHAN_SW IE to interfaces.\n");
+			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 */
+			}
+
+			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 TO NEXT STAGE */
+
+	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 - firmware will accept on any interface,
+		   and apply to all */
+		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");
+
+			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 */
+			}
+
+			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 */
+			}
+
+			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 TO NEXT STAGE */
+
+	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;
+
+#ifdef DFS_TESTING_SUPPORT
+		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 */
+		}
+#endif
+		/* FALL THROUGH TO NEXT STAGE */
+
+	case RDH_SET_NEW_CHANNEL:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n",
+		       __func__, pstate_rdh->stage,
+		       rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+		/* only set new channel for UAP intfs */
+		while ((++pstate_rdh->priv_curr_idx) <
+		       pstate_rdh->priv_list_count) {
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+
+				pmpriv->uap_state_chan_cb.pioctl_req_curr =
+					MNULL;
+				pmpriv->uap_state_chan_cb.get_chan_callback =
+					wlan_11h_radar_detected_callback;
+
+				/* DFS only in 5GHz */
+				wlan_11h_update_bandcfg(&pstate_rdh->
+							uap_band_cfg,
+							pstate_rdh->
+							new_channel);
+				PRINTM(MCMD_D,
+				       "RDH_SET_NEW_CHANNEL: uAP band config = 0x%x channel=%d\n",
+				       pstate_rdh->uap_band_cfg,
+				       pstate_rdh->new_channel);
+
+				ret = wlan_uap_set_channel(pmpriv,
+							   pstate_rdh->
+							   uap_band_cfg,
+							   pstate_rdh->
+							   new_channel);
+				break;	/* leads to exit case */
+			}
+#endif
+		}
+
+		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
+		    ret == MLAN_STATUS_FAILURE)
+			break;	/* EXIT CASE (for UAP) */
+		/* else */
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_RESTART_INTFS;
+		/* FALL THROUGH TO NEXT STAGE */
+
+	case RDH_RESTART_INTFS:
+#ifdef DFS_TESTING_SUPPORT
+rdh_restart_intfs:
+#endif
+		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 TO NEXT STAGE */
+
+	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;
+			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 */
+			}
+
+			pmpriv = pstate_rdh->priv_list[0];
+			pstate_rdh->priv_curr_idx = 0;
+			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: 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];
+
+	ENTER();
+	switch (pmadapter->event_cause & EVENT_ID_MASK) {
+	case EVENT_RADAR_DETECTED:
+		/* find active intf:  prefer dfs_master over dfs_slave */
+		if (wlan_get_privs_by_two_cond(pmadapter,
+					       wlan_11h_is_master_active_on_dfs_chan,
+					       wlan_11h_is_dfs_master,
+					       MTRUE, priv_list)) {
+			pmpriv = priv_list[0];
+			PRINTM(MINFO, "%s: found dfs_master priv=%p\n",
+			       __func__, pmpriv);
+		} else if (wlan_get_privs_by_two_cond(pmadapter,
+						      wlan_11h_is_slave_active_on_dfs_chan,
+						      wlan_11h_is_dfs_slave,
+						      MTRUE, priv_list)) {
+			pmpriv = priv_list[0];
+			PRINTM(MINFO, "%s: found dfs_slave priv=%p\n",
+			       __func__, pmpriv);
+		} else if (pmadapter->state_dfs.dfs_check_pending) {
+			pmpriv = (mlan_private *)(pmadapter->state_dfs.
+						  dfs_check_priv);
+			PRINTM(MINFO, "%s: found dfs priv=%p\n", __func__,
+			       pmpriv);
+		}
+
+		/* update event_cause if we found an appropriate priv */
+		if (pmpriv) {
+			pmlan_buffer pmevbuf = pmadapter->pmlan_buffer_event;
+			t_u32 new_event_cause =
+				pmadapter->event_cause & EVENT_ID_MASK;
+			new_event_cause |=
+				((GET_BSS_NUM(pmpriv) & 0xff) << 16) |
+				((pmpriv->bss_type & 0xff) << 24);
+			PRINTM(MINFO, "%s: priv - bss_num=%d, bss_type=%d\n",
+			       __func__, GET_BSS_NUM(pmpriv), pmpriv->bss_type);
+			memcpy(pmadapter, pmevbuf->pbuf + pmevbuf->data_offset,
+			       &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();
+
+#ifdef DFS_TESTING_SUPPORT
+	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;
+	}
+#endif
+
+	/*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;
+}
diff --git a/wlan_sd8897/mlan/mlan_11h.h b/wlan_sd8897/mlan/mlan_11h.h
new file mode 100644
index 0000000..4326299
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11h.h
@@ -0,0 +1,183 @@
+/** @file mlan_11h.h
+ *
+ *  @brief This header file contains data structures and
+ *  function declarations of 802.11h
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+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);
+
+#ifdef DFS_TESTING_SUPPORT
+/** 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);
+#endif
+
+extern mlan_status
+
+wlan_11h_ioctl_dfs_cancel_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);
+
+/** 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);
+
+/** Handler for RADAR_DETECTED */
+extern mlan_status wlan_11h_radar_detected_handling(mlan_adapter *pmadapter,
+						    mlan_private *priv);
+/** 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(IN Band_Config_t *uap_band_cfg,
+				    IN 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_sd8897/mlan/mlan_11n.c b/wlan_sd8897/mlan/mlan_11n.c
new file mode 100644
index 0000000..3f6f38e
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11n.c
@@ -0,0 +1,3262 @@
+/** @file mlan_11n.c
+ *
+ *  @brief This file contains functions for 11n handling.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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(IN pmlan_adapter pmadapter,
+			       IN 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_SET) {
+		if (cfg->param.tx_buf_size == 0xffff) {
+			PRINTM(MIOCTL, "Send reconfigure tx buf to FW\n");
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_RECONFIGURE_TX_BUFF,
+					       HostCmd_ACT_GEN_SET, 0,
+					       (t_void *)pioctl_req,
+					       &cfg->param.tx_buf_size);
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = MLAN_STATUS_PENDING;
+			LEAVE();
+			return ret;
+		}
+	}
+	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(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_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(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_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(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_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(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_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(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_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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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(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_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(IN pmlan_adapter pmadapter,
+			    IN 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(pmadapter, cfg->param.addba_reject, pmpriv->addba_reject,
+		       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(IN pmlan_adapter pmadapter,
+				IN 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 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(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_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(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_11n_cfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_REJECT_ADDBA_REQ,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &cfg->param.reject_addba_req);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will send DELBA to entries in the priv's
+ *          Tx BA stream table
+ *
+ *  @param priv                 A pointer to mlan_private
+ *  @param tid                  TID
+ *
+ *  @return		 N/A
+ */
+static void
+wlan_send_delba_txbastream_tbl(pmlan_private priv, t_u8 tid)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	TxBAStreamTbl *tx_ba_stream_tbl_ptr;
+
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	tx_ba_stream_tbl_ptr =
+		(TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+						&priv->tx_ba_stream_tbl_ptr,
+						MNULL, MNULL);
+	if (!tx_ba_stream_tbl_ptr) {
+		wlan_release_ralist_lock(priv);
+		LEAVE();
+		return;
+	}
+
+	while (tx_ba_stream_tbl_ptr !=
+	       (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (tx_ba_stream_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) {
+			if (tid == tx_ba_stream_tbl_ptr->tid) {
+				PRINTM(MIOCTL,
+				       "Tx:Send delba to tid=%d, " MACSTR "\n",
+				       tid, MAC2STR(tx_ba_stream_tbl_ptr->ra));
+				wlan_release_ralist_lock(priv);
+				wlan_send_delba(priv, MNULL,
+						tx_ba_stream_tbl_ptr->tid,
+						tx_ba_stream_tbl_ptr->ra, 1);
+				LEAVE();
+				return;
+			}
+		}
+		tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext;
+	}
+	wlan_release_ralist_lock(priv);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief update station list for the new aggr_prio_tbl setting
+ *
+ *  @param priv 	A pointer to mlan_private structure
+ *
+ *
+ *  @return		N/A
+ */
+void
+wlan_update_all_stations_ampdu(mlan_private *priv)
+{
+	sta_node *sta_ptr;
+	mlan_adapter *pmadapter = priv->adapter;
+	int i = 0;
+
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	sta_ptr = (sta_node *)util_peek_list(pmadapter->pmoal_handle,
+					     &priv->sta_list, MNULL, MNULL);
+	if (!sta_ptr) {
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		LEAVE();
+		return;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			if (sta_ptr->is_11n_enabled)
+				sta_ptr->ampdu_sta[i] =
+					priv->aggr_prio_tbl[i].ampdu_user;
+		}
+		sta_ptr = sta_ptr->pnext;
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Set/get aggr_prio_tbl
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_aggr_prio_tbl(IN pmlan_adapter pmadapter,
+			     IN 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(IN pmlan_adapter pmadapter,
+				 IN 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(pmadapter, cfg->param.supported_mcs_set, mcs_set, 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 */
+	if (priv->adapter->psdio_device->v15_fw_api) {
+		RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+	} else {
+		if (GET_DELAYEDBACK(priv->adapter->hw_dot_11n_dev_cap))
+			SETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+		else
+			RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+	}
+
+	/* Need change to support 8k AMSDU receive */
+	RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+	/* SM power save */
+	if (ISSUPP_MIMOPS(priv->adapter->hw_dot_11n_dev_cap))
+		RESETHT_SM_POWERSAVE(ht_cap->ht_cap_info);	/* Enable HT SMPS */
+	else
+		SETHT_STATIC_SMPS(ht_cap->ht_cap_info);	/* Disable HT SMPS */
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function clear the bit in cap info which we don't support
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_reset_cap_info(mlan_private *priv, HTCap_t *ht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11n_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+	if (!ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
+		RESETHT_GREENFIELD(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
+		RESETHT_SHORTGI20(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+	if (!ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
+		RESETHT_RXSTBC(ht_cap->ht_cap_info);
+
+	if (!ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+
+	/** if current channel only allow 20Mhz, we should cler 40Mhz support */
+	if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	    priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+	}
+	/* No user config for LDPC coding capability yet */
+	if (!ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
+		RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+
+	/* No user config for TX STBC yet */
+	if (!ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
+		RESETHT_TXSTBC(ht_cap->ht_cap_info);
+
+	/* No user config for Delayed BACK yet */
+	if (priv->adapter->psdio_device->v15_fw_api) {
+		RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+	} else {
+		if (!GET_DELAYEDBACK(priv->adapter->hw_dot_11n_dev_cap))
+			RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+	}
+
+	/* Need change to support 8k AMSDU receive */
+	RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+	/* SM power save */
+	if (!ISSUPP_MIMOPS(priv->adapter->hw_dot_11n_dev_cap))
+		SETHT_STATIC_SMPS(ht_cap->ht_cap_info);	/* Disable HT SMPS */
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function fills the HT cap tlv
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *  @param fill         A flag for fill the htcap info
+ *
+ *  @return             N/A
+ */
+void
+wlan_fill_ht_cap_tlv(mlan_private *priv,
+		     MrvlIETypes_HTCap_t *pht_cap, t_u8 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);
+	/* 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_u8 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);
+	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"));
+
+	if (pmadapter->psdio_device->v15_fw_api) {
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Number of Tx BA streams supported = %d\n",
+		       ISSUPP_GETTXBASTREAM(cap));
+	} else {
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Number of Delayed Block Ack streams = %d\n",
+		       GET_DELAYEDBACK(cap));
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Number of Immediate Block Ack streams = %d\n",
+		       GET_IMMEDIATEBACK(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 (priv->bss_mode == MLAN_BSS_MODE_IBSS)
+				disable_station_ampdu(priv, tid,
+						      padd_ba_rsp->
+						      peer_mac_addr);
+			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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *cmd,
+		 IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *cmd,
+		   IN t_u16 cmd_action, IN 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(pmadapter, txbfcfg->body.bf_periodicity.peer_mac,
+		       txbf->body.bf_periodicity[0].peer_mac,
+		       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(pmadapter, txbfcfg->body.bf_sound_args.peer_mac,
+			       txbf->body.bf_sound[0].peer_mac,
+			       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(pmadapter, txbfcfg->body.tx_bf_peer.peer_mac,
+			       txbf->body.tx_bf_peer[0].peer_mac,
+			       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(pmadapter, txbfcfg->body.bf_snr.peer_mac,
+			       txbf->body.bf_snr[0].peer_mac,
+			       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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *resp, IN 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(pmadapter, txbf->body.bf_sound[0].peer_mac,
+			       txbfcfg->body.bf_sound_args.peer_mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			txbf->body.bf_sound[0].status =
+				txbfcfg->body.bf_sound_args.status;
+			break;
+		case SET_GET_BF_PERIODICITY:
+			memcpy(pmadapter, txbf->body.bf_periodicity->peer_mac,
+			       txbfcfg->body.bf_periodicity.peer_mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			txbf->body.bf_periodicity->interval =
+				wlan_le16_to_cpu(txbfcfg->body.bf_periodicity.
+						 interval);
+			break;
+		case TX_BF_FOR_PEER_ENBL:
+			txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+			tx_bf_peer =
+				(bf_peer_args *)((t_u8 *)&txbfcfg->body +
+						 sizeof(t_u8));
+			for (i = 0; i < txbf->no_of_peers; i++) {
+				memcpy(pmadapter,
+				       txbf->body.tx_bf_peer[i].peer_mac,
+				       (t_u8 *)tx_bf_peer->peer_mac,
+				       MLAN_MAC_ADDR_LENGTH);
+				txbf->body.tx_bf_peer[i].bf_enbl =
+					tx_bf_peer->bf_enbl;
+				txbf->body.tx_bf_peer[i].sounding_enbl =
+					tx_bf_peer->sounding_enbl;
+				txbf->body.tx_bf_peer[i].fb_type =
+					tx_bf_peer->fb_type;
+				tx_bf_peer++;
+			}
+			break;
+		case SET_SNR_THR_PEER:
+			txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+			bf_snr = (bf_snr_thr_t *)((t_u8 *)&txbfcfg->body +
+						  sizeof(t_u8));
+			for (i = 0; i < txbf->no_of_peers; i++) {
+				memcpy(pmadapter, txbf->body.bf_snr[i].peer_mac,
+				       (t_u8 *)bf_snr->peer_mac,
+				       MLAN_MAC_ADDR_LENGTH);
+				txbf->body.bf_snr[i].snr = bf_snr->snr;
+				bf_snr++;
+			}
+			break;
+		default:
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get second channel offset
+ *
+ * @param chan            channel num
+ * @return                second channel offset
+ */
+t_u8
+wlan_get_second_channel_offset(int chan)
+{
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+
+	switch (chan) {
+	case 36:
+	case 44:
+	case 52:
+	case 60:
+	case 100:
+	case 108:
+	case 116:
+	case 124:
+	case 132:
+	case 140:
+	case 149:
+	case 157:
+		chan2Offset = SEC_CHAN_ABOVE;
+		break;
+	case 40:
+	case 48:
+	case 56:
+	case 64:
+	case 104:
+	case 112:
+	case 120:
+	case 128:
+	case 136:
+	case 144:
+	case 153:
+	case 161:
+		chan2Offset = SEC_CHAN_BELOW;
+		break;
+	case 165:
+		/* Special Case: 20Mhz-only Channel */
+		chan2Offset = SEC_CHAN_NONE;
+		break;
+	}
+	return chan2Offset;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief validate the channel offset for Infra/Ad-hoc band configuration
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param band         band
+ *  @param chan         primary channel
+ *  @param chan_bw      channel bandwidth
+ *
+ *  @return             channel offset (NO_SEC_CHANNEL, SEC_CHANNEL_ABOVE,
+ *                                      SEC_CHANNEL_BELOW)
+ */
+t_u8
+wlan_validate_chan_offset(IN mlan_private *pmpriv,
+			  IN t_u8 band, IN t_u32 chan, IN t_u8 chan_bw)
+{
+	t_u8 chan_offset;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+
+	if (chan_bw == CHANNEL_BW_40MHZ_ABOVE)
+		chan_offset = SEC_CHAN_ABOVE;
+	else if (chan_bw == CHANNEL_BW_40MHZ_BELOW)
+		chan_offset = SEC_CHAN_BELOW;
+	else
+		chan_offset = SEC_CHAN_NONE;
+
+	/* validation */
+	if (chan_offset != SEC_CHAN_NONE) {
+		if (band & BAND_GN) {
+			if ((chan == 1) || (chan == 2) || (chan == 3) ||
+			    (chan == 4))
+				chan_offset = SEC_CHAN_ABOVE;
+			else if ((chan == 10) || (chan == 11) ||
+				 (chan == 12) || (chan == 13))
+				chan_offset = SEC_CHAN_BELOW;
+
+			/* check if channel 12 is supported in the region */
+			if (!wlan_find_cfp_by_band_and_channel
+			    (pmadapter, band, 12))
+				if ((chan == 8) || (chan == 9))
+					chan_offset = SEC_CHAN_BELOW;
+		} else if (band & BAND_AN)
+			chan_offset = wlan_get_second_channel_offset(chan);
+	}
+	return chan_offset;
+}
+
+/**
+ *  @brief This function check if ht40 is allowed in current region
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc    A pointer to BSSDescriptor_t structure
+ *
+ *  @return MTRUE/MFALSE
+ */
+static int
+wlan_check_chan_width_ht40_by_region(IN mlan_private *pmpriv,
+				     IN 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))
+		return MFALSE;
+	if ((chan_offset == SEC_CHAN_BELOW) &&
+	    (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS))
+		return MFALSE;
+
+	num_cfp = pmadapter->region_channel[0].num_cfp;
+
+	if ((pbss_desc->bss_band & (BAND_B | BAND_G)) &&
+	    pmadapter->region_channel && 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(IN mlan_private *pmpriv,
+			IN BSSDescriptor_t *pbss_desc, OUT t_u8 **ppbuffer)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	MrvlIETypes_HTCap_t *pht_cap;
+	MrvlIETypes_HTInfo_t *pht_info;
+	MrvlIEtypes_ChanListParamSet_t *pchan_list;
+	MrvlIETypes_2040BSSCo_t *p2040_bss_co;
+	MrvlIETypes_ExtCap_t *pext_cap;
+	t_u32 usr_dot_11n_dev_cap, orig_usr_dot_11n_dev_cap = 0;
+	t_u32 usr_vht_cap_info;
+	t_u8 usr_dot_11ac_bw;
+	int ret_len = 0;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+
+	if (pbss_desc->bss_band & BAND_A)
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
+
+	if (pbss_desc->bss_band & BAND_A)
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_bg;
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+		usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
+	else
+		usr_dot_11ac_bw = pmpriv->usr_dot_11ac_bw;
+	if ((pbss_desc->bss_band & (BAND_B | BAND_G)) &&
+	    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(pmadapter, (t_u8 *)pht_cap + sizeof(MrvlIEtypesHeader_t),
+		       (t_u8 *)pbss_desc->pht_cap + sizeof(IEEEtypes_Header_t),
+		       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);
+
+		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) {
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+			pht_info = (MrvlIETypes_HTInfo_t *)*ppbuffer;
+			memset(pmadapter, pht_info, 0,
+			       sizeof(MrvlIETypes_HTInfo_t));
+			pht_info->header.type = wlan_cpu_to_le16(HT_OPERATION);
+			pht_info->header.len = sizeof(HTInfo_t);
+
+			memcpy(pmadapter,
+			       (t_u8 *)pht_info + sizeof(MrvlIEtypesHeader_t),
+			       (t_u8 *)pbss_desc->pht_info +
+			       sizeof(IEEEtypes_Header_t),
+			       pht_info->header.len);
+
+			if (!ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+				RESET_CHANWIDTH40(pht_info->ht_info.field2);
+
+			*ppbuffer += sizeof(MrvlIETypes_HTInfo_t);
+			ret_len += sizeof(MrvlIETypes_HTInfo_t);
+			pht_info->header.len =
+				wlan_cpu_to_le16(pht_info->header.len);
+		}
+
+		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;
+			if (pmpriv->adapter->psdio_device->v15_update)
+				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(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);
+
+		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(pmadapter,
+		       (t_u8 *)pext_cap + sizeof(MrvlIEtypesHeader_t),
+		       (t_u8 *)&pmpriv->ext_cap, sizeof(ExtCap_t));
+		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, 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(IN pmlan_adapter pmadapter, IN 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;
+	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(pmadapter, new_node->ra, ra, 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(priv->adapter, &add_ba_req.peer_mac_addr, peer_mac,
+	       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(priv->adapter, &delba.peer_mac_addr, peer_mac,
+	       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();
+	rx_reorder_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_reorder_tbl_ptr) {
+		LEAVE();
+		return count;
+	}
+	while (rx_reorder_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		ptbl->tid = (t_u16)rx_reorder_tbl_ptr->tid;
+		memcpy(priv->adapter, ptbl->ta, rx_reorder_tbl_ptr->ta,
+		       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;
+	}
+	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;
+	}
+	if (priv->adapter->psdio_device->v15_fw_api) {
+		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(priv->adapter, ptbl->ra, ptxtbl->ra,
+		       MLAN_MAC_ADDR_LENGTH);
+		ptbl->amsdu = ptxtbl->amsdu;
+		ptxtbl = ptxtbl->pnext;
+		ptbl++;
+		count++;
+		if ((priv->adapter->psdio_device->v15_fw_api &&
+		     (count >= bastream_max)) ||
+		    (!priv->adapter->psdio_device->v15_fw_api &&
+		     (count >= MLAN_MAX_TX_BASTREAM_SUPPORTED_NOV15)))
+			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_sd8897/mlan/mlan_11n.h b/wlan_sd8897/mlan/mlan_11n.h
new file mode 100644
index 0000000..aa4855b
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11n.h
@@ -0,0 +1,397 @@
+/** @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 (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf);
+/** Prepare 11ncfg command */
+mlan_status wlan_cmd_11n_cfg(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action,
+			     IN t_void *pdata_buf);
+/** Prepare reject addba requst command */
+mlan_status wlan_cmd_reject_addba_req(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_u16 cmd_action,
+				      IN t_void *pdata_buf);
+/** Handle the command response of rejecting addba request */
+mlan_status wlan_ret_reject_addba_req(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+/** Prepare TX BF configuration command */
+mlan_status wlan_cmd_tx_bf_cfg(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action, IN t_void *pdata_buf);
+/** Handle the command response TX BF configuration */
+mlan_status wlan_ret_tx_bf_cfg(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *resp,
+			       IN 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(IN mlan_private *pmpriv,
+			    IN BSSDescriptor_t *pbss_desc, OUT t_u8 **ppbuffer);
+/** wlan fill HT cap tlv */
+void wlan_fill_ht_cap_tlv(mlan_private *priv, MrvlIETypes_HTCap_t *pht_cap,
+			  t_u8 band, t_u8 fill);
+/** wlan fill HT cap IE */
+void wlan_fill_ht_cap_ie(mlan_private *priv, IEEEtypes_HTCap_t *pht_cap,
+			 t_u8 bands);
+#endif /* STA_SUPPORT */
+/** Miscellaneous configuration handler */
+mlan_status wlan_11n_cfg_ioctl(IN pmlan_adapter pmadapter,
+			       IN 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(IN mlan_private *pmpriv,
+			       IN t_u8 band, IN t_u32 chan, IN t_u8 chan_bw);
+/** get channel offset */
+t_u8 wlan_get_second_channel_offset(int chan);
+
+void wlan_update_11n_cap(mlan_private *pmpriv);
+
+/** clean up txbastream_tbl */
+void wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra);
+/**
+ *  @brief This function checks whether a station has 11N enabled or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param mac      station mac address
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+is_station_11n_enabled(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		return (sta_ptr->is_11n_enabled) ? MTRUE : MFALSE;
+	return MFALSE;
+}
+
+/**
+ *  @brief This function get station max amsdu size
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param mac      station mac address
+ *  @return         max amsdu size statio supported
+ */
+static INLINE t_u16
+get_station_max_amsdu_size(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		return sta_ptr->max_amsdu;
+	return 0;
+}
+
+/**
+ *  @brief This function checks whether a station allows AMPDU or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ptr      A pointer to RA list table
+ *  @param tid      TID value for ptr
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+is_station_ampdu_allowed(mlan_private *priv, raListTbl *ptr, int tid)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+	if (sta_ptr) {
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			if (priv->sec_info.wapi_enabled &&
+			    !sta_ptr->wapi_key_on)
+				return MFALSE;
+		}
+		return (sta_ptr->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED)
+			? MTRUE : MFALSE;
+	}
+	return MFALSE;
+}
+
+/**
+ *  @brief This function disable station ampdu for specific tid
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param tid     tid index
+ *  @param ra      station mac address
+ *  @return        N/A
+ */
+static INLINE void
+disable_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ra);
+	if (sta_ptr)
+		sta_ptr->ampdu_sta[tid] = BA_STREAM_NOT_ALLOWED;
+	return;
+}
+
+/**
+ *  @brief This function reset station ampdu for specific id to user setting.
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param tid     tid index
+ *  @param ra      station mac address
+ *  @return        N/A
+ */
+static INLINE void
+reset_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ra);
+	if (sta_ptr)
+		sta_ptr->ampdu_sta[tid] = priv->aggr_prio_tbl[tid].ampdu_user;
+	return;
+}
+
+/**
+ *  @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)
+{
+#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;
+	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->bss_mode == MLAN_BSS_MODE_IBSS)
+		return is_station_ampdu_allowed(priv, ptr, tid);
+	return (priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED)
+		? MTRUE : MFALSE;
+}
+
+/**
+ *  @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;
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+		if (sta_ptr) {
+			if (priv->sec_info.wapi_enabled &&
+			    !sta_ptr->wapi_key_on)
+				return MFALSE;
+		}
+	}
+#endif /* UAP_SUPPORT */
+#define TXRATE_BITMAP_INDEX_MCS0_7 2
+	return ((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)
+		&&((priv->is_data_rate_auto)
+		   || !((priv->bitmap_rates[TXRATE_BITMAP_INDEX_MCS0_7]) &
+			0x03))) ? 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);
+	}
+	if (priv->adapter->psdio_device->v15_fw_api) {
+		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;
+	} else {
+		return (bastream_num <
+			MLAN_MAX_TX_BASTREAM_SUPPORTED_NOV15) ? 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(priv->adapter, ra, ptx_tbl->ra,
+			       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 */
+#ifdef STA_SUPPORT
+	if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
+		if ((!(ra[0] & 0x01)) && (priv->adapter->adhoc_11n_enabled))
+			ret = is_station_11n_enabled(priv, ra);
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+#endif /* !_MLAN_11N_H_ */
diff --git a/wlan_sd8897/mlan/mlan_11n_aggr.c b/wlan_sd8897/mlan/mlan_11n_aggr.c
new file mode 100644
index 0000000..be23760
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11n_aggr.c
@@ -0,0 +1,592 @@
+/** @file mlan_11n_aggr.c
+ *
+ *  @brief This file contains functions for 11n Aggregation.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.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(pmadapter, amsdu_buf, data, (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(pmadapter, amsdu_buf + amsdu_buf_offset, &snap, LLC_SNAP_LEN);
+	amsdu_buf_offset += LLC_SNAP_LEN;
+
+	memcpy(pmadapter, amsdu_buf + amsdu_buf_offset, data + 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 };
+
+	ENTER();
+
+	data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+	total_pkt_len = pmbuf->data_len;
+
+	/* Sanity test */
+	if (total_pkt_len > max_rx_data_size) {
+		PRINTM(MERROR, "Total packet length greater than tx buffer"
+		       " size %d\n", total_pkt_len);
+		goto done;
+	}
+
+	pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len);
+
+	while (total_pkt_len >= hdr_len) {
+		prx_pkt = (RxPacketHdr_t *)data;
+		/* Length will be in network format, change it to host */
+		pkt_len = mlan_ntohs((*(t_u16 *)(data + (2 *
+							 MLAN_MAC_ADDR_LENGTH))));
+		if (pkt_len > total_pkt_len) {
+			PRINTM(MERROR,
+			       "Error in packet length: total_pkt_len = %d, pkt_len = %d\n",
+			       total_pkt_len, pkt_len);
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+
+		pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
+			(4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;
+
+		total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);
+
+		if (memcmp(pmadapter, &prx_pkt->rfc1042_hdr,
+			   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
+			memmove(pmadapter, data + LLC_SNAP_LEN, data, (2 *
+								       MLAN_MAC_ADDR_LENGTH));
+			data += LLC_SNAP_LEN;
+			pkt_len += sizeof(Eth803Hdr_t) - LLC_SNAP_LEN;
+		} else {
+			*(t_u16 *)(data + (2 * MLAN_MAC_ADDR_LENGTH))
+				= (t_u16)0;
+			pkt_len += sizeof(Eth803Hdr_t);
+		}
+		daggr_mbuf =
+			wlan_alloc_mlan_buffer(pmadapter,
+					       pkt_len + MLAN_NET_IP_ALIGN, 0,
+					       MOAL_ALLOC_MLAN_BUFFER);
+		if (daggr_mbuf == MNULL) {
+			PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		daggr_mbuf->data_offset += MLAN_NET_IP_ALIGN;
+		daggr_mbuf->bss_index = pmbuf->bss_index;
+		daggr_mbuf->buf_type = pmbuf->buf_type;
+		daggr_mbuf->data_len = pkt_len;
+		daggr_mbuf->in_ts_sec = pmbuf->in_ts_sec;
+		daggr_mbuf->in_ts_usec = pmbuf->in_ts_usec;
+		daggr_mbuf->pparent = pmbuf;
+		daggr_mbuf->priority = pmbuf->priority;
+		memcpy(pmadapter, daggr_mbuf->pbuf + daggr_mbuf->data_offset,
+		       data, pkt_len);
+
+#ifdef UAP_SUPPORT
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			ret = wlan_uap_recv_packet(priv, daggr_mbuf);
+		} else {
+#endif /* UAP_SUPPORT */
+		/** send EAPOL from AMSDU pkt to firmware */
+			if (priv->sec_info.ewpa_enabled &&
+			    (!memcmp
+			     (pmadapter,
+			      daggr_mbuf->pbuf + daggr_mbuf->data_offset +
+			      MLAN_ETHER_PKT_TYPE_OFFSET, eapol_type,
+			      sizeof(eapol_type)))) {
+				ret = wlan_prepare_cmd(priv,
+						       HostCmd_CMD_802_11_EAPOL_PKT,
+						       0, 0, MNULL, daggr_mbuf);
+				if (ret == MLAN_STATUS_SUCCESS)
+					wlan_recv_event(priv,
+							MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+							MNULL);
+				wlan_free_mlan_buffer(pmadapter, daggr_mbuf);
+				data += pkt_len + pad;
+				continue;
+			}
+	/**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;
+		case MLAN_STATUS_SUCCESS:
+			wlan_recv_packet_complete(pmadapter, daggr_mbuf, ret);
+			break;
+		default:
+			break;
+		}
+
+		data += pkt_len + pad;
+	}
+
+done:
+	priv->msdu_in_rx_amsdu_cnt += pmbuf->use_count;
+	priv->amsdu_rx_cnt++;
+    /** we should free the aggr buffer after deaggr */
+	wlan_free_mlan_buffer(pmadapter, pmbuf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Aggregate multiple packets into one single AMSDU packet
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param pra_list Pointer to the RA List table containing the pointers
+ *                  to packets.
+ *  @param headroom Any interface specific headroom that may be need. TxPD
+ *                  will be formed leaving this headroom.
+ *  @param ptrindex Pointer index
+ *
+ *  @return     Final packet size or MLAN_STATUS_FAILURE
+ */
+int
+wlan_11n_aggregate_pkt(mlan_private *priv, raListTbl *pra_list,
+		       int headroom, int ptrindex)
+{
+	int pkt_size = 0;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_buffer *pmbuf_aggr, *pmbuf_src;
+	t_u8 *data;
+	int pad = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	mlan_tx_param tx_param;
+#ifdef STA_SUPPORT
+	TxPD *ptx_pd = MNULL;
+#endif
+	t_u32 max_amsdu_size = MIN(pra_list->max_amsdu, pmadapter->tx_buf_size);
+	ENTER();
+
+	PRINTM(MDAT_D, "Handling Aggr packet\n");
+
+	pmbuf_src =
+		(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+					     &pra_list->buf_head, MNULL, MNULL);
+	if (pmbuf_src) {
+		pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter,
+						    pmadapter->tx_buf_size, 0,
+						    MOAL_MALLOC_BUFFER);
+		if (!pmbuf_aggr) {
+			PRINTM(MERROR, "Error allocating mlan_buffer\n");
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		data = pmbuf_aggr->pbuf + headroom;
+		pmbuf_aggr->bss_index = pmbuf_src->bss_index;
+		pmbuf_aggr->buf_type = pmbuf_src->buf_type;
+		pmbuf_aggr->priority = pmbuf_src->priority;
+		pmbuf_aggr->pbuf = data;
+		pmbuf_aggr->data_offset = 0;
+		pmbuf_aggr->in_ts_sec = pmbuf_src->in_ts_sec;
+		pmbuf_aggr->in_ts_usec = pmbuf_src->in_ts_usec;
+		if (pmbuf_src->flags & MLAN_BUF_FLAG_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);
+
+		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);
+
+		pkt_size += wlan_11n_form_amsdu_pkt(pmadapter,
+						    (data + pkt_size),
+						    pmbuf_src->pbuf +
+						    pmbuf_src->data_offset,
+						    pmbuf_src->data_len, &pad);
+
+		DBG_HEXDUMP(MDAT_D, "pmbuf_src", pmbuf_src,
+			    sizeof(mlan_buffer));
+		wlan_write_data_complete(pmadapter, pmbuf_src,
+					 MLAN_STATUS_SUCCESS);
+
+		pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+						    priv->wmm.ra_list_spinlock);
+
+		if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		pmbuf_src =
+			(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &pra_list->buf_head, MNULL,
+						     MNULL);
+		priv->msdu_in_tx_amsdu_cnt++;
+	}
+
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+
+	/* Last AMSDU packet does not need padding */
+	pkt_size -= pad;
+	pmbuf_aggr->data_len = pkt_size;
+	wlan_11n_update_pktlen_amsdu_txpd(priv, pmbuf_aggr);
+	pmbuf_aggr->data_len += headroom;
+	pmbuf_aggr->pbuf = data - headroom;
+	tx_param.next_pkt_len = ((pmbuf_src) ?
+				 pmbuf_src->data_len + sizeof(TxPD) : 0);
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA,
+				     pmbuf_aggr, &tx_param);
+	switch (ret) {
+	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;
+			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:
+		pmadapter->data_sent = MFALSE;
+		PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
+		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_sd8897/mlan/mlan_11n_aggr.h b/wlan_sd8897/mlan/mlan_11n_aggr.h
new file mode 100644
index 0000000..396f1b5
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11n_aggr.h
@@ -0,0 +1,37 @@
+/** @file mlan_11n_aggr.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of 11n aggregation functionalities
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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_sd8897/mlan/mlan_11n_rxreorder.c b/wlan_sd8897/mlan/mlan_11n_rxreorder.c
new file mode 100644
index 0000000..9335f7c
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11n_rxreorder.c
@@ -0,0 +1,1570 @@
+/** @file mlan_11n_rxreorder.c
+ *
+ *  @brief This file contains the handling of RxReordering in wlan
+ *  driver.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+Change log:
+    11/10/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief This function will dispatch amsdu packet and
+ *         forward it to kernel/upper layer
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param pmbuf    A pointer to the received buffer
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11n_dispatch_amsdu_pkt(mlan_private *priv, pmlan_buffer pmbuf)
+{
+	RxPD *prx_pd;
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+
+	ENTER();
+	if (prx_pd->rx_pkt_type == PKT_TYPE_AMSDU) {
+		pmbuf->data_len = prx_pd->rx_pkt_length;
+		pmbuf->data_offset += prx_pd->rx_pkt_offset;
+		wlan_11n_deaggregate_pkt(priv, pmbuf);
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function will process the rx packet and
+ *         forward it to kernel/upper layer
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param payload  A pointer to rx packet payload
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11n_dispatch_pkt(t_void *priv, t_void *payload)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef STA_SUPPORT
+	pmlan_adapter pmadapter = ((pmlan_private)priv)->adapter;
+#endif
+	ENTER();
+	if (payload == (t_void *)RX_PKT_DROPPED_IN_FW) {
+		LEAVE();
+		return ret;
+	}
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE((mlan_private *)priv) == MLAN_BSS_ROLE_UAP) {
+		if (MLAN_STATUS_SUCCESS ==
+		    wlan_11n_dispatch_amsdu_pkt((mlan_private *)priv,
+						(pmlan_buffer)payload)) {
+			LEAVE();
+			return ret;
+		}
+		ret = wlan_process_uap_rx_packet(priv, (pmlan_buffer)payload);
+		LEAVE();
+		return ret;
+	}
+#endif /* UAP_SUPPORT */
+
+#ifdef STA_SUPPORT
+	if (MLAN_STATUS_SUCCESS ==
+	    wlan_11n_dispatch_amsdu_pkt((mlan_private *)priv,
+					(pmlan_buffer)payload)) {
+		LEAVE();
+		return ret;
+	}
+	ret = wlan_process_rx_packet(pmadapter, (pmlan_buffer)payload);
+#endif /* STA_SUPPORT */
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function restarts the reordering timeout timer
+ *
+ *  @param pmadapter        A pointer to mlan_adapter
+ *  @param rx_reor_tbl_ptr  A pointer to structure RxReorderTbl
+ *
+ *  @return                 N/A
+ */
+static void
+mlan_11n_rxreorder_timer_restart(pmlan_adapter pmadapter,
+				 RxReorderTbl *rx_reor_tbl_ptr)
+{
+	t_u16 min_flush_time = 0;
+	ENTER();
+
+	if (rx_reor_tbl_ptr->win_size >= 32)
+		min_flush_time = MIN_FLUSH_TIMER_15_MS;
+	else
+		min_flush_time = MIN_FLUSH_TIMER_MS;
+
+	if (rx_reor_tbl_ptr->timer_context.timer_is_set)
+		pmadapter->callbacks.moal_stop_timer(pmadapter->pmoal_handle,
+						     rx_reor_tbl_ptr->
+						     timer_context.timer);
+
+	pmadapter->callbacks.moal_start_timer(pmadapter->pmoal_handle,
+					      rx_reor_tbl_ptr->timer_context.
+					      timer, MFALSE,
+					      (rx_reor_tbl_ptr->win_size *
+					       min_flush_time));
+
+	rx_reor_tbl_ptr->timer_context.timer_is_set = MTRUE;
+	LEAVE();
+}
+
+/**
+ *  @brief This function dispatches all the packets in the buffer.
+ *         There could be holes in the buffer.
+ *
+ *  @param priv             A pointer to mlan_private
+ *  @param rx_reor_tbl_ptr  A pointer to structure RxReorderTbl
+ *  @param start_win        Start window
+ *
+ *  @return                 MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11n_dispatch_pkt_until_start_win(t_void *priv,
+				      RxReorderTbl *rx_reor_tbl_ptr,
+				      int start_win)
+{
+	int no_pkt_to_send, i, xchg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	void *rx_tmp_ptr = MNULL;
+	mlan_private *pmpriv = (mlan_private *)priv;
+
+	ENTER();
+
+	no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ?
+		MIN((start_win - rx_reor_tbl_ptr->start_win),
+		    rx_reor_tbl_ptr->win_size) : rx_reor_tbl_ptr->win_size;
+
+	for (i = 0; i < no_pkt_to_send; ++i) {
+		pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->
+							  pmoal_handle,
+							  pmpriv->rx_pkt_lock);
+		rx_tmp_ptr = MNULL;
+		if (rx_reor_tbl_ptr->rx_reorder_ptr[i]) {
+			rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];
+			rx_reor_tbl_ptr->rx_reorder_ptr[i] = MNULL;
+		}
+		pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->adapter->
+							    pmoal_handle,
+							    pmpriv->
+							    rx_pkt_lock);
+		if (rx_tmp_ptr)
+			wlan_11n_dispatch_pkt(priv, rx_tmp_ptr);
+	}
+
+	pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->pmoal_handle,
+						  pmpriv->rx_pkt_lock);
+	/*
+	 * We don't have a circular buffer, hence use rotation to simulate
+	 * circular buffer
+	 */
+	xchg = rx_reor_tbl_ptr->win_size - no_pkt_to_send;
+	for (i = 0; i < xchg; ++i) {
+		rx_reor_tbl_ptr->rx_reorder_ptr[i] =
+			rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i];
+		rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i] = MNULL;
+	}
+
+	rx_reor_tbl_ptr->start_win = start_win;
+	pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->adapter->
+						    pmoal_handle,
+						    pmpriv->rx_pkt_lock);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will display the rxReorder table
+ *
+ *  @param pmadapter          A pointer to mlan_adapter structure
+ *  @param rx_reor_tbl_ptr    A pointer to structure RxReorderTbl
+ *
+ *  @return                   N/A
+ */
+static t_void
+wlan_11n_display_tbl_ptr(pmlan_adapter pmadapter, RxReorderTbl *rx_reor_tbl_ptr)
+{
+	ENTER();
+
+	DBG_HEXDUMP(MDAT_D, "Reorder ptr", rx_reor_tbl_ptr->rx_reorder_ptr,
+		    sizeof(t_void *) * rx_reor_tbl_ptr->win_size);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function will dispatch all packets sequentially
+ *          from start_win until a hole is found and adjust the
+ *          start_win appropriately
+ *
+ *  @param priv             A pointer to mlan_private
+ *  @param rx_reor_tbl_ptr  A pointer to structure RxReorderTbl
+ *
+ *  @return                 MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11n_scan_and_dispatch(t_void *priv, RxReorderTbl *rx_reor_tbl_ptr)
+{
+	int i, j, xchg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	void *rx_tmp_ptr = MNULL;
+	mlan_private *pmpriv = (mlan_private *)priv;
+
+	ENTER();
+
+	for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) {
+		pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->
+							  pmoal_handle,
+							  pmpriv->rx_pkt_lock);
+		if (!rx_reor_tbl_ptr->rx_reorder_ptr[i]) {
+			pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->
+								    adapter->
+								    pmoal_handle,
+								    pmpriv->
+								    rx_pkt_lock);
+			break;
+		}
+		rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];
+		rx_reor_tbl_ptr->rx_reorder_ptr[i] = MNULL;
+		pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->adapter->
+							    pmoal_handle,
+							    pmpriv->
+							    rx_pkt_lock);
+		wlan_11n_dispatch_pkt(priv, rx_tmp_ptr);
+	}
+
+	pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->pmoal_handle,
+						  pmpriv->rx_pkt_lock);
+	/*
+	 * We don't have a circular buffer, hence use rotation to simulate
+	 * circular buffer
+	 */
+	if (i > 0) {
+		xchg = rx_reor_tbl_ptr->win_size - i;
+		for (j = 0; j < xchg; ++j) {
+			rx_reor_tbl_ptr->rx_reorder_ptr[j] =
+				rx_reor_tbl_ptr->rx_reorder_ptr[i + j];
+			rx_reor_tbl_ptr->rx_reorder_ptr[i + j] = MNULL;
+		}
+	}
+
+	rx_reor_tbl_ptr->start_win = (rx_reor_tbl_ptr->start_win + i)
+		& (MAX_TID_VALUE - 1);
+
+	pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->adapter->
+						    pmoal_handle,
+						    pmpriv->rx_pkt_lock);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function delete rxreorder table's entry
+ *          and free the memory
+ *
+ *  @param priv             A pointer to mlan_private
+ *  @param rx_reor_tbl_ptr  A pointer to structure RxReorderTbl
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_11n_delete_rxreorder_tbl_entry(mlan_private *priv,
+				    RxReorderTbl *rx_reor_tbl_ptr)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+
+	ENTER();
+
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+	mlan_block_rx_process(pmadapter, MTRUE);
+
+	wlan_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr,
+					      (rx_reor_tbl_ptr->start_win +
+					       rx_reor_tbl_ptr->win_size)
+					      & (MAX_TID_VALUE - 1));
+
+	if (rx_reor_tbl_ptr->timer_context.timer) {
+		if (rx_reor_tbl_ptr->timer_context.timer_is_set) {
+			priv->adapter->callbacks.moal_stop_timer(pmadapter->
+								 pmoal_handle,
+								 rx_reor_tbl_ptr->timer_context.
+								 timer);
+			rx_reor_tbl_ptr->timer_context.timer_is_set = MFALSE;
+		}
+		priv->adapter->callbacks.moal_free_timer(pmadapter->
+							 pmoal_handle,
+							 rx_reor_tbl_ptr->timer_context.
+							 timer);
+		rx_reor_tbl_ptr->timer_context.timer = MNULL;
+	}
+
+	PRINTM(MDAT_D, "Delete rx_reor_tbl_ptr: %p\n", rx_reor_tbl_ptr);
+	util_unlink_list(pmadapter->pmoal_handle,
+			 &priv->rx_reorder_tbl_ptr,
+			 (pmlan_linked_list)rx_reor_tbl_ptr,
+			 pmadapter->callbacks.moal_spin_lock,
+			 pmadapter->callbacks.moal_spin_unlock);
+
+	pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)rx_reor_tbl_ptr->
+					rx_reorder_ptr);
+	pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)rx_reor_tbl_ptr);
+	mlan_block_rx_process(pmadapter, MFALSE);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function returns the last used sequence number
+ *
+ *  @param rx_reorder_tbl_ptr   A pointer to structure RxReorderTbl
+ *
+ *  @return                     Last used sequence number
+ */
+static int
+wlan_11n_find_last_seqnum(RxReorderTbl *rx_reorder_tbl_ptr)
+{
+	int i;
+
+	ENTER();
+	for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i) {
+		if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
+			LEAVE();
+			return i;
+		}
+	}
+	LEAVE();
+	return -1;
+}
+
+/**
+ *  @brief This function flushes all data
+ *
+ *  @param priv          A pointer to  mlan_private structure
+ *  @param rx_reor_tbl_ptr  A pointer to RxReorderTbl
+ *
+ *  @return             N/A
+ */
+static t_void
+wlan_start_flush_data(mlan_private *priv, RxReorderTbl *rx_reor_tbl_ptr)
+{
+
+	int startWin;
+
+	ENTER();
+	wlan_11n_display_tbl_ptr(priv->adapter, rx_reor_tbl_ptr);
+
+	startWin = wlan_11n_find_last_seqnum(rx_reor_tbl_ptr);
+	if (startWin >= 0) {
+		PRINTM(MINFO, "Flush data %d\n", startWin);
+		wlan_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr,
+						      ((rx_reor_tbl_ptr->
+							start_win + startWin +
+							1) & (MAX_TID_VALUE -
+							      1)));
+	}
+	wlan_11n_display_tbl_ptr(priv->adapter, rx_reor_tbl_ptr);
+	LEAVE();
+}
+
+/**
+ *  @brief This function set the flag to flushes data
+ *
+ *  @param context      Reorder context pointer
+ *
+ *  @return             N/A
+ */
+static t_void
+wlan_flush_data(t_void *context)
+{
+	reorder_tmr_cnxt_t *reorder_cnxt = (reorder_tmr_cnxt_t *)context;
+	ENTER();
+	/* Set the flag to flush data */
+	reorder_cnxt->priv->adapter->flush_data = MTRUE;
+	reorder_cnxt->ptr->flush_data = MTRUE;
+	reorder_cnxt->timer_is_set = MFALSE;
+	wlan_recv_event(reorder_cnxt->priv, MLAN_EVENT_ID_DRV_DEFER_RX_WORK,
+			MNULL);
+	LEAVE();
+}
+
+/**
+ *  @brief This function will create a entry in rx reordering table for the
+ *          given ta/tid and will initialize it with seq_num, win_size
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ta       ta to find in reordering table
+ *  @param tid      tid to find in reordering table
+ *  @param win_size win_size for the give ta/tid pair.
+ *  @param seq_num  Starting sequence number for current entry.
+ *
+ *  @return         N/A
+ */
+static t_void
+wlan_11n_create_rxreorder_tbl(mlan_private *priv, t_u8 *ta, int tid,
+			      int win_size, int seq_num)
+{
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	RxReorderTbl *rx_reor_tbl_ptr, *new_node;
+	sta_node *sta_ptr = MNULL;
+	t_u16 last_seq = 0;
+
+	ENTER();
+
+	/*
+	 * If we get a TID, ta pair which is already present dispatch all the
+	 * the packets and move the window size until the ssn
+	 */
+	rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, tid, ta);
+	if (rx_reor_tbl_ptr) {
+		wlan_11n_dispatch_pkt_until_start_win(priv,
+						      rx_reor_tbl_ptr, seq_num);
+	} else {
+		PRINTM(MDAT_D, "%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");
+			LEAVE();
+			return;
+		}
+
+		util_init_list((pmlan_linked_list)new_node);
+		new_node->tid = tid;
+		memcpy(pmadapter, new_node->ta, ta, MLAN_MAC_ADDR_LENGTH);
+		new_node->start_win = seq_num;
+		new_node->pkt_count = 0;
+		if (queuing_ra_based(priv)) {
+			/* TODO for adhoc */
+			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];
+			}
+			if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
+				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;
+
+		if (pmadapter->callbacks.
+		    moal_malloc(pmadapter->pmoal_handle,
+				sizeof(t_void *) * 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);
+			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;
+		new_node->ba_status = BA_STREAM_SETUP_INPROGRESS;
+
+		pmadapter->callbacks.moal_init_timer(pmadapter->pmoal_handle,
+						     &new_node->
+						     timer_context.timer,
+						     wlan_flush_data,
+						     &new_node->timer_context);
+
+		for (i = 0; i < win_size; ++i)
+			new_node->rx_reorder_ptr[i] = MNULL;
+
+		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);
+	}
+
+	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(priv->adapter, padd_ba_req, pdata_buf,
+	       sizeof(HostCmd_DS_11N_ADDBA_REQ));
+	padd_ba_req->block_ack_param_set =
+		wlan_cpu_to_le16(padd_ba_req->block_ack_param_set);
+	padd_ba_req->block_ack_tmo =
+		wlan_cpu_to_le16(padd_ba_req->block_ack_tmo);
+	padd_ba_req->ssn = wlan_cpu_to_le16(padd_ba_req->ssn);
+	padd_ba_req->add_req_result = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+  *  @brief This function check if AMPDU Rx allowed
+  *
+  *  @param priv        A pointer to mlan_private structure
+  *  @param tid         TID
+  *
+  *  @return            MTRUE/MFALSE
+  */
+t_u8
+wlan_is_addba_reject(mlan_private *priv, t_u8 tid)
+{
+#ifdef STA_SUPPORT
+	if (priv->bss_mode == MLAN_BSS_MODE_IBSS)
+		return priv->ibss_addba_reject[tid];
+#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(priv->adapter, padd_ba_rsp->peer_mac_addr,
+	       pevt_addba_req->peer_mac_addr, 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
+	    || ((priv->bss_mode == MLAN_BSS_MODE_IBSS)
+		&& !wlan_is_11n_enabled(priv, pevt_addba_req->peer_mac_addr))
+	    || ((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(priv->adapter, pdel_ba, pdata_buf, sizeof(HostCmd_DS_11N_DELBA));
+	pdel_ba->del_ba_param_set = wlan_cpu_to_le16(pdel_ba->del_ba_param_set);
+	pdel_ba->reason_code = wlan_cpu_to_le16(pdel_ba->reason_code);
+	pdel_ba->del_result = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function will identify if RxReodering is needed for the packet
+ *          and will do the reordering if required before sending it to kernel
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param seq_num  Seqence number of the current packet
+ *  @param tid      Tid of the current packet
+ *  @param ta       Transmiter address of the current packet
+ *  @param pkt_type Packetype for the current packet (to identify if its a BAR)
+ *  @param payload  Pointer to the payload
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+mlan_11n_rxreorder_pkt(void *priv, t_u16 seq_num, t_u16 tid,
+		       t_u8 *ta, t_u8 pkt_type, void *payload)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+	int prev_start_win, start_win, end_win, win_size;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_adapter pmadapter = ((mlan_private *)priv)->adapter;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		wlan_11n_get_rxreorder_tbl((mlan_private *)priv, tid, ta);
+	if (!rx_reor_tbl_ptr || rx_reor_tbl_ptr->win_size <= 1) {
+		if (pkt_type != PKT_TYPE_BAR)
+			wlan_11n_dispatch_pkt(priv, payload);
+
+		LEAVE();
+		return ret;
+
+	} else {
+		if (rx_reor_tbl_ptr->flush_data) {
+			rx_reor_tbl_ptr->flush_data = MFALSE;
+			wlan_start_flush_data(priv, rx_reor_tbl_ptr);
+		}
+		if ((pkt_type == PKT_TYPE_AMSDU) && !rx_reor_tbl_ptr->amsdu) {
+			wlan_11n_dispatch_pkt(priv, payload);
+			LEAVE();
+			return ret;
+		}
+		if (pkt_type == PKT_TYPE_BAR)
+			PRINTM(MDAT_D, "BAR ");
+		if (pkt_type == PKT_TYPE_AMSDU)
+			PRINTM(MDAT_D, "AMSDU ");
+
+		if (rx_reor_tbl_ptr->check_start_win) {
+			if (seq_num == rx_reor_tbl_ptr->start_win)
+				rx_reor_tbl_ptr->check_start_win = MFALSE;
+			else {
+				rx_reor_tbl_ptr->pkt_count++;
+				if (rx_reor_tbl_ptr->pkt_count <
+				    (rx_reor_tbl_ptr->win_size / 2)) {
+					if (rx_reor_tbl_ptr->last_seq ==
+					    seq_num) {
+						/** drop duplicate packet */
+						ret = MLAN_STATUS_FAILURE;
+					} else {
+						/** forward the packet to kernel */
+						rx_reor_tbl_ptr->last_seq =
+							seq_num;
+						if (pkt_type != PKT_TYPE_BAR)
+							wlan_11n_dispatch_pkt
+								(priv, payload);
+					}
+					LEAVE();
+					return ret;
+				}
+				rx_reor_tbl_ptr->check_start_win = MFALSE;
+				if ((seq_num != rx_reor_tbl_ptr->start_win) &&
+				    (rx_reor_tbl_ptr->last_seq !=
+				     DEFAULT_SEQ_NUM)) {
+					end_win =
+						(rx_reor_tbl_ptr->start_win +
+						 rx_reor_tbl_ptr->win_size -
+						 1) & (MAX_TID_VALUE - 1);
+					if (((end_win >
+					      rx_reor_tbl_ptr->start_win)
+					     && (rx_reor_tbl_ptr->last_seq >=
+						 rx_reor_tbl_ptr->start_win)
+					     && (rx_reor_tbl_ptr->last_seq <
+						 end_win)) ||
+					    ((end_win <
+					      rx_reor_tbl_ptr->start_win) &&
+					     ((rx_reor_tbl_ptr->last_seq >=
+					       rx_reor_tbl_ptr->start_win) ||
+					      (rx_reor_tbl_ptr->last_seq <
+					       end_win)))) {
+						PRINTM(MDAT_D,
+						       "Update start_win: last_seq=%d, start_win=%d seq_num=%d\n",
+						       rx_reor_tbl_ptr->
+						       last_seq,
+						       rx_reor_tbl_ptr->
+						       start_win, seq_num);
+						rx_reor_tbl_ptr->start_win =
+							rx_reor_tbl_ptr->
+							last_seq + 1;
+					} else if ((seq_num <
+						    rx_reor_tbl_ptr->start_win)
+						   && (seq_num >
+						       rx_reor_tbl_ptr->
+						       last_seq)) {
+						PRINTM(MDAT_D,
+						       "Update start_win: last_seq=%d, start_win=%d seq_num=%d\n",
+						       rx_reor_tbl_ptr->
+						       last_seq,
+						       rx_reor_tbl_ptr->
+						       start_win, seq_num);
+						rx_reor_tbl_ptr->start_win =
+							rx_reor_tbl_ptr->
+							last_seq + 1;
+					}
+				}
+			}
+		}
+		if (rx_reor_tbl_ptr->force_no_drop) {
+			wlan_11n_dispatch_pkt_until_start_win(priv,
+							      rx_reor_tbl_ptr,
+							      (rx_reor_tbl_ptr->
+							       start_win +
+							       rx_reor_tbl_ptr->
+							       win_size)
+							      & (MAX_TID_VALUE -
+								 1));
+			if (pkt_type != PKT_TYPE_BAR)
+				rx_reor_tbl_ptr->start_win = seq_num;
+			mlan_11n_rxreorder_timer_restart(pmadapter,
+							 rx_reor_tbl_ptr);
+		}
+
+		prev_start_win = start_win = rx_reor_tbl_ptr->start_win;
+		win_size = rx_reor_tbl_ptr->win_size;
+		end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
+
+		PRINTM(MDAT_D, "TID %d, TA " MACSTR "\n", tid, MAC2STR(ta));
+		PRINTM(MDAT_D,
+		       "1:seq_num %d start_win %d win_size %d end_win %d\n",
+		       seq_num, start_win, win_size, end_win);
+		/*
+		 * If seq_num is less then starting win then ignore and drop
+		 * the packet
+		 */
+		if (rx_reor_tbl_ptr->force_no_drop) {
+			PRINTM(MDAT_D, "No drop packet\n");
+			rx_reor_tbl_ptr->force_no_drop = MFALSE;
+		} else {
+			/* Wrap */
+			if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
+				if (seq_num >= ((start_win + (TWOPOW11)) &
+						(MAX_TID_VALUE - 1)) &&
+				    (seq_num < start_win)) {
+					if (pkt_type == PKT_TYPE_BAR)
+						PRINTM(MDAT_D,
+						       "BAR: start_win=%d, end_win=%d, seq_num=%d\n",
+						       start_win, end_win,
+						       seq_num);
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+			} else if ((seq_num < start_win) ||
+				   (seq_num >= (start_win + (TWOPOW11)))) {
+				if (pkt_type == PKT_TYPE_BAR)
+					PRINTM(MDAT_D,
+					       "BAR: start_win=%d, end_win=%d, seq_num=%d\n",
+					       start_win, end_win, seq_num);
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+
+		/*
+		 * If this packet is a BAR we adjust seq_num as
+		 * WinStart = seq_num
+		 */
+		if (pkt_type == PKT_TYPE_BAR)
+			seq_num =
+				((seq_num + win_size) - 1) & (MAX_TID_VALUE -
+							      1);
+
+		PRINTM(MDAT_D,
+		       "2:seq_num %d start_win %d win_size %d end_win %d\n",
+		       seq_num, start_win, win_size, end_win);
+
+		if (((end_win < start_win) &&
+		     (seq_num < start_win) && (seq_num > end_win))
+		    || ((end_win > start_win) &&
+			((seq_num > end_win) || (seq_num < start_win)))) {
+
+			end_win = seq_num;
+			if (((seq_num - win_size) + 1) >= 0)
+				start_win = (end_win - win_size) + 1;
+			else
+				start_win = (MAX_TID_VALUE -
+					     (win_size - seq_num)) + 1;
+			ret = wlan_11n_dispatch_pkt_until_start_win(priv,
+								    rx_reor_tbl_ptr,
+								    start_win);
+			if (ret)
+				goto done;
+		}
+
+		PRINTM(MDAT_D, "3:seq_num %d start_win %d win_size %d"
+		       " end_win %d\n", seq_num, start_win, win_size, end_win);
+		if (pkt_type != PKT_TYPE_BAR) {
+			if (seq_num >= start_win) {
+				if (rx_reor_tbl_ptr->rx_reorder_ptr[seq_num
+								    -
+								    start_win])
+				{
+					PRINTM(MDAT_D, "Drop Duplicate Pkt\n");
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+				rx_reor_tbl_ptr->rx_reorder_ptr[seq_num
+								- start_win] =
+					payload;
+			} else {	/* Wrap condition */
+				if (rx_reor_tbl_ptr->rx_reorder_ptr[(seq_num
+								     +
+								     (MAX_TID_VALUE))
+								    -
+								    start_win])
+				{
+					PRINTM(MDAT_D, "Drop Duplicate Pkt\n");
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+				rx_reor_tbl_ptr->rx_reorder_ptr[(seq_num
+								 +
+								 (MAX_TID_VALUE))
+								- start_win] =
+					payload;
+			}
+		}
+
+		wlan_11n_display_tbl_ptr(pmadapter, rx_reor_tbl_ptr);
+
+		/*
+		 * Dispatch all packets sequentially from start_win until a
+		 * hole is found and adjust the start_win appropriately
+		 */
+		ret = wlan_11n_scan_and_dispatch(priv, rx_reor_tbl_ptr);
+
+		wlan_11n_display_tbl_ptr(pmadapter, rx_reor_tbl_ptr);
+	}
+
+done:
+	if (!rx_reor_tbl_ptr->timer_context.timer_is_set ||
+	    (prev_start_win != rx_reor_tbl_ptr->start_win)) {
+
+		mlan_11n_rxreorder_timer_restart(pmadapter, rx_reor_tbl_ptr);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will delete an entry for a given tid/ta pair. tid/ta
+ *          are taken from delba_event body
+ *
+ *  @param priv         A pointer to mlan_private
+ *  @param tid          tid to send delba
+ *  @param peer_mac     MAC address to send delba
+ *  @param type         TYPE_DELBA_SENT	or TYPE_DELBA_RECEIVE
+ *  @param initiator    MTRUE if we are initiator of ADDBA, MFALSE otherwise
+ *  @param reason_code  delete ba reason
+ *
+ *  @return             N/A
+ */
+void
+mlan_11n_delete_bastream_tbl(mlan_private *priv, int tid,
+			     t_u8 *peer_mac, t_u8 type, int initiator,
+			     t_u16 reason_code)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+	TxBAStreamTbl *ptxtbl;
+	t_u8 cleanup_rx_reorder_tbl;
+	raListTbl *ra_list = MNULL;
+	int tid_down;
+
+	ENTER();
+
+	if (type == TYPE_DELBA_RECEIVE)
+		cleanup_rx_reorder_tbl = (initiator) ? MTRUE : MFALSE;
+	else
+		cleanup_rx_reorder_tbl = (initiator) ? MFALSE : MTRUE;
+
+	PRINTM(MEVENT, "delete_bastream_tbl: " MACSTR " tid=%d, type=%d"
+	       "initiator=%d reason=%d\n", MAC2STR(peer_mac), tid, type,
+	       initiator, reason_code);
+
+	if (cleanup_rx_reorder_tbl) {
+		rx_reor_tbl_ptr =
+			wlan_11n_get_rxreorder_tbl(priv, tid, peer_mac);
+		if (!rx_reor_tbl_ptr) {
+			PRINTM(MWARN, "TID, TA not found in table!\n");
+			LEAVE();
+			return;
+		}
+		wlan_11n_delete_rxreorder_tbl_entry(priv, rx_reor_tbl_ptr);
+	} else {
+		wlan_request_ralist_lock(priv);
+		ptxtbl = wlan_11n_get_txbastream_tbl(priv, tid, peer_mac,
+						     MFALSE);
+		if (!ptxtbl) {
+			PRINTM(MWARN, "TID, RA not found in table!\n");
+			wlan_release_ralist_lock(priv);
+			LEAVE();
+			return;
+		}
+		wlan_11n_delete_txbastream_tbl_entry(priv, ptxtbl);
+		wlan_release_ralist_lock(priv);
+		tid_down = wlan_get_wmm_tid_down(priv, tid);
+		ra_list = wlan_wmm_get_ralist_node(priv, tid_down, peer_mac);
+		if (ra_list) {
+			ra_list->amsdu_in_ampdu = MFALSE;
+			ra_list->ba_status = BA_STREAM_NOT_SETUP;
+			if (type == TYPE_DELBA_RECEIVE) {
+				if (reason_code == REASON_CODE_STA_TIMEOUT)
+					ra_list->del_ba_count = 0;
+				else
+					ra_list->del_ba_count++;
+				ra_list->packet_count = 0;
+				ra_list->ba_packet_threshold =
+					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(MERROR, "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(priv->adapter, delba.peer_mac_addr, event->peer_mac_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	delba.del_ba_param_set |= (t_u16)event->tid << DELBA_TID_POS;
+	delba.del_ba_param_set |=
+		(t_u16)event->origninator << DELBA_INITIATOR_POS;
+	delba.reason_code = REASON_CODE_STA_TIMEOUT;
+	wlan_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, MNULL, &delba);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function cleans up reorder tbl
+ *
+ *  @param priv     A pointer to mlan_private
+ *
+ *  @return         N/A
+ */
+void
+wlan_11n_cleanup_reorder_tbl(mlan_private *priv)
+{
+	RxReorderTbl *del_tbl_ptr;
+
+	ENTER();
+
+	while ((del_tbl_ptr = (RxReorderTbl *)
+		util_peek_list(priv->adapter->pmoal_handle,
+			       &priv->rx_reorder_tbl_ptr,
+			       priv->adapter->callbacks.moal_spin_lock,
+			       priv->adapter->callbacks.moal_spin_unlock))) {
+		wlan_11n_delete_rxreorder_tbl_entry(priv, del_tbl_ptr);
+	}
+
+	util_init_list((pmlan_linked_list)&priv->rx_reorder_tbl_ptr);
+
+	memset(priv->adapter, priv->rx_seq, 0xff, sizeof(priv->rx_seq));
+	LEAVE();
+}
+
+/**
+ *  @brief This function handle the rxba_sync event
+ *
+ *  @param priv       A pointer to mlan_private
+ *  @param event_buf  A pointer to event buf
+ *  @param len        event_buf length
+ *  @return           N/A
+ */
+void
+wlan_11n_rxba_sync_event(mlan_private *priv, t_u8 *event_buf, t_u16 len)
+{
+	MrvlIEtypes_RxBaSync_t *tlv_rxba = (MrvlIEtypes_RxBaSync_t *)event_buf;
+	t_u16 tlv_type, tlv_len;
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+	t_u8 i, j;
+	t_u16 seq_num = 0;
+	int tlv_buf_left = len;
+	ENTER();
+
+	DBG_HEXDUMP(MEVT_D, "RXBA_SYNC_EVT", event_buf, len);
+	while (tlv_buf_left >= sizeof(MrvlIEtypes_RxBaSync_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv_rxba->header.type);
+		tlv_len = wlan_le16_to_cpu(tlv_rxba->header.len);
+		if (tlv_type != TLV_TYPE_RXBA_SYNC) {
+			PRINTM(MERROR, "Wrong TLV id=0x%x\n", tlv_type);
+			goto done;
+		}
+		tlv_rxba->seq_num = wlan_le16_to_cpu(tlv_rxba->seq_num);
+		tlv_rxba->bitmap_len = wlan_le16_to_cpu(tlv_rxba->bitmap_len);
+		PRINTM(MEVENT, MACSTR " tid=%d seq_num=%d bitmap_len=%d\n",
+		       MAC2STR(tlv_rxba->mac), tlv_rxba->tid, tlv_rxba->seq_num,
+		       tlv_rxba->bitmap_len);
+		rx_reor_tbl_ptr =
+			wlan_11n_get_rxreorder_tbl(priv, tlv_rxba->tid,
+						   tlv_rxba->mac);
+		if (!rx_reor_tbl_ptr) {
+			PRINTM(MEVENT, "Can not find rx_reorder_tbl\n");
+			goto done;
+		}
+		if (rx_reor_tbl_ptr->force_no_drop) {
+			PRINTM(MEVENT, "Ignore RXBA_SYNC_EVT in resume\n");
+			goto done;
+		}
+		for (i = 0; i < tlv_rxba->bitmap_len; i++) {
+			for (j = 0; j < 8; j++) {
+				if (tlv_rxba->bitmap[i] & (1 << j)) {
+					seq_num =
+						(tlv_rxba->seq_num + i * 8 +
+						 j) & (MAX_TID_VALUE - 1);
+					PRINTM(MEVENT,
+					       "Fw dropped packet, seq=%d start_win=%d, win_size=%d\n",
+					       seq_num,
+					       rx_reor_tbl_ptr->start_win,
+					       rx_reor_tbl_ptr->win_size);
+					if (MLAN_STATUS_SUCCESS !=
+					    mlan_11n_rxreorder_pkt(priv,
+								   seq_num,
+								   tlv_rxba->
+								   tid,
+								   tlv_rxba->
+								   mac, 0,
+								   (t_void *)
+								   RX_PKT_DROPPED_IN_FW))
+					{
+						PRINTM(MERROR,
+						       "Fail to handle dropped packet, seq=%d\n",
+						       seq_num);
+					}
+				}
+			}
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv_rxba =
+			(MrvlIEtypes_RxBaSync_t *)((t_u8 *)tlv_rxba + tlv_len +
+						   sizeof(MrvlIEtypesHeader_t));
+	}
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function cleans up reorder tbl for specific station
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ta       ta to find in reordering table
+ *  @return         N/A
+ */
+void
+wlan_cleanup_reorder_tbl(mlan_private *priv, t_u8 *ta)
+{
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+	t_u8 i;
+	ENTER();
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, i, ta);
+		if (rx_reor_tbl_ptr)
+			wlan_11n_delete_rxreorder_tbl_entry(priv,
+							    rx_reor_tbl_ptr);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function will set force_no_drop flag in rxreorder_tbl.
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param flag    MTRUE/MFALSE
+ *
+ *  @return        N/A
+ */
+void
+wlan_set_rxreorder_tbl_no_drop_flag(mlan_private *priv, t_u8 flag)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		rx_reor_tbl_ptr->force_no_drop = flag;
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param flag         MTRUE/MFALSE
+ *  @return             N/A
+ */
+void
+wlan_update_rxreorder_tbl(pmlan_adapter pmadapter, t_u8 flag)
+{
+	t_u8 i;
+	pmlan_private priv = MNULL;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			wlan_set_rxreorder_tbl_no_drop_flag(priv, flag);
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief This function will flush the data  in rxreorder_tbl.
+ *  	   which has flush_data flag on.
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return        N/A
+ */
+void
+wlan_flush_priv_rxreorder_tbl(mlan_private *priv)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		if (rx_reor_tbl_ptr->flush_data) {
+			rx_reor_tbl_ptr->flush_data = MFALSE;
+			wlan_start_flush_data(priv, rx_reor_tbl_ptr);
+		}
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @return             N/A
+ */
+void
+wlan_flush_rxreorder_tbl(pmlan_adapter pmadapter)
+{
+	t_u8 i;
+	pmlan_private priv = MNULL;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			wlan_flush_priv_rxreorder_tbl(priv);
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_win_size based on coex flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param coex_flag    coex flag
+ *
+ *  @return             N/A
+ */
+void
+wlan_update_ampdu_rxwinsize(pmlan_adapter pmadapter, t_u8 coex_flag)
+{
+	t_u8 i;
+	t_u32 rx_win_size = 0;
+	pmlan_private priv = MNULL;
+
+	ENTER();
+	if (!pmadapter->coex_rx_winsize) {
+		LEAVE();
+		return;
+	}
+	PRINTM(MEVENT, "Update rxwinsize %d\n", coex_flag);
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			rx_win_size = priv->add_ba_param.rx_win_size;
+			if (coex_flag == MTRUE) {
+#ifdef STA_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_STA)
+					priv->add_ba_param.rx_win_size =
+						MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+					priv->add_ba_param.rx_win_size =
+						MLAN_WFD_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+				if (priv->bss_type == MLAN_BSS_TYPE_NAN)
+					priv->add_ba_param.rx_win_size =
+						MLAN_NAN_COEX_AMPDU_DEF_RXWINSIZE;
+#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 This function updates ampdu rx_win_size
+ *
+ *  @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_sd8897/mlan/mlan_11n_rxreorder.h b/wlan_sd8897/mlan/mlan_11n_rxreorder.h
new file mode 100644
index 0000000..d7465d2
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_11n_rxreorder.h
@@ -0,0 +1,102 @@
+/** @file mlan_11n_rxreorder.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of 11n RxReordering functionalities
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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_sd8897/mlan/mlan_cfp.c b/wlan_sd8897/mlan/mlan_cfp.c
new file mode 100644
index 0000000..1f6ffb0
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_cfp.c
@@ -0,0 +1,2379 @@
+/**
+ * @file mlan_cfp.c
+ *
+ *  @brief This file contains WLAN client mode channel, frequency and power
+ *  related code
+ *
+ *  Copyright (C) 2009-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+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"
+#include "mlan_sdio.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/** 100mW */
+#define WLAN_TX_PWR_DEFAULT     20
+/** 100mW */
+#define WLAN_TX_PWR_00_DEFAULT      20
+/** 100mW */
+#define WLAN_TX_PWR_US_DEFAULT      20
+/** 100mW */
+#define WLAN_TX_PWR_JP_BG_DEFAULT   20
+/** 200mW */
+#define WLAN_TX_PWR_JP_A_DEFAULT    23
+/** 100mW */
+#define WLAN_TX_PWR_FR_100MW        20
+/** 10mW */
+#define WLAN_TX_PWR_FR_10MW         10
+/** 100mW */
+#define WLAN_TX_PWR_EMEA_DEFAULT    20
+/** 2000mW */
+#define WLAN_TX_PWR_CN_2000MW       33
+/** 200mW */
+#define WLAN_TX_PWR_200MW   23
+/** 1000mW */
+#define WLAN_TX_PWR_1000MW   30
+/** 30mW */
+#define WLAN_TX_PWR_SP_30MW   14
+/** 60mW */
+#define WLAN_TX_PWR_SP_60MW   17
+/** 25mW */
+#define WLAN_TX_PWR_25MW   14
+/** 250mW */
+#define WLAN_TX_PWR_250MW   24
+
+/** Region code mapping */
+typedef struct _country_code_mapping {
+    /** Region */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+    /** Code for B/G CFP table */
+	t_u8 cfp_code_bg;
+    /** Code for A CFP table */
+	t_u8 cfp_code_a;
+} country_code_mapping_t;
+
+#define EU_CFP_CODE_BG  0x30
+#define EU_CFP_CODE_A   0x30
+
+/** Region code mapping table */
+static country_code_mapping_t country_code_mapping[] = {
+	{"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    */
+};
+
+/** 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"
+};
+
+/**
+ * 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: USA FCC/Canada IC */
+static chan_freq_power_t channel_freq_power_US_BG[] = {
+	{1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Europe ETSI/China */
+static chan_freq_power_t channel_freq_power_EU_BG[] = {
+	{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
+	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPNFE_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE}
+};
+
+/** Band : 'B/G', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR_BG[] = {
+	{1, 2412, WLAN_TX_PWR_1000MW, MFALSE},
+	{2, 2417, WLAN_TX_PWR_1000MW, MFALSE},
+	{3, 2422, WLAN_TX_PWR_1000MW, MFALSE},
+	{4, 2427, WLAN_TX_PWR_1000MW, MFALSE},
+	{5, 2432, WLAN_TX_PWR_1000MW, MFALSE},
+	{6, 2437, WLAN_TX_PWR_1000MW, MFALSE},
+	{7, 2442, WLAN_TX_PWR_1000MW, MFALSE},
+	{8, 2447, WLAN_TX_PWR_1000MW, MFALSE},
+	{9, 2452, WLAN_TX_PWR_1000MW, MFALSE},
+	{10, 2457, WLAN_TX_PWR_1000MW, MFALSE},
+	{11, 2462, WLAN_TX_PWR_1000MW, MFALSE},
+	{12, 2467, WLAN_TX_PWR_1000MW, MFALSE},
+	{13, 2472, WLAN_TX_PWR_1000MW, MFALSE},
+};
+
+/** Band : 'B/G', Region: Special */
+static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
+};
+
+/**
+ * The 2.4GHz CFP tables
+ */
+static cfp_table_t cfp_table_BG[] = {
+	{
+	 0x01,			/* Brazil */
+	 channel_freq_power_BR_BG,
+	 NELEMENTS(channel_freq_power_BR_BG),
+	 },
+	{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 FCC */
+
+/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
+/** Band: 'A', Region: USA FCC */
+static chan_freq_power_t channel_freq_power_A[] = {
+	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Region: Canada IC */
+static chan_freq_power_t channel_freq_power_CAN_A[] = {
+	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Region: Europe ETSI */
+static chan_freq_power_t channel_freq_power_EU_A[] = {
+	{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE}
+};
+
+/** Band: 'A', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN_A[] = {
+	{36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE}
+};
+
+/** Band: 'A', Region: China */
+static chan_freq_power_t channel_freq_power_CN_A[] = {
+	{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
+	{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
+	{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
+	{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
+	{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
+	{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
+	{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
+	{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
+	{149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE}
+};
+
+/** Band: 'A', NULL */
+static chan_freq_power_t channel_freq_power_NULL_A[] = {
+};
+
+/** Band: 'A', Region: Spain/Austria/Brazil */
+static chan_freq_power_t channel_freq_power_SPN2_A[] = {
+	{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
+	{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
+	{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
+	{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
+	{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
+	{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
+	{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
+	{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR1_A[] = {
+	{100, 5500, WLAN_TX_PWR_250MW, MTRUE},
+	{104, 5520, WLAN_TX_PWR_250MW, MTRUE},
+	{108, 5540, WLAN_TX_PWR_250MW, MTRUE},
+	{112, 5560, WLAN_TX_PWR_250MW, MTRUE},
+	{116, 5580, WLAN_TX_PWR_250MW, MTRUE},
+	{120, 5600, WLAN_TX_PWR_250MW, MTRUE},
+	{124, 5620, WLAN_TX_PWR_250MW, MTRUE},
+	{128, 5640, WLAN_TX_PWR_250MW, MTRUE},
+	{132, 5660, WLAN_TX_PWR_250MW, MTRUE},
+	{136, 5680, WLAN_TX_PWR_250MW, MTRUE},
+	{140, 5700, WLAN_TX_PWR_250MW, MTRUE},
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR2_A[] = {
+	{149, 5745, WLAN_TX_PWR_1000MW, MFALSE},
+	{153, 5765, WLAN_TX_PWR_1000MW, MFALSE},
+	{157, 5785, WLAN_TX_PWR_1000MW, MFALSE},
+	{161, 5805, WLAN_TX_PWR_1000MW, MFALSE},
+	{165, 5825, WLAN_TX_PWR_1000MW, MFALSE}
+};
+
+/** Band: 'A', Region: Russia */
+static chan_freq_power_t channel_freq_power_RU_A[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{132, 5660, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{136, 5680, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{140, 5700, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+};
+
+/** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+};
+
+/** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
+static chan_freq_power_t channel_freq_power_lower_middle_band[] = {
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE},
+};
+
+/** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
+static chan_freq_power_t channel_freq_power_upper_middle_band[] = {
+	{100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE},
+};
+
+/** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_high_band[] = {
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
+ * High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_high_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Code: 6, Low band (5150-5250 MHz) and
+ * mid low (5260-5320) and High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_middle_high_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
+};
+
+/**
+ * The 5GHz CFP tables
+ */
+static cfp_table_t cfp_table_A[] = {
+	{0x1,			/* Low band (5150-5250 MHz) channels */
+	 channel_freq_power_low_band,
+	 NELEMENTS(channel_freq_power_low_band)
+	 },
+	{0x2,			/* Lower middle band (5250-5350 MHz) channels */
+	 channel_freq_power_lower_middle_band,
+	 NELEMENTS(channel_freq_power_lower_middle_band)
+	 },
+	{0x3,			/* Upper middle band (5470-5725 MHz) channels */
+	 channel_freq_power_upper_middle_band,
+	 NELEMENTS(channel_freq_power_upper_middle_band)
+	 },
+	{0x4,			/* High band (5725-5850 MHz) channels */
+	 channel_freq_power_high_band,
+	 NELEMENTS(channel_freq_power_high_band)
+	 },
+	{0x5,			/* Low band (5150-5250 MHz) and
+				   High band (5725-5850 MHz) channels */
+	 channel_freq_power_low_high_band,
+	 NELEMENTS(channel_freq_power_low_high_band)
+	 },
+	{0x6,			/* Low band (5150-5250 MHz)
+				   Mid band (5260-5320) and
+				   High band (5725-5850 MHz) channels */
+	 channel_freq_power_low_middle_high_band,
+	 NELEMENTS(channel_freq_power_low_middle_high_band)
+	 },
+	{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),
+	 },
+	{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))
+
+/********************************************************
+			Global Variables
+********************************************************/
+/**
+ * The table to keep region code
+ */
+t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = {
+	0x10, 0x20, 0x30, 0x40, 0x41, 0x50, 0xfe, 0xff
+};
+
+/** The table to keep CFP code for BG */
+t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG] = { };
+
+/** The table to keep CFP code for A */
+t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = { 0x1, 0x2, 0x3, 0x4, 0x5 };
+
+/**
+ * The rates supported for ad-hoc B mode
+ */
+t_u8 AdhocRates_B[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
+
+/**
+ * The rates supported for ad-hoc G mode
+ */
+t_u8 AdhocRates_G[G_SUPPORTED_RATES] = {
+	0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported for ad-hoc BG mode
+ */
+t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = {
+	0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
+	0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in A mode for ad-hoc
+ */
+t_u8 AdhocRates_A[A_SUPPORTED_RATES] = {
+	0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in A mode (used for BAND_A)
+ */
+t_u8 SupportedRates_A[A_SUPPORTED_RATES] = {
+	0x0c, 0x12, 0x18, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported by the card
+ */
+t_u16 WlanDataRates[WLAN_SUPPORTED_RATES_EXT] = {
+	0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
+	0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,
+	0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75,
+	0x82, 0x0C, 0x1B, 0x36, 0x51, 0x6C, 0xA2,
+	0xD8, 0xF3, 0x10E, 0x00
+};
+
+/**
+ * The rates supported in B mode
+ */
+t_u8 SupportedRates_B[B_SUPPORTED_RATES] = {
+	0x02, 0x04, 0x0b, 0x16, 0x00
+};
+
+/**
+ * The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_G[G_SUPPORTED_RATES] = {
+	0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = {
+	0x02, 0x04, 0x0b, 0x0c, 0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
+	0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in N mode
+ */
+t_u8 SupportedRates_N[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
+
+/********************************************************
+			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)) {
+		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)) {
+		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();
+
+	/* first clear dest dynamic blacklisted entries */
+	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();
+
+	/* Look for code in mapping table */
+	for (i = 0; i < NELEMENTS(country_code_mapping); i++) {
+		if (!memcmp(pmadapter, country_code_mapping[i].country_code,
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			*cfp_bg = country_code_mapping[i].cfp_code_bg;
+			*cfp_a = country_code_mapping[i].cfp_code_a;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	/* If still not found, look for code in EU country code table */
+	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+		if (!memcmp(pmadapter, eu_country_code_table[i],
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			*cfp_bg = EU_CFP_CODE_BG;
+			*cfp_a = EU_CFP_CODE_A;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function finds if given country code is in EU table
+ *
+ *  @param pmadapter        A pointer to mlan_adapter structure
+ *  @param country_code     Country string
+ *
+ *  @return                 MTRUE or MFALSE
+ */
+t_bool
+wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
+{
+
+	t_u8 i;
+
+	ENTER();
+
+	/* Look for code in EU country code table */
+	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+		if (!memcmp(pmadapter, eu_country_code_table[i],
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			LEAVE();
+			return MTRUE;
+		}
+	}
+
+	LEAVE();
+	return MFALSE;
+}
+
+#define BAND_MASK_5G        0x03
+#define ANTENNA_OFFSET      2
+/**
+ *   @brief This function adjust the antenna index
+ *
+ *   V16_FW_API: Bit0: ant A, Bit 1:ant B, Bit0 & Bit 1: A+B
+ *   8887: case1: 0 - 2.4G ant A,  1- 2.4G antB, 2-- 5G ant C
+ *   case2: 0 - 2.4G ant A,  1- 2.4G antB, 0x80- 5G antA, 0x81-5G ant B
+ *   @param priv 	 A pointer to mlan_private structure
+ *   @param prx_pd   A pointer to the RxPD structure
+ *
+ *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+t_u8
+wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd)
+{
+	t_u8 antenna = prx_pd->antenna;
+	t_u32 rx_channel = (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+	if (prx_pd->antenna == 0xff)
+		return 0;
+	if (priv->adapter->psdio_device->v16_fw_api &&
+	    (IS_STREAM_2X2(priv->adapter->feature_control))) {
+		if ((antenna & MBIT(0)) && (antenna & MBIT(1)))
+			antenna = 2;
+		else if (antenna & MBIT(1))
+			antenna = 1;
+		else if (antenna & MBIT(0))
+			antenna = 0;
+	}
+
+	if (IS_SD8887(priv->adapter->card_type) ||
+	    IS_SD8987(priv->adapter->card_type)) {
+		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;
+
+		}
+	}
+
+	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_u8
+wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info)
+{
+	t_u8 rate_index = 0;
+	t_u8 bw = 0;
+	t_u8 nss = 0;
+	t_bool sgi_enable = 0;
+
+#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);
+	}
+	return rate_index;
+}
+
+#ifdef STA_SUPPORT
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief convert ht_info to rate_info
+ *
+ *  @param ht_info      ht info
+ *
+ *  @return             rate info
+ */
+t_u8
+wlan_convert_v14_rate_ht_info(t_u8 ht_info)
+{
+	t_u8 rate_info = 0;
+	rate_info = ht_info & 0x01;
+	/* band */
+	rate_info |= (ht_info & MBIT(1)) << 1;
+	/* short GI */
+	rate_info |= (ht_info & MBIT(2)) << 2;
+	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
+ *
+ *  @return                 Data rate or 0
+ */
+t_u32
+wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 tx_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 bw = 0;
+	t_u8 gi = 0;
+	ENTER();
+
+	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_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_u8 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:
+			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:
+			case BAND_B:	/* Matching BAND_B/G */
+			case BAND_G:
+			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, "wlan_get_cfp_by_band_and_channel(): cannot find "
+		       "cfp by band %d & channel %d\n", 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:
+			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:
+			case BAND_B:
+			case BAND_G:
+			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,
+		       "wlan_find_cfp_by_band_and_freq(): cannot find cfp by "
+		       "band %d & freq %d\n", 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_u8 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:
+			PRINTM(MINFO, "Infra band=%d SupportedRates_G\n",
+			       config_bands);
+			k = wlan_copy_rates(rates, k, SupportedRates_G,
+					    sizeof(SupportedRates_G));
+			break;
+		case BAND_B | BAND_G:
+		case BAND_A | BAND_B | BAND_G:
+		case BAND_A | BAND_B:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC | BAND_GAC:
+		case BAND_B | BAND_G | BAND_GN:
+		case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+			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:
+			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:
+			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:
+		case BAND_G | BAND_GN:
+		case BAND_G | BAND_GN | BAND_GAC:
+			PRINTM(MINFO, "Band: Adhoc G only\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_G,
+					    sizeof(AdhocRates_G));
+			break;
+		case BAND_B | BAND_G:
+		case BAND_B | BAND_G | BAND_GN:
+		case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+			PRINTM(MINFO, "Band: Adhoc BG\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_BG,
+					    sizeof(AdhocRates_BG));
+			break;
+		case BAND_A:
+		case BAND_AN:
+		case BAND_A | BAND_AN:
+		case BAND_A | BAND_AN | BAND_AAC:
+			PRINTM(MINFO, "Band: Adhoc A\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_A,
+					    sizeof(AdhocRates_A));
+			break;
+		}
+	}
+
+	LEAVE();
+	return k;
+}
+
+#define COUNTRY_ID_US 0
+#define COUNTRY_ID_JP 1
+#define COUNTRY_ID_CN 2
+#define COUNTRY_ID_EU 3
+typedef struct _oper_bw_chan {
+	/*non-global operating class */
+	t_u8 oper_class;
+	/*global operating class */
+	t_u8 global_oper_class;
+	/*bandwidth 0-20M 1-40M 2-80M 3-160M */
+	t_u8 bandwidth;
+	/*channel list */
+	t_u8 channel_list[13];
+} oper_bw_chan;
+
+/** oper class table for US*/
+static oper_bw_chan oper_bw_chan_us[] = {
+    /** non-Global oper class, global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 124, 0, {149, 153, 157, 161}},
+	{4, 121, 0,
+	 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144}},
+	{5, 125, 0, {149, 153, 157, 161, 165}},
+	{12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
+	{22, 116, 1, {36, 44}},
+	{23, 119, 1, {52, 60}},
+	{24, 122, 1, {100, 108, 116, 124, 132, 140}},
+	{25, 126, 1, {149, 157}},
+	{26, 126, 1, {149, 157}},
+	{27, 117, 1, {40, 48}},
+	{28, 120, 1, {56, 64}},
+	{29, 123, 1, {104, 112, 120, 128, 136, 144}},
+	{30, 127, 1, {153, 161}},
+	{31, 127, 1, {153, 161}},
+	{32, 83, 1, {1, 2, 3, 4, 5, 6, 7}},
+	{33, 84, 1, {5, 6, 7, 8, 9, 10, 11}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for EU*/
+static oper_bw_chan oper_bw_chan_eu[] = {
+    /** non-global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{5, 116, 1, {36, 44}},
+	{6, 119, 1, {52, 60}},
+	{7, 122, 1, {100, 108, 116, 124, 132}},
+	{8, 117, 1, {40, 48}},
+	{9, 120, 1, {56, 64}},
+	{10, 123, 1, {104, 112, 120, 128, 136}},
+	{11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{17, 125, 0, {149, 153, 157, 161, 165, 169}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for Japan*/
+static oper_bw_chan oper_bw_chan_jp[] = {
+    /** non-Global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48}},
+	{30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{31, 82, 0, {14}},
+	{32, 118, 0, {52, 56, 60, 64}},
+	{33, 118, 0, {52, 56, 60, 64}},
+	{34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{36, 116, 1, {36, 44}},
+	{37, 119, 1, {52, 60}},
+	{38, 119, 1, {52, 60}},
+	{39, 122, 1, {100, 108, 116, 124, 132}},
+	{40, 122, 1, {100, 108, 116, 124, 132}},
+	{41, 117, 1, {40, 48}},
+	{42, 120, 1, {56, 64}},
+	{43, 120, 1, {56, 64}},
+	{44, 123, 1, {104, 112, 120, 128, 136}},
+	{45, 123, 1, {104, 112, 120, 128, 136}},
+	{56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for China*/
+static oper_bw_chan oper_bw_chan_cn[] = {
+    /** non-Global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 125, 0, {149, 153, 157, 161, 165}},
+	{4, 116, 1, {36, 44}},
+	{5, 119, 1, {52, 60}},
+	{6, 126, 1, {149, 157}},
+	{7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/**
+ *  @brief Get non-global operaing class table according to country
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param arraysize          A pointer to table size
+ *
+ *  @return                   A pointer to oper_bw_chan
+ */
+oper_bw_chan *
+wlan_get_nonglobal_operclass_table(mlan_private *pmpriv, int *arraysize)
+{
+	t_u8 country_code[][COUNTRY_CODE_LEN] = { "US", "JP", "CN" };
+	int country_id = 0;
+	oper_bw_chan *poper_bw_chan = MNULL;
+
+	ENTER();
+
+	for (country_id = 0; country_id < 3; country_id++)
+		if (!memcmp
+		    (pmpriv->adapter, pmpriv->adapter->country_code,
+		     country_code[country_id], COUNTRY_CODE_LEN - 1))
+			break;
+	if (country_id >= 3)
+		country_id = COUNTRY_ID_US;	/*Set default to US */
+	if (wlan_is_etsi_country
+	    (pmpriv->adapter, pmpriv->adapter->country_code))
+		country_id = COUNTRY_ID_EU;
+				    /** Country in EU */
+
+	switch (country_id) {
+	case COUNTRY_ID_US:
+		poper_bw_chan = oper_bw_chan_us;
+		*arraysize = sizeof(oper_bw_chan_us);
+		break;
+	case COUNTRY_ID_JP:
+		poper_bw_chan = oper_bw_chan_jp;
+		*arraysize = sizeof(oper_bw_chan_jp);
+		break;
+	case COUNTRY_ID_CN:
+		poper_bw_chan = oper_bw_chan_cn;
+		*arraysize = sizeof(oper_bw_chan_cn);
+		break;
+	case COUNTRY_ID_EU:
+		poper_bw_chan = oper_bw_chan_eu;
+		*arraysize = sizeof(oper_bw_chan_eu);
+		break;
+	default:
+		PRINTM(MERROR, "Country not support!\n");
+		break;
+	}
+
+	LEAVE();
+	return poper_bw_chan;
+}
+
+/**
+ *  @brief Check validation of given channel and oper class
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param channel            Channel number
+ *  @param oper_class         operating class
+ *
+ *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
+				t_u8 oper_class)
+{
+	int arraysize = 0, i = 0, channum = 0;
+	oper_bw_chan *poper_bw_chan = MNULL;
+	t_u8 center_freq_idx = 0;
+	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
+
+	ENTER();
+
+	for (i = 0; i < sizeof(center_freqs); i++) {
+		if (channel == center_freqs[i]) {
+			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	if (oper_class <= 0 || oper_class > 130) {
+		PRINTM(MERROR, "Invalid operating class!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (oper_class >= 128) {
+		center_freq_idx =
+			wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
+						 CHANNEL_BW_80MHZ);
+		channel = center_freq_idx;
+	}
+	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+	if (!poper_bw_chan) {
+		PRINTM(MCMND, "Operating class table do not find!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
+		if (poper_bw_chan[i].oper_class == oper_class ||
+		    poper_bw_chan[i].global_oper_class == oper_class) {
+			for (channum = 0;
+			     channum < sizeof(poper_bw_chan[i].channel_list);
+			     channum++) {
+				if (poper_bw_chan[i].channel_list[channum] &&
+				    poper_bw_chan[i].channel_list[channum] ==
+				    channel) {
+					LEAVE();
+					return MLAN_STATUS_SUCCESS;
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMND, "Operating class %d do not match channel %d!\n",
+	       oper_class, channel);
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Get current operating class from channel and bandwidth
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param channel            Channel number
+ *  @param bw                 Bandwidth
+ *  @param oper_class         A pointer to current operating class
+ *
+ *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel, t_u8 bw,
+			 t_u8 *oper_class)
+{
+	oper_bw_chan *poper_bw_chan = MNULL;
+	t_u8 center_freq_idx = 0;
+	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
+	int i = 0, arraysize = 0, channum = 0;
+
+	ENTER();
+
+	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+	if (!poper_bw_chan) {
+		PRINTM(MCMND, "Operating class table do not find!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	for (i = 0; i < sizeof(center_freqs); i++) {
+		if (channel == center_freqs[i]) {
+			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	if (bw == BW_80MHZ) {
+		center_freq_idx =
+			wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
+						 CHANNEL_BW_80MHZ);
+		channel = center_freq_idx;
+	}
+
+	for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
+		if (poper_bw_chan[i].bandwidth == bw) {
+			for (channum = 0;
+			     channum < sizeof(poper_bw_chan[i].channel_list);
+			     channum++) {
+				if (poper_bw_chan[i].channel_list[channum] &&
+				    poper_bw_chan[i].channel_list[channum] ==
+				    channel) {
+					*oper_class =
+						poper_bw_chan[i].oper_class;
+					return MLAN_STATUS_SUCCESS;
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMND, "Operating class not find!\n");
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Add Supported operating classes IE
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param pptlv_out          A pointer to TLV to fill in
+ *  @param curr_oper_class    Current operating class
+ *
+ *  @return                   Length
+ */
+int
+wlan_add_supported_oper_class_ie(IN mlan_private *pmpriv, OUT 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(pmpriv->adapter, &poper_class->oper_class, oper_class_us,
+		       sizeof(oper_class_us));
+	} else if (country_id == COUNTRY_ID_JP) {
+		poper_class->header.len = sizeof(oper_class_jp);
+		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_jp,
+		       sizeof(oper_class_jp));
+	} else if (country_id == COUNTRY_ID_CN) {
+		poper_class->header.len = sizeof(oper_class_cn);
+		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_cn,
+		       sizeof(oper_class_cn));
+	} else if (country_id == COUNTRY_ID_EU) {
+		poper_class->header.len = sizeof(oper_class_eu);
+		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_eu,
+		       sizeof(oper_class_eu));
+	}
+	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];
+
+	ENTER();
+
+	memcpy(pmadapter, region_chan_old, pmadapter->region_channel,
+	       sizeof(pmadapter->region_channel));
+	memset(pmadapter, pmadapter->region_channel, 0,
+	       sizeof(pmadapter->region_channel));
+
+	if (band & (BAND_B | BAND_G | BAND_GN)) {
+		cfp = wlan_get_region_cfp_table(pmadapter, region,
+						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)
+			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
+					      region_chan_old[j].pcfp,
+					      region_chan_old[j].num_cfp);
+		else
+			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
+		i++;
+	}
+	if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+		cfp = wlan_get_region_cfp_table(pmadapter, region, 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
+			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 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 & MARVELL_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	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(IN pmlan_adapter pmadapter, IN 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_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);
+
+	/* Get cfp table and its size corresponding to the region code */
+	cfp_bg = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
+					   BAND_G | BAND_B, &cfp_no_bg);
+	size += cfp_no_bg * sizeof(chan_freq_power_t);
+	cfp_a = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
+					  BAND_A, &cfp_no_a);
+	size += cfp_no_a * sizeof(chan_freq_power_t);
+	/* 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);
+	tmp = (t_u8 *)&size;
+	memcpy(pmadapter, req_buf, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, &pmadapter->region_code,
+	       sizeof(pmadapter->region_code));
+	len += sizeof(pmadapter->region_code);
+	memcpy(pmadapter, req_buf + len, &pmadapter->country_code,
+	       sizeof(pmadapter->country_code));
+	len += sizeof(pmadapter->country_code);
+	/* 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(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, cfp_bg, size);
+	len += size;
+	if (!cfp_a)
+		goto out;
+	size = cfp_no_a * sizeof(chan_freq_power_t);
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, cfp_a, size);
+	len += size;
+out:
+	if (pioctl_req)
+		pioctl_req->data_read_written = len;
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8897/mlan/mlan_cmdevt.c b/wlan_sd8897/mlan/mlan_cmdevt.c
new file mode 100644
index 0000000..a0080f7
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_cmdevt.c
@@ -0,0 +1,6546 @@
+/**
+ * @file mlan_cmdevt.c
+ *
+ *  @brief This file contains the handling of CMD/EVENT in MLAN
+ *
+ *  Copyright (C) 2009-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+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_11h.h"
+#include "mlan_sdio.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(IN mlan_private *pmpriv, IN cmd_ctrl_node *pcmd_node)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (pcmd_node == MNULL)
+		goto done;
+	pcmd_node->cmd_flag |= CMD_F_SCAN;
+
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &pmadapter->scan_pending_q,
+			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief Internal function used to flush the scan pending queue
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+void
+wlan_check_scan_queue(IN 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
+/**
+ *  @brief This function dump debug info
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param reason        Reason code
+ *
+ *  @return     N/A
+ */
+t_void
+wlan_dump_info(mlan_adapter *pmadapter, t_u8 reason)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	t_u8 i;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	t_u8 j;
+	t_u8 mp_aggr_pkt_limit = pmadapter->psdio_device->mp_aggr_pkt_limit;
+#endif
+	t_u16 cmd_id, cmd_act;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	PRINTM(MERROR, "------------Dump info-----------\n", reason);
+	switch (reason) {
+	case REASON_CODE_NO_CMD_NODE:
+		pmadapter->dbg.num_no_cmd_node++;
+		PRINTM(MERROR, "No Free command node\n");
+		break;
+	case REASON_CODE_CMD_TIMEOUT:
+		PRINTM(MERROR, "Commmand Timeout\n");
+		break;
+	case REASON_CODE_CMD_TO_CARD_FAILURE:
+		PRINTM(MERROR, "Command to card failure\n");
+		break;
+	default:
+		break;
+	}
+	if ((reason == REASON_CODE_NO_CMD_NODE) &&
+	    (pmadapter->dbg.num_no_cmd_node > 1)) {
+		if (pmadapter->dbg.num_no_cmd_node >= 5)
+			wlan_recv_event(wlan_get_priv
+					(pmadapter, MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+		LEAVE();
+		return;
+	}
+	wlan_dump_pending_commands(pmadapter);
+	if (reason != REASON_CODE_CMD_TIMEOUT) {
+		if (!pmadapter->curr_cmd) {
+			PRINTM(MERROR, "CurCmd Empty\n");
+		} else {
+			pcmd_node = pmadapter->curr_cmd;
+			cmd_id = pmadapter->dbg.last_cmd_id[pmadapter->dbg.
+							    last_cmd_index];
+			cmd_act =
+				pmadapter->dbg.last_cmd_act[pmadapter->dbg.
+							    last_cmd_index];
+			PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
+			PRINTM(MERROR,
+			       "Current cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n",
+			       sec, usec, cmd_id, cmd_act);
+			if (pcmd_node->cmdbuf) {
+				t_u8 *pcmd_buf;
+				pcmd_buf =
+					pcmd_node->cmdbuf->pbuf +
+					pcmd_node->cmdbuf->data_offset +
+					INTF_HEADER_LEN;
+				for (i = 0; i < 16; i++)
+					PRINTM(MERROR, "%02x ", *pcmd_buf++);
+				PRINTM(MERROR, "\n");
+			}
+			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, "dbg.num_cmd_timeout = %d\n",
+	       pmadapter->dbg.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);
+	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);
+	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, "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\n",
+	       pmadapter->pm_wakeup_card_req, pmadapter->pm_wakeup_fw_try);
+	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, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
+	       pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port);
+	PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
+	       pmadapter->mp_wr_bitmap, pmadapter->curr_wr_port);
+	PRINTM(MERROR, "mp_invalid_update=%d\n", pmadapter->mp_invalid_update);
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n",
+	       pmadapter->last_recv_wr_bitmap, pmadapter->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->last_mp_wr_bitmap[i],
+		       pmadapter->last_mp_wr_ports[i],
+		       pmadapter->last_mp_wr_len[i],
+		       pmadapter->last_curr_wr_port[i]);
+		for (j = 0; j < mp_aggr_pkt_limit; j++) {
+			PRINTM(MERROR, "0x%02x ",
+			       pmadapter->last_mp_wr_info[i *
+							  mp_aggr_pkt_limit +
+							  j]);
+		}
+		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)
+			) {
+			if (pmpriv)
+				wlan_recv_event(pmpriv,
+						MLAN_EVENT_ID_DRV_DBG_DUMP,
+						MNULL);
+			else
+				wlan_recv_event(wlan_get_priv
+						(pmadapter, MLAN_BSS_ROLE_ANY),
+						MLAN_EVENT_ID_DRV_DBG_DUMP,
+						MNULL);
+		}
+	}
+	PRINTM(MERROR, "-------- Dump info End---------\n", reason);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function convert a given character to hex
+ *
+ *  @param chr        Character to be converted
+ *
+ *  @return           The converted hex if chr is a valid hex, else 0
+ */
+static t_u32
+wlan_hexval(t_u8 chr)
+{
+	if (chr >= '0' && chr <= '9')
+		return chr - '0';
+	if (chr >= 'A' && chr <= 'F')
+		return chr - 'A' + 10;
+	if (chr >= 'a' && chr <= 'f')
+		return chr - 'a' + 10;
+
+	return 0;
+}
+
+/**
+ *  @brief This function convert a given string to hex
+ *
+ *  @param a            A pointer to string to be converted
+ *
+ *  @return             The converted hex value if param a is a valid hex, else 0
+ */
+int
+wlan_atox(t_u8 *a)
+{
+	int i = 0;
+
+	ENTER();
+
+	while (wlan_isxdigit(*a))
+		i = i * 16 + wlan_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief This function parse cal data from ASCII to hex
+ *
+ *  @param src          A pointer to source data
+ *  @param len          Source data length
+ *  @param dst          A pointer to a buf to store the parsed data
+ *
+ *  @return             The parsed hex data length
+ */
+static t_u32
+wlan_parse_cal_cfg(t_u8 *src, t_size len, t_u8 *dst)
+{
+	t_u8 *ptr;
+	t_u8 *dptr;
+
+	ENTER();
+	ptr = src;
+	dptr = dst;
+
+	while (ptr - src < len) {
+		if (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) {
+			ptr++;
+			continue;
+		}
+
+		if (wlan_isxdigit(*ptr)) {
+			*dptr++ = wlan_atox(ptr);
+			ptr += 2;
+		} else {
+			ptr++;
+		}
+	}
+	LEAVE();
+	return dptr - dst;
+}
+
+/**
+ *  @brief This function finds first occurrence of a char in a string
+ *
+ *  @param s            A pointer to the string to be searched
+ *  @param c            The character to search for
+ *
+ *  @return             Location of the first occurrence of the char
+ *                      if found, else NULL
+ */
+t_u8 *
+wlan_strchr(t_u8 *s, int c)
+{
+	t_u8 *pos = s;
+	while (*pos != '\0') {
+		if (*pos == (t_u8)c)
+			return pos;
+		pos++;
+	}
+	return MNULL;
+}
+
+#define CFG_TYPE_HOSTCMD        0
+#define CFG_TYPE_DPDFILE          1
+
+/**
+ *    @brief WOAL parse ASCII format raw data to hex format
+ *
+ *    @param pmpriv       MOAL handle
+ *    @param cfg_type     Conf file type
+ *    @param data         Source data
+ *    @param size         data length
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+wlan_process_hostcmd_cfg(IN pmlan_private pmpriv, IN t_u16 cfg_type,
+			 IN t_u8 *data, IN 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 = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+	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, MLAN_SIZE_OF_CMD_BUFFER);
+			ptr = buf;
+			start_raw = MFALSE;
+			pos++;
+			continue;
+		}
+
+		if (start_raw == MFALSE) {
+			intf_s = wlan_strchr(pos, '=');
+			if (intf_s)
+				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) {
+					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_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             N/A
+ */
+static void
+wlan_init_cmd_node(IN pmlan_private pmpriv,
+		   IN cmd_ctrl_node *pcmd_node,
+		   IN t_u32 cmd_oid,
+		   IN t_void *pioctl_buf, IN t_void *pdata_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (pcmd_node == MNULL) {
+		LEAVE();
+		return;
+	}
+	pcmd_node->priv = pmpriv;
+	pcmd_node->cmd_oid = cmd_oid;
+	pcmd_node->pioctl_buf = pioctl_buf;
+	pcmd_node->pdata_buf = pdata_buf;
+
+	pcmd_node->cmdbuf = pcmd_node->pmbuf;
+
+	/* 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;
+	pcmd_node->cmdbuf->data_offset += INTF_HEADER_LEN;
+
+	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_oid = 0;
+	pcmd_node->cmd_flag = 0;
+	pcmd_node->pioctl_buf = MNULL;
+	pcmd_node->pdata_buf = MNULL;
+
+	if (pcmd_node->respbuf) {
+		wlan_free_mlan_buffer(pmadapter, pcmd_node->respbuf);
+		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(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *resp, IN 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(pmpriv->adapter, misc->param.hostcmd.cmd, (void *)resp,
+		       size);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function sends host command to firmware.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_host_cmd(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_cmd *pcmd_ptr = (mlan_ds_misc_cmd *)pdata_buf;
+
+	ENTER();
+
+	/* Copy the HOST command to command buffer */
+	memcpy(pmpriv->adapter, (void *)cmd, pcmd_ptr->cmd,
+	       MIN(MRVDRV_SIZE_OF_CMD_BUFFER, pcmd_ptr->len));
+	PRINTM(MINFO, "Host command size = %d\n", pcmd_ptr->len);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN mlan_private *pmpriv, IN 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 DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+
+	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);
+	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);
+
+	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\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));
+	DBG_HEXDUMP(MCMD_D, "DNLD_CMD", (t_u8 *)pcmd, cmd_size);
+
+	/* Send the command to lower layer */
+
+	pcmd_node->cmdbuf->data_offset -= INTF_HEADER_LEN;
+	pcmd_node->cmdbuf->data_len += INTF_HEADER_LEN;
+	/* Extra header for SDIO is added here */
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_CMD,
+				     pcmd_node->cmdbuf, MNULL);
+
+	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,
+			      MRVDRV_TIMER_10S * 2);
+
+	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;
+	t_u16 cmd_len = 0;
+	opt_sleep_confirm_buffer *sleep_cfm_buf =
+		(opt_sleep_confirm_buffer *)(pmadapter->psleep_cfm->pbuf +
+					     pmadapter->psleep_cfm->
+					     data_offset);
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	if (!pmpriv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	cmd_len = sizeof(OPT_Confirm_Sleep);
+	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 */
+
+	pmadapter->psleep_cfm->data_len = cmd_len + INTF_HEADER_LEN;
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_CMD,
+				     pmadapter->psleep_cfm, MNULL);
+
+	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 */
+
+#define NUM_SC_PER_LINE         16
+		if (++i % NUM_SC_PER_LINE == 0)
+			PRINTM(MEVENT, "+\n");
+		else
+			PRINTM(MEVENT, "+");
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Event handler
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param event_id Event ID
+ *  @param pmevent  Event buffer
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_recv_event(pmlan_private priv, mlan_event_id event_id, t_void *pmevent)
+{
+	pmlan_callbacks pcb = MNULL;
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pcb = &priv->adapter->callbacks;
+
+	if (pmevent)
+		/* The caller has provided the event. */
+		pcb->moal_recv_event(priv->adapter->pmoal_handle,
+				     (pmlan_event)pmevent);
+	else {
+		mlan_event mevent;
+
+		memset(priv->adapter, &mevent, 0, sizeof(mlan_event));
+		mevent.bss_index = priv->bss_index;
+		mevent.event_id = event_id;
+		mevent.event_len = 0;
+
+		pcb->moal_recv_event(priv->adapter->pmoal_handle, &mevent);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function allocates the command buffer and links
+ *          it to command free queue.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_alloc_cmd_buffer(IN 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);
+
+	/* 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;
+		}
+	}
+	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(IN 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++) {
+		if (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;
+		}
+		if (pcmd_array[i].respbuf) {
+			wlan_free_mlan_buffer(pmadapter, pcmd_array[i].respbuf);
+			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(pmadapter, (t_u8 *)&eventcause,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       sizeof(eventcause));
+		} else {
+			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(pmadapter,
+		       pmbuf->pbuf + pmbuf->data_offset,
+		       (t_u8 *)&eventcause, sizeof(eventcause));
+	}
+
+	if (MTRUE
+	    && (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE)
+		) {
+		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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	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(IN 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(IN 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(IN mlan_private *pmpriv,
+		 IN t_u16 cmd_no,
+		 IN t_u16 cmd_action,
+		 IN t_u32 cmd_oid, IN t_void *pioctl_buf, IN 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)
+			) {
+			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_oid, pioctl_buf, pdata_buf);
+
+	if (pcmd_node->cmdbuf == MNULL) {
+		PRINTM(MERROR, "PREP_CMD: No free cmd buf\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_ptr =
+		(HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+				       pcmd_node->cmdbuf->data_offset);
+	cmd_ptr->command = cmd_no;
+	cmd_ptr->result = 0;
+
+	/* Prepare command */
+	if (cmd_no)
+		ret = pmpriv->ops.prepare_cmd(pmpriv, cmd_no, cmd_action,
+					      cmd_oid, pioctl_buf, pdata_buf,
+					      cmd_ptr);
+	else {
+		ret = wlan_cmd_host_cmd(pmpriv, cmd_ptr, pdata_buf);
+		pcmd_node->cmd_flag |= CMD_F_HOSTCMD;
+	}
+
+	/* Return error, since the command preparation failed */
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "PREP_CMD: Command 0x%x preparation failed\n",
+		       cmd_no);
+		pcmd_node->pioctl_buf = MNULL;
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+		wlan_request_cmd_lock(pmadapter);
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+		wlan_release_cmd_lock(pmadapter);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	/* Send command */
+#ifdef STA_SUPPORT
+	if (cmd_no == HostCmd_CMD_802_11_SCAN
+	    || cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
+		wlan_queue_scan_cmd(pmpriv, pcmd_node);
+	} else {
+#endif
+		if ((cmd_no == HostCmd_CMD_802_11_HS_CFG_ENH) &&
+		    (cmd_action == HostCmd_ACT_GEN_SET) &&
+		    (pmadapter->hs_cfg.conditions == HOST_SLEEP_CFG_CANCEL))
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MFALSE);
+		else
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MTRUE);
+#ifdef STA_SUPPORT
+	}
+#endif
+	wlan_release_cmd_lock(pmadapter);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function inserts command node to cmd_free_q
+ *              after cleaning it.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_insert_cmd_to_free_q(IN mlan_adapter *pmadapter,
+			  IN 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(IN mlan_adapter *pmadapter,
+			     IN cmd_ctrl_node *pcmd_node, IN 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();
+
+	/* 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;
+	}
+
+	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;
+	}
+
+	pmadapter->num_cmd_timeout = 0;
+
+	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);
+	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);
+	}
+	orig_cmdresp_no = wlan_le16_to_cpu(resp->command);
+	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) {
+#if defined(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;
+		}
+	}
+
+	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) {
+
+#if defined(STA_SUPPORT)
+			if (pmadapter->pwarm_reset_ioctl_req) {
+				/* warm reset complete */
+				pmadapter->hw_status = WlanHardwareStatusReady;
+				pcb->moal_ioctl_complete(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 pwarm_reset_ioctl_req,
+							 MLAN_STATUS_SUCCESS);
+				pmadapter->pwarm_reset_ioctl_req = MNULL;
+				goto done;
+			}
+#endif
+			pmadapter->hw_status = WlanHardwareStatusInitdone;
+		} else {
+			/* Issue init commands for the next interface */
+			ret = pmpriv_next->ops.init_cmd(pmpriv_next, MFALSE);
+		}
+	} else if ((pmadapter->hw_status == WlanHardwareStatusGetHwSpec) &&
+		   (HostCmd_CMD_GET_HW_SPEC == cmdresp_no)) {
+		pmadapter->hw_status = WlanHardwareStatusGetHwSpecdone;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the timeout of command sending.
+ *          It will re-send the same command again.
+ *
+ *  @param function_context   A pointer to function_context
+ *  @return                   N/A
+ */
+t_void
+wlan_cmd_timeout_func(t_void *function_context)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)function_context;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	t_u8 i;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	pmadapter->cmd_timer_is_set = MFALSE;
+	if (!pmadapter->curr_cmd) {
+		PRINTM(MWARN, "CurCmd Empty\n");
+		goto exit;
+	}
+	pmadapter->num_cmd_timeout++;
+	pmadapter->dbg.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 (pcmd_node->cmdbuf) {
+		t_u8 *pcmd_buf;
+		pcmd_buf =
+			pcmd_node->cmdbuf->pbuf +
+			pcmd_node->cmdbuf->data_offset + INTF_HEADER_LEN;
+		for (i = 0; i < 16; i++)
+			PRINTM(MERROR, "%02x ", *pcmd_buf++);
+		PRINTM(MERROR, "\n");
+	}
+
+	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(IN pmlan_adapter pmadapter)
+{
+
+	cmd_ctrl_node *pcmd_node = MNULL;
+
+	ENTER();
+
+	wlan_request_cmd_lock(pmadapter);
+	while ((pcmd_node =
+		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						&pmadapter->scan_pending_q,
+						MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->scan_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		pcmd_node->pioctl_buf = MNULL;
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+
+	pmadapter->scan_processing = MFALSE;
+	wlan_release_cmd_lock(pmadapter);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Cancel pending SCAN ioctl cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param pioctl_req   A pointer to pmlan_ioctl_req
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	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;
+		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);
+	/* 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
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	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;
+		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;
+		pmadapter->curr_cmd = 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);
+	}
+
+	/* Cancel all pending command */
+	while ((pcmd_node =
+		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						&pmadapter->cmd_pending_q,
+						MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		if (pcmd_node->pioctl_buf) {
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+			pcmd_node->pioctl_buf = MNULL;
+		}
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+	wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	/* Cancel all pending scan command */
+	wlan_flush_scan_queue(pmadapter);
+#endif
+	LEAVE();
+}
+
+/**
+ *  @brief Cancel specific bss's pending ioctl cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param bss_index    BSS index
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+	t_u8 flash_scan = MFALSE;
+#endif
+	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;
+		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) {
+		/* 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;
+
+	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) {
+		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) {
+		/* 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(IN pmlan_private pmpriv,
+			IN mlan_wifi_rate * pmlan_rate, OUT 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) * 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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(pmpriv->adapter, info->param.ver_ext.version_str,
+		       ver_ext->version_str, sizeof(char) * 128);
+	}
+	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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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 && !IS_CARD_RX_RCVD(pmadapter)) {
+		wlan_dnld_sleep_confirm_cmd(pmadapter);
+	} else {
+		PRINTM(MCMND, "Delay Sleep Confirm (%s%s%s)\n",
+		       (pmadapter->cmd_sent) ? "D" : "",
+		       (pmadapter->curr_cmd) ? "C" : "",
+		       (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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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();
+
+	if (wlan_le16_to_cpu(phs_cfg->action) == HS_ACTIVATE) {
+		/* 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);
+		wlan_host_sleep_activated_event(pmpriv, MTRUE);
+		goto done;
+	} else {
+		phs_cfg->params.hs_config.conditions =
+			wlan_le32_to_cpu(phs_cfg->params.hs_config.conditions);
+		PRINTM(MCMND,
+		       "CMD_RESP: HS_CFG cmd reply result=%#x,"
+		       " conditions=0x%x gpio=0x%x gap=0x%x\n", resp->result,
+		       phs_cfg->params.hs_config.conditions,
+		       phs_cfg->params.hs_config.gpio,
+		       phs_cfg->params.hs_config.gap);
+	}
+	if (phs_cfg->params.hs_config.conditions != HOST_SLEEP_CFG_CANCEL) {
+		pmadapter->is_hs_configured = 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)
+		wlan_pm_wakeup_card(pmadapter);
+	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;
+
+	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);
+
+	/* 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 (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(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,
+			IN HostCmd_DS_COMMAND *cmd,
+			IN t_u16 cmd_action,
+			IN t_u16 ps_bitmap, IN 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->adhoc_wake_period =
+				wlan_cpu_to_le16(pmadapter->adhoc_awake_period);
+			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(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *resp,
+			IN 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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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->psdio_device->v15_fw_api)
+		pmpriv->tx_rate_info =
+			wlan_convert_v14_rate_ht_info(pmpriv->tx_rate_info);
+
+	if (!pmpriv->is_data_rate_auto) {
+		pmpriv->data_rate = wlan_index_to_data_rate(pmadapter,
+							    pmpriv->tx_rate,
+							    pmpriv->
+							    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)
+					/* 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);
+			}
+		} else if (rate->sub_command == MLAN_OID_GET_DATA_RATE) {
+			/* Tx rate info */
+			if ((pmpriv->tx_rate_info & 0x3) ==
+			    MLAN_RATE_FORMAT_VHT) {
+				/* VHT rate */
+				rate->param.data_rate.tx_rate_format =
+					MLAN_RATE_FORMAT_VHT;
+				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_nss =
+					(pmpriv->tx_rate) >> 4;
+				rate->param.data_rate.tx_mcs_index =
+					(pmpriv->tx_rate) & 0xF;
+				rate->param.data_rate.tx_data_rate =
+					wlan_index_to_data_rate(pmadapter,
+								pmpriv->tx_rate,
+								pmpriv->
+								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);
+			} 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) {
+				/* VHT rate */
+				rate->param.data_rate.rx_rate_format =
+					MLAN_RATE_FORMAT_VHT;
+				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_nss =
+					(pmpriv->rxpd_rate) >> 4;
+				rate->param.data_rate.rx_mcs_index =
+					(pmpriv->rxpd_rate) & 0xF;
+				rate->param.data_rate.rx_data_rate =
+					wlan_index_to_data_rate(pmadapter,
+								pmpriv->
+								rxpd_rate,
+								pmpriv->
+								rxpd_rate_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);
+			} 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 fw_wakeup_method.
+ *
+ * @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_fw_wakeup_method(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *cmd,
+				 IN t_u16 cmd_action, IN t_u16 *pdata_buf)
+{
+	HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &cmd->params.fwwakeupmethod;
+	mlan_fw_wakeup_params *fw_wakeup_params = MNULL;
+	MrvlIEtypes_WakeupSourceGPIO_t *tlv =
+		(MrvlIEtypes_WakeupSourceGPIO_t *) ((t_u8 *)fwwm +
+						    sizeof
+						    (HostCmd_DS_802_11_FW_WAKEUP_METHOD));
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_FW_WAKE_METHOD);
+	cmd->size = sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) + S_DS_GEN;
+	fwwm->action = wlan_cpu_to_le16(cmd_action);
+	switch (cmd_action) {
+	case HostCmd_ACT_GEN_SET:
+		fw_wakeup_params = (mlan_fw_wakeup_params *) pdata_buf;
+		fwwm->method = wlan_cpu_to_le16(fw_wakeup_params->method);
+
+		if (fw_wakeup_params->method == WAKEUP_FW_THRU_GPIO) {
+			cmd->size += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
+			tlv->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_HS_WAKEUP_SOURCE_GPIO);
+			tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_WakeupSourceGPIO_t)
+						 - sizeof(MrvlIEtypesHeader_t));
+			tlv->ind_gpio = (t_u8)fw_wakeup_params->gpio_pin;
+		}
+
+		break;
+	case HostCmd_ACT_GEN_GET:
+	default:
+		fwwm->method = wlan_cpu_to_le16(WAKEUP_FW_UNCHANGED);
+		break;
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of fw_wakeup_method
+ *
+ *  @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_fw_wakeup_method(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &resp->params.fwwakeupmethod;
+	t_u16 action;
+	MrvlIEtypes_WakeupSourceGPIO_t *gpio_tlv =
+		(MrvlIEtypes_WakeupSourceGPIO_t *) ((t_u8 *)fwwm +
+						    sizeof
+						    (HostCmd_DS_802_11_FW_WAKEUP_METHOD));
+	mlan_ds_pm_cfg *pmcfg = MNULL;
+
+	ENTER();
+
+	action = wlan_le16_to_cpu(fwwm->action);
+
+	pmpriv->adapter->fw_wakeup_method = wlan_le16_to_cpu(fwwm->method);
+	pmpriv->adapter->fw_wakeup_gpio_pin = 0;
+
+	if ((resp->size -
+	     (sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) + S_DS_GEN))
+	    == sizeof(MrvlIEtypes_WakeupSourceGPIO_t)) {
+		pmpriv->adapter->fw_wakeup_gpio_pin = gpio_tlv->ind_gpio;
+	}
+	PRINTM(MCMND, "FW wakeup method=%d, gpio=%d\n",
+	       pmpriv->adapter->fw_wakeup_method,
+	       pmpriv->adapter->fw_wakeup_gpio_pin);
+
+	if (pioctl_buf) {
+		pmcfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+		pmcfg->param.fw_wakeup_params.method =
+			pmpriv->adapter->fw_wakeup_method;
+		pmcfg->param.fw_wakeup_params.gpio_pin =
+			pmpriv->adapter->fw_wakeup_gpio_pin;
+	}
+	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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN 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 *) ((t_u8 *)rbstcx +
+							sizeof
+							(HostCmd_DS_802_11_ROBUSTCOEX));
+
+	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;
+}
+
+/**
+ *  @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
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN t_void *pdata_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;
+	t_u16 *pbitmap_rates = (t_u16 *)pdata_buf;
+
+	t_u32 i;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
+
+	rate_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	rate_scope = (MrvlRateScope_t *)((t_u8 *)rate_cfg +
+					 sizeof(HostCmd_DS_TX_RATE_CFG));
+	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]);
+	} 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]);
+	}
+
+	rate_drop = (MrvlRateDropPattern_t *)((t_u8 *)rate_scope +
+					      sizeof(MrvlRateScope_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) +
+				     sizeof(MrvlRateScope_t) +
+				     sizeof(MrvlRateDropPattern_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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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;
+
+	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 *)((t_u8 *)prate_cfg) + sizeof(HostCmd_DS_TX_RATE_CFG);
+	if (tlv_buf) {
+		tlv_buf_len = *(t_u16 *)(tlv_buf + sizeof(t_u16));
+		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]);
+			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;
+	}
+
+	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;
+			}
+			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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	/*
+	 * This should be issued in the very first to config
+	 *   SDIO_GPIO interrupt mode.
+	 */
+	if (wlan_set_sdio_gpio_int(priv) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	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;
+	}
+    /** 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 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(IN 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
+
+	/* Get fw wakeup method */
+	if (pmpriv) {
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_802_11_FW_WAKE_METHOD,
+				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Reconfigure tx buf size */
+	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
+
+#if defined(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;
+		}
+	}
+	if (pmadapter->init_para.drcs_chantime_mode) {
+		mlan_ds_drcs_cfg drcs_init_cfg[2];
+		drcs_init_cfg[0].chan_idx = 0x1;
+		drcs_init_cfg[0].chantime =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 8);
+		/* switchtime use default value in fw */
+		drcs_init_cfg[0].switchtime = 10;
+		drcs_init_cfg[0].undozetime = 5;
+		drcs_init_cfg[0].mode =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode);
+		drcs_init_cfg[1].chan_idx = 0x2;
+		drcs_init_cfg[1].chantime =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 24);
+		/* switchtime use default value in fw */
+		drcs_init_cfg[1].switchtime = 10;
+		drcs_init_cfg[1].undozetime = 5;
+		drcs_init_cfg[1].mode =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 16);
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DRCS_CONFIG,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       (t_void *)drcs_init_cfg);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef RX_PACKET_COALESCE
+/**
+ *  @brief This function prepares command of rx_pkt_coalesce_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_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			     const IN HostCmd_DS_COMMAND *resp,
+			     OUT 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 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_handle_event_multi_chan_info(IN pmlan_private pmpriv, pmlan_buffer pevent)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	t_u32 interfaces = 0;
+	MrvlIEtypes_multi_chan_info_t *pmulti_chan_info = MNULL;
+	MrvlIEtypes_multi_chan_group_info_t *pmulti_chan_grp_info = MNULL;
+	int tlv_buf_left = pevent->data_len - sizeof(mlan_event_id);
+	t_u16 tlv_type, tlv_len;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private intf_priv = MNULL;
+	int num_intf = 0, bss_type = 0, bss_num = 0;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+
+	ENTER();
+
+	PRINTM(MEVENT, "multi channel event\n");
+	pmulti_chan_info =
+		(MrvlIEtypes_multi_chan_info_t *)(pevent->pbuf +
+						  pevent->data_offset +
+						  sizeof(mlan_event_id));
+	if (tlv_buf_left < sizeof(MrvlIEtypes_multi_chan_info_t) ||
+	    wlan_le16_to_cpu(pmulti_chan_info->header.type) !=
+	    TLV_TYPE_MULTI_CHAN_INFO) {
+		PRINTM(MERROR, "Invalid multi channel event\n");
+		goto done;
+	}
+
+	pmadapter->mc_status = wlan_le16_to_cpu(pmulti_chan_info->status);
+	PRINTM(MEVENT, "mc_status=%d\n", pmadapter->mc_status);
+	tlv_buf_left -= sizeof(MrvlIEtypes_multi_chan_info_t);
+	tlv = (MrvlIEtypesHeader_t *)pmulti_chan_info->tlv_buffer;
+
+	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_MULTI_CHAN_GROUP_INFO_TLV_ID) {
+			PRINTM(MERROR, "wrong tlv type:0x%x\n", tlv_type);
+			break;
+		}
+		pmulti_chan_grp_info =
+			(MrvlIEtypes_multi_chan_group_info_t *)tlv;
+		PRINTM(MEVENT, "mc_info: groupid=%d chan=%d, numintf=%d\n",
+		       pmulti_chan_grp_info->chan_group_id,
+		       pmulti_chan_grp_info->chan_band_info.chan_num,
+		       pmulti_chan_grp_info->num_intf);
+		num_intf = pmulti_chan_grp_info->num_intf;
+		for (interfaces = 0; interfaces < num_intf; interfaces++) {
+			bss_type =
+				pmulti_chan_grp_info->
+				bss_type_numlist[interfaces] >> 4;
+			bss_num =
+				pmulti_chan_grp_info->
+				bss_type_numlist[interfaces] & BSS_NUM_MASK;
+			PRINTM(MEVENT, "intf%d: bss_type=%d bss_num=%d\n",
+			       interfaces, bss_type, bss_num);
+			intf_priv =
+				wlan_get_priv_by_id(pmadapter, bss_num,
+						    bss_type);
+			if (intf_priv) {
+			} else {
+				PRINTM(MERROR,
+				       "Invalid bss_type, bss_num in multi_channel event\n");
+			}
+		}
+
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares the command MULTI_CHAN_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          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_multi_chan_cfg(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *cmd,
+			IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_multi_chan_cfg *multi_chan_cfg =
+		(mlan_ds_multi_chan_cfg *)pdata_buf;
+	HostCmd_DS_MULTI_CHAN_CFG *pmchan_cfg =
+		(HostCmd_DS_MULTI_CHAN_CFG *)&cmd->params.multi_chan_cfg;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_CONFIG);
+	pmchan_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		pmchan_cfg->buffer_weight = multi_chan_cfg->buffer_weight;
+		pmchan_cfg->channel_time =
+			wlan_cpu_to_le32(multi_chan_cfg->channel_time);
+		PRINTM(MCMND,
+		       "Set multi-channel: buffer_weight=%d channel_time=%d\n",
+		       multi_chan_cfg->buffer_weight,
+		       multi_chan_cfg->channel_time);
+		cmd->size =
+			wlan_cpu_to_le16(S_DS_GEN +
+					 sizeof(HostCmd_DS_MULTI_CHAN_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 MULTI_CHAN_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_multi_chan_cfg(IN pmlan_private pmpriv,
+			const IN HostCmd_DS_COMMAND *resp,
+			OUT mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_MULTI_CHAN_CFG *presp_cfg =
+		&resp->params.multi_chan_cfg;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		pcfg->param.multi_chan_cfg.channel_time =
+			wlan_le32_to_cpu(presp_cfg->channel_time);
+		pcfg->param.multi_chan_cfg.buffer_weight =
+			presp_cfg->buffer_weight;
+		pcfg->param.multi_chan_cfg.tlv_len =
+			resp->size - (sizeof(HostCmd_DS_GEN) +
+				      sizeof(HostCmd_DS_MULTI_CHAN_CFG));
+		PRINTM(MCMND,
+		       "Get multi-channel: buffer_weight=%d channel_time=%d tlv_len=%d\n",
+		       pcfg->param.multi_chan_cfg.buffer_weight,
+		       pcfg->param.multi_chan_cfg.channel_time,
+		       pcfg->param.multi_chan_cfg.tlv_len);
+		memcpy(pmpriv->adapter, pcfg->param.multi_chan_cfg.tlv_buf,
+		       presp_cfg->tlv_buf, pcfg->param.multi_chan_cfg.tlv_len);
+		pioctl_buf->buf_len =
+			sizeof(mlan_ds_multi_chan_cfg) +
+			pcfg->param.multi_chan_cfg.tlv_len;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command MULTI_CHAN_POLICY
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          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_multi_chan_policy(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	t_u16 policy = 0;
+	HostCmd_DS_MULTI_CHAN_POLICY *pmulti_chan_policy =
+		(HostCmd_DS_MULTI_CHAN_POLICY *)&cmd->params.multi_chan_policy;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_POLICY);
+	pmulti_chan_policy->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size =
+		wlan_cpu_to_le16(S_DS_GEN +
+				 sizeof(HostCmd_DS_MULTI_CHAN_POLICY));
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		policy = *((t_u16 *)pdata_buf);
+		pmulti_chan_policy->policy = wlan_cpu_to_le16(policy);
+		PRINTM(MCMND, "Set multi-channel policy: %d\n", policy);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of MULTI_CHAN_POLICY
+ *
+ *  @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_multi_chan_policy(IN pmlan_private pmpriv,
+			   const IN HostCmd_DS_COMMAND *resp,
+			   OUT mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_MULTI_CHAN_POLICY *presp_cfg =
+		&resp->params.multi_chan_policy;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		pcfg->param.multi_chan_policy =
+			wlan_le16_to_cpu(presp_cfg->policy);
+
+		if (pioctl_buf->action == HostCmd_ACT_GEN_SET) {
+			if (pcfg->param.multi_chan_policy)
+				pmpriv->adapter->mc_policy = MTRUE;
+			else
+				pmpriv->adapter->mc_policy = MFALSE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command DRCD_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          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_drcs_cfg(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *cmd,
+		  IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_drcs_cfg *drcs_cfg = (mlan_ds_drcs_cfg *) pdata_buf;
+	HostCmd_DS_DRCS_CFG *pdrcs_cfg =
+		(HostCmd_DS_DRCS_CFG *) & cmd->params.drcs_cfg;
+	MrvlTypes_DrcsTimeSlice_t *channel_time_slicing =
+		&pdrcs_cfg->time_slicing;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DRCS_CONFIG);
+	pdrcs_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		channel_time_slicing->header.type =
+			wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
+		channel_time_slicing->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlTypes_DrcsTimeSlice_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		channel_time_slicing->chan_idx =
+			wlan_cpu_to_le16(drcs_cfg->chan_idx);
+		channel_time_slicing->chantime = drcs_cfg->chantime;
+		channel_time_slicing->switchtime = drcs_cfg->switchtime;
+		channel_time_slicing->undozetime = drcs_cfg->undozetime;
+		channel_time_slicing->mode = drcs_cfg->mode;
+		PRINTM(MCMND,
+		       "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+		       channel_time_slicing->chan_idx,
+		       channel_time_slicing->chantime,
+		       channel_time_slicing->switchtime,
+		       channel_time_slicing->undozetime,
+		       channel_time_slicing->mode);
+		cmd->size =
+			wlan_cpu_to_le16(S_DS_GEN +
+					 sizeof(HostCmd_DS_DRCS_CFG));
+		/* Set two channels different parameters */
+		if (0x3 != channel_time_slicing->chan_idx) {
+			drcs_cfg++;
+			channel_time_slicing = pdrcs_cfg->drcs_buf;
+			channel_time_slicing->header.type =
+				wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
+			channel_time_slicing->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlTypes_DrcsTimeSlice_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			channel_time_slicing->chan_idx =
+				wlan_cpu_to_le16(drcs_cfg->chan_idx);
+			channel_time_slicing->chantime = drcs_cfg->chantime;
+			channel_time_slicing->switchtime = drcs_cfg->switchtime;
+			channel_time_slicing->undozetime = drcs_cfg->undozetime;
+			channel_time_slicing->mode = drcs_cfg->mode;
+			PRINTM(MCMND,
+			       "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+			       channel_time_slicing->chan_idx,
+			       channel_time_slicing->chantime,
+			       channel_time_slicing->switchtime,
+			       channel_time_slicing->undozetime,
+			       channel_time_slicing->mode);
+			cmd->size +=
+				wlan_cpu_to_le16(sizeof
+						 (MrvlTypes_DrcsTimeSlice_t));
+		}
+	} 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 DRCS_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_drcs_cfg(IN pmlan_private pmpriv,
+		  const IN HostCmd_DS_COMMAND *resp,
+		  OUT mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_DRCS_CFG *presp_cfg = &resp->params.drcs_cfg;
+	const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing =
+		&presp_cfg->time_slicing;
+	const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing1 = MNULL;
+	mlan_ds_drcs_cfg *drcs_cfg1 = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		if (wlan_le16_to_cpu(channel_time_slicing->header.type) !=
+		    MRVL_DRCS_TIME_SLICE_TLV_ID ||
+		    wlan_le16_to_cpu(channel_time_slicing->header.len) !=
+		    sizeof(MrvlTypes_DrcsTimeSlice_t) -
+		    sizeof(MrvlIEtypesHeader_t)) {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pcfg->param.drcs_cfg[0].chan_idx =
+			wlan_le16_to_cpu(channel_time_slicing->chan_idx);
+		pcfg->param.drcs_cfg[0].chantime =
+			channel_time_slicing->chantime;
+		pcfg->param.drcs_cfg[0].switchtime =
+			channel_time_slicing->switchtime;
+		pcfg->param.drcs_cfg[0].undozetime =
+			channel_time_slicing->undozetime;
+		pcfg->param.drcs_cfg[0].mode = channel_time_slicing->mode;
+		PRINTM(MCMND,
+		       "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+		       pcfg->param.drcs_cfg[0].chan_idx,
+		       channel_time_slicing->chantime,
+		       channel_time_slicing->switchtime,
+		       channel_time_slicing->undozetime,
+		       channel_time_slicing->mode);
+		pioctl_buf->buf_len = sizeof(mlan_ds_drcs_cfg);
+		/*Channel for chan_idx 1 and 2 have different parameters */
+		if (0x3 != pcfg->param.drcs_cfg[0].chan_idx) {
+			channel_time_slicing1 = presp_cfg->drcs_buf;
+			if (wlan_le16_to_cpu(channel_time_slicing1->header.type)
+			    != MRVL_DRCS_TIME_SLICE_TLV_ID ||
+			    wlan_le16_to_cpu(channel_time_slicing1->header.
+					     len) !=
+			    sizeof(MrvlTypes_DrcsTimeSlice_t) -
+			    sizeof(MrvlIEtypesHeader_t)) {
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+			drcs_cfg1 =
+				(mlan_ds_drcs_cfg *) & pcfg->param.drcs_cfg[1];
+			drcs_cfg1->chan_idx =
+				wlan_le16_to_cpu(channel_time_slicing1->
+						 chan_idx);
+			drcs_cfg1->chantime = channel_time_slicing1->chantime;
+			drcs_cfg1->switchtime =
+				channel_time_slicing1->switchtime;
+			drcs_cfg1->undozetime =
+				channel_time_slicing1->undozetime;
+			drcs_cfg1->mode = channel_time_slicing1->mode;
+			PRINTM(MCMND,
+			       "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+			       drcs_cfg1->chan_idx, drcs_cfg1->chantime,
+			       drcs_cfg1->switchtime, drcs_cfg1->undozetime,
+			       drcs_cfg1->mode);
+			pioctl_buf->buf_len += sizeof(mlan_ds_drcs_cfg);
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv, IN 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(pmpriv->adapter, hw_spec->permanent_addr, pmpriv->curr_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *pcmd,
+		  IN t_u16 cmd_action, IN t_u32 cmd_oid, IN 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;
+	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));
+	} else {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	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);
+
+done:
+	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;
+
+	ENTER();
+
+	if (resp->result != HostCmd_RESULT_OK) {
+		PRINTM(MERROR, "CFG data cmd resp failed\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *pcmd,
+		     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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;
+
+	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;
+			}
+		}
+		if ((pmadapter->fw_bands & BAND_AN)
+			) {
+			pmadapter->adhoc_start_band = BAND_A | BAND_AN;
+			pmadapter->adhoc_11n_enabled = MTRUE;
+		} else
+			pmadapter->adhoc_start_band = BAND_A;
+		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
+	} else if ((pmadapter->fw_bands & BAND_GN)
+		) {
+		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+		pmadapter->adhoc_11n_enabled = MTRUE;
+	} 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 */
+
+	PRINTM(MCMND, "fw_band=0x%x, config_band=0x%x adhoc_band=0x%x\n",
+	       pmadapter->fw_bands, pmadapter->config_bands,
+	       pmadapter->adhoc_start_band);
+	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 (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 =
+					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);
+	pmadapter->mp_end_port = wlan_le16_to_cpu(hw_spec->mp_end_port);
+
+	for (i = 1; i <= (unsigned)(MAX_PORT - pmadapter->mp_end_port); i++)
+		pmadapter->mp_data_port_mask &= ~(1 << (MAX_PORT - i));
+
+	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 (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+				 pmadapter->fw_bands)) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#ifdef STA_SUPPORT
+	if (wlan_11d_set_universaltable(pmpriv, pmadapter->fw_bands)) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#endif /* STA_SUPPORT */
+	if (pmadapter->fw_cap_info & FW_CAPINFO_ECSA) {
+		t_u8 ecsa_enable = MTRUE;
+		pmadapter->ecsa_enable = MTRUE;
+		PRINTM(MCMND, "pmadapter->ecsa_enable=%d\n",
+		       pmadapter->ecsa_enable);
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET, ECSAEnable_i, MNULL,
+				       &ecsa_enable);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (pmadapter->fw_cap_info & FW_CAPINFO_GET_LOG) {
+		pmadapter->getlog_enable = MTRUE;
+		PRINTM(MCMND, "pmadapter->getlog_enable=%d\n",
+		       pmadapter->getlog_enable);
+	}
+
+	left_len = resp->size - sizeof(HostCmd_DS_GET_HW_SPEC) - S_DS_GEN;
+	tlv = (MrvlIEtypesHeader_t *)((t_u8 *)hw_spec +
+				      sizeof(HostCmd_DS_GET_HW_SPEC));
+	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		switch (tlv_type) {
+		case TLV_TYPE_FW_VER_INFO:
+			api_rev = (MrvlIEtypes_fw_ver_info_t *) tlv;
+			api_id = wlan_le16_to_cpu(api_rev->api_id);
+			switch (api_id) {
+			case FW_API_VER_ID:
+				pmadapter->fw_ver = api_rev->major_ver;
+				pmadapter->fw_min_ver = api_rev->minor_ver;
+				PRINTM(MCMND, "fw ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			case UAP_FW_API_VER_ID:
+				pmadapter->uap_fw_ver = api_rev->major_ver;
+				PRINTM(MCMND, "uap fw ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			case CHANRPT_API_VER_ID:
+				pmadapter->chanrpt_param_bandcfg =
+					api_rev->minor_ver;
+				PRINTM(MCMND, "chanrpt api ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			default:
+				break;
+			}
+			break;
+		case TLV_TYPE_MAX_CONN:
+			tlv_max_conn = (MrvlIEtypes_Max_Conn_t *) tlv;
+			PRINTM(MMSG, "max_p2p_conn = %d, max_sta_conn = %d\n",
+			       tlv_max_conn->max_p2p_conn,
+			       tlv_max_conn->max_sta_conn);
+			if (tlv_max_conn->max_p2p_conn &&
+			    tlv_max_conn->max_sta_conn)
+				pmadapter->max_sta_conn =
+					MIN(tlv_max_conn->max_sta_conn,
+					    tlv_max_conn->max_p2p_conn);
+			else if (tlv_max_conn->max_sta_conn)
+				pmadapter->max_sta_conn =
+					tlv_max_conn->max_sta_conn;
+			else if (tlv_max_conn->max_p2p_conn)
+				pmadapter->max_sta_conn =
+					tlv_max_conn->max_p2p_conn;
+			else
+				pmadapter->max_sta_conn = 0;
+			break;
+		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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN 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(pmpriv->adapter, &radio_ctl, pdata_buf, sizeof(t_u32));
+	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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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 +
+			sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG);
+		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 +
+			sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG);
+		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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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 *)((t_u8 *)p2p_config +
+						      sizeof
+						      (HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG));
+			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 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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);
+	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(MINFO, "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);
+	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 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(IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_reg_rw *reg_rw;
+
+	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);
+			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;
+			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;
+			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;
+		}
+	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,
+		    IN HostCmd_DS_COMMAND *resp, IN 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(pmadapter, &eeprom->value,
+					       &cmd_eeprom->value,
+					       MIN(MAX_EEPROM_DATA,
+						   eeprom->byte_count));
+					HEXDUMP("EEPROM",
+						(char *)&eeprom->value,
+						MIN(MAX_EEPROM_DATA,
+						    eeprom->byte_count));
+				}
+				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(IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_ds_mem_rw *mem_rw = MNULL;
+	HostCmd_DS_MEM_ACCESS *mem = (HostCmd_DS_MEM_ACCESS *)&resp->params.mem;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
+		mem_rw = &reg_mem->param.mem_rw;
+
+		mem_rw->addr = wlan_le32_to_cpu(mem->addr);
+		mem_rw->value = wlan_le32_to_cpu(mem->value);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+*
+*  @brief This function handles coex events generated by firmware
+*
+*  @param priv A pointer to mlan_private structure
+*  @param pevent   A pointer to event buf
+*
+*  @return     N/A
+*/
+void
+wlan_bt_coex_wlan_param_update_event(pmlan_private priv, pmlan_buffer pevent)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	MrvlIETypes_BtCoexAggrWinSize_t *pCoexWinsize = MNULL;
+	MrvlIEtypes_BtCoexScanTime_t *pScantlv = MNULL;
+	t_s32 len = pevent->data_len - sizeof(t_u32);
+	t_u8 *pCurrent_ptr = pevent->pbuf + pevent->data_offset + sizeof(t_u32);
+	t_u16 tlv_type, tlv_len;
+
+	ENTER();
+
+	while (len >= sizeof(MrvlIEtypesHeader_t)) {
+		tlv = (MrvlIEtypesHeader_t *)pCurrent_ptr;
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		if ((tlv_len + sizeof(MrvlIEtypesHeader_t)) > len)
+			break;
+		switch (tlv_type) {
+		case TLV_BTCOEX_WL_AGGR_WINSIZE:
+			pCoexWinsize = (MrvlIETypes_BtCoexAggrWinSize_t *) tlv;
+			pmadapter->coex_win_size = pCoexWinsize->coex_win_size;
+			pmadapter->coex_tx_win_size = pCoexWinsize->tx_win_size;
+			pmadapter->coex_rx_win_size = pCoexWinsize->rx_win_size;
+			wlan_coex_ampdu_rxwinsize(pmadapter);
+			wlan_update_ampdu_txwinsize(pmadapter);
+			break;
+		case TLV_BTCOEX_WL_SCANTIME:
+			pScantlv = (MrvlIEtypes_BtCoexScanTime_t *) tlv;
+			pmadapter->coex_scan = pScantlv->coex_scan;
+			pmadapter->coex_min_scan_time =
+				wlan_le16_to_cpu(pScantlv->min_scan_time);
+			pmadapter->coex_max_scan_time =
+				wlan_le16_to_cpu(pScantlv->max_scan_time);
+			break;
+		default:
+			break;
+		}
+		len -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		pCurrent_ptr += tlv_len + sizeof(MrvlIEtypesHeader_t);
+	}
+	PRINTM(MEVENT,
+	       "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
+	       pmadapter->coex_scan, pmadapter->coex_min_scan_time,
+	       pmadapter->coex_win_size, pmadapter->coex_tx_win_size,
+	       pmadapter->coex_rx_win_size);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares command of supplicant pmk
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_802_11_supplicant_pmk(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+	MrvlIEtypes_Passphrase_t *ppassphrase_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;
+
+	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=marvell
+	 *  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=mrvl/: 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=marvell
+	 */
+
+	/* -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(pmpriv->adapter, pbssid_tlv->bssid, (t_u8 *)&psk->bssid,
+		       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(pmpriv->adapter, ppmk_tlv->pmk, psk->psk.pmk.pmk,
+		       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 && 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(pmpriv->adapter, (t_u8 *)pssid_tlv->ssid,
+		       (t_u8 *)psk->ssid.ssid, MIN(MLAN_MAX_SSID_LENGTH,
+						   psk->ssid.ssid_len));
+		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->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(pmpriv->adapter, ppassphrase_tlv->passphrase,
+		       psk->psk.passphrase.passphrase,
+		       MIN(MLAN_MAX_PASSPHRASE_LENGTH,
+			   psk->psk.passphrase.passphrase_len));
+		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 ((cmd_action == HostCmd_ACT_GEN_SET) &&
+	    ((ssid_flag || bssid_flag) && (!pmk_flag && !passphrase_flag))) {
+		PRINTM(MERROR,
+		       "Invalid case,ssid/bssid present without pmk or passphrase\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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *resp,
+			       IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_SUPPLICANT_PMK *supplicant_pmk_resp =
+		&resp->params.esupplicant_psk;
+	mlan_ds_sec_cfg sec_buf;
+	mlan_ds_sec_cfg *sec = MNULL;
+	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+	MrvlIEtypes_Passphrase_t *passphrase_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)
+			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))
+					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(pmpriv->adapter,
+					       sec->param.passphrase.ssid.ssid,
+					       pssid_tlv->ssid,
+					       MIN(MLAN_MAX_SSID_LENGTH,
+						   pssid_tlv->header.len));
+					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(pmpriv->adapter,
+					       &sec->param.passphrase.bssid,
+					       pbssid_tlv->bssid,
+					       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(pmpriv->adapter,
+					       sec->param.passphrase.psk.
+					       passphrase.passphrase,
+					       passphrase_tlv->passphrase,
+					       MIN(MLAN_MAX_PASSPHRASE_LENGTH,
+						   passphrase_tlv->header.len));
+					tlv_buf +=
+						passphrase_tlv->header.len +
+						sizeof(MrvlIEtypesHeader_t);
+					tlv_buf_len -=
+						(passphrase_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(pmpriv->adapter,
+					       sec->param.passphrase.psk.pmk.
+					       pmk, ppmk_tlv->pmk,
+					       MIN(MLAN_MAX_KEY_LENGTH,
+						   ppmk_tlv->header.len));
+					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;
+		}
+	}
+
+	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(IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action, IN 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,
+		 IN HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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 sends fw dump event command to firmware.
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param cmd            HostCmd_DS_COMMAND structure
+ *  @param cmd_action     the action: GET or SET
+ *  @param pdata_buf      A void pointer to information buffer
+ *  @return               N/A
+ */
+mlan_status
+wlan_cmd_fw_dump_event(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action,
+			       IN 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 *)((t_u8 *)plink_stat +
+				      sizeof(HostCmd_DS_802_11_LINK_STATISTIC));
+	DBG_HEXDUMP(MCMD_D, "tlv:", (void *)tlv, 1024);
+	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		switch (tlv_type) {
+		case TLV_TYPE_LL_STAT_IFACE:
+			fw_ifaceStat =
+				(mlan_wifi_iface_stat *) ((t_u8 *)tlv +
+							  sizeof
+							  (MrvlIEtypesHeader_t));
+			break;
+		case TLV_TYPE_LL_STAT_RADIO:
+			fw_radioStat =
+				(mlan_wifi_radio_stat *) ((t_u8 *)tlv +
+							  sizeof
+							  (MrvlIEtypesHeader_t));
+			num_radio = MAX_RADIO;
+			break;
+		default:
+			break;
+		}
+		left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+	if (!fw_ifaceStat || !fw_radioStat) {
+		PRINTM(MERROR, "!fw_ifaceStat || !fw_radioStat\n");
+		return;
+	}
+
+	*((t_u32 *)link_statistic) = num_radio;
+	link_statistic += sizeof(num_radio);
+
+	/* Fill radio stats array */
+	for (i = 0; i < num_radio; i++) {
+		radio_stat = (wifi_radio_stat *) link_statistic;
+		link_statistic += sizeof(wifi_radio_stat);
+
+		radio_stat->radio = wlan_le32_to_cpu(fw_radioStat[i].radio);
+
+		radio_stat->on_time = wlan_le32_to_cpu(fw_radioStat[i].on_time);
+		radio_stat->tx_time = wlan_le32_to_cpu(fw_radioStat[i].tx_time);
+		radio_stat->reserved0 =
+			wlan_le32_to_cpu(fw_radioStat[i].reserved0);
+		radio_stat->rx_time = wlan_le32_to_cpu(fw_radioStat[i].rx_time);
+		radio_stat->on_time_scan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_scan);
+		radio_stat->on_time_nbd =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_nbd);
+		radio_stat->on_time_gscan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_gscan);
+		radio_stat->on_time_roam_scan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_roam_scan);
+		radio_stat->on_time_pno_scan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_pno_scan);
+		radio_stat->on_time_hs20 =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_hs20);
+
+		radio_stat->num_channels =
+			wlan_le32_to_cpu(fw_radioStat[i].num_channels);
+		for (chan_idx = 0; chan_idx < radio_stat->num_channels;
+		     chan_idx++) {
+			if (radio_stat->num_channels > MAX_NUM_CHAN) {
+				radio_stat->num_channels =
+					wlan_le32_to_cpu(MAX_NUM_CHAN);
+				PRINTM(MERROR,
+				       "%s : radio_stat->num_channels=%d\n",
+				       __func__, radio_stat->num_channels);
+				break;
+			}
+			radio_stat->channels[chan_idx].channel.width =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].channel.
+						 width);
+			radio_stat->channels[chan_idx].channel.center_freq =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].channel.
+						 center_freq);
+			radio_stat->channels[chan_idx].channel.center_freq0 =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].channel.
+						 center_freq0);
+			radio_stat->channels[chan_idx].channel.center_freq1 =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].channel.
+						 center_freq1);
+
+			radio_stat->channels[chan_idx].on_time =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].on_time);
+			radio_stat->channels[chan_idx].cca_busy_time =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].
+						 cca_busy_time);
+		}
+	}
+
+	/* Fill iface stats */
+	iface_stat = (wifi_iface_stat *) link_statistic;
+
+	/* get wifi_interface_link_layer_info in driver, not in firmware */
+	if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+		iface_stat->info.mode = WIFI_INTERFACE_STA;
+		if (priv->media_connected)
+			iface_stat->info.state = WIFI_ASSOCIATING;
+		else
+			iface_stat->info.state = WIFI_DISCONNECTED;
+		iface_stat->info.roaming = WIFI_ROAMING_IDLE;
+		iface_stat->info.capabilities = WIFI_CAPABILITY_QOS;
+		memcpy(priv->adapter, iface_stat->info.ssid,
+		       priv->curr_bss_params.bss_descriptor.ssid.ssid,
+		       MLAN_MAX_SSID_LENGTH);
+		memcpy(priv->adapter, iface_stat->info.bssid,
+		       priv->curr_bss_params.bss_descriptor.mac_address,
+		       MLAN_MAC_ADDR_LENGTH);
+	} else {
+		iface_stat->info.mode = WIFI_INTERFACE_SOFTAP;
+		iface_stat->info.capabilities = WIFI_CAPABILITY_QOS;
+	}
+	memcpy(priv->adapter, iface_stat->info.mac_addr, priv->curr_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+	memcpy(priv->adapter, iface_stat->info.ap_country_str,
+	       priv->adapter->country_code, COUNTRY_CODE_LEN);
+	memcpy(priv->adapter, iface_stat->info.country_str,
+	       priv->adapter->country_code, 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(priv->adapter,
+		       iface_stat->peer_info[peerIdx].peer_mac_address,
+		       fw_ifaceStat->peer_info[peerIdx].peer_mac_address, 6);
+		iface_stat->peer_info[peerIdx].capabilities =
+			wlan_le32_to_cpu(fw_ifaceStat->peer_info[peerIdx].
+					 capabilities);
+		iface_stat->peer_info[peerIdx].num_rate =
+			wlan_le32_to_cpu(fw_ifaceStat->peer_info[peerIdx].
+					 num_rate);
+
+		PRINTM(MINFO,
+		       "bitrate  tx_mpdu  rx_mpdu  mpdu_lost retries retries_short retries_long\n");
+		for (rate_idx = 0;
+		     rate_idx < iface_stat->peer_info[peerIdx].num_rate;
+		     rate_idx++) {
+			wlan_fill_hal_wifi_rate(priv,
+						&fw_ifaceStat->
+						peer_info[peerIdx].
+						rate_stats[rate_idx].rate,
+						&iface_stat->peer_info[peerIdx].
+						rate_stats[rate_idx].rate);
+
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				tx_mpdu =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].tx_mpdu);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				rx_mpdu =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].rx_mpdu);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				mpdu_lost =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].
+						 mpdu_lost);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				retries =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].retries);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				retries_short =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].
+						 retries_short);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				retries_long =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].
+						 retries_long);
+			PRINTM(MCMND,
+			       "0x%x  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x\n",
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].rate.bitrate,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].tx_mpdu,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].rx_mpdu,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].mpdu_lost,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].retries,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].retries_short,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].retries_long);
+		}
+	}
+}
+
+/**
+ *  @brief This function handles the command response of get_link_statistic
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_get_link_statistic(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *resp, IN 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;
+}
diff --git a/wlan_sd8897/mlan/mlan_decl.h b/wlan_sd8897/mlan/mlan_decl.h
new file mode 100644
index 0000000..da16ed0
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_decl.h
@@ -0,0 +1,1725 @@
+/** @file mlan_decl.h
+ *
+ *  @brief This file declares the generic data structures and APIs.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    11/07/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_DECL_H_
+#define _MLAN_DECL_H_
+
+/** MLAN release version */
+#define MLAN_RELEASE_VERSION		 "C534"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef signed char t_s8;
+/** Unsigned char (1-byte) */
+typedef unsigned char t_u8;
+/** Signed short (2-bytes) */
+typedef short t_s16;
+/** Unsigned short (2-bytes) */
+typedef unsigned short t_u16;
+/** Signed long (4-bytes) */
+typedef int t_s32;
+/** Unsigned long (4-bytes) */
+typedef unsigned int t_u32;
+/** Signed long long 8-bytes) */
+typedef long long t_s64;
+/** Unsigned long long 8-bytes) */
+typedef unsigned long long t_u64;
+/** Void pointer (4-bytes) */
+typedef void t_void;
+/** 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)
+
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM         (16)
+
+/** NET IP alignment */
+#define MLAN_NET_IP_ALIGN        2
+
+/** DMA alignment */
+/* SDIO3.0 Inrevium Adapter require 32 bit DMA alignment */
+#define DMA_ALIGNMENT            32
+
+/** max size of TxPD */
+#define MAX_TXPD_SIZE            32
+
+/** Minimum data header length */
+#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT+MAX_TXPD_SIZE)
+
+/** rx data header length */
+#define MLAN_RX_HEADER_LEN       MLAN_MIN_DATA_HEADER_LEN
+
+/** This is current limit on Maximum Tx AMPDU allowed */
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED          16
+#define MLAN_MAX_TX_BASTREAM_DEFAULT            2
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED_NOV15    2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED     16
+
+/** station ampdu tx win size */
+#define MLAN_STA_AMPDU_DEF_TXWINSIZE_NOV15      32
+/** uap ampdu tx win size */
+#define MLAN_UAP_AMPDU_DEF_TXWINSIZE_NOV15      32
+/** uap ampdu rx win size */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE_NOV15      32
+#ifdef WIFI_DIRECT_SUPPORT
+/** wfd ampdu tx/rx win size */
+#define MLAN_WFD_AMPDU_DEF_TXRXWINSIZE_NOV15    32
+#endif
+
+#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       48
+/** Default Win size attached during ADDBA response */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE       32
+/** 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
+
+/** NAN use the same window size for tx/rx */
+#define MLAN_NAN_AMPDU_DEF_TXRXWINSIZE     16
+/** RX winsize for COEX */
+#define MLAN_NAN_COEX_AMPDU_DEF_RXWINSIZE  16
+
+/** 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 7 */
+#define MLAN_RATE_INDEX_MCS7    7
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9    9
+/** 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 */
+#define MLAN_RX_DATA_BUF_SIZE     (4 * 1024)
+/** Size of rx command buffer */
+#define MLAN_RX_CMD_BUF_SIZE      (2 * 1024)
+
+#define MLAN_USB_RX_DATA_BUF_SIZE       MLAN_RX_DATA_BUF_SIZE
+
+/** 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
+
+/** 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           (4 * 1024)
+/** 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)
+/** SDIO MP aggr pkt limit 16*/
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_16	 (16)
+/** max SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX	 (16)
+
+/** SDIO IO Port mask */
+#define MLAN_SDIO_IO_PORT_MASK		0xfffff
+/** SDIO Block/Byte mode mask */
+#define MLAN_SDIO_BYTE_MODE_MASK	0x80000000
+
+/** Max retry number of IO write */
+#define MAX_WRITE_IOMEM_RETRY		2
+
+/** 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)
+
+/** 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 NET_MONITOR */
+#define MLAN_BUF_FLAG_NET_MONITOR        MBIT(11)
+
+/** Buffer flag for NULL data packet */
+#define MLAN_BUF_FLAG_NULL_PKT        MBIT(12)
+
+#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 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,
+	MLAN_STATUS_COMPLETE,
+} 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,
+} mlan_buf_type;
+
+/** 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_NAN = 4,
+	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 bit mask */
+#define BSS_ROLE_BIT_MASK    MBIT(0)
+
+/** Get BSS role */
+#define GET_BSS_ROLE(priv)   ((priv)->bss_role & BSS_ROLE_BIT_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,
+	/* 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_NAN_STARTED = 0x80000024,
+	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;
+
+/** Data Structures */
+/** mlan_image data structure */
+typedef struct _mlan_fw_image {
+    /** Helper image buffer pointer */
+	t_u8 *phelper_buf;
+    /** Helper image length */
+	t_u32 helper_len;
+    /** 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;
+
+#define OID_TYPE_CAL    0x2
+#define OID_TYPE_DPD    0xa
+
+/** 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 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,
+};
+
+/** 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;
+
+/** 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[0];
+} mlan_event, *pmlan_event;
+
+/** 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;
+
+/** mix rate information structure */
+typedef MLAN_PACK_START struct _mix_rate_info {
+    /**  bit0: LGI: gi=0, SGI: gi= 1 */
+    /**  bit1-2: 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3  */
+    /**  bit3-4: LG: format=0, HT: format=1, VHT: format=2 */
+    /**  bit5: LDPC: 0-not support,  1-support */
+    /**  bit6-7:reserved */
+	t_u8 rate_info;
+    /** MCS index */
+	t_u8 mcs_index;
+    /** bitrate, in 500Kbps */
+	t_u16 bitrate;
+} MLAN_PACK_END mix_rate_info, *pmix_rate_info;
+
+/** rxpd extra information structure */
+typedef MLAN_PACK_START struct _rxpd_extra_info {
+    /** flags */
+	t_u8 flags;
+    /** channel.flags */
+	t_u16 channel_flags;
+    /** mcs.known */
+	t_u8 mcs_known;
+    /** mcs.flags */
+	t_u8 mcs_flags;
+} MLAN_PACK_END rxpd_extra_info, *prxpd_extra_info;
+
+/** rdaio tap information structure */
+typedef MLAN_PACK_START struct _radiotap_info {
+    /** Rate Info */
+	mix_rate_info rate_info;
+    /** SNR */
+	t_s8 snr;
+    /** Noise Floor */
+	t_s8 nf;
+    /** band config */
+	t_u8 band_config;
+    /** chan number */
+	t_u8 chan_num;
+    /** antenna */
+	t_u8 antenna;
+    /** extra rxpd info from FW */
+	rxpd_extra_info extra_info;
+} MLAN_PACK_END radiotap_info, *pradiotap_info;
+
+/** 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;
+    /** Offset to data */
+	t_u32 data_offset;
+    /** Data length */
+	t_u32 data_len;
+    /** Buffer type: data, cmd, event etc. */
+	mlan_buf_type buf_type;
+
+    /** Fields below are valid for data packet only */
+    /** QoS priority */
+	t_u32 priority;
+    /** Time stamp when packet is received (seconds) */
+	t_u32 in_ts_sec;
+    /** Time stamp when packet is received (micro seconds) */
+	t_u32 in_ts_usec;
+    /** Time stamp when packet is processed (seconds) */
+	t_u32 out_ts_sec;
+    /** Time stamp when packet is processed (micro seconds) */
+	t_u32 out_ts_usec;
+    /** tx_seq_num */
+	t_u32 tx_seq_num;
+
+    /** Fields below are valid for MLAN module only */
+    /** Pointer to parent mlan_buffer */
+	struct _mlan_buffer *pparent;
+    /** Use count for this buffer */
+	t_u32 use_count;
+} mlan_buffer, *pmlan_buffer;
+
+/** mlan_fw_info data structure */
+typedef struct _mlan_hw_info {
+    /** Firmware capabilities */
+	t_u32 fw_cap;
+} mlan_hw_info, *pmlan_hw_info;
+
+/** mlan_bss_attr data structure */
+typedef struct _mlan_bss_attr {
+    /** BSS type */
+	t_u32 bss_type;
+    /** Data frame type: Ethernet II, 802.11, etc. */
+	t_u32 frame_type;
+    /** The BSS is active (non-0) or not (0). */
+	t_u32 active;
+    /** BSS Priority */
+	t_u32 bss_priority;
+    /** BSS number */
+	t_u32 bss_num;
+    /** The BSS is virtual */
+	t_u32 bss_virtual;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+/** bss tbl data structure */
+typedef struct _mlan_bss_tbl {
+    /** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+} mlan_bss_tbl, *pmlan_bss_tbl;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** Type enumeration for the command result */
+typedef MLAN_PACK_START enum _mlan_cmd_result_e {
+	MLAN_CMD_RESULT_SUCCESS = 0,
+	MLAN_CMD_RESULT_FAILURE = 1,
+	MLAN_CMD_RESULT_TIMEOUT = 2,
+	MLAN_CMD_RESULT_INVALID_DATA = 3
+} MLAN_PACK_END mlan_cmd_result_e;
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} MLAN_PACK_END mlan_wmm_ac_e;
+
+/** Type enumeration for the action field in the Queue Config command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e {
+	MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_config_action_e;
+
+/** Type enumeration for the action field in the queue stats command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e {
+	MLAN_WMM_STATS_ACTION_START = 0,
+	MLAN_WMM_STATS_ACTION_STOP = 1,
+	MLAN_WMM_STATS_ACTION_GET_CLR = 2,
+	MLAN_WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_stats_action_e;
+
+/**
+ *  @brief IOCTL structure for a Traffic stream status.
+ *
+ */
+typedef MLAN_PACK_START struct {
+    /** TSID: Range: 0->7 */
+	t_u8 tid;
+    /** TSID specified is valid */
+	t_u8 valid;
+    /** AC TSID is active on */
+	t_u8 access_category;
+    /** UP specified for the TSID */
+	t_u8 user_priority;
+    /** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 psb;
+    /** Upstream(0), Downlink(1), Bidirectional(3) */
+	t_u8 flow_dir;
+    /** Medium time granted for the TSID */
+	t_u16 medium_time;
+} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t,
+/** Type definition of mlan_ds_wmm_ts_status for MLAN_OID_WMM_CFG_TS_STATUS */
+mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status;
+
+/** Max Ie length */
+#define MAX_IE_SIZE             256
+
+/** custom IE */
+typedef MLAN_PACK_START struct _custom_ie {
+    /** IE Index */
+	t_u16 ie_index;
+    /** Mgmt Subtype Mask */
+	t_u16 mgmt_subtype_mask;
+    /** IE Length */
+	t_u16 ie_length;
+    /** IE buffer */
+	t_u8 ie_buffer[MAX_IE_SIZE];
+} MLAN_PACK_END custom_ie;
+
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW         4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX               26
+
+/** custom IE info */
+typedef MLAN_PACK_START struct _custom_ie_info {
+    /** size of buffer */
+	t_u16 buf_size;
+    /** no of buffers of buf_size */
+	t_u16 buf_count;
+} MLAN_PACK_END custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** No of tuples */
+	t_u16 count;
+    /** custom IE info tuples */
+	custom_ie_info info[MAX_MGMT_IE_INDEX];
+} MLAN_PACK_END tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef MLAN_PACK_START struct _tlvbuf_custom_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** IE data */
+	custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW];
+    /** Max mgmt IE TLV */
+	tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+/** 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[0];
+} 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[0];
+		} 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[0];
+		} 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[0];
+		} 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;
+
+#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 {
+	WIFI_DISCONNECTED = 0,
+	WIFI_AUTHENTICATING = 1,
+	WIFI_ASSOCIATING = 2,
+	WIFI_ASSOCIATED = 3,
+    /** if done by firmware/driver */
+	WIFI_EAPOL_STARTED = 4,
+    /** if done by firmware/driver */
+	WIFI_EAPOL_COMPLETED = 5,
+} wifi_connection_state;
+/** roam state */
+typedef enum {
+	WIFI_ROAMING_IDLE = 0,
+	WIFI_ROAMING_ACTIVE = 1,
+} wifi_roam_state;
+/** interface mode */
+typedef enum {
+	WIFI_INTERFACE_STA = 0,
+	WIFI_INTERFACE_SOFTAP = 1,
+	WIFI_INTERFACE_IBSS = 2,
+	WIFI_INTERFACE_P2P_CLIENT = 3,
+	WIFI_INTERFACE_P2P_GO = 4,
+	WIFI_INTERFACE_NAN = 5,
+	WIFI_INTERFACE_MESH = 6,
+} wifi_interface_mode;
+
+/** set for QOS association */
+#define WIFI_CAPABILITY_QOS          0x00000001
+/** set for protected association (802.11 beacon frame control protected bit set) */
+#define WIFI_CAPABILITY_PROTECTED    0x00000002
+/** set if 802.11 Extended Capabilities element interworking bit is set */
+#define WIFI_CAPABILITY_INTERWORKING 0x00000004
+/** set for HS20 association */
+#define WIFI_CAPABILITY_HS20         0x00000008
+/** set is 802.11 Extended Capabilities element UTF-8 SSID bit is set */
+#define WIFI_CAPABILITY_SSID_UTF8    0x00000010
+/** set is 802.11 Country Element is present */
+#define WIFI_CAPABILITY_COUNTRY      0x00000020
+
+/** link layer status */
+typedef struct {
+    /** interface mode */
+	wifi_interface_mode mode;
+    /** interface mac address (self) */
+	t_u8 mac_addr[6];
+    /** connection state (valid for STA, CLI only) */
+	wifi_connection_state state;
+    /** roaming state */
+	wifi_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];
+} wifi_interface_link_layer_info;
+
+typedef wifi_interface_link_layer_info *wifi_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;
+
+/** 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 */
+	wifi_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) */
+
+#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) (IN t_void *pmoal_handle,
+					 IN t_u32 offset,
+					 IN t_u32 len, OUT t_u8 *pbuf);
+    /** moal_get_hw_spec_complete */
+	mlan_status (*moal_get_hw_spec_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status,
+						  IN mlan_hw_info * phw,
+						  IN pmlan_bss_tbl ptbl);
+    /** moal_init_fw_complete */
+	mlan_status (*moal_init_fw_complete) (IN t_void *pmoal_handle,
+					      IN mlan_status status);
+    /** moal_shutdown_fw_complete */
+	mlan_status (*moal_shutdown_fw_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status);
+    /** moal_send_packet_complete */
+	mlan_status (*moal_send_packet_complete) (IN t_void *pmoal_handle,
+						  IN pmlan_buffer pmbuf,
+						  IN mlan_status status);
+    /** moal_recv_complete */
+	mlan_status (*moal_recv_complete) (IN t_void *pmoal_handle,
+					   IN pmlan_buffer pmbuf,
+					   IN t_u32 port,
+					   IN mlan_status status);
+    /** moal_recv_packet */
+	mlan_status (*moal_recv_packet) (IN t_void *pmoal_handle,
+					 IN pmlan_buffer pmbuf);
+    /** moal_recv_event */
+	mlan_status (*moal_recv_event) (IN t_void *pmoal_handle,
+					IN pmlan_event pmevent);
+    /** moal_ioctl_complete */
+	mlan_status (*moal_ioctl_complete) (IN t_void *pmoal_handle,
+					    IN pmlan_ioctl_req pioctl_req,
+					    IN mlan_status status);
+
+    /** moal_alloc_mlan_buffer */
+	mlan_status (*moal_alloc_mlan_buffer) (IN t_void *pmoal_handle,
+					       IN t_u32 size,
+					       OUT pmlan_buffer *pmbuf);
+    /** moal_free_mlan_buffer */
+	mlan_status (*moal_free_mlan_buffer) (IN t_void *pmoal_handle,
+					      IN pmlan_buffer pmbuf);
+
+    /** moal_write_reg */
+	mlan_status (*moal_write_reg) (IN t_void *pmoal_handle,
+				       IN t_u32 reg, IN t_u32 data);
+    /** moal_read_reg */
+	mlan_status (*moal_read_reg) (IN t_void *pmoal_handle,
+				      IN t_u32 reg, OUT t_u32 *data);
+    /** moal_write_data_sync */
+	mlan_status (*moal_write_data_sync) (IN t_void *pmoal_handle,
+					     IN pmlan_buffer pmbuf,
+					     IN t_u32 port, IN t_u32 timeout);
+    /** moal_read_data_sync */
+	mlan_status (*moal_read_data_sync) (IN t_void *pmoal_handle,
+					    IN OUT pmlan_buffer pmbuf,
+					    IN t_u32 port, IN t_u32 timeout);
+    /** moal_malloc */
+	mlan_status (*moal_malloc) (IN t_void *pmoal_handle,
+				    IN t_u32 size,
+				    IN t_u32 flag, OUT t_u8 **ppbuf);
+    /** moal_mfree */
+	mlan_status (*moal_mfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_vmalloc */
+	mlan_status (*moal_vmalloc) (IN t_void *pmoal_handle,
+				     IN t_u32 size, OUT t_u8 **ppbuf);
+    /** moal_vfree */
+	mlan_status (*moal_vfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_memset */
+	t_void *(*moal_memset) (IN t_void *pmoal_handle,
+				IN t_void *pmem, IN t_u8 byte, IN t_u32 num);
+    /** moal_memcpy */
+	t_void *(*moal_memcpy) (IN t_void *pmoal_handle,
+				IN t_void *pdest,
+				IN const t_void *psrc, IN t_u32 num);
+    /** moal_memmove */
+	t_void *(*moal_memmove) (IN t_void *pmoal_handle,
+				 IN t_void *pdest,
+				 IN const t_void *psrc, IN t_u32 num);
+    /** moal_memcmp */
+	t_s32 (*moal_memcmp) (IN t_void *pmoal_handle,
+			      IN const t_void *pmem1,
+			      IN const t_void *pmem2, IN t_u32 num);
+    /** moal_udelay */
+	t_void (*moal_udelay) (IN t_void *pmoal_handle, IN t_u32 udelay);
+    /** moal_get_system_time */
+	mlan_status (*moal_get_system_time) (IN t_void *pmoal_handle,
+					     OUT t_u32 *psec, OUT t_u32 *pusec);
+    /** moal_init_timer*/
+	mlan_status (*moal_init_timer) (IN t_void *pmoal_handle,
+					OUT t_void **pptimer,
+					IN t_void (*callback) (t_void
+							       *pcontext),
+					IN t_void *pcontext);
+    /** moal_free_timer */
+	mlan_status (*moal_free_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_start_timer*/
+	mlan_status (*moal_start_timer) (IN t_void *pmoal_handle,
+					 IN t_void *ptimer,
+					 IN t_u8 periodic, IN t_u32 msec);
+    /** moal_stop_timer*/
+	mlan_status (*moal_stop_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_init_lock */
+	mlan_status (*moal_init_lock) (IN t_void *pmoal_handle,
+				       OUT t_void **pplock);
+    /** moal_free_lock */
+	mlan_status (*moal_free_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_lock */
+	mlan_status (*moal_spin_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_unlock */
+	mlan_status (*moal_spin_unlock) (IN t_void *pmoal_handle,
+					 IN t_void *plock);
+    /** moal_print */
+	t_void (*moal_print) (IN t_void *pmoal_handle,
+			      IN t_u32 level, IN char *pformat, IN ...
+		);
+    /** moal_print_netintf */
+	t_void (*moal_print_netintf) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index, IN t_u32 level);
+    /** moal_assert */
+	t_void (*moal_assert) (IN t_void *pmoal_handle, IN t_u32 cond);
+    /** moal_hist_data_add */
+	t_void (*moal_hist_data_add) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index,
+				      IN t_u8 rx_rate,
+				      IN t_s8 snr,
+				      IN t_s8 nflr, IN t_u8 antenna);
+	t_void (*moal_updata_peer_signal) (IN t_void *pmoal_handle,
+					   IN t_u32 bss_index,
+					   IN t_u8 *peer_addr,
+					   IN t_s8 snr, IN t_s8 nflr);
+} 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
+
+/** 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
+
+/** 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(6)
+/** Control bit for DFS support */
+#define FEATURE_CTRL_DFS_SUPPORT    MBIT(7)
+
+/** Default feature control */
+#define FEATURE_CTRL_DEFAULT        0xffffffff
+
+/** 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
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#ifdef DEBUG_LEVEL1
+    /** Driver debug bit masks */
+	t_u32 drvdbg;
+#endif
+    /** allocate fixed buffer size for scan beacon buffer*/
+	t_u32 fixed_beacon_buffer;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** SDIO MPA Rx */
+	t_u32 mpa_rx_cfg;
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/* 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
+    /** FW download CRC check flag */
+	t_u32 fw_crc_check;
+    /** 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;
+    /** Host sleep wakeup interval */
+	t_u32 hs_wake_interval;
+    /** GPIO to indicate wakeup source */
+	t_u8 indication_gpio;
+    /** channel time and mode for DRCS*/
+	t_u32 drcs_chantime_mode;
+} mlan_device, *pmlan_device;
+
+/** MLAN API function prototype */
+#define MLAN_API
+
+/** Registration */
+MLAN_API mlan_status mlan_register(IN pmlan_device pmdevice,
+				   OUT t_void **ppmlan_adapter);
+
+/** Un-registration */
+MLAN_API mlan_status mlan_unregister(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Downloading */
+MLAN_API mlan_status mlan_dnld_fw(IN t_void *pmlan_adapter,
+				  IN pmlan_fw_image pmfw);
+
+/** Custom data pass API */
+MLAN_API mlan_status mlan_set_init_param(IN t_void *pmlan_adapter,
+					 IN pmlan_init_param pparam);
+
+/** Firmware Initialization */
+MLAN_API mlan_status mlan_init_fw(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Shutdown */
+MLAN_API mlan_status mlan_shutdown_fw(IN t_void *pmlan_adapter
+	);
+
+/** Main Process */
+MLAN_API mlan_status mlan_main_process(IN t_void *pmlan_adapter
+	);
+
+/** Rx process */
+mlan_status mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts);
+
+/** Packet Transmission */
+MLAN_API mlan_status mlan_send_packet(IN t_void *pmlan_adapter,
+				      IN pmlan_buffer pmbuf);
+
+/** Packet Reception complete callback */
+MLAN_API mlan_status mlan_recv_packet_complete(IN t_void *pmlan_adapter,
+					       IN pmlan_buffer pmbuf,
+					       IN mlan_status status);
+
+/** interrupt handler */
+MLAN_API mlan_status mlan_interrupt(IN t_void *pmlan_adapter);
+
+#if defined(SYSKT)
+/** GPIO IRQ callback function */
+MLAN_API t_void mlan_hs_callback(IN t_void *pctx);
+#endif /* SYSKT_MULTI || SYSKT */
+
+MLAN_API t_void mlan_pm_wakeup_card(IN t_void *pmlan_adapter);
+
+MLAN_API t_u8 mlan_is_main_process_running(IN t_void *adapter);
+
+/** mlan ioctl */
+MLAN_API mlan_status mlan_ioctl(IN t_void *pmlan_adapter,
+				IN pmlan_ioctl_req pioctl_req);
+/** mlan select wmm queue */
+MLAN_API t_u8 mlan_select_wmm_queue(IN t_void *pmlan_adapter,
+				    IN t_u8 bss_num, IN t_u8 tid);
+#endif /* !_MLAN_DECL_H_ */
diff --git a/wlan_sd8897/mlan/mlan_fw.h b/wlan_sd8897/mlan/mlan_fw.h
new file mode 100644
index 0000000..fdd7374
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_fw.h
@@ -0,0 +1,6463 @@
+/** @file mlan_fw.h
+ *
+ *  @brief This file contains firmware specific defines.
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    10/27/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_FW_H_
+#define _MLAN_FW_H_
+
+/** Interface header length */
+#define INTF_HEADER_LEN     4
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** 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];
+
+/** Firmware wakeup method : Unchanged */
+#define WAKEUP_FW_UNCHANGED                     0
+/** Firmware wakeup method : Through interface */
+#define WAKEUP_FW_THRU_INTERFACE                1
+/** Firmware wakeup method : Through GPIO*/
+#define WAKEUP_FW_THRU_GPIO                     2
+/** Default value of GPIO */
+#define DEF_WAKEUP_FW_GPIO                      0
+
+/** Default auto deep sleep mode */
+#define DEFAULT_AUTO_DS_MODE                  MTRUE
+/** Default power save mode */
+#define DEFAULT_PS_MODE                 Wlan802_11PowerModePSP
+
+#define EVENT_NAN_GENERIC 0x00000075
+#define NAN_EVT_SUBTYPE_SD_EVENT 0
+#define NAN_EVT_SUBTYPE_NAN_STARTED 1
+#define NAN_EVT_SUBTYPE_SDF_TX_DONE 2
+
+/** 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_ID;
+
+/** Key Info flag for multicast key */
+#define KEY_INFO_MCAST_KEY      0x01
+/** Key Info flag for unicast key */
+#define KEY_INFO_UCAST_KEY      0x02
+
+/** KEY_INFO_WEP*/
+typedef enum _KEY_INFO_WEP {
+	KEY_INFO_WEP_MCAST = 0x01,
+	KEY_INFO_WEP_UNICAST = 0x02,
+	KEY_INFO_WEP_ENABLED = 0x04
+} KEY_INFO_WEP;
+
+/** KEY_INFO_TKIP */
+typedef enum _KEY_INFO_TKIP {
+	KEY_INFO_TKIP_MCAST = 0x01,
+	KEY_INFO_TKIP_UNICAST = 0x02,
+	KEY_INFO_TKIP_ENABLED = 0x04
+} KEY_INFO_TKIP;
+
+/** KEY_INFO_AES*/
+typedef enum _KEY_INFO_AES {
+	KEY_INFO_AES_MCAST = 0x01,
+	KEY_INFO_AES_UNICAST = 0x02,
+	KEY_INFO_AES_ENABLED = 0x04,
+	KEY_INFO_AES_MCAST_IGTK = 0x400,
+} KEY_INFO_AES;
+
+/** WPA AES key length */
+#define WPA_AES_KEY_LEN                 16
+/** WPA TKIP key length */
+#define WPA_TKIP_KEY_LEN                32
+/** WPA AES IGTK key length */
+#define CMAC_AES_KEY_LEN                16
+/** IGTK key length */
+#define WPA_IGTK_KEY_LEN                16
+
+/** WAPI key length */
+#define WAPI_KEY_LEN            50
+/** KEY_INFO_WAPI*/
+typedef enum _KEY_INFO_WAPI {
+	KEY_INFO_WAPI_MCAST = 0x01,
+	KEY_INFO_WAPI_UNICAST = 0x02,
+	KEY_INFO_WAPI_ENABLED = 0x04
+} KEY_INFO_WAPI;
+
+/** Maximum ethernet frame length sans FCS */
+#define MV_ETH_FRAME_LEN   1514
+
+/** 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
+
+/** This is for firmware specific length */
+#define EXTRA_LEN	36
+
+/** 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)
+
+/* Macros in interface module */
+/** Firmware ready */
+#define FIRMWARE_READY          0xfedc
+
+/** Number of firmware blocks to transfer */
+#define FIRMWARE_TRANSFER_NBLOCK	2
+
+/** 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
+
+/** TLV  type ID definition */
+#define PROPRIETARY_TLV_BASE_ID                 0x0100
+
+/** 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
+
+/** 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 : Passphrase */
+#define TLV_TYPE_PASSPHRASE         (PROPRIETARY_TLV_BASE_ID + 0x3c)	/* 0x013c */
+
+/** 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: robustcoex mode */
+#define TLV_TYPE_ROBUSTCOEX           (PROPRIETARY_TLV_BASE_ID + 0x11B)	/* 0x021B */
+
+/** 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 : 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)
+
+#define TLV_TYPE_LL_STAT_IFACE                     (PROPRIETARY_TLV_BASE_ID + 300)
+#define TLV_TYPE_LL_STAT_RADIO                     (PROPRIETARY_TLV_BASE_ID + 301)
+
+/** 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
+/** Test if adhoc 11n is enabled */
+#define IS_11N_ADHOC_ENABLED(priv) ((priv->bss_mode == MLAN_BSS_MODE_IBSS) && pmadapter->adhoc_11n_enabled)
+#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)
+/** Find out if we are the initiator or not */
+#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) & \
+			MBIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS)
+
+/** 4K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_4K        4096
+/** 8K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_8K        8192
+/** 12K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_12K        12288
+/** Max Rx AMPDU Size */
+#define MAX_RX_AMPDU_SIZE_64K   0x03
+/** Non green field station */
+#define NON_GREENFIELD_STAS     0x04
+
+/** Greenfield support */
+#define HWSPEC_GREENFIELD_SUPP   MBIT(29)
+/** RX STBC support */
+#define HWSPEC_RXSTBC_SUPP   MBIT(26)
+/** ShortGI @ 40Mhz support */
+#define HWSPEC_SHORTGI40_SUPP    MBIT(24)
+/** ShortGI @ 20Mhz support */
+#define HWSPEC_SHORTGI20_SUPP    MBIT(23)
+/** RX LDPC support */
+#define HWSPEC_LDPC_SUPP         MBIT(22)
+/** Channel width 40Mhz support */
+#define HWSPEC_CHANBW40_SUPP     MBIT(17)
+/** 40Mhz intolarent enable */
+#define CAPINFO_40MHZ_INTOLARENT MBIT(8)
+
+/** Default 11n capability mask for 2.4GHz */
+#define DEFAULT_11N_CAP_MASK_BG (HWSPEC_SHORTGI20_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+/** Default 11n capability mask for 5GHz */
+#define DEFAULT_11N_CAP_MASK_A  (HWSPEC_CHANBW40_SUPP | HWSPEC_SHORTGI20_SUPP | \
+		HWSPEC_SHORTGI40_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+
+/** Default 11n TX BF capability **/
+#define DEFAULT_11N_TX_BF_CAP   0x19E74608
+
+/** Bits to ignore in hw_dev_cap as these bits are set in get_hw_spec */
+#define IGN_HW_DEV_CAP      (CAPINFO_40MHZ_INTOLARENT)
+
+/** HW_SPEC FwCapInfo */
+#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & MBIT(11))
+
+/** HW_SPEC Dot11nDevCap : MAX AMSDU supported */
+#define ISSUPP_MAXAMSDU(Dot11nDevCap) (Dot11nDevCap & MBIT(31))
+/** HW_SPEC Dot11nDevCap : Beamforming support */
+#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & MBIT(30))
+/** HW_SPEC Dot11nDevCap : Green field support */
+#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & MBIT(29))
+/** HW_SPEC Dot11nDevCap : AMPDU support */
+#define ISSUPP_AMPDU(Dot11nDevCap) (Dot11nDevCap & MBIT(28))
+/** HW_SPEC Dot11nDevCap : MIMO PS support  */
+#define ISSUPP_MIMOPS(Dot11nDevCap) (Dot11nDevCap & MBIT(27))
+/** HW_SPEC Dot11nDevCap : Rx STBC support */
+#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & MBIT(26))
+/** HW_SPEC Dot11nDevCap : Tx STBC support */
+#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & MBIT(25))
+/** HW_SPEC Dot11nDevCap : Short GI @ 40Mhz support */
+#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24))
+/** HW_SPEC Dot11nDevCap : Reset Short GI @ 40Mhz support */
+#define RESETSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(24))
+/** HW_SPEC Dot11nDevCap : Short GI @ 20Mhz support */
+#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & MBIT(23))
+/** HW_SPEC Dot11nDevCap : Rx LDPC support */
+#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & MBIT(22))
+/** HW_SPEC Dot11nDevCap : Number of TX BA streams supported */
+#define ISSUPP_GETTXBASTREAM(Dot11nDevCap) ((Dot11nDevCap >> 18) & 0xF)
+/** HW_SPEC Dot11nDevCap : Delayed ACK */
+#define GET_DELAYEDBACK(Dot11nDevCap) (((Dot11nDevCap >> 20) & 0x03))
+/** HW_SPEC Dot11nDevCap : Immediate ACK */
+#define GET_IMMEDIATEBACK(Dot11nDevCap) (((Dot11nDevCap >> 18) & 0x03))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 40Mhz  support */
+#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 20Mhz  support */
+#define ISSUPP_CHANWIDTH20(Dot11nDevCap) (Dot11nDevCap & MBIT(16))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 10Mhz  support */
+#define ISSUPP_CHANWIDTH10(Dot11nDevCap) (Dot11nDevCap & MBIT(15))
+/** Dot11nUsrCap : 40Mhz intolarance enabled */
+#define ISENABLED_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap & MBIT(8))
+/** Dot11nUsrCap : Reset 40Mhz intolarance enabled */
+#define RESET_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(8))
+/** HW_SPEC Dot11nDevCap : Rx AntennaD support */
+#define ISSUPP_RXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(7))
+/** HW_SPEC Dot11nDevCap : Rx AntennaC support */
+#define ISSUPP_RXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(6))
+/** HW_SPEC Dot11nDevCap : Rx AntennaB support */
+#define ISSUPP_RXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(5))
+/** HW_SPEC Dot11nDevCap : Rx AntennaA support */
+#define ISSUPP_RXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(4))
+/** HW_SPEC Dot11nDevCap : Tx AntennaD support */
+#define ISSUPP_TXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(3))
+/** HW_SPEC Dot11nDevCap : Tx AntennaC support */
+#define ISSUPP_TXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(2))
+/** HW_SPEC Dot11nDevCap : Tx AntennaB support */
+#define ISSUPP_TXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(1))
+/** HW_SPEC Dot11nDevCap : Tx AntennaA support */
+#define ISSUPP_TXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(0))
+
+/** HW_SPEC Dot11nDevCap : Set support of channel bw @ 40Mhz */
+#define SETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap |= MBIT(17))
+/** HW_SPEC Dot11nDevCap : Reset support of channel bw @ 40Mhz */
+#define RESETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(17))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_TXMCSSUPP(DevMCSSupported) (DevMCSSupported >> 4)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
+
+/** GET HTCapInfo : Supported Channel BW */
+#define GETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo & MBIT(1))
+/** GET HTCapInfo : Support for Greenfield */
+#define GETHT_GREENFIELD(HTCapInfo) (HTCapInfo & MBIT(4))
+/** GET HTCapInfo : Support for Short GI @ 20Mhz */
+#define GETHT_SHORTGI20(HTCapInfo) (HTCapInfo & MBIT(5))
+/** GET HTCapInfo : Support for Short GI @ 40Mhz */
+#define GETHT_SHORTGI40(HTCapInfo) (HTCapInfo & MBIT(6))
+/** GET HTCapInfo : Support for Tx STBC */
+#define GETHT_TXSTBC(HTCapInfo) (HTCapInfo & MBIT(7))
+
+/** GET HTCapInfo : Support for Rx STBC */
+#define GETHT_RXSTBC(HTCapInfo) ((HTCapInfo >> 8) & 0x03)
+/** GET HTCapInfo : Support for Delayed ACK */
+#define GETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo & MBIT(10))
+/** GET HTCapInfo : Support for Max AMSDU */
+#define GETHT_MAXAMSDU(HTCapInfo) (HTCapInfo & MBIT(11))
+
+/** SET HTCapInfo : Set support for LDPC coding capability */
+#define SETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo |= MBIT(0))
+/** SET HTCapInfo : Set support for Channel BW */
+#define SETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo |= MBIT(1))
+/** SET HTCapInfo : Set support for Greenfield */
+#define SETHT_GREENFIELD(HTCapInfo) (HTCapInfo |= MBIT(4))
+/** SET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define SETHT_SHORTGI20(HTCapInfo) (HTCapInfo |= MBIT(5))
+/** SET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define SETHT_SHORTGI40(HTCapInfo) (HTCapInfo |= MBIT(6))
+/** SET HTCapInfo : Set support for Tx STBC */
+#define SETHT_TXSTBC(HTCapInfo) (HTCapInfo |= MBIT(7))
+/** SET HTCapInfo : Set support for Rx STBC */
+#define SETHT_RXSTBC(HTCapInfo, value) (HTCapInfo |= (value << 8))
+/** SET HTCapInfo : Set support for delayed block ack */
+#define SETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo |= MBIT(10))
+/** SET HTCapInfo : Set support for Max size AMSDU */
+#define SETHT_MAXAMSDU(HTCapInfo) (HTCapInfo |= MBIT(11))
+/** SET HTCapInfo : Set support for DSSS/CCK Rates @ 40Mhz */
+#define SETHT_DSSSCCK40(HTCapInfo) (HTCapInfo |= MBIT(12))
+/** SET HTCapInfo : Enable 40Mhz Intolarence */
+#define SETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo |= MBIT(14))
+/** SET HTCapInfo : Disable Static SM power save */
+#define SETHT_STATIC_SMPS(HTCapInfo) ((HTCapInfo) |= (MBIT(2) | MBIT(3)))
+
+/** RESET HTCapInfo : Set support for LDPC coding capability */
+#define RESETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo &= ~MBIT(0))
+/** RESET HTCapInfo : Set support for Channel BW */
+#define RESETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo &= ~MBIT(1))
+/** RESET HTCapInfo : Set support for Greenfield */
+#define RESETHT_GREENFIELD(HTCapInfo) (HTCapInfo &= ~MBIT(4))
+/** RESET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define RESETHT_SHORTGI20(HTCapInfo) (HTCapInfo &= ~MBIT(5))
+/** RESET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define RESETHT_SHORTGI40(HTCapInfo) (HTCapInfo &= ~MBIT(6))
+/** RESET HTCapInfo : Set support for Tx STBC */
+#define RESETHT_TXSTBC(HTCapInfo) (HTCapInfo &= ~MBIT(7))
+/** RESET HTCapInfo : Set support for Rx STBC */
+#define RESETHT_RXSTBC(HTCapInfo) (HTCapInfo &= ~(0x03 << 8))
+/** RESET HTCapInfo : Set support for delayed block ack */
+#define RESETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo &= ~MBIT(10))
+/** RESET HTCapInfo : Set support for Max size AMSDU */
+#define RESETHT_MAXAMSDU(HTCapInfo) (HTCapInfo &= ~MBIT(11))
+/** RESET HTCapInfo : Disable 40Mhz Intolarence */
+#define RESETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo &= ~MBIT(14))
+/** RESET HTCapInfo: Enable SM power save */
+#define RESETHT_SM_POWERSAVE(HTCapInfo) ((HTCapInfo) &= ~(MBIT(2) | MBIT(3)))
+/** RESET HTExtCap : Clear RD Responder bit */
+#define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~MBIT(11))
+/** SET MCS32 */
+#define SETHT_MCS32(x) (x[4] |= 1)
+/** Set mcs set defined bit */
+#define SETHT_MCS_SET_DEFINED(x) (x[12] |= 1)
+/** Set the highest Rx data rate */
+#define SETHT_RX_HIGHEST_DT_SUPP(x, y) ((*(t_u16 *) (x + 10)) = y)
+/** AMPDU factor size */
+#define AMPDU_FACTOR_64K	0x03
+/** Set AMPDU size in A-MPDU paramter field */
+#define SETAMPDU_SIZE(x, y) do { \
+	x = x & ~0x03; \
+	x |= y & 0x03; \
+} while (0) \
+/** Set AMPDU spacing in A-MPDU paramter field */
+#define SETAMPDU_SPACING(x, y) do { \
+	x = x & ~0x1c; \
+	x |= (y & 0x07) << 2; \
+} while (0) \
+
+/** RadioType : Support for Band A */
+#define ISSUPP_BANDA(FwCapInfo) (FwCapInfo & MBIT(10))
+/** RadioType : Support for 40Mhz channel BW */
+#define ISALLOWED_CHANWIDTH40(Field2) (Field2 & MBIT(2))
+/** RadioType : Set support 40Mhz channel */
+#define SET_CHANWIDTH40(Field2) (Field2 |= MBIT(2))
+/** RadioType : Reset support 40Mhz channel */
+#define RESET_CHANWIDTH40(Field2) (Field2 &= ~(MBIT(0) | MBIT(1) | MBIT(2)))
+/** RadioType : Get secondary channel */
+#define GET_SECONDARYCHAN(Field2) (Field2 & (MBIT(0) | MBIT(1)))
+
+/** ExtCap : Support for FILS */
+#define ISSUPP_EXTCAP_FILS(ext_cap) (ext_cap.FILS)
+/** ExtCap : Set support FILS */
+#define SET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 1)
+/** ExtCap : Reset support FILS */
+#define RESET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 0)
+
+/** ExtCap : Support for TDLS */
+#define ISSUPP_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport)
+/** ExtCap : Set support TDLS */
+#define SET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 1)
+/** ExtCap : Reset support TDLS */
+#define RESET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 0)
+/** ExtCap : Support for TDLS UAPSD */
+#define ISSUPP_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport)
+/** ExtCap : Set support TDLS UAPSD */
+#define SET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 1)
+/** ExtCap : Reset support TDLS UAPSD */
+#define RESET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 0)
+/** ExtCap : Support for TDLS CHANNEL SWITCH */
+#define ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching)
+/** ExtCap : Set support TDLS CHANNEL SWITCH */
+#define SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching = 1)
+/** ExtCap : Reset support TDLS CHANNEL SWITCH */
+#define RESET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching = 0)
+
+/** ExtCap : 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)
+
+/** LLC/SNAP header len   */
+#define LLC_SNAP_LEN    8
+
+/** bandwidth following HTCAP */
+#define BW_FOLLOW_HTCAP             0
+/** bandwidth following VHTCAP */
+#define BW_FOLLOW_VHTCAP            1
+
+/** HW_SPEC FwCapInfo */
+#define HWSPEC_11ACSGI80_SUPP       MBIT(5)
+#define HWSPEC_11ACRXSTBC_SUPP      MBIT(8)
+
+#define ISSUPP_11ACENABLED(FwCapInfo) (FwCapInfo & (MBIT(12)|MBIT(13)))
+
+#define ISSUPP_11AC2GENABLED(FwCapInfo) (FwCapInfo & MBIT(12))
+#define ISSUPP_11AC5GENABLED(FwCapInfo) (FwCapInfo & MBIT(13))
+
+/** HW_SPEC Dot11acDevCap : HTC-VHT supported */
+#define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & MBIT(22))
+/** HW_SPEC Dot11acDevCap : VHT TXOP PS support */
+#define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & MBIT(21))
+/** HW_SPEC Dot11acDevCap : MU RX beamformee support */
+#define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(20))
+/** HW_SPEC Dot11acDevCap : MU TX beamformee support */
+#define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(19))
+/** HW_SPEC Dot11acDevCap : SU Beamformee support */
+#define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(12))
+/** HW_SPEC Dot11acDevCap : SU Beamformer support */
+#define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & MBIT(11))
+/** HW_SPEC Dot11acDevCap : Rx STBC support */
+#define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(8))
+/** HW_SPEC Dot11acDevCap : Tx STBC support */
+#define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(7))
+/** HW_SPEC Dot11acDevCap : Short GI support for 160MHz BW */
+#define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & MBIT(6))
+/** HW_SPEC Dot11acDevCap : Short GI support for 80MHz BW */
+#define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & MBIT(5))
+/** HW_SPEC Dot11acDevCap : LDPC coding support */
+#define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & MBIT(4))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160/80+80 MHz support */
+#define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & MBIT(3))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160 MHz support */
+#define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & MBIT(2))
+
+/** Set VHT Cap Info: Max MPDU length */
+#define SET_VHTCAP_MAXMPDULEN(VHTCapInfo, value) (VHTCapInfo |= (value & 0x03))
+/** SET VHT CapInfo:  Supported Channel Width SET (2 bits)*/
+#define SET_VHTCAP_CHWDSET(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x3) << 2))
+/** SET VHT CapInfo:  Rx STBC (3 bits) */
+#define SET_VHTCAP_RXSTBC(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 8))
+/** SET VHT CapInfo:  Commpressed Steering Num of BFer Ant Supported (3 bits) */
+#define SET_VHTCAP_SNBFERANT(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 13))
+/** SET VHT CapInfo:  Num of Sounding Dimensions (3 bits) */
+#define SET_VHTCAP_NUMSNDDM(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 16))
+/** SET VHT CapInfo:  Max AMPDU Length Exponent (3 bits) */
+#define SET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 23))
+/** SET VHT CapInfo:  VHT Link Adaptation Capable (2 bits) */
+#define SET_VHTCAP_LINKADPCAP(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x3) << 26))
+
+/** HW_SPEC Dot11acDevCap : ReSet VHT Link Adapation Capable */
+#define RESET_11ACVHTLINKCAPA(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x03))
+/** HW_SPEC Dot11acDevCap : ReSet Maximum AMPDU Length Exponent */
+#define RESET_11ACAMPDULENEXP(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x07))
+/** HW_SPEC Dot11acDevCap : ReSet support of HTC-VHT */
+#define RESET_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(22))
+/** HW_SPEC Dot11acDevCap : ReSet support of VHT TXOP PS */
+#define RESET_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(21))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU RX beamformee */
+#define RESET_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(20))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU TX beamformee */
+#define RESET_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(19))
+/** HW_SPEC Dot11acDevCap : ReSet Number of Sounding Dimensions */
+#define RESET_11ACSOUNDINGNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 16))
+/** HW_SPEC Dot11acDevCap : ReSet Compressed Steering Number
+  * of Beamformer Antenna */
+#define RESET_11ACBFANTNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 13))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformee */
+#define RESET_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(12))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformer */
+#define RESET_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(11))
+/** HW_SPEC Dot11acDevCap : ReSet support of Rx STBC */
+#define RESET_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 8))
+/** HW_SPEC Dot11acDevCap : ReSet support of Tx STBC */
+#define RESET_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(7))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 160MHz BW */
+#define RESET_11ACSGI160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(6))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 80MHz BW */
+#define RESET_11ACSGI80(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(5))
+/** HW_SPEC Dot11acDevCap : ReSet support of LDPC coding */
+#define RESET_11ACLDPC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(4))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+  * Channel BW 20/40/80/160/80+80 MHz */
+#define RESET_11ACBW8080(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(3))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+  * Channel BW 20/40/80/160 MHz */
+#define RESET_11ACBW160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(2))
+/** HW_SPEC Dot11acDevCap : ReSet Max MPDU length */
+#define RESET_11ACMAXMPDULEN(Dot11acDevCap) (Dot11acDevCap &= ~(0x03))
+
+/** Default 11ac capability mask for 2.4GHz */
+#define DEFAULT_11AC_CAP_MASK_BG (HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** Default 11ac capability mask for 5GHz */
+#define DEFAULT_11AC_CAP_MASK_A  (HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** GET VHT CapInfo : MAX MPDU Length */
+#define GET_VHTCAP_MAXMPDULEN(VHTCapInfo) (VHTCapInfo & 0x3)
+/** GET VHT CapInfo:  Supported Channel Width SET (2 bits)*/
+#define GET_VHTCAP_CHWDSET(VHTCapInfo)    ((VHTCapInfo >> 2) & 0x3)
+/** GET VHT CapInfo:  Rx STBC (3 bits) */
+#define GET_VHTCAP_RXSTBC(VHTCapInfo)     ((VHTCapInfo >> 8) & 0x7)
+/** GET VHT CapInfo:  Compressed Steering Num of BFer Ant Supported (3 bits) */
+#define GET_VHTCAP_SNBFERANT(VHTCapInfo)  ((VHTCapInfo >> 13) & 0x7)
+/** GET VHT CapInfo:  Num of Sounding Dimensions (3 bits) */
+#define GET_VHTCAP_NUMSNDDM(VHTCapInfo)   ((VHTCapInfo >> 16) & 0x7)
+/** GET VHT CapInfo:  Max AMPDU Length Exponent (3 bits) */
+#define GET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo)   ((VHTCapInfo >> 23) & 0x7)
+/** GET VHT CapInfo:  VHT Link Adaptation Capable (2 bits) */
+#define GET_VHTCAP_LINKADPCAP(VHTCapInfo)  ((VHTCapInfo >> 26) & 0x3)
+/**SET OPERATING MODE:Channel Width:80M*/
+#define SET_OPER_MODE_80M(oper_mode)  (oper_mode = (oper_mode & ~MBIT(0))| MBIT(1))
+/**SET OPERATING MODE:Channel Width:40M*/
+#define SET_OPER_MODE_40M(oper_mode)  (oper_mode = (oper_mode & ~MBIT(1))| MBIT(0))
+/**SET OPERATING MODE:Channel Width:20M*/
+#define SET_OPER_MODE_20M(oper_mode)  (oper_mode &= ~(0x03))
+#define IS_OPER_MODE_20M(oper_mode) (((oper_mode) & (MBIT(0) | MBIT(1))) == 0)
+/**SET OPERATING MODE:Rx NSS:2*/
+#define SET_OPER_MODE_2NSS(oper_mode)  (oper_mode = (oper_mode &~(MBIT(5)|MBIT(6)))| MBIT(4))
+/**SET OPERATING MODE:Rx NSS:1*/
+#define SET_OPER_MODE_1NSS(oper_mode)  (oper_mode &= ~(MBIT(4)|MBIT(5)|MBIT(6)))
+
+#define GET_VHTMCS(MCSMapSet)         (MCSMapSet & 0xFFFF)
+#define GET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2*(nss-1)))&0x3)
+#define RET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2*(nss-1)))&0x3)
+#define SET_VHTNSSMCS(MCSMapSet, nss, value) \
+            (MCSMapSet |= (value & 0x3) << (2 * (nss - 1)))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_DEVTXMCSMAP(DevMCSMap)      (DevMCSMap >> 16)
+#define GET_DEVNSSTXMCS(DevMCSMap, nss) ((DevMCSMap >> (2*(nss-1)+16))&0x3)
+#define SET_DEVNSSTXMCS(DevMCSMap, nss, value) \
+            (DevMCSMap |= (value & 0x3) << (2 * (nss - 1) + 16))
+#define RESET_DEVTXMCSMAP(DevMCSMap)    (DevMCSMap &= 0xFFFF)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_DEVRXMCSMAP(DevMCSMap)      (DevMCSMap & 0xFFFF)
+#define GET_DEVNSSRXMCS(DevMCSMap, nss) ((DevMCSMap >> (2*(nss-1)))&0x3)
+#define SET_DEVNSSRXMCS(DevMCSMap, nss, value) \
+            (DevMCSMap |= (value & 0x3) << (2 * (nss - 1)))
+#define RESET_DEVRXMCSMAP(DevMCSMap)    (DevMCSMap &= 0xFFFF0000)
+
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_DROP_PATTERN  (PROPRIETARY_TLV_BASE_ID + 0x51)	/* 0x0151 */
+/** TLV type : Rate drop pattern */
+#define TLV_TYPE_RATE_DROP_CONTROL  (PROPRIETARY_TLV_BASE_ID + 0x52)	/* 0x0152 */
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_SCOPE         (PROPRIETARY_TLV_BASE_ID + 0x53)	/* 0x0153 */
+
+/** TLV type : Power group */
+#define TLV_TYPE_POWER_GROUP        (PROPRIETARY_TLV_BASE_ID + 0x54)	/* 0x0154 */
+
+/** Modulation class for DSSS Rates */
+#define MOD_CLASS_HR_DSSS       0x03
+/** Modulation class for OFDM Rates */
+#define MOD_CLASS_OFDM          0x07
+/** Modulation class for HT Rates */
+#define MOD_CLASS_HT            0x08
+/** Modulation class for VHT Rates */
+#define MOD_CLASS_VHT           0x09
+/** HT bandwidth 20 MHz */
+#define HT_BW_20    0
+/** HT bandwidth 40 MHz */
+#define HT_BW_40    1
+/** HT bandwidth 80 MHz */
+#define HT_BW_80    2
+
+/** TLV type : 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 : 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 : 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 : 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
+
+/** 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 firmware wakeup method */
+#define HostCmd_CMD_802_11_FW_WAKE_METHOD     0x0074
+/** 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 : 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
+
+/** Host Command ID : SDIO GPIO interrupt configuration */
+#define HostCmd_CMD_SDIO_GPIO_INT_CONFIG      0x0088
+
+#ifdef MFG_CMD_SUPPORT
+/** Host Command ID : Mfg command */
+#define HostCmd_CMD_MFG_COMMAND               0x0089
+#endif
+/** 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 : 802.11 RSSI INFO EXT*/
+#define HostCmd_CMD_RSSI_INFO_EXT             0x0237
+
+/** Host Command ID: Multi chan config */
+#define HostCmd_CMD_MULTI_CHAN_CONFIG                0x011e
+/** Host Command ID: Multi chan policy */
+#define HostCmd_CMD_MULTI_CHAN_POLICY                0x0121
+/** TLV ID for multi chan info */
+#define TLV_TYPE_MULTI_CHAN_INFO             (PROPRIETARY_TLV_BASE_ID + 0xb7)
+/** TLV ID for multi chan group info */
+#define TLV_TYPE_MULTI_CHAN_GROUP_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0xb8)
+/** TLV ID for DRCS TimeSlice */
+#define MRVL_DRCS_TIME_SLICE_TLV_ID  (PROPRIETARY_TLV_BASE_ID + 263)
+/** Host Command ID: DRCS config */
+#define HostCmd_CMD_DRCS_CONFIG                     0x024a
+
+#ifdef RX_PACKET_COALESCE
+/** TLV ID for RX pkt coalesce config */
+#define TLV_TYPE_RX_PKT_COAL_CONFIG           (PROPRIETARY_TLV_BASE_ID + 0xC9)
+#endif
+
+/** Host Command ID : Channel report request */
+#define HostCmd_CMD_CHAN_REPORT_REQUEST              0x00dd
+
+/** Host Command ID: SUPPLICANT_PMK */
+#define HostCmd_CMD_SUPPLICANT_PMK            0x00c4
+/** Host Command ID: SUPPLICANT_PROFILE */
+#define HostCmd_CMD_SUPPLICANT_PROFILE        0x00c5
+
+/** Host Command ID : Add Block Ack Request */
+#define HostCmd_CMD_11N_ADDBA_REQ             0x00ce
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_CFG                   0x00cd
+/** Host Command ID : Add Block Ack Response */
+#define HostCmd_CMD_11N_ADDBA_RSP             0x00cf
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_DELBA                 0x00d0
+/** Host Command ID: Configure Tx Buf size */
+#define HostCmd_CMD_RECONFIGURE_TX_BUFF       0x00d9
+/** Host Command ID: AMSDU Aggr Ctrl */
+#define HostCmd_CMD_AMSDU_AGGR_CTRL           0x00df
+/** Host Command ID: 11AC config */
+#define HostCmd_CMD_11AC_CFG                   0x0112
+/** Host Command ID: Configure TX Beamforming capability */
+#define HostCmd_CMD_TX_BF_CFG                 0x0104
+
+/** Host Command ID : 802.11 TX power configuration */
+#define HostCmd_CMD_TXPWR_CFG                 0x00d1
+
+/** Host Command ID : Soft Reset */
+#define  HostCmd_CMD_SOFT_RESET               0x00d5
+
+/** Host Command ID : 802.11 b/g/n rate configration */
+#define HostCmd_CMD_TX_RATE_CFG               0x00d6
+
+/** Host Command ID : Enhanced PS mode */
+#define HostCmd_CMD_802_11_PS_MODE_ENH        0x00e4
+
+/** Host command action : Host sleep configuration */
+#define HostCmd_CMD_802_11_HS_CFG_ENH         0x00e5
+
+/** Host Command ID : CAU register access */
+#define HostCmd_CMD_CAU_REG_ACCESS            0x00ed
+
+/** Host Command ID : mgmt IE list */
+#define  HostCmd_CMD_MGMT_IE_LIST             0x00f2
+
+/** Host Command ID : TDLS configuration */
+#define  HostCmd_CMD_TDLS_CONFIG              0x0100
+/** Host Command ID : TDLS operation */
+#define HostCmd_CMD_TDLS_OPERATION          0x0122
+
+/* 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)
+
+#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
+
+/** 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: 802.11 Network Monitor */
+#define HostCmd_CMD_802_11_NET_MONITOR         0x0102
+
+/** Host Command ID: Tx data pause */
+#define HostCmd_CMD_CFG_TX_DATA_PAUSE           0x0103
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** Host Command ID: P2P PARAMS CONFIG */
+#define HOST_CMD_P2P_PARAMS_CONFIG              0x00ea
+/** Host Command ID: WIFI_DIRECT_MODE_CONFIG */
+#define HOST_CMD_WIFI_DIRECT_MODE_CONFIG    0x00eb
+#endif
+
+/** Host Command ID: Remain On Channel */
+#define HostCmd_CMD_802_11_REMAIN_ON_CHANNEL     0x010d
+
+#define HostCmd_CMD_COALESCE_CFG                 0x010a
+
+/** Host Command ID : 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: Get sensor temp*/
+#define HostCmd_DS_GET_SENSOR_TEMP	0x0227
+
+/** Host Command ID : Configure ADHOC_OVER_IP parameters */
+#define HostCmd_CMD_WMM_PARAM_CONFIG                0x023a
+
+#ifdef STA_SUPPORT
+/** Host Command ID :  set/get sta configure */
+#define HostCmd_CMD_STA_CONFIGURE            0x023f
+#endif
+
+/** Host Command ID : GPIO independent reset configure */
+#define HostCmd_CMD_INDEPENDENT_RESET_CFG    0x0243
+
+/** Channel usability flags */
+#define MARVELL_CHANNEL_DISABLED		MBIT(7)
+#define MARVELL_CHANNEL_NOHT160			MBIT(4)
+#define MARVELL_CHANNEL_NOHT80			MBIT(3)
+#define MARVELL_CHANNEL_NOHT40			MBIT(2)
+#define MARVELL_CHANNEL_DFS				MBIT(1)
+#define MARVELL_CHANNEL_PASSIVE			MBIT(0)
+
+#define HostCmd_CMD_DYN_BW                  0x0252
+
+#define HostCmd_CMD_BOOT_SLEEP              0x0258
+
+#define HostCmd_CMD_ACS     0x025a
+
+/** 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 : 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        30
+/** Size of command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+
+/** 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
+
+/** 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
+
+/** 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
+
+/** 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: Multi Chan Info*/
+#define EVENT_MULTI_CHAN_INFO               0x0000006a
+
+/** Event ID: Tx status */
+#define EVENT_TX_STATUS_REPORT               0x00000074
+
+#define EVENT_BT_COEX_WLAN_PARA_CHANGE	 0x00000076
+
+#define EVENT_EXCEED_MAX_P2P_CONN     0x00000089
+
+#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             1
+/** 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;
+
+/** tdls ie data structure */
+typedef MLAN_PACK_START struct _ie_data {
+    /** IE Length */
+	t_u16 ie_length;
+    /** IE pointer */
+	t_u8 ie_ptr[0];
+} 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 structure for generic events from NAN FW */
+typedef MLAN_PACK_START struct _event_nan_generic {
+    /** NAN Event SubType */
+	t_u16 event_sub_type;
+} MLAN_PACK_END event_nan_generic;
+
+#define RXPD_FLAG_EXTRA_HEADER             (1 << 1)
+
+/** 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*/
+/** MrvlIEtypesHeader_t */
+typedef MLAN_PACK_START struct _MrvlIEtypesHeader {
+    /** Header type */
+	t_u16 type;
+    /** Header length */
+	t_u16 len;
+} MLAN_PACK_END MrvlIEtypesHeader_t;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Data_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Data */
+	t_u8 data[1];
+} MLAN_PACK_END MrvlIEtypes_Data_t;
+
+/*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] Reserved */
+	t_u8 rate_info;
+   /** Reserved */
+	t_u8 reserved[3];
+    /** TDLS flags, bit 0: 0=InfraLink, 1=DirectLink */
+	t_u8 flags;
+    /**For SD8887 antenna info: 0 = 2.4G antenna a; 1 = 2.4G antenna b; 3 = 5G antenna; 0xff = invalid value */
+	t_u8 antenna;
+	/* [31:0] ToA of the rx packet, [63:32] ToD of the ack for the rx packet Both ToA and ToD are in nanoseconds */
+	t_u64 toa_tod_tstamps;
+    /** rx info */
+	t_u32 rx_info;
+} MLAN_PACK_END RxPD, *PRxPD;
+
+/** IEEEtypes_FrameCtl_t*/
+#ifdef BIG_ENDIAN_SUPPORT
+typedef MLAN_PACK_START struct _IEEEtypes_FrameCtl_t {
+
+    /** Order */
+	t_u8 order:1;
+    /** Wep */
+	t_u8 wep:1;
+    /** More Data */
+	t_u8 more_data:1;
+    /** Power Mgmt */
+	t_u8 pwr_mgmt:1;
+    /** Retry */
+	t_u8 retry:1;
+    /** More Frag */
+	t_u8 more_frag:1;
+    /** From DS */
+	t_u8 from_ds:1;
+    /** To DS */
+	t_u8 to_ds:1;
+    /** Sub Type */
+	t_u8 sub_type:4;
+    /** Type */
+	t_u8 type:2;
+    /** Protocol Version */
+	t_u8 protocol_version:2;
+} MLAN_PACK_END IEEEtypes_FrameCtl_t;
+#else
+typedef MLAN_PACK_START struct _IEEEtypes_FrameCtl_t {
+    /** Protocol Version */
+	t_u8 protocol_version:2;
+    /** Type */
+	t_u8 type:2;
+    /** Sub Type */
+	t_u8 sub_type:4;
+    /** To DS */
+	t_u8 to_ds:1;
+    /** From DS */
+	t_u8 from_ds:1;
+    /** More Frag */
+	t_u8 more_frag:1;
+    /** Retry */
+	t_u8 retry:1;
+    /** Power Mgmt */
+	t_u8 pwr_mgmt:1;
+    /** More Data */
+	t_u8 more_data:1;
+    /** Wep */
+	t_u8 wep:1;
+    /** Order */
+	t_u8 order:1;
+} MLAN_PACK_END IEEEtypes_FrameCtl_t;
+#endif
+
+/** MrvlIETypes_MgmtFrameSet_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_MgmtFrameSet_t {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** Frame Control */
+	IEEEtypes_FrameCtl_t frame_control;
+	/* t_u8 frame_contents[0]; */
+} 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
+/** TxPD descriptor */
+typedef MLAN_PACK_START struct _UapTxPD {
+	/** 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 UapTxPD, *PUapTxPD;
+
+/** RxPD Descriptor */
+typedef MLAN_PACK_START struct _UapRxPD {
+    /** BSS Type */
+	t_u8 bss_type;
+    /** BSS number*/
+	t_u8 bss_num;
+    /** Rx packet length */
+	t_u16 rx_pkt_length;
+    /** Rx packet offset */
+	t_u16 rx_pkt_offset;
+    /** Rx packet type */
+	t_u16 rx_pkt_type;
+    /** Sequence nunmber */
+	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] Reserved */
+	t_u8 rate_info;
+    /** Reserved */
+	t_u8 reserved1[3];
+    /** TDLS flags, bit 0: 0=InfraLink, 1=DirectLink */
+	t_u8 flags;
+    /** For SD8887 ntenna info: 0 = 2.4G antenna a; 1 = 2.4G antenna b; 3 = 5G antenna; 0xff = invalid value */
+	t_u8 antenna;
+	/* [31:0] ToA of the rx packet, [63:32] ToD of the ack for the rx packet Both ToA and ToD are in nanoseconds */
+	t_u64 toa_tod_tstamps;
+    /** rx info */
+	t_u32 rx_info;
+} MLAN_PACK_END UapRxPD, *PUapRxPD;
+
+/** 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[0]; */
+} 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[0]; */
+} 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_6_7:2;
+    /** 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;
+    /** Reserved */
+	t_u8 reserved_6_7:2;
+#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;
+
+/** 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_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 tlv */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ChannelStats_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** channel statictics */
+	ChanStatistics_t chanStat[0];
+} MLAN_PACK_END MrvlIEtypes_ChannelStats_t;
+
+/** MrvlIETypes_ActionFrame_t */
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header;
+				  /**< Header */
+
+    /** Source Address */
+	t_u8 srcAddr[MLAN_MAC_ADDR_LENGTH];
+    /** Destination Address */
+	t_u8 dstAddr[MLAN_MAC_ADDR_LENGTH];
+
+    /** IEEEtypes Action frame structure */
+	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[0];
+} MLAN_PACK_END MrvlIEtypes_RsnParamSet_t;
+
+/** 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;
+
+/** 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;
+	} 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;
+
+/** 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)
+
+/** 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;
+
+/* 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 new power save command */
+typedef MLAN_PACK_START struct _HostCmd_DS_PS_MODE_ENH {
+    /** Action */
+	t_u16 action;
+    /** Data speciifc to action */
+	/* For IEEE power save data will be as
+	 * UINT16 mode (0x01 - firmware to automatically choose PS_POLL or NULL mode, 0x02 - PS_POLL, 0x03 - NULL mode )
+	 * UINT16 NullpacketInterval
+	 * UINT16 NumDtims
+	 * UINT16 BeaconMissInterval
+	 * UINT16 locallisteninterval
+	 * UINT16 adhocawakeperiod */
+
+	/* For auto deep sleep */
+	/* UINT16 Deep sleep inactivity timeout */
+
+	/* For PS sleep confirm
+	 * UINT16 responeCtrl - 0x00 - reponse from fw not needed, 0x01 - response from fw is needed */
+
+	union {
+    /** PS param definition */
+		ps_param opt_ps;
+    /** Auto ds param definition */
+		auto_ds_param auto_ds;
+    /** Sleep comfirm param definition */
+		sleep_confirm_param sleep_cfm;
+    /** bitmap for get PS info and Disable PS mode */
+		t_u16 ps_bitmap;
+    /** auto ps param */
+		auto_ps_param auto_ps;
+	} params;
+} MLAN_PACK_END HostCmd_DS_802_11_PS_MODE_ENH;
+
+/** FW VERSION tlv */
+#define TLV_TYPE_FW_VER_INFO        (PROPRIETARY_TLV_BASE_ID + 0xC7)	/* 0x1C7 */
+
+/** MrvlIEtypes_fw_ver_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_ver_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** API id */
+	t_u16 api_id;
+    /** major version */
+	t_u8 major_ver;
+    /** minor version */
+	t_u8 minor_ver;
+} MLAN_PACK_END MrvlIEtypes_fw_ver_info_t;
+
+/** API ID */
+enum API_VER_ID {
+	KEY_API_VER_ID = 1,
+	FW_API_VER_ID = 2,
+	UAP_FW_API_VER_ID = 3,
+	CHANRPT_API_VER_ID = 4,
+};
+
+/** FW AP V15 */
+#define HOST_API_VERSION_V15  15
+/** FW minor version 1 */
+#define FW_MINOR_VERSION_1    1
+
+/** 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;
+
+/**  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[0];
+} 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_802_11_NET_MONITOR */
+typedef MLAN_PACK_START struct _HostCmd_802_11_DS_NET_MONITOR {
+    /** Action */
+	t_u16 action;
+    /** Enable/disable net monitor */
+	t_u16 enable_net_mon;
+    /** set net monitor filer flag */
+	t_u16 filter_flag;
+    /** Channel to monitor */
+	MrvlIEtypes_ChanBandListParamSet_t monitor_chan;
+} MLAN_PACK_END HostCmd_DS_802_11_NET_MONITOR;
+
+/** 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;
+
+/** 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;
+
+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;
+} 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 {
+    /** wifi radio (if multiple radio supported) */
+	t_u32 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 */
+	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[0];
+} 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[0]; */
+} 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[0]; */
+} 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[0];
+} MLAN_PACK_END HostCmd_DS_802_11_LINK_STATISTIC;
+
+/**_HostCmd_TX_RATE_QUERY */
+typedef MLAN_PACK_START struct _HostCmd_TX_RATE_QUERY {
+    /** Tx rate */
+	t_u8 tx_rate;
+    /** Tx Rate Info:
+     * [Bit 0-1] tx rate formate: LG = 0, HT = 1, VHT = 2
+     * [Bit 2-3] HT/VHT Bandwidth: BW20 = 0, BW40 = 1, BW80 = 2, BW160 = 3
+     * [Bit 4]   HT/VHT Guard Interval: LGI = 0, SGI = 1 */
+	t_u8 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_FW_WAKE_METHOD */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_FW_WAKEUP_METHOD {
+    /** Action */
+	t_u16 action;
+    /** Method */
+	t_u16 method;
+} MLAN_PACK_END HostCmd_DS_802_11_FW_WAKEUP_METHOD;
+
+/** HostCmd_CMD_802_11_ROBUSTCOEX */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_ROBUSTCOEX {
+    /** Action */
+	t_u16 action;
+    /** RSVD */
+	t_u16 rsvd;
+} MLAN_PACK_END HostCmd_DS_802_11_ROBUSTCOEX;
+
+/** 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
+
+/**  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];
+    /** VHT MCS rate bitmap */
+	t_u16 vht_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[0]; */
+} MLAN_PACK_END MrvlRateDropPattern_t;
+
+/** HostCmd_DS_TX_RATE_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TX_RATE_CFG {
+    /** Action */
+	t_u16 action;
+    /** Reserved */
+	t_u16 reserved_1;
+	/* MrvlRateScope_t RateScope;
+	 * MrvlRateDropPattern_t RateDrop; */
+} 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[0] */
+} 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;
+
+#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
+     */
+} MLAN_PACK_END HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG;
+#endif
+
+/** Coalesce filter field parameter */
+MLAN_PACK_START struct coalesce_filt_field_param {
+    /** Operation */
+	t_u8 operation;
+    /** Operation length */
+	t_u8 operand_len;
+    /** Offset */
+	t_u16 offset;
+    /** Operand byte stream */
+	t_u8 operand_byte_stream[4];
+} MLAN_PACK_END;
+
+/** Coalesce receive filter rule */
+MLAN_PACK_START struct coalesce_receive_filt_rule {
+    /** header */
+	MrvlIEtypesHeader_t header;
+    /** Number of fields */
+	t_u8 num_of_fields;
+    /** packet type */
+	t_u8 pkt_type;
+    /** maximum coalescing delay */
+	t_u16 max_coalescing_delay;
+	struct coalesce_filt_field_param params[0];
+} MLAN_PACK_END;
+
+/** HostCmd_DS_COALESCE_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_COALESCE_CONFIG {
+    /** Action 0-GET, 1-SET */
+	t_u16 action;
+    /** Number of rules */
+	t_u16 num_of_rules;
+	struct coalesce_receive_filt_rule rule[0];
+} 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;
+
+/*
+ * 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_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 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;
+
+/** 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 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;
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_VHTOprat_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+
+    /** Channel width */
+	t_u8 chan_width;
+    /** Channel center frequency 1 */
+	t_u8 chan_center_freq_1;
+    /** Channel center frequency 2 */
+	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;
+
+    /** Maximum tx power */
+	t_u8 max_tx_power;
+    /** Channel center frequency */
+	t_u8 chan_center_freq;
+    /** Channel width */
+	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;
+
+    /** MIMO Capability count */
+	t_u8 MU_MIMO_capa_count;
+    /** Stream under utilization */
+	t_u8 stream_underutilization;
+    /** VHT40 util */
+	t_u8 VHT40_util;
+    /** VHT80 util */
+	t_u8 VHT80_util;
+    /** VHT160 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;
+
+    /** AP quiet mode */
+	t_u8 AP_quiet_mode;
+    /** Quiet count */
+	t_u8 quiet_count;
+    /** Quiet period */
+	t_u8 quiet_period;
+    /** Quiet duration */
+	t_u16 quiet_dur;
+    /** Quiet offset */
+	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;
+
+    /** New Channel width */
+	t_u8 new_chan_width;
+    /** New Channel center frequency 1 */
+	t_u8 new_chan_center_freq_1;
+    /** New channel center frequency 2 */
+	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;
+
+/* 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;
+
+/* 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;
+
+/** 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;
+
+/** 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_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;
+
+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;
+
+/** HostCmd_DS_ACS */
+typedef MLAN_PACK_START struct _HostCmd_DS_ACS {
+    /** Best channel */
+	t_u8 best_ch;
+    /** TLV buffer */
+    /** MrvlIEtypes_ChanListParamSet_t TLV (0x0101) in cmd */
+    /** MrvlIEtypes_ScanChanGap_t TLV (0x01c5) in cmd */
+    /** MrvlIEtypes_ChannelStats_t TLV (0x01c6) in cmd resp */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END HostCmd_DS_ACS;
+
+/** TLV type : STA Mac address */
+#define TLV_TYPE_STA_MAC_ADDRESS      (PROPRIETARY_TLV_BASE_ID + 0x20)	/* 0x0120 */
+
+/** 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 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_sta_ageout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sta_ageout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** station age out timer */
+	t_u32 sta_ageout_timer;
+} MLAN_PACK_END MrvlIEtypes_sta_ageout_t;
+
+/** MrvlIEtypes_rts_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rts_threshold_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** rts threshold */
+	t_u16 rts_threshold;
+} MLAN_PACK_END MrvlIEtypes_rts_threshold_t;
+
+/** MrvlIEtypes_frag_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_frag_threshold_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** frag threshold */
+	t_u16 frag_threshold;
+} MLAN_PACK_END MrvlIEtypes_frag_threshold_t;
+
+/** MrvlIEtypes_retry_limit_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_retry_limit_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** retry limit */
+	t_u8 retry_limit;
+} MLAN_PACK_END MrvlIEtypes_retry_limit_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_timeout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** pairwise update timeout in milliseconds */
+	t_u32 pairwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_retries_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** pairwise handshake retries */
+	t_u32 pwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_retries_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_timeout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** groupwise update timeout in milliseconds */
+	t_u32 groupwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_retries_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** groupwise handshake retries */
+	t_u32 gwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_retries_t;
+
+/** MrvlIEtypes_mgmt_ie_passthru_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mgmt_ie_passthru_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** mgmt IE mask value */
+	t_u32 mgmt_ie_mask;
+} MLAN_PACK_END MrvlIEtypes_mgmt_ie_passthru_t;
+
+/** MrvlIEtypes_mac_filter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mac_filter_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Filter mode */
+	t_u8 filter_mode;
+    /** Number of STA MACs */
+	t_u8 count;
+    /** STA MAC addresses buffer */
+	t_u8 mac_address[1];
+} MLAN_PACK_END MrvlIEtypes_mac_filter_t;
+
+/** MrvlIEtypes_auth_type_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_auth_type_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Authentication type */
+	t_u8 auth_type;
+} MLAN_PACK_END MrvlIEtypes_auth_type_t;
+
+/** MrvlIEtypes_encrypt_protocol_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_encrypt_protocol_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** encryption protocol */
+	t_u16 protocol;
+} MLAN_PACK_END MrvlIEtypes_encrypt_protocol_t;
+
+/** MrvlIEtypes_pwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_pwk_cipher_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** protocol */
+	t_u16 protocol;
+    /** pairwise cipher */
+	t_u8 pairwise_cipher;
+    /** reserved */
+	t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_pwk_cipher_t;
+
+/** MrvlIEtypes_gwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_gwk_cipher_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** group cipher */
+	t_u8 group_cipher;
+    /** reserved */
+	t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_gwk_cipher_t;
+
+/** MrvlIEtypes_akmp_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_akmp_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** key management */
+	t_u16 key_mgmt;
+    /** key management operation */
+	t_u16 key_mgmt_operation;
+} MLAN_PACK_END MrvlIEtypes_akmp_t;
+
+/** MrvlIEtypes_passphrase_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_passphrase_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** passphrase */
+	t_u8 passphrase[1];
+} MLAN_PACK_END MrvlIEtypes_passphrase_t;
+
+/** MrvlIEtypes_rsn_replay_prot_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rsn_replay_prot_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** rsn replay proection */
+	t_u8 rsn_replay_prot;
+} MLAN_PACK_END MrvlIEtypes_rsn_replay_prot_t;
+
+/** MrvlIEtypes_group_rekey_time_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_group_rekey_time_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** group key rekey time */
+	t_u32 gk_rekey_time;
+} MLAN_PACK_END MrvlIEtypes_group_rekey_time_t;
+
+/** MrvlIEtypes_wep_key_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wep_key_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** key index */
+	t_u8 key_index;
+    /** is default */
+	t_u8 is_default;
+    /** key data */
+	t_u8 key[1];
+} MLAN_PACK_END MrvlIEtypes_wep_key_t;
+
+/** MrvlIEtypes_bss_status_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_bss_status_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** BSS status, READ only */
+	t_u16 bss_status;
+} MLAN_PACK_END MrvlIEtypes_bss_status_t;
+
+/** MrvlIEtypes_preamble_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_preamble_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** preamble type, READ only */
+	t_u8 preamble_type;
+} MLAN_PACK_END MrvlIEtypes_preamble_t;
+
+/** MrvlIEtypes_wmm_parameter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wmm_parameter_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** WMM parameter */
+	WmmParameter_t wmm_para;
+} MLAN_PACK_END MrvlIEtypes_wmm_parameter_t;
+
+/** SNMP_MIB_UAP_INDEX */
+typedef enum _SNMP_MIB_UAP_INDEX {
+	tkip_mic_failures = 0x0b,
+	ccmp_decrypt_errors = 0x0c,
+	wep_undecryptable_count = 0x0d,
+	wep_icv_error_count = 0x0e,
+	decrypt_failure_count = 0xf,
+	dot11_failed_count = 0x12,
+	dot11_retry_count = 0x13,
+	dot11_multi_retry_count = 0x14,
+	dot11_frame_dup_count = 0x15,
+	dot11_rts_success_count = 0x16,
+	dot11_rts_failure_count = 0x17,
+	dot11_ack_failure_count = 0x18,
+	dot11_rx_fragment_count = 0x19,
+	dot11_mcast_rx_frame_count = 0x1a,
+	dot11_fcs_error_count = 0x1b,
+	dot11_tx_frame_count = 0x1c,
+	dot11_rsna_tkip_cm_invoked = 0x1d,
+	dot11_rsna_4way_hshk_failures = 0x1e,
+	dot11_mcast_tx_count = 0x1f,
+} SNMP_MIB_UAP_INDEX;
+
+/** MrvlIEtypes_snmp_oid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_snmp_oid_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** data */
+	t_u32 data;
+} MLAN_PACK_END MrvlIEtypes_snmp_oid_t;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_CONFIG {
+	/** CMD Action GET/SET*/
+	t_u16 action;
+	/** Tlv buffer */
+	t_u8 tlv_buffer[1];
+} MLAN_PACK_END HostCmd_DS_SYS_CONFIG;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_INFO {
+    /** sys info */
+	t_u8 sys_info[64];
+} MLAN_PACK_END HostCmd_DS_SYS_INFO;
+
+/** HostCmd_DS_STA_DEAUTH */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_DEAUTH {
+    /** mac address */
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+    /** reason code */
+	t_u16 reason;
+} MLAN_PACK_END HostCmd_DS_STA_DEAUTH;
+
+/** HostCmd_DS_REPORT_MIC */
+typedef MLAN_PACK_START struct _HostCmd_DS_REPORT_MIC {
+    /** mac address */
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END HostCmd_DS_REPORT_MIC;
+
+/** HostCmd_UAP_OPER_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_UAP_OPER_CTRL {
+    /** CMD Action GET/SET*/
+	t_u16 action;
+    /** control*/
+	t_u16 ctrl;
+    /**channel operation*/
+	t_u16 chan_opt;
+    /**channel band tlv*/
+	MrvlIEtypes_channel_band_t channel_band;
+} MLAN_PACK_END HostCmd_DS_UAP_OPER_CTRL;
+
+/** Host Command id: POWER_MGMT  */
+#define HOST_CMD_POWER_MGMT_EXT                   0x00ef
+/** TLV type: AP Sleep param */
+#define TLV_TYPE_AP_SLEEP_PARAM\
+		(PROPRIETARY_TLV_BASE_ID + 0x6a)	/* 0x016a */
+/** TLV type: AP Inactivity Sleep param */
+#define TLV_TYPE_AP_INACT_SLEEP_PARAM\
+		(PROPRIETARY_TLV_BASE_ID + 0x6b)	/* 0x016b */
+
+/** MrvlIEtypes_sleep_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sleep_param_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** control bitmap */
+	t_u32 ctrl_bitmap;
+    /** min_sleep */
+	t_u32 min_sleep;
+    /** max_sleep */
+	t_u32 max_sleep;
+} MLAN_PACK_END MrvlIEtypes_sleep_param_t;
+
+/** MrvlIEtypes_inact_sleep_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_inact_sleep_param_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** inactivity timeout */
+	t_u32 inactivity_to;
+
+    /** min_awake */
+	t_u32 min_awake;
+    /** max_awake */
+	t_u32 max_awake;
+} MLAN_PACK_END MrvlIEtypes_inact_sleep_param_t;
+
+/** HostCmd_DS_POWER_MGMT */
+typedef MLAN_PACK_START struct _HostCmd_DS_POWER_MGMT_EXT {
+    /** CMD Action Get/Set*/
+	t_u16 action;
+    /** power mode */
+	t_u16 power_mode;
+} MLAN_PACK_END HostCmd_DS_POWER_MGMT_EXT;
+
+/** MrvlIEtypes_ps_sta_ageout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ps_sta_ageout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** station age out timer */
+	t_u32 ps_sta_ageout_timer;
+} MLAN_PACK_END MrvlIEtypes_ps_sta_ageout_t;
+
+/** MrvlIEtypes_sta_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sta_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+} 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[0]; */
+} 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 */
+
+/** 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;
+
+/** 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;
+
+/**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[0];
+} 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;
+
+#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
+
+typedef MLAN_PACK_START struct _MrvlTypes_DrcsTimeSlice_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Channel Index*/
+	t_u16 chan_idx;
+	/** Channel time (in TU) for chan_idx*/
+	t_u8 chantime;
+	/** Channel swith time (in TU) for chan_idx*/
+	t_u8 switchtime;
+	/** Undoze time (in TU) for chan_idx*/
+	t_u8 undozetime;
+	/** Rx traffic control scheme when channel switch*/
+	/** only valid for GC/STA interface*/
+	t_u8 mode;
+} MLAN_PACK_END MrvlTypes_DrcsTimeSlice_t;
+typedef MLAN_PACK_START struct _HostCmd_DS_MULTI_CHAN_CFG {
+	/** Action */
+	t_u16 action;
+	/** Channel time */
+	t_u32 channel_time;
+	/** Buffer weight */
+	t_u8 buffer_weight;
+	/** TLV buffer */
+	t_u8 tlv_buf[0];
+	/* t_u8 *tlv_buf; */
+} MLAN_PACK_END HostCmd_DS_MULTI_CHAN_CFG;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_DRCS_CFG {
+	/** Action */
+	t_u16 action;
+	/** TLV buffer */
+	MrvlTypes_DrcsTimeSlice_t time_slicing;
+	/** TLV buffer */
+	MrvlTypes_DrcsTimeSlice_t drcs_buf[0];
+	/* t_u8 *tlv_buf; */
+} MLAN_PACK_END HostCmd_DS_DRCS_CFG;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_MULTI_CHAN_POLICY {
+	/** Action */
+	t_u16 action;
+	/** Multi-channel Policy */
+	t_u16 policy;
+} MLAN_PACK_END HostCmd_DS_MULTI_CHAN_POLICY;
+
+/** Channel band info */
+typedef MLAN_PACK_START struct _ChannelBandInfo {
+	/* band config */
+	Band_Config_t bandcfg;
+    /** channel num for specificed band */
+	t_u8 chan_num;
+} MLAN_PACK_END ChannelBandInfo;
+
+/** MrvlIETypes_mutli_chan_group_info_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_mutli_chan_group_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** channel group id */
+	t_u8 chan_group_id;
+    /** buffer weight for this channel group */
+	t_u8 chan_buff_weight;
+    /** channel number and band information */
+	ChannelBandInfo chan_band_info;
+    /** Max channel time (us) */
+	t_u32 channel_time;
+    /** Reserved */
+	t_u32 reserved;
+	MLAN_PACK_START union {
+		t_u8 sdio_func_num;
+		t_u8 usb_epnum;
+	} MLAN_PACK_END hid_num;
+    /** interface number in this group */
+	t_u8 num_intf;
+    /** bss_type list */
+	t_u8 bss_type_numlist[0];
+} MLAN_PACK_END MrvlIEtypes_multi_chan_group_info_t;
+
+/** MrvlIEtypes_multi_chan_info_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_mutli_chan_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** multi channel operation status */
+	t_u16 status;
+    /** Tlv buffer */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END MrvlIEtypes_multi_chan_info_t;
+
+/** 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;
+
+/** 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*/
+
+/* 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 Marvell extended TLV
+ */
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header;
+				/**< Marvell 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;
+
+/**
+ * @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;
+
+/** Marvell channel descriptor */
+typedef MLAN_PACK_START struct {
+	t_u16 startFreq;		/**< Start Frequency */
+	Band_Config_t bandcfg;		/**< bandcfg */
+	t_u8 chanNum;			/**< channel no */
+
+} MLAN_PACK_END MrvlChannelDesc_t;
+
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t Header;  /**< Header */
+
+	MeasRptBasicMap_t map;	     /**< IEEE 802.11h basic meas report */
+} MLAN_PACK_END MrvlIEtypes_ChanRpt11hBasic_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;
+
+/** HostCmd_DS_SENSOR_TEMP structure */
+typedef MLAN_PACK_START struct _HostCmd_DS_SENSOR_TEMP {
+	/** Temperature */
+	t_u32 temperature;
+} MLAN_PACK_END HostCmd_DS_SENSOR_TEMP;
+
+#ifdef STA_SUPPORT
+/** HostCmd_DS_STA_CONFIGURE structure */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_CONFIGURE {
+    /** Action Set or get */
+	t_u16 action;
+    /** Tlv buffer */
+	t_u8 tlv_buffer[0];
+    /**MrvlIEtypes_channel_band_t band_channel; */
+} MLAN_PACK_END HostCmd_DS_STA_CONFIGURE;
+#endif
+
+/** 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;
+
+/** 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;
+	/** 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;
+	/** 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;
+
+	/** Enhanced power save command */
+		HostCmd_DS_802_11_PS_MODE_ENH psmode_enh;
+		HostCmd_DS_802_11_HS_CFG_ENH opt_hs_cfg;
+		HostCmd_DS_802_11_FW_WAKEUP_METHOD fwwakeupmethod;
+	/** 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;
+	/** 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;
+
+	/** 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 */
+
+       /** Sleep period command */
+		HostCmd_DS_802_11_SLEEP_PERIOD sleep_pd;
+       /** Sleep params command */
+		HostCmd_DS_802_11_SLEEP_PARAMS sleep_param;
+
+       /** SDIO GPIO interrupt config command */
+		HostCmd_DS_SDIO_GPIO_INT_CONFIG sdio_gpio_int;
+		HostCmd_DS_SDIO_PULL_CTRL sdio_pull_ctl;
+		HostCmd_DS_SET_BSS_MODE bss_mode;
+		HostCmd_DS_802_11_NET_MONITOR net_mon;
+		HostCmd_DS_CMD_TX_DATA_PAUSE tx_data_pause;
+		HostCmd_DS_REMAIN_ON_CHANNEL remain_on_chan;
+#ifdef WIFI_DIRECT_SUPPORT
+		HostCmd_DS_WIFI_DIRECT_MODE wifi_direct_mode;
+		HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG p2p_params_config;
+#endif
+		HostCmd_DS_COALESCE_CONFIG coalesce_config;
+		HostCmd_DS_HS_WAKEUP_REASON hs_wakeup_reason;
+		HostCmd_DS_MULTI_CHAN_CFG multi_chan_cfg;
+		HostCmd_DS_MULTI_CHAN_POLICY multi_chan_policy;
+		HostCmd_DS_DRCS_CFG drcs_cfg;
+		HostCmd_CONFIG_LOW_PWR_MODE low_pwr_mode_cfg;
+		HostCmd_DS_TSF tsf;
+#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;
+#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_ACS acs;
+		HostCmd_DS_DYN_BW dyn_bw;
+		HostCmd_DS_802_11_ROBUSTCOEX robustcoexparams;
+    /** boot sleep configure */
+		HostCmd_DS_BOOT_SLEEP boot_sleep;
+	} params;
+} MLAN_PACK_END HostCmd_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_u8 hdr[4];
+#ifdef SPI_SUPPORT
+    /** Header for interface */
+	t_u16 hdr;
+#endif
+    /** 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;
+
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+#endif /* !_MLAN_FW_H_ */
diff --git a/wlan_sd8897/mlan/mlan_ieee.h b/wlan_sd8897/mlan/mlan_ieee.h
new file mode 100644
index 0000000..4ffb54d
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_ieee.h
@@ -0,0 +1,1918 @@
+/** @file mlan_ieee.h
+ *
+ *  @brief This file contains IEEE information element related
+ *  definitions used in MLAN and MOAL module.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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
+
+/** 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,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	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_IE = VENDOR_SPECIFIC_221,
+	RSN_IE = 48,
+	VS_IE = VENDOR_SPECIFIC_221,
+	WAPI_IE = 68,
+} 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;
+
+/** 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[0];
+} MLAN_PACK_END IEEEtypes_Auth_framebody;
+
+/*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[0];
+} 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[0];
+} MLAN_PACK_END IEEEtypes_Ft_action_request;
+
+/*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_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_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_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
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN    4
+/** AKM Suite length */
+#define AKM_SUITE_LEN    4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT    7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT    6
+/** PMF ORing mask */
+#define PMF_MASK    0x00c0
+#endif
+
+/** wpa_suite_t */
+typedef MLAN_PACK_START struct _wpa_suite_t {
+    /** OUI */
+	t_u8 oui[3];
+    /** tyep */
+	t_u8 type;
+} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t;
+
+/** wpa_suite_ucast_t */
+typedef MLAN_PACK_START struct {
+	/* count */
+	t_u16 count;
+    /** wpa_suite list */
+	wpa_suite list[1];
+} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+
+/** IEEEtypes_Rsn_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t {
+    /** Rsn : Element ID */
+	t_u8 element_id;
+    /** Rsn : Length */
+	t_u8 len;
+    /** Rsn : version */
+	t_u16 version;
+    /** Rsn : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Rsn : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t;
+
+/** IEEEtypes_Wpa_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t {
+    /** Wpa : Element ID */
+	t_u8 element_id;
+    /** Wpa : Length */
+	t_u8 len;
+    /** Wpa : oui */
+	t_u8 oui[4];
+    /** version */
+	t_u16 version;
+    /** Wpa : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Wpa : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Reserved */
+	t_u8 reserved:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aifsn */
+	t_u8 aifsn:4;
+#else
+    /** Aifsn */
+	t_u8 aifsn:4;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn;   /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;		    /**< Ecw */
+	t_u16 tx_op_limit;		      /**< Tx op limit */
+} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t {
+
+    /**
+     * WMM Info IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [7]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [0]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+
+} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t {
+    /**
+     * WMM Parameter IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [24]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [1]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+    /** Reserved */
+	t_u8 reserved;
+
+    /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/** Enumerator for TSPEC direction */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e {
+
+	TSPEC_DIR_UPLINK = 0,
+	TSPEC_DIR_DOWNLINK = 1,
+	/* 2 is a reserved value */
+	TSPEC_DIR_BIDIRECT = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e;
+
+/** Enumerator for TSPEC PSB */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e {
+
+	TSPEC_PSB_LEGACY = 0,
+	TSPEC_PSB_TRIG = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e;
+
+/** Enumerator for TSPEC Ack Policy */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e {
+
+	TSPEC_ACKPOLICY_NORMAL = 0,
+	TSPEC_ACKPOLICY_NOACK = 1,
+	/* 2 is reserved */
+	TSPEC_ACKPOLICY_BLOCKACK = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e;
+
+/** Enumerator for TSPEC Trafffice type */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e {
+
+	TSPEC_TRAFFIC_APERIODIC = 0,
+	TSPEC_TRAFFIC_PERIODIC = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e;
+
+/** Data structure of WMM TSPEC information */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+	t_u8 Schedule:1;
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 AccessPolicy1:1;	/* ! */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+#else
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 AccessPolicy1:1;	/* ! */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 Schedule:1;
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t;
+
+/** Data structure of WMM TSPEC Nominal Size */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+	t_u16 Size:15;		/* ! Nominal size in octets */
+#else
+	t_u16 Size:15;		/* ! Nominal size in octets */
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t;
+
+/** Data structure of WMM TSPEC SBWA */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Whole:3;		/* ! Whole portion */
+	t_u16 Fractional:13;	/* ! Fractional portion */
+#else
+	t_u16 Fractional:13;	/* ! Fractional portion */
+	t_u16 Whole:3;		/* ! Whole portion */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA;
+
+/** Data structure of WMM TSPEC Body */
+typedef MLAN_PACK_START struct {
+
+    /** TS Information */
+	IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo;
+    /** NomMSDU size */
+	IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize;
+    /** MAximum MSDU size */
+	t_u16 MaximumMSDUSize;
+    /** Minimum Service Interval */
+	t_u32 MinServiceInterval;
+    /** Maximum Service Interval */
+	t_u32 MaxServiceInterval;
+    /** Inactivity Interval */
+	t_u32 InactivityInterval;
+    /** Suspension Interval */
+	t_u32 SuspensionInterval;
+    /** Service Start Time */
+	t_u32 ServiceStartTime;
+    /** Minimum Data Rate */
+	t_u32 MinimumDataRate;
+    /** Mean Data Rate */
+	t_u32 MeanDataRate;
+    /** Peak Data Rate */
+	t_u32 PeakDataRate;
+    /** Maximum Burst Size */
+	t_u32 MaxBurstSize;
+    /** Delay Bound */
+	t_u32 DelayBound;
+    /** Minimum Phy Rate */
+	t_u32 MinPHYRate;
+    /** Surplus BA Allowance */
+	IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance;
+    /** Medium Time */
+	t_u16 MediumTime;
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t;
+
+/** Data structure of WMM TSPEC all elements */
+typedef MLAN_PACK_START struct {
+    /** Element ID */
+	t_u8 ElementId;
+    /** Length */
+	t_u8 Len;
+    /** Oui Type */
+	t_u8 OuiType[4];	/* 00:50:f2:02 */
+    /** Ouisubtype */
+	t_u8 OuiSubType;	/* 01 */
+    /** Version */
+	t_u8 Version;
+
+    /** TspecBody */
+	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 {
+
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+    /** Action */
+	IEEEtypes_WMM_Tspec_Action_e action;
+    /** Dialog Token */
+	t_u8 dialogToken;
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t;
+
+/** WMM TSPEC AddTS request structure */
+typedef MLAN_PACK_START struct {
+
+    /** Tspec action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Status Code */
+	t_u8 statusCode;
+    /** tspecIE */
+	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 {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Reason Code */
+	t_u8 reasonCode;
+    /** tspecIE */
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t;
+
+/** union of WMM TSPEC structures */
+typedef MLAN_PACK_START union {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+
+    /** add TS request */
+	IEEEtypes_Action_WMM_AddTsReq_t addTsReq;
+    /** add TS response */
+	IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp;
+    /** Delete TS */
+	IEEEtypes_Action_WMM_DelTs_t delTs;
+
+} MLAN_PACK_END IEEEtypes_Action_WMMAC_t;
+
+/** union of WMM TSPEC & Action category */
+typedef MLAN_PACK_START union {
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+
+    /** wmmAc */
+	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;
+
+/** 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;
+    /** Channel width */
+	t_u8 chan_width;
+    /** Channel center frequency 1 */
+	t_u8 chan_center_freq_1;
+    /** Channel center frequency 2 */
+	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;
+    /** maximum tx power */
+	t_u8 max_tx_power;
+    /** channel center frequency */
+	t_u8 chan_center_freq;
+    /** channel width */
+	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;
+    /** MIMO capability count */
+	t_u8 MU_MIMO_capa_count;
+    /** stream under utilization */
+	t_u8 stream_underutilization;
+    /** VHT 40 util */
+	t_u8 VHT40_util;
+    /** VHT 80 util */
+	t_u8 VHT80_util;
+    /** VHT 160 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;
+    /** AP quiet mode */
+	t_u8 AP_quiet_mode;
+    /** Quiet count */
+	t_u8 quiet_count;
+    /** Quiet period */
+	t_u8 quiet_period;
+    /** Quiet duration */
+	t_u16 quiet_dur;
+    /** Quiet offset */
+	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;
+    /** New channel width */
+	t_u8 new_chan_width;
+    /** New channel center frequency 1 */
+	t_u8 new_chan_center_freq_1;
+    /** New channel center frequency 2 */
+	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;
+
+/** Maximum number of subbands in the IEEEtypes_SupportedChannels_t structure */
+#define WLAN_11H_MAX_SUBBANDS  5
+
+/** Maximum number of DFS channels configured in IEEEtypes_IBSS_DFS_t */
+#define WLAN_11H_MAX_IBSS_DFS_CHANNELS 25
+
+/**  IEEE Power Constraint element (7.3.2.15) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;    /**< IEEE Element ID = 32 */
+	t_u8 len;	    /**< Element length after id and len */
+	t_u8 local_constraint;
+			    /**< Local power constraint applied to 11d
+                             chan info */
+} MLAN_PACK_END IEEEtypes_PowerConstraint_t;
+
+/**  IEEE Power Capability element (7.3.2.16) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;	    /**< IEEE Element ID = 33 */
+	t_u8 len;		    /**< Element length after id and len */
+	t_s8 min_tx_power_capability;
+				    /**< Minimum Transmit power (dBm) */
+	t_s8 max_tx_power_capability;
+				    /**< Maximum Transmit power (dBm) */
+} MLAN_PACK_END IEEEtypes_PowerCapability_t;
+
+/**  IEEE TPC Report element (7.3.2.18) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;/**< IEEE Element ID = 35 */
+	t_u8 len;	/**< Element length after id and len */
+	t_s8 tx_power;	/**< Max power used to transmit the TPC Report frame (dBm) */
+	t_s8 link_margin;
+			/**< Link margin when TPC Request received (dB) */
+} MLAN_PACK_END IEEEtypes_TPCReport_t;
+
+/*  IEEE Supported Channel sub-band description (7.3.2.19) */
+/**
+ *  Sub-band description used in the supported channels element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 start_chan;/**< Starting channel in the subband */
+	t_u8 num_chans;	/**< Number of channels in the subband */
+
+} MLAN_PACK_END IEEEtypes_SupportChan_Subband_t;
+
+/*  IEEE Supported Channel element (7.3.2.19) */
+/**
+ *  Sent in association requests. Details the sub-bands and number
+ *    of channels supported in each subband
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;/**< IEEE Element ID = 36 */
+	t_u8 len;	/**< Element length after id and len */
+
+    /** Configured sub-bands information in the element */
+	IEEEtypes_SupportChan_Subband_t subband[WLAN_11H_MAX_SUBBANDS];
+
+} MLAN_PACK_END IEEEtypes_SupportedChannels_t;
+
+/** default channel switch count */
+#define DEF_CHAN_SWITCH_COUNT       5
+
+/*  IEEE Channel Switch Announcement Element (7.3.2.20) */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a chan switch element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;	/**< IEEE Element ID = 37 */
+	t_u8 len;		/**< Element length after id and len */
+	t_u8 chan_switch_mode;	/**< STA should not transmit any frames if 1 */
+	t_u8 new_channel_num;	/**< Channel # that AP/IBSS is moving to */
+	t_u8 chan_switch_count;	/**< # of TBTTs before channel switch */
+
+} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t;
+
+/** data structure for extended channel switch */
+typedef MLAN_PACK_START struct {
+   /** IEEE element ID = 60 */
+	t_u8 element_id;
+    /** Element length after id and len, set to 4 */
+	t_u8 len;
+    /** STA should not transmit any frames if 1 */
+	t_u8 chan_switch_mode;
+    /** Operate class # that AP/IBSS is moving to */
+	t_u8 new_oper_class;
+    /** Channel # that AP/IBSS is moving to */
+	t_u8 new_channel_num;
+    /** of TBTTs before channel switch */
+	t_u8 chan_switch_count;
+} MLAN_PACK_END IEEEtypes_ExtChanSwitchAnn_t;
+
+/*  IEEE Wide Bandwidth Channel Switch Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a wide bandwidth chan
+ *    switch element.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 194*/
+	IEEEtypes_Header_t ieee_hdr;
+    /** New channel width */
+	t_u8 new_channel_width;
+    /** New channel center frequency 0*/
+	t_u8 new_channel_center_freq0;
+    /** New channel center frequency 1*/
+	t_u8 new_channel_center_freq1;
+} MLAN_PACK_END IEEEtypes_WideBWChanSwitch_t;
+
+/*  IEEE VHT Transmit Power Envelope Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise the max
+ *    TX power in sepeate bandwidth and as a sub element of Channel Switch
+ *    Wrapper IE.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 195*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 tpc_info;		/**< Transmit Power Information>*/
+	t_u8 local_max_tp_20mhz;/**< Local Maximum Transmit Power for 20 MHZ>*/
+	t_u8 local_max_tp_40mhz;/**< Local Maximum Transmit Power for 40 MHZ>*/
+	t_u8 local_max_tp_80mhz;/**< Local Maximum Transmit Power for 80 MHZ>*/
+} MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t;
+
+/*  IEEE Quiet Period Element (7.3.2.23) */
+/**
+ *  Provided in beacons and probe responses.  Indicates times during
+ *    which the STA should not be transmitting data.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a quiet element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;    /**< IEEE Element ID = 40 */
+	t_u8 len;	    /**< Element length after id and len */
+	t_u8 quiet_count;   /**< Number of TBTTs until beacon with the quiet period */
+	t_u8 quiet_period;  /**< Regular quiet period, # of TBTTS between periods */
+	t_u16 quiet_duration;
+			    /**< Duration of the quiet period in TUs */
+	t_u16 quiet_offset; /**< Offset in TUs from the TBTT for the quiet period */
+
+} MLAN_PACK_END IEEEtypes_Quiet_t;
+
+/**
+***  @brief Map octet of the basic measurement report (7.3.2.22.1)
+**/
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+    /**< Reserved */
+	t_u8 rsvd5_7:3;
+    /**< Channel is unmeasured */
+	t_u8 unmeasured:1;
+    /**< Radar detected on channel */
+	t_u8 radar:1;
+    /**< Unidentified signal found on channel */
+	t_u8 unidentified_sig:1;
+    /**< OFDM preamble detected on channel */
+	t_u8 ofdm_preamble:1;
+    /**< At least one valid MPDU received on channel */
+	t_u8 bss:1;
+#else
+    /**< At least one valid MPDU received on channel */
+	t_u8 bss:1;
+    /**< OFDM preamble detected on channel */
+	t_u8 ofdm_preamble:1;
+    /**< Unidentified signal found on channel */
+	t_u8 unidentified_sig:1;
+    /**< Radar detected on channel */
+	t_u8 radar:1;
+    /**< Channel is unmeasured */
+	t_u8 unmeasured:1;
+    /**< Reserved */
+	t_u8 rsvd5_7:3;
+#endif				/* BIG_ENDIAN_SUPPORT */
+
+} MLAN_PACK_END MeasRptBasicMap_t;
+
+/*  IEEE DFS Channel Map field (7.3.2.24) */
+/**
+ *  Used to list supported channels and provide a octet "map" field which
+ *    contains a basic measurement report for that channel in the
+ *    IEEEtypes_IBSS_DFS_t element
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 channel_number;	/**< Channel number */
+	MeasRptBasicMap_t rpt_map;
+				/**< Basic measurement report for the channel */
+
+} MLAN_PACK_END IEEEtypes_ChannelMap_t;
+
+/*  IEEE IBSS DFS Element (7.3.2.24) */
+/**
+ *  IBSS DFS element included in ad hoc beacons and probe responses.
+ *    Provides information regarding the IBSS DFS Owner as well as the
+ *    originating STAs supported channels and basic measurement results.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;		    /**< IEEE Element ID = 41 */
+	t_u8 len;			    /**< Element length after id and len */
+	t_u8 dfs_owner[MLAN_MAC_ADDR_LENGTH];
+					    /**< DFS Owner STA Address */
+	t_u8 dfs_recovery_interval;	    /**< DFS Recovery time in TBTTs */
+
+    /** Variable length map field, one Map entry for each supported channel */
+	IEEEtypes_ChannelMap_t channel_map[WLAN_11H_MAX_IBSS_DFS_CHANNELS];
+
+} MLAN_PACK_END IEEEtypes_IBSS_DFS_t;
+
+/* 802.11h BSS information kept for each BSSID received in scan results */
+/**
+ * IEEE BSS information needed from scan results for later processing in
+ *    join commands
+ */
+typedef struct {
+	t_u8 sensed_11h;
+		      /**< Capability bit set or 11h IE found in this BSS */
+
+	IEEEtypes_PowerConstraint_t power_constraint;
+						  /**< Power Constraint IE */
+	IEEEtypes_PowerCapability_t power_capability;
+						  /**< Power Capability IE */
+	IEEEtypes_TPCReport_t tpc_report;	  /**< TPC Report IE */
+	IEEEtypes_ChanSwitchAnn_t chan_switch_ann;/**< Channel Switch Announcement IE */
+	IEEEtypes_Quiet_t quiet;		  /**< Quiet IE */
+	IEEEtypes_IBSS_DFS_t ibss_dfs;		  /**< IBSS DFS Element IE */
+
+} wlan_11h_bss_info_t;
+
+/** 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
+
+/** 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;
+
+/**
+ *  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;
+    /** flag to filer only probe response */
+	t_u8 proberesp_only;
+} 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
+
+/**
+ *  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;
+} MLAN_PACK_END wlan_bgscan_cfg;
+#endif /* STA_SUPPORT */
+
+/** 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;
+} MLAN_PACK_END ChanStatistics_t;
+
+#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 */
+	t_u32 channel;
+
+    /** Freq */
+	t_u32 freq;
+
+    /** Beacon period */
+	t_u16 beacon_period;
+
+    /** ATIM window */
+	t_u32 atim_window;
+
+    /** ERP flags */
+	t_u8 erp_flags;
+
+    /** Type of network in use */
+	WLAN_802_11_NETWORK_TYPE network_type_use;
+
+    /** Network infrastructure mode */
+	t_u32 bss_mode;
+
+    /** Network supported rates */
+	WLAN_802_11_RATES supported_rates;
+
+    /** Supported data rates */
+	t_u8 data_rates[WLAN_SUPPORTED_RATES];
+
+    /** Current channel bandwidth
+     *  0 : 20MHZ
+     *  1 : 40MHZ
+     *  2 : 80MHZ
+     *  3 : 160MHZ
+     */
+	t_u8 curr_bandwidth;
+
+    /** Network band.
+     * BAND_B(0x01): 'b' band
+     * BAND_G(0x02): 'g' band
+     * BAND_A(0X04): 'a' band
+     */
+	t_u16 bss_band;
+
+    /** TSF timestamp from the current firmware TSF */
+	t_u64 network_tsf;
+
+    /** TSF value included in the beacon/probe response */
+	t_u8 time_stamp[8];
+
+    /** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+
+    /** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+
+    /** Capability information */
+	IEEEtypes_CapInfo_t cap_info;
+
+    /** WMM IE */
+	IEEEtypes_WmmParameter_t wmm_ie;
+
+    /** 802.11h BSS information */
+	wlan_11h_bss_info_t wlan_11h_bss_info;
+
+    /** Indicate disabling 11n when associate with AP */
+	t_u8 disable_11n;
+    /** 802.11n BSS information */
+    /** HT Capabilities IE */
+	IEEEtypes_HTCap_t *pht_cap;
+    /** HT Capabilities Offset */
+	t_u16 ht_cap_offset;
+    /** HT Information IE */
+	IEEEtypes_HTInfo_t *pht_info;
+    /** HT Information Offset */
+	t_u16 ht_info_offset;
+    /** 20/40 BSS Coexistence IE */
+	IEEEtypes_2040BSSCo_t *pbss_co_2040;
+    /** 20/40 BSS Coexistence Offset */
+	t_u16 bss_co_2040_offset;
+    /** Extended Capabilities IE */
+	IEEEtypes_ExtCap_t *pext_cap;
+    /** Extended Capabilities Offset */
+	t_u16 ext_cap_offset;
+    /** Overlapping BSS Scan Parameters IE */
+	IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param;
+    /** Overlapping BSS Scan Parameters Offset */
+	t_u16 overlap_bss_offset;
+
+    /** VHT Capabilities IE */
+	IEEEtypes_VHTCap_t *pvht_cap;
+    /** VHT Capabilities IE offset */
+	t_u16 vht_cap_offset;
+    /** VHT Operations IE */
+	IEEEtypes_VHTOprat_t *pvht_oprat;
+    /** VHT Operations IE offset */
+	t_u16 vht_oprat_offset;
+    /** VHT Transmit Power Envelope IE */
+	IEEEtypes_VHTtxpower_t *pvht_txpower;
+    /** VHT Transmit Power Envelope IE offset */
+	t_u16 vht_txpower_offset;
+    /** Extended Power Constraint IE */
+	IEEEtypes_ExtPwerCons_t *pext_pwer;
+    /** Extended Power Constraint IE offset */
+	t_u16 ext_pwer_offset;
+    /** Extended BSS Load IE  */
+	IEEEtypes_ExtBSSload_t *pext_bssload;
+    /** Extended BSS Load IE offset */
+	t_u16 ext_bssload_offset;
+    /** Quiet Channel IE */
+	IEEEtypes_QuietChan_t *pquiet_chan;
+    /** Quiet Channel IE offset */
+	t_u16 quiet_chan_offset;
+    /** Operating Mode Notification IE */
+	IEEEtypes_OperModeNtf_t *poper_mode;
+    /** Operating Mode Notification IE offset */
+	t_u16 oper_mode_offset;
+
+#ifdef STA_SUPPORT
+    /** Country information set */
+	IEEEtypes_CountryInfoFullSet_t country_info;
+#endif				/* STA_SUPPORT */
+
+    /** WPA IE */
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+    /** WPA IE offset in the beacon buffer */
+	t_u16 wpa_offset;
+    /** RSN IE */
+	IEEEtypes_Generic_t *prsn_ie;
+    /** RSN IE offset in the beacon buffer */
+	t_u16 rsn_offset;
+#ifdef STA_SUPPORT
+    /** WAPI IE */
+	IEEEtypes_Generic_t *pwapi_ie;
+    /** WAPI IE offset in the beacon buffer */
+	t_u16 wapi_offset;
+#endif
+	/* Hotspot 2.0 OSEN AKM  IE */
+	IEEEtypes_Generic_t *posen_ie;
+    /** osen IE offset in the beacon buffer */
+	t_u16 osen_offset;
+	/* Mobility domain IE */
+	IEEEtypes_MobilityDomain_t *pmd_ie;
+	/** Mobility domain IE offset in the beacon buffer */
+	t_u16 md_offset;
+
+    /** Pointer to the returned scan response */
+	t_u8 *pbeacon_buf;
+    /** Length of the stored scan response */
+	t_u32 beacon_buf_size;
+    /** Max allocated size for updated scan response */
+	t_u32 beacon_buf_size_max;
+
+} BSSDescriptor_t, *pBSSDescriptor_t;
+
+/**
+ *  Type definitions for TCLAS element
+ */
+#define TCLAS_CLASSIFIER_TYPE_4      4
+
+/**
+ *  IEEE TCLAS Classifier Type 4
+ *
+ *  Type definition for Classifier Type 4 in TCLAS element
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_IPv4_t {
+    /** Version */
+	t_u8 version;
+    /** Source IP address */
+	t_u8 source_ip_addr[4];
+    /** Dest IP address */
+	t_u8 dest_ip_addr[4];
+    /** Source port */
+	t_u8 source_port[2];
+    /** Dest port */
+	t_u8 dest_port[2];
+    /** DSCP value */
+	t_u8 dscp;
+    /** Protocol value */
+	t_u8 protocol;
+    /** Reserved */
+	t_u8 reserved;
+} MLAN_PACK_END IEEEtypes_TCLAS_IPv4_t;
+
+/**
+ *  IEEE TCLAS base
+ *
+ *  Type definition for common parameters for every
+ *    classifier type
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_Base_t {
+    /** Element id */
+	t_u8 element_id;
+    /** Element len */
+	t_u8 element_len;
+    /** User priority */
+	t_u8 user_priority;
+    /** Classifier type */
+	t_u8 classifier_type;
+    /** Classifier mask */
+	t_u8 classifier_mask;
+} MLAN_PACK_END IEEEtypes_TCLAS_Base_t;
+
+/**
+ *  IEEE TCLAS element
+ *
+ *  Type definition for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_t {
+    /** Base structure for TCLAS */
+	IEEEtypes_TCLAS_Base_t tclas_base;
+
+	union MLAN_PACK_START {
+	/** Classifier type 4 */
+		IEEEtypes_TCLAS_IPv4_t ipv4;
+	} MLAN_PACK_END classifier;
+} MLAN_PACK_END IEEEtypes_TCLAS_t;
+
+/**
+ *  TCLAS element TLV
+ *
+ *  Structure that defines TLV for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _tclasElemen_tlv {
+    /** Type */
+	t_u16 type;
+    /** Length of TLV */
+	t_u16 len;
+    /** Tclas Ie */
+	IEEEtypes_TCLAS_t tclas_ie;
+} MLAN_PACK_END tclas_element_tlv_t;
+
+#endif /* !_MLAN_IEEE_H_ */
diff --git a/wlan_sd8897/mlan/mlan_init.c b/wlan_sd8897/mlan/mlan_init.c
new file mode 100644
index 0000000..61d23db
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_init.c
@@ -0,0 +1,1658 @@
+/** @file mlan_init.c
+ *
+ *  @brief This file contains the initialization for FW
+ *  and HW.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.h"
+
+/********************************************************
+			Global Variables
+********************************************************/
+extern mlan_operations *mlan_ops[];
+/*******************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief This function adds a BSS priority table
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_add_bsspriotbl(pmlan_private priv)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_bssprio_node *pbssprio = MNULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	status = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						  sizeof(mlan_bssprio_node),
+						  MLAN_MEM_DEF,
+						  (t_u8 **)&pbssprio);
+	if (status) {
+		PRINTM(MERROR, "Failed to allocate bsspriotbl\n");
+		LEAVE();
+		return status;
+	}
+
+	pbssprio->priv = priv;
+
+	util_init_list((pmlan_linked_list)pbssprio);
+
+	if (!pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur)
+		pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur
+			= pbssprio;
+
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &pmadapter->bssprio_tbl[priv->bss_priority].
+			       bssprio_head, (pmlan_linked_list)pbssprio,
+			       pmadapter->callbacks.moal_spin_lock,
+			       pmadapter->callbacks.moal_spin_unlock);
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function deletes the BSS priority table
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         N/A
+ */
+static t_void
+wlan_delete_bsspriotbl(pmlan_private priv)
+{
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_bssprio_node *pbssprio_node = MNULL, *ptmp_node = MNULL, **ppcur =
+		MNULL;
+	pmlan_list_head phead;
+
+	ENTER();
+
+	for (i = 0; i < pmadapter->priv_num; ++i) {
+		phead = &pmadapter->bssprio_tbl[i].bssprio_head;
+		ppcur = &pmadapter->bssprio_tbl[i].bssprio_cur;
+		PRINTM(MINFO,
+		       "Delete BSS priority table, index = %d, i = %d, phead = %p, pcur = %p\n",
+		       priv->bss_index, i, phead, *ppcur);
+		if (*ppcur) {
+			pbssprio_node =
+				(mlan_bssprio_node *)util_peek_list(pmadapter->
+								    pmoal_handle,
+								    phead,
+								    pmadapter->
+								    callbacks.
+								    moal_spin_lock,
+								    pmadapter->
+								    callbacks.
+								    moal_spin_unlock);
+			while (pbssprio_node &&
+			       ((pmlan_list_head)pbssprio_node != phead)) {
+				ptmp_node = pbssprio_node->pnext;
+				if (pbssprio_node->priv == priv) {
+					PRINTM(MINFO,
+					       "Delete node, pnode = %p, pnext = %p\n",
+					       pbssprio_node, ptmp_node);
+					util_unlink_list(pmadapter->
+							 pmoal_handle, phead,
+							 (pmlan_linked_list)
+							 pbssprio_node,
+							 pmadapter->callbacks.
+							 moal_spin_lock,
+							 pmadapter->callbacks.
+							 moal_spin_unlock);
+					pmadapter->callbacks.
+						moal_mfree(pmadapter->
+							   pmoal_handle,
+							   (t_u8 *)
+							   pbssprio_node);
+				}
+				pbssprio_node = ptmp_node;
+			}
+			*ppcur = (mlan_bssprio_node *)phead;
+		}
+	}
+
+	LEAVE();
+}
+
+/********************************************************
+			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
+	t_u32 max_mp_regs = pmadapter->psdio_device->reg->max_mp_regs;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	t_u32 mp_tx_aggr_buf_size =
+		pmadapter->psdio_device->mp_tx_aggr_buf_size;
+	t_u32 mp_rx_aggr_buf_size =
+		pmadapter->psdio_device->mp_rx_aggr_buf_size;
+#endif
+
+	ENTER();
+
+#ifdef STA_SUPPORT
+	/* Allocate buffer to store the BSSID list */
+	buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST;
+	if (pmadapter->callbacks.moal_vmalloc &&
+	    pmadapter->callbacks.moal_vfree)
+		ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle,
+							buf_size,
+							(t_u8 **)
+							&ptemp_scan_table);
+	else
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       buf_size, MLAN_MEM_DEF,
+						       (t_u8 **)
+						       &ptemp_scan_table);
+	if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) {
+		PRINTM(MERROR, "Failed to allocate scan table\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->pscan_table = ptemp_scan_table;
+
+	if (pmadapter->fixed_beacon_buffer)
+		beacon_buffer_size = MAX_SCAN_BEACON_BUFFER;
+	else
+		beacon_buffer_size = DEFAULT_SCAN_BEACON_BUFFER;
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       beacon_buffer_size, MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->bcn_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->bcn_buf) {
+		PRINTM(MERROR, "Failed to allocate bcn buf\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->bcn_buf_size = beacon_buffer_size;
+
+	pmadapter->num_in_chan_stats = sizeof(chan_2g);
+	pmadapter->num_in_chan_stats += sizeof(chan_5g);
+	buf_size = sizeof(ChanStatistics_t) * pmadapter->num_in_chan_stats;
+	if (pmadapter->callbacks.moal_vmalloc &&
+	    pmadapter->callbacks.moal_vfree)
+		ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle,
+							buf_size,
+							(t_u8 **)&pmadapter->
+							pchan_stats);
+	else
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       buf_size, MLAN_MEM_DEF,
+						       (t_u8 **)&pmadapter->
+						       pchan_stats);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pchan_stats) {
+		PRINTM(MERROR, "Failed to allocate channel statistics\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+#endif
+
+	/* Allocate command buffer */
+	ret = wlan_alloc_cmd_buffer(pmadapter);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to allocate command buffer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       max_mp_regs + DMA_ALIGNMENT,
+					       MLAN_MEM_DEF | MLAN_MEM_DMA,
+					       (t_u8 **)&pmadapter->
+					       mp_regs_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mp_regs_buf) {
+		PRINTM(MERROR, "Failed to allocate mp_regs_buf\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->mp_regs =
+		(t_u8 *)ALIGN_ADDR(pmadapter->mp_regs_buf, DMA_ALIGNMENT);
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       MAX_SUPPORT_AMSDU_SIZE,
+					       MLAN_MEM_DEF | MLAN_MEM_DMA,
+					       (t_u8 **)&pmadapter->rx_buffer);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->rx_buffer) {
+		PRINTM(MERROR, "Failed to allocate receive buffer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->rx_buf =
+		(t_u8 *)ALIGN_ADDR(pmadapter->rx_buffer, DMA_ALIGNMENT);
+#endif
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	pmadapter->max_sp_tx_size = MAX_SUPPORT_AMSDU_SIZE;
+	pmadapter->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->mpa_buf_size =
+			SDIO_MP_DBG_NUM *
+			pmadapter->psdio_device->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->
+								mpa_buf_size,
+								(t_u8 **)
+								&pmadapter->
+								mpa_buf);
+		else
+			ret = pmadapter->callbacks.moal_malloc(pmadapter->
+							       pmoal_handle,
+							       pmadapter->
+							       mpa_buf_size,
+							       MLAN_MEM_DEF,
+							       (t_u8 **)
+							       &pmadapter->
+							       mpa_buf);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->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);
+
+	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;
+
+	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->adhoc_aes_enabled = 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->curr_bss_params, 0,
+	       sizeof(priv->curr_bss_params));
+	priv->listen_interval = MLAN_DEFAULT_LISTEN_INTERVAL;
+
+	memset(pmadapter, &priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf));
+	priv->assoc_rsp_size = 0;
+
+	wlan_11d_priv_init(priv);
+	wlan_11h_priv_init(priv);
+
+#ifdef UAP_SUPPORT
+	priv->uap_bss_started = MFALSE;
+	priv->uap_host_based = MFALSE;
+	memset(pmadapter, &priv->uap_state_chan_cb, 0,
+	       sizeof(priv->uap_state_chan_cb));
+#endif
+#if defined(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->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+	priv->atim_window = 0;
+	priv->adhoc_state = ADHOC_IDLE;
+	priv->tx_power_level = 0;
+	priv->max_tx_power_level = 0;
+	priv->min_tx_power_level = 0;
+	priv->tx_rate = 0;
+	priv->rxpd_rate_info = 0;
+	/* refer to V15 CMD_TX_RATE_QUERY */
+	priv->rxpd_vhtinfo = 0;
+	priv->rxpd_rate = 0;
+	priv->rate_bitmap = 0;
+	priv->data_rssi_last = 0;
+	priv->data_rssi_avg = 0;
+	priv->data_nf_avg = 0;
+	priv->data_nf_last = 0;
+	priv->bcn_rssi_last = 0;
+	priv->bcn_rssi_avg = 0;
+	priv->bcn_nf_avg = 0;
+	priv->bcn_nf_last = 0;
+
+	priv->sec_info.ewpa_enabled = MFALSE;
+	priv->sec_info.wpa_enabled = MFALSE;
+	priv->sec_info.wpa2_enabled = MFALSE;
+	memset(pmadapter, &priv->wpa_ie, 0, sizeof(priv->wpa_ie));
+	memset(pmadapter, &priv->aes_key, 0, sizeof(priv->aes_key));
+	priv->wpa_ie_len = 0;
+	priv->wpa_is_gtk_set = MFALSE;
+#if defined(STA_SUPPORT)
+	priv->pmfcfg.mfpc = 0;
+	priv->pmfcfg.mfpr = 0;
+#endif
+	priv->sec_info.wapi_enabled = MFALSE;
+	priv->wapi_ie_len = 0;
+	priv->sec_info.wapi_key_on = MFALSE;
+
+	memset(pmadapter, &priv->wps, 0, sizeof(priv->wps));
+	memset(pmadapter, &priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
+	priv->gen_ie_buf_len = 0;
+#endif /* STA_SUPPORT */
+	priv->wmm_required = MTRUE;
+	priv->wmm_enabled = MFALSE;
+	priv->wmm_qosinfo = 0;
+	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;
+	priv->tdls_idle_time = TDLS_IDLE_TIMEOUT;
+	priv->txaggrctrl = MTRUE;
+#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(priv->adapter, &priv->def_ext_cap, &priv->ext_cap,
+	       sizeof(priv->ext_cap));
+#endif /* STA_SUPPORT */
+
+	for (i = 0; i < MAX_NUM_TID; i++)
+		priv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+	priv->addba_reject[6] = ADDBA_RSP_STATUS_REJECT;
+	priv->addba_reject[7] = ADDBA_RSP_STATUS_REJECT;
+	memcpy(priv->adapter, priv->ibss_addba_reject, priv->addba_reject,
+	       sizeof(priv->addba_reject));
+	priv->max_amsdu = 0;
+#ifdef STA_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+		priv->add_ba_param.tx_win_size =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_sta_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 =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_wfd_txrxwinsize;
+		priv->add_ba_param.rx_win_size =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_wfd_txrxwinsize;
+	}
+#endif
+#ifdef UAP_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		priv->add_ba_param.tx_win_size =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_uap_txwinsize;
+		priv->add_ba_param.rx_win_size =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_uap_rxwinsize;
+		priv->aggr_prio_tbl[6].ampdu_user =
+			priv->aggr_prio_tbl[7].ampdu_user =
+			BA_STREAM_NOT_ALLOWED;
+	}
+#endif
+	priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
+
+	priv->port_ctrl_mode = MTRUE;
+
+	priv->port_open = MFALSE;
+
+	priv->intf_hr_len = INTF_HEADER_LEN;
+	ret = wlan_add_bsspriotbl(priv);
+
+	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;
+
+	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
+
+	pmadapter->int_mode = pmadapter->init_para.int_mode;
+	pmadapter->gpio_pin = pmadapter->init_para.gpio_pin;
+
+#if defined(STA_SUPPORT)
+	pmadapter->pwarm_reset_ioctl_req = MNULL;
+#endif
+	pmadapter->cmd_sent = MFALSE;
+	pmadapter->data_sent = MTRUE;
+	pmadapter->mp_rd_bitmap = 0;
+	pmadapter->mp_wr_bitmap = 0;
+	if (pmadapter->psdio_device->supports_sdio_new_mode) {
+		pmadapter->curr_rd_port = 0;
+		pmadapter->curr_wr_port = 0;
+	} else {
+		pmadapter->curr_rd_port = 1;
+		pmadapter->curr_wr_port = 1;
+	}
+	pmadapter->mp_data_port_mask =
+		pmadapter->psdio_device->reg->data_port_mask;
+	pmadapter->mp_invalid_update = 0;
+	memset(pmadapter, pmadapter->mp_update, 0,
+	       sizeof(pmadapter->mp_update));
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	pmadapter->mpa_tx.buf_len = 0;
+	pmadapter->mpa_tx.pkt_cnt = 0;
+	pmadapter->mpa_tx.start_port = 0;
+
+	if (!pmadapter->init_para.mpa_tx_cfg)
+		pmadapter->mpa_tx.enabled = MFALSE;
+	else if (pmadapter->init_para.mpa_tx_cfg == MLAN_INIT_PARA_DISABLED)
+		pmadapter->mpa_tx.enabled = MFALSE;
+	else
+		pmadapter->mpa_tx.enabled = MTRUE;
+	pmadapter->mpa_tx.pkt_aggr_limit =
+		pmadapter->psdio_device->mp_aggr_pkt_limit;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	pmadapter->mpa_rx.buf_len = 0;
+	pmadapter->mpa_rx.pkt_cnt = 0;
+	pmadapter->mpa_rx.start_port = 0;
+
+	if (!pmadapter->init_para.mpa_rx_cfg)
+		pmadapter->mpa_rx.enabled = MFALSE;
+	else if (pmadapter->init_para.mpa_rx_cfg == MLAN_INIT_PARA_DISABLED)
+		pmadapter->mpa_rx.enabled = MFALSE;
+	else
+		pmadapter->mpa_rx.enabled = MTRUE;
+	pmadapter->mpa_rx.pkt_aggr_limit =
+		pmadapter->psdio_device->mp_aggr_pkt_limit;
+
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+	pmadapter->rx_pkts_queued = 0;
+	pmadapter->cmd_resp_received = MFALSE;
+	pmadapter->event_received = MFALSE;
+	pmadapter->data_received = MFALSE;
+
+	pmadapter->cmd_timer_is_set = MFALSE;
+
+	/* PnP and power profile */
+	pmadapter->surprise_removed = MFALSE;
+
+	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;
+
+	pmadapter->num_in_scan_table = 0;
+	memset(pmadapter, pmadapter->pscan_table, 0,
+	       (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
+	pmadapter->active_scan_triggered = MFALSE;
+	pmadapter->ext_scan = pmadapter->psdio_device->ext_scan;
+	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->fw_wakeup_method = WAKEUP_FW_UNCHANGED;
+	pmadapter->fw_wakeup_gpio_pin = DEF_WAKEUP_FW_GPIO;
+
+	pmadapter->is_deep_sleep = MFALSE;
+	pmadapter->idle_time = DEEP_SLEEP_IDLE_TIME;
+	if (!pmadapter->init_para.auto_ds)
+		pmadapter->init_auto_ds = DEFAULT_AUTO_DS_MODE;
+	else if (pmadapter->init_para.auto_ds == MLAN_INIT_PARA_DISABLED)
+		pmadapter->init_auto_ds = MFALSE;
+	else
+		pmadapter->init_auto_ds = MTRUE;
+
+	pmadapter->delay_null_pkt = MFALSE;
+	pmadapter->delay_to_ps = DELAY_TO_PS_DEFAULT;
+	pmadapter->enhanced_ps_mode = PS_MODE_AUTO;
+
+	pmadapter->gen_null_pkt = MFALSE;	/* Disable NULL Pkt generation-default */
+	pmadapter->pps_uapsd_mode = MFALSE;	/* Disable pps/uapsd mode -default */
+
+	pmadapter->pm_wakeup_card_req = MFALSE;
+
+	pmadapter->pm_wakeup_fw_try = MFALSE;
+
+	if (!pmadapter->init_para.max_tx_buf)
+		pmadapter->max_tx_buf_size =
+			pmadapter->psdio_device->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;
+
+	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->adhoc_11n_enabled = MFALSE;
+	pmadapter->tdls_status = TDLS_NOT_SETUP;
+#endif /* STA_SUPPORT */
+
+	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);
+	}
+	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->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(pmadapter, pmadapter->country_code, MRVDRV_DEFAULT_COUNTRY_CODE,
+	       COUNTRY_CODE_LEN);
+	pmadapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
+	pmadapter->adhoc_awake_period = 0;
+#ifdef STA_SUPPORT
+	memset(pmadapter, &pmadapter->arp_filter, 0,
+	       sizeof(pmadapter->arp_filter));
+	pmadapter->arp_filter_size = 0;
+#endif /* STA_SUPPORT */
+
+	pmadapter->mc_status = MFALSE;
+
+	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(IN 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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pmlan_lock)
+	    != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pint_lock)
+	    != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	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;
+	}
+
+	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(IN 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 (pmadapter->pint_lock)
+		pcb->moal_free_lock(pmadapter->pmoal_handle,
+				    pmadapter->pint_lock);
+	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);
+
+	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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	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;
+	}
+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(IN pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	if (pmadapter->pmlan_cmd_timer)
+		pcb->moal_free_timer(pmadapter->pmoal_handle,
+				     pmadapter->pmlan_cmd_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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	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
+	}
+#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;
+	}
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode == MTRUE) {
+		pmadapter->hw_status = WlanHardwareStatusInitializing;
+		ret = wlan_get_hw_spec_complete(pmadapter);
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function udpate hw spec info to each interface
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+void
+wlan_update_hw_spec(IN 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;
+			}
+		}
+		if ((pmadapter->fw_bands & BAND_AN)
+			) {
+			pmadapter->adhoc_start_band = BAND_A | BAND_AN;
+			pmadapter->adhoc_11n_enabled = MTRUE;
+		} else
+			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_GN)
+		) {
+		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i])
+				pmadapter->priv[i]->adhoc_channel =
+					DEFAULT_AD_HOC_CHANNEL;
+		}
+		pmadapter->adhoc_11n_enabled = MTRUE;
+	} 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 =
+					DEFAULT_11N_TX_BF_CAP;
+		}
+	}
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i])
+			wlan_update_11ac_cap(pmadapter->priv[i]);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief  This function initializes firmware for interface
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_init_priv_fw(IN 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;
+	} 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;
+	ENTER();
+
+	if (!pmadapter) {
+		PRINTM(MERROR, "The adapter is NULL\n");
+		LEAVE();
+		return;
+	}
+
+	wlan_cancel_all_pending_cmd(pmadapter);
+	/* 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;
+	}
+#ifdef STA_SUPPORT
+	PRINTM(MINFO, "Free ScanTable\n");
+	if (pmadapter->pscan_table) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pscan_table);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pscan_table);
+		pmadapter->pscan_table = MNULL;
+	}
+	if (pmadapter->pchan_stats) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pchan_stats);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pchan_stats);
+		pmadapter->pchan_stats = MNULL;
+	}
+	if (pmadapter->bcn_buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->bcn_buf);
+		pmadapter->bcn_buf = MNULL;
+	}
+#endif
+
+	wlan_11h_cleanup(pmadapter);
+
+	if (pmadapter->mp_regs_buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mp_regs_buf);
+		pmadapter->mp_regs_buf = MNULL;
+		pmadapter->mp_regs = MNULL;
+	}
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+	if (pmadapter->rx_buffer) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->rx_buffer);
+		pmadapter->rx_buffer = MNULL;
+		pmadapter->rx_buf = MNULL;
+	}
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	wlan_free_sdio_mpa_buffers(pmadapter);
+#ifdef DEBUG_LEVEL1
+	if (pmadapter->mpa_buf) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->mpa_buf);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->mpa_buf);
+		pmadapter->mpa_buf = MNULL;
+		pmadapter->mpa_buf_size = 0;
+	}
+#endif
+#endif
+	wlan_free_mlan_buffer(pmadapter, pmadapter->psleep_cfm);
+	pmadapter->psleep_cfm = MNULL;
+
+	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 */
+
+	wlan_delete_station_list(pmpriv);
+	LEAVE();
+}
+
+/**
+ *  @brief This function init interface based on pmadapter's bss_attr table
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+mlan_status
+wlan_init_interface(IN 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(pmadapter,
+					       &pmadapter->priv[i]->ops,
+					       mlan_ops[j],
+					       sizeof(mlan_operations));
+				}
+			}
+		}
+	}
+	/*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(IN pmlan_adapter pmadapter)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_hw_info info;
+	mlan_bss_tbl bss_tbl;
+
+	ENTER();
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode != MTRUE) {
+#endif
+		/* Check if hardware is ready */
+		if (pmadapter->hw_status != WlanHardwareStatusInitializing)
+			status = MLAN_STATUS_FAILURE;
+		else {
+			memset(pmadapter, &info, 0, sizeof(info));
+			info.fw_cap = pmadapter->fw_cap_info;
+			memset(pmadapter, &bss_tbl, 0, sizeof(bss_tbl));
+			memcpy(pmadapter, bss_tbl.bss_attr, pmadapter->bss_attr,
+			       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(pmadapter, pmadapter->bss_attr, bss_tbl.bss_attr,
+			       sizeof(mlan_bss_tbl));
+#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(IN pmlan_adapter pmadapter)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	/* Check if hardware is ready */
+	if (pmadapter->hw_status != WlanHardwareStatusReady)
+		status = MLAN_STATUS_FAILURE;
+
+	/* Reconfigure wmm parameter */
+	if (status == MLAN_STATUS_SUCCESS) {
+		wlan_prepare_cmd(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA),
+				 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(IN 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_sd8897/mlan/mlan_init.h b/wlan_sd8897/mlan/mlan_init.h
new file mode 100644
index 0000000..4182cf2
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_init.h
@@ -0,0 +1,90 @@
+/** @file mlan_init.h
+ *
+ *  @brief This file defines the FW initialization data
+ *  structures.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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	620
+/** 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 CMD7 */
+#define FW_CMD_7                0x00000007
+
+/** 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;
+} MLAN_PACK_END FWSyncHeader;
+
+#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); \
+	}
+#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_sd8897/mlan/mlan_ioctl.h b/wlan_sd8897/mlan/mlan_ioctl.h
new file mode 100644
index 0000000..394fe26
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_ioctl.h
@@ -0,0 +1,4334 @@
+/** @file mlan_ioctl.h
+ *
+ *  @brief This file declares the IOCTL data structures and APIs.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_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
+
+	/* 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,
+
+	/* 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,
+
+	/* 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_FW_WAKEUP_METHOD = 0x00090007,
+	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,
+
+	/* 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,
+#if defined(DFS_TESTING_SUPPORT)
+	MLAN_OID_11H_DFS_TESTING = 0x00110003,
+#endif
+	MLAN_OID_11H_CHAN_REPORT_REQUEST = 0x00110004,
+	MLAN_OID_11H_CHAN_SWITCH_COUNT = 0x00110005,
+#ifdef DFS_TESTING_SUPPORT
+	MLAN_OID_11H_CHAN_NOP_INFO = 0x00110006,
+#endif
+
+	/* 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,
+
+	/* 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,
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	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_COALESCING_STATUS = 0x0020000E,
+	MLAN_OID_MISC_CUSTOM_IE = 0x0020000F,
+	MLAN_OID_MISC_TDLS_CONFIG = 0x00200010,
+	MLAN_OID_MISC_NET_MONITOR = 0x00200011,
+	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,
+	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
+	MLAN_OID_MISC_MULTI_CHAN_CFG = 0x00200023,
+	MLAN_OID_MISC_MULTI_CHAN_POLICY = 0x00200024,
+#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,
+#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_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_OPER_CLASS_CHECK = 0x00200049,
+	MLAN_OID_MISC_DRCS_CFG = 0x00200050,
+
+	MLAN_OID_MISC_CWMODE_CTRL = 0x00200051,
+	MLAN_OID_MISC_DYN_BW = 0x00200053,
+	MLAN_OID_MISC_FW_DUMP_EVENT = 0x00200054,
+	MLAN_OID_MISC_ROBUSTCOEX = 0x00200056,
+	MLAN_OID_MISC_CFP_INFO = 0x00200060,
+	MLAN_OID_MISC_BOOT_SLEEP = 0x00200061,
+	MLAN_OID_MISC_ACS = 0x00200063,
+};
+
+/** 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
+};
+
+/** 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
+};
+
+/** Max number of supported rates */
+#define MLAN_SUPPORTED_RATES	32
+
+/** 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
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES      4
+
+/** Default number of probes to send on each channel */
+#define DEFAULT_PROBES  4
+
+/** MAX BG channel */
+#define MAX_BG_CHANNEL 14
+
+/**
+ *  @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;
+    /** 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;
+
+/** tx status event structure */
+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[0]; */
+} 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;
+
+/** 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;
+    /** Ext_scan:  0 disable, 1: enable, 2: enhance scan*/
+	t_u32 ext_scan;
+} 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)
+
+/** mlan_ssid_bssid  data structure for
+ *  MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS
+ */
+typedef struct _mlan_ssid_bssid {
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+    /** index in BSSID list, start from 1 */
+	t_u32 idx;
+    /** Receive signal strength in dBm */
+	t_s32 rssi;
+    /**channel*/
+	t_u16 channel;
+    /**mobility domain value*/
+	t_u16 ft_md;
+    /**ft capability*/
+	t_u8 ft_cap;
+    /**band*/
+	t_u16 bss_band;
+	t_u32 channel_flags;
+} mlan_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
+/** 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   10
+/** 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  300
+/** 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           16
+
+/* 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
+
+/** 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
+
+/** 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;
+
+/** 5G band */
+#define BAND_CONFIG_5G        0x01
+/** 2.4 G band */
+#define BAND_CONFIG_2G        0x00
+/** 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;
+
+} mlan_uap_bss_param;
+
+/** mlan_uap_scan_channels */
+typedef struct _mlan_uap_scan_channels {
+    /** flag for remove nop channel*/
+	t_u8 remove_nop_channel;
+	/** num of removed channel */
+	t_u8 num_remvoed_channel;
+    /** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+    /** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+} mlan_uap_scan_channels;
+
+/** mlan_uap_oper_ctrl */
+typedef struct _mlan_uap_oper_ctrl {
+    /** control value
+      *  0: do nothing,
+      *  2: uap stops and restarts automaticaly
+     */
+	t_u16 ctrl_value;
+    /** channel opt
+      *  1: uap restart on default 2.4G/channel 6
+      *  2: uap restart on the band/channel configured by driver previously
+      *  3: uap restart on the band/channel specified by band_cfg and channel
+	*/
+	t_u16 chan_opt;
+    /** band cfg   0
+      *  0: 20Mhz  2: 40 Mhz  3: 80Mhz
+     */
+	t_u8 band_cfg;
+    /** channel */
+	t_u8 channel;
+} mlan_uap_oper_ctrl;
+
+#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 uap flag for MLAN_OID_BSS_START */
+		t_u8 host_based;
+	/** BSS param for AP mode for MLAN_OID_UAP_BSS_CONFIG */
+		mlan_uap_bss_param bss_config;
+	/** AP Wmm parameters for MLAN_OID_UAP_CFG_WMM_PARAM */
+		wmm_parameter_t ap_wmm_para;
+	/** ap scan channels for MLAN_OID_UAP_SCAN_CHANNELS*/
+		mlan_uap_scan_channels ap_scan_channels;
+	/** ap channel for MLAN_OID_UAP_CHANNEL*/
+		chan_band_info ap_channel;
+	/** ap operation control for MLAN_OID_UAP_OPER_CTRL*/
+		mlan_uap_oper_ctrl ap_oper_ctrl;
+#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
+	} param;
+} mlan_ds_bss, *pmlan_ds_bss;
+
+/*-----------------------------------------------------------------*/
+/** 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,
+};
+
+/** 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;
+    /** Ad-hoc channel bandwidth */
+	t_u32 adhoc_chan_bandwidth;
+    /** 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_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 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
+
+/** filt field param structure */
+struct filt_field_param {
+	/** Operation */
+	t_u8 operation;
+	/** Operand len */
+	t_u8 operand_len;
+	/** offset */
+	t_u16 offset;
+	/** Operand byte stream */
+	t_u8 operand_byte_stream[COALESCE_MAX_BYTESEQ];
+};
+
+/** coalesce rule structure */
+struct coalesce_rule {
+	/** max coalescing delay */
+	t_u16 max_coalescing_delay;
+	/** number of fields */
+	t_u8 num_of_fields;
+	/** packet type */
+	t_u8 pkt_type;
+	struct filt_field_param params[COALESCE_MAX_FILTERS];
+};
+
+/** coalesce configuration structure */
+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
+};
+
+/** Get stats org structure */
+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;
+} mlan_ds_get_stats, *pmlan_ds_get_stats;
+
+/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_uap_stats {
+    /** tkip mic failures */
+	t_u32 tkip_mic_failures;
+    /** ccmp decrypt errors */
+	t_u32 ccmp_decrypt_errors;
+    /** wep undecryptable count */
+	t_u32 wep_undecryptable_count;
+    /** wep icv error count */
+	t_u32 wep_icv_error_count;
+    /** decrypt failure count */
+	t_u32 decrypt_failure_count;
+    /** dot11 multicast tx count */
+	t_u32 mcast_tx_count;
+    /** dot11 failed count */
+	t_u32 failed_count;
+    /** dot11 retry count */
+	t_u32 retry_count;
+    /** dot11 multi retry count */
+	t_u32 multi_retry_count;
+    /** dot11 frame duplicate count */
+	t_u32 frame_dup_count;
+    /** dot11 rts success count */
+	t_u32 rts_success_count;
+    /** dot11 rts failure count */
+	t_u32 rts_failure_count;
+    /** dot11 ack failure count */
+	t_u32 ack_failure_count;
+    /** dot11 rx ragment count */
+	t_u32 rx_fragment_count;
+    /** dot11 mcast rx frame count */
+	t_u32 mcast_rx_frame_count;
+    /** dot11 fcs error count */
+	t_u32 fcs_error_count;
+    /** dot11 tx frame count */
+	t_u32 tx_frame_count;
+    /** dot11 rsna tkip cm invoked */
+	t_u32 rsna_tkip_cm_invoked;
+    /** dot11 rsna 4way handshake failures */
+	t_u32 rsna_4way_hshk_failures;
+} mlan_ds_uap_stats, *pmlan_ds_uap_stats;
+
+/** Mask of last beacon RSSI */
+#define BCN_RSSI_LAST_MASK              0x00000001
+/** Mask of average beacon RSSI */
+#define BCN_RSSI_AVG_MASK               0x00000002
+/** Mask of last data RSSI */
+#define DATA_RSSI_LAST_MASK             0x00000004
+/** Mask of average data RSSI */
+#define DATA_RSSI_AVG_MASK              0x00000008
+/** Mask of last beacon SNR */
+#define BCN_SNR_LAST_MASK               0x00000010
+/** Mask of average beacon SNR */
+#define BCN_SNR_AVG_MASK                0x00000020
+/** Mask of last data SNR */
+#define DATA_SNR_LAST_MASK              0x00000040
+/** Mask of average data SNR */
+#define DATA_SNR_AVG_MASK               0x00000080
+/** Mask of last beacon NF */
+#define BCN_NF_LAST_MASK                0x00000100
+/** Mask of average beacon NF */
+#define BCN_NF_AVG_MASK                 0x00000200
+/** Mask of last data NF */
+#define DATA_NF_LAST_MASK               0x00000400
+/** Mask of average data NF */
+#define DATA_NF_AVG_MASK                0x00000800
+/** Mask of all RSSI_INFO */
+#define ALL_RSSI_INFO_MASK              0x00000fff
+#define MAX_PATH_NUM                    3
+/** path A */
+#define PATH_A							0x01
+/** path B */
+#define PATH_B							0x02
+/** path AB */
+#define PATH_AB							0x03
+/** ALL the path */
+#define PATH_ALL						0
+/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */
+typedef struct _mlan_ds_get_signal {
+    /** Selector of get operation */
+	/*
+	 * Bit0:  Last Beacon RSSI,  Bit1:  Average Beacon RSSI,
+	 * Bit2:  Last Data RSSI,    Bit3:  Average Data RSSI,
+	 * Bit4:  Last Beacon SNR,   Bit5:  Average Beacon SNR,
+	 * Bit6:  Last Data SNR,     Bit7:  Average Data SNR,
+	 * Bit8:  Last Beacon NF,    Bit9:  Average Beacon NF,
+	 * Bit10: Last Data NF,      Bit11: Average Data NF
+	 *
+	 * Bit0: PATH A
+	 * Bit1: PATH B
+	 */
+	t_u16 selector;
+
+    /** RSSI */
+    /** RSSI of last beacon */
+	t_s16 bcn_rssi_last;
+    /** RSSI of beacon average */
+	t_s16 bcn_rssi_avg;
+    /** RSSI of last data packet */
+	t_s16 data_rssi_last;
+    /** RSSI of data packet average */
+	t_s16 data_rssi_avg;
+
+    /** SNR */
+    /** SNR of last beacon */
+	t_s16 bcn_snr_last;
+    /** SNR of beacon average */
+	t_s16 bcn_snr_avg;
+    /** SNR of last data packet */
+	t_s16 data_snr_last;
+    /** SNR of data packet average */
+	t_s16 data_snr_avg;
+
+    /** NF */
+    /** NF of last beacon */
+	t_s16 bcn_nf_last;
+    /** NF of beacon average */
+	t_s16 bcn_nf_avg;
+    /** NF of last data packet */
+	t_s16 data_nf_last;
+    /** NF of data packet average */
+	t_s16 data_nf_avg;
+} mlan_ds_get_signal, *pmlan_ds_get_signal;
+
+/** bit for 2.4 G antenna diversity */
+#define ANT_DIVERSITY_2G   MBIT(3)
+/** bit for 5 G antenna diversity */
+#define ANT_DIVERSITY_5G   MBIT(7)
+
+/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */
+typedef struct _mlan_fw_info {
+    /** Firmware version */
+	t_u32 fw_ver;
+    /** MAC address */
+	mlan_802_11_mac_addr mac_addr;
+    /** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+    /** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+    /** user's MCS setting */
+	t_u8 usr_dev_mcs_support;
+    /** 802.11ac device capabilities */
+	t_u32 hw_dot_11ac_dev_cap;
+    /** 802.11ac device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11ac_dev_cap_bg;
+    /** 802.11ac device Capabilities for 5GHz */
+	t_u32 usr_dot_11ac_dev_cap_a;
+    /** 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_u8 fw_bands;
+	/** region code */
+	t_u16 region_code;
+    /** 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;
+} mlan_fw_info, *pmlan_fw_info;
+
+/** Version string buffer length */
+#define MLAN_MAX_VER_STR_LEN    128
+
+/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */
+typedef struct _mlan_ver_ext {
+    /** Selected version string */
+	t_u32 version_str_sel;
+    /** Version string */
+	char version_str[MLAN_MAX_VER_STR_LEN];
+} mlan_ver_ext, *pmlan_ver_ext;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+    /** Extended Capabilities value */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit77: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 MaxAMSDU:2;	/* bit 63-bit 64 */
+	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 MaxAMSDU:2;	/* bit 63-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 rsvdBit77:1;	/* bit 77 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#endif
+
+/** ExtCap : TDLS prohibited */
+#define IS_EXTCAP_TDLS_PROHIBITED(ext_cap) (ext_cap.TDLSProhibited)
+/** ExtCap : TDLS channel switch prohibited */
+#define IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ext_cap) (ext_cap.TDLSChlSwitchProhib)
+
+/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */
+typedef struct _mlan_bss_info {
+    /** BSS mode */
+	t_u32 bss_mode;
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** Table index */
+	t_u32 scan_table_idx;
+    /** Channel */
+	t_u32 bss_chan;
+    /** Band */
+	t_u8 bss_band;
+    /** Region code */
+	t_u32 region_code;
+    /** Connection status */
+	t_u32 media_connected;
+    /** Radio on */
+	t_u32 radio_on;
+    /** Max power level in dBm */
+	t_s32 max_power_level;
+    /** Min power level in dBm */
+	t_s32 min_power_level;
+    /** Adhoc state */
+	t_u32 adhoc_state;
+    /** NF of last beacon */
+	t_s32 bcn_nf_last;
+    /** wep status */
+	t_u32 wep_status;
+    /** scan block status */
+	t_u8 scan_block;
+     /** Host Sleep configured flag */
+	t_u32 is_hs_configured;
+    /** Deep Sleep flag */
+	t_u32 is_deep_sleep;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+#ifdef STA_SUPPORT
+    /** Capability Info */
+	t_u16 capability_info;
+    /** Beacon Interval */
+	t_u16 beacon_interval;
+    /** Listen Interval */
+	t_u16 listen_interval;
+    /** Association Id  */
+	t_u16 assoc_id;
+    /** AP/Peer supported rates */
+	t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES];
+    /** extend capability for AP */
+	ExtCap_t ext_cap;
+#endif				/* STA_SUPPORT */
+    /** Mobility Domain ID */
+	t_u16 mdid;
+    /** FT Capability policy */
+	t_u8 ft_cap;
+    /** 11h active */
+	t_bool is_11h_active;
+    /** dfs check channel */
+	t_u8 dfs_check_channel;
+} mlan_bss_info, *pmlan_bss_info;
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID     8
+
+/** Max RX Win size */
+#define MAX_RX_WINSIZE  64
+
+/** rx_reorder_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** TA */
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+    /** Start window */
+	t_u32 start_win;
+    /** Window size */
+	t_u32 win_size;
+    /** amsdu flag */
+	t_u8 amsdu;
+    /** buffer status */
+	t_u32 buffer[MAX_RX_WINSIZE];
+} rx_reorder_tbl;
+
+/** tx_ba_stream_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** RA */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+    /** amsdu flag */
+	t_u8 amsdu;
+} tx_ba_stream_tbl;
+
+/** Debug command number */
+#define DBG_CMD_NUM	10
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** 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;
+
+/** 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;
+    /** Corresponds to is_hs_configured member of mlan_adapter */
+	t_u8 is_hs_configured;
+    /** Corresponds to hs_activated member of mlan_adapter */
+	t_u8 hs_activated;
+    /** Corresponds to pps_uapsd_mode member of mlan_adapter */
+	t_u16 pps_uapsd_mode;
+    /** Corresponds to sleep_period.period member of mlan_adapter */
+	t_u16 sleep_pd;
+    /** Corresponds to wmm_qosinfo member of mlan_private */
+	t_u8 qos_cfg;
+    /** Corresponds to tx_lock_flag member of mlan_adapter */
+	t_u8 tx_lock_flag;
+    /** Corresponds to port_open member of mlan_private */
+	t_u8 port_open;
+    /** bypass pkt count */
+	t_u16 bypass_pkt_count;
+    /** Corresponds to scan_processing member of mlan_adapter */
+	t_u32 scan_processing;
+    /** Corresponds to mlan_processing member of mlan_adapter */
+	t_u32 mlan_processing;
+    /** Corresponds to main_lock_flag member of mlan_adapter */
+	t_u32 main_lock_flag;
+    /** Corresponds to main_process_cnt member of mlan_adapter */
+	t_u32 main_process_cnt;
+	/** Corresponds to delay_task_flag member of mlan_adapter */
+	t_u32 delay_task_flag;
+    /** mlan_rx_processing */
+	t_u32 mlan_rx_processing;
+    /** rx pkts queued */
+	t_u32 rx_pkts_queued;
+    /** Number of host to card command failures */
+	t_u32 num_cmd_host_to_card_failure;
+    /** Number of host to card sleep confirm failures */
+	t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+    /** Number of host to card Tx failures */
+	t_u32 num_tx_host_to_card_failure;
+    /** Number of allocate buffer failure */
+	t_u32 num_alloc_buffer_failure;
+	/** Number of pkt dropped */
+	t_u32 num_pkt_dropped;
+    /** 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;
+    /** 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;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** Number of packets tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+    /** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+	/** last recv wr_bitmap */
+	t_u32 last_recv_wr_bitmap;
+    /** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+    /** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+	/** last len for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+    /** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+    /** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** last mp_index */
+	t_u8 last_mp_index;
+    /** buffer for mp debug */
+	t_u8 *mpa_buf;
+    /** length info for mp buf size */
+	t_u32 mpa_buf_size;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** Number of packets rx aggr */
+	t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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 Tx timeouts */
+	t_u32 num_tx_timeout;
+    /** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+    /** Number of command timeouts */
+	t_u32 dbg_num_cmd_timeout;
+    /** Timeout command ID */
+	t_u16 timeout_cmd_id;
+    /** Timeout command action */
+	t_u16 timeout_cmd_act;
+    /** List of last command IDs */
+	t_u16 last_cmd_id[DBG_CMD_NUM];
+    /** List of last command actions */
+	t_u16 last_cmd_act[DBG_CMD_NUM];
+    /** Last command index */
+	t_u16 last_cmd_index;
+    /** List of last command response IDs */
+	t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+    /** Last command response index */
+	t_u16 last_cmd_resp_index;
+    /** List of last events */
+	t_u16 last_event[DBG_CMD_NUM];
+    /** Last event index */
+	t_u16 last_event_index;
+    /** Number of no free command node */
+	t_u16 num_no_cmd_node;
+    /** pending command id */
+	t_u16 pending_cmd;
+    /** time stamp for dnld last cmd */
+	t_u32 dnld_cmd_in_secs;
+    /** Corresponds to data_sent member of mlan_adapter */
+	t_u8 data_sent;
+    /** Corresponds to cmd_sent member of mlan_adapter */
+	t_u8 cmd_sent;
+    /** SDIO multiple port read bitmap */
+	t_u32 mp_rd_bitmap;
+    /** SDIO multiple port write bitmap */
+	t_u32 mp_wr_bitmap;
+    /** Current available port for read */
+	t_u8 curr_rd_port;
+    /** Current available port for write */
+	t_u8 curr_wr_port;
+    /** 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
+    /** mlan_adapter pointer */
+	t_void *mlan_adapter;
+    /** mlan_adapter_size */
+	t_u32 mlan_adapter_size;
+    /** mlan_priv vector */
+	t_void *mlan_priv[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_size */
+	t_u32 mlan_priv_size[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_num */
+	t_u8 mlan_priv_num;
+} mlan_debug_info, *pmlan_debug_info;
+
+#ifdef UAP_SUPPORT
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS         MAX_STA_COUNT
+
+/** station info */
+typedef struct _sta_info {
+    /** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+    /** station bandmode */
+	t_u8 bandmode;
+} sta_info;
+
+/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */
+typedef struct _mlan_ds_sta_list {
+    /** station count */
+	t_u16 sta_count;
+    /** station list */
+	sta_info info[MAX_NUM_CLIENTS];
+} mlan_ds_sta_list, *pmlan_ds_sta_list;
+#endif
+
+/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */
+typedef struct _mlan_ds_get_info {
+    /** Sub-command */
+	t_u32 sub_command;
+
+    /** Status information parameter */
+	union {
+	/** Signal information for MLAN_OID_GET_SIGNAL */
+		mlan_ds_get_signal signal;
+		/** Signal path id for MLAN_OID_GET_SIGNAL_EXT */
+		t_u16 path_id;
+	/** Signal information for MLAN_OID_GET_SIGNAL_EXT */
+		mlan_ds_get_signal signal_ext[MAX_PATH_NUM];
+	/** Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_get_stats stats;
+	/** Statistics information for MLAN_OID_LINK_STATS*/
+		t_u8 link_statistic[1];
+	/** Firmware information for MLAN_OID_GET_FW_INFO */
+		mlan_fw_info fw_info;
+	/** Extended version information for MLAN_OID_GET_VER_EXT */
+		mlan_ver_ext ver_ext;
+	/** BSS information for MLAN_OID_GET_BSS_INFO */
+		mlan_bss_info bss_info;
+	/** Debug information for MLAN_OID_GET_DEBUG_INFO */
+		t_u8 debug_info[1];
+#ifdef UAP_SUPPORT
+	/** UAP Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_uap_stats ustats;
+	/** UAP station list for MLAN_OID_UAP_STA_LIST */
+		mlan_ds_sta_list sta_list;
+#endif
+	} param;
+} mlan_ds_get_info, *pmlan_ds_get_info;
+
+/*-----------------------------------------------------------------*/
+/** Security Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for authentication mode */
+enum _mlan_auth_mode {
+	MLAN_AUTH_MODE_OPEN = 0x00,
+	MLAN_AUTH_MODE_SHARED = 0x01,
+	MLAN_AUTH_MODE_FT = 0x02,
+	MLAN_AUTH_MODE_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_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,
+};
+
+/** Enumeration for PSK */
+enum _mlan_psk_type {
+	MLAN_PSK_PASSPHRASE = 1,
+	MLAN_PSK_PMK,
+	MLAN_PSK_CLEAR,
+	MLAN_PSK_QUERY,
+};
+
+/** 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
+/** 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
+/** 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 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;
+	/** 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;
+
+/*-----------------------------------------------------------------*/
+/** 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_AUTO = 0xFF,
+};
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE   18
+
+/** 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;
+} 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;
+	} param;
+} mlan_ds_power_cfg, *pmlan_ds_power_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 adhoc awake period */
+#define MIN_ADHOC_AWAKE_PD      0
+/** Maximum adhoc awake period */
+#define MAX_ADHOC_AWAKE_PD      31
+/** Special adhoc awake period */
+#define SPECIAL_ADHOC_AWAKE_PD  255
+
+/** 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;
+    /** Adhoc awake period */
+	t_u32 adhoc_awake_period;
+    /** 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_fw_wakeup_params for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+typedef struct _mlan_fw_wakeup_params {
+    /** FW wakeup method */
+	t_u16 method;
+    /** GPIO pin NO.*/
+	t_u8 gpio_pin;
+} mlan_fw_wakeup_params, *pmlan_fw_wakeup_params;
+
+/** 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;
+	/** FW wakeup method for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+		mlan_fw_wakeup_params fw_wakeup_params;
+	/** 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;
+	} 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;
+
+/** 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,
+};
+
+/** 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 */
+/*-----------------------------------------------------------------*/
+#if defined(DFS_TESTING_SUPPORT)
+/** 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;
+} 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;
+#endif
+
+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;
+
+/** 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;
+#if defined(DFS_TESTING_SUPPORT)
+	/** 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;
+#endif
+		mlan_ds_11h_chan_rep_req chan_rpt_req;
+		t_s8 cs_count;
+	} param;
+} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Miscellaneous Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** CMD buffer size */
+#define MLAN_SIZE_OF_CMD_BUFFER 2048
+
+/** 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;
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** 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[MLAN_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;
+
+/** 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;
+
+/** Enumeration for function init/shutdown */
+enum _mlan_func_cmd {
+	MLAN_FUNC_INIT = 1,
+	MLAN_FUNC_SHUTDOWN,
+};
+
+/** Enumeration for Coalescing status */
+enum _mlan_coal_status {
+	MLAN_MISC_COALESCING_ENABLE = 1,
+	MLAN_MISC_COALESCING_DISABLE = 0
+};
+
+/* Net monitor filters: */
+/* management frame */
+#define MLAN_NETMON_MANAGEMENT    MBIT(0)
+/* control frame */
+#define MLAN_NETMON_CONTROL       MBIT(1)
+/* data frame */
+#define MLAN_NETMON_DATA          MBIT(2)
+/* only unicast frame (no promiscuous) */
+#define MLAN_NETMON_NOPROM        MBIT(3)
+/* decrypted frame */
+#define MLAN_NETMON_DECRYPTED     MBIT(4)
+
+typedef struct _mlan_ds_misc_net_monitor {
+    /** Enable/disable network monitor */
+	t_u32 enable_net_mon;
+    /** Set net monitor filer flag */
+	t_u32 filter_flag;
+   /** Radio type */
+	t_u32 band;
+    /** Channel */
+	t_u32 channel;
+    /** Secondary channel bandwidth */
+	t_u32 chan_bandwidth;
+} mlan_ds_misc_net_monitor;
+
+/** 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;
+
+/** 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;
+
+/* 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_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;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** flag for NOA */
+#define WIFI_DIRECT_NOA         1
+/** flag for OPP_PS */
+#define WIFI_DIRECT_OPP_PS      2
+/** Type definition of mlan_ds_wifi_direct_config
+ *  for MLAN_OID_MISC_WIFI_DIRECT_CONFIG
+ */
+typedef struct _mlan_ds_wifi_direct_config {
+    /** flags for NOA/OPP_PS */
+	t_u8 flags;
+     /** NoA enable/disable */
+	t_u8 noa_enable;
+    /** index */
+	t_u16 index;
+    /** NoA count */
+	t_u8 noa_count;
+    /** NoA duration */
+	t_u32 noa_duration;
+    /** NoA interval */
+	t_u32 noa_interval;
+    /** opp ps enable/disable */
+	t_u8 opp_ps_enable;
+    /** CT window value */
+	t_u8 ct_window;
+} mlan_ds_wifi_direct_config;
+#endif
+
+#if defined(STA_SUPPORT)
+/** mlan_ds_misc_pmfcfg structure */
+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
+
+/** mlan_ds_multi_chan_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_multi_chan_cfg {
+    /** Channel Time */
+	t_u32 channel_time;
+    /** Buffer Weight */
+	t_u8 buffer_weight;
+    /** tlv len */
+	t_u16 tlv_len;
+    /** TLV buffer */
+	t_u8 tlv_buf[0];
+} MLAN_PACK_END mlan_ds_multi_chan_cfg;
+
+/** mlan_ds_drcs_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_drcs_cfg {
+    /** Channel Index*/
+	t_u16 chan_idx;
+    /** Channel time (in TU) for chan_idx */
+	t_u8 chantime;
+    /** Channel swith time (in TU) for chan_idx */
+	t_u8 switchtime;
+    /** Undoze time (in TU) for chan_idx */
+	t_u8 undozetime;
+    /** Rx traffic control scheme when channel switch*/
+    /** only valid for GC/STA interface*/
+	t_u8 mode;
+} MLAN_PACK_END mlan_ds_drcs_cfg;
+
+#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
+
+#define WOWLAN_MAX_PATTERN_LEN		20
+#define WOWLAN_MAX_OFFSET_LEN		50
+#define MAX_NUM_FILTERS              10
+
+/** Temperature Sensor structure */
+typedef struct _mlan_ds_sensor_temp {
+    /** Temperature */
+	t_u32 temperature;
+} mlan_ds_sensor_temp;
+
+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;
+
+/** 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;
+
+/** channel statictics */
+typedef struct _ChStat_t {
+    /** channle number */
+	t_u8 chan_num;
+    /** total network */
+	t_u16 total_networks;
+    /** busy duration */
+	t_u16 cca_busy_duration;
+} ChStat_t, *pChStat_t;
+
+#define MAX_CH_STATS    MAX_BG_CHANNEL
+/** Type definition of mlan_acs_scan */
+typedef struct _mlan_ds_misc_acs {
+    /** Best Channel Number */
+	t_u8 best_ch;
+    /** Scan channel gap */
+	t_u16 scan_chan_gap;
+    /** Channel Statistics Number */
+	t_u8 ch_stats_num;
+    /** Channel Statistics */
+	ChStat_t ch_stats[MAX_CH_STATS];
+} mlan_ds_misc_acs, *pmlan_ds_misc_acs;
+
+/** 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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;
+	/** Coalescing status for MLAN_OID_MISC_COALESCING_STATUS */
+		t_u16 coalescing_status;
+	/** 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;
+	/** Net monitor for MLAN_OID_MISC_NET_MONITOR */
+		mlan_ds_misc_net_monitor net_mon;
+	/** Tx data pause for MLAN_OID_MISC_TX_DATAPAUSE */
+		mlan_ds_misc_tx_datapause tx_datapause;
+	/** IP address configuration */
+		mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
+	/** MAC control for MLAN_OID_MISC_MAC_CONTROL */
+		t_u32 mac_ctrl;
+	/** MEF configuration for MLAN_OID_MISC_MEF_CFG */
+		mlan_ds_misc_mef_cfg mef_cfg;
+	/** CFP code for MLAN_OID_MISC_CFP_CODE */
+		mlan_ds_misc_cfp_code cfp_code;
+	/** Country code for MLAN_OID_MISC_COUNTRY_CODE */
+		mlan_ds_misc_country_code country_code;
+	/** Thermal reading for MLAN_OID_MISC_THERMAL */
+		t_u32 thermal;
+	/** Mgmt subtype mask for MLAN_OID_MISC_RX_MGMT_IND */
+		t_u32 mgmt_subtype_mask;
+	/** subscribe event for MLAN_OID_MISC_SUBSCRIBE_EVENT */
+		mlan_ds_subscribe_evt subscribe_event;
+#ifdef DEBUG_LEVEL1
+	/** Driver debug bit masks */
+		t_u32 drvdbg;
+#endif
+	/** Hotspot config param set */
+		t_u32 hotspot_cfg;
+#ifdef STA_SUPPORT
+		ExtCap_t ext_cap;
+#endif
+		mlan_ds_misc_otp_user_data otp_user_data;
+	/** Tx control */
+		t_u32 tx_control;
+#if defined(STA_SUPPORT)
+		mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+	/** Multi-channel config for MLAN_OID_MISC_MULTI_CHAN_CFG */
+		mlan_ds_multi_chan_cfg multi_chan_cfg;
+	/** Multi-channel policy for MLAN_OID_MISC_MULTI_CHAN_POLICY */
+		t_u16 multi_chan_policy;
+	/** channel drcs time slicing config for MLAN_OID_MISC_DRCS_CFG */
+		mlan_ds_drcs_cfg drcs_cfg[2];
+#ifdef WIFI_DIRECT_SUPPORT
+		mlan_ds_wifi_direct_config p2p_config;
+#endif
+		mlan_ds_coalesce_cfg coalesce_cfg;
+		t_u8 low_pwr_mode;
+#ifdef RX_PACKET_COALESCE
+		mlan_ds_misc_rx_packet_coalesce rx_coalesce;
+#endif
+	/** FW reload flag */
+		t_u8 fw_reload;
+	/** Sensor temperature */
+		mlan_ds_sensor_temp sensor_temp;
+	/** Bandwidth Channel operation */
+		mlan_ds_bw_chan_oper bw_chan_oper;
+    /** Independent Reset Configuration */
+		mlan_ds_ind_rst_cfg ind_rst_cfg;
+    /** misc tsf */
+		t_u64 misc_tsf;
+		mlan_ds_misc_robustcoex_params robustcoexparams;
+    /** boot sleep enable or disable */
+		t_u16 boot_sleep;
+    /** ACS */
+		mlan_ds_misc_acs acs;
+	} 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_sd8897/mlan/mlan_join.c b/wlan_sd8897/mlan/mlan_join.c
new file mode 100644
index 0000000..ae97dae
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_join.c
@@ -0,0 +1,2558 @@
+/** @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 (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_11h.h"
+/********************************************************
+			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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, priv->gen_ie_buf,
+		       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(MrvlIEtypesHeader_t));
+		memcpy(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, ie,
+		       ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_t));
+
+		/* Increment the return size and the return buffer pointer param */
+		*ppbuffer += ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_t);
+		ret_len += ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_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(pmriv->adapter, *ppbuffer, &tsf_tlv, 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(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val));
+	*ppbuffer += sizeof(tsf_val);
+
+	memcpy(pmriv->adapter, &tsf_val, pbss_desc->time_stamp,
+	       sizeof(tsf_val));
+
+	PRINTM(MINFO, "ASSOC: TSF offset calc: %016llx - %016llx\n",
+	       tsf_val, pbss_desc->network_tsf);
+
+	memcpy(pmriv->adapter, *ppbuffer, &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(IN mlan_private *pmpriv,
+		      IN t_u8 *rate1,
+		      IN t_u32 rate1_size, IN t_u8 *rate2, IN 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(pmpriv->adapter, tmp, rate1, 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(IN mlan_private *pmpriv,
+			      IN BSSDescriptor_t *pbss_desc,
+			      OUT t_u8 *pout_rates, OUT t_u32 *pout_rates_size)
+{
+	t_u8 card_rates[WLAN_SUPPORTED_RATES];
+	t_u32 card_rates_size = 0;
+	ENTER();
+	/* Copy AP supported rates */
+	memcpy(pmpriv->adapter, pout_rates, pbss_desc->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(IN mlan_private *pmpriv,
+			   IN 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(pmpriv->adapter, &new_tsf_base, 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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, priv->wapi_ie,
+		       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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, &priv->osen_ie[2],
+		       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;
+}
+
+/********************************************************
+				Global Functions
+********************************************************/
+/**
+ *  @brief This function updates RSN IE in the association request.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @param ptlv_rsn_ie       A pointer to rsn_ie TLV
+ */
+int
+wlan_update_rsn_ie(mlan_private *pmpriv, MrvlIEtypes_RsnParamSet_t *ptlv_rsn_ie)
+{
+	t_u16 *prsn_cap;
+	t_u16 *ptr;
+	t_u16 *akm_suite_count_ptr;
+	t_u16 pmf_mask = 0x00;
+	t_u8 *temp;
+	t_u16 pairwise_cipher_count = 0;
+	t_u16 akm_suite_count = 0;
+	t_u16 temp_akm_suite_count = 0;
+	int found = 0;
+	t_u8 sha_256_oui[4] = { 0x00, 0x0f, 0xac, 0x06 };
+	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 (!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(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)),
+			       sha_256_oui, 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 PMF is required by AP, just leave the same value with AP */
+	if (!(*prsn_cap & (0x1 << MFPR_BIT)))
+		*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 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(IN mlan_private *pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_ASSOCIATE *passo = &cmd->params.associate;
+	BSSDescriptor_t *pbss_desc;
+	MrvlIEtypes_SsIdParamSet_t *pssid_tlv;
+	MrvlIEtypes_PhyParamSet_t *pphy_tlv;
+	MrvlIEtypes_SsParamSet_t *pss_tlv;
+	MrvlIEtypes_RatesParamSet_t *prates_tlv;
+	MrvlIEtypes_AuthType_t *pauth_tlv;
+	MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
+	WLAN_802_11_RATES rates;
+	t_u32 rates_size;
+	t_u16 tmp_cap;
+	t_u8 *pos;
+	t_u8 ft_akm = 0;
+	t_u8 oper_class;
+
+	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;
+
+	memcpy(pmadapter, passo->peer_sta_addr,
+	       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(pmadapter, pssid_tlv->ssid, pbss_desc->ssid.ssid,
+	       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(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));
+	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(pmadapter, &pmpriv->curr_bss_params.data_rates, rates,
+	       rates_size);
+
+	/* 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(pmadapter, prates_tlv->rates, rates, 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
+			pauth_tlv->auth_type =
+				wlan_cpu_to_le16(MLAN_AUTH_MODE_OPEN);
+		pos += sizeof(pauth_tlv->header) + pauth_tlv->header.len;
+		pauth_tlv->header.len = wlan_cpu_to_le16(pauth_tlv->header.len);
+	}
+
+	if (IS_SUPPORT_MULTI_BANDS(pmadapter)
+	    && (pbss_desc->bss_band & pmpriv->config_bands)
+	    && !(ISSUPP_11NENABLED(pmadapter->fw_cap_info)
+		 && (!pbss_desc->disable_11n)
+		 && (pmpriv->config_bands & BAND_GN
+		     || pmpriv->config_bands & BAND_AN)
+		 && (pbss_desc->pht_cap)
+	    )
+		) {
+		/* Append a channel TLV for the channel the attempted AP was found on */
+		pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
+		pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		pchan_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
+
+		memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
+		       sizeof(ChanScanParamSet_t));
+		pchan_tlv->chan_scan_param[0].chan_number =
+			(pbss_desc->phy_param_set.ds_param_set.current_chan);
+		PRINTM(MINFO, "Assoc: TLV Chan = %d\n",
+		       pchan_tlv->chan_scan_param[0].chan_number);
+
+		pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
+			wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
+
+		PRINTM(MINFO, "Assoc: TLV Bandcfg = %x\n",
+		       pchan_tlv->chan_scan_param[0].bandcfg);
+		pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+	}
+	if (!pmpriv->wps.session_enable) {
+		if ((pmpriv->sec_info.wpa_enabled
+		     || pmpriv->sec_info.wpa2_enabled)) {
+			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+			/* WPA_IE or RSN_IE */
+			prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
+			prsn_ie_tlv->header.type =
+				prsn_ie_tlv->header.type & 0x00FF;
+			prsn_ie_tlv->header.type =
+				wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+			prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
+			prsn_ie_tlv->header.len =
+				prsn_ie_tlv->header.len & 0x00FF;
+			if (prsn_ie_tlv->header.len <=
+			    (sizeof(pmpriv->wpa_ie) - 2))
+				memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
+				       &pmpriv->wpa_ie[2],
+				       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);
+		} 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(pmadapter, prsn_ie_tlv->rsn_ie,
+					       &((*(pbss_desc->pwpa_ie)).
+						 vend_hdr.oui[0]),
+					       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(pmadapter, prsn_ie_tlv->rsn_ie,
+					       &((*(pbss_desc->prsn_ie)).
+						 data[0])
+					       , 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, &pos);
+	if (pmpriv->adapter->ecsa_enable) {
+		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);
+
+	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 (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(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+	       sizeof(passo->cap_info));
+
+	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(pmadapter, &passo->cap_info, &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(IN mlan_private *pmpriv,
+			  IN HostCmd_DS_COMMAND *resp, IN 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;
+	ENTER();
+
+	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(pmpriv->adapter, cur_mac,
+		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		       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(pmpriv->adapter, pmpriv->assoc_rsp_buf, &resp->params,
+	       pmpriv->assoc_rsp_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++;
+		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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+		       &passoc_rsp->status_code, 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(pmpriv->adapter, &pmpriv->ext_cap, &pmpriv->def_ext_cap,
+	       sizeof(pmpriv->ext_cap));
+	/* Make a copy of current BSSID descriptor */
+	memcpy(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+	       pbss_desc, 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;
+
+	/*
+	 * 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->amsdu_rx_cnt = 0;
+	pmpriv->amsdu_tx_cnt = 0;
+	pmpriv->msdu_in_rx_amsdu_cnt = 0;
+	pmpriv->msdu_in_tx_amsdu_cnt = 0;
+	pmpriv->rxpd_rate = 0;
+	pmpriv->rxpd_rate_info = 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++;
+
+	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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+	       (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	/* 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) {
+		/* 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)
+		pmpriv->adapter->scan_block = MTRUE;
+
+	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(pmpriv->adapter, (t_u8 *)assoc_succ->bssid,
+	       pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH);
+	memcpy(pmpriv->adapter, (t_u8 *)assoc_succ->oui, pbss_desc->mac_address,
+	       MLAN_MAC_ADDR_LENGTH / 2);
+	memcpy(pmpriv->adapter, (t_u8 *)assoc_succ->ssid, pbss_desc->ssid.ssid,
+	       pbss_desc->ssid.ssid_len);
+	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(IN mlan_private *pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd, IN 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;
+	MrvlIETypes_HTCap_t *pht_cap;
+	MrvlIETypes_HTInfo_t *pht_info;
+	t_u32 rx_mcs_supp = 0;
+	MrvlIETypes_VHTCap_t *pvht_cap = MNULL;
+	MrvlIETypes_VHTOprat_t *pvht_op = MNULL;
+	t_u16 mcs_map_user = 0;
+	/* 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(pmadapter, padhoc_start->ssid,
+	       ((mlan_802_11_ssid *)pdata_buf)->ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len));
+
+	PRINTM(MINFO, "ADHOC_S_CMD: SSID = %s\n", padhoc_start->ssid);
+
+	memset(pmadapter, pbss_desc->ssid.ssid, 0, MLAN_MAX_SSID_LENGTH);
+	memcpy(pmadapter, pbss_desc->ssid.ssid,
+	       ((mlan_802_11_ssid *)pdata_buf)->ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len));
+
+	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(pmadapter, &pbss_desc->phy_param_set,
+	       &padhoc_start->phy_param_set, 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(pmadapter, &pbss_desc->ss_param_set,
+	       &padhoc_start->ss_param_set, 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->adhoc_aes_enabled
+	    || 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(pmadapter, &pmpriv->curr_bss_params.data_rates,
+	       &padhoc_start->DataRate, pmpriv->curr_bss_params.num_of_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);
+		if (pmadapter->adhoc_start_band & BAND_GN
+		    || pmadapter->adhoc_start_band & BAND_AN
+		    || pmadapter->adhoc_start_band & BAND_GAC
+		    || pmadapter->adhoc_start_band & BAND_AAC) {
+			if (pmadapter->chan_bandwidth == CHANNEL_BW_40MHZ_ABOVE) {
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chan2Offset = SEC_CHAN_ABOVE;
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chanWidth = CHAN_BW_40MHZ;
+			} else if (pmadapter->chan_bandwidth ==
+				   CHANNEL_BW_40MHZ_BELOW) {
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chan2Offset = SEC_CHAN_BELOW;
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chanWidth = CHAN_BW_40MHZ;
+			} else if (pmadapter->chan_bandwidth ==
+				   CHANNEL_BW_80MHZ) {
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chanWidth = CHAN_BW_80MHZ;
+			}
+		}
+		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(pmadapter, pmpriv->wpa_ie, wpa_ie, sizeof(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(pmadapter, prsn_ie_tlv->rsn_ie,
+			       &pmpriv->wpa_ie[2], 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);
+	}
+
+	if (pmadapter->adhoc_11n_enabled == MTRUE) {
+		{
+			pht_cap = (MrvlIETypes_HTCap_t *)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);
+			rx_mcs_supp =
+				GET_RXMCSSUPP(pmpriv->usr_dev_mcs_support);
+			/* Set MCS for 1x1/2x2 */
+			memset(pmadapter,
+			       (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
+			       rx_mcs_supp);
+			wlan_fill_ht_cap_tlv(pmpriv, pht_cap,
+					     pmpriv->curr_bss_params.band,
+					     MTRUE);
+			HEXDUMP("ADHOC_START: HT_CAPABILITIES IE",
+				(t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
+			pos += sizeof(MrvlIETypes_HTCap_t);
+			cmd_append_size += sizeof(MrvlIETypes_HTCap_t);
+			pht_cap->header.len =
+				wlan_cpu_to_le16(pht_cap->header.len);
+		}
+		{
+			pht_info = (MrvlIETypes_HTInfo_t *)pos;
+			memset(pmadapter, pht_info, 0,
+			       sizeof(MrvlIETypes_HTInfo_t));
+			pht_info->header.type = wlan_cpu_to_le16(HT_OPERATION);
+			pht_info->header.len = sizeof(HTInfo_t);
+			pht_info->ht_info.pri_chan =
+				(t_u8)pmpriv->curr_bss_params.bss_descriptor.
+				channel;
+			if ((pmadapter->chan_bandwidth ==
+			     CHANNEL_BW_40MHZ_ABOVE) ||
+			    (pmadapter->chan_bandwidth ==
+			     CHANNEL_BW_40MHZ_BELOW)) {
+				pht_info->ht_info.field2 =
+					pmadapter->chan_bandwidth;
+				SET_CHANWIDTH40(pht_info->ht_info.field2);
+			}
+			if (pmadapter->chan_bandwidth == CHANNEL_BW_80MHZ) {
+				pht_info->ht_info.field2 =
+					wlan_get_second_channel_offset
+					(pht_info->ht_info.pri_chan);
+				pht_info->ht_info.field2 |= MBIT(2);
+			}
+			pht_info->ht_info.field3 =
+				wlan_cpu_to_le16(NON_GREENFIELD_STAS);
+			pht_info->ht_info.basic_mcs_set[0] = 0xff;
+			HEXDUMP("ADHOC_START: HT_INFORMATION IE",
+				(t_u8 *)pht_info, sizeof(MrvlIETypes_HTInfo_t));
+			pos += sizeof(MrvlIETypes_HTInfo_t);
+			cmd_append_size += sizeof(MrvlIETypes_HTInfo_t);
+			pht_info->header.len =
+				wlan_cpu_to_le16(pht_info->header.len);
+		}
+		if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info)
+		    && (pmadapter->adhoc_start_band & BAND_GAC
+			|| pmadapter->adhoc_start_band & BAND_AAC)) {
+			/* VHT Capabilities IE */
+			pvht_cap = (MrvlIETypes_VHTCap_t *)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);
+			/* rx MCS Map */
+			mcs_map_user =
+				GET_DEVRXMCSMAP(pmpriv->
+						usr_dot_11ac_mcs_support);
+			pvht_cap->vht_cap.mcs_sets.rx_mcs_map =
+				wlan_cpu_to_le16(mcs_map_user);
+			/* rx highest rate */
+			pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+				wlan_convert_mcsmap_to_maxrate(pmpriv,
+							       pmadapter->
+							       adhoc_start_band,
+							       mcs_map_user);
+			pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+				wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.
+						 rx_max_rate);
+			/* tx MCS map */
+			mcs_map_user =
+				GET_DEVTXMCSMAP(pmpriv->
+						usr_dot_11ac_mcs_support);
+			pvht_cap->vht_cap.mcs_sets.tx_mcs_map =
+				wlan_cpu_to_le16(mcs_map_user);
+			/* tx highest rate */
+			pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+				wlan_convert_mcsmap_to_maxrate(pmpriv,
+							       pmadapter->
+							       adhoc_start_band,
+							       mcs_map_user);
+			pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+				wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.
+						 tx_max_rate);
+
+			wlan_fill_vht_cap_tlv(pmpriv, pvht_cap,
+					      pmadapter->adhoc_start_band,
+					      MTRUE);
+			HEXDUMP("VHT_CAPABILITIES IE", (t_u8 *)pvht_cap,
+				sizeof(MrvlIETypes_VHTCap_t));
+			pos += sizeof(MrvlIETypes_VHTCap_t);
+			cmd_append_size += sizeof(MrvlIETypes_VHTCap_t);
+			pvht_cap->header.len =
+				wlan_cpu_to_le16(pvht_cap->header.len);
+			/* VHT Operation IE */
+			pvht_op = (MrvlIETypes_VHTOprat_t *)pos;
+			memset(pmadapter, pvht_op, 0,
+			       sizeof(MrvlIETypes_VHTOprat_t));
+			pvht_op->header.type = wlan_cpu_to_le16(VHT_OPERATION);
+			pvht_op->header.len = sizeof(MrvlIETypes_VHTOprat_t) -
+				sizeof(MrvlIEtypesHeader_t);
+			if (pmadapter->chan_bandwidth == CHANNEL_BW_80MHZ) {
+				pvht_op->chan_width = VHT_OPER_CHWD_80MHZ;
+				/* central frequency */
+				pvht_op->chan_center_freq_1 =
+					wlan_get_center_freq_idx(pmpriv,
+								 pmadapter->
+								 adhoc_start_band,
+								 pmpriv->
+								 adhoc_channel,
+								 pmadapter->
+								 chan_bandwidth);
+			}
+			/* basic MCS (rx MCS Map) */
+			pvht_op->basic_MCS_map =
+				GET_DEVRXMCSMAP(pmpriv->
+						usr_dot_11ac_mcs_support);
+			pvht_op->basic_MCS_map =
+				wlan_cpu_to_le16(pvht_op->basic_MCS_map);
+
+			HEXDUMP("VHT_OPERATION IE", (t_u8 *)pvht_op,
+				sizeof(MrvlIETypes_VHTOprat_t));
+			pos += sizeof(MrvlIETypes_VHTOprat_t);
+			cmd_append_size += sizeof(MrvlIETypes_VHTOprat_t);
+			pvht_op->header.len =
+				wlan_cpu_to_le16(pvht_op->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(pmadapter, &tmp_cap, &padhoc_start->cap, sizeof(t_u16));
+
+	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(pmadapter, &padhoc_start->cap, &tmp_cap, sizeof(t_u16));
+
+	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(IN mlan_private *pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd, IN 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(pmadapter, &padhoc_join->bss_descriptor.bssid,
+	       &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH);
+
+	memcpy(pmadapter, &padhoc_join->bss_descriptor.ssid,
+	       &pbss_desc->ssid.ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH, pbss_desc->ssid.ssid_len));
+
+	memcpy(pmadapter, &padhoc_join->bss_descriptor.phy_param_set,
+	       &pbss_desc->phy_param_set, 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(pmadapter, &padhoc_join->bss_descriptor.ss_param_set,
+	       &pbss_desc->ss_param_set, 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(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+	       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(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
+	       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(pmadapter, padhoc_join->bss_descriptor.data_rates,
+	       pbss_desc->supported_rates, rates_size);
+
+	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(pmadapter, &pmpriv->curr_bss_params.data_rates,
+	       pbss_desc->supported_rates, rates_size);
+
+	/* 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->adhoc_aes_enabled
+	    || 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(pmadapter, prsn_ie_tlv->rsn_ie,
+			       &pmpriv->wpa_ie[2], 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(pmadapter, prsn_ie_tlv->rsn_ie,
+				       &((*(pbss_desc->pwpa_ie)).vend_hdr.
+					 oui[0]), 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(pmadapter, prsn_ie_tlv->rsn_ie,
+				       &((*(pbss_desc->prsn_ie)).data[0])
+				       , 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 (ISSUPP_11NENABLED(pmadapter->fw_cap_info)
+	    && wlan_11n_bandconfig_allowed(pmpriv, pbss_desc->bss_band)
+		)
+		cmd_append_size +=
+			wlan_cmd_append_11n_tlv(pmpriv, pbss_desc, &pos);
+	if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info)
+	    && wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
+		cmd_append_size +=
+			wlan_cmd_append_11ac_tlv(pmpriv, pbss_desc, &pos);
+
+	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(pmadapter, &tmp_cap, &padhoc_join->bss_descriptor.cap,
+	       sizeof(IEEEtypes_CapInfo_t));
+	tmp_cap = wlan_cpu_to_le16(tmp_cap);
+
+	memcpy(pmadapter, &padhoc_join->bss_descriptor.cap,
+	       &tmp_cap, 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(IN mlan_private *pmpriv,
+		       IN HostCmd_DS_COMMAND *resp, IN 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(pmpriv->adapter, pbss_desc->mac_address,
+		       padhoc_start_result->bssid, 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(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+		       pbss_desc, sizeof(BSSDescriptor_t));
+
+		pmpriv->adhoc_state = ADHOC_JOINED;
+	}
+
+    /** process wmm ie */
+	if (ie_len >= sizeof(IEEEtypes_VendorHeader_t)) {
+		if ((pwmm_param_ie->vend_hdr.element_id == VENDOR_SPECIFIC_221)
+		    && !memcmp(pmadapter, pwmm_param_ie->vend_hdr.oui, wmm_oui,
+			       sizeof(wmm_oui)) &&
+		    (pwmm_param_ie->vend_hdr.len + 2 == ie_len)) {
+			DBG_HEXDUMP(MCMD_D, "WMM Param", (t_u8 *)pwmm_param_ie,
+				    ie_len);
+			memcpy(pmpriv->adapter,
+			       (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.
+			       wmm_ie, pwmm_param_ie,
+			       MIN(sizeof(IEEEtypes_WmmParameter_t),
+				   (pwmm_param_ie->vend_hdr.len + 2)));
+			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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+	       (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+	       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(IN mlan_private *pmpriv,
+	       IN t_void *pioctl_buf, IN 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(pmpriv->adapter, &current_bssid,
+	       &pmpriv->curr_bss_params.bss_descriptor.mac_address,
+	       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(IN mlan_private *pmpriv,
+		 IN t_void *pioctl_buf, IN 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(pmpriv->adapter, &pmpriv->adhoc_last_start_ssid,
+		       padhoc_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(IN mlan_private *pmpriv,
+		IN t_void *pioctl_buf, IN 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(IN mlan_private *pmpriv,
+		IN mlan_ioctl_req *pioctl_req,
+		IN 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(pmpriv->adapter, &local_param, deauth_param,
+		       sizeof(*deauth_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(pmpriv->adapter, local_param.mac_addr,
+				       (t_u8 *)&pmpriv->curr_bss_params.
+				       bss_descriptor.mac_address,
+				       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(IN 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_sd8897/mlan/mlan_join.h b/wlan_sd8897/mlan/mlan_join.h
new file mode 100644
index 0000000..3ca0cbe
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_join.h
@@ -0,0 +1,40 @@
+/** @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 (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_sd8897/mlan/mlan_main.h b/wlan_sd8897/mlan/mlan_main.h
new file mode 100644
index 0000000..276c493
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_main.h
@@ -0,0 +1,3722 @@
+/** @file mlan_main.h
+ *
+ *  @brief This file defines the private and adapter data
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    10/13/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_MAIN_H_
+#define _MLAN_MAIN_H_
+
+#ifdef DEBUG_LEVEL1
+extern t_void (*print_callback) (IN t_void *pmoal_handle,
+				 IN t_u32 level, IN char *pformat, IN ...
+	);
+
+extern mlan_status (*get_sys_time_callback) (IN t_void *pmoal_handle,
+					     OUT t_u32 *psec, OUT t_u32 *pusec);
+
+extern t_u32 mlan_drvdbg;
+
+/* Reason Code 3: STA is leaving (or has left) IBSS or ESS */
+#define DEF_DEAUTH_REASON_CODE (0x3)
+
+#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 */
+
+/** 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))
+
+#ifdef memcmp
+#undef memcmp
+#endif
+/** Memcmp routine */
+#define memcmp(adapter, s1, s2, len) \
+	(adapter->callbacks.moal_memcmp(adapter->pmoal_handle, s1, s2, len))
+
+/** Find number of elements */
+#ifndef NELEMENTS
+#define NELEMENTS(x)    (sizeof(x)/sizeof(x[0]))
+#endif
+
+/** SWAP: swap t_u8 */
+#define SWAP_U8(a, b)	{t_u8 t; t = a; a = b; b = t; }
+
+/** SWAP: swap t_u8 */
+#define SWAP_U16(a, b)	{t_u16 t; t = a; a = b; b = t; }
+
+/** MLAN MNULL pointer */
+#define MNULL                           (0)
+
+/** 16 bits byte swap */
+#define swap_byte_16(x) \
+((t_u16)((((t_u16)(x) & 0x00ffU) << 8) | \
+		 (((t_u16)(x) & 0xff00U) >> 8)))
+
+/** 32 bits byte swap */
+#define swap_byte_32(x) \
+((t_u32)((((t_u32)(x) & 0x000000ffUL) << 24) | \
+	 (((t_u32)(x) & 0x0000ff00UL) <<  8) | \
+	 (((t_u32)(x) & 0x00ff0000UL) >>  8) | \
+	 (((t_u32)(x) & 0xff000000UL) >> 24)))
+
+/** 64 bits byte swap */
+#define swap_byte_64(x) \
+((t_u64)((t_u64)(((t_u64)(x) & 0x00000000000000ffULL) << 56) | \
+	     (t_u64)(((t_u64)(x) & 0x000000000000ff00ULL) << 40) | \
+	     (t_u64)(((t_u64)(x) & 0x0000000000ff0000ULL) << 24) | \
+	     (t_u64)(((t_u64)(x) & 0x00000000ff000000ULL) <<  8) | \
+	     (t_u64)(((t_u64)(x) & 0x000000ff00000000ULL) >>  8) | \
+	     (t_u64)(((t_u64)(x) & 0x0000ff0000000000ULL) >> 24) | \
+	     (t_u64)(((t_u64)(x) & 0x00ff000000000000ULL) >> 40) | \
+	     (t_u64)(((t_u64)(x) & 0xff00000000000000ULL) >> 56)))
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert ulong n/w to host */
+#define mlan_ntohl(x) x
+/** Convert host ulong to n/w */
+#define mlan_htonl(x) x
+/** Convert n/w to host */
+#define mlan_ntohs(x)  x
+/** Convert host to n/w */
+#define mlan_htons(x)  x
+/** Convert from 16 bit little endian format to CPU format */
+#define wlan_le16_to_cpu(x) swap_byte_16(x)
+/** Convert from 32 bit little endian format to CPU format */
+#define wlan_le32_to_cpu(x) swap_byte_32(x)
+/** Convert from 64 bit little endian format to CPU format */
+#define wlan_le64_to_cpu(x) swap_byte_64(x)
+/** Convert to 16 bit little endian format from CPU format */
+#define wlan_cpu_to_le16(x) swap_byte_16(x)
+/** Convert to 32 bit little endian format from CPU format */
+#define wlan_cpu_to_le32(x) swap_byte_32(x)
+/** Convert to 64 bit little endian format from CPU format */
+#define wlan_cpu_to_le64(x) swap_byte_64(x)
+
+/** Convert TxPD to little endian format from CPU format */
+#define endian_convert_TxPD(x)                                          \
+	{                                                                   \
+	    (x)->tx_pkt_length = wlan_cpu_to_le16((x)->tx_pkt_length);      \
+	    (x)->tx_pkt_offset = wlan_cpu_to_le16((x)->tx_pkt_offset);      \
+	    (x)->tx_pkt_type   = wlan_cpu_to_le16((x)->tx_pkt_type);        \
+	    (x)->tx_control    = wlan_cpu_to_le32((x)->tx_control);         \
+        (x)->tx_control_1  = wlan_cpu_to_le32((x)->tx_control_1);         \
+	}
+/** Convert RxPD from little endian format to CPU format */
+#define endian_convert_RxPD(x)                                          \
+	{                                                                   \
+	    (x)->rx_pkt_length = wlan_le16_to_cpu((x)->rx_pkt_length);      \
+	    (x)->rx_pkt_offset = wlan_le16_to_cpu((x)->rx_pkt_offset);      \
+	    (x)->rx_pkt_type   = wlan_le16_to_cpu((x)->rx_pkt_type);        \
+	    (x)->seq_num       = wlan_le16_to_cpu((x)->seq_num);            \
+        (x)->rx_info       = wlan_le32_to_cpu((x)->rx_info);            \
+	}
+/** Convert RxPD extra header from little endian format to CPU format */
+#define endian_convert_RxPD_extra_header(x)                                          \
+	{                                                                   \
+	    (x)->channel_flags = wlan_le16_to_cpu((x)->channel_flags);      \
+	}
+#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)
+/** Convert RxPD extra header from little endian format to CPU format */
+#define endian_convert_RxPD_extra_header(x)  do {} while (0)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** Global moal_assert_callback */
+extern t_void (*assert_callback) (IN t_void *pmoal_handle, IN 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)
+
+/** Upload size */
+#define WLAN_UPLD_SIZE                  (2312)
+
+/** Maximum event buffer size */
+#define MAX_EVENT_SIZE                  2048
+
+#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
+/** 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          8
+
+/** 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         100
+/** low rx pending packets */
+#define LOW_RX_PENDING          80
+
+/** Default region code */
+#define MRVDRV_DEFAULT_REGION_CODE      0x10
+
+/** Default country code */
+#define MRVDRV_DEFAULT_COUNTRY_CODE      "US"
+
+/** Japan country code */
+#define COUNTRY_CODE_JP_40	        0x40
+/** Japan special country code */
+#define COUNTRY_CODE_JP_FF	        0xFF
+
+/** Default factor for calculating beacon average */
+#define DEFAULT_BCN_AVG_FACTOR          8
+/** Default factor for calculating data average */
+#define DEFAULT_DATA_AVG_FACTOR         8
+
+/** The first valid channel for use */
+#define FIRST_VALID_CHANNEL          0xff
+/** Default Ad-Hoc channel */
+#define DEFAULT_AD_HOC_CHANNEL       6
+/** Default Ad-Hoc channel A */
+#define DEFAULT_AD_HOC_CHANNEL_A     36
+
+/** Number of WEP keys */
+#define MRVL_NUM_WEP_KEY                (4)
+
+/** Default multiple DTIM */
+#define MRVDRV_DEFAULT_MULTIPLE_DTIM        1
+
+/** Default beacon missing timeout */
+#define DEFAULT_BCN_MISS_TIMEOUT            10
+
+/** Maximum buffer space for beacons retrieved from scan responses */
+#define MAX_SCAN_BEACON_BUFFER          49152
+/** Default buffer space for beacons retrieved from scan responses */
+#define DEFAULT_SCAN_BEACON_BUFFER      4096
+
+/**
+ * @brief Buffer pad space for newly allocated beacons/probe responses
+ *
+ * Beacons are typically 6 bytes longer than an equivalent probe response.
+ *  For each scan response stored, allocate an extra byte pad at the end to
+ *  allow easy expansion to store a beacon in the same memory a probe response
+ *  previously contained
+ */
+#define SCAN_BEACON_ENTRY_PAD          6
+
+/** Scan time specified in the channel TLV
+ *  for each channel for passive scans
+ */
+#define MRVDRV_PASSIVE_SCAN_CHAN_TIME       200
+
+/** Scan time specified in the channel TLV
+ *  for each channel for active scans
+ */
+#define MRVDRV_ACTIVE_SCAN_CHAN_TIME        200
+
+/** Scan time specified in the channel TLV
+ *  for each channel for specific scans
+ */
+#define MRVDRV_SPECIFIC_SCAN_CHAN_TIME      110
+
+/**
+ * Max total scan time in milliseconds
+ * The total scan time should be less than scan command timeout value (20s)
+ */
+#define MRVDRV_MAX_TOTAL_SCAN_TIME     (MRVDRV_TIMER_10S * 2 - MRVDRV_TIMER_1S)
+
+/** Offset for GTK as it has version to skip past for GTK */
+#define RSN_GTK_OUI_OFFSET 2
+
+/** If OUI is not found */
+#define MLAN_OUI_NOT_PRESENT 0
+/** If OUI is found */
+#define MLAN_OUI_PRESENT 1
+
+/** Is cmd_resp, event or data packet received? */
+#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \
+	adapter->event_received || \
+	adapter->data_received)
+/** Type command */
+#define MLAN_TYPE_CMD			1
+/** Type data */
+#define MLAN_TYPE_DATA			0
+/** Type event */
+#define MLAN_TYPE_EVENT			3
+
+#define MAX_SUPPORT_AMSDU_SIZE          4096
+/** Maximum numbfer of registers to read for multiple port */
+/* upto 0xB7 */
+#define MAX_MP_REGS			184
+/** Maximum port */
+#define MAX_PORT			32
+
+/** max MP REGS */
+#define MAX_MP_REGS_MAX	    (196)
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** Multi port TX aggregation buffer size */
+#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE        (65280)	/* 64K - 256 */
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+/** Multi port RX aggregation buffer size */
+#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE        (65280)	/* 64K - 256 */
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+/** High threshold at which to start drop packets */
+#define  RX_HIGH_THRESHOLD           1024
+/** Low threshold to allow Rx BA */
+#define  RX_LOW_THRESHOLD            128
+
+/** 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 Tx timeouts */
+	t_u32 num_tx_timeout;
+    /** 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;
+} 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;
+
+/** 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];
+} 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
+
+/** CFP dynamic (non-const) elements */
+typedef struct _cfp_dyn_t {
+	/** extra flags to specify channel usability
+	 *  bit 7 : if set, channel is disabled
+	 *  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_u8 flags;
+    /** TRUE: Channel is blacklisted (do not use) */
+	t_bool blacklist;
+} cfp_dyn_t;
+
+/** Chan-Freq-TxPower mapping table*/
+typedef struct _chan_freq_power_t {
+    /** Channel Number */
+	t_u16 channel;
+    /** Frequency of this Channel */
+	t_u32 freq;
+    /** Max allowed Tx power level */
+	t_u16 max_tx_power;
+    /** TRUE:radar detect required for BAND A or passive scan for BAND B/G;
+      * FALSE:radar detect not required for BAND A or active scan for BAND B/G*/
+	t_bool passive_scan_or_radar_detect;
+    /** Elements associated to cfp that change at run-time */
+	cfp_dyn_t dynamic;
+} chan_freq_power_t;
+
+/** 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) (IN t_void *priv, IN t_u8 first_bss);
+    /** ioctl handler */
+	mlan_status (*ioctl) (t_void *adapter, pmlan_ioctl_req pioctl_req);
+    /** cmd handler */
+	mlan_status (*prepare_cmd) (IN t_void *priv,
+				    IN t_u16 cmd_no,
+				    IN t_u16 cmd_action,
+				    IN t_u32 cmd_oid,
+				    IN t_void *pioctl_buf,
+				    IN t_void *pdata_buf, IN t_void *pcmd_buf);
+    /** cmdresp handler */
+	mlan_status (*process_cmdresp) (IN t_void *priv,
+					IN t_u16 cmdresp_no,
+					IN t_void *pcmd_buf, IN t_void *pioctl);
+    /** rx handler */
+	mlan_status (*process_rx_packet) (IN t_void *adapter,
+					  IN pmlan_buffer pmbuf);
+    /** event handler */
+	mlan_status (*process_event) (IN t_void *priv);
+    /** txpd handler */
+	t_void *(*process_txpd) (IN t_void *priv, IN pmlan_buffer pmbuf);
+    /** BSS role */
+	mlan_bss_role bss_role;
+} mlan_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;
+    /** rxpd_htinfo */
+	t_u8 rxpd_rate_info;
+    /** max amsdu size */
+	t_u16 max_amsdu;
+    /** 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 */
+#ifdef UAP_SUPPORT
+    /** UAP 11ac flag */
+	t_u8 is_11ac_enabled;
+#endif				/* UAP_SUPPORT */
+    /** 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;
+    /**  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;
+    /** Rate bitmap */
+	t_u16 rate_bitmap;
+    /** 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;
+    /** 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;
+
+    /** Current SSID/BSSID related parameters*/
+	current_bss_params_t curr_bss_params;
+    /** current channel flags */
+	t_u32 curr_chan_flags;
+    /** User selected bands */
+	t_u8 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;
+	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;
+    /** Advanced Encryption Standard */
+	t_u8 adhoc_aes_enabled;
+    /** 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;
+    /** Current Beacon buffer */
+	t_u8 *pcurr_bcn_buf;
+    /** Current Beacon size */
+	t_u32 curr_bcn_size;
+    /** Current Beacon buffer lock */
+	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];
+    /** Hotspot configuration */
+	t_u32 hotspot_cfg;
+#ifdef STA_SUPPORT
+    /** Extended capabilities */
+	ExtCap_t ext_cap;
+    /** Default extended capabilities */
+	ExtCap_t def_ext_cap;
+#endif
+    /** interface header len */
+	t_u8 intf_hr_len;
+    /** Control TX AMPDU on infra link */
+	t_u8 txaggrctrl;
+    /** 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];
+    /** 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;
+
+/** 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 OID for sub-command use */
+	t_u32 cmd_oid;
+    /** 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;
+    /** pre_allocated mlan_buffer for cmd */
+	mlan_buffer *pmbuf;
+};
+
+/** 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;
+
+/** 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;
+    /** tdls status */
+	tdlsStatus_e status;
+    /** SNR */
+	t_s8 snr;
+    /** Noise Floor */
+	t_s8 nf;
+    /** flag for host based tdls */
+	t_u8 external_tdls;
+    /** peer capability */
+	t_u16 capability;
+    /** 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_u8 bandmode;
+};
+
+/** 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;
+
+#ifdef DFS_TESTING_SUPPORT
+/** 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;
+} wlan_dfs_testing_settings_t;
+#endif /* DFS_SUPPORT_TESTING */
+
+/**
+ * @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;
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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++;
+}
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** 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;
+#endif
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+/** 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 /* SDIO_MULTI_PORT_RX_AGGR */
+
+/** mlan_init_para structure */
+typedef struct _mlan_init_para {
+#ifdef MFG_CMD_SUPPORT
+    /** MFG mode */
+	t_u32 mfg_mode;
+#endif
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** 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;
+    /** FW download CRC check flag */
+	t_u32 fw_crc_check;
+    /** dev cap mask */
+	t_u32 dev_cap_mask;
+    /** oob independent reset mode */
+	t_u32 indrstcfg;
+	t_u32 drcs_chantime_mode;
+} mlan_init_para, *pmlan_init_para;
+/** mlan sdio card register structure */
+typedef struct _mlan_sdio_card_reg {
+    /** start read port */
+	t_u8 start_rd_port;
+    /** start write port */
+	t_u8 start_wr_port;
+    /** base 0 register */
+	t_u8 base_0_reg;
+    /** base 1 register */
+	t_u8 base_1_reg;
+    /** poll register */
+	t_u8 poll_reg;
+    /** host interrupt enable */
+	t_u8 host_int_enable;
+    /** host interrupt status */
+	t_u8 host_int_status;
+    /** status register 0 */
+	t_u8 status_reg_0;
+    /** status register 1 */
+	t_u8 status_reg_1;
+    /** sdio interrupt mask */
+	t_u8 sdio_int_mask;
+    /** data port mask */
+	t_u32 data_port_mask;
+    /** maximum mp register */
+	t_u8 max_mp_regs;
+    /** read bitmap lower byte */
+	t_u8 rd_bitmap_l;
+    /** read bitmap upper byte */
+	t_u8 rd_bitmap_u;
+    /** read bitmap_1 lower byte */
+	t_u8 rd_bitmap_1l;
+    /** read bitmap_1 upper byte */
+	t_u8 rd_bitmap_1u;
+    /** write bitmap lower byte */
+	t_u8 wr_bitmap_l;
+     /** write bitmap upper byte */
+	t_u8 wr_bitmap_u;
+    /** write bitmap_1 lower byte */
+	t_u8 wr_bitmap_1l;
+    /** write bitmap_1 upper byte */
+	t_u8 wr_bitmap_1u;
+    /** read port0 length lower byte */
+	t_u8 rd_len_p0_l;
+    /** read port0 length upper byte */
+	t_u8 rd_len_p0_u;
+    /** card misc configuration register */
+	t_u8 card_misc_cfg_reg;
+    /** scratch reg used for reset */
+	t_u8 reset_reg;
+    /** reset value */
+	t_u8 reset_val;
+} mlan_sdio_card_reg, *pmlan_sdio_card_reg;
+
+/** ampdu info */
+typedef struct _ampdu_info {
+    /** staion tx win_size */
+	t_u32 ampdu_sta_txwinsize;
+    /** uap tx win_size */
+	t_u32 ampdu_uap_txwinsize;
+    /** uap rx win_size */
+	t_u32 ampdu_uap_rxwinsize;
+#ifdef WIFI_DIRECT_SUPPORT
+    /** wfd tx/rx winsize */
+	t_u32 ampdu_wfd_txrxwinsize;
+#endif
+} ampdu_info;
+/** mlan sdio device structure */
+typedef struct _mlan_sdio_device {
+    /** reg */
+	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;
+    /** control mask */
+	t_bool has_control_mask;
+    /** more option */
+	t_u8 card_config_2_1_reg;	//8897:0xCD, 8887:0xD9
+	t_u8 cmd_config_0;	//CMD_CONFIG_0 8897:0xB8 8887:0xC4
+	t_u8 cmd_config_1;	//CMD_CONFIG_1 8897:0xB9, 8887:0xC5
+	t_u8 cmd_rd_len_0;	//CMD_RD_LEN_0 8897:0xB4, 8887:0xC0
+	t_u8 cmd_rd_len_1;	//CMD_RD_LEN_1   8897:0xB5, 8887:0xC1
+	t_u8 io_port_0_reg;	//IO_PORT_0_REG
+	t_u8 io_port_1_reg;	//IO_PORT_1_REG
+	t_u8 io_port_2_reg;	//IO_PORT_2_REG
+	t_u8 host_int_rsr_reg;	//HOST_INT_RSR_REG
+	t_u8 card_rx_len_reg;	//CARD_RX_LEN_REG
+	t_u8 card_rx_unit_reg;	//CARD_RX_UNIT_REG
+	t_u8 host_int_mask_reg;	//HOST_INT_MASK_REG
+	t_u8 host_int_status_reg;	//HOST_INT_STATUS_REG
+	t_u32 mp_tx_aggr_buf_size;
+	t_u32 mp_rx_aggr_buf_size;
+    /** Max Tx buffer size */
+	t_u32 max_tx_buf_size;
+    /** support V15_UPDATE */
+	t_u8 v15_update;
+    /** support V15_FW_API */
+	t_u8 v15_fw_api;
+    /** support V16_FW_API */
+	t_u8 v16_fw_api;
+    /** support ext_scan */
+	t_u8 ext_scan;
+    /** support fw reload */
+	t_u8 fw_reload;
+	/** ampdu info*/
+	ampdu_info *ampdu_info;
+} mlan_sdio_device, *pmlan_sdio_device;
+
+/** 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;
+    /** more_rx_task_flag */
+	t_u32 more_rx_task_flag;
+    /** rx_proc_lock for main_rx_process */
+	t_void *prx_proc_lock;
+    /** 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 */
+	t_u8 flush_data;
+    /** IO port */
+	t_u32 ioport;
+
+    /** STATUS variables */
+	WLAN_HARDWARE_STATUS hw_status;
+    /** PnP SUPPORT */
+	t_u8 surprise_removed;
+
+    /** ECSA support */
+	t_u8 ecsa_enable;
+
+    /** Get log support */
+	t_u8 getlog_enable;
+
+    /** Radio on flag */
+	t_u16 radio_on;
+
+    /** Firmware release number */
+	t_u32 fw_release_number;
+    /** firmware version */
+	t_u8 fw_ver;
+    /** firmware minor version */
+	t_u8 fw_min_ver;
+    /** uap firmware version */
+	t_u8 uap_fw_ver;
+    /** mac address retrun from get_hw_spec */
+	t_u8 permanent_addr[MLAN_MAC_ADDR_LENGTH];
+    /** Number of antenna used */
+	t_u16 number_of_antenna;
+    /** antenna info */
+	t_u8 antinfo;
+    /** Firmware capability information */
+	t_u32 fw_cap_info;
+    /** pint_lock for interrupt handling */
+	t_void *pint_lock;
+	const mlan_sdio_device *psdio_device;
+	t_u16 card_type;
+    /** Interrupt status */
+	t_u8 sdio_ireg;
+    /** 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/* see blk_queue_max_segment_size */
+	t_u32 max_seg_size;
+	/* see blk_queue_max_segments */
+	t_u16 max_segs;
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	/** data structure for SDIO MPA TX */
+	sdio_mpa_tx mpa_tx;
+    /** packet number for tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+    /** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+    /** last wr_bitmap from FW */
+	t_u32 last_recv_wr_bitmap;
+    /** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+    /** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+    /** last length for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+    /** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+
+    /** buffer for mp debug */
+	t_u8 *mpa_buf;
+    /** length info for mp buf size */
+	t_u32 mpa_buf_size;
+
+    /** last mp_index */
+	t_u8 last_mp_index;
+#endif				/* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	/** 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];
+#endif				/* SDIO_MULTI_PORT_RX_AGGR */
+
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+
+    /** Event cause */
+	t_u32 event_cause;
+    /** Event buffer */
+	pmlan_buffer pmlan_buffer_event;
+    /** Upload length */
+	t_u32 upld_len;
+    /** Upload buffer*/
+	t_u8 upld_buf[WLAN_UPLD_SIZE];
+    /** Data sent:
+     *       TRUE - Data is sent to fw, no Tx Done received
+     *       FALSE - Tx done received for previous Tx
+     */
+	t_u8 data_sent;
+    /** CMD sent:
+     *       TRUE - CMD is sent to fw, no CMD Done received
+     *       FALSE - CMD done received for previous CMD
+     */
+	t_u8 cmd_sent;
+    /** CMD Response received:
+     *       TRUE - CMD is response is received from fw, and yet to process
+     *       FALSE - No cmd response to process
+     */
+	t_u8 cmd_resp_received;
+    /** Event received:
+     *       TRUE - Event received from fw, and yet to process
+     *       FALSE - No events to process
+     */
+	t_u8 event_received;
+
+    /** Data received:
+     *       TRUE - Data received from fw
+     *       FALSE - No Data received
+     */
+	t_u8 data_received;
+
+    /** Command-related variables */
+    /** Command sequence number */
+	t_u16 seq_num;
+    /** Command controller nodes */
+	cmd_ctrl_node *cmd_pool;
+    /** Current Command */
+	cmd_ctrl_node *curr_cmd;
+    /** mlan_lock for command */
+	t_void *pmlan_cmd_lock;
+    /** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+    /** Last init fw command id */
+	t_u16 last_init_cmd;
+    /** Command timer */
+	t_void *pmlan_cmd_timer;
+    /** Command timer set flag */
+	t_u8 cmd_timer_is_set;
+    /** time stamp for command dnld */
+	t_u32 dnld_cmd_in_secs;
+
+    /** Command Queues */
+    /** Free command buffers */
+	mlan_list_head cmd_free_q;
+    /** Pending command buffers */
+	mlan_list_head cmd_pending_q;
+    /** Command queue for scanning */
+	mlan_list_head scan_pending_q;
+    /** ioctl pending queue */
+	mlan_list_head ioctl_pending_q;
+    /** pending_ioctl flag */
+	t_u8 pending_ioctl;
+    /** mlan_processing */
+	t_u32 scan_processing;
+    /** 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 */
+	wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+#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;
+#ifdef DFS_TESTING_SUPPORT
+    /** User configured settings for DFS testing */
+	wlan_dfs_testing_settings_t dfs_test_params;
+#endif
+    /** 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;
+    /** Scan block flag */
+	t_u8 scan_block;
+    /** Extended scan or legacy scan */
+	t_u8 ext_scan;
+	t_u16 bcn_buf_size;
+    /** Beacon buffer */
+	t_u8 *bcn_buf;
+    /** Pointer to valid beacon buffer end */
+	t_u8 *pbcn_buf_end;
+    /** allocate fixed scan beacon buffer size*/
+	t_u32 fixed_beacon_buffer;
+
+    /** F/W supported bands */
+	t_u8 fw_bands;
+    /** User selected band to start adhoc network */
+	t_u8 adhoc_start_band;
+    /** User selected bands */
+	t_u8 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;
+	/** Multi channel status */
+	t_u8 mc_status;
+
+    /** 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;
+
+    /** 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;
+
+    /** AdHoc awake period */
+	t_u16 adhoc_awake_period;
+
+    /** Firmware wakeup method */
+	t_u16 fw_wakeup_method;
+    /** Firmware wakeup GPIO pin */
+	t_u8 fw_wakeup_gpio_pin;
+    /** 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;
+
+    /** 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;
+    /** 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
+    /** Enable 11n support for adhoc start */
+	t_u8 adhoc_11n_enabled;
+    /** 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;
+
+    /** 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;
+    /** management frame wakeup filter config */
+	mlan_mgmt_frame_wakeup mgmt_filter[MAX_MGMT_FRAME_FILTER];
+
+    /** Bypass TX queue pkt count  */
+	t_u16 bypass_pkt_count;
+#if defined(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;
+    /** NetMon enabled */
+	t_u32 enable_net_mon;
+    /** Feature control bitmask */
+	t_u32 feature_control;
+
+    /** Control coex RX window size configuration */
+	t_u8 coex_rx_winsize;
+    /** multi channel policy */
+	t_bool mc_policy;
+    /**channel param band config */
+	t_u8 chanrpt_param_bandcfg;
+    /** maximum station connection */
+	t_u8 max_sta_conn;
+} 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)
+
+/** Ethernet packet type for EAPOL */
+#define MLAN_ETHER_PKT_TYPE_EAPOL	(0x888E)
+/** 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_cmd_net_monitor(IN HostCmd_DS_COMMAND *cmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_net_monitor(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_net_monitor(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+
+void wlan_rxpdinfo_to_radiotapinfo(pmlan_private priv,
+				   RxPD *prx_pd, radiotap_info * prt_info);
+
+mlan_status wlan_init_lock_list(IN pmlan_adapter pmadapter);
+mlan_status wlan_init_priv_lock_list(IN pmlan_adapter pmadapter,
+				     t_u8 start_index);
+t_void wlan_free_lock_list(IN pmlan_adapter pmadapter);
+mlan_status wlan_init_timer(IN pmlan_adapter pmadapter);
+t_void wlan_free_timer(IN pmlan_adapter pmadapter);
+
+/* Function prototype */
+/** Download firmware */
+mlan_status wlan_dnld_fw(IN pmlan_adapter pmadapter, IN pmlan_fw_image pmfw);
+
+/** Initialize firmware */
+mlan_status wlan_init_fw(IN pmlan_adapter pmadapter);
+
+/** get hw spec complete */
+mlan_status wlan_get_hw_spec_complete(IN pmlan_adapter pmadapter);
+
+/** Initialize firmware complete */
+mlan_status wlan_init_fw_complete(IN pmlan_adapter pmadapter);
+
+/** Shutdown firmware complete */
+mlan_status wlan_shutdown_fw_complete(IN 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(IN pmlan_adapter pmadapter);
+
+/** Initialize mlan_private structure */
+mlan_status wlan_init_priv(IN pmlan_private priv);
+
+/** Process event */
+mlan_status wlan_process_event(pmlan_adapter pmadapter);
+
+/** Prepare command */
+mlan_status wlan_prepare_cmd(IN pmlan_private priv,
+			     IN t_u16 cmd_no,
+			     IN t_u16 cmd_action,
+			     IN t_u32 cmd_oid,
+			     IN t_void *pioctl_buf, IN t_void *pdata_buf);
+
+/** cmd timeout handler */
+t_void wlan_cmd_timeout_func(t_void *function_context);
+/** process host cmd */
+mlan_status wlan_misc_ioctl_host_cmd(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req);
+/** process init/shutdown cmd*/
+mlan_status wlan_misc_ioctl_init_shutdown(IN pmlan_adapter pmadapter,
+					  IN pmlan_ioctl_req pioctl_req);
+/** process debug info */
+mlan_status wlan_get_info_debug_info(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req);
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/** Set/Get BSS role */
+mlan_status wlan_bss_ioctl_bss_role(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_set_ewpa_mode(mlan_private *priv, mlan_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(IN mlan_adapter *pmadapter);
+/** Free command buffer */
+mlan_status wlan_free_cmd_buffer(IN mlan_adapter *pmadapter);
+/** Request command lock */
+t_void wlan_request_cmd_lock(mlan_adapter *pmadapter);
+/** Release command lock */
+t_void wlan_release_cmd_lock(mlan_adapter *pmadapter);
+#ifdef STA_SUPPORT
+/** Flush the scan pending queue */
+t_void wlan_flush_scan_queue(pmlan_adapter pmadapter);
+mlan_status wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+					 pmlan_ioctl_req pioctl_req);
+#endif
+/**Cancel pending command */
+t_void wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter);
+/**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(IN mlan_adapter *pmadapter,
+				 IN cmd_ctrl_node *pcmd_node);
+
+/** Insert command to pending queue */
+t_void wlan_insert_cmd_to_pending_q(IN mlan_adapter *pmadapter,
+				    IN cmd_ctrl_node *pcmd_node,
+				    IN 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);
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+mlan_status wlan_alloc_sdio_mpa_buffers(IN mlan_adapter *pmadapter,
+					t_u32 mpa_tx_buf_size,
+					t_u32 mpa_rx_buf_size);
+
+mlan_status wlan_free_sdio_mpa_buffers(IN mlan_adapter *pmadapter);
+#endif
+
+/** Process write data complete */
+mlan_status wlan_write_data_complete(pmlan_adapter pmlan_adapter,
+				     pmlan_buffer pmbuf, mlan_status status);
+/** 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)
+
+/** 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,
+				    IN HostCmd_DS_COMMAND *cmd,
+				    IN t_u16 cmd_action,
+				    IN t_u16 ps_bitmap, IN t_void *pdata_buf);
+/** handle command resp for enhanced power save mode */
+mlan_status wlan_ret_enh_power_mode(IN pmlan_private pmpriv,
+				    IN HostCmd_DS_COMMAND *resp,
+				    IN mlan_ioctl_req *pioctl_buf);
+
+/** handle commnand for cfg data */
+mlan_status wlan_cmd_cfg_data(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *pcmd,
+			      IN t_u16 cmd_action,
+			      IN t_u32 cmd_oid, IN t_void *pdata_buf);
+/** handle command resp for cfg data */
+mlan_status wlan_ret_cfg_data(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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);
+
+mlan_status wlan_pm_reset_card(pmlan_adapter adapter);
+mlan_status wlan_pm_wakeup_card(pmlan_adapter pmadapter);
+
+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);
+
+#ifdef WIFI_DIRECT_SUPPORT
+mlan_status wlan_bss_ioctl_wifi_direct_mode(IN pmlan_adapter pmadapter,
+					    IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_wifi_direct_mode(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_u16 cmd_action,
+				      IN t_void *pdata_buf);
+mlan_status wlan_ret_wifi_direct_mode(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_p2p_params_config(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+mlan_status wlan_ret_p2p_params_config(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *resp,
+				       IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_p2p_config(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req);
+#endif
+/** get ralist info */
+int wlan_get_ralist_info(mlan_private *priv, ralist_info *buf);
+/** dump ralist */
+void wlan_dump_ralist(mlan_private *priv);
+
+/** get pm info */
+mlan_status wlan_get_pm_info(IN pmlan_adapter pmadapter,
+			     IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_bss_ioctl_bss_remove(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_config_mgmt_filter(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_get_hs_wakeup_reason(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_hs_wakeup_reason(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_void *pdata_buf);
+
+mlan_status wlan_ret_hs_wakeup_reason(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_radio_ioctl_radio_ctl(IN pmlan_adapter pmadapter,
+				       IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_radio_ioctl_remain_chan_cfg(IN pmlan_adapter pmadapter,
+					     IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_remain_on_channel(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+mlan_status wlan_ret_remain_on_channel(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *resp,
+				       IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_radio_ioctl_ant_cfg(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *cmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_cfg(IN pmlan_adapter pmadapter,
+				IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_get_data_rate(IN pmlan_adapter pmadapter,
+					  IN 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(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN mlan_ioctl_req *pioctl_buf);
+/** Sends HS_WAKEUP event to applications */
+t_void wlan_host_sleep_wakeup_event(pmlan_private priv);
+
+mlan_status wlan_cmd_802_11_fw_wakeup_method(IN pmlan_private pmpriv,
+					     IN HostCmd_DS_COMMAND *cmd,
+					     IN t_u16 cmd_action,
+					     IN t_u16 *pdata_buf);
+mlan_status wlan_ret_fw_wakeup_method(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_fw_wakeup_method(IN pmlan_adapter pmadapter,
+				  IN pmlan_ioctl_req pioctl_req);
+
+/** Prepares command of robustcoex */
+mlan_status wlan_cmd_robustcoex(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_u16 *pdata_buf);
+/** Set Robustcoex gpiocfg */
+mlan_status wlan_misc_robustcoex(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req);
+
+/** send get hw spec command to firmware */
+mlan_status wlan_adapter_get_hw_spec(IN pmlan_adapter pmadapter);
+/** send adapter specific init cmd to firmware */
+mlan_status wlan_adapter_init_cmd(IN pmlan_adapter pmadapter);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status wlan_cmd_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
+					 IN HostCmd_DS_COMMAND *cmd,
+					 IN t_u16 cmd_action,
+					 IN t_void *pdata_buf);
+mlan_status wlan_ret_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
+					 const IN HostCmd_DS_COMMAND *resp,
+					 OUT mlan_ioctl_req *pioctl_buf);
+#endif
+mlan_status wlan_handle_event_multi_chan_info(IN pmlan_private pmpriv,
+					      pmlan_buffer pevent);
+
+#ifdef STA_SUPPORT
+/** warm reset */
+mlan_status wlan_misc_ioctl_warm_reset(IN pmlan_adapter pmadapter,
+				       IN 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(IN t_void *priv,
+				     IN t_u16 cmd_no,
+				     IN t_u16 cmd_action,
+				     IN t_u32 cmd_oid,
+				     IN t_void *pioctl_buf,
+				     IN t_void *pdata_buf, IN t_void *pcmd_buf);
+
+/** cmdresp handler for station mode */
+mlan_status wlan_ops_sta_process_cmdresp(IN t_void *priv,
+					 IN t_u16 cmdresp_no,
+					 IN t_void *pcmd_buf,
+					 IN t_void *pioctl);
+
+/** rx handler for station mode */
+mlan_status wlan_ops_sta_process_rx_packet(IN t_void *adapter,
+					   IN pmlan_buffer pmbuf);
+
+/** event handler for station mode */
+mlan_status wlan_ops_sta_process_event(IN t_void *priv);
+
+/** fill txpd for station mode */
+t_void *wlan_ops_sta_process_txpd(IN t_void *priv, IN pmlan_buffer pmbuf);
+
+/** send init cmd to firmware for station mode */
+mlan_status wlan_ops_sta_init_cmd(IN t_void *priv, IN t_u8 first_bss);
+
+/** Flush the scan table */
+mlan_status wlan_flush_scan_table(IN pmlan_adapter pmadapter);
+
+/** Scan for networks */
+mlan_status wlan_scan_networks(IN mlan_private *pmpriv,
+			       IN t_void *pioctl_buf,
+			       IN wlan_user_scan_cfg *puser_scan_in);
+
+/** Scan for specific SSID */
+mlan_status wlan_scan_specific_ssid(IN mlan_private *pmpriv,
+				    IN t_void *pioctl_buf,
+				    IN mlan_802_11_ssid *preq_ssid);
+
+/** Scan command handler */
+mlan_status wlan_cmd_802_11_scan(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *pcmd,
+				 IN t_void *pdata_buf);
+
+/** Handler for scan command response */
+mlan_status wlan_ret_802_11_scan(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN t_void *pioctl_buf);
+
+/** Extended scan command handler */
+mlan_status wlan_cmd_802_11_scan_ext(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *pcmd,
+				     IN t_void *pdata_buf);
+/** Handler for extended scan command response */
+mlan_status wlan_ret_802_11_scan_ext(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *resp,
+				     IN t_void *pioctl_buf);
+/** Handler event for extended scan report */
+mlan_status wlan_handle_event_ext_scan_report(IN mlan_private *pmpriv,
+					      IN mlan_buffer *pmbuf);
+
+/** check network compatibility */
+t_s32 wlan_is_network_compatible(IN mlan_private *pmpriv,
+				 IN t_u32 index, IN t_u32 mode);
+
+/** Find an SSID in a list */
+t_s32 wlan_find_ssid_in_list(IN pmlan_private pmpriv,
+			     IN mlan_802_11_ssid *ssid,
+			     IN t_u8 *bssid, IN t_u32 mode);
+
+/** Find a BSSID in a list */
+t_s32 wlan_find_bssid_in_list(IN mlan_private *pmpriv,
+			      IN t_u8 *bssid, IN t_u32 mode);
+
+/** Find best network */
+mlan_status wlan_find_best_network(IN mlan_private *pmpriv,
+				   OUT mlan_ssid_bssid *preq_ssid_bssid);
+
+/** Compare two SSIDs */
+t_s32 wlan_ssid_cmp(IN pmlan_adapter pmadapter,
+		    IN mlan_802_11_ssid *ssid1, IN mlan_802_11_ssid *ssid2);
+
+/** Associate */
+mlan_status wlan_associate(IN mlan_private *pmpriv,
+			   IN t_void *pioctl_buf, IN BSSDescriptor_t *pBSSDesc);
+
+/** Associate command handler */
+mlan_status wlan_cmd_802_11_associate(IN mlan_private *pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_void *pdata_buf);
+
+/** Handler for association command response */
+mlan_status wlan_ret_802_11_associate(IN mlan_private *pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN t_void *pioctl_buf);
+
+/** Reset connected state */
+t_void wlan_reset_connect_state(IN pmlan_private priv, IN 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(IN t_u8 band);
+/** convert radio_type to band */
+t_u8 radio_type_to_band(t_u8 chanBand);
+
+/** Disconnect */
+mlan_status wlan_disconnect(IN mlan_private *pmpriv,
+			    IN mlan_ioctl_req *pioctl_req,
+			    IN mlan_deauth_param *deauth_param);
+
+/** Ad-Hoc start */
+mlan_status wlan_adhoc_start(IN mlan_private *pmpriv,
+			     IN t_void *pioctl_buf,
+			     IN mlan_802_11_ssid *padhoc_ssid);
+
+/** Ad-Hoc join */
+mlan_status wlan_adhoc_join(IN mlan_private *pmpriv,
+			    IN t_void *pioctl_buf,
+			    IN BSSDescriptor_t *pBSSDesc);
+
+/** Ad-Hoc start command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_start(IN mlan_private *pmpriv,
+					 IN HostCmd_DS_COMMAND *cmd,
+					 IN t_void *pdata_buf);
+
+/** Ad-Hoc command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_join(IN mlan_private *pmpriv,
+					IN HostCmd_DS_COMMAND *cmd,
+					IN t_void *pdata_buf);
+
+/** Handler for Ad-Hoc commands */
+mlan_status wlan_ret_802_11_ad_hoc(IN mlan_private *pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN t_void *pioctl_buf);
+
+/** Handler for bgscan query commands */
+mlan_status wlan_cmd_802_11_bg_scan_query(IN mlan_private *pmpriv,
+					  IN HostCmd_DS_COMMAND *pcmd,
+					  IN t_void *pdata_buf);
+/** Handler for bgscan config command */
+mlan_status wlan_cmd_bgscan_config(IN mlan_private *pmpriv,
+				   IN HostCmd_DS_COMMAND *pcmd,
+				   IN t_void *pdata_buf);
+/** Hander for bgscan config command response */
+mlan_status wlan_ret_bgscan_config(IN mlan_private *pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_802_11_bgscan_query(IN mlan_private *pmpriv,
+					 IN HostCmd_DS_COMMAND *resp,
+					 IN 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(IN mlan_private *pmpriv);
+/*  Free a beacon buffer of the current bss descriptor */
+t_void wlan_free_curr_bcn(IN mlan_private *pmpriv);
+
+#endif /* STA_SUPPORT */
+
+/* Rate related functions */
+t_u8 wlan_convert_v14_rate_ht_info(t_u8 ht_info);
+/** Convert index into data rate */
+t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index,
+			      t_u8 rate_info);
+/** Get active data rates */
+t_u32 wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
+				 t_u8 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_u8 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);
+
+/* 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 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 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(IN pmlan_adapter pmadapter,
+				     IN mlan_ioctl_req *pioctl_req);
+
+/** This function converts region string to CFP table code */
+mlan_status wlan_misc_country_2_cfp_table_code(IN pmlan_adapter pmadapter,
+					       IN t_u8 *country_code,
+					       OUT t_u8 *cfp_bg,
+					       OUT 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 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_void 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(IN mlan_private *priv,
+				       IN 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(IN mlan_private *priv, IN pmlan_buffer pmbuf);
+#endif /* UAP_SUPPORT */
+
+mlan_status wlan_misc_ioctl_coalescing_status(IN pmlan_adapter pmadapter,
+					      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req,
+					   IN t_bool send_ioctl);
+
+mlan_status wlan_cmd_get_hw_spec(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *pcmd);
+mlan_status wlan_ret_get_hw_spec(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN t_void *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_mac_control(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *pcmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_mac_control(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_radio_control(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *cmd,
+					  IN t_u16 cmd_action,
+					  IN t_void *pdata_buf);
+mlan_status wlan_ret_802_11_radio_control(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_rf_antenna(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+mlan_status wlan_ret_802_11_rf_antenna(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *resp,
+				       IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_ret_reg_access(mlan_adapter *pmadapter,
+				t_u16 type,
+				IN HostCmd_DS_COMMAND *resp,
+				IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_mem_access(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *resp,
+				IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_reg_mem_ioctl_reg_rw(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_read_eeprom(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_mem_rw(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_reg_access(IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_cmd_mem_access(IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_void *pdata_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(IN pmlan_adapter pmadapter,
+					IN 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(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status
+
+wlan_misc_ioctl_tdls_get_ies(IN pmlan_adapter pmadapter,
+			     IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_tdls_idle_time(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req);
+
+t_void wlan_tdls_config(IN pmlan_private pmpriv, IN t_u8 enable);
+mlan_status wlan_misc_ioctl_tdls_cs_channel(IN pmlan_adapter pmadapter,
+					    IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_get_info_ver_ext(IN pmlan_adapter pmadapter,
+				  IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_ioctl_link_statistic(IN mlan_private *pmpriv,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_802_11_link_statistic(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *cmd,
+					   IN t_u16 cmd_action,
+					   IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_ret_get_link_statistic(IN pmlan_private pmpriv,
+					IN HostCmd_DS_COMMAND *resp,
+					IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_reg_rx_mgmt_ind(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req);
+
+#ifdef DEBUG_LEVEL1
+mlan_status wlan_set_drvdbg(IN pmlan_adapter pmadapter,
+			    IN pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_hotspot_cfg(IN pmlan_adapter pmadapter,
+				  IN pmlan_ioctl_req pioctl_req);
+#ifdef STA_SUPPORT
+mlan_status wlan_misc_ext_capa_cfg(IN pmlan_adapter pmadapter,
+				   IN pmlan_ioctl_req pioctl_req);
+
+t_u32 wlan_is_ext_capa_support(IN mlan_private *pmpriv);
+#endif
+
+#ifdef STA_SUPPORT
+void wlan_add_ext_capa_info_ie(IN mlan_private *pmpriv, OUT t_u8 **pptlv_out);
+#endif
+
+mlan_status wlan_cmd_boot_sleep(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_boot_sleep(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *resp,
+				IN mlan_ioctl_req *pioctl_buf);
+
+#define BW_20MHZ  0
+#define BW_40MHZ  1
+#define BW_80MHZ  2
+#define BW_160MHZ 3
+int wlan_add_supported_oper_class_ie(IN mlan_private *pmpriv,
+				     OUT 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(IN pmlan_adapter pmadapter,
+						 IN mlan_ioctl_req *pioctl_req);
+mlan_status wlan_misc_ioctl_oper_class(IN pmlan_adapter pmadapter,
+				       IN mlan_ioctl_req *pioctl_req);
+
+t_u8 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(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_txcontrol(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_region(IN pmlan_adapter pmadapter,
+				   IN pmlan_ioctl_req pioctl_req);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status
+
+wlan_misc_ioctl_rx_pkt_coalesce_config(IN pmlan_adapter pmadapter,
+				       IN pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_ioctl_multi_chan_config(IN pmlan_adapter pmadapter,
+					      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_multi_chan_cfg(IN pmlan_private pmpriv,
+				    IN HostCmd_DS_COMMAND *cmd,
+				    IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_multi_chan_cfg(IN pmlan_private pmpriv,
+				    const IN HostCmd_DS_COMMAND *resp,
+				    OUT mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_multi_chan_policy(IN pmlan_adapter pmadapter,
+					      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_multi_chan_policy(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+
+mlan_status wlan_ret_multi_chan_policy(IN pmlan_private pmpriv,
+				       const IN HostCmd_DS_COMMAND *resp,
+				       OUT mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_drcs_config(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_drcs_cfg(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_drcs_cfg(IN pmlan_private pmpriv,
+			      const IN HostCmd_DS_COMMAND *resp,
+			      OUT mlan_ioctl_req *pioctl_buf);
+
+void wlan_bt_coex_wlan_param_update_event(pmlan_private priv,
+					  pmlan_buffer pevent);
+
+mlan_status wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,
+					 IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_low_pwr_mode(IN pmlan_adapter pmadapter,
+					 IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_pmic_configure(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_ind_rst_cfg(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_ind_rst_cfg(IN HostCmd_DS_COMMAND *cmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_ind_rst_cfg(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_supplicant_pmk(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *cmd,
+					   IN t_u16 cmd_action,
+					   IN t_void *pdata_buf);
+
+mlan_status wlan_ret_802_11_supplicant_pmk(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *resp,
+					   IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_sec_ioctl_passphrase(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_get_tsf(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_get_cfpinfo(IN pmlan_adapter pmadapter,
+			     IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_acs(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_acs(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_acs(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_get_tsf(pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action);
+mlan_status wlan_ret_get_tsf(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf);
+
+t_u8 wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie);
+
+mlan_status wlan_cmd_ps_inactivity_timeout(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *cmd,
+					   IN t_u16 cmd_action,
+					   IN t_void *pdata_buf);
+
+t_u8 wlan_get_center_freq_idx(IN mlan_private *pmpriv,
+			      IN t_u8 band, IN t_u32 pri_chan, IN t_u8 chan_bw);
+
+mlan_status wlan_misc_ioctl_fw_dump_event(IN pmlan_adapter pmadapter,
+					  IN mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_fw_dump_event(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *cmd,
+				   IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_misc_bootsleep(IN pmlan_adapter pmadapter,
+				IN pmlan_ioctl_req pioctl_req);
+
+/**
+ *  @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) (IN pmlan_private pmpriv),
+		     t_bool (*check_cond) (IN 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) (IN pmlan_private pmpriv),
+		      t_bool (*check_cond) (IN 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) (IN 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) (IN pmlan_private pmpriv),
+			   t_bool (*check_cond_2) (IN 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_sd8897/mlan/mlan_meas.c b/wlan_sd8897/mlan/mlan_meas.c
new file mode 100644
index 0000000..f8e4209
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_meas.c
@@ -0,0 +1,463 @@
+/**
+ * @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 (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+Change Log:
+    03/24/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_ioctl.h"
+#include "mlan_meas.h"
+
+/** Default measurement duration when not provided by the application */
+#define WLAN_MEAS_DEFAULT_MEAS_DURATION    1000U	/* TUs */
+
+#ifdef DEBUG_LEVEL2
+/** String descriptions of the different measurement enums.  Debug display */
+static const char *meas_type_str[WLAN_MEAS_NUM_TYPES] = {
+	"basic",
+};
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief Retrieve the measurement string representation of a meas_type enum
+ *  Used for debug display only
+ *
+ *  @param meas_type Measurement type enumeration input for string lookup
+ *
+ *  @return         Constant string representing measurement type
+ */
+static const char *
+wlan_meas_get_meas_type_str(MeasType_t meas_type)
+{
+	if (meas_type <= WLAN_MEAS_11H_MAX_TYPE)
+		return meas_type_str[meas_type];
+
+	return "Invld";
+}
+#endif
+
+/**
+ *  @brief Debug print display of the input measurement request
+ *
+ *  @param pmeas_req  Pointer to the measurement request to display
+ *
+ *  @return          N/A
+ */
+static
+	void
+wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req)
+{
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+
+	PRINTM(MINFO, "Meas: Req: mac_addr: " MACSTR "\n",
+	       MAC2STR(pmeas_req->mac_addr));
+
+	PRINTM(MINFO, "Meas: Req:  dlgTkn: %d\n", pmeas_req->dialog_token);
+	PRINTM(MINFO, "Meas: Req:    mode: dm[%c] rpt[%c] req[%c]\n",
+	       pmeas_req->req_mode.duration_mandatory ? 'X' : ' ',
+	       pmeas_req->req_mode.report ? 'X' : ' ',
+	       pmeas_req->req_mode.request ? 'X' : ' ');
+	PRINTM(MINFO, "Meas: Req:        : en[%c] par[%c]\n",
+	       pmeas_req->req_mode.enable ? 'X' : ' ',
+	       pmeas_req->req_mode.parallel ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+	PRINTM(MINFO, "Meas: Req: measTyp: %s\n",
+	       wlan_meas_get_meas_type_str(pmeas_req->meas_type));
+#endif
+
+	switch (pmeas_req->meas_type) {
+	case WLAN_MEAS_BASIC:
+		/* Lazy cheat, fields of bas, cca, rpi union match on the request */
+		PRINTM(MINFO, "Meas: Req: chan: %u\n",
+		       pmeas_req->req.basic.channel);
+		PRINTM(MINFO, "Meas: Req: strt: %llu\n",
+		       wlan_le64_to_cpu(pmeas_req->req.basic.start_time));
+		PRINTM(MINFO, "Meas: Req:  dur: %u\n",
+		       wlan_le16_to_cpu(pmeas_req->req.basic.duration));
+		break;
+	default:
+		PRINTM(MINFO, "Meas: Req: <unhandled>\n");
+		break;
+	}
+
+	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+	LEAVE();
+}
+
+/**
+ *  @brief Debug print display of the input measurement report
+ *
+ *  @param pmeas_rpt  Pointer to measurement report to display
+ *
+ *  @return          N/A
+ */
+static
+	void
+wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
+{
+	MeasType_t type;
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+	PRINTM(MINFO, "Meas: Rpt: mac_addr: " MACSTR "\n",
+	       MAC2STR(pmeas_rpt->mac_addr));
+
+	PRINTM(MINFO, "Meas: Rpt:  dlgTkn: %d\n", pmeas_rpt->dialog_token);
+
+	PRINTM(MINFO, "Meas: Rpt: rptMode: (%x): Rfs[%c] ICp[%c] Lt[%c]\n",
+	       *(t_u8 *)&pmeas_rpt->rpt_mode,
+	       pmeas_rpt->rpt_mode.refused ? 'X' : ' ',
+	       pmeas_rpt->rpt_mode.incapable ? 'X' : ' ',
+	       pmeas_rpt->rpt_mode.late ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+	PRINTM(MINFO, "Meas: Rpt: measTyp: %s\n",
+	       wlan_meas_get_meas_type_str(pmeas_rpt->meas_type));
+#endif
+
+	type = wlan_le32_to_cpu(pmeas_rpt->meas_type);
+	switch (type) {
+	case WLAN_MEAS_BASIC:
+		PRINTM(MINFO, "Meas: Rpt: chan: %u\n",
+		       pmeas_rpt->rpt.basic.channel);
+		PRINTM(MINFO, "Meas: Rpt: strt: %llu\n",
+		       wlan_le64_to_cpu(pmeas_rpt->rpt.basic.start_time));
+		PRINTM(MINFO, "Meas: Rpt:  dur: %u\n",
+		       wlan_le16_to_cpu(pmeas_rpt->rpt.basic.duration));
+		PRINTM(MINFO, "Meas: Rpt:  bas: (%x): unmsd[%c], radar[%c]\n",
+		       *(t_u8 *)&(pmeas_rpt->rpt.basic.map),
+		       pmeas_rpt->rpt.basic.map.unmeasured ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.radar ? 'X' : ' ');
+		PRINTM(MINFO, "Meas: Rpt:  bas: unidSig[%c] ofdm[%c] bss[%c]\n",
+		       pmeas_rpt->rpt.basic.map.unidentified_sig ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.ofdm_preamble ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.bss ? 'X' : ' ');
+		break;
+	default:
+		PRINTM(MINFO, "Meas: Rpt: <unhandled>\n");
+		break;
+	}
+
+	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+	LEAVE();
+}
+
+/**
+ *  @brief Retrieve a measurement report from the firmware
+ *
+ *  Callback from command processing when a measurement report is received
+ *    from the firmware.  Perform the following when a report is received:
+ *
+ *   -# Debug displays the report if compiled with the appropriate flags
+ *   -# If we are pending on a specific measurement report token, and it
+ *      matches the received report's token, store the report and wake up
+ *      any pending threads
+ *
+ *  @param pmpriv Private driver information structure
+ *  @param resp HostCmd_DS_COMMAND struct returned from the firmware command
+ *              passing a HostCmd_DS_MEASUREMENT_REPORT structure.
+ *
+ *  @return     MLAN_STATUS_SUCCESS
+ */
+static int
+wlan_meas_cmdresp_get_report(mlan_private *pmpriv,
+			     const HostCmd_DS_COMMAND *resp)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt = &resp->params.meas_rpt;
+
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Rpt: %#x-%u, Seq=%u, Ret=%u\n",
+	       resp->command, resp->size, resp->seq_num, resp->result);
+
+	/* Debug displays the measurement report */
+	wlan_meas_dump_meas_rpt(pmeas_rpt);
+
+	/*
+	 * Check if we are pending on a measurement report and it matches
+	 *  the dialog token of the received report:
+	 */
+	if (pmadapter->state_meas.meas_rpt_pend_on
+	    && pmadapter->state_meas.meas_rpt_pend_on ==
+	    pmeas_rpt->dialog_token) {
+		PRINTM(MINFO, "Meas: Rpt: RCV'd Pend on meas #%d\n",
+		       pmadapter->state_meas.meas_rpt_pend_on);
+
+		/* Clear the pending report indicator */
+		pmadapter->state_meas.meas_rpt_pend_on = 0;
+
+		/* Copy the received report into the measurement state for retrieval */
+		memcpy(pmadapter, &pmadapter->state_meas.meas_rpt_returned,
+		       pmeas_rpt,
+		       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(pmpriv->adapter, &pcmd_ptr->params.meas_req, pmeas_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(pmpriv->adapter, pcmd_ptr->params.meas_rpt.mac_addr,
+	       pmpriv->curr_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_sd8897/mlan/mlan_meas.h b/wlan_sd8897/mlan/mlan_meas.h
new file mode 100644
index 0000000..fa909a0
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_meas.h
@@ -0,0 +1,55 @@
+/**
+ *  @file mlan_meas.h
+ *
+ *  @brief Interface for the measurement module implemented in mlan_meas.c
+ *
+ *  Driver interface functions and type declarations for the measurement module
+ *    implemented in mlan_meas.c
+ *
+ *  @sa mlan_meas.c
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+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(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);
+
+/* 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_sd8897/mlan/mlan_misc.c b/wlan_sd8897/mlan/mlan_misc.c
new file mode 100644
index 0000000..b860309
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_misc.c
@@ -0,0 +1,5247 @@
+/**
+ * @file mlan_misc.c
+ *
+ *  @brief This file include miscellaneous functions for MLAN module
+ *
+ *  Copyright (C) 2009-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+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_sdio.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+extern mlan_operations *mlan_ops[];
+#endif
+extern t_u8 ac_to_tid[4][2];
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/** 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(IN pmlan_private pmpriv, IN 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(IN pmlan_private pmpriv,
+			      IN pmlan_ioctl_req pioctl_req,
+			      IN t_u16 mask,
+			      IN custom_ie *ie_data, OUT 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(IN pmlan_private pmpriv,
+			      IN pmlan_ioctl_req pioctl_req,
+			      IN custom_ie *ie_data, IN 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(pmpriv->adapter, del_ie, ie_data->ie_buffer,
+	       MIN(MAX_IE_SIZE, ie_data->ie_length));
+	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)
+			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(pmpriv->adapter, ie,
+				       pmpriv->mgmt_ie[index].ie_buffer, cnt);
+				if (pmpriv->mgmt_ie[index].ie_length >
+				    (cnt + del_len))
+					memcpy(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)));
+				memset(pmpriv->adapter,
+				       &pmpriv->mgmt_ie[index].ie_buffer, 0,
+				       sizeof(pmpriv->mgmt_ie[index].
+					      ie_buffer));
+				memcpy(pmpriv->adapter,
+				       &pmpriv->mgmt_ie[index].ie_buffer, ie,
+				       pmpriv->mgmt_ie[index].ie_length -
+				       del_len);
+				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     Do ACS
+ *
+ *  @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_acs(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_misc_acs *acs = MNULL;
+
+	ENTER();
+
+	if (pioctl_req != MNULL) {
+		misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+		acs = &misc->param.acs;
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	} else {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_ACS,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, (t_void *)acs);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(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;
+
+	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(IN pmlan_adapter pmadapter,
+			      IN 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(IN pmlan_adapter pmadapter,
+			 IN 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->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_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->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_tx_timeout = pmadapter->dbg.num_tx_timeout;
+		debug_info->num_cmd_timeout = pmadapter->num_cmd_timeout;
+		debug_info->dbg_num_cmd_timeout =
+			pmadapter->dbg.num_cmd_timeout;
+		debug_info->timeout_cmd_id = pmadapter->dbg.timeout_cmd_id;
+		debug_info->timeout_cmd_act = pmadapter->dbg.timeout_cmd_act;
+		memcpy(pmadapter, debug_info->last_cmd_id,
+		       pmadapter->dbg.last_cmd_id,
+		       sizeof(pmadapter->dbg.last_cmd_id));
+		memcpy(pmadapter, debug_info->last_cmd_act,
+		       pmadapter->dbg.last_cmd_act,
+		       sizeof(pmadapter->dbg.last_cmd_act));
+		debug_info->last_cmd_index = pmadapter->dbg.last_cmd_index;
+		memcpy(pmadapter, debug_info->last_cmd_resp_id,
+		       pmadapter->dbg.last_cmd_resp_id,
+		       sizeof(pmadapter->dbg.last_cmd_resp_id));
+		debug_info->last_cmd_resp_index =
+			pmadapter->dbg.last_cmd_resp_index;
+		memcpy(pmadapter, debug_info->last_event,
+		       pmadapter->dbg.last_event,
+		       sizeof(pmadapter->dbg.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;
+		debug_info->mp_rd_bitmap = pmadapter->mp_rd_bitmap;
+		debug_info->mp_wr_bitmap = pmadapter->mp_wr_bitmap;
+		debug_info->curr_rd_port = pmadapter->curr_rd_port;
+		debug_info->curr_wr_port = pmadapter->curr_wr_port;
+		debug_info->mp_invalid_update = pmadapter->mp_invalid_update;
+		debug_info->num_of_irq = pmadapter->num_of_irq;
+		memcpy(pmadapter, debug_info->mp_update, pmadapter->mp_update,
+		       sizeof(pmadapter->mp_update));
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+		memcpy(pmadapter, debug_info->mpa_tx_count,
+		       pmadapter->mpa_tx_count,
+		       sizeof(pmadapter->mpa_tx_count));
+		debug_info->mpa_sent_last_pkt = pmadapter->mpa_sent_last_pkt;
+		debug_info->mpa_sent_no_ports = pmadapter->mpa_sent_no_ports;
+		debug_info->last_recv_wr_bitmap =
+			pmadapter->last_recv_wr_bitmap;
+		debug_info->last_mp_index = pmadapter->last_mp_index;
+		memcpy(pmadapter, debug_info->last_mp_wr_bitmap,
+		       pmadapter->last_mp_wr_bitmap,
+		       sizeof(pmadapter->last_mp_wr_bitmap));
+		memcpy(pmadapter, debug_info->last_mp_wr_ports,
+		       pmadapter->last_mp_wr_ports,
+		       sizeof(pmadapter->last_mp_wr_ports));
+		memcpy(pmadapter, debug_info->last_mp_wr_len,
+		       pmadapter->last_mp_wr_len,
+		       sizeof(pmadapter->last_mp_wr_len));
+		memcpy(pmadapter, debug_info->last_mp_wr_info,
+		       pmadapter->last_mp_wr_info,
+		       sizeof(pmadapter->last_mp_wr_info));
+		memcpy(pmadapter, debug_info->last_curr_wr_port,
+		       pmadapter->last_curr_wr_port,
+		       sizeof(pmadapter->last_curr_wr_port));
+		debug_info->mpa_buf = pmadapter->mpa_buf;
+		debug_info->mpa_buf_size = pmadapter->mpa_buf_size;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+		memcpy(pmadapter, debug_info->mpa_rx_count,
+		       pmadapter->mpa_rx_count,
+		       sizeof(pmadapter->mpa_rx_count));
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+		debug_info->mp_aggr_pkt_limit =
+			pmadapter->psdio_device->mp_aggr_pkt_limit;
+#endif
+		debug_info->data_sent = pmadapter->data_sent;
+		debug_info->cmd_sent = pmadapter->cmd_sent;
+		debug_info->cmd_resp_received = pmadapter->cmd_resp_received;
+		debug_info->tx_pkts_queued =
+			util_scalar_read(pmadapter->pmoal_handle,
+					 &pmpriv->wmm.tx_pkts_queued, MNULL,
+					 MNULL);
+#ifdef UAP_SUPPORT
+		debug_info->num_bridge_pkts =
+			util_scalar_read(pmadapter->pmoal_handle,
+					 &pmadapter->pending_bridge_pkts,
+					 pmadapter->callbacks.moal_spin_lock,
+					 pmadapter->callbacks.moal_spin_unlock);
+		debug_info->num_drop_pkts = pmpriv->num_drop_pkts;
+#endif
+		debug_info->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(IN pmlan_adapter pmadapter,
+			    IN 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 function wakes up the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pm_wakeup_card(IN pmlan_adapter pmadapter)
+{
+	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 (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
+		/* GPIO_PORT_TO_LOW(); */
+	} else
+		ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+					  HOST_TO_CARD_EVENT_REG,
+					  HOST_POWER_UP);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function resets the PM setting of the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pm_reset_card(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
+		/* GPIO_PORT_TO_HIGH(); */
+	} else
+		ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+					  HOST_TO_CARD_EVENT_REG, 0);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter, IN 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 Get/Set the firmware wakeup method
+ *
+ *  @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_fw_wakeup_method(IN pmlan_adapter pmadapter, IN 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_pm_cfg *pmcfg = (mlan_ds_pm_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_FW_WAKE_METHOD,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &pmcfg->param.fw_wakeup_params);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter, IN 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 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();
+
+	/* make sure that the data length is at least SDIO block size */
+	data_len =
+		(data_len + MLAN_SDIO_BLOCK_SIZE -
+		 1) / MLAN_SDIO_BLOCK_SIZE * MLAN_SDIO_BLOCK_SIZE;
+
+	/* 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;
+		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 Send coalescing status 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_coalescing_status(IN pmlan_adapter pmadapter,
+				  IN 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;
+
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc->param.coalescing_status);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			IN 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;
+#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);
+
+		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(pmadapter, &pmpriv->ops, mlan_ops[j],
+				       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(IN pmlan_adapter pmadapter,
+			       IN pmlan_ioctl_req pioctl_req,
+			       IN 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(pmadapter,
+							       (t_u8 *)ie_data +
+							       len, &i,
+							       sizeof(ie_data->
+								      ie_index));
+							len += sizeof(ie_data->
+								      ie_index);
+							memcpy(pmadapter,
+							       (t_u8 *)ie_data +
+							       len,
+							       &pmpriv->
+							       mgmt_ie[i].
+							       mgmt_subtype_mask,
+							       sizeof(ie_data->
+								      mgmt_subtype_mask));
+							len += sizeof(ie_data->
+								      mgmt_subtype_mask);
+							memcpy(pmadapter,
+							       (t_u8 *)ie_data +
+							       len,
+							       &pmpriv->
+							       mgmt_ie[i].
+							       ie_length,
+							       sizeof(ie_data->
+								      ie_length));
+							len += sizeof(ie_data->
+								      ie_length);
+							if (pmpriv->mgmt_ie[i].
+							    ie_length) {
+								memcpy(pmadapter, (t_u8 *)ie_data + len, &pmpriv->mgmt_ie[i].ie_buffer, 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) {
+						ret = MLAN_STATUS_SUCCESS;
+						goto done;
+					}
+					tmp_ie = (t_u8 *)&pmpriv->
+						mgmt_ie[index].ie_buffer;
+					memcpy(pmadapter,
+					       tmp_ie +
+					       pmpriv->mgmt_ie[index].ie_length,
+					       &ie_data->ie_buffer,
+					       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(pmadapter, &ie_data->ie_buffer,
+					       &pmpriv->mgmt_ie[index].
+					       ie_buffer,
+					       pmpriv->mgmt_ie[index].
+					       ie_length);
+					misc->param.cust_ie.len +=
+						pmpriv->mgmt_ie[index].
+						ie_length +
+						MLAN_CUSTOM_IE_HDR_SIZE;
+				}
+			} else {
+				if (index >= pmadapter->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(pmadapter, (t_u8 *)ie_data,
+					       &pmpriv->mgmt_ie[index],
+					       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(pmadapter,
+					       &pmpriv->mgmt_ie[index], ie_data,
+					       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(IN pmlan_adapter pmadapter,
+			  IN 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:
+		cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
+		break;
+	case MLAN_REG_BBP:
+		cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
+		break;
+	case MLAN_REG_RF:
+		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;
+	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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_MEM_ACCESS,
+			       cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&reg_mem->param.mem_rw);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will check if station list is empty
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return	   MFALSE/MTRUE
+ */
+t_u8
+wlan_is_station_list_empty(mlan_private *priv)
+{
+	ENTER();
+	if (!(util_peek_list(priv->adapter->pmoal_handle,
+			     &priv->sta_list,
+			     priv->adapter->callbacks.moal_spin_lock,
+			     priv->adapter->callbacks.moal_spin_unlock))) {
+		LEAVE();
+		return MTRUE;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief This function will return the pointer to station entry in station list
+ *          table which matches the give mac address
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     mac address to find in station list table
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+sta_node *
+wlan_get_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr;
+
+	ENTER();
+
+	if (!mac) {
+		LEAVE();
+		return MNULL;
+	}
+	sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+					     &priv->sta_list,
+					     priv->adapter->callbacks.
+					     moal_spin_lock,
+					     priv->adapter->callbacks.
+					     moal_spin_unlock);
+
+	while (sta_ptr && (sta_ptr != (sta_node *)&priv->sta_list)) {
+		if (!memcmp
+		    (priv->adapter, sta_ptr->mac_addr, mac,
+		     MLAN_MAC_ADDR_LENGTH)) {
+			LEAVE();
+			return sta_ptr;
+		}
+		sta_ptr = sta_ptr->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function will add a pointer to station entry in station list
+ *          table with the give mac address, if it does not exist already
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     mac address to find in station list table
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+sta_node *
+wlan_add_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	mlan_adapter *pmadapter = priv->adapter;
+
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		goto done;
+	if (priv->adapter->callbacks.
+	    moal_malloc(priv->adapter->pmoal_handle, sizeof(sta_node),
+			MLAN_MEM_DEF, (t_u8 **)&sta_ptr)) {
+		PRINTM(MERROR, "Failed to allocate memory for station node\n");
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		LEAVE();
+		return MNULL;
+	}
+	memset(priv->adapter, sta_ptr, 0, sizeof(sta_node));
+	memcpy(priv->adapter, sta_ptr->mac_addr, mac, 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);
+done:
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return sta_ptr;
+}
+
+/**
+ *  @brief This function will delete a station entry from station list
+ *
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     station's mac address
+ *
+ *  @return	   N/A
+ */
+t_void
+wlan_delete_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	mlan_adapter *pmadapter = priv->adapter;
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr) {
+		util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list,
+				 (pmlan_linked_list)sta_ptr,
+				 priv->adapter->callbacks.moal_spin_lock,
+				 priv->adapter->callbacks.moal_spin_unlock);
+		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
+						    (t_u8 *)sta_ptr);
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Clean up wapi station list
+ *
+ *  @param priv  Pointer to the mlan_private driver data struct
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_delete_station_list(pmlan_private priv)
+{
+	sta_node *sta_ptr;
+
+	ENTER();
+	while ((sta_ptr =
+		(sta_node *)util_dequeue_list(priv->adapter->pmoal_handle,
+					      &priv->sta_list,
+					      priv->adapter->callbacks.
+					      moal_spin_lock,
+					      priv->adapter->callbacks.
+					      moal_spin_unlock))) {
+		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(priv->adapter, peer_info->mac_addr,
+			       sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH);
+			memcpy(priv->adapter, peer_info->ht_cap,
+			       &sta_ptr->HTcap, sizeof(IEEEtypes_HTCap_t));
+			memcpy(priv->adapter, peer_info->ext_cap,
+			       &sta_ptr->ExtCap, sizeof(IEEEtypes_ExtCap_t));
+			memcpy(priv->adapter, peer_info->vht_cap,
+			       &sta_ptr->vht_cap, sizeof(IEEEtypes_VHTCap_t));
+			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(IN pmlan_adapter pmadapter,
+			    IN 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(pmpriv->adapter, (t_u8 *)tdls_evt->peer_mac_addr,
+			       tdls_all_cfg->u.tdls_tear_down.peer_mac_addr,
+			       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)pMrvlTlv->header.len;
+				memset(pmadapter, pmpriv->chan_supp, 0,
+				       sizeof(pmpriv->chan_supp));
+				memcpy(pmadapter, pmpriv->chan_supp,
+				       pMrvlTlv->data, MIN(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)pMrvlTlv->header.len;
+				memset(pmadapter, pmpriv->supp_regulatory_class,
+				       0,
+				       sizeof(pmpriv->supp_regulatory_class));
+				memcpy(pmadapter, pmpriv->supp_regulatory_class,
+				       pMrvlTlv->data, MIN(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	        N/A
+ */
+t_void
+wlan_tdls_config(IN pmlan_private pmpriv, IN 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	        N/A
+ */
+t_void
+wlan_tdls_cs_param_config(IN 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	         N/A
+ */
+t_void
+wlan_tdls_cs_start(IN pmlan_private pmpriv,
+		   IN t_u8 *peer_mac_addr, IN 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(pmpriv->adapter, tdls_config, &misc->param.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(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(pmpriv->adapter,
+		       tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr,
+		       peer_mac_addr, 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->
+							       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();
+}
+
+/**
+ *  @brief stop tdls channel switch
+ *
+ *  @param pmpriv	A pointer to mlan_private structure
+ *  @param peer_mac_addr 	A pointer to peer mac address
+ *  @return	                N/A
+ */
+t_void
+wlan_tdls_cs_stop(IN pmlan_private pmpriv, IN 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(pmpriv->adapter,
+	       tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
+	       peer_mac_addr, 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();
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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(pmpriv->adapter,
+				       (t_u8 *)tdls_evt->peer_mac_addr,
+				       ptdls_oper->peer_mac,
+				       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
+ */
+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(pmadapter, (t_u8 *)ext_cap,
+		       (t_u8 *)pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t),
+		       pbss_desc->pext_cap->ieee_hdr.len);
+	}
+	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(IN pmlan_adapter pmadapter,
+			     IN 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(pmadapter, &sta_ptr->vht_oprat,
+			       tdls_ies->vht_oprat,
+			       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) {
+		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(pbss_desc->
+							       channel);
+		}
+		if (vht_oprat &&
+		    vht_oprat->ieee_hdr.element_id == VHT_OPERATION) {
+			ht_info->ht_info.field2 =
+				wlan_get_second_channel_offset(pbss_desc->
+							       channel);
+			ht_info->ht_info.field2 |= MBIT(2);
+		}
+		if (sta_ptr)
+			memcpy(pmadapter, &sta_ptr->HTInfo, tdls_ies->ht_info,
+			       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(pmadapter, pSupp_chan->data, pmpriv->chan_supp,
+			       pmpriv->chan_supp_len);
+		} else {
+			pSupp_chan->ieee_hdr.len = sizeof(supp_chan);
+			memcpy(pmadapter, pSupp_chan->data, supp_chan,
+			       sizeof(supp_chan));
+		}
+		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(pmadapter, pRegulatory_class->data,
+			       pmpriv->supp_regulatory_class,
+			       pmpriv->supp_regulatory_class_len);
+		} else {
+			pRegulatory_class->ieee_hdr.len =
+				sizeof(regulatory_class);
+			memcpy(pmadapter, pRegulatory_class->data,
+			       regulatory_class, sizeof(regulatory_class));
+		}
+		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 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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_get_info *pinfo = (mlan_ds_get_info *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_VERSION_EXT,
+			       HostCmd_ACT_GEN_GET,
+			       0,
+			       (t_void *)pioctl_req,
+			       &pinfo->param.ver_ext.version_str_sel);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function convert mlan_wifi_rate to wifi_rate.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param rateStats   wifi_rate_stat array
+ *  @param pnum_rate   A pointer to num_rate
+ *
+ *  @return           N/A
+ */
+t_void
+wlan_fill_hal_wifi_rate_in_host(IN pmlan_private pmpriv,
+				OUT wifi_rate_stat rateStats[],
+				OUT t_u32 *pnumRate)
+{
+	t_u32 total_num_rate = 0;
+	t_u32 mcs_idx = 0;
+	t_u8 index = 0;
+	t_u8 rate_info = 0;
+
+	ENTER();
+
+	/* HT MCS */
+	for (mcs_idx = 0; mcs_idx < MCS_NUM_SUPP; mcs_idx++) {
+		/* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+		rateStats[total_num_rate].rate.preamble = 2;
+		/* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+		rateStats[total_num_rate].rate.bw = 0;
+		rateStats[total_num_rate].rate.rateMcsIdx = mcs_idx;
+		index = rateStats[total_num_rate].rate.rateMcsIdx;
+		rate_info =
+			MLAN_RATE_FORMAT_HT | (rateStats[total_num_rate].rate.
+					       bw << 2);
+		rateStats[total_num_rate].rate.bitrate =
+			wlan_index_to_data_rate(pmpriv->adapter, index,
+						rate_info) * 5;
+		PRINTM(MINFO, "HT[%d] index=0x%x rate_info=0x%x bitrate=0x%x\n",
+		       total_num_rate, index, rate_info,
+		       rateStats[total_num_rate].rate.bitrate / 5);
+
+		/* Get Tx mpdu */
+		rateStats[total_num_rate].tx_mpdu = 0;
+		rateStats[total_num_rate].rx_mpdu = 0;
+
+		/* Todo: mpdu_lost/retries*, need extend GetTxRxRateInfo */
+		rateStats[total_num_rate].mpdu_lost = 0xC1;
+		rateStats[total_num_rate].retries = 0xC2;
+		rateStats[total_num_rate].retries_short = 0xC3;
+		rateStats[total_num_rate].retries_long = 0xC4;
+
+		total_num_rate++;
+	}
+
+	/* VHT MCS */
+	for (mcs_idx = 0; mcs_idx < VHT_NUM_SUPPORT_MCS; mcs_idx++) {
+		/* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+		rateStats[total_num_rate].rate.preamble = 3;
+		/* 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
+		rateStats[total_num_rate].rate.nss = 0;
+		/* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+		rateStats[total_num_rate].rate.bw = 0;
+		rateStats[total_num_rate].rate.rateMcsIdx = mcs_idx;
+		/* nss 2 ? bw 20MHZ ? */
+		index = rateStats[total_num_rate].rate.
+			rateMcsIdx | (rateStats[total_num_rate].rate.nss << 4);
+		rate_info =
+			MLAN_RATE_FORMAT_VHT | (rateStats[total_num_rate].rate.
+						bw << 2);
+		rateStats[total_num_rate].rate.bitrate =
+			wlan_index_to_data_rate(pmpriv->adapter, index,
+						rate_info) * 5;
+		PRINTM(MINFO,
+		       "VHT[%d] index=0x%x rate_info=0x%x bitrate=0x%x\n",
+		       total_num_rate, index, rate_info,
+		       rateStats[total_num_rate].rate.bitrate / 5);
+
+		rateStats[total_num_rate].tx_mpdu = 0;
+		rateStats[total_num_rate].rx_mpdu = 0;
+
+		/* Todo: mpdu_lost/retries*, need extend GetTxRxRateInfo */
+		rateStats[total_num_rate].mpdu_lost = 0xC1;
+		rateStats[total_num_rate].retries = 0xC2;
+		rateStats[total_num_rate].retries_short = 0xC3;
+		rateStats[total_num_rate].retries_long = 0xC4;
+
+		total_num_rate++;
+	}
+
+	*pnumRate = total_num_rate;
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function fill link layer statistic from firmware
+ *
+ *  @param priv       					A pointer to mlan_private structure
+ *  @param link_statistic_ioctl_buf,    A pointer to fill ioctl buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static void
+wlan_fill_link_statistic_in_host(mlan_private *priv,
+				 char *link_statistic_ioctl_buf)
+{
+	char *link_statistic = link_statistic_ioctl_buf;
+	wifi_radio_stat *radio_stat = MNULL;
+	wifi_iface_stat *iface_stat = MNULL;
+	t_u32 num_radio = MAX_RADIO;
+	int i = 0, chan_idx = 0;
+	t_u32 num_peers = 0;
+	sta_node *sta_ptr = MNULL;
+	t_u8 *ptid = MNULL;
+
+	ENTER();
+
+	*((t_u32 *)link_statistic) = num_radio;
+	link_statistic += sizeof(num_radio);
+
+	/* Fill radio stats array */
+	for (i = 0; i < num_radio; i++) {
+		radio_stat = (wifi_radio_stat *) link_statistic;
+		link_statistic += sizeof(wifi_radio_stat);
+
+		radio_stat->radio = 0xF0;
+
+		radio_stat->on_time = 0;
+		radio_stat->tx_time = 0;
+		radio_stat->reserved0 = 0;
+		radio_stat->rx_time = 0;
+		radio_stat->on_time_scan = 0;
+		radio_stat->on_time_nbd = 0;
+		radio_stat->on_time_gscan = 0;
+		radio_stat->on_time_roam_scan = 0;
+		radio_stat->on_time_pno_scan = 0;
+		radio_stat->on_time_hs20 = 0;
+
+		radio_stat->num_channels = 1;
+		for (chan_idx = 0; chan_idx < radio_stat->num_channels;
+		     chan_idx++) {
+			if (radio_stat->num_channels > MAX_NUM_CHAN) {
+				radio_stat->num_channels = MAX_NUM_CHAN;
+				PRINTM(MERROR,
+				       "%s : radio_stat->num_channels=%d\n",
+				       __func__, radio_stat->num_channels);
+				break;
+			}
+
+			if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+				if (priv->media_connected) {
+					radio_stat->channels[chan_idx].channel.
+						width =
+						priv->curr_bss_params.
+						bss_descriptor.curr_bandwidth;
+					radio_stat->channels[chan_idx].channel.
+						center_freq =
+						priv->curr_bss_params.
+						bss_descriptor.freq;
+					radio_stat->channels[chan_idx].channel.
+						center_freq0 = 0;
+					radio_stat->channels[chan_idx].channel.
+						center_freq1 = 0;
+				}
+			} else {
+				radio_stat->channels[chan_idx].channel.width =
+					priv->uap_state_chan_cb.bandcfg.
+					chanWidth;
+				radio_stat->channels[chan_idx].channel.
+					center_freq =
+					wlan_11d_chan_2_freq(priv->adapter,
+							     priv->
+							     uap_state_chan_cb.
+							     channel,
+							     (priv->
+							      uap_state_chan_cb.
+							      channel >
+							      14) ? BAND_A :
+							     BAND_G);
+				radio_stat->channels[chan_idx].channel.
+					center_freq0 = 0;
+				radio_stat->channels[chan_idx].channel.
+					center_freq1 = 0;
+			}
+			radio_stat->channels[chan_idx].on_time = 0xE3;
+			radio_stat->channels[chan_idx].cca_busy_time = 0xE4;
+		}
+	}
+
+	/* Fill iface stats */
+	iface_stat = (wifi_iface_stat *) link_statistic;
+
+	/* get wifi_interface_link_layer_info in driver, not in firmware */
+	if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+		iface_stat->info.mode = WIFI_INTERFACE_STA;
+		if (priv->media_connected)
+			iface_stat->info.state = WIFI_ASSOCIATING;
+		else
+			iface_stat->info.state = WIFI_DISCONNECTED;
+		iface_stat->info.roaming = WIFI_ROAMING_IDLE;
+		iface_stat->info.capabilities = WIFI_CAPABILITY_QOS;
+		memcpy(priv->adapter, iface_stat->info.ssid,
+		       priv->curr_bss_params.bss_descriptor.ssid.ssid,
+		       MLAN_MAX_SSID_LENGTH);
+		memcpy(priv->adapter, iface_stat->info.bssid,
+		       priv->curr_bss_params.bss_descriptor.mac_address,
+		       MLAN_MAC_ADDR_LENGTH);
+	} else {
+		iface_stat->info.mode = WIFI_INTERFACE_SOFTAP;
+		iface_stat->info.capabilities = WIFI_CAPABILITY_QOS;
+	}
+	memcpy(priv->adapter, iface_stat->info.mac_addr, priv->curr_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+	memcpy(priv->adapter, iface_stat->info.ap_country_str,
+	       priv->adapter->country_code, COUNTRY_CODE_LEN);
+	memcpy(priv->adapter, iface_stat->info.country_str,
+	       priv->adapter->country_code, COUNTRY_CODE_LEN);
+
+	iface_stat->beacon_rx = 0;
+	iface_stat->average_tsf_offset = 0;
+	iface_stat->leaky_ap_detected = 0;
+	iface_stat->leaky_ap_avg_num_frames_leaked = 0;
+	iface_stat->leaky_ap_guard_time = 0;
+
+	/* Value of iface_stat should be Reaccumulate by each peer */
+	iface_stat->mgmt_rx = 0;
+	iface_stat->mgmt_action_rx = 0;
+	iface_stat->mgmt_action_tx = 0;
+
+	iface_stat->rssi_mgmt = 0;
+	iface_stat->rssi_data = 0;
+	iface_stat->rssi_ack = 0;
+
+	for (i = WMM_AC_BK; i <= WMM_AC_VO; i++) {
+		iface_stat->ac[i].ac = i;
+		ptid = ac_to_tid[i];
+		iface_stat->ac[i].tx_mpdu =
+			priv->wmm.packets_out[ptid[0]] +
+			priv->wmm.packets_out[ptid[1]];
+		iface_stat->ac[i].rx_mpdu = 0;
+		iface_stat->ac[i].tx_mcast = 0;
+		iface_stat->ac[i].rx_mcast = 0;
+		iface_stat->ac[i].rx_ampdu = 0;
+		iface_stat->ac[i].tx_ampdu = 0;
+		iface_stat->ac[i].mpdu_lost = 0;
+		iface_stat->ac[i].retries = 0;
+		iface_stat->ac[i].retries_short = 0;
+		iface_stat->ac[i].retries_long = 0;
+		iface_stat->ac[i].contention_time_min = 0;
+		iface_stat->ac[i].contention_time_max = 0;
+		iface_stat->ac[i].contention_time_avg = 0;
+		iface_stat->ac[i].contention_num_samples = 0;
+	}
+
+	if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+		if (priv->media_connected) {
+			iface_stat->peer_info[0].type = WIFI_PEER_AP;
+			memcpy(priv->adapter,
+			       iface_stat->peer_info[0].peer_mac_address,
+			       priv->curr_bss_params.bss_descriptor.mac_address,
+			       MLAN_MAC_ADDR_LENGTH);
+			iface_stat->peer_info[0].capabilities =
+				WIFI_CAPABILITY_QOS;
+			wlan_fill_hal_wifi_rate_in_host(priv,
+							iface_stat->
+							peer_info[0].rate_stats,
+							&(iface_stat->
+							  peer_info[0].
+							  num_rate));
+			num_peers = 1;
+		}
+	} else {
+		sta_ptr =
+			(sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+						   &priv->sta_list,
+						   priv->adapter->callbacks.
+						   moal_spin_lock,
+						   priv->adapter->callbacks.
+						   moal_spin_unlock);
+		if (sta_ptr) {
+			while (sta_ptr != (sta_node *)&priv->sta_list) {
+				iface_stat->peer_info[num_peers].type =
+					WIFI_PEER_STA;
+				memcpy(priv->adapter,
+				       iface_stat->peer_info[num_peers].
+				       peer_mac_address, sta_ptr->mac_addr,
+				       MLAN_MAC_ADDR_LENGTH);
+				iface_stat->peer_info[num_peers].capabilities =
+					WIFI_CAPABILITY_QOS;
+				wlan_fill_hal_wifi_rate_in_host(priv,
+								iface_stat->
+								peer_info
+								[num_peers].
+								rate_stats,
+								&(iface_stat->
+								  peer_info
+								  [num_peers].
+								  num_rate));
+				num_peers++;
+
+				sta_ptr = sta_ptr->pnext;
+			}
+		}
+	}
+	iface_stat->num_peers = num_peers;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Set/Get link layer statistics
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_ioctl_link_statistic(IN mlan_private *pmpriv,
+			  IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *info = MNULL;
+	t_u8 *link_statistic = MNULL;
+
+	ENTER();
+
+	/* Check buffer length of MLAN IOCTL */
+	if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+    /** We will not send HostCmd_CMD_802_11_LINK_STATS to FW */
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		info = (mlan_ds_get_info *)pioctl_req->pbuf;
+		link_statistic = info->param.link_statistic;
+	/** Get the LL STATS from driver */
+		wlan_fill_link_statistic_in_host(pmpriv, link_statistic);
+		DBG_HEXDUMP(MCMD_D,
+			    "wlan_ioctl_link_statistic() link_statistic in host",
+			    (t_u8 *)link_statistic, 800);
+	}
+	ret = MLAN_STATUS_SUCCESS;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+#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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(IN mlan_private *priv,
+			       IN t_u8 *payload,
+			       IN t_u32 payload_len, IN 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;
+	IEEE80211_MGMT *mgmt = MNULL;
+	t_u8 category = 0;
+	t_u8 action_code = 0;
+	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:
+	case SUBTYPE_DISASSOC:
+	case SUBTYPE_DEAUTH:
+	case SUBTYPE_AUTH:
+	case SUBTYPE_PROBE_RESP:
+		unicast = MTRUE;
+		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);
+		}
+		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 (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(pmadapter, (t_u8 *)pevent->event_buf,
+		       &mgmt->u.ft_resp.target_ap_addr, MLAN_MAC_ADDR_LENGTH);
+		memcpy(pmadapter,
+		       (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+		       payload + FT_ACTION_HEAD_LEN,
+		       payload_len - FT_ACTION_HEAD_LEN);
+	} else if (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(pmadapter, (t_u8 *)pevent->event_buf, mgmt->sa,
+		       MLAN_MAC_ADDR_LENGTH);
+		memcpy(pmadapter,
+		       (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+		       payload + AUTH_PACKET_LEN,
+		       payload_len - AUTH_PACKET_LEN);
+	} else {
+		pevent->event_id = MLAN_EVENT_ID_DRV_MGMT_FRAME;
+		pevent->event_len = payload_len + sizeof(pevent->event_id);
+		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+		       (t_u8 *)&pevent->event_id, sizeof(pevent->event_id));
+		memcpy(pmadapter,
+		       (t_u8 *)(pevent->event_buf + sizeof(pevent->event_id)),
+		       payload, 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(IN pmlan_adapter pmadapter,
+		       IN 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(pmpriv->adapter, &misc->param.ext_cap, &pmpriv->ext_cap,
+		       sizeof(misc->param.ext_cap));
+	else if (MLAN_ACT_SET == pioctl_req->action) {
+		memcpy(pmpriv->adapter, &pmpriv->ext_cap, &misc->param.ext_cap,
+		       sizeof(misc->param.ext_cap));
+		/* Save default Extended Capability */
+		memcpy(pmpriv->adapter, &pmpriv->def_ext_cap, &pmpriv->ext_cap,
+		       sizeof(pmpriv->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(IN pmlan_adapter pmadapter, IN 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 pptlv_out          A pointer to TLV to fill in
+ *
+ *  @return                   N/A
+ */
+void
+wlan_add_ext_capa_info_ie(IN mlan_private *pmpriv, OUT 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);
+	memcpy(pmpriv->adapter, &pext_cap->ext_cap, &pmpriv->ext_cap,
+	       sizeof(pmpriv->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(IN pmlan_adapter pmadapter,
+			IN 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;
+#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(priv->adapter, &frame_control,
+			       (t_u8 *)&(mgmt_tlv->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);
+				if (pht_cap) {
+					PRINTM(MCMND, "STA supports 11n\n");
+					sta_ptr->is_11n_enabled = MTRUE;
+					memcpy(priv->adapter,
+					       (t_u8 *)&sta_ptr->HTcap, pht_cap,
+					       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);
+				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");
+				}
+#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);
+				erp = wlan_get_specific_ie(priv, assoc_req_ie,
+							   ie_len, ERP_INFO);
+				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_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
+				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
+ *
+ *  @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_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;
+
+	ENTER();
+
+	DBG_HEXDUMP(MCMD_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);
+		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 (element_id == id) {
+			PRINTM(MCMND, "Find IE: id=%d\n", id);
+			DBG_HEXDUMP(MCMND, "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(IN pmlan_adapter pmadapter, IN 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)
+	    || pmadapter->sdio_ireg) {
+		pm_cfg->param.ps_info.is_suspend_allowed = MFALSE;
+		PRINTM(MIOCTL,
+		       "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d sdio_ireg=0x%x\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),
+		       pmadapter->sdio_ireg);
+	}
+	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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(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_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 (!ant_cfg->tx_antenna ||
+			    bitcount(ant_cfg->tx_antenna & 0xFFFF) >
+			    pmadapter->number_of_antenna) {
+				PRINTM(MERROR, "Invalid antenna setting\n");
+				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 & 0xFFFF) >
+				    pmadapter->number_of_antenna) {
+					PRINTM(MERROR,
+					       "Invalid antenna setting\n");
+					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(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];
+
+	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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			       IN 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 (!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(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];
+
+	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(IN pmlan_adapter pmadapter,
+			       IN 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 < 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_HRDSSS0) &&
+			    (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_MCS0) &&
+			    (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 (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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			      IN 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(IN pmlan_adapter pmadapter,
+				 IN 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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_P2P_PARAMS_CONFIG,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc_cfg->param.p2p_config);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set coalesce config
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,
+			     IN 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 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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+				       IN 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 Get/Set channel time and buffer weight 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_multi_chan_config(IN pmlan_adapter pmadapter,
+				  IN 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_MULTI_CHAN_CONFIG,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc->param.multi_chan_cfg);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set multi-channel policy setting
+ *
+ *  @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_multi_chan_policy(IN pmlan_adapter pmadapter,
+				  IN 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_MULTI_CHAN_POLICY,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc->param.multi_chan_policy);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set DRCS 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_drcs_config(IN pmlan_adapter pmadapter,
+			    IN 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_DRCS_CONFIG,
+			       cmd_action,
+			       0, (t_void *)pioctl_req, &misc->param.drcs_cfg);
+
+	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(IN pmlan_adapter pmadapter,
+			     IN 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(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];
+
+	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 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(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_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;
+
+	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(pmadapter,
+					       &sec->param.passphrase.ssid,
+					       &pbss_desc->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/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(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;
+	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 {
+		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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+			IN 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 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(IN pmlan_adapter pmadapter,
+				     IN 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 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(IN pmlan_adapter pmadapter,
+			   IN 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;
+	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(IN pmlan_adapter pmadapter,
+			      IN mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_FW_DUMP_EVENT,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get the network monitor 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_net_monitor(IN pmlan_adapter pmadapter,
+			    IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv;
+	mlan_ds_misc_cfg *misc;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (!pioctl_req) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	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_NET_MONITOR,
+			       cmd_action,
+			       0, (t_void *)pioctl_req, &misc->param.net_mon);
+
+	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(IN pmlan_adapter pmadapter, IN 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;
+}
diff --git a/wlan_sd8897/mlan/mlan_module.c b/wlan_sd8897/mlan/mlan_module.c
new file mode 100644
index 0000000..4745b72
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_module.c
@@ -0,0 +1,54 @@
+/** @file mlan_module.c
+ *
+ *  @brief This file declares the exported symbols from MLAN.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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);
+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_interrupt);
+#if defined(SYSKT)
+EXPORT_SYMBOL(mlan_hs_callback);
+#endif /* SYSKT_MULTI || SYSKT */
+
+EXPORT_SYMBOL(mlan_pm_wakeup_card);
+EXPORT_SYMBOL(mlan_is_main_process_running);
+
+MODULE_DESCRIPTION("M-WLAN MLAN Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_VERSION(MLAN_RELEASE_VERSION);
+MODULE_LICENSE("GPL");
+#endif /* LINUX */
diff --git a/wlan_sd8897/mlan/mlan_scan.c b/wlan_sd8897/mlan/mlan_scan.c
new file mode 100644
index 0000000..c4fe92a
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_scan.c
@@ -0,0 +1,5969 @@
+/** @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 (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_11h.h"
+/********************************************************
+			Local Constants
+********************************************************/
+/** 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))
+
+/** 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        \
+				+ 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_MAX
+};
+
+static t_u8 wpa_oui[CIPHER_SUITE_MAX][4] = {
+	{0x00, 0x50, 0xf2, 0x01},	/* WEP40 */
+	{0x00, 0x50, 0xf2, 0x02},	/* TKIP */
+	{0x00, 0x50, 0xf2, 0x04},	/* AES */
+	{0x00, 0x50, 0xf2, 0x05},	/* WEP104 */
+};
+
+static t_u8 rsn_oui[CIPHER_SUITE_MAX][4] = {
+	{0x00, 0x0f, 0xac, 0x01},	/* WEP40 */
+	{0x00, 0x0f, 0xac, 0x02},	/* TKIP */
+	{0x00, 0x0f, 0xac, 0x04},	/* AES */
+	{0x00, 0x0f, 0xac, 0x05},	/* WEP104 */
+};
+
+/**
+ *  @brief Convert radio type scan parameter to a band config used in join cmd
+ *
+ *  @param radio_type Scan parameter indicating the radio used for a channel
+ *                    in a scan command.
+ *
+ *  @return          Band type conversion of scanBand used in join/assoc cmds
+ *
+ */
+t_u8
+radio_type_to_band(t_u8 radio_type)
+{
+	t_u8 ret_band;
+
+	switch (radio_type) {
+	case BAND_5GHZ:
+		ret_band = BAND_A;
+		break;
+	case BAND_2GHZ:
+	default:
+		ret_band = BAND_G;
+		break;
+	}
+
+	return ret_band;
+}
+
+/**
+ *  @brief This function will update the channel statistics from scan result
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param pchanstats_tlv   A pointer to MrvlIEtypes_ChannelStats_t tlv
+ *
+ *  @return                NA
+ */
+void
+wlan_update_chan_statistics(mlan_private *pmpriv,
+			    MrvlIEtypes_ChannelStats_t *pchanstats_tlv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 i;
+	ChanStatistics_t *pchan_stats =
+		(ChanStatistics_t *)((t_u8 *)pchanstats_tlv +
+				     sizeof(MrvlIEtypesHeader_t));
+	t_u8 num_chan =
+		wlan_le16_to_cpu(pchanstats_tlv->header.len) /
+		sizeof(ChanStatistics_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(pmadapter,
+		       &pmadapter->pchan_stats[pmadapter->idx_chan_stats],
+		       pchan_stats, sizeof(ChanStatistics_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))) {
+		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 pbss_desc for appropriate IE and then check if WPA IE has AES
+ *  OUI in it. If WPA IE does not have AES in PTK then return 0;
+ *
+ *  @param pbss_desc       A pointer to current BSS descriptor
+ *  @return                0 on failure to find AES OUI, 1 on success.
+ */
+static t_u8
+is_wpa_oui_present(mlan_adapter *pmadapter, BSSDescriptor_t *pbss_desc,
+		   t_u32 cipher_suite)
+{
+	t_u8 *oui = MNULL;
+	IEBody *ie_body = MNULL;
+	t_u8 ret = MLAN_OUI_NOT_PRESENT;
+
+	ENTER();
+	if (((pbss_desc->pwpa_ie) &&
+	     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE))) {
+		ie_body = (IEBody *)pbss_desc->pwpa_ie->data;
+		oui = &wpa_oui[cipher_suite][0];
+		ret = search_oui_in_ie(pmadapter, ie_body, oui);
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief compare config band and a band from the scan result,
+ *  which is defined by functiion radio_type_to_band(t_u8 radio_type) above
+ *
+ *  @param cfg_band:  band configured
+ *         scan_band: band from scan result
+ *
+ *  @return  matched: non-zero. unmatched: 0
+ *
+ */
+static t_u8
+wlan_is_band_compatible(t_u8 cfg_band, t_u8 scan_band)
+{
+	t_u8 band;
+	switch (scan_band) {
+	case BAND_A:
+		band = BAND_A | BAND_AN | BAND_AAC;
+		break;
+	case BAND_G:
+	default:
+		band = BAND_B | BAND_G | BAND_GN | BAND_GAC;
+	}
+	return cfg_band & band;
+}
+
+/**
+ *  @brief This function finds the best SSID in the Scan List
+ *
+ *  Search the scan table for the best SSID that also matches the current
+ *   adapter network preference (infrastructure or adhoc)
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @return             index in BSSID list
+ */
+static t_s32
+wlan_find_best_network_in_list(IN mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u32 mode = pmpriv->bss_mode;
+	t_s32 best_net = -1;
+	t_s32 best_rssi = 0;
+	t_u32 i;
+
+	ENTER();
+
+	PRINTM(MINFO, "Num of BSSIDs = %d\n", pmadapter->num_in_scan_table);
+
+	for (i = 0; i < pmadapter->num_in_scan_table; i++) {
+		switch (mode) {
+		case MLAN_BSS_MODE_INFRA:
+		case MLAN_BSS_MODE_IBSS:
+			if (wlan_is_network_compatible(pmpriv, i, mode) >= 0) {
+				if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+				    best_rssi) {
+					best_rssi =
+						SCAN_RSSI(pmadapter->
+							  pscan_table[i].rssi);
+					best_net = i;
+				}
+			}
+			break;
+		case MLAN_BSS_MODE_AUTO:
+		default:
+			if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+			    best_rssi) {
+				best_rssi =
+					SCAN_RSSI(pmadapter->pscan_table[i].
+						  rssi);
+				best_net = i;
+			}
+			break;
+		}
+	}
+
+	LEAVE();
+	return best_net;
+}
+
+/**
+ *  @brief Create a channel list for the driver to scan based on region info
+ *
+ *  Use the driver region/band information to construct a comprehensive list
+ *    of channels to scan.  This routine is used for any scan that is not
+ *    provided a specific channel list to scan.
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param puser_scan_in    MNULL or pointer to scan configuration parameters
+ *  @param pscan_chan_list  Output parameter: Resulting channel list to scan
+ *  @param filtered_scan    Flag indicating whether or not a BSSID or SSID filter
+ *                          is being sent in the command to firmware.  Used to
+ *                          increase the number of channels sent in a scan
+ *                          command and to disable the firmware channel scan
+ *                          filter.
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_scan_create_channel_list(IN mlan_private *pmpriv,
+			      IN const wlan_user_scan_cfg *puser_scan_in,
+			      OUT ChanScanParamSet_t *pscan_chan_list,
+			      IN 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;
+
+	ENTER();
+
+	for (region_idx = 0;
+	     region_idx < NELEMENTS(pmadapter->region_channel); region_idx++) {
+
+		if (wlan_11d_is_enabled(pmpriv) &&
+		    pmpriv->media_connected != MTRUE) {
+			/* Scan all the supported chan for the first scan */
+			if (!pmadapter->universal_channel[region_idx].valid)
+				continue;
+			pscan_region =
+				&pmadapter->universal_channel[region_idx];
+		} else {
+			if (!pmadapter->region_channel[region_idx].valid)
+				continue;
+			pscan_region = &pmadapter->region_channel[region_idx];
+		}
+
+		if (puser_scan_in && !puser_scan_in->chan_list[0].chan_number &&
+		    puser_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
+			radio_type =
+				puser_scan_in->chan_list[0].
+				radio_type & ~BAND_SPECIFIED;
+			if (!radio_type && (pscan_region->band != BAND_B) &&
+			    (pscan_region->band != BAND_G))
+				continue;
+			if (radio_type && (pscan_region->band != BAND_A))
+				continue;
+		}
+		if ((puser_scan_in &&
+		     (puser_scan_in->bss_mode == MLAN_SCAN_MODE_IBSS)) ||
+		    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+			band = pmadapter->adhoc_start_band;
+		else
+			band = pmpriv->config_bands;
+		if (!wlan_is_band_compatible(band, pscan_region->band))
+			continue;
+		for (next_chan = 0;
+		     next_chan < pscan_region->num_cfp;
+		     next_chan++, chan_idx++) {
+			/* 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;
+
+			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;
+				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) {
+				pscan_chan_list[chan_idx].max_scan_time =
+					wlan_cpu_to_le16((t_u16)puser_scan_in->
+							 chan_list[0].
+							 scan_time);
+			} else if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				pscan_chan_list[chan_idx].max_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 passive_scan_time);
+			} else if (filtered_scan) {
+				pscan_chan_list[chan_idx].max_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 specific_scan_time);
+			} else {
+				pscan_chan_list[chan_idx].max_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 active_scan_time);
+			}
+
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				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;
+
+			if (filtered_scan) {
+				pscan_chan_list[chan_idx].chan_scan_mode.
+					disable_chan_filt = MTRUE;
+			}
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares command of sending acs.
+ *
+ *  @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_acs(IN pmlan_private pmpriv,
+	     IN HostCmd_DS_COMMAND *cmd,
+	     IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	mlan_ds_misc_acs *acs_param = (mlan_ds_misc_acs *) pdata_buf;
+	HostCmd_DS_ACS *acs_cmd = (HostCmd_DS_ACS *) & cmd->params.acs;
+	t_u8 *ptlv_pos = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchanlist_tlv = MNULL;
+	MrvlIEtypes_ScanChanGap_t *pscangap_tlv = MNULL;
+	t_u32 buf_size = 0;
+	ChanScanParamSet_t *pscan_chan_list = MNULL;
+	t_u32 i = 0;
+	t_u32 scan_type = 0;
+	t_u16 scan_dur = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ACS);
+	cmd->size = sizeof(HostCmd_DS_ACS) + S_DS_GEN;
+
+	buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
+	status = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
+				  MLAN_MEM_DEF, (t_u8 **)&pscan_chan_list);
+	if (status != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
+		PRINTM(MERROR,
+		       "wlan_cmd_acs: Failed to allocate scan_chan_list\n");
+		goto done;
+	}
+	memset(pmadapter, pscan_chan_list, 0x00, buf_size);
+
+    /** Prepare channel list, we will use it to fill into MrvlIEtypes_ChanListParamSet_t */
+	if (acs_param->ch_stats_num) {
+		PRINTM(MCMND, "ACS using user specified channels\n");
+		for (i = 0; i < MIN(MAX_CH_STATS, acs_param->ch_stats_num); i++) {
+			if (!acs_param->ch_stats[i].chan_num)
+				continue;
+
+	    /** Set the fields in pscan_chan_list */
+	    /** Set chan_number */
+			pscan_chan_list[i].chan_number =
+				acs_param->ch_stats[i].chan_num;
+
+	    /** Set bandcfg */
+			if (acs_param->ch_stats[i].chan_num <= 14)
+				pscan_chan_list[i].bandcfg.chanBand = BAND_2GHZ;
+			else
+				pscan_chan_list[i].bandcfg.chanBand = BAND_5GHZ;
+			if (pscan_chan_list[i].bandcfg.chanBand == BAND_5GHZ) {
+				if (pmadapter->fw_bands & BAND_A)
+					PRINTM(MINFO,
+					       "UserScan request for A Band channel %d!!\n",
+					       pscan_chan_list[i].chan_number);
+				else {
+					PRINTM(MERROR,
+					       "Scan in A band is not allowed!!\n");
+					status = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+			}
+
+	    /** Set chan_scan_mode */
+			scan_type = pmadapter->scan_type;
+	    /** Prevent active scanning on a radar controlled channel */
+			if (pscan_chan_list[i].bandcfg.chanBand == BAND_5GHZ) {
+				if (pmadapter->active_scan_triggered == MFALSE)
+					if (wlan_11h_radar_detect_required
+					    (pmpriv,
+					     pscan_chan_list[i].chan_number))
+						scan_type =
+							MLAN_SCAN_TYPE_PASSIVE;
+			}
+			if (pscan_chan_list[i].bandcfg.chanBand == BAND_2GHZ) {
+				if (pmadapter->active_scan_triggered == MFALSE)
+					if (wlan_bg_scan_type_is_passive
+					    (pmpriv,
+					     pscan_chan_list[i].chan_number))
+						scan_type =
+							MLAN_SCAN_TYPE_PASSIVE;
+			}
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				pscan_chan_list[i].chan_scan_mode.passive_scan =
+					MTRUE;
+				pscan_chan_list[i].chan_scan_mode.
+					hidden_ssid_report = MTRUE;
+			} else
+				pscan_chan_list[i].chan_scan_mode.passive_scan =
+					MFALSE;
+
+	    /** Set min_scan_time & max_scan_time */
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
+				scan_dur = pmadapter->passive_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;
+			pscan_chan_list[i].min_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+			pscan_chan_list[i].max_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+		}
+	} else {
+		PRINTM(MCMND, "ACS using full region channel list\n");
+		wlan_scan_create_channel_list(pmpriv, MNULL, pscan_chan_list,
+					      MFALSE);
+	}
+
+	ptlv_pos = acs_cmd->tlv_buffer;
+
+	if (!pscan_chan_list[0].chan_number) {
+		PRINTM(MERROR, "No valid chan_number in pscan_chan_list\n");
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pchanlist_tlv = (MrvlIEtypes_ChanListParamSet_t *)ptlv_pos;
+	pchanlist_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+	pchanlist_tlv->header.len = 0;
+	PRINTM(MCMND, "--- pscan_chan_list ---\n");
+	for (i = 0;
+	     i < WLAN_USER_SCAN_CHAN_MAX && pscan_chan_list[i].chan_number;
+	     i++) {
+		memcpy(pmadapter, &(pchanlist_tlv->chan_scan_param[i]),
+		       &(pscan_chan_list[i]), sizeof(ChanScanParamSet_t));
+		pchanlist_tlv->header.len += sizeof(ChanScanParamSet_t);
+		PRINTM(MCMND,
+		       "[%d] chan_number=%d bandcfg=0x%x chan_scan_mode=0x%x scan_time=%d~%d\n",
+		       i, pscan_chan_list[i].chan_number,
+		       pscan_chan_list[i].bandcfg,
+		       pscan_chan_list[i].chan_scan_mode,
+		       pscan_chan_list[i].min_scan_time,
+		       pscan_chan_list[i].max_scan_time);
+	}
+	ptlv_pos += sizeof(pchanlist_tlv->header) + pchanlist_tlv->header.len;
+	pchanlist_tlv->header.len = wlan_cpu_to_le16(pchanlist_tlv->header.len);
+
+	pscangap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
+	pscangap_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
+	pscangap_tlv->header.len = sizeof(pscangap_tlv->gap);
+	pscangap_tlv->gap = wlan_cpu_to_le16(acs_param->scan_chan_gap);
+	ptlv_pos += sizeof(pscangap_tlv->header) + pscangap_tlv->header.len;
+	pscangap_tlv->header.len = wlan_cpu_to_le16(pscangap_tlv->header.len);
+
+	cmd->size += ptlv_pos - acs_cmd->tlv_buffer;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+done:
+	if (pscan_chan_list)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pscan_chan_list);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function handles the command response of acs
+ *
+ *  @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_acs(IN pmlan_private pmpriv,
+	     IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *cfg = MNULL;
+	mlan_ds_misc_acs *acs_param = MNULL;
+	HostCmd_DS_ACS *acs_cmd = (HostCmd_DS_ACS *) & resp->params.acs;
+	int left_len = resp->size;
+	t_u8 *tlv_pos = MNULL;
+	MrvlIEtypesHeader_t *tlv_ie = MNULL;
+	MrvlIEtypes_ChannelStats_t *tlv_ch_stats = MNULL;
+	ChanStatistics_t *ch_stats = MNULL;
+	int ch_stats_num = 0;
+	int i = 0;
+	t_u16 tlv_id = 0;
+	int tlv_ie_len = 0;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		acs_param = &cfg->param.acs;
+		memset(pmpriv->adapter, acs_param, 0x00, sizeof(*acs_param));
+		acs_param->best_ch = acs_cmd->best_ch;
+
+		left_len -= S_DS_GEN + sizeof(HostCmd_DS_ACS);
+		tlv_pos = acs_cmd->tlv_buffer;
+		while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+			tlv_ie = (MrvlIEtypesHeader_t *)(tlv_pos);
+			tlv_id = wlan_le16_to_cpu(tlv_ie->type);
+			tlv_ie_len = wlan_le16_to_cpu(tlv_ie->len);
+			PRINTM(MCMND, "[TLV: id=0x%x len=%d]  left_len=%d\n",
+			       tlv_id, tlv_ie_len, left_len);
+			if ((tlv_id == TLV_TYPE_CHANNEL_STATS) &&
+			    (tlv_ie_len >= sizeof(ChanStatistics_t))) {
+				tlv_ch_stats =
+					(MrvlIEtypes_ChannelStats_t *)tlv_ie;
+				ch_stats = tlv_ch_stats->chanStat;
+				ch_stats_num =
+					tlv_ie_len / sizeof(ChanStatistics_t);
+				for (i = 0; i < MIN(ch_stats_num, MAX_CH_STATS);
+				     i++) {
+					if (ch_stats[i].chan_num) {
+						acs_param->ch_stats[i].
+							chan_num =
+							ch_stats[i].chan_num;
+						acs_param->ch_stats[i].
+							total_networks =
+							wlan_le16_to_cpu
+							(ch_stats[i].
+							 total_networks);
+						acs_param->ch_stats[i].
+							cca_busy_duration =
+							wlan_le16_to_cpu
+							(ch_stats[i].
+							 cca_busy_duration);
+						acs_param->ch_stats_num++;
+					}
+				}
+				if (acs_param->ch_stats_num)
+					break;
+			}
+			left_len -= sizeof(*tlv_ie) + tlv_ie_len;
+			tlv_pos += sizeof(*tlv_ie) + tlv_ie_len;
+		}
+
+		/* Indicate ioctl complete */
+		pioctl_buf->data_read_written = sizeof(*acs_param);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN mlan_private *pmpriv, OUT 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(pmpriv->adapter, *pptlv_out,
+		       pmpriv->wps.wps_ie.vend_hdr.oui,
+		       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(IN mlan_private *pmpriv,
+		       IN t_void *pioctl_buf,
+		       IN t_u32 max_chan_per_scan,
+		       IN t_u8 filtered_scan,
+		       OUT wlan_scan_cmd_config *pscan_cfg_out,
+		       OUT MrvlIEtypes_ChanListParamSet_t *pchan_tlv_out,
+		       IN ChanScanParamSet_t *pscan_chan_list)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	ChanScanParamSet_t *ptmp_chan_list;
+	ChanScanParamSet_t *pstart_chan;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+	t_u8 *pchan_tlv_out_temp = MNULL;
+	t_u8 *ptlv_temp = MNULL;
+	t_bool foundJPch14 = MFALSE;
+	t_u16 tlv_buf_len = 0;
+	t_u32 tlv_idx;
+	t_u32 total_scan_time;
+	t_u32 done_early;
+	t_u32 cmd_no;
+	t_u32 first_chan = 1;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+
+	if (!pscan_cfg_out || !pchan_tlv_out || !pscan_chan_list) {
+		PRINTM(MINFO, "Scan: Null detect: %p, %p, %p\n",
+		       pscan_cfg_out, pchan_tlv_out, pscan_chan_list);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (!pscan_chan_list->chan_number) {
+		PRINTM(MERROR, "Scan: No channel configured\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* check expiry before preparing scan list - may affect blacklist */
+	wlan_11h_get_csa_closed_channel(pmpriv);
+
+	pchan_tlv_out->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+
+	/* Set the temp channel struct pointer to the start of the desired list */
+	ptmp_chan_list = pscan_chan_list;
+
+	/*
+	 * Loop through the desired channel list, sending a new firmware scan
+	 * commands for each max_chan_per_scan channels (or for 1,6,11
+	 * individually if configured accordingly)
+	 */
+	while (ptmp_chan_list->chan_number) {
+
+		tlv_idx = 0;
+		total_scan_time = 0;
+		pchan_tlv_out->header.len = 0;
+		pstart_chan = ptmp_chan_list;
+		done_early = MFALSE;
+
+		/*
+		 * Construct the Channel TLV for the scan command.  Continue to
+		 * insert channel TLVs until:
+		 *   - the tlv_idx hits the maximum configured per scan command
+		 *   - the next channel to insert is 0 (end of desired
+		 *     channel list)
+		 *   - done_early is set (controlling individual
+		 *     scanning of 1,6,11)
+		 */
+		while (tlv_idx < max_chan_per_scan &&
+		       ptmp_chan_list->chan_number && !done_early) {
+			if (wlan_is_chan_blacklisted
+			    (pmpriv,
+			     radio_type_to_band(ptmp_chan_list->bandcfg.
+						chanBand),
+			     ptmp_chan_list->chan_number) ||
+			    wlan_is_chan_disabled(pmpriv,
+						  radio_type_to_band
+						  (ptmp_chan_list->bandcfg.
+						   chanBand),
+						  ptmp_chan_list->
+						  chan_number)) {
+				ptmp_chan_list++;
+				continue;
+			}
+
+			if (first_chan) {
+				ptmp_chan_list->chan_scan_mode.first_chan =
+					MTRUE;
+				first_chan = 0;
+			}
+
+			PRINTM(MINFO,
+			       "Scan: Chan(%3d), bandcfg(%x), Mode(%d,%d), Dur(%d)\n",
+			       ptmp_chan_list->chan_number,
+			       ptmp_chan_list->bandcfg,
+			       ptmp_chan_list->chan_scan_mode.passive_scan,
+			       ptmp_chan_list->chan_scan_mode.disable_chan_filt,
+			       wlan_le16_to_cpu(ptmp_chan_list->max_scan_time));
+
+			if (foundJPch14 == MTRUE) {
+				foundJPch14 = MFALSE;
+				/* Restore the TLV buffer */
+				pchan_tlv_out =
+					(MrvlIEtypes_ChanListParamSet_t *)
+					pchan_tlv_out_temp;
+				pchan_tlv_out->header.type =
+					wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+				pchan_tlv_out->header.len = 0;
+				if (ptlv_temp) {
+					memcpy(pmadapter,
+					       pscan_cfg_out->tlv_buf,
+					       ptlv_temp, 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)
+				) {
+
+				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(pmadapter, ptlv_temp, ptlv_pos,
+				       tlv_buf_len);
+
+				/* 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(pmadapter,
+			       pchan_tlv_out->chan_scan_param + tlv_idx,
+			       ptmp_chan_list,
+			       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;
+			}
+		}
+
+		/* The total scan time should be less than scan command timeout value */
+		if (total_scan_time > MRVDRV_MAX_TOTAL_SCAN_TIME) {
+			PRINTM(MMSG,
+			       "Total scan time %d ms is over limit (%d ms), scan skipped\n",
+			       total_scan_time, MRVDRV_MAX_TOTAL_SCAN_TIME);
+			if (pioctl_req)
+				pioctl_req->status_code =
+					MLAN_ERROR_CMD_SCAN_FAIL;
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+
+		pchan_tlv_out->header.len =
+			wlan_cpu_to_le16(pchan_tlv_out->header.len);
+
+		pmadapter->pscan_channels = pstart_chan;
+
+		/* Send the scan command to the firmware with the specified cfg */
+		if (pmadapter->ext_scan)
+			cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
+		else
+			cmd_no = HostCmd_CMD_802_11_SCAN;
+		ret = wlan_prepare_cmd(pmpriv,
+				       cmd_no,
+				       HostCmd_ACT_GEN_SET,
+				       0, MNULL, pscan_cfg_out);
+		if (ret)
+			break;
+	}
+
+	LEAVE();
+
+	if (ptlv_temp)
+		pcb->moal_mfree(pmadapter->pmoal_handle, ptlv_temp);
+
+	if (ret)
+		return MLAN_STATUS_FAILURE;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Construct a wlan_scan_cmd_config structure to use in scan commands
+ *
+ *  Application layer or other functions can invoke wlan_scan_networks
+ *    with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
+ *    This structure is used as the basis of one or many wlan_scan_cmd_config
+ *    commands that are sent to the command processing module and sent to
+ *    firmware.
+ *
+ *  Create a wlan_scan_cmd_config based on the following user supplied
+ *    parameters (if present):
+ *             - SSID filter
+ *             - BSSID filter
+ *             - Number of Probes to be sent
+ *             - Channel list
+ *
+ *  If the SSID or BSSID filter is not present, disable/clear the filter.
+ *  If the number of probes is not set, use the adapter default setting
+ *  Qualify the channel
+ *
+ *  @param pmpriv              A pointer to mlan_private structure
+ *  @param puser_scan_in       MNULL or pointer to scan config parameters
+ *  @param pscan_cfg_out       Output parameter: Resulting scan configuration
+ *  @param ppchan_list_out     Output parameter: Pointer to the start of the
+ *                             channel TLV portion of the output scan config
+ *  @param pscan_chan_list     Output parameter: Pointer to the resulting
+ *                             channel list to scan
+ *  @param pmax_chan_per_scan  Output parameter: Number of channels to scan for
+ *                             each issuance of the firmware scan command
+ *  @param pfiltered_scan      Output parameter: Flag indicating whether or not
+ *                             a BSSID or SSID filter is being sent in the
+ *                             command to firmware. Used to increase the number
+ *                             of channels sent in a scan command and to
+ *                             disable the firmware channel scan filter.
+ *  @param pscan_current_only  Output parameter: Flag indicating whether or not
+ *                             we are only scanning our current active channel
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_scan_setup_scan_config(IN mlan_private *pmpriv,
+			    IN wlan_user_scan_cfg *puser_scan_in,
+			    OUT wlan_scan_cmd_config *pscan_cfg_out,
+			    OUT MrvlIEtypes_ChanListParamSet_t
+			    **ppchan_list_out,
+			    OUT ChanScanParamSet_t *pscan_chan_list,
+			    OUT t_u8 *pmax_chan_per_scan,
+			    OUT t_u8 *pfiltered_scan,
+			    OUT 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;
+	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(pmadapter, pscan_cfg_out->specific_bssid,
+		       puser_scan_in->specific_bssid,
+		       sizeof(pscan_cfg_out->specific_bssid));
+
+		if (pmadapter->ext_scan
+		    && 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 = MLAN_MAC_ADDR_LENGTH;
+			memcpy(pmadapter, pbssid_tlv->bssid,
+			       puser_scan_in->specific_bssid,
+			       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(pmadapter, pwildcard_ssid_tlv->ssid,
+			       puser_scan_in->ssid_list[ssid_idx].ssid,
+			       MIN(MLAN_MAX_SSID_LENGTH, ssid_len));
+
+			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 && puser_scan_in->scan_chan_gap) {
+		*pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+		PRINTM(MINFO, "Scan: channel gap = %d\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);
+	}
+	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 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(pmadapter, prates_tlv->rates, rates, 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);
+		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 (wlan_is_ext_capa_support(pmpriv))
+		wlan_add_ext_capa_info_ie(pmpriv, &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);
+	}
+
+	/*
+	 * 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;
+
+				}
+			}
+
+			/* Prevent active scanning on a radar controlled channel */
+			if (radio_type == BAND_5GHZ) {
+				if (pmadapter->active_scan_triggered == MFALSE)
+					if (wlan_11h_radar_detect_required
+					    (pmpriv, channel)) {
+						scan_type =
+							MLAN_SCAN_TYPE_PASSIVE;
+					}
+			}
+			if (radio_type == BAND_2GHZ) {
+				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) {
+				(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_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;
+			(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);
+			if (*pfiltered_scan) {
+				(pscan_chan_list +
+				 chan_list_idx)->chan_scan_mode.
+		      disable_chan_filt = MTRUE;
+			}
+			chan_list_idx++;
+		}
+
+		/* Check if we are only scanning the current channel */
+		if ((chan_idx == 1)
+		    && (puser_scan_in->chan_list[0].chan_number
+			== pmpriv->curr_bss_params.bss_descriptor.channel)) {
+			*pscan_current_only = MTRUE;
+			PRINTM(MINFO, "Scan: Scanning current channel only\n");
+		}
+
+	} else {
+		PRINTM(MINFO, "Scan: Creating full region channel list\n");
+		wlan_scan_create_channel_list(pmpriv, puser_scan_in,
+					      pscan_chan_list, *pfiltered_scan);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Inspect the scan response buffer for pointers to expected TLVs
+ *
+ *  TLVs can be included at the end of the scan response BSS information.
+ *    Parse the data in the buffer for pointers to TLVs that can potentially
+ *    be passed back in the response
+ *
+ *  @param pmadapter        Pointer to the mlan_adapter structure
+ *  @param ptlv             Pointer to the start of the TLV buffer to parse
+ *  @param tlv_buf_size     Size of the TLV buffer
+ *  @param req_tlv_type     Request TLV's type
+ *  @param pptlv            Output parameter: Pointer to the request TLV if found
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_ret_802_11_scan_get_tlv_ptrs(IN pmlan_adapter pmadapter,
+				  IN MrvlIEtypes_Data_t *ptlv,
+				  IN t_u32 tlv_buf_size,
+				  IN t_u32 req_tlv_type,
+				  OUT 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(IN pmlan_adapter pmadapter,
+				OUT BSSDescriptor_t *pbss_entry,
+				IN t_u8 **pbeacon_info,
+				IN t_u32 *bytes_left, IN 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;
+
+	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(pmadapter, &beacon_size, *pbeacon_info,
+		       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(pmadapter, pbss_entry->mac_address, pcurrent_ptr,
+	       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(pmadapter, fixed_ie.time_stamp, pcurrent_ptr, 8);
+	memcpy(pmadapter, pbss_entry->time_stamp, pcurrent_ptr, 8);
+	pcurrent_ptr += 8;
+	bytes_left_for_current_beacon -= 8;
+
+	/* Beacon interval is 2 bytes long */
+	memcpy(pmadapter, &fixed_ie.beacon_interval, pcurrent_ptr, 2);
+	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(pmadapter, &fixed_ie.capabilities, pcurrent_ptr, 2);
+	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(pmadapter, &pbss_entry->cap_info, pcap_info,
+	       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;
+			continue;
+		}
+
+		switch (element_id) {
+
+		case SSID:
+			if (element_len > MRVDRV_MAX_SSID_LENGTH) {
+				bytes_left_for_current_beacon = 0;
+				continue;
+			}
+			if (!pbss_entry->ssid.ssid_len) {
+				pbss_entry->ssid.ssid_len = element_len;
+				memcpy(pmadapter, pbss_entry->ssid.ssid,
+				       (pcurrent_ptr + 2), element_len);
+			}
+			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;
+				continue;
+			}
+			memcpy(pmadapter, pbss_entry->data_rates,
+			       pcurrent_ptr + 2, element_len);
+			memcpy(pmadapter, pbss_entry->supported_rates,
+			       pcurrent_ptr + 2, element_len);
+			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(pmadapter,
+			       &pbss_entry->phy_param_set.fh_param_set,
+			       pfh_param_set, MIN(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(pmadapter,
+			       &pbss_entry->phy_param_set.ds_param_set,
+			       pds_param_set, MIN(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(pmadapter,
+			       &pbss_entry->ss_param_set.cf_param_set,
+			       pcf_param_set, MIN(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(pmadapter,
+			       &pbss_entry->ss_param_set.ibss_param_set,
+			       pibss_param_set, MIN(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(pmadapter, &pbss_entry->country_info,
+			       pcountry_info, pcountry_info->len + 2);
+			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(pmadapter, prate, pcurrent_ptr + 2,
+				       bytes_to_copy);
+
+				prate = (t_u8 *)pbss_entry->supported_rates;
+				prate += rate_size;
+				memcpy(pmadapter, prate, pcurrent_ptr + 2,
+				       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(pmadapter,
+					       (t_u8 *)&pbss_entry->wmm_ie,
+					       pcurrent_ptr, total_ie_len);
+					HEXDUMP("InterpretIE: Resp WMM_IE",
+						(t_u8 *)&pbss_entry->wmm_ie,
+						total_ie_len);
+				}
+			} else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+					   osen_oui, sizeof(osen_oui))) {
+				pbss_entry->posen_ie =
+					(IEEEtypes_Generic_t *)pcurrent_ptr;
+				pbss_entry->osen_offset =
+					(t_u16)(pcurrent_ptr -
+						pbss_entry->pbeacon_buf);
+				HEXDUMP("InterpretIE: Resp OSEN_IE",
+					(t_u8 *)pbss_entry->posen_ie,
+					(*(pbss_entry->posen_ie)).ieee_hdr.len +
+					sizeof(IEEEtypes_Header_t));
+			}
+			break;
+		case RSN_IE:
+			pbss_entry->prsn_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pbss_entry->rsn_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp RSN_IE",
+				(t_u8 *)pbss_entry->prsn_ie,
+				(*(pbss_entry->prsn_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case WAPI_IE:
+			pbss_entry->pwapi_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pbss_entry->wapi_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp WAPI_IE",
+				(t_u8 *)pbss_entry->pwapi_ie,
+				(*(pbss_entry->pwapi_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case HT_CAPABILITY:
+			pbss_entry->pht_cap = (IEEEtypes_HTCap_t *)pcurrent_ptr;
+			pbss_entry->ht_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp HTCAP_IE",
+				(t_u8 *)pbss_entry->pht_cap,
+				(*(pbss_entry->pht_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case HT_OPERATION:
+			pbss_entry->pht_info =
+				(IEEEtypes_HTInfo_t *)pcurrent_ptr;
+			pbss_entry->ht_info_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp HTINFO_IE",
+				(t_u8 *)pbss_entry->pht_info,
+				(*(pbss_entry->pht_info)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case BSSCO_2040:
+			pbss_entry->pbss_co_2040 =
+				(IEEEtypes_2040BSSCo_t *)pcurrent_ptr;
+			pbss_entry->bss_co_2040_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp 2040BSSCOEXISTANCE_IE",
+				(t_u8 *)pbss_entry->pbss_co_2040,
+				(*(pbss_entry->pbss_co_2040)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_CAPABILITY:
+			pbss_entry->pext_cap =
+				(IEEEtypes_ExtCap_t *)pcurrent_ptr;
+			pbss_entry->ext_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTCAP_IE",
+				(t_u8 *)pbss_entry->pext_cap,
+				(*(pbss_entry->pext_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case OVERLAPBSSSCANPARAM:
+			pbss_entry->poverlap_bss_scan_param =
+				(IEEEtypes_OverlapBSSScanParam_t *)pcurrent_ptr;
+			pbss_entry->overlap_bss_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp OBSS_IE",
+				(t_u8 *)pbss_entry->poverlap_bss_scan_param,
+				(*(pbss_entry->poverlap_bss_scan_param)).
+				ieee_hdr.len + sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_CAPABILITY:
+			pbss_entry->pvht_cap =
+				(IEEEtypes_VHTCap_t *)pcurrent_ptr;
+			pbss_entry->vht_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp VHTCAP_IE",
+				(t_u8 *)pbss_entry->pvht_cap,
+				(*(pbss_entry->pvht_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_OPERATION:
+			pbss_entry->pvht_oprat =
+				(IEEEtypes_VHTOprat_t *)pcurrent_ptr;
+			pbss_entry->vht_oprat_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp VHTOPER_IE",
+				(t_u8 *)pbss_entry->pvht_oprat,
+				(*(pbss_entry->pvht_oprat)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_BSS_LOAD:
+			pbss_entry->pext_bssload =
+				(IEEEtypes_ExtBSSload_t *)pcurrent_ptr;
+			pbss_entry->ext_bssload_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTBSSLOAD_IE",
+				(t_u8 *)pbss_entry->pext_bssload,
+				(*(pbss_entry->pext_bssload)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_TX_POWER_ENV:
+			pbss_entry->pvht_txpower =
+				(IEEEtypes_VHTtxpower_t *)pcurrent_ptr;
+			pbss_entry->vht_txpower_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp TXPOW_IE",
+				(t_u8 *)pbss_entry->pvht_txpower,
+				(*(pbss_entry->pvht_txpower)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_POWER_CONSTR:
+			pbss_entry->pext_pwer =
+				(IEEEtypes_ExtPwerCons_t *)pcurrent_ptr;
+			pbss_entry->ext_pwer_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTPOW_IE",
+				(t_u8 *)pbss_entry->pext_pwer,
+				(*(pbss_entry->pext_pwer)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case QUIET_CHAN:
+			pbss_entry->pquiet_chan =
+				(IEEEtypes_QuietChan_t *)pcurrent_ptr;
+			pbss_entry->quiet_chan_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp QUIETCHAN_IE",
+				(t_u8 *)pbss_entry->pquiet_chan,
+				(*(pbss_entry->pquiet_chan)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case BW_CHANNEL_SWITCH:
+			/* RANDYTODO */
+			break;
+		case AID_INFO:
+			break;
+		case OPER_MODE_NTF:
+			pbss_entry->poper_mode =
+				(IEEEtypes_OperModeNtf_t *)pcurrent_ptr;
+			pbss_entry->oper_mode_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp OPERMODENTF_IE",
+				(t_u8 *)pbss_entry->poper_mode,
+				(*(pbss_entry->poper_mode)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case 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(IN mlan_private *pmpriv,
+			    IN 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);
+		}
+	} 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(IN mlan_private *pmpriv,
+				  IN t_u32 beacon_idx,
+				  IN t_u32 num_of_ent,
+				  IN BSSDescriptor_t *pnew_beacon)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 *pbcn_store;
+	t_u32 new_bcn_size;
+	t_u32 old_bcn_size;
+	t_u32 bcn_space;
+	t_u32 adj_idx;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *tmp_buf;
+	t_u16 bcn_size = 0;
+	t_u32 bcn_offset = 0;
+
+	ENTER();
+
+	if (pmadapter->pscan_table[beacon_idx].pbeacon_buf) {
+
+		new_bcn_size = pnew_beacon->beacon_buf_size;
+		old_bcn_size =
+			pmadapter->pscan_table[beacon_idx].beacon_buf_size;
+		bcn_space =
+			pmadapter->pscan_table[beacon_idx].beacon_buf_size_max;
+		pbcn_store = pmadapter->pscan_table[beacon_idx].pbeacon_buf;
+
+		/* Set the max to be the same as current entry unless changed below */
+		pnew_beacon->beacon_buf_size_max = bcn_space;
+
+		if (new_bcn_size == old_bcn_size) {
+			/*
+			 * Beacon is the same size as the previous entry.
+			 *   Replace the previous contents with the scan result
+			 */
+			memcpy(pmadapter, pbcn_store,
+			       pnew_beacon->pbeacon_buf,
+			       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(pmadapter, pbcn_store, pnew_beacon->pbeacon_buf,
+			       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(pmadapter, pbcn_store, pnew_beacon->pbeacon_buf,
+			       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;
+		}
+		/* Point the new entry to its permanent storage space */
+		pnew_beacon->pbeacon_buf = pbcn_store;
+		wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
+	} else {
+		if ((pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+		     SCAN_BEACON_ENTRY_PAD > (pmadapter->bcn_buf +
+					      pmadapter->bcn_buf_size)) &&
+		    (pmadapter->bcn_buf_size < MAX_SCAN_BEACON_BUFFER)) {
+			/* no space for this entry, realloc bcn buffer */
+			ret = pmadapter->callbacks.moal_malloc(pmadapter->
+							       pmoal_handle,
+							       pmadapter->
+							       bcn_buf_size +
+							       DEFAULT_SCAN_BEACON_BUFFER,
+							       MLAN_MEM_DEF,
+							       (t_u8 **)
+							       &tmp_buf);
+
+			if ((ret == MLAN_STATUS_SUCCESS) && (tmp_buf)) {
+				PRINTM(MCMND,
+				       "Realloc Beacon buffer, old size=%d, new_size=%d\n",
+				       pmadapter->bcn_buf_size,
+				       pmadapter->bcn_buf_size +
+				       DEFAULT_SCAN_BEACON_BUFFER);
+				bcn_size =
+					pmadapter->pbcn_buf_end -
+					pmadapter->bcn_buf;
+				memcpy(pmadapter, tmp_buf, pmadapter->bcn_buf,
+				       bcn_size);
+				/* Adjust beacon buffer pointers that are past the current */
+				for (adj_idx = 0; adj_idx < num_of_ent;
+				     adj_idx++) {
+					bcn_offset =
+						pmadapter->pscan_table[adj_idx].
+						pbeacon_buf -
+						pmadapter->bcn_buf;
+					pmadapter->pscan_table[adj_idx].
+						pbeacon_buf =
+						tmp_buf + bcn_offset;
+					wlan_adjust_ie_in_bss_entry(pmpriv,
+								    &pmadapter->
+								    pscan_table
+								    [adj_idx]);
+				}
+				pmadapter->pbcn_buf_end = tmp_buf + bcn_size;
+				pmadapter->callbacks.moal_mfree(pmadapter->
+								pmoal_handle,
+								(t_u8 *)
+								pmadapter->
+								bcn_buf);
+				pmadapter->bcn_buf = tmp_buf;
+				pmadapter->bcn_buf_size +=
+					DEFAULT_SCAN_BEACON_BUFFER;
+			}
+		}
+		/*
+		 * No existing beacon data exists for this entry, check to see
+		 *   if we can fit it in the remaining space
+		 */
+		if (pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+		    SCAN_BEACON_ENTRY_PAD < (pmadapter->bcn_buf +
+					     pmadapter->bcn_buf_size)) {
+
+			/*
+			 * Copy the beacon buffer data from the local entry
+			 * to the adapter dev struct buffer space used to
+			 * store the raw beacon data for each entry in the
+			 * scan table
+			 */
+			memcpy(pmadapter, pmadapter->pbcn_buf_end,
+			       pnew_beacon->pbeacon_buf,
+			       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(IN 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);
+		}
+
+		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 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(IN 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(pmadapter, &pmadapter->pscan_table[j].ssid,
+			       &pmpriv->curr_bss_params.bss_descriptor.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.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(pmadapter,
+			       &pmpriv->curr_bss_params.bss_descriptor,
+			       &pmadapter->pscan_table[j],
+			       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(pmadapter, bss_new_entry,
+					       &pmpriv->curr_bss_params.
+					       bss_descriptor,
+					       sizeof(pmpriv->curr_bss_params.
+						      bss_descriptor));
+					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(pmadapter,
+						       &pmadapter->
+						       pscan_table[pmadapter->
+								   num_in_scan_table
+								   - 1],
+						       bss_new_entry,
+						       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);
+
+	/*
+	 * 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(IN mlan_private *pmpriv, IN 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(pmadapter, pmadapter->pscan_table + del_idx,
+		       pmadapter->pscan_table + del_idx + 1,
+		       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);
+			}
+		}
+	}
+
+	/* The last entry is invalid now that it has been deleted or moved back */
+	memset(pmadapter,
+	       pmadapter->pscan_table + pmadapter->num_in_scan_table - 1, 0x00,
+	       sizeof(BSSDescriptor_t));
+
+	pmadapter->num_in_scan_table--;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Delete all occurrences of a given SSID from the scan table
+ *
+ *  Iterate through the scan table and delete all entries that match a given
+ *    SSID.  Compact the remaining scan table entries.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pdel_ssid    Pointer to an SSID to be used in deleting all
+ *                        matching SSIDs from the scan table
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_scan_delete_ssid_table_entry(IN mlan_private *pmpriv,
+				  IN 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(IN mlan_private *pmpriv,
+			   IN t_u32 index, IN 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 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)) {
+		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)
+				) {
+
+				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->adhoc_aes_enabled &&
+		    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
+			   && !pmpriv->adhoc_aes_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))
+			   && !pmpriv->adhoc_aes_enabled
+			   /*
+			    * Privacy bit may NOT be set in some APs like
+			    * LinkSys WRT54G && pbss_desc->privacy
+			    */
+			) {
+			/* WPA enabled */
+			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))
+			   && !pmpriv->adhoc_aes_enabled
+			   /*
+			    * 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)
+				) {
+				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 {
+					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->adhoc_aes_enabled &&
+			   pmpriv->sec_info.encryption_mode ==
+			   MLAN_ENCRYPTION_MODE_NONE && pbss_desc->privacy) {
+			/* Ad-hoc AES enabled */
+			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->adhoc_aes_enabled &&
+			   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(IN 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(IN mlan_private *pmpriv,
+		   IN t_void *pioctl_buf, IN wlan_user_scan_cfg *puser_scan_in)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	wlan_scan_cmd_config_tlv *pscan_cfg_out = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchan_list_out;
+	t_u32 buf_size;
+	ChanScanParamSet_t *pscan_chan_list;
+
+	t_u8 keep_previous_scan;
+	t_u8 filtered_scan;
+	t_u8 scan_current_chan_only;
+	t_u8 max_chan_per_scan;
+	t_u8 i;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(wlan_scan_cmd_config_tlv), MLAN_MEM_DEF,
+			       (t_u8 **)&pscan_cfg_out);
+	if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg_out) {
+		PRINTM(MERROR, "Memory allocation for pscan_cfg_out failed!\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF,
+			       (t_u8 **)&pscan_chan_list);
+	if (ret != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
+		PRINTM(MERROR, "Failed to allocate scan_chan_list\n");
+		if (pscan_cfg_out)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_cfg_out);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(pmadapter, pscan_chan_list, 0x00, buf_size);
+	memset(pmadapter, pscan_cfg_out, 0x00,
+	       sizeof(wlan_scan_cmd_config_tlv));
+
+	keep_previous_scan = MFALSE;
+
+	ret = wlan_scan_setup_scan_config(pmpriv,
+					  puser_scan_in,
+					  &pscan_cfg_out->config,
+					  &pchan_list_out,
+					  pscan_chan_list,
+					  &max_chan_per_scan,
+					  &filtered_scan,
+					  &scan_current_chan_only);
+	if (ret != MLAN_STATUS_SUCCESS) {
+
+		PRINTM(MERROR, "Failed to setup scan config\n");
+		if (pscan_cfg_out)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_cfg_out);
+		if (pscan_chan_list)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_chan_list);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (puser_scan_in)
+		keep_previous_scan = puser_scan_in->keep_previous_scan;
+
+	if (keep_previous_scan == MFALSE) {
+		memset(pmadapter, pmadapter->pscan_table, 0x00,
+		       sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
+		pmadapter->num_in_scan_table = 0;
+		pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+		for (i = 0; i < pmadapter->num_in_chan_stats; i++)
+			pmadapter->pchan_stats[i].cca_scan_duration = 0;
+		pmadapter->idx_chan_stats = 0;
+	}
+
+	ret = wlan_scan_channel_list(pmpriv,
+				     pioctl_buf,
+				     max_chan_per_scan,
+				     filtered_scan,
+				     &pscan_cfg_out->config,
+				     pchan_list_out, pscan_chan_list);
+
+	/* Get scan command from scan_pending_q and put to cmd_pending_q */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		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(IN mlan_private *pmpriv,
+		     IN HostCmd_DS_COMMAND *pcmd, IN 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(pmpriv->adapter, pscan_cmd->bssid, pscan_cfg->specific_bssid,
+	       sizeof(pscan_cmd->bssid));
+	memcpy(pmpriv->adapter, pscan_cmd->tlv_buffer, pscan_cfg->tlv_buf,
+	       pscan_cfg->tlv_buf_len);
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN);
+
+	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+	pcmd->size = (t_u16)wlan_cpu_to_le16((t_u16)(sizeof(pscan_cmd->bss_mode)
+						     + sizeof(pscan_cmd->bssid)
+						     + pscan_cfg->tlv_buf_len
+						     + S_DS_GEN));
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief  Check if any hidden SSID found in passive scan channels
+ *          and do specific SSID active scan for those channels
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MTRUE/MFALSE
+ */
+
+t_bool
+wlan_active_scan_req_for_passive_chan(IN mlan_private *pmpriv,
+				      IN 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(pmpriv->adapter, user_scan_cfg->ssid_list,
+			       puser_scan_in->ssid_list,
+			       sizeof(user_scan_cfg->ssid_list));
+		} else {
+			pscan_req = &pscan->param.scan_req;
+			memcpy(pmpriv->adapter,
+			       user_scan_cfg->ssid_list[0].ssid,
+			       pscan_req->scan_ssid.ssid,
+			       pscan_req->scan_ssid.ssid_len);
+		}
+		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(IN mlan_private *pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = MNULL;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	HostCmd_DS_802_11_SCAN_RSP *pscan_rsp = MNULL;
+	BSSDescriptor_t *bss_new_entry = MNULL;
+	MrvlIEtypes_Data_t *ptlv;
+	MrvlIEtypes_TsfTimestamp_t *ptsf_tlv = MNULL;
+	MrvlIEtypes_ChannelStats_t *pchanstats_tlv = MNULL;
+	t_u8 *pbss_info;
+	t_u32 scan_resp_size;
+	t_u32 bytes_left;
+	t_u32 num_in_table;
+	t_u32 bss_idx;
+	t_u32 idx;
+	t_u32 tlv_buf_size;
+	t_u64 tsf_val;
+	chan_freq_power_t *cfp;
+	MrvlIEtypes_ChanBandListParamSet_t *pchan_band_tlv = MNULL;
+	ChanBandParamSet_t *pchan_band;
+	t_u8 band;
+	t_u8 is_bgscan_resp;
+	t_u32 age_ts_usec;
+	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = { 0 };
+	t_u32 status_code = 0;
+	pmlan_ioctl_req pscan_ioctl_req = MNULL;
+
+	ENTER();
+	pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+	is_bgscan_resp = (resp->command == HostCmd_CMD_802_11_BG_SCAN_QUERY);
+	if (is_bgscan_resp)
+		pscan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
+	else
+		pscan_rsp = &resp->params.scan_resp;
+
+	if (pscan_rsp->number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+		PRINTM(MERROR,
+		       "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
+		       pscan_rsp->number_of_sets);
+		status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bytes_left = wlan_le16_to_cpu(pscan_rsp->bss_descript_size);
+	PRINTM(MINFO, "SCAN_RESP: bss_descript_size %d\n", bytes_left);
+
+	scan_resp_size = resp->size;
+
+	PRINTM(MINFO, "SCAN_RESP: returned %d APs before parsing\n",
+	       pscan_rsp->number_of_sets);
+
+	num_in_table = pmadapter->num_in_scan_table;
+	pbss_info = pscan_rsp->bss_desc_and_tlv_buffer;
+
+	/*
+	 * The size of the TLV buffer is equal to the entire command response
+	 *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
+	 *   BSS Descriptions (bss_descript_size as bytesLef) and the command
+	 *   response header (S_DS_GEN)
+	 */
+	tlv_buf_size = scan_resp_size - (bytes_left
+					 + sizeof(pscan_rsp->bss_descript_size)
+					 + sizeof(pscan_rsp->number_of_sets)
+					 + S_DS_GEN);
+	if (is_bgscan_resp)
+		tlv_buf_size -=
+			sizeof(resp->params.bg_scan_query_resp.
+			       report_condition);
+
+	ptlv = (MrvlIEtypes_Data_t *)(pscan_rsp->bss_desc_and_tlv_buffer +
+				      bytes_left);
+
+	/*
+	 * Search the TLV buffer space in the scan response
+	 * for any valid TLVs
+	 */
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter,
+					  ptlv,
+					  tlv_buf_size,
+					  TLV_TYPE_TSFTIMESTAMP,
+					  (MrvlIEtypes_Data_t **)&ptsf_tlv);
+
+	/*
+	 * Search the TLV buffer space in the scan response
+	 * for any valid TLVs
+	 */
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter,
+					  ptlv,
+					  tlv_buf_size,
+					  TLV_TYPE_CHANNELBANDLIST,
+					  (MrvlIEtypes_Data_t **)
+					  &pchan_band_tlv);
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter, ptlv, tlv_buf_size,
+					  TLV_TYPE_CHANNEL_STATS,
+					  (MrvlIEtypes_Data_t **)
+					  &pchanstats_tlv);
+
+	if (pchanstats_tlv)
+		wlan_update_chan_statistics(pmpriv, pchanstats_tlv);
+
+	/*
+	 * Process each scan response returned (pscan_rsp->number_of_sets).
+	 * Save the information in the bss_new_entry and then insert into
+	 * the driver scan table either as an update to an existing entry
+	 * or as an addition at the end of the table
+	 */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+		status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	for (idx = 0; idx < pscan_rsp->number_of_sets && bytes_left; idx++) {
+		/* Zero out the bss_new_entry we are about to store info in */
+		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+		/* Process the data fields and IEs returned for this BSS */
+		if (wlan_interpret_bss_desc_with_ie(pmadapter,
+						    bss_new_entry,
+						    &pbss_info,
+						    &bytes_left,
+						    MFALSE) ==
+		    MLAN_STATUS_SUCCESS) {
+			PRINTM(MINFO, "SCAN_RESP: BSSID = " MACSTR "\n",
+			       MAC2STR(bss_new_entry->mac_address));
+
+			band = BAND_G;
+			if (pchan_band_tlv) {
+				pchan_band =
+					&pchan_band_tlv->chan_band_param[idx];
+				band = radio_type_to_band(pchan_band->bandcfg.
+							  chanBand);
+				if (!bss_new_entry->channel)
+					bss_new_entry->channel =
+						pchan_band->chan_number;
+			}
+			/*
+			 * Save the band designation for this entry
+			 * for use in join
+			 */
+			bss_new_entry->bss_band = band;
+
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								(t_u8)
+								bss_new_entry->
+								bss_band,
+								(t_u16)
+								bss_new_entry->
+								channel);
+			if (cfp)
+				bss_new_entry->freq = cfp->freq;
+			else
+				bss_new_entry->freq = 0;
+
+			/* Skip entry if on blacklisted channel */
+			if (cfp && cfp->dynamic.blacklist) {
+				PRINTM(MINFO,
+				       "SCAN_RESP: dropping entry on blacklist channel.\n");
+				continue;
+			}
+
+			/*
+			 * Search the scan table for the same bssid
+			 */
+			for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
+				if (!memcmp
+				    (pmadapter, bss_new_entry->mac_address,
+				     pmadapter->pscan_table[bss_idx].
+				     mac_address,
+				     sizeof(bss_new_entry->mac_address))) {
+					/*
+					 * If the SSID matches as well, it is a
+					 * duplicate of this entry.  Keep the
+					 * bss_idx set to this entry so we
+					 * replace the old contents in the table
+					 */
+					if ((bss_new_entry->ssid.ssid_len ==
+					     pmadapter->pscan_table[bss_idx].
+					     ssid.ssid_len)
+					    &&
+					    (!memcmp
+					     (pmadapter,
+					      bss_new_entry->ssid.ssid,
+					      pmadapter->pscan_table[bss_idx].
+					      ssid.ssid,
+					      bss_new_entry->ssid.ssid_len))) {
+						PRINTM(MINFO,
+						       "SCAN_RESP: Duplicate of index: %d\n",
+						       bss_idx);
+
+						break;
+					}
+					/*
+					 * If the SSID is NULL for same BSSID
+					 * keep the bss_idx set to this entry
+					 * so we replace the old contents in
+					 * the table
+					 */
+					if (!memcmp
+					    (pmadapter,
+					     pmadapter->pscan_table[bss_idx].
+					     ssid.ssid, null_ssid,
+					     pmadapter->pscan_table[bss_idx].
+					     ssid.ssid_len)) {
+						PRINTM(MINFO,
+						       "SCAN_RESP: Duplicate of index: %d\n",
+						       bss_idx);
+						break;
+					}
+				}
+			}
+			/*
+			 * If the bss_idx is equal to the number of entries
+			 * in the table, the new entry was not a duplicate;
+			 * append it to the scan table
+			 */
+			if (bss_idx == num_in_table) {
+				/*
+				 * Range check the bss_idx, keep it limited
+				 * to the last entry
+				 */
+				if (bss_idx == MRVDRV_MAX_BSSID_LIST)
+					bss_idx--;
+				else
+					num_in_table++;
+			}
+
+			/*
+			 * 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(pmpriv->adapter, &tsf_val,
+				       &ptsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
+				       sizeof(tsf_val));
+				tsf_val = wlan_le64_to_cpu(tsf_val);
+				memcpy(pmpriv->adapter,
+				       &bss_new_entry->network_tsf, &tsf_val,
+				       sizeof(bss_new_entry->network_tsf));
+			}
+
+			/* Copy the locally created bss_new_entry to the scan table */
+			memcpy(pmadapter, &pmadapter->pscan_table[bss_idx],
+			       bss_new_entry,
+			       sizeof(pmadapter->pscan_table[bss_idx]));
+
+		} else {
+			/* Error parsing/interpreting the scan response, skipped */
+			PRINTM(MERROR,
+			       "SCAN_RESP: wlan_interpret_bss_desc_with_ie returned error\n");
+		}
+	}
+
+	PRINTM(MINFO, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
+	       pscan_rsp->number_of_sets,
+	       num_in_table - pmadapter->num_in_scan_table, num_in_table);
+
+	/* Update the total number of BSSIDs in the scan table */
+	pmadapter->num_in_scan_table = num_in_table;
+	/* Update the age_in_second */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->age_in_secs,
+						  &age_ts_usec);
+	if (is_bgscan_resp)
+		goto done;
+	wlan_request_cmd_lock(pmadapter);
+	if (!util_peek_list
+	    (pmadapter->pmoal_handle, &pmadapter->scan_pending_q, MNULL,
+	     MNULL)) {
+		wlan_release_cmd_lock(pmadapter);
+		if (pmadapter->pscan_ioctl_req) {
+			if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)->
+			    sub_command == MLAN_OID_SCAN_SPECIFIC_SSID ||
+			    ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)->
+			    sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+				if (wlan_active_scan_req_for_passive_chan
+				    (pmpriv, pmadapter->pscan_ioctl_req)) {
+					goto done;
+				}
+			}
+		}
+		/*
+		 * Process the resulting scan table:
+		 *   - Remove any bad ssids
+		 *   - Update our current BSS information from scan data
+		 */
+		wlan_scan_process_results(pmpriv);
+
+		wlan_request_cmd_lock(pmadapter);
+		pmadapter->scan_processing = MFALSE;
+		pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+		pmadapter->pscan_ioctl_req = MNULL;
+		/* Need to indicate IOCTL complete */
+		if (pscan_ioctl_req) {
+			pscan_ioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+			/* Indicate ioctl complete */
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 (pmlan_ioctl_req)
+						 pscan_ioctl_req,
+						 MLAN_STATUS_SUCCESS);
+		}
+		wlan_release_cmd_lock(pmadapter);
+		pmadapter->bgscan_reported = MFALSE;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
+	} else {
+		/* If firmware not ready, do not issue any more scan commands */
+		if (pmadapter->hw_status != WlanHardwareStatusReady) {
+			wlan_release_cmd_lock(pmadapter);
+			status_code = MLAN_ERROR_FW_NOT_READY;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		} else {
+			/* Get scan command from scan_pending_q and put to cmd_pending_q */
+			pcmd_node =
+				(cmd_ctrl_node *)util_dequeue_list(pmadapter->
+								   pmoal_handle,
+								   &pmadapter->
+								   scan_pending_q,
+								   MNULL,
+								   MNULL);
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MTRUE);
+			wlan_release_cmd_lock(pmadapter);
+		}
+	}
+
+done:
+	if (bss_new_entry)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
+	if (ret) {
+		/* Flush all pending scan commands */
+		wlan_flush_scan_queue(pmadapter);
+		wlan_request_cmd_lock(pmadapter);
+		pmadapter->scan_processing = MFALSE;
+		pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+		pmadapter->pscan_ioctl_req = MNULL;
+		if (pscan_ioctl_req) {
+			pscan_ioctl_req->status_code = status_code;
+			/* Indicate ioctl complete */
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pscan_ioctl_req,
+						 MLAN_STATUS_FAILURE);
+		}
+		wlan_release_cmd_lock(pmadapter);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Prepare an extended scan command to be sent to the firmware
+ *
+ *  Use the wlan_scan_cmd_config sent to the command processing module in
+ *   the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN_EXT command
+ *   struct to send to firmware.
+ *
+ *  @param pmpriv     A pointer to mlan_private structure
+ *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
+ *                    firmware with the HostCmd_DS_802_11_SCAN_EXT structure
+ *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
+ *                    to set the fields/TLVs for the command sent to firmware
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_scan_ext(IN mlan_private *pmpriv,
+			 IN HostCmd_DS_COMMAND *pcmd, IN 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);
+
+	pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
+
+	memcpy(pmpriv->adapter, pext_scan_cmd->tlv_buffer,
+	       pscan_cfg->tlv_buf, 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(IN mlan_private *pmpriv,
+			 IN HostCmd_DS_COMMAND *resp, IN 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;
+	ENTER();
+
+	PRINTM(MINFO, "EXT scan returns successfully\n");
+	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 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(IN mlan_private *pmpriv,
+			   IN t_u8 number_of_sets,
+			   IN t_u8 *pscan_resp, IN 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 bss_idx;
+	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;
+	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = { 0 };
+
+	ENTER();
+	pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+	if (number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+		PRINTM(MERROR,
+		       "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
+		       number_of_sets);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bytes_left = scan_resp_size;
+	PRINTM(MINFO, "EXT_SCAN: bss_descript_size %d\n", scan_resp_size);
+	PRINTM(MINFO, "EXT_SCAN: returned %d APs before parsing\n",
+	       number_of_sets);
+
+	num_in_table = pmadapter->num_in_scan_table;
+	ptlv = (MrvlIEtypes_Data_t *)pscan_resp;
+
+	/*
+	 *  Process each scan response returned number_of_sets. Save
+	 *    the information in the bss_new_entry and then insert into the
+	 *    driver scan table either as an update to an existing entry
+	 *    or as an addition at the end of the table
+	 */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	for (idx = 0; idx < number_of_sets && bytes_left >
+	     sizeof(MrvlIEtypesHeader_t); idx++) {
+		tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+		tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+		if (bytes_left < sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+			PRINTM(MERROR,
+			       "EXT_SCAN: Error bytes left < TLV length\n");
+			break;
+		}
+		pscan_rsp_tlv = MNULL;
+		pscan_info_tlv = MNULL;
+		bytes_left_for_tlv = bytes_left;
+		/*
+		 * BSS response TLV with beacon or probe response buffer
+		 * at the initial position of each descriptor
+		 */
+		if (tlv_type == TLV_TYPE_BSS_SCAN_RSP) {
+			pbss_info = (t_u8 *)ptlv;
+			pscan_rsp_tlv = (MrvlIEtypes_Bss_Scan_Rsp_t *)ptlv;
+			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+			bytes_left_for_tlv -=
+				(tlv_len + sizeof(MrvlIEtypesHeader_t));
+		} else
+			break;
+
+		/* Process variable TLV */
+		while (bytes_left_for_tlv >= sizeof(MrvlIEtypesHeader_t) &&
+		       wlan_le16_to_cpu(ptlv->header.type) !=
+		       TLV_TYPE_BSS_SCAN_RSP) {
+			tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+			if (bytes_left_for_tlv <
+			    sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+				PRINTM(MERROR,
+				       "EXT_SCAN: Error in processing TLV, "
+				       "bytes left < TLV length\n");
+				pscan_rsp_tlv = MNULL;
+				bytes_left_for_tlv = 0;
+				continue;
+			}
+			switch (tlv_type) {
+			case TLV_TYPE_BSS_SCAN_INFO:
+				pscan_info_tlv =
+					(MrvlIEtypes_Bss_Scan_Info_t *)ptlv;
+				if (tlv_len !=
+				    sizeof(MrvlIEtypes_Bss_Scan_Info_t) -
+				    sizeof(MrvlIEtypesHeader_t)) {
+					bytes_left_for_tlv = 0;
+					continue;
+				}
+				break;
+			default:
+				break;
+			}
+			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+			bytes_left -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
+			bytes_left_for_tlv -=
+				(tlv_len + sizeof(MrvlIEtypesHeader_t));
+		}
+		/* No BSS response TLV */
+		if (pscan_rsp_tlv == MNULL)
+			break;
+
+		/*
+		 * Advance pointer to the beacon buffer length and
+		 * update the bytes count so that the function
+		 * wlan_interpret_bss_desc_with_ie() can handle the
+		 * scan buffer withut any change
+		 */
+		pbss_info += sizeof(t_u16);
+		bytes_left -= sizeof(t_u16);
+
+		/* Zero out the bss_new_entry we are about to store info in */
+		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+		/* Process the data fields and IEs returned for this BSS */
+		if (wlan_interpret_bss_desc_with_ie(pmadapter,
+						    bss_new_entry,
+						    &pbss_info,
+						    &bytes_left,
+						    MTRUE) ==
+		    MLAN_STATUS_SUCCESS) {
+			PRINTM(MINFO, "EXT_SCAN: BSSID = " MACSTR "\n",
+			       MAC2STR(bss_new_entry->mac_address));
+
+			band = BAND_G;
+			/*
+			 * If the BSS info TLV was appended to the scan results,
+			 * save this entry's TSF value in the networkTSF field.
+			 * The networkTSF is the firmware's TSF value at the
+			 * time the beacon or probe response was received.
+			 */
+			if (pscan_info_tlv) {
+				/* RSSI is 2 byte long */
+				bss_new_entry->rssi =
+					-(t_s32)(wlan_le16_to_cpu
+						 (pscan_info_tlv->rssi));
+				PRINTM(MINFO, "EXT_SCAN: RSSI=%d\n",
+				       bss_new_entry->rssi);
+				memcpy(pmpriv->adapter, &tsf_val,
+				       &pscan_info_tlv->tsf, sizeof(tsf_val));
+				tsf_val = wlan_le64_to_cpu(tsf_val);
+				memcpy(pmpriv->adapter,
+				       &bss_new_entry->network_tsf, &tsf_val,
+				       sizeof(bss_new_entry->network_tsf));
+				band = radio_type_to_band(pscan_info_tlv->
+							  bandcfg.chanBand);
+			}
+			/* Save the band designation for this entry for use in join */
+			bss_new_entry->bss_band = band;
+
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								(t_u8)
+								bss_new_entry->
+								bss_band,
+								(t_u16)
+								bss_new_entry->
+								channel);
+			if (cfp)
+				bss_new_entry->freq = cfp->freq;
+			else
+				bss_new_entry->freq = 0;
+
+			/* Skip entry if on blacklisted channel */
+			if (cfp && cfp->dynamic.blacklist) {
+				PRINTM(MINFO,
+				       "EXT_SCAN: dropping entry on blacklist channel.\n");
+				continue;
+			}
+
+			/*
+			 * 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++;
+			}
+
+			/*
+			 * 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;
+			}
+
+			/* Copy the locally created bss_new_entry to the scan table */
+			memcpy(pmadapter, &pmadapter->pscan_table[bss_idx],
+			       bss_new_entry,
+			       sizeof(pmadapter->pscan_table[bss_idx]));
+		} else {
+			/* Error parsing/interpreting the scan response, skipped */
+			PRINTM(MERROR,
+			       "EXT_SCAN: wlan_interpret_bss_desc_with_ie returned error\n");
+		}
+	}
+
+	PRINTM(MINFO, "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(IN mlan_private *pmpriv,
+				  IN 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) {
+		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 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(IN mlan_private *pmpriv,
+			      IN HostCmd_DS_COMMAND *pcmd, IN 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(IN mlan_private *pmpriv,
+				IN 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;
+			tlv_chan_list->chan_scan_param[chan_idx].chan_scan_mode.
+				disable_chan_filt = MTRUE;
+		}
+	}
+
+	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(IN mlan_private *pmpriv,
+		       IN HostCmd_DS_COMMAND *pcmd, IN 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;
+	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;
+
+	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(pmadapter, pwildcard_ssid_tlv->ssid,
+		       bg_scan_in->ssid_list[ssid_idx].ssid,
+		       MIN(MLAN_MAX_SSID_LENGTH, ssid_len));
+		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;
+	}
+
+	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);
+
+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(IN mlan_private *pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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(IN mlan_private *pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_scan *pscan = MNULL;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	ENTER();
+	wlan_ret_802_11_scan(pmpriv, resp, MNULL);
+	if (pioctl_buf) {
+		pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
+		pscan->param.scan_resp.pscan_table =
+			(t_u8 *)pmadapter->pscan_table;
+		pscan->param.scan_resp.num_in_scan_table =
+			pmadapter->num_in_scan_table;
+		pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs;
+		pscan->param.scan_resp.pchan_stats =
+			(t_u8 *)pmadapter->pchan_stats;
+		pscan->param.scan_resp.num_in_chan_stats =
+			pmadapter->num_in_chan_stats;
+
+		pioctl_buf->data_read_written = sizeof(mlan_scan_resp) +
+			MLAN_SUB_COMMAND_SIZE;
+
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function finds ssid in ssid list.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param ssid         SSID to find in the list
+ *  @param bssid        BSSID to qualify the SSID selection (if provided)
+ *  @param mode         Network mode: Infrastructure or IBSS
+ *
+ *  @return             index in BSSID list or < 0 if error
+ */
+t_s32
+wlan_find_ssid_in_list(IN mlan_private *pmpriv,
+		       IN mlan_802_11_ssid *ssid, IN t_u8 *bssid, IN 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(IN mlan_private *pmpriv, IN t_u8 *bssid, IN 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(IN pmlan_adapter pmadapter,
+	      IN mlan_802_11_ssid *ssid1, IN 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(IN mlan_private *pmpriv,
+		       OUT 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(pmadapter, &preq_ssid_bssid->ssid, &preq_bss->ssid,
+		       sizeof(mlan_802_11_ssid));
+		memcpy(pmadapter, (t_u8 *)&preq_ssid_bssid->bssid,
+		       (t_u8 *)&preq_bss->mac_address, 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;
+	}
+
+	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(IN mlan_private *pmpriv,
+			IN t_void *pioctl_buf, IN 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(pmpriv->adapter, pscan_cfg->ssid_list[0].ssid,
+	       preq_ssid->ssid, preq_ssid->ssid_len);
+	pscan_cfg->keep_previous_scan = MTRUE;
+
+	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(IN 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(pmpriv->adapter, pmpriv->pcurr_bcn_buf,
+				       pcurr_bss->pbeacon_buf,
+				       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(IN 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_sd8897/mlan/mlan_sdio.c b/wlan_sd8897/mlan/mlan_sdio.c
new file mode 100644
index 0000000..92a4f72
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_sdio.c
@@ -0,0 +1,2588 @@
+/** @file mlan_sdio.c
+ *
+ *  @brief This file contains SDIO specific code
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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
+********************************************************/
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB2   28
+/** FW header for CRC check disable */
+static t_u8 fw_crc_header_rb2[FW_CRC_HEADER_RB2] = {
+	0x05, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x0c, 0x00, 0x00, 0x00,
+	0x9d, 0x32, 0xbb, 0x11,
+	0x01, 0x00, 0x00, 0x7f,
+	0x00, 0x00, 0x00, 0x00,
+	0x67, 0xd6, 0xfc, 0x25
+};
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB   24
+/** FW header for CRC check disable */
+static t_u8 fw_crc_header_rb[FW_CRC_HEADER_RB] = {
+	0x01, 0x00, 0x00, 0x00, 0x04, 0xfd, 0x00, 0x04,
+	0x08, 0x00, 0x00, 0x00, 0x26, 0x52, 0x2a, 0x7b,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/********************************************************
+		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;
+
+	const mlan_sdio_device *psdio_device = pmadapter->psdio_device;
+	t_u8 host_int_rsr_reg = psdio_device->host_int_rsr_reg;
+	t_u8 host_int_rsr_mask = psdio_device->reg->sdio_int_mask;
+	t_u8 card_misc_cfg_reg = psdio_device->reg->card_misc_cfg_reg;
+	t_u8 card_config_2_1_reg = psdio_device->card_config_2_1_reg;
+	t_u8 cmd_config_0 = psdio_device->cmd_config_0;
+	t_u8 cmd_config_1 = psdio_device->cmd_config_1;
+
+	ENTER();
+	pmadapter->ioport = 0;
+
+	if (psdio_device->supports_sdio_new_mode) {
+		pmadapter->ioport = MEM_PORT;
+	} else {
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       psdio_device->io_port_0_reg, &reg))
+			pmadapter->ioport |= (reg & 0xff);
+		else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       psdio_device->io_port_1_reg, &reg))
+			pmadapter->ioport |= ((reg & 0xff) << 8);
+		else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       psdio_device->io_port_2_reg, &reg))
+			pmadapter->ioport |= ((reg & 0xff) << 16);
+		else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	PRINTM(MINFO, "SDIO FUNC1 IO port: 0x%x\n", pmadapter->ioport);
+
+	if (psdio_device->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 (IS_SD8977(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);
+		}
+	}
+	/* 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->mp_rd_bitmap;
+	const mlan_sdio_device *psdio_device = pmadapter->psdio_device;
+	const mlan_sdio_card_reg *reg = psdio_device->reg;
+	t_bool new_mode = psdio_device->supports_sdio_new_mode;
+	t_u8 max_ports = psdio_device->max_ports;
+
+	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->mp_rd_bitmap & CTRL_PORT_MASK)) {
+		pmadapter->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->mp_rd_bitmap);
+	} else {
+		if (pmadapter->mp_rd_bitmap & (1 << pmadapter->curr_rd_port)) {
+			pmadapter->mp_rd_bitmap &=
+				(t_u32)(~(1 << pmadapter->curr_rd_port));
+			*pport = pmadapter->curr_rd_port;
+
+			/* hw rx wraps round only after port (MAX_PORT-1) */
+			if (++pmadapter->curr_rd_port == max_ports)
+				pmadapter->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->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->mp_wr_bitmap;
+	const mlan_sdio_device *psdio_device = pmadapter->psdio_device;
+	const mlan_sdio_card_reg *reg = psdio_device->reg;
+	t_bool new_mode = psdio_device->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->mp_data_port_mask)) {
+		pmadapter->data_sent = MTRUE;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	if (pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port)) {
+		pmadapter->mp_wr_bitmap &=
+			(t_u32)(~(1 << pmadapter->curr_wr_port));
+		*pport = pmadapter->curr_wr_port;
+		if (++pmadapter->curr_wr_port == pmadapter->mp_end_port)
+			pmadapter->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->curr_wr_port, wr_bitmap,
+		       pmadapter->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->mp_wr_bitmap);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function polls the card status register.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param bits       the bit mask
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_poll_card_status(mlan_adapter *pmadapter, t_u8 bits)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 tries;
+	t_u32 cs = 0;
+
+	ENTER();
+
+	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       pmadapter->psdio_device->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->psdio_device->
+						      reg->status_reg_0,
+						      &fws0)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      pmadapter->psdio_device->
+						      reg->status_reg_1,
+						      &fws1)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	*dat = (t_u16)((fws1 << 8) | fws0);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**  @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->psdio_device->
+						      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->psdio_device->
+						       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->psdio_device->
+						       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_prog_fw_w_helper(IN 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;
+	t_u16 card_type = pmadapter->card_type;
+	const mlan_sdio_card_reg *reg = pmadapter->psdio_device->reg;
+	t_u32 read_base_0_reg = reg->base_0_reg;
+	t_u32 read_base_1_reg = reg->base_1_reg;
+	t_u8 crc_buffer = 0;
+	t_u8 *header_crc_fw;
+	t_u8 header_crc_fw_len = 0;
+	if (IS_SD8787(card_type)) {
+		header_crc_fw = fw_crc_header_rb;
+		header_crc_fw_len = FW_CRC_HEADER_RB;
+	} else {
+		header_crc_fw = fw_crc_header_rb2;
+		header_crc_fw_len = FW_CRC_HEADER_RB2;
+	}
+
+	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 (!pmadapter->init_para.fw_crc_check
+	    && (IS_SD8777(card_type) || (IS_SD8787(card_type)))
+		) {
+		/* CRC check not required, use custom header first */
+
+		firmware = header_crc_fw;
+		firmwarelen = header_crc_fw_len;
+
+		crc_buffer = 1;
+	}
+
+	/* 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;
+		}
+
+		if (!crc_buffer)
+			/* 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)) {
+			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);
+
+			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->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;
+		if (crc_buffer && offset >= header_crc_fw_len
+		    && (IS_SD8777(card_type) || (IS_SD8787(card_type)))
+			) {
+			/* Custom header download complete, restore original FW */
+			offset = 0;
+			firmware = fw;
+			firmwarelen = fw_len;
+			crc_buffer = 0;
+		}
+	} 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_host_int(pmlan_adapter pmadapter)
+{
+	mlan_status ret;
+
+	ENTER();
+	ret = wlan_sdio_disable_host_int_mask(pmadapter, HIM_DISABLE);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function decodes the rx packet &
+ *  calls corresponding handlers according to the packet type
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf      A pointer to the SDIO data/cmd buffer
+ *  @param upld_typ  Type of rx packet
+ *  @param lock_flag  flag for spin_lock.
+ *  @return          MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_decode_rx_packet(mlan_adapter *pmadapter, mlan_buffer *pmbuf,
+		      t_u32 upld_typ, t_u8 lock_flag)
+{
+	t_u8 *cmd_buf;
+	t_u32 event;
+
+	ENTER();
+
+	switch (upld_typ) {
+	case MLAN_TYPE_DATA:
+		PRINTM(MINFO, "--- Rx: Data packet ---\n");
+		pmbuf->data_len = (pmadapter->upld_len - INTF_HEADER_LEN);
+		pmbuf->data_offset += INTF_HEADER_LEN;
+		if (pmadapter->rx_work_flag) {
+			if (lock_flag)
+				pmadapter->callbacks.moal_spin_lock(pmadapter->
+								    pmoal_handle,
+								    pmadapter->
+								    rx_data_queue.
+								    plock);
+			util_enqueue_list_tail(pmadapter->pmoal_handle,
+					       &pmadapter->rx_data_queue,
+					       (pmlan_linked_list)pmbuf, MNULL,
+					       MNULL);
+			pmadapter->rx_pkts_queued++;
+			if (lock_flag)
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 rx_data_queue.plock);
+		} else {
+			wlan_handle_rx_packet(pmadapter, pmbuf);
+		}
+		pmadapter->data_received = MTRUE;
+		break;
+
+	case MLAN_TYPE_CMD:
+		PRINTM(MINFO, "--- Rx: Cmd Response ---\n");
+		/* take care of curr_cmd = NULL case */
+		if (!pmadapter->curr_cmd) {
+			cmd_buf = pmadapter->upld_buf;
+			if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
+				wlan_process_sleep_confirm_resp(pmadapter,
+								pmbuf->pbuf +
+								pmbuf->
+								data_offset +
+								INTF_HEADER_LEN,
+								pmadapter->
+								upld_len -
+								INTF_HEADER_LEN);
+			}
+			pmadapter->upld_len -= INTF_HEADER_LEN;
+			memcpy(pmadapter, cmd_buf,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       INTF_HEADER_LEN, MIN(MRVDRV_SIZE_OF_CMD_BUFFER,
+						    pmadapter->upld_len -
+						    INTF_HEADER_LEN));
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+		} else {
+			pmadapter->cmd_resp_received = MTRUE;
+			pmadapter->upld_len -= INTF_HEADER_LEN;
+			pmbuf->data_len = pmadapter->upld_len;
+			pmbuf->data_offset += 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 +
+					       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(pmadapter, pmadapter->event_body,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       MLAN_EVENT_HEADER_LEN,
+			       pmadapter->upld_len - MLAN_EVENT_HEADER_LEN);
+		}
+
+		/* 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 += INTF_HEADER_LEN;
+		pmbuf->data_len -= 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;
+}
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+/**
+ *  @brief This function receives single packet
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_receive_single_packet(mlan_adapter *pmadapter)
+{
+	mlan_buffer *pmbuf;
+	t_u8 port;
+	t_u16 rx_len;
+	t_u32 pkt_type = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	pmbuf = pmadapter->mpa_rx.mbuf_arr[0];
+	port = pmadapter->mpa_rx.start_port;
+	rx_len = pmadapter->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->ioport +
+							  port)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (pkt_type != MLAN_TYPE_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->mpa_rx_count[0]++;
+	wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
+done:
+	if (ret != MLAN_STATUS_SUCCESS)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	MP_RX_AGGR_BUF_RESET(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function receives data from the card in aggregate mode.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_receive_mp_aggr_buf(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer mbuf_aggr;
+	mlan_buffer *mbuf_deaggr;
+	t_u32 pind = 0;
+	t_u32 pkt_len, pkt_type = 0;
+	t_u8 *curr_ptr;
+	t_u32 cmd53_port = 0;
+	t_u32 i = 0;
+	t_u32 port_count = 0;
+	t_bool new_mode = pmadapter->psdio_device->supports_sdio_new_mode;
+
+	/* do aggr RX now */
+	PRINTM(MINFO, "do_rx_aggr: num of packets: %d\n",
+	       pmadapter->mpa_rx.pkt_cnt);
+
+	memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+	if (pmadapter->mpa_rx.pkt_cnt == 1)
+		return wlan_receive_single_packet(pmadapter);
+	if (!pmadapter->mpa_rx.buf) {
+		mbuf_aggr.data_len = pmadapter->mpa_rx.buf_len;
+		mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+		mbuf_aggr.use_count = 0;
+		for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) {
+			pmadapter->mpa_rx.mbuf_arr[pind]->data_len =
+				pmadapter->mpa_rx.len_arr[pind];
+			wlan_link_buf_to_aggr(&mbuf_aggr,
+					      pmadapter->mpa_rx.mbuf_arr[pind]);
+		}
+	} else {
+		mbuf_aggr.pbuf = (t_u8 *)pmadapter->mpa_rx.buf;
+		mbuf_aggr.data_len = pmadapter->mpa_rx.buf_len;
+	}
+
+	if (new_mode) {
+		port_count = bitcount(pmadapter->mpa_rx.ports) - 1;
+		/* port_count = pmadapter->mpa_rx.pkt_cnt - 1; */
+		cmd53_port =
+			(pmadapter->
+			 ioport | SDIO_MPA_ADDR_BASE | (port_count << 8))
+			+ pmadapter->mpa_rx.start_port;
+	} else {
+		cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE |
+			      (pmadapter->mpa_rx.ports << 4)) +
+			pmadapter->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->mpa_rx.buf && pmadapter->mpa_rx.pkt_cnt > 1) {
+		for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) {
+			mbuf_deaggr = pmadapter->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->mpa_rx.buf,
+			    MIN(pmadapter->mpa_rx.buf_len, MAX_DATA_DUMP_LEN));
+
+		curr_ptr = pmadapter->mpa_rx.buf;
+
+		for (pind = 0; pind < pmadapter->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->mpa_rx.mbuf_arr[pind];
+			if ((pkt_type == MLAN_TYPE_DATA) &&
+			    (pkt_len <= pmadapter->mpa_rx.len_arr[pind])) {
+				memcpy(pmadapter,
+				       mbuf_deaggr->pbuf +
+				       mbuf_deaggr->data_offset, curr_ptr,
+				       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->mpa_rx.len_arr[pind]);
+				wlan_free_mlan_buffer(pmadapter, mbuf_deaggr);
+			}
+			curr_ptr += pmadapter->mpa_rx.len_arr[pind];
+		}
+	}
+	if (pmadapter->rx_work_flag)
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      pmadapter->rx_data_queue.
+						      plock);
+	pmadapter->mpa_rx_count[pmadapter->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_device *psdio_device = pmadapter->psdio_device;
+	const mlan_sdio_card_reg *reg = psdio_device->reg;
+	t_bool new_mode = psdio_device->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->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->mp_rd_bitmap & reg->data_port_mask)) ||
+	    (!new_mode &&
+	     (pmadapter->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 (pmadapter->psdio_device->supports_sdio_new_mode) {
+			MP_RX_AGGR_SETUP_NEWMODE(pmadapter, pmbuf, port,
+						 rx_len);
+		} else {
+			MP_RX_AGGR_SETUP_NONEWMODE(pmadapter, pmbuf, port,
+						   rx_len);
+		}
+
+		if (MP_RX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
+		    (((pmadapter->psdio_device->supports_sdio_new_mode) &&
+		      (MP_RX_AGGR_PORT_LIMIT_REACHED_NEWMODE(pmadapter))) ||
+		     ((!pmadapter->psdio_device->supports_sdio_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->ioport + port)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		if ((new_mode && (pkt_type != MLAN_TYPE_DATA)
+		    ) ||
+		    (!new_mode &&
+		     ((port == CTRL_PORT) &&
+		      ((pkt_type != MLAN_TYPE_EVENT) &&
+		       (pkt_type != MLAN_TYPE_CMD))))) {
+			if (new_mode)
+				PRINTM(MERROR,
+				       "receive a wrong pkt from DATA PORT: type=%d, len=%dd\n",
+				       pkt_type, pmbuf->data_len);
+			else
+				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))
+			pmadapter->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 (pmadapter->psdio_device->supports_sdio_new_mode) {
+			MP_RX_AGGR_SETUP_NEWMODE(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->mpa_rx.pkt_cnt; pind++) {
+				wlan_free_mlan_buffer(pmadapter,
+						      pmadapter->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;
+
+}
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/**
+ *  @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_bool new_mode = pmadapter->psdio_device->supports_sdio_new_mode;
+	t_u8 mp_aggr_pkt_limit = pmadapter->psdio_device->mp_aggr_pkt_limit;
+
+	ENTER();
+
+	if (!pmadapter->mpa_tx.pkt_cnt) {
+		LEAVE();
+		return ret;
+	}
+	PRINTM(MINFO, "host_2_card_mp_aggr: Send aggregation buffer."
+	       "%d %d\n", pmadapter->mpa_tx.start_port,
+	       pmadapter->mpa_tx.ports);
+
+	memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+	if (!pmadapter->mpa_tx.buf && pmadapter->mpa_tx.pkt_cnt > 1) {
+		mbuf_aggr.data_len = pmadapter->mpa_tx.buf_len;
+		mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+		mbuf_aggr.use_count = 0;
+		for (i = 0; i < pmadapter->mpa_tx.pkt_cnt; i++)
+			wlan_link_buf_to_aggr(&mbuf_aggr,
+					      pmadapter->mpa_tx.mbuf_arr[i]);
+	} else {
+		mbuf_aggr.pbuf = (t_u8 *)pmadapter->mpa_tx.buf;
+		mbuf_aggr.data_len = pmadapter->mpa_tx.buf_len;
+	}
+
+	if (new_mode) {
+		port_count = bitcount(pmadapter->mpa_tx.ports) - 1;
+		cmd53_port =
+			(pmadapter->
+			 ioport | SDIO_MPA_ADDR_BASE | (port_count << 8))
+			+ pmadapter->mpa_tx.start_port;
+	} else {
+		cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE |
+			      (pmadapter->mpa_tx.ports << 4)) +
+			pmadapter->mpa_tx.start_port;
+	}
+
+	if (pmadapter->mpa_tx.pkt_cnt == 1)
+		cmd53_port = pmadapter->ioport + pmadapter->mpa_tx.start_port;
+    /** only one packet */
+	if (!pmadapter->mpa_tx.buf && pmadapter->mpa_tx.pkt_cnt == 1)
+		ret = wlan_write_data_sync(pmadapter,
+					   pmadapter->mpa_tx.mbuf_arr[0],
+					   cmd53_port);
+	else
+		ret = wlan_write_data_sync(pmadapter, &mbuf_aggr, cmd53_port);
+	if (!pmadapter->mpa_tx.buf) {
+	/** free mlan buffer */
+		for (i = 0; i < pmadapter->mpa_tx.pkt_cnt; i++) {
+			wlan_write_data_complete(pmadapter,
+						 pmadapter->mpa_tx.mbuf_arr[i],
+						 MLAN_STATUS_SUCCESS);
+		}
+	}
+	if (!(pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port))
+	    && (pmadapter->mpa_tx.pkt_cnt < mp_aggr_pkt_limit))
+		pmadapter->mpa_sent_no_ports++;
+	pmadapter->mpa_tx_count[pmadapter->mpa_tx.pkt_cnt - 1]++;
+	pmadapter->last_mp_wr_bitmap[pmadapter->last_mp_index] =
+		pmadapter->mp_wr_bitmap;
+	pmadapter->last_mp_wr_ports[pmadapter->last_mp_index] = cmd53_port;
+	pmadapter->last_mp_wr_len[pmadapter->last_mp_index] =
+		pmadapter->mpa_tx.buf_len;
+	pmadapter->last_curr_wr_port[pmadapter->last_mp_index] =
+		pmadapter->curr_wr_port;
+	memcpy(pmadapter,
+	       (t_u8 *)&pmadapter->last_mp_wr_info[pmadapter->last_mp_index *
+						   mp_aggr_pkt_limit],
+	       (t_u8 *)pmadapter->mpa_tx.mp_wr_info,
+	       mp_aggr_pkt_limit * sizeof(t_u16)
+		);
+	pmadapter->last_mp_index++;
+	if (pmadapter->last_mp_index >= SDIO_MP_DBG_NUM)
+		pmadapter->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->psdio_device->mp_aggr_pkt_limit;
+
+	ENTER();
+
+	PRINTM(MIF_D, "host_2_card_mp_aggr: next_pkt_len: %d curr_port:%d\n",
+	       next_pkt_len, port);
+
+	if (!pmadapter->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->
+				     mp_wr_bitmap & (1 << pmadapter->
+						     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->
+				     mp_wr_bitmap & (1 << pmadapter->
+						     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->
+			     mp_wr_bitmap & (1 << pmadapter->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->mpa_sent_last_pkt++;
+	}
+
+	if (f_precopy_cur_buf) {
+		PRINTM(MINFO, "host_2_card_mp_aggr: Precopy current buffer\n");
+		if (pmadapter->mpa_buf)
+			memcpy(pmadapter, pmadapter->mpa_buf +
+			       (pmadapter->last_mp_index * mp_aggr_pkt_limit +
+				pmadapter->mpa_tx.pkt_cnt) *
+			       MLAN_SDIO_BLOCK_SIZE,
+			       mbuf->pbuf + mbuf->data_offset,
+			       MLAN_SDIO_BLOCK_SIZE);
+		if (!pmadapter->mpa_tx.buf) {
+			if (pmadapter->psdio_device->supports_sdio_new_mode)
+				MP_TX_AGGR_BUF_PUT_SG_NEWMODE(pmadapter, mbuf,
+							      port);
+			else
+				MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(pmadapter, mbuf,
+								port);
+			aggr_sg = MTRUE;
+		} else {
+
+			if (pmadapter->psdio_device->supports_sdio_new_mode)
+				MP_TX_AGGR_BUF_PUT_NEWMODE(pmadapter, mbuf,
+							   port);
+			else
+				MP_TX_AGGR_BUF_PUT_NONEWMODE(pmadapter, mbuf,
+							     port);
+		}
+		if (MP_TX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
+		    (!pmadapter->psdio_device->supports_sdio_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->ioport + port);
+		if (!(pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port)))
+			pmadapter->mpa_sent_no_ports++;
+		pmadapter->last_mp_wr_bitmap[pmadapter->last_mp_index] =
+			pmadapter->mp_wr_bitmap;
+		pmadapter->last_mp_wr_ports[pmadapter->last_mp_index] =
+			pmadapter->ioport + port;
+		pmadapter->last_mp_wr_len[pmadapter->last_mp_index] =
+			mbuf->data_len;
+		memset(pmadapter,
+		       (t_u8 *)&pmadapter->last_mp_wr_info[pmadapter->
+							   last_mp_index *
+							   mp_aggr_pkt_limit],
+		       0, sizeof(t_u16) * mp_aggr_pkt_limit);
+		pmadapter->last_mp_wr_info[pmadapter->last_mp_index *
+					   mp_aggr_pkt_limit] =
+			*(t_u16 *)(mbuf->pbuf + mbuf->data_offset);
+		pmadapter->last_curr_wr_port[pmadapter->last_mp_index] =
+			pmadapter->curr_wr_port;
+		if (pmadapter->mpa_buf)
+			memcpy(pmadapter,
+			       pmadapter->mpa_buf +
+			       (pmadapter->last_mp_index * mp_aggr_pkt_limit *
+				MLAN_SDIO_BLOCK_SIZE),
+			       mbuf->pbuf + mbuf->data_offset,
+			       MLAN_SDIO_BLOCK_SIZE);
+		pmadapter->last_mp_index++;
+		if (pmadapter->last_mp_index >= SDIO_MP_DBG_NUM)
+			pmadapter->last_mp_index = 0;
+		pmadapter->mpa_tx_count[0]++;
+	}
+	if (f_postcopy_cur_buf) {
+		PRINTM(MINFO, "host_2_card_mp_aggr: Postcopy current buffer\n");
+		if (pmadapter->mpa_buf)
+			memcpy(pmadapter, pmadapter->mpa_buf +
+			       (pmadapter->last_mp_index * mp_aggr_pkt_limit +
+				pmadapter->mpa_tx.pkt_cnt) *
+			       MLAN_SDIO_BLOCK_SIZE,
+			       mbuf->pbuf + mbuf->data_offset,
+			       MLAN_SDIO_BLOCK_SIZE);
+		if (!pmadapter->mpa_tx.buf) {
+			if (pmadapter->psdio_device->supports_sdio_new_mode)
+				MP_TX_AGGR_BUF_PUT_SG_NEWMODE(pmadapter, mbuf,
+							      port);
+			else
+				MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(pmadapter, mbuf,
+								port);
+			aggr_sg = MTRUE;
+		} else {
+			if (pmadapter->psdio_device->supports_sdio_new_mode)
+				MP_TX_AGGR_BUF_PUT_NEWMODE(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;
+}
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+/********************************************************
+		Global functions
+********************************************************/
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interface is present
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param val        Winner status (0: winner)
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status
+wlan_check_winner_status(mlan_adapter *pmadapter, t_u32 *val)
+{
+	t_u32 winner = 0;
+	pmlan_callbacks pcb;
+	t_u8 card_fw_status0_reg = pmadapter->psdio_device->reg->status_reg_0;
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_read_reg(pmadapter->pmoal_handle, card_fw_status0_reg,
+			       &winner)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param pollnum    Maximum polling number
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_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 == 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 downloads firmware to card
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param pmfw			A pointer to firmware image
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_dnld_fw(IN pmlan_adapter pmadapter, IN pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Download the firmware image via helper */
+	ret = wlan_prog_fw_w_helper(pmadapter, pmfw->pfw_buf, pmfw->fw_len);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	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->psdio_device->host_int_status_reg,
+			   &sdio_ireg);
+
+	/* Disable host interrupt mask register for SDIO */
+	ret = wlan_disable_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();
+
+	switch (card_type) {
+	case CARD_TYPE_SD8777:
+		pmadapter->psdio_device = &mlan_sdio_sd8777;
+		break;
+	case CARD_TYPE_SD8787:
+		pmadapter->psdio_device = &mlan_sdio_sd8787;
+		break;
+	case CARD_TYPE_SD8887:
+		pmadapter->psdio_device = &mlan_sdio_sd8887;
+		break;
+	case CARD_TYPE_SD8801:
+		pmadapter->psdio_device = &mlan_sdio_sd8801;
+		break;
+	case CARD_TYPE_SD8897:
+		pmadapter->psdio_device = &mlan_sdio_sd8897;
+		break;
+	case CARD_TYPE_SD8797:
+		pmadapter->psdio_device = &mlan_sdio_sd8797;
+		break;
+	case CARD_TYPE_SD8977:
+		pmadapter->psdio_device = &mlan_sdio_sd8977;
+		break;
+	case CARD_TYPE_SD8997:
+		pmadapter->psdio_device = &mlan_sdio_sd8997;
+		break;
+	case CARD_TYPE_SD8987:
+		pmadapter->psdio_device = &mlan_sdio_sd8987;
+		break;
+	default:
+		PRINTM(MERROR, "can't get right card type \n");
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets interrupt status.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_interrupt(pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer mbuf;
+	t_u32 sdio_ireg = 0;
+
+	t_u8 max_mp_regs = pmadapter->psdio_device->reg->max_mp_regs;
+	t_u8 host_int_status_reg = pmadapter->psdio_device->host_int_status_reg;
+
+	ENTER();
+
+	memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+	mbuf.pbuf = pmadapter->mp_regs;
+	mbuf.data_len = max_mp_regs;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf,
+				     REG_PORT | MLAN_SDIO_BYTE_MODE_MASK, 0)) {
+		PRINTM(MERROR, "moal_read_data_sync: read registers failed\n");
+		pmadapter->dbg.num_int_read_failure++;
+		goto done;
+	}
+
+	DBG_HEXDUMP(MIF_D, "SDIO MP Registers", pmadapter->mp_regs,
+		    max_mp_regs);
+	sdio_ireg = pmadapter->mp_regs[host_int_status_reg];
+	pmadapter->dbg.last_int_status = pmadapter->sdio_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->num_of_irq++;
+		pcb->moal_spin_lock(pmadapter->pmoal_handle,
+				    pmadapter->pint_lock);
+		pmadapter->sdio_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 enables the host interrupts.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_enable_host_int(pmlan_adapter pmadapter)
+{
+	mlan_status ret;
+	t_u8 mask = HIM_ENABLE;
+	mask = pmadapter->psdio_device->reg->host_int_enable;
+
+	ENTER();
+	ret = wlan_sdio_enable_host_int_mask(pmadapter, mask);
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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->psdio_device->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->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->ioport +
+							  port)) {
+		PRINTM(MERROR, "Recovery: Fail to do cmd53\n");
+	}
+	if (pkt_type != MLAN_TYPE_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++;
+	}
+	PRINTM(MMSG, "wlan: Success handle rx port=%d, rx_len=%d \n", port,
+	       rx_len);
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function checks the interrupt status and handle it accordingly.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_process_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_device *psdio_device = pmadapter->psdio_device;
+	const mlan_sdio_card_reg *reg = psdio_device->reg;
+	t_bool new_mode = psdio_device->supports_sdio_new_mode;
+	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 = psdio_device->cmd_rd_len_0;
+	t_u8 cmd_rd_len_1 = psdio_device->cmd_rd_len_1;
+
+	ENTER();
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+	sdio_ireg = pmadapter->sdio_ireg;
+	pmadapter->sdio_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->mp_regs[cmd_rd_len_1]) << 8;
+			rx_len |= (t_u16)pmadapter->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 <= 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->
+						   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%d\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->mp_wr_bitmap & pmadapter->mp_data_port_mask)
+			pmadapter->mp_invalid_update++;
+		pmadapter->mp_wr_bitmap =
+			(t_u32)pmadapter->mp_regs[reg->wr_bitmap_l];
+		pmadapter->mp_wr_bitmap |=
+			((t_u32)pmadapter->mp_regs[reg->wr_bitmap_u]) << 8;
+		if (psdio_device->supports_sdio_new_mode) {
+			pmadapter->mp_wr_bitmap |=
+				((t_u32)pmadapter->
+				 mp_regs[reg->wr_bitmap_1l]) << 16;
+			pmadapter->mp_wr_bitmap |=
+				((t_u32)pmadapter->
+				 mp_regs[reg->wr_bitmap_1u]) << 24;
+		}
+		bit_count =
+			bitcount(pmadapter->mp_wr_bitmap & pmadapter->
+				 mp_data_port_mask);
+		if (bit_count) {
+			pmadapter->mp_update[bit_count - 1]++;
+			if (pmadapter->mp_update[bit_count - 1] == 0xffffffff)
+				memset(pmadapter, pmadapter->mp_update, 0,
+				       sizeof(pmadapter->mp_update));
+		}
+
+		pmadapter->last_recv_wr_bitmap = pmadapter->mp_wr_bitmap;
+		PRINTM(MINTR, "DNLD: wr_bitmap=0x%08x\n",
+		       pmadapter->mp_wr_bitmap);
+		if (pmadapter->data_sent &&
+		    (pmadapter->
+		     mp_wr_bitmap & (1 << pmadapter->curr_wr_port))) {
+			PRINTM(MINFO, " <--- Tx DONE Interrupt --->\n");
+			pmadapter->data_sent = MFALSE;
+		}
+	}
+
+	if ((!psdio_device->supports_sdio_new_mode) &&
+	    (pmadapter->cmd_sent == MTRUE)) {
+		/* Check if firmware has attach buffer at command port and update just that in wr_bit_map. */
+		pmadapter->mp_wr_bitmap |=
+			(t_u32)pmadapter->mp_regs[reg->
+						  wr_bitmap_l] & CTRL_PORT_MASK;
+		if (pmadapter->mp_wr_bitmap & CTRL_PORT_MASK)
+			pmadapter->cmd_sent = MFALSE;
+	}
+
+	PRINTM(MINFO, "cmd_sent=%d, data_sent=%d\n", pmadapter->cmd_sent,
+	       pmadapter->data_sent);
+	if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
+		pmadapter->mp_rd_bitmap =
+			(t_u32)pmadapter->mp_regs[reg->rd_bitmap_l];
+		pmadapter->mp_rd_bitmap |=
+			((t_u32)pmadapter->mp_regs[reg->rd_bitmap_u]) << 8;
+		if (psdio_device->supports_sdio_new_mode) {
+			pmadapter->mp_rd_bitmap |=
+				((t_u32)pmadapter->
+				 mp_regs[reg->rd_bitmap_1l]) << 16;
+			pmadapter->mp_rd_bitmap |=
+				((t_u32)pmadapter->
+				 mp_regs[reg->rd_bitmap_1u]) << 24;
+		}
+		PRINTM(MINTR, "UPLD: rd_bitmap=0x%08x\n",
+		       pmadapter->mp_rd_bitmap);
+
+		while (MTRUE) {
+			ret = wlan_get_rd_port(pmadapter, &port);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MINFO,
+				       "no more rd_port to be handled\n");
+				break;
+			}
+			len_reg_l = rd_len_p0_l + (port << 1);
+			len_reg_u = rd_len_p0_u + (port << 1);
+			rx_len = ((t_u16)pmadapter->mp_regs[len_reg_u]) << 8;
+			rx_len |= (t_u16)pmadapter->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 <= 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);
+			if ((!new_mode && (port == CTRL_PORT)) ||
+			    (rx_len > MLAN_TX_DATA_BUF_SIZE_2K
+			     && !pmadapter->enable_net_mon))
+				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 defined(SDIO_MULTI_PORT_RX_AGGR)
+				if (MLAN_STATUS_SUCCESS ==
+				    wlan_sdio_card_to_host_recovery(pmadapter,
+								    port,
+								    rx_len))
+					continue;
+#endif
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(MINFO, "rx_len = %d\n", rx_len);
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+			if (MLAN_STATUS_SUCCESS !=
+			    wlan_sdio_card_to_host_mp_aggr(pmadapter, pmbuf,
+							   port, rx_len)) {
+#else
+			/* 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->ioport + port)) {
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+				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);
+#ifndef SDIO_MULTI_PORT_RX_AGGR
+				wlan_free_mlan_buffer(pmadapter, pmbuf);
+#endif
+				ret = MLAN_STATUS_FAILURE;
+				goto term_cmd53;
+			}
+#ifndef SDIO_MULTI_PORT_RX_AGGR
+			wlan_decode_rx_packet(pmadapter, pmbuf, upld_typ,
+					      MTRUE);
+#endif
+		}
+		/* We might receive data/sleep_cfm at the same time */
+		/* reset data_receive flag to avoid ps_state change */
+		if ((ps_state == PS_STATE_SLEEP_CFM) &&
+		    (pmadapter->ps_state == PS_STATE_SLEEP))
+			pmadapter->data_received = MFALSE;
+	}
+
+	ret = MLAN_STATUS_SUCCESS;
+	goto done;
+
+term_cmd53:
+	/* terminate cmd53 */
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      HOST_TO_CARD_EVENT_REG,
+						      &cr))
+		PRINTM(MERROR, "read CFG reg failed\n");
+	PRINTM(MINFO, "Config Reg val = %d\n", cr);
+	if (MLAN_STATUS_SUCCESS != pcb->moal_write_reg(pmadapter->pmoal_handle,
+						       HOST_TO_CARD_EVENT_REG,
+						       (cr | HOST_TERM_CMD53)))
+		PRINTM(MERROR, "write CFG reg failed\n");
+	PRINTM(MINFO, "write success\n");
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      HOST_TO_CARD_EVENT_REG,
+						      &cr))
+		PRINTM(MERROR, "read CFG reg failed\n");
+	PRINTM(MINFO, "Config reg val =%x\n", cr);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param type      data or command
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include SDIO header)
+ *  @param tx_param  A pointer to mlan_tx_param
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_sdio_host_to_card(mlan_adapter *pmadapter, t_u8 type, mlan_buffer *pmbuf,
+		       mlan_tx_param *tx_param)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 buf_block_len;
+	t_u32 blksz;
+	t_u8 port = 0;
+	t_u32 cmd53_port = 0;
+	t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset;
+
+	ENTER();
+
+	/* Allocate buffer and copy payload */
+	blksz = MLAN_SDIO_BLOCK_SIZE;
+	buf_block_len = (pmbuf->data_len + blksz - 1) / blksz;
+	*(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+	*(t_u16 *)&payload[2] = wlan_cpu_to_le16(type);
+
+	/*
+	 * This is SDIO specific header
+	 *  t_u16 length,
+	 *  t_u16 type (MLAN_TYPE_DATA = 0,
+	 *    MLAN_TYPE_CMD = 1, MLAN_TYPE_EVENT = 3)
+	 */
+	if (type == MLAN_TYPE_DATA) {
+		ret = wlan_get_wr_port_data(pmadapter, &port);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "no wr_port available: wr_bitmap=0x%08x curr_wr_port=%d\n",
+			       pmadapter->mp_wr_bitmap,
+			       pmadapter->curr_wr_port);
+			goto exit;
+		}
+		/* Transfer data to card */
+		pmbuf->data_len = buf_block_len * blksz;
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+		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
+		ret = wlan_write_data_sync(pmadapter, pmbuf,
+					   pmadapter->ioport + port);
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+	} else {
+		/*Type must be MLAN_TYPE_CMD */
+		pmadapter->cmd_sent = MTRUE;
+		if (!pmadapter->psdio_device->supports_sdio_new_mode)
+			pmadapter->mp_wr_bitmap &= (t_u32)(~(1 << CTRL_PORT));
+		if (pmbuf->data_len <= 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 (pmadapter->psdio_device->supports_sdio_new_mode)
+			cmd53_port = (pmadapter->ioport) | CMD_PORT_SLCT;
+		else
+			cmd53_port = pmadapter->ioport + CTRL_PORT;
+		ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port);
+	}
+
+	if (ret == MLAN_STATUS_FAILURE) {
+		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->
+			     mp_wr_bitmap & (1 << pmadapter->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(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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(IN 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->psdio_device->mp_aggr_pkt_limit;
+
+	ENTER();
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	if ((pmadapter->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->max_seg_size < pmadapter->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->mpa_tx.head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mpa_tx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP TX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->mpa_tx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->mpa_tx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable TX SG mode\n");
+		pmadapter->mpa_tx.head_ptr = MNULL;
+		pmadapter->mpa_tx.buf = MNULL;
+	}
+	pmadapter->mpa_tx.buf_size = mpa_tx_buf_size;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	if ((pmadapter->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->max_seg_size < pmadapter->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->mpa_rx.head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mpa_rx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP RX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->mpa_rx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->mpa_rx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable RX SG mode\n");
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+	}
+	pmadapter->mpa_rx.buf_size = mpa_rx_buf_size;
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+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(IN mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	if (pmadapter->mpa_tx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mpa_tx.head_ptr);
+		pmadapter->mpa_tx.head_ptr = MNULL;
+		pmadapter->mpa_tx.buf = MNULL;
+		pmadapter->mpa_tx.buf_size = 0;
+	}
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	if (pmadapter->mpa_rx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mpa_rx.head_ptr);
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+		pmadapter->mpa_rx.buf_size = 0;
+	}
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#endif /* SDIO_MULTI_PORT_TX_AGGR || SDIO_MULTI_PORT_RX_AGGR */
+
+/**
+ *  @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(IN 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->int_mode == INT_MODE_GPIO) {
+		if (pmadapter->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->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,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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(pmpriv->adapter, psdio_gpio_int, pdata_buf,
+		       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;
+}
+
+#define SD8897_FW_RESET_REG  0x0E8
+#define SD8887_FW_RESET_REG  0x0B6
+#define SD8977_SD8997_FW_RESET_REG  0x0EE
+#define SD8887_SD8897_FW_RESET_VAL  1
+#define SD8977_SD8997_FW_RESET_VAL  0x99
+mlan_status
+wlan_reset_fw(pmlan_adapter pmadapter)
+{
+	t_u32 tries = 0;
+	t_u32 value = 1;
+	t_u32 reset_reg = pmadapter->psdio_device->reg->reset_reg;
+	t_u8 reset_val = pmadapter->psdio_device->reg->reset_val;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	wlan_pm_wakeup_card(pmadapter);
+
+    /** 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 (pmadapter->card_type == CARD_TYPE_SD8977
+	    || pmadapter->card_type == CARD_TYPE_SD8987
+	    || pmadapter->card_type == CARD_TYPE_SD8997) {
+		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);
+	}
+	/* 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;
+}
diff --git a/wlan_sd8897/mlan/mlan_sdio.h b/wlan_sd8897/mlan/mlan_sdio.h
new file mode 100644
index 0000000..49947f8
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_sdio.h
@@ -0,0 +1,1169 @@
+/** @file mlan_sdio.h
+  *
+  * @brief This file contains definitions for SDIO interface.
+  * driver.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/****************************************************
+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 : Host interrupt RSR */
+#define HOST_INT_RSR_REG		0x01
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR		(0x1U)
+#define HOST_INT_RSR_MASK		0xFF
+
+/** Host Control Registers : Host interrupt mask */
+#define HOST_INT_MASK_REG		0x02
+
+/** 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 : Host interrupt status */
+#define HOST_INT_STATUS_REG		0x03
+
+/** 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 status */
+#define UP_LD_HOST_INT_STATUS		(0x1U)
+/** Host Control Registers : Download host interrupt status */
+#define DN_LD_HOST_INT_STATUS		(0x2U)
+
+/** Port for registers */
+#define REG_PORT			0
+/** LSB of read bitmap */
+#define RD_BITMAP_L			0x04
+/** MSB of read bitmap */
+#define RD_BITMAP_U			0x05
+/** LSB of write bitmap */
+#define WR_BITMAP_L			0x06
+/** MSB of write bitmap */
+#define WR_BITMAP_U			0x07
+/** LSB of read length for port 0 */
+#define RD_LEN_P0_L			0x08
+/** MSB of read length for port 0 */
+#define RD_LEN_P0_U			0x09
+/** Ctrl port */
+#define CTRL_PORT			0
+/** Ctrl port mask */
+#define CTRL_PORT_MASK			0x0001
+/** Data port mask */
+#define DATA_PORT_MASK			0xfffe
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT		MBIT(4)
+
+/** Host Control Registers : Host transfer status */
+#define HOST_RESTART_REG		0x28
+/** 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 */
+/** Card Control Registers : Card to host event */
+#define CARD_TO_HOST_EVENT_REG		0x30
+/** 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 interrupt mask register */
+#define HOST_INTERRUPT_MASK_REG		0x34
+/** 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 : Card interrupt status register */
+#define CARD_INTERRUPT_STATUS_REG	0x38
+/** 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 : Card interrupt RSR register */
+#define CARD_INTERRUPT_RSR_REG		0x3c
+/** 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 : SQ Read base address 0 register */
+#define READ_BASE_0_REG			0x40
+/** Card Control Registers : SQ Read base address 1 register */
+#define READ_BASE_1_REG			0x41
+
+/** Card Control Registers : Card revision register */
+#define CARD_REVISION_REG		0x5c
+
+/** Firmware status 0 register (SCRATCH0_0) */
+#define CARD_FW_STATUS0_REG		0x60
+/** Firmware status 1 register (SCRATCH0_1) */
+#define CARD_FW_STATUS1_REG		0x61
+/** Rx length register (SCRATCH0_2) */
+#define CARD_RX_LEN_REG			0x62
+/** Rx unit register (SCRATCH0_3) */
+#define CARD_RX_UNIT_REG		0x63
+
+/** Card Control Registers : Card OCR 0 register */
+#define CARD_OCR_0_REG			0x68
+/** Card Control Registers : Card OCR 1 register */
+#define CARD_OCR_1_REG			0x69
+/** Card Control Registers : Card OCR 3 register */
+#define CARD_OCR_3_REG			0x6A
+/** Card Control Registers : Card config register */
+#define CARD_CONFIG_REG			0x6B
+/** Card Control Registers : Miscellaneous Configuration Register */
+#define CARD_MISC_CFG_REG		0x6C
+
+/** Card Control Registers : Debug 0 register */
+#define DEBUG_0_REG			0x70
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0			(0x1U)
+/** Card Control Registers : Debug 1 register */
+#define DEBUG_1_REG			0x71
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1			(0x1U)
+/** Card Control Registers : Debug 2 register */
+#define DEBUG_2_REG			0x72
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2			(0x1U)
+/** Card Control Registers : Debug 3 register */
+#define DEBUG_3_REG			0x73
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3			(0x1U)
+
+/** Host Control Registers : I/O port 0 */
+#define IO_PORT_0_REG			0x78
+/** Host Control Registers : I/O port 1 */
+#define IO_PORT_1_REG			0x79
+/** Host Control Registers : I/O port 2 */
+#define IO_PORT_2_REG			0x7A
+
+/** Port for memory */
+#define MEM_PORT	                        0x10000
+/** Card Control Registers : cmd53 new mode */
+#define CMD53_NEW_MODE      (0x1U << 0)
+#define CMD_PORT_RD_LEN_EN  (0x1U << 2)
+#define CMD_PORT_AUTO_EN              (0x1U << 0)
+#define CMD_PORT_SLCT                   0x8000
+/** Ctrl port mask */
+#define CTRL_PORT_MASK			0x0001
+/** 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
+
+/** SD8787 card type */
+#define CARD_TYPE_SD8787   0x01
+/** SD8777 card type */
+#define CARD_TYPE_SD8777   0x02
+/** SD8887 card type */
+#define CARD_TYPE_SD8887   0x03
+/** SD8801 card type */
+#define CARD_TYPE_SD8801   0x04
+/** SD8897 card type */
+#define CARD_TYPE_SD8897   0x05
+/** SD8797 card type */
+#define CARD_TYPE_SD8797   0x06
+/** SD8977 card type */
+#define CARD_TYPE_SD8977   0x07
+/** SD8997 card type */
+#define CARD_TYPE_SD8997   0x08
+/** SD8987 card type */
+#define CARD_TYPE_SD8987   0x09
+
+#define IS_SD8777(ct) (CARD_TYPE_SD8777 == (ct))
+#define IS_SD8787(ct) (CARD_TYPE_SD8787 == (ct))
+#define IS_SD8887(ct) (CARD_TYPE_SD8887 == (ct))
+#define IS_SD8801(ct) (CARD_TYPE_SD8801 == (ct))
+#define IS_SD8897(ct) (CARD_TYPE_SD8897 == (ct))
+#define IS_SD8797(ct) (CARD_TYPE_SD8797 == (ct))
+#define IS_SD8977(ct) (CARD_TYPE_SD8977 == (ct))
+#define IS_SD8997(ct) (CARD_TYPE_SD8997 == (ct))
+#define IS_SD8987(ct) (CARD_TYPE_SD8987 == (ct))
+
+/** Event header Len*/
+#define MLAN_EVENT_HEADER_LEN           8
+
+/** SDIO byte mode size */
+#define MAX_BYTE_MODE_SIZE             512
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** The base address for packet with multiple ports aggregation */
+#define SDIO_MPA_ADDR_BASE             0x1000
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+
+/** SDIO Tx aggregation in progress ? */
+#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0)
+
+/** SDIO Tx aggregation buffer room for next packet ? */
+#define MP_TX_AGGR_BUF_HAS_ROOM(a, mbuf, len) \
+			(((a->mpa_tx.buf_len) + len) <= (a->mpa_tx.buf_size))
+
+/** Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */
+#define MP_TX_AGGR_BUF_PUT_NEWMODE(a, mbuf, port) do {                  \
+	pmadapter->callbacks.moal_memmove(a->pmoal_handle, \
+		&a->mpa_tx.buf[a->mpa_tx.buf_len], \
+		mbuf->pbuf+mbuf->data_offset, mbuf->data_len);\
+	a->mpa_tx.buf_len += mbuf->data_len;                        \
+    a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+	if (!a->mpa_tx.pkt_cnt) {                                   \
+	    a->mpa_tx.start_port = port;                            \
+	}                                                           \
+	a->mpa_tx.ports |= (1 << port);                             \
+	a->mpa_tx.pkt_cnt++;                                        \
+} while (0)
+
+#define MP_TX_AGGR_BUF_PUT_SG_NEWMODE(a, mbuf, port) do {               \
+	a->mpa_tx.buf_len += mbuf->data_len;                        \
+    a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+    a->mpa_tx.mbuf_arr[a->mpa_tx.pkt_cnt] = mbuf;               \
+	if (!a->mpa_tx.pkt_cnt) {                                   \
+	    a->mpa_tx.start_port = port;                            \
+	}                                                           \
+	a->mpa_tx.ports |= (1 << port);                             \
+	a->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->mpa_tx.buf[a->mpa_tx.buf_len], \
+		mbuf->pbuf+mbuf->data_offset, mbuf->data_len);\
+	a->mpa_tx.buf_len += mbuf->data_len;                        \
+	a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+	if (!a->mpa_tx.pkt_cnt) {                                   \
+	    a->mpa_tx.start_port = port;                            \
+	}                                                           \
+	if (a->mpa_tx.start_port <= port) {                         \
+	    a->mpa_tx.ports |= (1 << (a->mpa_tx.pkt_cnt));			\
+	} else {                                                    \
+	      a->mpa_tx.ports |= (1 << (a->mpa_tx.pkt_cnt \
+			+ 1 + (a->psdio_device->max_ports - a->mp_end_port)));  \
+	}                                                           \
+	a->mpa_tx.pkt_cnt++;                                       \
+} while (0)
+#define MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(a, mbuf, port) do {                  \
+	a->mpa_tx.buf_len += mbuf->data_len;                        \
+    a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+    a->mpa_tx.mbuf_arr[a->mpa_tx.pkt_cnt] = mbuf;               \
+	if (!a->mpa_tx.pkt_cnt) {                                   \
+	    a->mpa_tx.start_port = port;                            \
+	}                                                           \
+	if (a->mpa_tx.start_port <= port) {                         \
+	    a->mpa_tx.ports |= (1 << (a->mpa_tx.pkt_cnt));			\
+	} else {                                                    \
+	      a->mpa_tx.ports |= (1 << (a->mpa_tx.pkt_cnt \
+			+ 1 + (a->psdio_device->max_ports - a->mp_end_port)));  \
+	}                                                           \
+	a->mpa_tx.pkt_cnt++;                                       \
+} while (0)
+/** SDIO Tx aggregation limit ? */
+#define MP_TX_AGGR_PKT_LIMIT_REACHED(a) ((a->mpa_tx.pkt_cnt) \
+			== (a->mpa_tx.pkt_aggr_limit))
+
+/** SDIO Tx aggregation port limit ? */
+
+#define MP_TX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_wr_port < \
+                a->mpa_tx.start_port) && (((a->psdio_device->max_ports - \
+                a->mpa_tx.start_port) + a->curr_wr_port) >= \
+                    a->psdio_device->mp_aggr_pkt_limit))
+
+/** Reset SDIO Tx aggregation buffer parameters */
+#define MP_TX_AGGR_BUF_RESET(a) do {         \
+	memset(a, a->mpa_tx.mp_wr_info, 0, sizeof(a->mpa_tx.mp_wr_info)); \
+	a->mpa_tx.pkt_cnt = 0;                   \
+	a->mpa_tx.buf_len = 0;                   \
+	a->mpa_tx.ports = 0;                     \
+	a->mpa_tx.start_port = 0;                \
+} while (0)
+
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+
+/** SDIO Rx aggregation limit ? */
+#define MP_RX_AGGR_PKT_LIMIT_REACHED(a) (a->mpa_rx.pkt_cnt \
+		== a->mpa_rx.pkt_aggr_limit)
+
+/** SDIO Rx aggregation port limit ? */
+#define MP_RX_AGGR_PORT_LIMIT_REACHED_NEWMODE(a) \
+			(((a->curr_rd_port < a->mpa_rx.start_port) && \
+			(((a->psdio_device->max_ports - a->mpa_rx.start_port) + a->curr_rd_port) \
+			>= (a->mp_end_port >> 1))) || \
+			((a->curr_rd_port - a->mpa_rx.start_port) >= \
+			(a->mp_end_port >> 1)))
+#define MP_RX_AGGR_PORT_LIMIT_REACHED_NONEWMODE(a) ((a->curr_rd_port < \
+                a->mpa_rx.start_port) && (((a->psdio_device->max_ports - \
+                a->mpa_rx.start_port) + a->curr_rd_port) >= \
+                a->psdio_device->mp_aggr_pkt_limit))
+
+/** SDIO Rx aggregation in progress ? */
+#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0)
+
+/** SDIO Rx aggregation buffer room for next packet ? */
+#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len)   \
+	((a->mpa_rx.buf_len + rx_len) <= a->mpa_rx.buf_size)
+
+/** Prepare to copy current packet from card to SDIO Rx aggregation buffer */
+#define MP_RX_AGGR_SETUP_NEWMODE(a, mbuf, port, rx_len) do {   \
+	a->mpa_rx.buf_len += rx_len;                       \
+	if (!a->mpa_rx.pkt_cnt) {                          \
+	    a->mpa_rx.start_port = port;                   \
+	}                                                  \
+	a->mpa_rx.ports |= (1 << port);                    \
+	a->mpa_rx.mbuf_arr[a->mpa_rx.pkt_cnt] = mbuf;      \
+	a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = rx_len;     \
+	a->mpa_rx.pkt_cnt++;                              \
+} while (0);
+
+#define MP_RX_AGGR_SETUP_NONEWMODE(a, mbuf, port, rx_len) do {   \
+	a->mpa_rx.buf_len += rx_len;                       \
+	if (!a->mpa_rx.pkt_cnt) {                          \
+	    a->mpa_rx.start_port = port;                   \
+	}                                                  \
+	if (a->mpa_rx.start_port <= port) {                  \
+	    a->mpa_rx.ports |= (1 << (a->mpa_rx.pkt_cnt)); \
+	} else {                                           \
+	    a->mpa_rx.ports |= (1 << (a->mpa_rx.pkt_cnt + 1)); \
+	}                                                  \
+	a->mpa_rx.mbuf_arr[a->mpa_rx.pkt_cnt] = mbuf;      \
+	a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = rx_len;     \
+	a->mpa_rx.pkt_cnt++;                               \
+} while (0);
+
+/** Reset SDIO Rx aggregation buffer parameters */
+#define MP_RX_AGGR_BUF_RESET(a) do {         \
+	a->mpa_rx.pkt_cnt = 0;                   \
+	a->mpa_rx.buf_len = 0;                   \
+	a->mpa_rx.ports = 0;                     \
+	a->mpa_rx.start_port = 0;                \
+} while (0)
+
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+/** Register sdio 87xx card structure */
+static const struct _mlan_sdio_card_reg mlan_reg_sd87xx = {
+     /** start read port */
+	.start_rd_port = 1,
+    /** start write port */
+	.start_wr_port = 1,
+    /** base register0 */
+	.base_0_reg = 0x40,	//0x0040,
+    /** base1 register1 */
+	.base_1_reg = 0x41,	//0x0041,
+    /** poll register */
+	.poll_reg = 0x30,
+    /** host interrupt enable */
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK,
+    /** host interrupt status*/
+	.host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS,
+     /** status register0 */
+	.status_reg_0 = 0x60,
+    /** status register 1 */
+	.status_reg_1 = 0x61,
+    /** sdio interrupt mask */
+	.sdio_int_mask = 0x3f,
+    /** data port mask */
+	.data_port_mask = 0x0000fffe,
+    /** maximum mp register */
+	.max_mp_regs = 64,
+     /** read bitmap lower byte */
+	.rd_bitmap_l = 0x04,
+    /** read bitmap upper byte */
+	.rd_bitmap_u = 0x05,
+    /** write bitmap lower byte */
+	.wr_bitmap_l = 0x06,
+    /** write bitmap upper byte */
+	.wr_bitmap_u = 0x07,
+    /** read port0 length lower byte */
+	.rd_len_p0_l = 0x08,
+    /** read port0 length upper byte */
+	.rd_len_p0_u = 0x09,
+    /** card misc configuration register */
+	.card_misc_cfg_reg = 0x6c,
+     /** scratch reg used for reset and check SOC wakeup*/
+	.reset_reg = 0x64,
+    /** reset value, not set for 87xx */
+	.reset_val = 0,
+};
+
+/** Registeri sdio 8887 card structure */
+static const struct _mlan_sdio_card_reg mlan_reg_sd8887 = {
+     /** start read port */
+	.start_rd_port = 0,
+    /** start write port */
+	.start_wr_port = 0,
+    /** base register0 */
+	.base_0_reg = 0x6C,
+    /** base register1 */
+	.base_1_reg = 0x6D,
+    /** poll register */
+	.poll_reg = 0x5C,
+    /** host interrupt enable */
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+		CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+     /** host interrupt status */
+	.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 register0 */
+	.status_reg_0 = 0x90,
+    /** status register1 */
+	.status_reg_1 = 0x91,
+     /** sdio interrupt mask */
+	.sdio_int_mask = 0xff,
+    /** data port mask */
+	.data_port_mask = 0xffffffff,
+    /** maximum mp register */
+	.max_mp_regs = 196,
+    /** read bitmap lower byte */
+	.rd_bitmap_l = 0x10,
+    /** read bitmap upper byte */
+	.rd_bitmap_u = 0x11,
+    /** read bitmap1 lower byte */
+	.rd_bitmap_1l = 0x12,
+    /** read bitmap1 upper byte */
+	.rd_bitmap_1u = 0x13,
+    /** write bitmap lower byte */
+	.wr_bitmap_l = 0x14,
+    /** write bitmap upper byte */
+	.wr_bitmap_u = 0x15,
+    /** write bitmap1 lower byte */
+	.wr_bitmap_1l = 0x16,
+    /** write bitmap1 upper byte */
+	.wr_bitmap_1u = 0x17,
+    /** read port0 length lower byte */
+	.rd_len_p0_l = 0x18,
+    /** read port0 length upper byte */
+	.rd_len_p0_u = 0x19,
+    /** card misc configuration register */
+	.card_misc_cfg_reg = 0xD8,
+     /** scratch reg used for reset and check SOC wakeup*/
+	.reset_reg = 0xB6,
+    /** reset value */
+	.reset_val = 1,
+};
+
+/** Register sdio 8897 card structure */
+static const struct _mlan_sdio_card_reg mlan_reg_sd8897 = {
+     /** start read port */
+	.start_rd_port = 0,
+    /** start write port */
+	.start_wr_port = 0,
+    /** base register0 */
+	.base_0_reg = 0x60,
+    /** base register1 */
+	.base_1_reg = 0x61,
+    /** poll register */
+	.poll_reg = 0x50,
+    /** host interrupt enable */
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+		CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+     /** host interrupt status*/
+	.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 register0 */
+	.status_reg_0 = 0xC0,
+     /** status register1 */
+	.status_reg_1 = 0xC1,
+     /** sdio interrupt mask */
+	.sdio_int_mask = 0xff,
+    /** data port mask */
+	.data_port_mask = 0xffffffff,
+    /** maximum mp register */
+	.max_mp_regs = 184,
+    /** read bitmap lower byte */
+	.rd_bitmap_l = 0x04,
+    /** read bitmap upper byte */
+	.rd_bitmap_u = 0x05,
+    /** read bitmap1 lower byte */
+	.rd_bitmap_1l = 0x06,
+    /** read bitmap1 upper byte */
+	.rd_bitmap_1u = 0x07,
+    /** write bitmap lower byte */
+	.wr_bitmap_l = 0x08,
+    /** write bitmap upper byte */
+	.wr_bitmap_u = 0x09,
+    /** write bitmap1 lower byte */
+	.wr_bitmap_1l = 0x0A,
+    /** write bitmapi1 upper byte */
+	.wr_bitmap_1u = 0x0B,
+    /** read port0 length lower byte */
+	.rd_len_p0_l = 0x0C,
+    /** read port0 length upper byte */
+	.rd_len_p0_u = 0x0D,
+    /** card misc configuration register */
+	.card_misc_cfg_reg = 0xCC,
+     /** scratch reg used for reset and check SOC wakeup*/
+	.reset_reg = 0xE8,
+    /** reset value */
+	.reset_val = 1,
+};
+
+/** Register sdio 8997 card structure */
+static const struct _mlan_sdio_card_reg mlan_reg_sd8977_sd8997 = {
+     /** start read port */
+	.start_rd_port = 0,
+    /** start write port */
+	.start_wr_port = 0,
+    /** base register0 */
+	.base_0_reg = 0xf8,
+    /** base register1 */
+	.base_1_reg = 0xf9,
+    /** poll register */
+	.poll_reg = 0x5C,
+    /** host interrupt enable */
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+		CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+     /** host interrupt status*/
+	.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 register0 */
+	.status_reg_0 = 0xe8,
+    /** status register1 */
+	.status_reg_1 = 0xe9,
+     /** sdio interrupt mask */
+	.sdio_int_mask = 0xff,
+     /** data port mask */
+	.data_port_mask = 0xffffffff,
+     /** maximum mp register */
+	.max_mp_regs = 196,
+    /** read bitmap lower byte */
+	.rd_bitmap_l = 0x10,
+    /** read bitmap upper byte */
+	.rd_bitmap_u = 0x11,
+    /** read bitmap1 lower byte */
+	.rd_bitmap_1l = 0x12,
+    /** read bitmap1 upper byte */
+	.rd_bitmap_1u = 0x13,
+    /** write bitmap lower byte */
+	.wr_bitmap_l = 0x14,
+    /** write bitmap upper byte */
+	.wr_bitmap_u = 0x15,
+    /** write bitmap1 lower byte */
+	.wr_bitmap_1l = 0x16,
+    /** write bitmap1 upper byte */
+	.wr_bitmap_1u = 0x17,
+    /** read port0 length lower byte */
+	.rd_len_p0_l = 0x18,
+    /** read port0 length upper byte */
+	.rd_len_p0_u = 0x19,
+    /** card misc configuration register */
+	.card_misc_cfg_reg = 0xd8,
+     /** scratch reg used for reset and check SOC wakeup*/
+	.reset_reg = 0xEE,
+    /** reset value */
+	.reset_val = 0x99,
+};
+
+/** ampdu info for general card */
+static struct _ampdu_info ampdu_info_nov15 = {
+     /** AMPDU station tx window size */
+	.ampdu_sta_txwinsize = MLAN_STA_AMPDU_DEF_TXWINSIZE_NOV15,
+    /** AMPDU uAP tx window size */
+	.ampdu_uap_txwinsize = MLAN_UAP_AMPDU_DEF_TXWINSIZE_NOV15,
+    /** AMPDU uAP rx window size */
+	.ampdu_uap_rxwinsize = MLAN_UAP_AMPDU_DEF_RXWINSIZE_NOV15,
+#ifdef WIFI_DIRECT_SUPPORT
+    /** AMPDU wifi direct txrx window size */
+	.ampdu_wfd_txrxwinsize = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE_NOV15,
+#endif
+};
+
+/** ampdu info for sd8887 and sd8897 */
+static struct _ampdu_info ampdu_info_v15 = {
+     /** AMPDU station tx window size */
+	.ampdu_sta_txwinsize = MLAN_STA_AMPDU_DEF_TXWINSIZE,
+     /** AMPDU uAP tx window size */
+	.ampdu_uap_txwinsize = MLAN_UAP_AMPDU_DEF_TXWINSIZE,
+     /** AMPDU uAP rx window size */
+	.ampdu_uap_rxwinsize = MLAN_UAP_AMPDU_DEF_RXWINSIZE,
+#ifdef WIFI_DIRECT_SUPPORT
+     /** AMPDU wifi direct txrx window size */
+	.ampdu_wfd_txrxwinsize = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE,
+#endif
+};
+
+/** 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)
+
+/** Sdio 8777 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8777 = {
+     /** register */
+	.reg = &mlan_reg_sd87xx,
+    /** maximum ports */
+	.max_ports = 16,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_8,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MFALSE,
+    /** control mask */
+	.has_control_mask = MTRUE,
+     /** io port0 register */
+	.io_port_0_reg = 0x78,
+     /** io port1 register */
+	.io_port_1_reg = 0x79,
+     /** io port2 register */
+	.io_port_2_reg = 0x7A,
+     /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+     /** card_rx_len_reg */
+	.card_rx_len_reg = 0x62,
+     /** card rx unit register */
+	.card_rx_unit_reg = 0x63,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+     /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 0,
+    /** V15 firmware api */
+	.v15_fw_api = 0,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 0,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_nov15,
+};
+
+/** Sdio 8787 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8787 = {
+    /** register */
+	.reg = &mlan_reg_sd87xx,
+    /** maximum ports */
+	.max_ports = 16,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_8,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MFALSE,
+    /** control mask */
+	.has_control_mask = MTRUE,
+     /** io port0 register */
+	.io_port_0_reg = 0x78,
+    /** io port1 register */
+	.io_port_1_reg = 0x79,
+    /** io port2 register */
+	.io_port_2_reg = 0x7A,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+    /** card_rx_len_reg */
+	.card_rx_len_reg = 0x62,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0x63,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 0,
+    /** V15 firmware api */
+	.v15_fw_api = 0,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 0,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_nov15,
+};
+
+/** Sdio 8797 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8797 = {
+     /** register */
+	.reg = &mlan_reg_sd87xx,
+    /** maximum ports */
+	.max_ports = 16,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_8,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MFALSE,
+    /** control mask */
+	.has_control_mask = MTRUE,
+    /** io port0 register */
+	.io_port_0_reg = 0x78,
+    /** io port1 register */
+	.io_port_1_reg = 0x79,
+    /** io port2 register */
+	.io_port_2_reg = 0x7A,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+    /** card_rx_len_reg */
+	.card_rx_len_reg = 0x62,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0x63,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 0,
+    /** V15 firmware api */
+	.v15_fw_api = 0,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 0,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_nov15,
+};
+
+/** Sdio 8887 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8887 = {
+    /** register */
+	.reg = &mlan_reg_sd8887,
+    /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xD9,
+     /** command configuration register0 */
+	.cmd_config_0 = 0xC4,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xC5,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xC0,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xC1,
+    /** io port0 register */
+	.io_port_0_reg = 0xE4,
+    /** io port1 register */
+	.io_port_1_reg = 0xE5,
+    /** io port2 register */
+	.io_port_2_reg = 0xE6,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x04,
+    /** card rx length register */
+	.card_rx_len_reg = 0x92,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0x93,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x08,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x0C,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Sdio 8801 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8801 = {
+     /** register */
+	.reg = &mlan_reg_sd87xx,
+    /** maximum ports */
+	.max_ports = 16,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_8,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MFALSE,
+    /** control mask */
+	.has_control_mask = MTRUE,
+    /** io port0 register */
+	.io_port_0_reg = 0x78,
+    /** io port1 register */
+	.io_port_1_reg = 0x79,
+    /** io port0 register */
+	.io_port_2_reg = 0x7A,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+    /** card rx length register */
+	.card_rx_len_reg = 0x62,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0x63,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 0,
+    /** V15 firmware api */
+	.v15_fw_api = 0,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 0,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_nov15,
+};
+
+/** Sdio 8897 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8897 = {
+     /** register */
+	.reg = &mlan_reg_sd8897,
+     /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xCD,
+    /** command configuration register0 */
+	.cmd_config_0 = 0xB8,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xB9,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xB4,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xB5,
+    /** io port0 register */
+	.io_port_0_reg = 0xD8,
+    /** io port1 register */
+	.io_port_1_reg = 0xD9,
+    /** io port2 register */
+	.io_port_2_reg = 0xDA,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+    /** card rx length register */
+	.card_rx_len_reg = 0xC2,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0xC3,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Sdio 8977 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8977 = {
+     /** register */
+	.reg = &mlan_reg_sd8977_sd8997,
+     /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xD9,
+    /** command configuration register0 */
+	.cmd_config_0 = 0xC4,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xC5,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xC0,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xC1,
+    /** io port0 register */
+	.io_port_0_reg = 0xE4,
+    /** io port1 register */
+	.io_port_1_reg = 0xE5,
+    /** io port2 register */
+	.io_port_2_reg = 0xE6,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x04,
+    /** card rx length register */
+	.card_rx_len_reg = 0xEA,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0xEB,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x08,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x0C,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 1,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Sdio 8997 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8997 = {
+    /** register */
+	.reg = &mlan_reg_sd8977_sd8997,
+    /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xD9,
+    /** command configuration register0 */
+	.cmd_config_0 = 0xC4,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xC5,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xC0,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xC1,
+    /** io port0 register */
+	.io_port_0_reg = 0xE4,
+    /** io port1 register */
+	.io_port_1_reg = 0xE5,
+    /** io port2 register */
+	.io_port_2_reg = 0xE6,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x04,
+    /** card rx length register */
+	.card_rx_len_reg = 0xEA,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0xEB,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x08,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x0C,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 1,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Sdio 8987 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8987 = {
+    /** register */
+	.reg = &mlan_reg_sd8977_sd8997,
+    /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xD9,
+    /** command configuration register0 */
+	.cmd_config_0 = 0xC4,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xC5,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xC0,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xC1,
+    /** io port0 register */
+	.io_port_0_reg = 0xE4,
+    /** io port1 register */
+	.io_port_1_reg = 0xE5,
+    /** io port2 register */
+	.io_port_2_reg = 0xE6,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x04,
+    /** card rx length register */
+	.card_rx_len_reg = 0xEA,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0xEB,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x08,
+    /** host interrupt mask register */
+	.host_int_status_reg = 0x0C,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 1,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Enable host interrupt */
+mlan_status wlan_enable_host_int(pmlan_adapter pmadapter);
+/** Probe and initialization function */
+mlan_status wlan_sdio_probe(pmlan_adapter pmadapter);
+mlan_status wlan_get_sdio_device(pmlan_adapter pmadapter);
+/** multi interface download check */
+mlan_status wlan_check_winner_status(mlan_adapter *pmadapter, t_u32 *val);
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+mlan_status wlan_send_mp_aggr_buf(mlan_adapter *pmadapter);
+#endif
+
+/** Firmware status check */
+mlan_status wlan_check_fw_status(mlan_adapter *pmadapter, t_u32 pollnum);
+/** Read interrupt status */
+mlan_status wlan_interrupt(pmlan_adapter pmadapter);
+/** Process Interrupt Status */
+mlan_status wlan_process_int_status(mlan_adapter *pmadapter);
+/** 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(IN pmlan_private priv);
+mlan_status wlan_cmd_sdio_gpio_int(pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *cmd,
+				   IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_reset_fw(pmlan_adapter pmadapter);
+#endif /* _MLAN_SDIO_H */
diff --git a/wlan_sd8897/mlan/mlan_shim.c b/wlan_sd8897/mlan/mlan_shim.c
new file mode 100644
index 0000000..df285c7
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_shim.c
@@ -0,0 +1,1438 @@
+/** @file mlan_shim.c
+ *
+ *  @brief This file contains APIs to MOAL module.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+#include "mlan_11h.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+#ifdef STA_SUPPORT
+mlan_operations mlan_sta_ops = {
+	/* init cmd handler */
+	wlan_ops_sta_init_cmd,
+	/* ioctl handler */
+	wlan_ops_sta_ioctl,
+	/* cmd handler */
+	wlan_ops_sta_prepare_cmd,
+	/* cmdresp handler */
+	wlan_ops_sta_process_cmdresp,
+	/* rx handler */
+	wlan_ops_sta_process_rx_packet,
+	/* Event handler */
+	wlan_ops_sta_process_event,
+	/* txpd handler */
+	wlan_ops_sta_process_txpd,
+	/* BSS role: STA */
+	MLAN_BSS_ROLE_STA,
+};
+#endif
+#ifdef UAP_SUPPORT
+mlan_operations mlan_uap_ops = {
+	/* init cmd handler */
+	wlan_ops_uap_init_cmd,
+	/* ioctl handler */
+	wlan_ops_uap_ioctl,
+	/* cmd handler */
+	wlan_ops_uap_prepare_cmd,
+	/* cmdresp handler */
+	wlan_ops_uap_process_cmdresp,
+	/* rx handler */
+	wlan_ops_uap_process_rx_packet,
+	/* Event handler */
+	wlan_ops_uap_process_event,
+	/* txpd handler */
+	wlan_ops_uap_process_txpd,
+	/* BSS role: uAP */
+	MLAN_BSS_ROLE_UAP,
+};
+#endif
+
+/** mlan function table */
+mlan_operations *mlan_ops[] = {
+#ifdef STA_SUPPORT
+	&mlan_sta_ops,
+#endif
+#ifdef UAP_SUPPORT
+	&mlan_uap_ops,
+#endif
+	MNULL,
+};
+
+/** Global moal_assert callback */
+t_void (*assert_callback) (IN t_void *pmoal_handle, IN 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) (IN t_void *pmoal_handle,
+			  IN t_u32 level, IN char *pformat, IN ...
+	) = MNULL;
+
+/** Global moal_get_system_time callback */
+mlan_status (*get_sys_time_callback) (IN t_void *pmoal_handle,
+				      OUT t_u32 *psec,
+				      OUT t_u32 *pusec) = MNULL;
+
+/** Global driver debug mit masks */
+t_u32 mlan_drvdbg = DEFAULT_DEBUG_MASK;
+#endif
+
+/********************************************************
+			Local Functions
+*******************************************************/
+/**
+ *  @brief This function process pending ioctl
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ */
+void
+wlan_process_pending_ioctl(mlan_adapter *pmadapter)
+{
+	pmlan_ioctl_req pioctl_buf;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	mlan_ds_bss *bss = MNULL;
+#endif
+#ifdef STA_SUPPORT
+	mlan_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\n");
+				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 (
+ *   IN pmlan_device     pmdevice,
+ *   OUT 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(IN pmlan_device pmdevice, OUT 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_memset);
+	MASSERT(pmdevice->callbacks.moal_memmove);
+
+	if (!pmdevice->callbacks.moal_malloc ||
+	    !pmdevice->callbacks.moal_memset ||
+	    !pmdevice->callbacks.moal_memmove) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Allocate memory for adapter structure */
+	if (pmdevice->callbacks.moal_vmalloc && pmdevice->callbacks.moal_vfree)
+		ret = pmdevice->callbacks.moal_vmalloc(pmdevice->pmoal_handle,
+						       sizeof(mlan_adapter),
+						       (t_u8 **)&pmadapter);
+	else
+		ret = pmdevice->callbacks.moal_malloc(pmdevice->pmoal_handle,
+						      sizeof(mlan_adapter),
+						      MLAN_MEM_DEF,
+						      (t_u8 **)&pmadapter);
+	if ((ret != MLAN_STATUS_SUCCESS) || !pmadapter) {
+		ret = MLAN_STATUS_FAILURE;
+		goto exit_register;
+	}
+
+	pmdevice->callbacks.moal_memset(pmdevice->pmoal_handle, pmadapter,
+					0, sizeof(mlan_adapter));
+
+	pcb = &pmadapter->callbacks;
+
+	/* Save callback functions */
+	pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
+					 &pmdevice->callbacks,
+					 sizeof(mlan_callbacks));
+
+	/* Assertion for all callback functions */
+	MASSERT(pcb->moal_get_hw_spec_complete);
+	MASSERT(pcb->moal_init_fw_complete);
+	MASSERT(pcb->moal_shutdown_fw_complete);
+	MASSERT(pcb->moal_send_packet_complete);
+	MASSERT(pcb->moal_recv_packet);
+	MASSERT(pcb->moal_recv_event);
+	MASSERT(pcb->moal_ioctl_complete);
+
+	MASSERT(pcb->moal_write_reg);
+	MASSERT(pcb->moal_read_reg);
+	MASSERT(pcb->moal_alloc_mlan_buffer);
+	MASSERT(pcb->moal_free_mlan_buffer);
+	MASSERT(pcb->moal_write_data_sync);
+	MASSERT(pcb->moal_read_data_sync);
+	MASSERT(pcb->moal_mfree);
+	MASSERT(pcb->moal_memcpy);
+	MASSERT(pcb->moal_memcmp);
+	MASSERT(pcb->moal_get_system_time);
+	MASSERT(pcb->moal_init_timer);
+	MASSERT(pcb->moal_free_timer);
+	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);
+	/* Save pmoal_handle */
+	pmadapter->pmoal_handle = pmdevice->pmoal_handle;
+
+	pmadapter->feature_control = pmdevice->feature_control;
+
+	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;
+	pmadapter->card_type = pmdevice->card_type;
+
+	ret = wlan_get_sdio_device(pmadapter);
+	if (MLAN_STATUS_SUCCESS != ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	/* card specific probing has been deferred until now .. */
+	ret = wlan_sdio_probe(pmadapter);
+	if (MLAN_STATUS_SUCCESS != ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+#ifdef DEBUG_LEVEL1
+	mlan_drvdbg = pmdevice->drvdbg;
+#endif
+
+#ifdef MFG_CMD_SUPPORT
+	pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	pmadapter->max_segs = pmdevice->max_segs;
+	pmadapter->max_seg_size = pmdevice->max_seg_size;
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
+#endif
+	pmadapter->init_para.auto_ds = pmdevice->auto_ds;
+	pmadapter->init_para.ps_mode = pmdevice->ps_mode;
+	if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
+	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
+	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_12K ||
+	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
+		pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;
+#ifdef STA_SUPPORT
+	pmadapter->init_para.cfg_11d = pmdevice->cfg_11d;
+#else
+	pmadapter->init_para.cfg_11d = 0;
+#endif
+	if (IS_DFS_SUPPORT(pmadapter->feature_control))
+		pmadapter->init_para.dfs_master_radar_det_en =
+			DFS_MASTER_RADAR_DETECT_EN;
+	pmadapter->init_para.dfs_slave_radar_det_en = DFS_SLAVE_RADAR_DETECT_EN;
+	if (IS_SD8777(pmadapter->card_type) || IS_SD8787(pmadapter->card_type))
+		pmadapter->init_para.fw_crc_check = pmdevice->fw_crc_check;
+	pmadapter->init_para.dev_cap_mask = pmdevice->dev_cap_mask;
+	pmadapter->init_para.indrstcfg = pmdevice->indrstcfg;
+	pmadapter->rx_work_flag = pmdevice->rx_work;
+
+	pmadapter->fixed_beacon_buffer = pmdevice->fixed_beacon_buffer;
+
+	pmadapter->multiple_dtim = pmdevice->multi_dtim;
+	pmadapter->inact_tmo = pmdevice->inact_tmo;
+	pmadapter->init_para.drcs_chantime_mode = pmdevice->drcs_chantime_mode;
+	pmadapter->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->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(pmadapter, &pmadapter->priv[0]->ops, mlan_ops[j],
+			       sizeof(mlan_operations));
+		}
+	}
+    /** back up bss_attr table */
+	memcpy(pmadapter, pmadapter->bss_attr, pmdevice->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 timers */
+	wlan_free_timer(pmadapter);
+	/* Free adapter structure */
+	wlan_free_adapter(pmadapter);
+	/* Free lock variables */
+	wlan_free_lock_list(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
+				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
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+
+exit_register:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function unregisters MOAL from MLAN module.
+ *
+ *  @param pmlan_adapter   A pointer to a mlan_device structure
+ *                         allocated in MOAL
+ *
+ *  @return                MLAN_STATUS_SUCCESS
+ *                             The deregistration succeeded.
+ */
+mlan_status
+mlan_unregister(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_callbacks pcb;
+	t_s32 i = 0;
+
+	MASSERT(pmlan_adapter);
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+	/* Free adapter structure */
+	wlan_free_adapter(pmadapter);
+
+	/* Free timers */
+	wlan_free_timer(pmadapter);
+
+	/* Free lock variables */
+	wlan_free_lock_list(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
+				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
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads the firmware
+ *
+ *  @param pmlan_adapter   A pointer to a t_void pointer to store
+ *                         mlan_adapter structure pointer
+ *  @param pmfw            A pointer to firmware image
+ *
+ *  @return                MLAN_STATUS_SUCCESS
+ *                             The firmware download succeeded.
+ *                         MLAN_STATUS_FAILURE
+ *                             The firmware download failed.
+ */
+mlan_status
+mlan_dnld_fw(IN t_void *pmlan_adapter, IN pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	t_u32 poll_num = 1;
+	t_u32 winner = 0;
+
+	ENTER();
+	MASSERT(pmlan_adapter);
+
+/*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_check_fw_status(pmadapter, poll_num);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		if (pmfw->fw_reload && pmadapter->psdio_device->fw_reload) {
+			ret = wlan_reset_fw(pmadapter);
+			if (ret == MLAN_STATUS_FAILURE) {
+				PRINTM(MERROR, "FW reset failure!");
+				LEAVE();
+				return ret;
+			}
+		} else {
+			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_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;
+	}
+
+	if (pmfw) {
+		/* Download helper/firmware */
+		ret = wlan_dnld_fw(pmadapter, pmfw);
+		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_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_host_int(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function pass init param to MLAN
+ *
+ *  @param pmlan_adapter  A pointer to a t_void pointer to store
+ *                        mlan_adapter structure pointer
+ *  @param pparam         A pointer to mlan_init_param structure
+ *
+ *  @return               MLAN_STATUS_SUCCESS
+ *
+ */
+mlan_status
+mlan_set_init_param(IN t_void *pmlan_adapter, IN pmlan_init_param pparam)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+	ENTER();
+	MASSERT(pmlan_adapter);
+
+    /** Save DPD data in MLAN */
+	if ((pparam->pdpd_data_buf) && (pparam->dpd_data_len > 0)) {
+		pmadapter->pdpd_data = pparam->pdpd_data_buf;
+		pmadapter->dpd_data_len = pparam->dpd_data_len;
+	}
+	if (pparam->ptxpwr_data_buf && (pparam->txpwr_data_len > 0)) {
+		pmadapter->ptxpwr_data = pparam->ptxpwr_data_buf;
+		pmadapter->txpwr_data_len = pparam->txpwr_data_len;
+	}
+    /** Save cal data in MLAN */
+	if ((pparam->pcal_data_buf) && (pparam->cal_data_len > 0)) {
+		pmadapter->pcal_data = pparam->pcal_data_buf;
+		pmadapter->cal_data_len = pparam->cal_data_len;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes the firmware
+ *
+ *  @param pmlan_adapter   A pointer to a t_void pointer to store
+ *                         mlan_adapter structure pointer
+ *
+ *  @return                MLAN_STATUS_SUCCESS
+ *                             The firmware initialization succeeded.
+ *                         MLAN_STATUS_PENDING
+ *                             The firmware initialization is pending.
+ *                         MLAN_STATUS_FAILURE
+ *                             The firmware initialization failed.
+ */
+mlan_status
+mlan_init_fw(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+	ENTER();
+	MASSERT(pmlan_adapter);
+
+	pmadapter->hw_status = WlanHardwareStatusGetHwSpec;
+
+	/* Initialize firmware, may return PENDING */
+	ret = wlan_init_fw(pmadapter);
+	PRINTM(MINFO, "wlan_init_fw returned ret=0x%x\n", ret);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Shutdown firmware
+ *
+ *  @param pmlan_adapter    A pointer to mlan_adapter structure
+ *
+ *  @return     MLAN_STATUS_SUCCESS
+ *                              The firmware shutdown call succeeded.
+ *              MLAN_STATUS_PENDING
+ *                              The firmware shutdown call is pending.
+ *              MLAN_STATUS_FAILURE
+ *                              The firmware shutdown call failed.
+ */
+mlan_status
+mlan_shutdown_fw(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_PENDING;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_buffer pmbuf;
+	pmlan_ioctl_req pioctl_buf;
+	pmlan_callbacks pcb;
+	t_s32 i = 0;
+
+	ENTER();
+
+	MASSERT(pmlan_adapter);
+	/* MLAN already shutdown */
+	if (pmadapter->hw_status == WlanHardwareStatusNotReady) {
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	pmadapter->hw_status = WlanHardwareStatusClosing;
+	/* Wait for mlan_process to complete */
+	if (pmadapter->mlan_processing) {
+		PRINTM(MWARN, "MLAN main processing is still running\n");
+		LEAVE();
+		return ret;
+	}
+
+	/* Shut down MLAN */
+	PRINTM(MINFO, "Shutdown MLAN...\n");
+
+	/* Cancel all pending commands and complete ioctls */
+	wlan_cancel_all_pending_cmd(pmadapter);
+
+	/* 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))) {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+	pmadapter->rx_pkts_queued = 0;
+
+	/* Notify completion */
+	ret = wlan_shutdown_fw_complete(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief queue main work
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return			N/A
+ */
+static t_void
+mlan_queue_main_work(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmain_proc_lock);
+
+	/* Check if already processing */
+	if (pmadapter->mlan_processing) {
+		pmadapter->more_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+	} else {
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+		wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+				MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief queue rx_work
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return			N/A
+ */
+static t_void
+mlan_queue_rx_work(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+
+	/* Check if already processing */
+	if (pmadapter->mlan_rx_processing) {
+		pmadapter->more_rx_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+	} else {
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+		wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+				MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief block main process
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param block            MTRUE/MFALSE
+ *
+ *  @return			N/A
+ */
+void
+mlan_block_main_process(mlan_adapter *pmadapter, t_u8 block)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmain_proc_lock);
+	if (!block) {
+		pmadapter->main_lock_flag = MFALSE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+	} else {
+		pmadapter->main_lock_flag = MTRUE;
+		if (pmadapter->mlan_processing) {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->pmain_proc_lock);
+			PRINTM(MEVENT, "wlan: wait main work done...\n");
+			wlan_recv_event(wlan_get_priv
+					(pmadapter, MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK,
+					MNULL);
+		} else {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->pmain_proc_lock);
+		}
+	}
+}
+
+/**
+ *  @brief block rx process
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param block            MTRUE/MFALSE;
+ *
+ *  @return			N/A
+ */
+void
+mlan_block_rx_process(mlan_adapter *pmadapter, t_u8 block)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+	if (!block) {
+		pmadapter->rx_lock_flag = MFALSE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+	} else {
+		pmadapter->rx_lock_flag = MTRUE;
+		if (pmadapter->mlan_rx_processing) {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->prx_proc_lock);
+			PRINTM(MEVENT, "wlan: wait rx work done...\n");
+			wlan_recv_event(wlan_get_priv
+					(pmadapter, MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
+		} else {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->prx_proc_lock);
+		}
+	}
+}
+
+/**
+ *  @brief The receive process
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param rx_pkts		    A pointer to save receive pkts number
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_callbacks pcb;
+	pmlan_buffer pmbuf;
+	t_u8 limit = 0;
+	t_u8 rx_num = 0;
+
+	ENTER();
+
+	MASSERT(pmlan_adapter);
+	pcb = &pmadapter->callbacks;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+	if (pmadapter->mlan_rx_processing || pmadapter->rx_lock_flag) {
+		pmadapter->more_rx_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+		goto exit_rx_proc;
+	} else {
+		pmadapter->mlan_rx_processing = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+	}
+	if (rx_pkts)
+		limit = *rx_pkts;
+
+rx_process_start:
+	/* Check for Rx data */
+	while (MTRUE) {
+		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);
+		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);
+		}
+		wlan_handle_rx_packet(pmadapter, pmbuf);
+		if (limit && rx_num >= limit)
+			break;
+	}
+	if (rx_pkts)
+		*rx_pkts = rx_num;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+	if (pmadapter->more_rx_task_flag) {
+		pmadapter->more_rx_task_flag = MFALSE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+		goto rx_process_start;
+	}
+	pmadapter->mlan_rx_processing = MFALSE;
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+			      pmadapter->prx_proc_lock);
+exit_rx_proc:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief The main process
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+mlan_main_process(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	MASSERT(pmlan_adapter);
+
+	pcb = &pmadapter->callbacks;
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmain_proc_lock);
+
+	/* Check if already processing */
+	if (pmadapter->mlan_processing || pmadapter->main_lock_flag) {
+		pmadapter->more_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+		goto exit_main_proc;
+	} else {
+		pmadapter->mlan_processing = MTRUE;
+		pmadapter->main_process_cnt++;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+	}
+process_start:
+	do {
+		/* Is MLAN shutting down or not ready? */
+		if ((pmadapter->hw_status == WlanHardwareStatusClosing) ||
+		    (pmadapter->hw_status == WlanHardwareStatusNotReady))
+			break;
+		if (pmadapter->pending_ioctl) {
+			wlan_process_pending_ioctl(pmadapter);
+			pmadapter->pending_ioctl = MFALSE;
+		}
+		if (pmadapter->rx_pkts_queued > HIGH_RX_PENDING) {
+			PRINTM(MEVENT, "Pause\n");
+			pmadapter->delay_task_flag = MTRUE;
+			mlan_queue_rx_work(pmadapter);
+			break;
+		}
+		/* Handle pending SDIO interrupts if any */
+		if (pmadapter->sdio_ireg) {
+			if (pmadapter->hs_activated == MTRUE)
+				wlan_process_hs_config(pmadapter);
+			wlan_process_int_status(pmadapter);
+			if (pmadapter->data_received && pmadapter->rx_work_flag)
+				mlan_queue_rx_work(pmadapter);
+		}
+
+		/* 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)
+		    )) {
+			wlan_pm_wakeup_card(pmadapter);
+			pmadapter->pm_wakeup_fw_try = MTRUE;
+			continue;
+		}
+		if (IS_CARD_RX_RCVD(pmadapter)) {
+			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;
+		} 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)
+					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)
+				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;
+		}
+
+		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 pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param pmbuf		A pointer to mlan_buffer structure
+ *
+ *  @return			MLAN_STATUS_PENDING
+ */
+mlan_status
+mlan_send_packet(IN t_void *pmlan_adapter, IN pmlan_buffer pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_PENDING;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	mlan_private *pmpriv;
+	t_u16 eth_type = 0;
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	tdlsStatus_e tdls_status;
+
+	ENTER();
+	MASSERT(pmlan_adapter &&pmbuf);
+
+	if (!pmlan_adapter ||!pmbuf) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	MASSERT(pmbuf->bss_index < pmadapter->priv_num);
+	pmbuf->flags |= MLAN_BUF_FLAG_MOAL_TX_BUF;
+	pmpriv = pmadapter->priv[pmbuf->bss_index];
+
+	eth_type =
+		mlan_ntohs(*(t_u16 *)&pmbuf->
+			   pbuf[pmbuf->data_offset +
+				MLAN_ETHER_PKT_TYPE_OFFSET]);
+	if (((pmadapter->priv[pmbuf->bss_index]->port_ctrl_mode == MTRUE) &&
+	     ((eth_type == MLAN_ETHER_PKT_TYPE_EAPOL)
+	      || (eth_type == MLAN_ETHER_PKT_TYPE_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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+			       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;
+		}
+		PRINTM(MINFO, "mlan_send_pkt(): enq(bybass_txq)\n");
+		wlan_add_buf_bypass_txqueue(pmadapter, pmbuf);
+	} 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(IN t_void *adapter, IN 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);
+		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;
+}
+
+/**
+ *  @brief Packet receive completion callback handler
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param pmbuf		A pointer to mlan_buffer structure
+ *  @param status		Callback status
+ *
+ *  @return			MLAN_STATUS_SUCCESS
+ */
+mlan_status
+mlan_recv_packet_complete(IN t_void *pmlan_adapter,
+			  IN pmlan_buffer pmbuf, IN mlan_status status)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+	ENTER();
+	wlan_recv_packet_complete(pmadapter, pmbuf, status);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief select wmm queue
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param bss_num		BSS number
+ *  @param tid			TID
+ *
+ *  @return			wmm queue priority (0 - 3)
+ */
+t_u8
+mlan_select_wmm_queue(IN t_void *pmlan_adapter, IN t_u8 bss_num, IN t_u8 tid)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_private pmpriv = pmadapter->priv[bss_num];
+	t_u8 ret;
+	ENTER();
+	ret = wlan_wmm_select_queue(pmpriv, tid);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets interrupt status.
+ *
+ */
+/**
+ *  @param adapter  A pointer to mlan_adapter structure
+ *  @return         N/A
+ */
+mlan_status
+mlan_interrupt(IN t_void *adapter)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+	mlan_status ret;
+
+	ENTER();
+	ret = wlan_interrupt(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function wakeup firmware.
+ *
+ *  @param adapter  A pointer to mlan_adapter structure
+ *  @return         N/A
+ */
+t_void
+mlan_pm_wakeup_card(IN t_void *adapter)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+	ENTER();
+	wlan_pm_wakeup_card(pmadapter);
+	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(IN 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;
+}
diff --git a/wlan_sd8897/mlan/mlan_sta_cmd.c b/wlan_sd8897/mlan/mlan_sta_cmd.c
new file mode 100644
index 0000000..3d04f08
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_sta_cmd.c
@@ -0,0 +1,3057 @@
+/** @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 (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+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_11h.h"
+#include "mlan_sdio.h"
+#include "mlan_meas.h"
+
+/********************************************************
+			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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *pcmd, IN 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_ext
+ *
+ *  @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
+ */
+static mlan_status
+wlan_cmd_802_11_rssi_info_ext(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *pcmd,
+			      IN t_u16 cmd_action, IN 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 +
+			sizeof(HostCmd_DS_802_11_RSSI_INFO_EXT);
+		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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action,
+			 IN t_u32 cmd_oid, IN 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(pmpriv->adapter, psnmp_mib->value, &ul_temp,
+			       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(IN pmlan_private pmpriv, IN 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 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd,
+			    IN t_u16 cmd_action, IN 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(IN 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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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;
+
+	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(pmpriv->adapter,
+		       ((t_u8 *)phs_cfg) + sizeof(HostCmd_DS_802_11_HS_CFG_ENH),
+		       pmadapter->arp_filter, 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(pmadapter, (t_u8 *)mgmt_filter_tlv->filter,
+			       (t_u8 *)mgmt_filter,
+			       i * sizeof(mgmt_frame_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);
+		}
+		cmd->size = wlan_cpu_to_le16(cmd->size);
+		PRINTM(MCMND,
+		       "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x holdoff=%d wake_interval=%d inactivity_timeout=%d\n",
+		       phs_cfg->params.hs_config.conditions,
+		       phs_cfg->params.hs_config.gpio,
+		       phs_cfg->params.hs_config.gap,
+		       pmadapter->min_wake_holdoff, pmadapter->hs_wake_interval,
+		       pmadapter->hs_inactivity_timeout);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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
+ */
+static mlan_status
+wlan_cmd_802_11_mac_address(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, cmd->params.mac_addr.mac_addr,
+		       pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
+		/* HEXDUMP("SET_CMD: MAC ADDRESS-", priv->CurrentAddr, 6); */
+	}
+	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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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(pmpriv->adapter, pmc_addr->mac_list, pmcast_list->mac_list,
+	       pmcast_list->num_multicast_addr * MLAN_MAC_ADDR_LENGTH);
+
+	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(IN pmlan_private pmpriv,
+			       IN t_u16 cmd_no,
+			       IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, pdeauth, (t_u8 *)pdata_buf, 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(IN pmlan_private pmpriv, IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action,
+			     IN t_u32 cmd_oid, IN 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		       pkey->mac_addr, 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		       pkey->mac_addr, 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+	       pkey->mac_addr, 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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wep.key,
+		       pkey->key_material, pkey->key_len);
+		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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.pn,
+		       pkey->pn, PN_SIZE);
+		pkey_material->key_param_set.key_params.wapi.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.key,
+		       pkey->key_material, pkey->key_len);
+		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_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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.aes.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.aes.key,
+		       pkey->key_material, pkey->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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.cmac_aes.
+			       ipn, pkey->pn, SEQ_MAX_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+		pkey_material->key_param_set.key_params.cmac_aes.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.cmac_aes.key,
+		       pkey->key_material, pkey->key_len);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set CMAC AES Key\n");
+		goto done;
+	}
+	if (pkey->key_len == WPA_TKIP_KEY_LEN) {
+		if (pkey->
+		    key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.tkip.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.tkip.key,
+		       pkey->key_material, pkey->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 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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *cmd,
+		   IN t_u16 cmd_action, IN 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(pmpriv->adapter, eapol_pkt->tlv_eapol.pkt_buf,
+	       pmbuf->pbuf + pmbuf->data_offset, 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
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_802_11_supplicant_profile(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *cmd,
+				   IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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)
+		    || (pmpriv->adapter->adhoc_start_band & BAND_AN)
+			)
+			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(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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);
+
+	if (pmgmt_ie_list->ds_mgmt_ie.ie_data_list && cust_ie->ie_data_list) {
+		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(pmpriv->adapter,
+			       pmgmt_ie_list->ds_mgmt_ie.ie_data_list,
+			       cust_ie->ie_data_list, cust_ie->len);
+	}
+
+	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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN 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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_setup, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       (t_u8 *)&tdls_all_cfg->u.tdls_set.cap_info,
+		       sizeof(t_u16));
+		memcpy(pmpriv->adapter,
+		       (t_u8 *)ptdls_config_data->tdls_info.tdls_data +
+		       sizeof(t_u16), &tdls_all_cfg->u.tdls_set.tlv_buffer,
+		       travel_len);
+		travel_len += sizeof(t_u16);
+		break;
+	case WLAN_TDLS_DISCOVERY_REQ:
+		travel_len = MLAN_MAC_ADDR_LENGTH;
+		memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       tdls_all_cfg->u.tdls_discovery.peer_mac_addr,
+		       travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_setup, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_tear_down, travel_len);
+		break;
+	case WLAN_TDLS_STOP_CHAN_SWITCH:
+		travel_len = MLAN_MAC_ADDR_LENGTH;
+		memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
+		       travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_chan_switch, travel_len);
+		break;
+	case WLAN_TDLS_CS_PARAMS:
+		travel_len = sizeof(tdls_all_cfg->u.tdls_cs_params);
+		memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_cs_params, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_disable_cs, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_power_mode, travel_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(pmpriv->adapter,
+			       ptdls_config_data->tdls_info.tdls_data,
+			       tdls_all_cfg->u.tdls_link_status_req.
+			       peer_mac_addr, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_debug_data, travel_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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *cmd,
+		   IN t_u16 cmd_action, IN 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(pmpriv->adapter, ptdls_oper->peer_mac, tdls_oper->peer_mac,
+	       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(pmpriv->adapter,
+			       pos + travel_len + sizeof(MrvlIEtypesHeader_t),
+			       sta_ptr->support_rate, Rate_tlv->header.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(pmpriv->adapter, &ExCap->ext_cap,
+				       &sta_ptr->ExtCap.ext_cap,
+				       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(pmpriv->adapter, Rsn_ie->rsn_ie,
+				       sta_ptr->rsn_ie.data,
+				       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(pmpriv->adapter, &LinkID->bssid,
+				       &sta_ptr->link_ie.bssid,
+				       sta_ptr->link_ie.len);
+				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(pmpriv->adapter, &HTcap_tlv->ht_cap,
+				       &sta_ptr->HTcap.ht_cap,
+				       sta_ptr->HTcap.ieee_hdr.len);
+				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(pmpriv->adapter, &HTInfo_tlv->ht_info,
+				       &sta_ptr->HTInfo.ht_info,
+				       sta_ptr->HTInfo.ieee_hdr.len);
+				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(pmpriv->adapter, &BSSCo->bss_co_2040,
+				       &sta_ptr->BSSCO_20_40.bss_co_2040,
+				       sta_ptr->BSSCO_20_40.ieee_hdr.len);
+				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(pmpriv->adapter,
+					       &VHTcap_tlv->vht_cap,
+					       &sta_ptr->vht_cap.vht_cap,
+					       sta_ptr->vht_cap.ieee_hdr.len);
+					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);
+					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(pmpriv->adapter,
+				       &VHTOper_tlv->chan_width,
+				       &sta_ptr->vht_oprat.chan_width,
+				       sta_ptr->vht_oprat.ieee_hdr.len);
+				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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_otp_user_data *user_data =
+		(mlan_ds_misc_otp_user_data *)pdata_buf;
+	HostCmd_DS_OTP_USER_DATA *cmd_user_data =
+		(HostCmd_DS_OTP_USER_DATA *)&cmd->params.otp_user_data;
+	t_u16 cmd_size = 0;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_OTP_READ_USER_DATA);
+	cmd_size = sizeof(HostCmd_DS_OTP_USER_DATA) + S_DS_GEN - 1;
+
+	cmd_user_data->action = wlan_cpu_to_le16(cmd_action);
+	cmd_user_data->reserved = 0;
+	cmd_user_data->user_data_length =
+		wlan_cpu_to_le16(user_data->user_data_length);
+	cmd_size += user_data->user_data_length;
+	cmd->size = wlan_cpu_to_le16(cmd_size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares 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(IN HostCmd_DS_COMMAND *cmd,
+			    IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	pmlan_ds_inactivity_to inac_to;
+	HostCmd_DS_INACTIVITY_TIMEOUT_EXT *cmd_inac_to =
+		&cmd->params.inactivity_to;
+
+	ENTER();
+
+	inac_to = (mlan_ds_inactivity_to *)pdata_buf;
+
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_INACTIVITY_TIMEOUT_EXT) +
+				 S_DS_GEN);
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+	cmd_inac_to->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cmd_inac_to->timeout_unit =
+			wlan_cpu_to_le16((t_u16)inac_to->timeout_unit);
+		cmd_inac_to->unicast_timeout =
+			wlan_cpu_to_le16((t_u16)inac_to->unicast_timeout);
+		cmd_inac_to->mcast_timeout =
+			wlan_cpu_to_le16((t_u16)inac_to->mcast_timeout);
+		cmd_inac_to->ps_entry_timeout =
+			wlan_cpu_to_le16((t_u16)inac_to->ps_entry_timeout);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares network monitor command
+ *
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_net_monitor(IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_net_monitor *net_mon;
+	HostCmd_DS_802_11_NET_MONITOR *cmd_net_mon = &cmd->params.net_mon;
+	ChanBandParamSet_t *pchan_band = MNULL;
+	t_u8 sec_chan_offset = 0;
+	t_u32 bw_offset = 0;
+
+	ENTER();
+
+	net_mon = (mlan_ds_misc_net_monitor *)pdata_buf;
+
+	cmd->size = wlan_cpu_to_le16(S_DS_GEN +
+				     sizeof(HostCmd_DS_802_11_NET_MONITOR));
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+	cmd_net_mon->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cmd_net_mon->enable_net_mon =
+			wlan_cpu_to_le16((t_u16)net_mon->enable_net_mon);
+		if (net_mon->enable_net_mon)
+			cmd_net_mon->filter_flag =
+				wlan_cpu_to_le16((t_u16)net_mon->filter_flag);
+		/* fill the TLV only if channel is specified */
+		if (net_mon->enable_net_mon && net_mon->channel) {
+			pchan_band =
+				&cmd_net_mon->monitor_chan.chan_band_param[0];
+			cmd_net_mon->monitor_chan.header.type =
+				wlan_cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
+			cmd_net_mon->monitor_chan.header.len =
+				wlan_cpu_to_le16(sizeof(ChanBandParamSet_t));
+			pchan_band->chan_number = (t_u8)net_mon->channel;
+			pchan_band->bandcfg.chanBand =
+				wlan_band_to_radio_type((t_u8)net_mon->band);
+
+			if (net_mon->band & BAND_GN
+			    || net_mon->band & BAND_AN
+			    || net_mon->band & BAND_GAC
+			    || net_mon->band & BAND_AAC) {
+				bw_offset = net_mon->chan_bandwidth;
+				if (bw_offset == CHANNEL_BW_40MHZ_ABOVE) {
+					pchan_band->bandcfg.chan2Offset =
+						SEC_CHAN_ABOVE;
+					pchan_band->bandcfg.chanWidth =
+						CHAN_BW_40MHZ;
+				} else if (bw_offset == CHANNEL_BW_40MHZ_BELOW) {
+					pchan_band->bandcfg.chan2Offset =
+						SEC_CHAN_BELOW;
+					pchan_band->bandcfg.chanWidth =
+						CHAN_BW_40MHZ;
+				} else if (bw_offset == CHANNEL_BW_80MHZ) {
+					sec_chan_offset =
+						wlan_get_second_channel_offset
+						(net_mon->channel);
+					if (sec_chan_offset == SEC_CHAN_ABOVE)
+						pchan_band->bandcfg.
+							chan2Offset =
+							SEC_CHAN_ABOVE;
+					else if (sec_chan_offset ==
+						 SEC_CHAN_BELOW)
+						pchan_band->bandcfg.
+							chan2Offset =
+							SEC_CHAN_BELOW;
+					pchan_band->bandcfg.chanWidth =
+						CHAN_BW_80MHZ;
+				}
+			}
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares Low Power Mode
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_low_pwr_mode(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd, IN 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 command of coalesce_config.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_coalesce_config(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	HostCmd_DS_COALESCE_CONFIG *coalesce_config =
+		&cmd->params.coalesce_config;
+	mlan_ds_coalesce_cfg *cfg = (mlan_ds_coalesce_cfg *) pdata_buf;
+	t_u16 cnt, idx, length;
+	struct coalesce_filt_field_param *param;
+	struct coalesce_receive_filt_rule *rule;
+	ENTER();
+
+	cmd->size = sizeof(HostCmd_DS_COALESCE_CONFIG) + S_DS_GEN;
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_COALESCE_CFG);
+	coalesce_config->action = wlan_cpu_to_le16(cmd_action);
+	coalesce_config->num_of_rules = wlan_cpu_to_le16(cfg->num_of_rules);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		rule = coalesce_config->rule;
+		for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
+			rule->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_COALESCE_RULE);
+			rule->max_coalescing_delay =
+				wlan_cpu_to_le16(cfg->rule[cnt].
+						 max_coalescing_delay);
+			rule->pkt_type = cfg->rule[cnt].pkt_type;
+			rule->num_of_fields = cfg->rule[cnt].num_of_fields;
+
+			length = 0;
+
+			param = rule->params;
+			for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) {
+				param->operation =
+					cfg->rule[cnt].params[idx].operation;
+				param->operand_len =
+					cfg->rule[cnt].params[idx].operand_len;
+				param->offset =
+					wlan_cpu_to_le16(cfg->rule[cnt].
+							 params[idx].offset);
+				memcpy(pmpriv->adapter,
+				       param->operand_byte_stream,
+				       cfg->rule[cnt].params[idx].
+				       operand_byte_stream, param->operand_len);
+
+				length +=
+					sizeof(struct
+					       coalesce_filt_field_param);
+
+				param++;
+			}
+
+			/* Total rule length is sizeof max_coalescing_delay(t_u16),
+			 * num_of_fields(t_u8), pkt_type(t_u8) and total length of the all
+			 * params
+			 */
+			rule->header.len =
+				wlan_cpu_to_le16(length + sizeof(t_u16) +
+						 sizeof(t_u8) + sizeof(t_u8));
+
+			/* Add the rule length to the command size */
+			cmd->size +=
+				wlan_le16_to_cpu(rule->header.len) +
+				sizeof(MrvlIEtypesHeader_t);
+
+			rule = (void *)((t_u8 *)rule->params + length);
+		}
+
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function prepares command for sensor temperature.
+ *
+ *  @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_get_sensor_temp(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd, IN 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 sends get sta band channel command to firmware.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action  Command action
+ *  @param pioctl_buf  A pointer to mlan_ioctl_req structure
+ *  @param pdata_buf   A pointer to information buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_sta_config(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action,
+		    IN mlan_ioctl_req *pioctl_buf, IN 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 check if the command is supported by firmware
+ *
+ *  @param priv       A pointer to mlan_private structure
+ *  @param cmd_no       Command number
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_is_cmd_allowed(mlan_private *priv, IN t_u16 cmd_no)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	if (priv->adapter->psdio_device->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 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             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_config_dyn_bw(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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 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(IN t_void *priv,
+			 IN t_u16 cmd_no,
+			 IN t_u16 cmd_action,
+			 IN t_u32 cmd_oid,
+			 IN t_void *pioctl_buf,
+			 IN t_void *pdata_buf, IN 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;
+	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);
+		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_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_FW_WAKE_METHOD:
+		ret = wlan_cmd_802_11_fw_wakeup_method(pmpriv, cmd_ptr,
+						       cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_ROBUSTCOEX:
+		ret = wlan_cmd_robustcoex(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_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:
+		ret = wlan_cmd_reg_access(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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		ret = wlan_cmd_sdio_gpio_int(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	case HostCmd_CMD_SET_BSS_MODE:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+#ifdef WIFI_DIRECT_SUPPORT
+		if (pdata_buf) {
+			cmd_ptr->params.bss_mode.con_type = *(t_u8 *)pdata_buf;
+		} else
+#endif
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+			cmd_ptr->params.bss_mode.con_type =
+				CONNECTION_TYPE_ADHOC;
+		else if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
+			cmd_ptr->params.bss_mode.con_type =
+				CONNECTION_TYPE_INFRA;
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_SET_BSS_MODE) +
+					 S_DS_GEN);
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_802_11_NET_MONITOR:
+		ret = wlan_cmd_net_monitor(cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_MEASUREMENT_REQUEST:
+	case HostCmd_CMD_MEASUREMENT_REPORT:
+		ret = wlan_meas_cmd_process(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	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;
+#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_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_cmd_multi_chan_cfg(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_cmd_multi_chan_policy(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_cmd_drcs_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCMD_CONFIG_LOW_POWER_MODE:
+		ret = wlan_cmd_low_pwr_mode(pmpriv, cmd_ptr, 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_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_DYN_BW:
+		ret = wlan_cmd_config_dyn_bw(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	case HostCmd_CMD_ACS:
+		ret = wlan_cmd_acs(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;
+	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(IN t_void *priv, IN t_u8 first_bss)
+{
+	pmlan_private pmpriv = (pmlan_private)priv;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 enable = MTRUE;
+	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;
+	}
+
+	if (pmpriv->adapter->psdio_device->v16_fw_api &&
+	    IS_FW_SUPPORT_ADHOC(pmpriv->adapter)) {
+		/* set ibss coalescing_status */
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+				       HostCmd_ACT_GEN_SET, 0, MNULL, &enable);
+		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_sd8897/mlan/mlan_sta_cmdresp.c b/wlan_sd8897/mlan/mlan_sta_cmdresp.c
new file mode 100644
index 0000000..e05a173
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_sta_cmdresp.c
@@ -0,0 +1,2732 @@
+/** @file mlan_sta_cmdresp.c
+ *
+ *  @brief This file contains the handling of command
+ *  responses generated by firmware.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_11h.h"
+#include "mlan_sdio.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
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @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: command 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 (MTRUE == wlan_is_station_list_empty(pmpriv))
+			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: command 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 mlan_ioctl_req structure
+ *
+ *  @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);
+
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	ENTER();
+	if (resp->command != HostCmd_CMD_WMM_PARAM_CONFIG)
+		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_802_11_ASSOCIATE:
+		wlan_reset_connect_state(pmpriv, MTRUE);
+		break;
+
+	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;
+	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_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
+ */
+static mlan_status
+wlan_ret_802_11_rssi_info_ext(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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 *) ((t_u8 *)prssi_info_rsp +
+						    sizeof
+						    (HostCmd_DS_802_11_RSSI_INFO_EXT));
+		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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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;
+		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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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 *)((t_u8 *)ptxp_cfg
+					      + sizeof(HostCmd_DS_TXPWR_CFG));
+	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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN 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 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
+ */
+static mlan_status
+wlan_ret_802_11_mac_address(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_MAC_ADDRESS *pmac_addr = &resp->params.mac_addr;
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+
+	memcpy(pmpriv->adapter, pmpriv->curr_addr, pmac_addr->mac_addr,
+	       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(pmpriv->adapter, &bss->param.mac_addr, pmpriv->curr_addr,
+		       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 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *resp,
+			       IN 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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+	       &resp->params.deauth.reason_code, 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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_KEY_MATERIAL *pkey = &resp->params.key_material;
+	mlan_ds_sec_cfg *sec = MNULL;
+
+	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 for WPA/WPA2 h-supp mode\n");
+				pmpriv->port_open = MTRUE;
+			}
+			pmpriv->adapter->scan_block = MFALSE;
+		}
+	} else {
+		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(pmpriv->adapter, sec->param.encrypt_key.mac_addr,
+			       pkey->key_param_set.mac_addr,
+			       MLAN_MAC_ADDR_LENGTH);
+			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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.wapi.key,
+				       sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.wapi.pn,
+				       PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.tkip.key,
+				       sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.tkip.pn,
+				       WPA_PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.aes.key,
+				       sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.aes.pn,
+				       WPA_PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.cmac_aes.
+				       key, sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.cmac_aes.
+				       ipn, IGTK_PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.wep.key,
+				       sec->param.encrypt_key.key_len);
+				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(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(IN pmlan_private pmpriv,
+				IN 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(pmpriv->adapter,
+		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		       pibss_coal_resp->bssid, MLAN_MAC_ADDR_LENGTH);
+
+		/* 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      OUT 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(pmpriv->adapter, &misc->param.cust_ie, cust_ie,
+		       (cust_ie->len + sizeof(MrvlIEtypesHeader_t)));
+		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(pmpriv->adapter,
+				       (t_u8 *)&misc->param.cust_ie +
+				       (cust_ie->len +
+					sizeof(MrvlIEtypesHeader_t)),
+				       max_mgmt_ie,
+				       max_mgmt_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(IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp,
+		     OUT 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(pmpriv->adapter, &misc->param.tdls_config,
+		       &ptdls_config_data->tdls_info,
+		       MIN(sizeof(mlan_ds_misc_tdls_config),
+			   (resp->size - S_DS_GEN)));
+		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);
+			/* 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);
+			link_ptr->u.final_data_rate = final_data_rate / 2;
+
+			link_ptr =
+				(tdls_each_link_status *)(((t_u8 *)link_ptr) +
+							  link_length);
+		}
+		memcpy(pmpriv->adapter, &misc->param.tdls_config,
+		       &ptdls_config_data->tdls_info,
+		       MIN(sizeof(mlan_ds_misc_tdls_config),
+			   (resp->size - S_DS_GEN)));
+		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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *resp, OUT 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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
+ *  network monitor
+ *
+ *  @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_net_monitor(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pmisc = MNULL;
+	mlan_ds_misc_net_monitor *net_mon = MNULL;
+	HostCmd_DS_802_11_NET_MONITOR *cmd_net_mon =
+		(HostCmd_DS_802_11_NET_MONITOR *)&resp->params.net_mon;
+	ChanBandParamSet_t *pchan_band = MNULL;
+	t_u8 band_info = 0;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pmisc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		net_mon = &pmisc->param.net_mon;
+		net_mon->enable_net_mon =
+			wlan_le16_to_cpu(cmd_net_mon->enable_net_mon);
+		net_mon->filter_flag =
+			wlan_le16_to_cpu(cmd_net_mon->filter_flag);
+		pchan_band = &cmd_net_mon->monitor_chan.chan_band_param[0];
+		/* Band information in the TLV is bits[1:0] */
+		band_info = pchan_band->bandcfg.chanBand;
+		net_mon->channel = pchan_band->chan_number;
+		if (band_info == BAND_2GHZ)
+			net_mon->band |= (BAND_B | BAND_G);
+		if (band_info == BAND_5GHZ)
+			net_mon->band |= BAND_A;
+		net_mon->chan_bandwidth =
+			GET_SECONDARYCHAN(pchan_band->bandcfg.chan2Offset);
+		if (band_info == BAND_2GHZ)
+			net_mon->band |= BAND_GN;
+		if (band_info == BAND_5GHZ)
+			net_mon->band |= BAND_AN;
+		if (band_info == BAND_2GHZ)
+			net_mon->band |= BAND_GAC;
+		if (band_info == BAND_5GHZ)
+			net_mon->band |= BAND_AAC;
+	}
+	pmpriv->adapter->enable_net_mon =
+		wlan_le16_to_cpu(cmd_net_mon->enable_net_mon);
+
+	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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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(pmpriv->adapter, user_data->user_data,
+		       cmd_user_data->user_data, user_data->user_data_length);
+		pioctl_buf->data_read_written =
+			sizeof(mlan_ds_misc_otp_user_data) +
+			user_data->user_data_length;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of coalesce config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_coalesce_config(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN mlan_ioctl_req *pioctl_buf)
+{
+	ENTER();
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+mlan_status
+wlan_ret_get_sensor_temp(IN pmlan_private pmpriv,
+			 const IN HostCmd_DS_COMMAND *resp,
+			 OUT 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 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *resp, IN 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.chanBand,
+				       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;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+		IN HostCmd_DS_COMMAND *resp, IN 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 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(IN t_void *priv,
+			     IN t_u16 cmdresp_no,
+			     IN t_void *pcmd_buf, IN 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;
+	int ctr;
+
+	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;
+	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_FW_WAKE_METHOD:
+		ret = wlan_ret_fw_wakeup_method(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_ROBUSTCOEX:
+		break;
+	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_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_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);
+		pmadapter->tx_buf_size =
+			(pmadapter->tx_buf_size / MLAN_SDIO_BLOCK_SIZE) *
+			MLAN_SDIO_BLOCK_SIZE;
+		pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+		pmadapter->mp_end_port =
+			wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port);
+		pmadapter->mp_data_port_mask =
+			pmadapter->psdio_device->reg->data_port_mask;
+
+		for (ctr = 1;
+		     ctr <=
+		     pmadapter->psdio_device->max_ports -
+		     pmadapter->mp_end_port; ctr++) {
+			pmadapter->mp_data_port_mask &=
+				~(1 <<
+				  (pmadapter->psdio_device->max_ports - ctr));
+		}
+
+		if (pmadapter->psdio_device->supports_sdio_new_mode) {
+			pmadapter->curr_wr_port = 0;
+			pmadapter->mpa_tx.pkt_aggr_limit =
+				MIN(pmadapter->psdio_device->mp_aggr_pkt_limit,
+				    (pmadapter->mp_end_port >> 1));
+		} else {
+			pmadapter->curr_wr_port = 1;
+		}
+		PRINTM(MCMND, "end port %d, data port mask %x\n",
+		       wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port),
+		       pmadapter->mp_data_port_mask);
+		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:
+		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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		break;
+	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;
+	case HostCmd_CMD_802_11_NET_MONITOR:
+		ret = wlan_ret_net_monitor(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;
+#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;
+#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_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_ret_multi_chan_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_ret_multi_chan_policy(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_ret_drcs_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCMD_CONFIG_LOW_POWER_MODE:
+		break;
+	case HostCmd_CMD_COALESCE_CFG:
+		ret = wlan_ret_coalesce_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_DS_GET_SENSOR_TEMP:
+		ret = wlan_ret_get_sensor_temp(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_DYN_BW:
+		ret = wlan_ret_dyn_bw(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_ACS:
+		ret = wlan_ret_acs(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_BOOT_SLEEP:
+		ret = wlan_ret_boot_sleep(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_sd8897/mlan/mlan_sta_event.c b/wlan_sd8897/mlan/mlan_sta_event.c
new file mode 100644
index 0000000..9c21e1a
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_sta_event.c
@@ -0,0 +1,1417 @@
+/** @file mlan_sta_event.c
+ *
+ *  @brief This file contains MLAN event handling.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+
+/********************************************************
+			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);
+				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(priv->adapter, tdls_oper.peer_mac,
+				       tdls_event->peer_mac_addr,
+				       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(priv->adapter,
+				       (t_u8 *)tdls_evt->peer_mac_addr,
+				       tdls_event->peer_mac_addr,
+				       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
+ */
+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(priv->adapter, (t_u8 *)tdls_evt->peer_mac_addr,
+			       sta_ptr->mac_addr, 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;
+}
+
+/**
+ *  @brief This function will handle the generic NAN event for further wlan action
+ *   based on the Event subtypes
+ *
+ *  @param pmpriv     A pointer to mlan_private
+ *  @param evt_buf    A pointer to mlan_event
+ *  @param pmbuf    A pointer to mlan buffer
+ *
+ *  @return         N/A
+ */
+static void
+wlan_process_nan_event(pmlan_private pmpriv, pmlan_buffer pmbuf)
+{
+	t_u8 *evt_buf = MNULL;
+	mlan_event *pevent;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	event_nan_generic *nan_event = (event_nan_generic *)
+		(pmbuf->pbuf + pmbuf->data_offset + sizeof(mlan_event_id));
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+			       MLAN_MEM_DEF, &evt_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !evt_buf) {
+		LEAVE();
+		return;
+	}
+
+	pevent = (pmlan_event)evt_buf;
+
+	pevent->bss_index = pmpriv->bss_index;
+	if (wlan_le16_to_cpu(nan_event->event_sub_type) ==
+	    NAN_EVT_SUBTYPE_SD_EVENT ||
+	    wlan_le16_to_cpu(nan_event->event_sub_type) ==
+	    NAN_EVT_SUBTYPE_SDF_TX_DONE) {
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+	} else {
+		t_u8 test_mac[MLAN_MAC_ADDR_LENGTH]
+		= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
+		pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
+		pevent->event_len = MLAN_MAC_ADDR_LENGTH;
+		memcpy(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+		       test_mac, MLAN_MAC_ADDR_LENGTH);
+		wlan_ralist_add(pmpriv, test_mac);
+		memcpy(pmpriv->adapter,
+		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		       test_mac, MLAN_MAC_ADDR_LENGTH);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
+		if (pmpriv->port_ctrl_mode == MTRUE)
+			pmpriv->port_open = MTRUE;
+		pmpriv->media_connected = MTRUE;
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "nan interface - opened\n");
+		pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+	}
+
+	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");
+
+	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;
+	}
+	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;
+	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;
+
+	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));
+		priv->assoc_rsp_size = 0;
+	}
+	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_11d_is_enabled(priv)) &&
+	    (priv->state_11d.user_enable_11d == DISABLE_11D)) {
+
+		priv->state_11d.enable_11d = DISABLE_11D;
+		enable = DISABLE_11D;
+
+		/* Send cmd to FW to enable/disable 11D function */
+		ret = wlan_prepare_cmd(priv,
+				       HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET,
+				       Dot11D_i, MNULL, &enable);
+		if (ret)
+			PRINTM(MERROR, "11D: Failed to enable 11D\n");
+	}
+	if (pmadapter->num_cmd_timeout && pmadapter->curr_cmd &&
+	    (pmadapter->cmd_timer_is_set == MFALSE)) {
+		LEAVE();
+		return;
+	}
+
+	pevent->bss_index = priv->bss_index;
+	pevent->event_id = MLAN_EVENT_ID_FW_DISCONNECTED;
+	pevent->event_len = sizeof(priv->disconnect_reason_code);
+	memcpy(priv->adapter, pevent->event_buf, &priv->disconnect_reason_code,
+	       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;
+		/* Copy OBSS scan parameters */
+		memcpy(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 = ele_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(IN 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[100];
+	t_u8 *evt_buf = MNULL;
+	pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
+	t_u16 reason_code;
+	t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+	sta_node *sta_ptr = MNULL;
+	t_u8 i = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_event *pevent = (mlan_event *)event_buf;
+
+	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;
+	}
+
+	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(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(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:
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+				       MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO;
+			pevent->event_len =
+				pmbuf->data_len - sizeof(eventcause);
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       sizeof(eventcause), pevent->event_len);
+			PRINTM(MEVENT, "EVENT: FW Debug Info %s\n",
+			       (t_u8 *)pevent->event_buf);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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_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;
+		}
+		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_ANN:
+		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);
+		if (pmadapter->ecsa_enable) {
+			t_u8 stop_tx = *(t_u8 *)pmadapter->event_body;
+			if (stop_tx)
+				pmadapter->state_rdh.tx_block = MTRUE;
+		} else
+			wlan_11h_handle_event_chanswann(pmpriv);
+		break;
+	case EVENT_RADAR_DETECTED:
+		PRINTM(MEVENT, "EVENT: Radar Detected\n");
+
+		/* Send as passthru first, this event can cause other events */
+		memset(pmadapter, pevent, 0x00, sizeof(event_buf));
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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(MEVENT, "EVENT: Channel Report Ready\n");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+				       MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			memset(pmadapter, evt_buf, 0x00, MAX_EVENT_SIZE);
+			/* Setup event buffer */
+			pevent = (pmlan_event)evt_buf;
+			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(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       sizeof(eventcause), pevent->event_len);
+			/* Handle / pass event data */
+			ret = wlan_11h_handle_event_chanrpt_ready(pmpriv,
+								  pevent);
+
+			/* Also send this event as passthru */
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			/* Now done with buffer */
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		/* 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_MEAS_REPORT_RDY:
+		PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n",
+		       eventcause);
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_MEASUREMENT_REPORT,
+				       HostCmd_ACT_GEN_SET, 0, 0, MNULL);
+		break;
+	case EVENT_WMM_STATUS_CHANGE:
+		if (pmbuf && pmbuf->data_len
+		    > sizeof(eventcause) + sizeof(MrvlIEtypesHeader_t)) {
+			PRINTM(MEVENT, "EVENT: WMM status changed: %d\n",
+			       pmbuf->data_len);
+
+			evt_buf = (pmbuf->pbuf
+				   + pmbuf->data_offset + sizeof(eventcause));
+
+			wlan_ret_wmm_get_status(pmpriv,
+						evt_buf,
+						pmbuf->data_len -
+						sizeof(eventcause));
+		} else {
+			PRINTM(MEVENT, "EVENT: WMM status changed\n");
+			ret = wlan_cmd_wmm_status_change(pmpriv);
+		}
+		break;
+
+	case EVENT_RSSI_LOW:
+		PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			memset(pmadapter, evt_buf, 0x00, MAX_EVENT_SIZE);
+			pevent = (pmlan_event)evt_buf;
+			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(pmadapter, (t_u8 *)pevent->event_buf,
+			       (t_u8 *)&pmadapter->event_body,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			memset(pmadapter, evt_buf, 0x00, MAX_EVENT_SIZE);
+			pevent = (pmlan_event)evt_buf;
+			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(pmadapter, (t_u8 *)pevent->event_buf,
+			       (t_u8 *)&pmadapter->event_body,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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));
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmadapter->event_body, 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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmadapter->event_body, pevent->event_len);
+		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);
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		break;
+	case EVENT_WIFIDIRECT_SERVICE_DISCOVERY:
+		PRINTM(MEVENT, "EVENT: WIFIDIRECT service discovery event %d\n",
+		       eventcause);
+		/* Allocate large memory for service discovery */
+		if (pmbuf->data_len < MAX_EVENT_SIZE)
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       MAX_EVENT_SIZE, MLAN_MEM_DEF,
+					       &evt_buf);
+		else
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       MAX_EVENT_SIZE * 2, MLAN_MEM_DEF,
+					       &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		break;
+	case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+		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;
+#endif /* WIFI_DIRECT_SUPPORT */
+
+	case EVENT_TDLS_GENERIC_EVENT:
+		PRINTM(MEVENT, "EVENT: TDLS event %d\n", eventcause);
+		wlan_parse_tdls_event(pmpriv, pmbuf);
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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:
+		memcpy(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		sta_ptr = wlan_add_station_entry(pmpriv, sta_addr);
+		if (sta_ptr) {
+			PRINTM(MMSG,
+			       "wlan: EVENT: IBSS_STA_CONNECT " MACSTR "\n",
+			       MAC2STR(sta_addr));
+			if (pmpriv->adapter->adhoc_11n_enabled) {
+				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->ibss_ampdu[i];
+					else
+						sta_ptr->ampdu_sta[i] =
+							BA_STREAM_NOT_ALLOWED;
+				}
+				memset(pmadapter, sta_ptr->rx_seq, 0xff,
+				       sizeof(sta_ptr->rx_seq));
+			}
+		}
+		break;
+	case EVENT_IBSS_STATION_DISCONNECT:
+		memcpy(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		PRINTM(MMSG, "wlan: EVENT: IBSS_STA_DISCONNECT " MACSTR "\n",
+		       MAC2STR(sta_addr));
+
+		if (pmpriv->adapter->adhoc_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);
+		break;
+	case EVENT_SAD_REPORT:
+		pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+		if (pevent->event_len > sizeof(t_u32)) {
+			PRINTM(MEVENT, "EVENT: SAD_REPORT %d\n", eventcause);
+			/* Allocate memory for event buffer */
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       MAX_EVENT_SIZE, MLAN_MEM_DEF,
+					       &evt_buf);
+			if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+				pevent = (pmlan_event)evt_buf;
+				pevent->bss_index = pmpriv->bss_index;
+				pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+				pevent->event_len = pmbuf->data_len;
+				memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pevent->event_len);
+				wlan_recv_event(pmpriv, pevent->event_id,
+						pevent);
+				pcb->moal_mfree(pmadapter->pmoal_handle,
+						evt_buf);
+			}
+		} else {
+#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_MULTI_CHAN_INFO:
+		PRINTM(MEVENT, "EVENT: MULTI_CHAN_INFO\n");
+		wlan_handle_event_multi_chan_info(pmpriv, pmbuf);
+		break;
+
+	case EVENT_FW_DUMP_INFO:
+		PRINTM(MEVENT, "EVENT: Dump FW info\n");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_FW_DUMP_INFO;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, MIN(pevent->event_len,
+							     sizeof
+							     (event_buf)));
+		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;
+	case EVENT_NAN_GENERIC:
+		PRINTM(MEVENT, "EVENT: NAN_GENERIC_EVENT\n");
+		wlan_process_nan_event(pmpriv, pmbuf);
+		break;
+
+	case EVENT_MANAGEMENT_FRAME_WAKEUP:
+		PRINTM(MEVENT, "EVENT: EVENT_MANAGEMENT_FRAME_WAKEUP HOST\n");
+		break;
+	default:
+		PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL);
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8897/mlan/mlan_sta_ioctl.c b/wlan_sd8897/mlan/mlan_sta_ioctl.c
new file mode 100644
index 0000000..4f2895f
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_sta_ioctl.c
@@ -0,0 +1,5837 @@
+/** @file mlan_sta_ioctl.c
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_sdio.h"
+#include "mlan_11h.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief enable adhoc aes key
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *
+ *  @return         N/A
+ */
+static void
+wlan_enable_aes_key(pmlan_private pmpriv)
+{
+
+	ENTER();
+
+	if (pmpriv->aes_key.key_len != WPA_AES_KEY_LEN) {
+		LEAVE();
+		return;
+	}
+	wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+			 HostCmd_ACT_GEN_SET, 0, MNULL, &pmpriv->aes_key);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			     IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(pmadapter, &info->param.bss_info.ssid, &pbss_desc->ssid,
+	       sizeof(mlan_802_11_ssid));
+
+	/* BSSID */
+	memcpy(pmadapter, &info->param.bss_info.bssid, &pbss_desc->mac_address,
+	       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(pmadapter, &info->param.bss_info.capability_info,
+	       &pbss_desc->cap_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(pmadapter, &info->param.bss_info.ext_cap,
+		       (t_u8 *)pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t),
+		       pbss_desc->pext_cap->ieee_hdr.len);
+	}
+
+	/* Listen Interval */
+	info->param.bss_info.listen_interval = pmpriv->listen_interval;
+
+	/* Association ID */
+	if (pmpriv->assoc_rsp_buf)
+		info->param.bss_info.assoc_id =
+			(t_u16)((IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf)->
+			a_id;
+	else
+		info->param.bss_info.assoc_id = 0;
+
+	/* AP/Peer supported rates */
+	memset(pmadapter, info->param.bss_info.peer_supp_rates, 0,
+	       sizeof(info->param.bss_info.peer_supp_rates));
+	memcpy(pmadapter, info->param.bss_info.peer_supp_rates,
+	       pbss_desc->supported_rates,
+	       MIN(sizeof(info->param.bss_info.peer_supp_rates),
+		   sizeof(pbss_desc->supported_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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *pget_info = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
+
+	switch (pget_info->sub_command) {
+	case MLAN_OID_GET_STATS:
+		status = wlan_get_info_stats(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_SIGNAL:
+		status = wlan_get_info_signal(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_SIGNAL_EXT:
+		status = wlan_get_info_signal_ext(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_FW_INFO:
+		pioctl_req->data_read_written =
+			sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
+		pget_info->param.fw_info.fw_ver = pmadapter->fw_release_number;
+		memcpy(pmadapter, &pget_info->param.fw_info.mac_addr,
+		       pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
+		pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+		pget_info->param.fw_info.region_code = pmadapter->region_code;
+		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;
+		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.fw_supplicant_support =
+			IS_FW_SUPPORT_SUPPLICANT(pmadapter) ? 0x01 : 0x00;
+		pget_info->param.fw_info.antinfo = pmadapter->antinfo;
+		pget_info->param.fw_info.max_ap_assoc_sta =
+			pmadapter->max_sta_conn;
+		break;
+	case MLAN_OID_GET_BSS_INFO:
+		status = wlan_get_info_bss_info(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_DEBUG_INFO:
+		status = wlan_get_info_debug_info(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_VER_EXT:
+		status = wlan_get_info_ver_ext(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_LINK_STATS:
+		status = wlan_ioctl_link_statistic(pmpriv, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set/Get SNMP MIB handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_snmp_mib_ioctl(IN pmlan_adapter pmadapter, IN 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 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
+ */
+static mlan_status
+wlan_radio_ioctl_band_cfg(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req)
+{
+	t_u8 i, global_band = 0;
+	t_u8 chan_offset;
+	t_u8 infra_band = 0;
+	t_u8 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 = (t_u8)radio_cfg->param.band_cfg.config_bands;
+		adhoc_band = (t_u8)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 |= 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;
+		}
+
+		if (wlan_11d_set_universaltable
+		    (pmpriv, global_band | adhoc_band)) {
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		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;
+		pmadapter->chan_bandwidth =
+			(t_u8)radio_cfg->param.band_cfg.adhoc_chan_bandwidth;
+		/*
+		 * 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)
+				    || (pmadapter->adhoc_start_band & BAND_AN)
+					) {
+					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;
+		}
+
+		/* validate the channel offset */
+		chan_offset = wlan_validate_chan_offset(pmpriv,
+							pmadapter->
+							adhoc_start_band,
+							pmpriv->adhoc_channel,
+							pmadapter->
+							chan_bandwidth);
+
+		if (chan_offset != SEC_CHAN_NONE) {
+			if (chan_offset == SEC_CHAN_ABOVE)
+				pmadapter->chan_bandwidth =
+					CHANNEL_BW_40MHZ_ABOVE;
+			else
+				pmadapter->chan_bandwidth =
+					CHANNEL_BW_40MHZ_BELOW;
+		}
+		if ((adhoc_band & BAND_GN)
+		    || (adhoc_band & BAND_AN)
+			) {
+			pmadapter->adhoc_11n_enabled = MTRUE;
+		} else {
+			pmadapter->adhoc_11n_enabled = MFALSE;
+		}
+	} 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);
+		/* adhoc channel bandwidth */
+		radio_cfg->param.band_cfg.adhoc_chan_bandwidth =
+			pmadapter->chan_bandwidth;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter, IN 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;
+	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(IN pmlan_adapter pmadapter,
+			   IN 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(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+		       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(IN pmlan_adapter pmadapter,
+				  IN 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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+		       IN 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_AN)
+		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+	else 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) {
+				if (pmadapter->adhoc_11n_enabled)
+					pmadapter->adhoc_start_band =
+						BAND_A | BAND_AN;
+				else
+					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) {
+				if (pmadapter->adhoc_11n_enabled)
+					pmadapter->adhoc_start_band =
+						BAND_A | BAND_AN;
+				else
+					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(IN pmlan_adapter pmadapter, IN 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(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_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");
+
+			/* Clear any past association response stored for application retrieval */
+			pmpriv->assoc_rsp_size = 0;
+			pmpriv->curr_chan_flags =
+				bss->param.ssid_bssid.channel_flags;
+			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;
+			if (pmpriv->adhoc_aes_enabled)
+				wlan_enable_aes_key(pmpriv);
+		} 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 (pmpriv->adhoc_aes_enabled)
+				wlan_enable_aes_key(pmpriv);
+		}
+	}
+
+	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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			   IN 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 passphrase
+ *
+ *  @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;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ssid_bssid *ssid_bssid = MNULL;
+	mlan_ds_sec_cfg sec;
+	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;
+
+	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(pmadapter, (t_u8 *)&sec_pp->ssid,
+			       &pbss_desc->ssid, sizeof(mlan_802_11_ssid));
+		} else
+			memcpy(pmadapter, (t_u8 *)&sec_pp->bssid,
+			       &ssid_bssid->bssid, MLAN_MAC_ADDR_LENGTH);
+	} else {
+		memcpy(pmadapter, (t_u8 *)&sec_pp->ssid, &ssid_bssid->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);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Search for a BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_bss_ioctl_find_bss(IN pmlan_adapter pmadapter,
+			IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	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;
+		}
+	}
+
+	ret = wlan_find_bss(pmpriv, pioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Check if BSS channel is valid for Station's region
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_bss_ioctl_bss_11d_check_channel(IN pmlan_adapter pmadapter,
+				     IN 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(IN pmlan_adapter pmadapter, IN 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_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(IN pmlan_adapter pmadapter,
+				   IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			   IN t_u16 cmd_no, IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(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_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(IN pmlan_adapter pmadapter, IN 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;
+	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(IN pmlan_adapter pmadapter,
+		      IN pmlan_ioctl_req pioctl_req, IN 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(IN pmlan_adapter pmadapter,
+				 IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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.adhoc_awake_period =
+			(t_u32)pmadapter->adhoc_awake_period;
+		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.adhoc_awake_period)
+			pmadapter->adhoc_awake_period =
+				(t_u16)pm_cfg->param.ps_cfg.adhoc_awake_period;
+		else
+			pm_cfg->param.ps_cfg.adhoc_awake_period =
+				(t_u32)pmadapter->adhoc_awake_period;
+		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(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_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(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_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(IN pmlan_adapter pmadapter,
+			IN 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(pmadapter, (t_u8 *)pmadapter->mgmt_filter,
+		       (t_u8 *)pm_cfg->param.mgmt_filter,
+		       (i + 1) * sizeof(mlan_mgmt_frame_wakeup));
+	} 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(IN pmlan_adapter pmadapter, IN 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_FW_WAKEUP_METHOD:
+		status = wlan_fw_wakeup_method(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(priv->adapter, priv->wpa_ie, ie_data_ptr, ie_len);
+		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(priv->adapter, priv->osen_ie, ie_data_ptr, ie_len);
+		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(priv->adapter, priv->wapi_ie, ie_data_ptr, ie_len);
+		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(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_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(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_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(IN pmlan_adapter pmadapter,
+				IN 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(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_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(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_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		sec->param.encrypt_mode = pmpriv->sec_info.encryption_mode;
+	else
+		pmpriv->sec_info.encryption_mode = sec->param.encrypt_mode;
+
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Random charactor
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return		random charactor
+ */
+t_u8
+wlan_get_random_charactor(pmlan_adapter pmadapter)
+{
+	t_u32 sec, usec;
+	t_u8 ch = 0;
+
+	ENTER();
+
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+						  &usec);
+	sec = (sec & 0xFFFF) + (sec >> 16);
+	usec = (usec & 0xFFFF) + (usec >> 16);
+	ch = (((sec << 16) + usec) % 26) + 'a';
+	LEAVE();
+	return ch;
+}
+
+/**
+ *  @brief Set/Get WPA status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_sec_ioctl_wpa_enable(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_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);
+		/** clear adhoc aes flag, when WPA enabled */
+		pmpriv->adhoc_aes_enabled = MFALSE;
+		pmpriv->aes_key.key_len = 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(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_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,
+						       MNULL,
+						       &sec->param.encrypt_key);
+				goto exit;
+			}
+			PRINTM(MERROR, "Key_index is invalid\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+		index = sec->param.encrypt_key.key_index;
+	}
+
+	if ((sec->param.encrypt_key.key_disable == MTRUE)||
+	    (sec->param.encrypt_key.key_remove == MTRUE)) {
+		pmpriv->sec_info.wep_status = Wlan802_11WEPDisabled;
+		/* remove key */
+		if (sec->param.encrypt_key.key_remove == MTRUE) {
+			memset(pmadapter, &pmpriv->wep_key[index], 0,
+			       sizeof(mrvl_wep_key_t));
+			/* call firmware remove key */
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_802_11_KEY_MATERIAL,
+					       HostCmd_ACT_GEN_SET,
+					       0,
+					       MNULL, &sec->param.encrypt_key);
+			if (ret)
+				goto exit;
+		}
+	} else {
+		if (sec->param.encrypt_key.key_len) {
+			if ((sec->param.encrypt_key.key_len !=
+			     WEP_104_BIT_LEN)&&(sec->param.encrypt_key.
+						key_len != WEP_40_BIT_LEN)) {
+				PRINTM(MERROR, "Invalid wep key len=%d\n",
+				       sec->param.encrypt_key.key_len);
+				/* We will use random key to clear the key buffer in FW */
+				if (sec->param.encrypt_key.key_len <
+				    WEP_40_BIT_LEN)
+					sec->param.encrypt_key.key_len =
+						WEP_40_BIT_LEN;
+				else
+					sec->param.encrypt_key.key_len =
+						WEP_104_BIT_LEN;
+				for (i = 0; i < sec->param.encrypt_key.key_len;
+				     i++)
+					sec->param.encrypt_key.key_material[i] =
+						wlan_get_random_charactor
+						(pmadapter);
+			}
+			pwep_key = &pmpriv->wep_key[index];
+			/* Cleanup */
+			memset(pmadapter, pwep_key, 0, sizeof(mrvl_wep_key_t));
+			/* Copy the key in the driver */
+
+			memcpy(pmadapter, pwep_key->key_material,
+			       sec->param.encrypt_key.key_material,
+			       sec->param.encrypt_key.key_len);
+			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 (0
+				    || &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(pmadapter, sec->param.encrypt_key.key_material,
+			       pwep_key->key_material,
+			       sec->param.encrypt_key.key_len);
+		}
+		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(pmadapter,
+				       sec->param.encrypt_key.key_material,
+				       pwep_key->key_material,
+				       sec->param.encrypt_key.key_len);
+			}
+			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(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_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;
+	}
+
+	if (sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN) {
+	/** back up adhoc AES key */
+		memset(pmpriv->adapter, &pmpriv->aes_key, 0,
+		       sizeof(pmpriv->aes_key));
+		memcpy(pmpriv->adapter, (t_u8 *)&pmpriv->aes_key,
+		       (t_u8 *)&sec->param.encrypt_key,
+		       sizeof(pmpriv->aes_key));
+	}
+
+    /** only adhoc aes key_index = MLAN_KEY_INDEX_UNICAST */
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS &&
+	    sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN
+	    && sec->param.encrypt_key.key_index & MLAN_KEY_INDEX_UNICAST) {
+		t_u8 zero_key_material[WPA_AES_KEY_LEN];
+		memset(pmadapter, zero_key_material, 0,
+		       sizeof(zero_key_material));
+		if (memcmp
+		    (pmadapter, sec->param.encrypt_key.key_material,
+		     zero_key_material, WPA_AES_KEY_LEN)) {
+			PRINTM(MINFO, "Adhoc AES Enabled.\n");
+			pmpriv->adhoc_aes_enabled = MTRUE;
+		} else {
+			PRINTM(MINFO, "Adhoc AES Disabled.\n");
+			pmpriv->adhoc_aes_enabled = MFALSE;
+	    /** clear adhoc AES key */
+			pmpriv->aes_key.key_len = 0;
+		}
+	}
+
+	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(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_sec_cfg *sec = MNULL;
+	int index;
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+
+	if ((sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_UNICAST)&&
+	    (sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN)) {
+		if (pmpriv->adhoc_aes_enabled == MTRUE &&
+		    (pmpriv->aes_key.key_len == WPA_AES_KEY_LEN)) {
+			HEXDUMP("Get ADHOCAES Key",
+				pmpriv->aes_key.key_material, WPA_AES_KEY_LEN);
+			memcpy(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->aes_key.key_material, WPA_AES_KEY_LEN);
+			LEAVE();
+			return ret;
+		} else {
+			PRINTM(MERROR, " ADHOCAES key is not set yet!\n");
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			LEAVE();
+			return ret;
+		}
+	}
+	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 || pmpriv->adhoc_aes_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(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->wep_key[index].key_material,
+			       MIN(MLAN_MAX_KEY_LENGTH,
+				   pmpriv->wep_key[index].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)
+			   || (pmpriv->adhoc_aes_enabled)
+			) {
+			/* Return WPA enabled */
+			sec->param.encrypt_key.key_disable = MFALSE;
+
+			memcpy(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->aes_key.key_material,
+			       MIN(MLAN_MAX_KEY_LENGTH,
+				   pmpriv->aes_key.key_len));
+			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(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->wep_key[index].key_material,
+			       MIN(MLAN_MAX_KEY_LENGTH,
+				   pmpriv->wep_key[index].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)
+			   || (pmpriv->adhoc_aes_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(IN pmlan_adapter pmadapter,
+			   IN 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(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_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(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_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(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];
+	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(IN pmlan_adapter pmadapter, IN 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 };
+
+	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) {
+			t_u8 len = sizeof(priv->ext_cap);
+			if (len > pvendor_ie->len)
+				len = pvendor_ie->len;
+			memcpy(priv->adapter, &priv->ext_cap, &ie_data_ptr[2],
+			       len);
+		} 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(priv->adapter, (t_u8 *)&priv->wps.wps_ie,
+				       ie_data_ptr, ie_len);
+				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(priv->adapter,
+				       priv->gen_ie_buf + priv->gen_ie_buf_len,
+				       ie_data_ptr, ie_len);
+				/* Increment the stored buffer length by
+				 * the size passed */
+				priv->gen_ie_buf_len += ie_len;
+			} else {
+				/* Passed data does not fit in the
+				 * remaining buffer space */
+				ret = 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(IN pmlan_adapter pmadapter,
+			IN 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(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_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(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];
+
+	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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			   IN 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)
+	    || (pmadapter->adhoc_start_band & BAND_AN)
+		) {
+		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(IN pmlan_adapter pmadapter,
+				      IN 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(IN pmlan_adapter pmadapter, IN 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;
+#if defined(DFS_TESTING_SUPPORT)
+	case MLAN_OID_11H_DFS_TESTING:
+		status = wlan_11h_ioctl_dfs_testing(pmadapter, pioctl_req);
+		break;
+#endif
+	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(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;
+
+	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(pmadapter, misc->param.gen_ie.ie_data,
+			       pmpriv->wpa_ie, misc->param.gen_ie.len);
+		} 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(pmadapter, pmadapter->arp_filter,
+			       misc->param.gen_ie.ie_data,
+			       misc->param.gen_ie.len);
+			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(IN pmlan_adapter pmadapter,
+			   IN 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;
+	t_u16 mc_policy = pmadapter->mc_policy;
+	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);
+    /** 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))) {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+	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;
+	}
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MULTI_CHAN_POLICY,
+			       HostCmd_ACT_GEN_SET, 0, MNULL, &mc_policy);
+	if (ret == MLAN_STATUS_FAILURE) {
+		LEAVE();
+		return ret;
+	}
+	if (ret == MLAN_STATUS_PENDING)
+		pmadapter->pwarm_reset_ioctl_req = pioctl_req;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+			      IN 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->mpa_tx.buf_size =
+					mpa_ctrl->tx_buf_size;
+
+			if (mpa_ctrl->rx_buf_size > 0)
+				pmadapter->mpa_rx.buf_size =
+					mpa_ctrl->rx_buf_size;
+
+			if (wlan_alloc_sdio_mpa_buffers(pmadapter,
+							pmadapter->mpa_tx.
+							buf_size,
+							pmadapter->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->mpa_tx.pkt_aggr_limit =
+				mpa_ctrl->tx_max_ports;
+		if (mpa_ctrl->rx_max_ports > 0)
+			pmadapter->mpa_rx.pkt_aggr_limit =
+				mpa_ctrl->rx_max_ports;
+
+		pmadapter->mpa_tx.enabled = (t_u8)mpa_ctrl->tx_enable;
+		pmadapter->mpa_rx.enabled = (t_u8)mpa_ctrl->rx_enable;
+
+	} else {
+		mpa_ctrl->tx_enable = (t_u16)pmadapter->mpa_tx.enabled;
+		mpa_ctrl->rx_enable = (t_u16)pmadapter->mpa_rx.enabled;
+		mpa_ctrl->tx_buf_size = (t_u16)pmadapter->mpa_tx.buf_size;
+		mpa_ctrl->rx_buf_size = (t_u16)pmadapter->mpa_rx.buf_size;
+		mpa_ctrl->tx_max_ports =
+			(t_u16)pmadapter->mpa_tx.pkt_aggr_limit;
+		mpa_ctrl->rx_max_ports =
+			(t_u16)pmadapter->mpa_rx.pkt_aggr_limit;
+	}
+
+exit:
+	LEAVE();
+	return ret;
+}
+#endif /* SDIO_MULTI_PORT_TX_AGGR || SDIO_MULTI_PORT_RX_AGGR */
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			      IN 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(pmadapter, misc->param.assoc_resp.assoc_resp_buf,
+		       pmpriv->assoc_rsp_buf, MIN(ASSOC_RSP_BUF_SIZE,
+						  pmpriv->assoc_rsp_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(IN pmlan_adapter pmadapter,
+			   IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_SOFT_RESET,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get the thermal reading
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_thermal(IN pmlan_adapter pmadapter,
+			IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		PRINTM(MERROR, "Thermal reading setting is not allowed!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	}
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_802_11_SNMP_MIB,
+			       cmd_action,
+			       Thermal_i, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set subscribe event
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_subscribe_evt(IN pmlan_adapter pmadapter,
+			      IN 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
+ */
+mlan_status
+wlan_ipaddr_arp_filter(IN pmlan_adapter pmadapter,
+		       IN pmlan_ioctl_req pioctl_req, IN 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(pmadapter, pmadapter->arp_filter, buf, len);
+		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;
+}
+
+#define FLTR_BUF_IP_OFFSET              24
+#define FLTR_BUF_IP_OFFSET_2_IP_1       9
+#define FLTR_BUF_IP_OFFSET_2_IP_2       26
+
+/**
+ *  @brief Enable/Disable Auto ARP resonse
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *  @param ipv4_addr    ipv4 Address
+ *  @param num_ipv4     Number of ipv4 Addresses
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_ipaddr_auto_arp_resp(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req,
+			  IN t_u32 *ipv4_addr, IN t_u8 num_ipv4)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_GEN *hostcmd_hdr;
+	HostCmd_DS_MEF_CFG *mefcmd;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_ds_misc_cmd *hostcmd;
+	t_u32 buf_len = 0;
+	t_u8 *buf, *filter;
+
+	t_u8 fltr_buf[] = { 0x01, 0x10, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0x08, 0x06, 0x02, 0x02, 0x14, 0x00, 0x00,
+		0x00, 0x01, 0x41, 0x01, 0x00, 0x00, 0x00, 0x01,
+		0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e, 0x00,
+		0x00, 0x00, 0x01, 0x41, 0x44
+	};
+	t_u8 fltr_buf_2_ip[] = { 0x01, 0x10, 0x33, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e,
+		0x00, 0x00, 0x00, 0x01, 0x41, 0x01, 0x00, 0x00,
+		0x00, 0x01, 0xc0, 0xa8, 0x02, 0x6d, 0x04, 0x02,
+		0x2e, 0x00, 0x00, 0x00, 0x01, 0x41, 0x45, 0x01,
+		0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x02, 0x02,
+		0x14, 0x00, 0x00, 0x00, 0x01, 0x41, 0x44
+	};
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_cmd),
+			       MLAN_MEM_DEF, (t_u8 **)&hostcmd);
+
+	if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
+		PRINTM(MERROR, "Failed to allocate hostcmd  buffer\n");
+		pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(pmpriv->adapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
+	buf = hostcmd->cmd;
+
+	/* Prepare hostcmd buffer */
+	hostcmd_hdr = (HostCmd_DS_GEN *)(buf);
+	hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
+	mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN);
+	buf_len = S_DS_GEN;
+
+	if (!ipv4_addr) {
+		PRINTM(MINFO, "Disable Auto ARP Response\n");
+		mefcmd->criteria = wlan_cpu_to_le32(0);
+		mefcmd->nentries = wlan_cpu_to_le16(0);
+		buf_len += sizeof(HostCmd_DS_MEF_CFG);
+	} else {
+		/* Event bit (bit2) of HS conditions should be masked out */
+		mefcmd->criteria =
+			wlan_cpu_to_le32(pmpriv->adapter->hs_cfg.
+					 conditions & ~MBIT(2));
+		mefcmd->nentries = wlan_cpu_to_le16(1);
+		buf_len += sizeof(HostCmd_DS_MEF_CFG);
+		filter = buf + buf_len;
+		if (num_ipv4 == 1) {
+			memcpy(pmpriv->adapter, filter, fltr_buf,
+			       sizeof(fltr_buf));
+			memcpy(pmpriv->adapter, &filter[FLTR_BUF_IP_OFFSET],
+			       &ipv4_addr[0], sizeof(t_u32));
+			buf_len += sizeof(fltr_buf);
+		} else if (num_ipv4 >= 2) {
+			memcpy(pmpriv->adapter, filter, fltr_buf_2_ip,
+			       sizeof(fltr_buf_2_ip));
+			memcpy(pmpriv->adapter,
+			       &filter[FLTR_BUF_IP_OFFSET_2_IP_1],
+			       &ipv4_addr[0], sizeof(t_u32));
+			memcpy(pmpriv->adapter,
+			       &filter[FLTR_BUF_IP_OFFSET_2_IP_2],
+			       &ipv4_addr[1], sizeof(t_u32));
+			buf_len += sizeof(fltr_buf_2_ip);
+		}
+	}
+	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+	hostcmd->len = buf_len;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       0,
+			       0, 0, (t_void *)pioctl_req, (t_void *)hostcmd);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief MEF configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_mef_cfg(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_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(pmpriv->adapter, filter, fltr_buf, sizeof(fltr_buf));
+		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(pmpriv->adapter, filter, mef_cfg->param.cmd_buf.cmd,
+		       mef_cfg->param.cmd_buf.len);
+		buf_len += mef_cfg->param.cmd_buf.len;
+		break;
+	default:
+		PRINTM(MERROR, "Invalid sub ID parameter\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+		break;
+	}
+	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+	hostcmd->len = buf_len;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       0,
+			       0, 0, (t_void *)pioctl_req, (t_void *)hostcmd);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+done:
+	if (hostcmd)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief ipaddr configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_ipaddr_cfg(IN pmlan_adapter pmadapter,
+			   IN 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];
+	int i = 0;
+
+	ENTER();
+
+	/* GET operation */
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		memcpy(pmadapter, misc->param.ipaddr_cfg.ip_addr,
+		       pmpriv->ip_addr, IPADDR_LEN);
+		misc->param.ipaddr_cfg.op_code = pmpriv->op_code;
+		goto done;
+	}
+	/* only one IP is supported in current firmware */
+	for (i = 0; i < misc->param.ipaddr_cfg.ip_addr_num; i++) {
+		memcpy(pmadapter, &ipv4_addr[i],
+		       misc->param.ipaddr_cfg.ip_addr[i], 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;
+	if (misc->param.ipaddr_cfg.op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP)
+		ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req,
+						ipv4_addr,
+						misc->param.ipaddr_cfg.
+						ip_addr_num);
+	else if (pmpriv->op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP)
+		ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req, MNULL,
+						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(pmadapter, pmpriv->ip_addr,
+		       misc->param.ipaddr_cfg.ip_addr, IPADDR_LEN);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief CFP code configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_cfp_code_cfg(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 = (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) {
+		/* Save the values in MLAN */
+		if (!cfp_code->cfp_code_bg)
+			cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+			/* Use the region code to search for the index */
+			if (cfp_code->cfp_code_bg == region_code_index[i]) {
+				region_bg = cfp_code->cfp_code_bg;
+				break;
+			}
+		}
+		if (!cfp_code->cfp_code_a)
+			cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+			/* Use the region code to search for the index */
+			if (cfp_code->cfp_code_a == region_code_index[i]) {
+				region_a = cfp_code->cfp_code_a;
+				break;
+			}
+		}
+		if (!region_a) {
+			for (i = 0; i < MRVDRV_MAX_CFP_CODE_A; i++) {
+				/* Use the CFP code to search for the index */
+				if (cfp_code->cfp_code_a == cfp_code_index_a[i])
+					break;
+			}
+			if (i >= MRVDRV_MAX_CFP_CODE_A) {
+				PRINTM(MERROR,
+				       "CFP Code not identified for A\n");
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		pmadapter->cfp_code_bg = (t_u8)cfp_code->cfp_code_bg;
+		pmadapter->cfp_code_a = (t_u8)cfp_code->cfp_code_a;
+		if (region_bg && region_a && (region_bg == region_a))
+			pmadapter->region_code = pmadapter->cfp_code_a;
+		else
+			pmadapter->region_code = 0;
+		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+					 pmadapter->config_bands | pmadapter->
+					 adhoc_start_band)) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	} else {
+		/* GET operation */
+		cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+		cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets up country code and downloads CMD to FW
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_ioctl_country_code(IN pmlan_adapter pmadapter,
+			     IN 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) {
+		/* 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_bg && cfp_a && (cfp_bg == cfp_a))
+			pmadapter->region_code = cfp_a;
+		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(pmadapter, pmadapter->country_code,
+		       country_code->country_code, COUNTRY_CODE_LEN);
+	} else {
+		/* GET operation */
+		memcpy(pmadapter, country_code->country_code,
+		       pmadapter->country_code, COUNTRY_CODE_LEN);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Configure MFPC and MFPR for management frame protection
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_pmfcfg(IN pmlan_adapter pmadapter, IN 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 get sensor temperature
+ *
+ *  @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_get_sensor_temp(IN pmlan_adapter pmadapter,
+				IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, " sensor temp only support get operation \n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_DS_GET_SENSOR_TEMP,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 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(IN pmlan_adapter pmadapter,
+		       IN 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 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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+
+	if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
+		PRINTM(MERROR, "Request buffer not found!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	switch (misc->sub_command) {
+	case MLAN_OID_MISC_GEN_IE:
+		status = wlan_misc_ioctl_gen_ie(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_REGION:
+		status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_WARM_RESET:
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &pmadapter->ioctl_pending_q,
+				       (pmlan_linked_list)pioctl_req,
+				       pmadapter->callbacks.moal_spin_lock,
+				       pmadapter->callbacks.moal_spin_unlock);
+		pmadapter->pending_ioctl = MTRUE;
+		status = MLAN_STATUS_PENDING;
+		break;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	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_COALESCING_STATUS:
+		status = wlan_misc_ioctl_coalescing_status(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_NET_MONITOR:
+		status = wlan_misc_ioctl_net_monitor(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;
+	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;
+	case MLAN_OID_MISC_MULTI_CHAN_CFG:
+		status = wlan_misc_ioctl_multi_chan_config(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_MISC_MULTI_CHAN_POLICY:
+		status = wlan_misc_ioctl_multi_chan_policy(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_MISC_DRCS_CFG:
+		status = wlan_misc_ioctl_drcs_config(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_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_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_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_ROBUSTCOEX:
+		status = wlan_misc_robustcoex(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;
+	case MLAN_OID_MISC_ACS:
+		status = wlan_misc_acs(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(IN pmlan_adapter pmadapter,
+		      IN pmlan_ioctl_req pioctl_req, IN t_u32 action)
+{
+	mlan_ds_scan *scan = MNULL;
+
+	ENTER();
+
+	scan = (mlan_ds_scan *)pioctl_req->pbuf;
+	if (action == MLAN_ACT_GET) {
+		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.ext_scan = pmadapter->ext_scan;
+	} else {
+		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;
+		pmadapter->ext_scan = scan->param.scan_cfg.ext_scan;
+	}
+	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(IN pmlan_adapter pmadapter, IN 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(pmadapter, mac, &bss->param.ssid_bssid.bssid,
+			       sizeof(mac));
+			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(pmadapter, &bss->param.ssid_bssid.ssid, &pbss_desc->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(pmadapter, (t_u8 *)&bss->param.ssid_bssid.bssid,
+		       (t_u8 *)&pbss_desc->mac_address, 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;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
diff --git a/wlan_sd8897/mlan/mlan_sta_rx.c b/wlan_sd8897/mlan/mlan_sta_rx.c
new file mode 100644
index 0000000..d3d3db8
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_sta_rx.c
@@ -0,0 +1,764 @@
+/** @file mlan_sta_rx.c
+ *
+ *  @brief This file contains the handling of RX in MLAN
+ *  module.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+
+/********************************************************
+		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 Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/********************************************************
+		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;
+
+#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 = pos[1];
+			for (i = 0; i < pos[1]; i++)
+				sta_ptr->support_rate[i] = pos[2 + i];
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+			for (i = 0; i < pos[1]; i++)
+				sta_ptr->support_rate[sta_ptr->rate_len + i] =
+					pos[2 + i];
+			sta_ptr->rate_len += pos[1];
+			break;
+		case HT_CAPABILITY:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->HTcap, pos,
+			       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(priv->adapter, &sta_ptr->HTInfo, pos,
+			       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(priv->adapter, (t_u8 *)&sta_ptr->BSSCO_20_40,
+			       pos, sizeof(IEEEtypes_2040BSSCo_t));
+			break;
+		case EXT_CAPABILITY:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->ExtCap, pos,
+			       pos[1] + sizeof(IEEEtypes_Header_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS Extended capability",
+				    (t_u8 *)(&sta_ptr->ExtCap),
+				    sta_ptr->ExtCap.ieee_hdr.len + 2);
+			break;
+		case RSN_IE:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->rsn_ie, pos,
+			       pos[1] + sizeof(IEEEtypes_Header_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS Rsn ie ",
+				    (t_u8 *)(&sta_ptr->rsn_ie),
+				    pos[1] + 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(priv->adapter, (t_u8 *)&sta_ptr->link_ie, pos,
+			       sizeof(IEEEtypes_LinkIDElement_t));
+			break;
+
+		case VHT_CAPABILITY:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->vht_cap, pos,
+			       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(priv->adapter, (t_u8 *)&sta_ptr->vht_oprat, pos,
+			       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(priv->adapter, (t_u8 *)&sta_ptr->aid_info, pos,
+			       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 get pxpd info for radiotap info
+ *
+ *  @param priv A pointer to pmlan_private
+ *  @param prx_pd   A pointer to RxPD
+ *  @param prt_info   A pointer to radiotap_info
+ *
+ *  @return        N/A
+ */
+void
+wlan_rxpdinfo_to_radiotapinfo(pmlan_private priv, RxPD *prx_pd,
+			      radiotap_info * prt_info)
+{
+	radiotap_info rt_info_tmp;
+	t_u8 rx_rate_info = 0;
+	t_u8 mcs_index = 0;
+	t_u8 format = 0;
+	t_u8 bw = 0;
+	t_u8 gi = 0;
+	t_u8 ldpc = 0;
+
+	memset(priv->adapter, &rt_info_tmp, 0x00, sizeof(rt_info_tmp));
+	rt_info_tmp.snr = prx_pd->snr;
+	rt_info_tmp.nf = prx_pd->nf;
+	rt_info_tmp.band_config = (prx_pd->rx_info & 0xf);
+	rt_info_tmp.chan_num = (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+
+	rt_info_tmp.antenna = prx_pd->antenna;
+	if (!priv->adapter->psdio_device->v15_fw_api)
+		rx_rate_info = wlan_convert_v14_rate_ht_info(prx_pd->rate_info);
+	else
+		rx_rate_info = prx_pd->rate_info;
+	if ((rx_rate_info & 0x3) == MLAN_RATE_FORMAT_VHT) {
+		/* VHT rate */
+		format = MLAN_RATE_FORMAT_VHT;
+		mcs_index = MIN(prx_pd->rx_rate & 0xF, 9);
+		/* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
+		bw = (rx_rate_info & 0xC) >> 2;
+		/* LGI: gi =0, SGI: gi = 1 */
+		gi = (rx_rate_info & 0x10) >> 4;
+	} else if ((rx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
+		/* HT rate */
+		format = MLAN_RATE_FORMAT_HT;
+		mcs_index = prx_pd->rx_rate;
+		/* 20M: bw=0, 40M: bw=1 */
+		bw = (rx_rate_info & 0xC) >> 2;
+		/* LGI: gi =0, SGI: gi = 1 */
+		gi = (rx_rate_info & 0x10) >> 4;
+	} else {
+		/* LG rate */
+		format = MLAN_RATE_FORMAT_LG;
+		mcs_index = (prx_pd->rx_rate > MLAN_RATE_INDEX_OFDM0) ?
+			prx_pd->rx_rate - 1 : prx_pd->rx_rate;
+	}
+	ldpc = rx_rate_info & 0x40;
+
+	rt_info_tmp.rate_info.mcs_index = mcs_index;
+	rt_info_tmp.rate_info.rate_info =
+		(ldpc << 5) | (format << 3) | (bw << 1) | gi;
+	rt_info_tmp.rate_info.bitrate =
+		wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
+					prx_pd->rate_info);
+
+	if (prx_pd->flags & RXPD_FLAG_EXTRA_HEADER)
+		memcpy(priv->adapter, &rt_info_tmp.extra_info,
+		       (t_u8 *)prx_pd + sizeof(*prx_pd),
+		       sizeof(rt_info_tmp.extra_info));
+
+	memset(priv->adapter, prt_info, 0x00, sizeof(*prt_info));
+	memcpy(priv->adapter, prt_info, &rt_info_tmp, sizeof(*prt_info));
+
+	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 };
+
+	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(pmadapter, peth_hdr->src_addr,
+		       prx_pkt->eth803_hdr.src_addr,
+		       sizeof(peth_hdr->src_addr));
+		memcpy(pmadapter, peth_hdr->dest_addr,
+		       prx_pkt->eth803_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);
+
+	if (pmadapter->enable_net_mon) {
+		/* set netmon flag only for a sniffed pkt */
+		if (prx_pd->rx_pkt_type == PKT_TYPE_802DOT11) {
+			pmbuf->flags |= MLAN_BUF_FLAG_NET_MONITOR;
+			goto mon_process;
+		}
+	}
+
+mon_process:
+	if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
+		//Use some rxpd space to save rxpd info for radiotap header
+		//We should insure radiotap_info is not bigger than RxPD
+		wlan_rxpdinfo_to_radiotapinfo(priv, prx_pd,
+					      (radiotap_info *) (pmbuf->pbuf +
+								 pmbuf->
+								 data_offset -
+								 sizeof
+								 (radiotap_info)));
+	}
+	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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	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(IN t_void *adapter, IN 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_u8 adj_rx_rate = 0;
+	t_u8 antenna = 0;
+	rxpd_extra_info *pextra_info = MNULL;
+	ENTER();
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	/* Endian conversion */
+	endian_convert_RxPD(prx_pd);
+
+	if (prx_pd->flags & RXPD_FLAG_EXTRA_HEADER) {
+		pextra_info =
+			(rxpd_extra_info *) ((t_u8 *)prx_pd + sizeof(*prx_pd));
+		endian_convert_RxPD_extra_header(pextra_info);
+	}
+	rx_pkt_type = prx_pd->rx_pkt_type;
+	prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+	priv->rxpd_rate_info = prx_pd->rate_info;
+	if (!priv->adapter->psdio_device->v15_fw_api)
+		priv->rxpd_rate_info =
+			wlan_convert_v14_rate_ht_info(priv->rxpd_rate_info);
+	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 ((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;
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		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);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		goto done;
+	}
+
+	/*
+	 * 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)
+	     && !IS_11N_ADHOC_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)) {
+		wlan_process_rx_packet(pmadapter, pmbuf);
+		goto done;
+	}
+
+	if (queuing_ra_based(priv) ||
+	    (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)) {
+		memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+		       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;
+				if (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK) {
+					sta_ptr->snr = prx_pd->snr;
+					sta_ptr->nf = prx_pd->nf;
+					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 {
+		if ((rx_pkt_type != PKT_TYPE_BAR) &&
+		    (prx_pd->priority < MAX_NUM_TID))
+			priv->rx_seq[prx_pd->priority] = prx_pd->seq_num;
+		memcpy(pmadapter, ta,
+		       priv->curr_bss_params.bss_descriptor.mac_address,
+		       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)
+		) {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+
+done:
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8897/mlan/mlan_sta_tx.c b/wlan_sd8897/mlan/mlan_sta_tx.c
new file mode 100644
index 0000000..54ed29c
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_sta_tx.c
@@ -0,0 +1,303 @@
+/** @file mlan_sta_tx.c
+ *
+ *  @brief This file contains the handling of data packet
+ *  transmission in MLAN module.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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_sdio.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(IN t_void *priv, IN 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(pmpriv->adapter, &pkt_type,
+		       pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type));
+		memcpy(pmpriv->adapter, &tx_control,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+		       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;
+	}
+	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 = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf, MNULL);
+
+	switch (ret) {
+	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:
+		pmadapter->data_sent = MFALSE;
+		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_sd8897/mlan/mlan_txrx.c b/wlan_sd8897/mlan/mlan_txrx.c
new file mode 100644
index 0000000..dd217ee
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_txrx.c
@@ -0,0 +1,395 @@
+/**
+ * @file mlan_txrx.c
+ *
+ *  @brief This file contains the handling of TX/RX in MLAN
+ *
+ *  Copyright (C) 2009-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+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"
+#include "mlan_sdio.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
+	TxPD *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
+
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf,
+				     tx_param);
+done:
+	switch (ret) {
+	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;
+			plocal_tx_pd->flags = 0;
+		}
+#endif
+		PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
+		break;
+	case MLAN_STATUS_FAILURE:
+		pmadapter->data_sent = MFALSE;
+		PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
+		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(IN pmlan_adapter pmadapter,
+			 IN pmlan_buffer pmbuf, IN 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 (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);
+		}
+	}
+
+	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(IN pmlan_adapter pmadapter,
+			  IN pmlan_buffer pmbuf, IN mlan_status status)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	MASSERT(pmadapter && pmbuf);
+	if (!pmadapter || !pmbuf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pcb = &pmadapter->callbacks;
+	MASSERT(pmbuf->bss_index < pmadapter->priv_num);
+
+	if (pmbuf->pparent) {
+	/** we will free the pparaent at the end of deaggr */
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	} else {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+
+	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();
+	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) {
+				PRINTM(MINFO, "Dequeuing bypassed packet %p\n",
+				       pmbuf);
+				/* XXX: nex_pkt_len ??? */
+				tx_param.next_pkt_len = 0;
+				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 */
+					util_enqueue_list_head(pmadapter->
+							       pmoal_handle,
+							       &priv->
+							       bypass_txq,
+							       (pmlan_linked_list)
+							       pmbuf,
+							       pmadapter->
+							       callbacks.
+							       moal_spin_lock,
+							       pmadapter->
+							       callbacks.
+							       moal_spin_unlock);
+				} else {
+					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);
+				}
+				break;
+			} else {
+				PRINTM(MINFO, "Nothing to send\n");
+			}
+		}
+	}
+	LEAVE();
+}
diff --git a/wlan_sd8897/mlan/mlan_uap.h b/wlan_sd8897/mlan/mlan_uap.h
new file mode 100644
index 0000000..da60eaa
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_uap.h
@@ -0,0 +1,87 @@
+/** @file mlan_uap.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of uap functionalities
+ *
+ *  Copyright (C) 2009-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+Change log:
+    02/05/2009: initial version
+********************************************************/
+
+#ifndef _MLAN_UAP_H_
+#define _MLAN_UAP_H_
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert TxPD to little endian format from CPU format */
+#define uap_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 uap_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 TxPD to little endian format from CPU format */
+#define uap_endian_convert_TxPD(x)  do {} while (0)
+/** Convert RxPD from little endian format to CPU format */
+#define uap_endian_convert_RxPD(x)  do {} while (0)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+mlan_status wlan_uap_get_channel(IN pmlan_private pmpriv);
+
+mlan_status wlan_uap_set_channel(IN pmlan_private pmpriv,
+				 IN Band_Config_t uap_band_cfg,
+				 IN t_u8 channel);
+
+mlan_status wlan_uap_get_beacon_dtim(IN pmlan_private pmpriv);
+
+mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_ops_uap_prepare_cmd(IN t_void *priv,
+				     IN t_u16 cmd_no,
+				     IN t_u16 cmd_action,
+				     IN t_u32 cmd_oid,
+				     IN t_void *pioctl_buf,
+				     IN t_void *pdata_buf, IN t_void *pcmd_buf);
+
+mlan_status wlan_ops_uap_process_cmdresp(IN t_void *priv,
+					 IN t_u16 cmdresp_no,
+					 IN t_void *pcmd_buf,
+					 IN t_void *pioctl);
+
+mlan_status wlan_ops_uap_process_rx_packet(IN t_void *adapter,
+					   IN pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_process_event(IN t_void *priv);
+
+t_void *wlan_ops_uap_process_txpd(IN t_void *priv, IN pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_init_cmd(IN t_void *priv, IN t_u8 first_bss);
+
+#endif /* _MLAN_UAP_H_ */
diff --git a/wlan_sd8897/mlan/mlan_uap_cmdevent.c b/wlan_sd8897/mlan/mlan_uap_cmdevent.c
new file mode 100644
index 0000000..5c1cde2
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_uap_cmdevent.c
@@ -0,0 +1,4715 @@
+/** @file mlan_uap_cmdevent.c
+ *
+ *  @brief This file contains the handling of AP mode command and event
+ *
+ *  Copyright (C) 2009-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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_sdio.h"
+#include "mlan_11n.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief This function handles the command response error
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             N/A
+ */
+static mlan_status
+uap_process_cmdresp_error(mlan_private *pmpriv, HostCmd_DS_COMMAND *resp,
+			  mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	ENTER();
+	if (resp->command != HostCmd_CMD_WMM_PARAM_CONFIG)
+		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) {
+
+	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;
+
+	default:
+		break;
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+	pmadapter->curr_cmd = MNULL;
+	wlan_release_cmd_lock(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will return the pointer to station entry in station list
+ *          table which matches the give mac address
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+void
+wlan_notify_station_deauth(mlan_private *priv)
+{
+	sta_node *sta_ptr;
+	t_u8 event_buf[100];
+	mlan_event *pevent = (mlan_event *)event_buf;
+	t_u8 *pbuf;
+
+	ENTER();
+	sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+					     &priv->sta_list,
+					     priv->adapter->callbacks.
+					     moal_spin_lock,
+					     priv->adapter->callbacks.
+					     moal_spin_unlock);
+	if (!sta_ptr) {
+		LEAVE();
+		return;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		memset(priv->adapter, event_buf, 0, sizeof(event_buf));
+		pevent->bss_index = priv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT;
+		pevent->event_len = MLAN_MAC_ADDR_LENGTH + 2;
+		pbuf = (t_u8 *)pevent->event_buf;
+		/* reason field set to 0, Unspecified */
+		memcpy(priv->adapter, pbuf + 2, sta_ptr->mac_addr,
+		       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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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_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(pmadapter, (t_u8 *)mgmt_filter_tlv->filter,
+			       (t_u8 *)mgmt_filter,
+			       i * sizeof(mgmt_frame_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);
+		}
+	}
+	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,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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 };
+
+	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_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 (!memcmp
+			    (priv->adapter, bc_mac, tx_pause_tlv->peermac,
+			     MLAN_MAC_ADDR_LENGTH))
+				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;
+						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 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,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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;
+	t_u32 cmd_size = 0;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+	t_u16 i;
+	t_u16 ac;
+
+	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(pmpriv->adapter, tlv_mac->mac,
+		       &bss->param.bss_config.mac_addr, MLAN_MAC_ADDR_LENGTH);
+		cmd_size += sizeof(MrvlIEtypes_MacAddr_t);
+		tlv += sizeof(MrvlIEtypes_MacAddr_t);
+	}
+
+	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(pmpriv->adapter, tlv_ssid->ssid,
+		       bss->param.bss_config.ssid.ssid,
+		       bss->param.bss_config.ssid.ssid_len);
+		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);
+	}
+
+	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);
+	}
+	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(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);
+		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);
+		}
+
+		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(pmpriv->adapter, tlv_passphrase->passphrase,
+			       bss->param.bss_config.wpa_cfg.passphrase,
+			       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);
+		}
+	} 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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key0.key,
+			       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key1.key,
+			       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key2.key,
+			       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key3.key,
+			       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(pmpriv->adapter, tlv_htcap->ht_cap.supported_mcs_set,
+		       bss->param.bss_config.supported_mcs_set, 16);
+		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.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(pmpriv->adapter, tlv_wmm_parameter->wmm_para.ouitype,
+		       bss->param.bss_config.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);
+	}
+	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,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action,
+			   IN pmlan_ioctl_req pioctl_buf, IN t_void *pdata_buf)
+{
+	mlan_ds_bss *bss = MNULL;
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config;
+	MrvlIEtypes_MacAddr_t *mac_tlv = MNULL;
+	MrvlIEtypes_channel_band_t *pdat_tlv_cb = MNULL;
+	MrvlIEtypes_beacon_period_t *bcn_pd_tlv = MNULL, *pdat_tlv_bcnpd =
+		MNULL;
+	MrvlIEtypes_dtim_period_t *dtim_pd_tlv = MNULL, *pdat_tlv_dtimpd =
+		MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	MrvlIEtypes_channel_band_t *chan_band_tlv = MNULL;
+	MrvlIEtypes_chan_bw_oper_t *poper_class_tlv = MNULL;
+	t_u8 length = 0;
+	t_u8 curr_oper_class = 1;
+	t_u8 *oper_class_ie = (t_u8 *)sys_config->tlv_buffer;
+	t_u16 i = 0;
+	t_u8 ac = 0;
+	mlan_ds_misc_custom_ie *cust_ie = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	MrvlIEtypesHeader_t *ie_header =
+		(MrvlIEtypesHeader_t *)sys_config->tlv_buffer;
+	MrvlIEtypesHeader_t *pdata_header = (MrvlIEtypesHeader_t *)pdata_buf;
+	t_u8 *ie = (t_u8 *)sys_config->tlv_buffer + sizeof(MrvlIEtypesHeader_t);
+	t_u16 req_len = 0, travel_len = 0;
+	custom_ie *cptr = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
+	sys_config->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN);
+	if (pioctl_buf == MNULL) {
+
+		if (pdata_buf) {
+			switch (pdata_header->type) {
+			case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
+				pdat_tlv_cb =
+					(MrvlIEtypes_channel_band_t *)pdata_buf;
+				chan_band_tlv =
+					(MrvlIEtypes_channel_band_t *)
+					sys_config->tlv_buffer;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_channel_band_t));
+				chan_band_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+				chan_band_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_channel_band_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				if (cmd_action) {
+					chan_band_tlv->bandcfg =
+						pdat_tlv_cb->bandcfg;
+					chan_band_tlv->channel =
+						pdat_tlv_cb->channel;
+				}
+				ret = MLAN_STATUS_SUCCESS;
+				break;
+			case TLV_TYPE_UAP_BEACON_PERIOD:
+				pdat_tlv_bcnpd =
+					(MrvlIEtypes_beacon_period_t *)
+					pdata_buf;
+				bcn_pd_tlv =
+					(MrvlIEtypes_beacon_period_t *)
+					sys_config->tlv_buffer;
+				cmd->size =
+					sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+					S_DS_GEN +
+					sizeof(MrvlIEtypes_beacon_period_t);
+				bcn_pd_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_BEACON_PERIOD);
+				bcn_pd_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_beacon_period_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				if (cmd_action) {
+					bcn_pd_tlv->beacon_period =
+						wlan_cpu_to_le16
+						(pdat_tlv_bcnpd->beacon_period);
+				}
+				/* Add TLV_UAP_DTIM_PERIOD if it follws in pdata_buf */
+				pdat_tlv_dtimpd =
+					(MrvlIEtypes_dtim_period_t
+					 *)(((t_u8 *)pdata_buf)
+					    +
+					    sizeof
+					    (MrvlIEtypes_beacon_period_t));
+				if (TLV_TYPE_UAP_DTIM_PERIOD ==
+				    pdat_tlv_dtimpd->header.type) {
+					dtim_pd_tlv =
+						(MrvlIEtypes_dtim_period_t
+						 *)(sys_config->tlv_buffer +
+						    sizeof
+						    (MrvlIEtypes_beacon_period_t));
+					cmd->size +=
+						sizeof
+						(MrvlIEtypes_dtim_period_t);
+					dtim_pd_tlv->header.type =
+						wlan_cpu_to_le16
+						(TLV_TYPE_UAP_DTIM_PERIOD);
+					dtim_pd_tlv->header.len =
+						wlan_cpu_to_le16(sizeof
+								 (MrvlIEtypes_dtim_period_t)
+								 -
+								 sizeof
+								 (MrvlIEtypesHeader_t));
+					if (cmd_action) {
+						dtim_pd_tlv->dtim_period =
+							pdat_tlv_dtimpd->
+							dtim_period;
+					}
+				}
+				/* Finalize cmd size */
+				cmd->size = wlan_cpu_to_le16(cmd->size);
+				ret = MLAN_STATUS_SUCCESS;
+				break;
+			case TLV_TYPE_MGMT_IE:
+				cust_ie = (mlan_ds_misc_custom_ie *)pdata_buf;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypesHeader_t) +
+							 cust_ie->len);
+				ie_header->type =
+					wlan_cpu_to_le16(TLV_TYPE_MGMT_IE);
+				ie_header->len = wlan_cpu_to_le16(cust_ie->len);
+
+				if (ie && cust_ie->ie_data_list) {
+					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(pmpriv->adapter, ie,
+					       cust_ie->ie_data_list,
+					       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;
+
+			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(pmpriv->adapter, mac_tlv->mac,
+				       &bss->param.mac_addr,
+				       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.chanBand,
+				       bss->param.ap_channel.channel);
+			}
+		} else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG) &&
+			   (cmd_action == HostCmd_ACT_GEN_SET)) {
+			ret = wlan_uap_cmd_ap_config(pmpriv, cmd, cmd_action,
+						     pioctl_buf);
+			goto done;
+		}
+	} else if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		if ((misc->sub_command == MLAN_OID_MISC_GEN_IE) &&
+		    (misc->param.gen_ie.type == MLAN_IE_TYPE_GEN_IE)
+			) {
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof(MrvlIEtypesHeader_t) +
+						 misc->param.gen_ie.len);
+			ie_header->type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE);
+			ie_header->len =
+				wlan_cpu_to_le16(misc->param.gen_ie.len);
+			if (cmd_action == HostCmd_ACT_GEN_SET)
+				memcpy(pmpriv->adapter, ie,
+				       misc->param.gen_ie.ie_data,
+				       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 && misc->param.cust_ie.ie_data_list) {
+				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(pmpriv->adapter, ie,
+					       misc->param.cust_ie.ie_data_list,
+					       misc->param.cust_ie.len);
+			}
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles command resp for get uap settings
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_cmd_ap_config(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(pmpriv->adapter, &bss->param.bss_config.mac_addr,
+			       tlv_mac->mac, 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(pmpriv->adapter, bss->param.bss_config.ssid.ssid,
+			       tlv_ssid->ssid, MIN(MLAN_MAX_SSID_LENGTH,
+						   tlv_len));
+			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(pmpriv->adapter, bss->param.bss_config.rates,
+			       tlv_rates->rates, MIN(MAX_DATA_RATES, tlv_len));
+			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(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);
+			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;
+			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(pmpriv->adapter,
+			       bss->param.bss_config.wpa_cfg.passphrase,
+			       tlv_passphrase->passphrase,
+			       bss->param.bss_config.wpa_cfg.length);
+			break;
+#ifdef WIFI_DIRECT_SUPPORT
+		case TLV_TYPE_UAP_PSK:
+			tlv_psk = (MrvlIEtypes_psk_t *)tlv;
+			memcpy(pmpriv->adapter, bss->param.bss_config.psk,
+			       tlv_psk->psk, MIN(MLAN_MAX_KEY_LENGTH, tlv_len));
+			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(pmpriv->adapter, pkey->key,
+				       tlv_wep_key->key, 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(pmpriv->adapter,
+			       bss->param.bss_config.supported_mcs_set,
+			       tlv_htcap->ht_cap.supported_mcs_set, 16);
+			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));
+	}
+	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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *resp,
+			IN mlan_ioctl_req *pioctl_buf)
+{
+	int resp_len = 0, travel_len = 0;
+	int i = 0;
+	custom_ie *cptr;
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	MrvlIEtypes_MacAddr_t *tlv =
+		(MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer;
+	mlan_ds_misc_custom_ie *cust_ie = MNULL;
+	tlvbuf_max_mgmt_ie *max_mgmt_ie = MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter =
+		(MrvlIEtypes_wmm_parameter_t *)sys_config->tlv_buffer;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list =
+		(MrvlIEtypes_ChanListParamSet_t *)sys_config->tlv_buffer;
+	MrvlIEtypes_channel_band_t *chan_band_tlv =
+		(MrvlIEtypes_channel_band_t *)sys_config->tlv_buffer;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	t_u8 ac = 0;
+	MrvlIEtypes_channel_band_t *tlv_cb = MNULL;
+	MrvlIEtypes_beacon_period_t *tlv_bcnpd = MNULL;
+	MrvlIEtypes_dtim_period_t *tlv_dtimpd = MNULL;
+
+	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(pmpriv->adapter,
+					       &bss->param.mac_addr, tlv->mac,
+					       MLAN_MAC_ADDR_LENGTH);
+				}
+			} else if (bss->sub_command ==
+				   MLAN_OID_UAP_CFG_WMM_PARAM) {
+				if (TLV_TYPE_AP_WMM_PARAM ==
+				    wlan_le16_to_cpu(tlv_wmm_parameter->header.
+						     type)) {
+					if (wlan_le16_to_cpu
+					    (tlv_wmm_parameter->header.len) <
+					    sizeof(bss->param.ap_wmm_para)) {
+						PRINTM(MCMND,
+						       "FW don't support AP WMM PARAM\n");
+					} else {
+						bss->param.ap_wmm_para.
+							reserved =
+							MLAN_STATUS_COMPLETE;
+						for (ac = 0; ac < 4; ac++) {
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								aci_aifsn.
+								aifsn =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								aci_aifsn.aifsn;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								aci_aifsn.aci =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								aci_aifsn.aci;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								ecw.ecw_max =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								ecw.ecw_max;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								ecw.ecw_min =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								ecw.ecw_min;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								tx_op_limit =
+								wlan_le16_to_cpu
+								(tlv_wmm_parameter->
+								 wmm_para.
+								 ac_params[ac].
+								 tx_op_limit);
+							PRINTM(MCMND,
+							       "ac=%d, aifsn=%d, aci=%d, ecw_max=%d, ecw_min=%d, tx_op=%d\n",
+							       ac,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       aci_aifsn.aifsn,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       aci_aifsn.aci,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       ecw.ecw_max,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       ecw.ecw_min,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       tx_op_limit);
+						}
+					}
+				}
+			} else if (bss->sub_command ==
+				   MLAN_OID_UAP_SCAN_CHANNELS) {
+				if (TLV_TYPE_CHANLIST ==
+				    wlan_le16_to_cpu(tlv_chan_list->header.
+						     type)) {
+					pscan_chan =
+						tlv_chan_list->chan_scan_param;
+					bss->param.ap_scan_channels.
+						num_of_chan = 0;
+					for (i = 0;
+					     i <
+					     wlan_le16_to_cpu(tlv_chan_list->
+							      header.len) /
+					     sizeof(ChanScanParamSet_t); i++) {
+						if (bss->param.ap_scan_channels.
+						    remove_nop_channel &&
+						    wlan_11h_is_channel_under_nop
+						    (pmpriv->adapter,
+						     pscan_chan->chan_number)) {
+							bss->param.
+								ap_scan_channels.
+								num_remvoed_channel++;
+							PRINTM(MCMND,
+							       "Remove nop channel=%d\n",
+							       pscan_chan->
+							       chan_number);
+							pscan_chan++;
+							continue;
+						}
+						bss->param.ap_scan_channels.
+							chan_list[bss->param.
+								  ap_scan_channels.
+								  num_of_chan].
+							chan_number =
+							pscan_chan->chan_number;
+						bss->param.ap_scan_channels.
+							chan_list[bss->param.
+								  ap_scan_channels.
+								  num_of_chan].
+							bandcfg =
+							pscan_chan->bandcfg;
+						bss->param.ap_scan_channels.
+							num_of_chan++;
+						pscan_chan++;
+					}
+					PRINTM(MCMND,
+					       "AP scan channel list=%d\n",
+					       bss->param.ap_scan_channels.
+					       num_of_chan);
+				}
+			} else if (bss->sub_command == MLAN_OID_UAP_CHANNEL) {
+				if (TLV_TYPE_UAP_CHAN_BAND_CONFIG ==
+				    wlan_le16_to_cpu(chan_band_tlv->header.
+						     type)) {
+					bss->param.ap_channel.bandcfg =
+						chan_band_tlv->bandcfg;
+					bss->param.ap_channel.channel =
+						chan_band_tlv->channel;
+					bss->param.ap_channel.is_11n_enabled =
+						pmpriv->is_11n_enabled;
+					bss->param.ap_channel.is_dfs_chan =
+						wlan_11h_radar_detect_required
+						(pmpriv,
+						 bss->param.ap_channel.channel);
+					if (chan_band_tlv->bandcfg.chanWidth ==
+					    CHAN_BW_80MHZ)
+						bss->param.ap_channel.
+							center_chan =
+							wlan_get_center_freq_idx
+							(pmpriv, BAND_AAC,
+							 chan_band_tlv->channel,
+							 CHANNEL_BW_80MHZ);
+					PRINTM(MCMND,
+					       "AP channel, band=0x%x, channel=%d, is_11n_enabled=%d center_chan=%d\n",
+					       bss->param.ap_channel.bandcfg.
+					       chanBand,
+					       bss->param.ap_channel.channel,
+					       bss->param.ap_channel.
+					       is_11n_enabled,
+					       bss->param.ap_channel.
+					       center_chan);
+				}
+			} else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG)
+				   && (pioctl_buf->action == MLAN_ACT_GET)) {
+				wlan_uap_ret_cmd_ap_config(pmpriv, resp,
+							   pioctl_buf);
+			}
+		}
+		if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+			misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+			cust_ie =
+				(mlan_ds_misc_custom_ie *)sys_config->
+				tlv_buffer;
+			if ((pioctl_buf->action == MLAN_ACT_GET ||
+			     pioctl_buf->action == MLAN_ACT_SET) &&
+			    (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)) {
+
+				cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+				resp_len = cust_ie->len =
+					wlan_le16_to_cpu(cust_ie->len);
+				travel_len = 0;
+				/* conversion for index, mask, len */
+				if (resp_len == sizeof(t_u16))
+					cust_ie->ie_data_list[0].ie_index =
+						wlan_cpu_to_le16(cust_ie->
+								 ie_data_list
+								 [0].ie_index);
+
+				while (resp_len > sizeof(t_u16)) {
+					cptr = (custom_ie
+						*)(((t_u8 *)cust_ie->
+						    ie_data_list) + travel_len);
+					cptr->ie_index =
+						wlan_le16_to_cpu(cptr->
+								 ie_index);
+					cptr->mgmt_subtype_mask =
+						wlan_le16_to_cpu(cptr->
+								 mgmt_subtype_mask);
+					cptr->ie_length =
+						wlan_le16_to_cpu(cptr->
+								 ie_length);
+					travel_len +=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+					resp_len -=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+				}
+				memcpy(pmpriv->adapter, &misc->param.cust_ie,
+				       cust_ie,
+				       MIN(sizeof(mlan_ds_misc_custom_ie) -
+					   sizeof(tlvbuf_max_mgmt_ie),
+					   (cust_ie->len +
+					    sizeof(MrvlIEtypesHeader_t))));
+				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(pmpriv->adapter,
+						       (t_u8 *)&misc->param.
+						       cust_ie + (cust_ie->len +
+								  sizeof
+								  (MrvlIEtypesHeader_t)),
+						       max_mgmt_ie,
+						       MIN(sizeof
+							   (tlvbuf_max_mgmt_ie),
+							   max_mgmt_ie->len +
+							   sizeof
+							   (MrvlIEtypesHeader_t)));
+					}
+				}
+			}
+		}
+	} else {		/* no ioctl: driver generated get/set */
+		switch (wlan_le16_to_cpu(tlv->header.type)) {
+		case TLV_TYPE_UAP_MAC_ADDRESS:
+			memcpy(pmpriv->adapter, pmpriv->curr_addr, tlv->mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			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,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action,
+		      IN t_u32 cmd_oid,
+		      IN pmlan_ioctl_req pioctl_buf, IN t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = &cmd->params.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 *)&psnmp_mib->oid;
+			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(IN pmlan_private pmpriv, IN 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 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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(pmadapter, &data, psnmp_oid, 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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;
+		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,
+			IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, pcmd_sta_deauth->mac, deauth->mac_addr,
+	       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,
+			IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, pcmd_report_mic->mac, pdata_buf,
+	       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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action,
+			  IN t_u16 cmd_oid, IN 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		       pkey->mac_addr, 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+	       pkey->mac_addr, 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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wep.key,
+		       pkey->key_material, pkey->key_len);
+		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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.pn,
+		       pkey->pn, PN_SIZE);
+		pkey_material->key_param_set.key_params.wapi.key_len =
+			wlan_cpu_to_le16(MIN(WAPI_KEY_SIZE, pkey->key_len));
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.key,
+		       pkey->key_material, MIN(WAPI_KEY_SIZE, pkey->key_len));
+		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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.aes.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.aes.key,
+		       pkey->key_material, pkey->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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.cmac_aes.
+			       ipn, pkey->pn, SEQ_MAX_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+		pkey_material->key_param_set.key_params.cmac_aes.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.cmac_aes.key,
+		       pkey->key_material, pkey->key_len);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set CMAC AES Key\n");
+		goto done;
+	}
+	if (pkey->key_len == WPA_TKIP_KEY_LEN) {
+		if (pkey->
+		    key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.tkip.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.tkip.key,
+		       pkey->key_material, pkey->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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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;
+
+	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);
+		tlv = (MrvlIEtypes_sta_info_t *)((t_u8 *)sta_list +
+						 sizeof(HostCmd_DS_STA_LIST));
+		info->param.sta_list.sta_count =
+			MIN(info->param.sta_list.sta_count, MAX_NUM_CLIENTS);
+		for (i = 0; i < info->param.sta_list.sta_count; i++) {
+			memcpy(pmpriv->adapter,
+			       info->param.sta_list.info[i].mac_address,
+			       tlv->mac_address, MLAN_MAC_ADDR_LENGTH);
+			info->param.sta_list.info[i].power_mfg_status =
+				tlv->power_mfg_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;
+			else
+				info->param.sta_list.info[i].bandmode = 0xFF;
+			tlv++;
+		}
+	}
+
+	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;
+	priv->wmm_enabled = MFALSE;
+	priv->pkt_fwd = MFALSE;
+	priv->is_11n_enabled = MFALSE;
+
+	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 == 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 == 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(priv->adapter, &wmm_param_ie,
+				       ((t_u8 *)tlv + 2),
+				       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(priv->adapter, (t_u8 *)&pchan_band_info->bandcfg,
+			       (t_u8 *)&pchan_info->bandcfg, 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(priv->adapter, (t_u8 *)tx_pn,
+			       wapi_tlv->multicast_PN, PN_SIZE);
+			for (i = 0; i < 4; i++)
+				tx_pn[i] = mlan_ntohl(tx_pn[i]);
+			memcpy(priv->adapter, wapi_tlv->multicast_PN,
+			       (t_u8 *)tx_pn, PN_SIZE);
+			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(priv->adapter, pevent->event_buf,
+	       pmbuf->pbuf + pmbuf->data_offset + 6, 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(priv->adapter, &frame_control,
+			       (t_u8 *)&(mgmt_tlv->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(priv->adapter,
+				       pevent->event_buf + pevent->event_len,
+				       assoc_req_ie, 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 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,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	HostCmd_DS_UAP_OPER_CTRL *poper_ctl =
+		(HostCmd_DS_UAP_OPER_CTRL *) & cmd->params.uap_oper_ctrl;
+	mlan_ds_bss *bss = (mlan_ds_bss *)pdata_buf;
+	mlan_uap_oper_ctrl *uap_oper_ctrl = &bss->param.ap_oper_ctrl;
+	Band_Config_t *bandcfg = MNULL;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_OPER_CTRL);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_UAP_OPER_CTRL) + S_DS_GEN);
+	poper_ctl->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		poper_ctl->ctrl = wlan_cpu_to_le16(uap_oper_ctrl->ctrl_value);
+		if (uap_oper_ctrl->ctrl_value == 2) {
+			poper_ctl->chan_opt =
+				wlan_cpu_to_le16(uap_oper_ctrl->chan_opt);
+			if (uap_oper_ctrl->chan_opt == 3) {
+				poper_ctl->channel_band.header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+				poper_ctl->channel_band.header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_channel_band_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				bandcfg = &poper_ctl->channel_band.bandcfg;
+				if (uap_oper_ctrl->channel > 14)
+					bandcfg->chanBand = BAND_5GHZ;
+				bandcfg->chanWidth = uap_oper_ctrl->band_cfg;
+				if (bandcfg->chanWidth)
+					bandcfg->chan2Offset =
+						wlan_get_second_channel_offset
+						(uap_oper_ctrl->channel);
+				bandcfg->scanMode = SCAN_MODE_MANUAL;
+				poper_ctl->channel_band.channel =
+					uap_oper_ctrl->channel;
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of uap operation control
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_oper_ctrl(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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;
+}
+
+/********************************************************
+			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(IN t_void *priv,
+			 IN t_u16 cmd_no,
+			 IN t_u16 cmd_action,
+			 IN t_u32 cmd_oid,
+			 IN t_void *pioctl_buf,
+			 IN t_void *pdata_buf, IN 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_CMD_SOFT_RESET:
+	case HOST_CMD_APCMD_BSS_STOP:
+	case HOST_CMD_APCMD_BSS_START:
+	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_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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		ret = wlan_cmd_sdio_gpio_int(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_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;
+	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_FW_WAKE_METHOD:
+		ret = wlan_cmd_802_11_fw_wakeup_method(pmpriv, cmd_ptr,
+						       cmd_action,
+						       (t_u16 *)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_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);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		cmd_ptr->command =
+			wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) +
+					 S_DS_GEN);
+		pmpriv->tx_rate = 0;
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_cmd_wifi_direct_mode(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+	case HOST_CMD_P2P_PARAMS_CONFIG:
+		ret = wlan_cmd_p2p_params_config(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_RF_ANTENNA:
+		ret = wlan_cmd_802_11_rf_antenna(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_cmd_11ac_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_802_11_EEPROM_ACCESS:
+		ret = wlan_cmd_reg_access(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;
+	case HostCmd_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_cmd_multi_chan_cfg(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_cmd_multi_chan_policy(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_cmd_drcs_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+#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;
+
+#ifdef STA_SUPPORT
+	case HostCmd_CMD_ACS:
+		ret = wlan_cmd_acs(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_NET_MONITOR:
+		ret = wlan_cmd_net_monitor(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;
+	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_BOOT_SLEEP:
+		ret = wlan_cmd_boot_sleep(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(IN t_void *priv,
+			     IN t_u16 cmdresp_no,
+			     IN t_void *pcmd_buf, IN 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;
+	int ctr;
+	const mlan_sdio_device *psdio_device = pmadapter->psdio_device;
+	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;
+		if (pmpriv->intf_state_11h.is_11h_host)
+			pmpriv->intf_state_11h.tx_disabled = MFALSE;
+		else
+			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);
+		pmpriv->uap_host_based = MFALSE;
+		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 = MFALSE;
+		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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		break;
+	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;
+	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_FW_WAKE_METHOD:
+		ret = wlan_ret_fw_wakeup_method(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_ROBUSTCOEX:
+		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_802_11_NET_MONITOR:
+		ret = wlan_ret_net_monitor(pmpriv, resp, pioctl_buf);
+		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);
+		pmadapter->tx_buf_size =
+			(pmadapter->tx_buf_size / MLAN_SDIO_BLOCK_SIZE) *
+			MLAN_SDIO_BLOCK_SIZE;
+		pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+		pmadapter->mp_end_port =
+			wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port);
+		pmadapter->mp_data_port_mask =
+			psdio_device->reg->data_port_mask;
+
+		for (ctr = 1;
+		     ctr <= psdio_device->max_ports - pmadapter->mp_end_port;
+		     ctr++) {
+			pmadapter->mp_data_port_mask &=
+				~(1 << (psdio_device->max_ports - ctr));
+		}
+
+		if (psdio_device->supports_sdio_new_mode) {
+			pmadapter->curr_wr_port = 0;
+			pmadapter->mpa_tx.pkt_aggr_limit =
+				MIN(psdio_device->mp_aggr_pkt_limit,
+				    (pmadapter->mp_end_port >> 1));
+		} else {
+			pmadapter->curr_wr_port = 1;
+		}
+		PRINTM(MCMND, "end port %d, data port mask %x\n",
+		       wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port),
+		       pmadapter->mp_data_port_mask);
+		PRINTM(MCMND, "max_tx_buf_size=%d, tx_buf_size=%d\n",
+		       pmadapter->max_tx_buf_size, pmadapter->tx_buf_size);
+		break;
+	case HostCmd_CMD_AMSDU_AGGR_CTRL:
+		ret = wlan_ret_amsdu_aggr_ctrl(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11N_CFG:
+		ret = wlan_ret_11n_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_REJECT_ADDBA_REQ:
+		ret = wlan_ret_reject_addba_req(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_BF_CFG:
+		ret = wlan_ret_tx_bf_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_VERSION_EXT:
+		ret = wlan_ret_ver_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RX_MGMT_IND:
+		ret = wlan_ret_rx_mgmt_ind(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_CFG_TX_DATA_PAUSE:
+		ret = wlan_uap_ret_txdatapause(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_RADIO_CONTROL:
+		ret = wlan_ret_802_11_radio_control(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_RATE_CFG:
+		ret = wlan_ret_tx_rate_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		ret = wlan_ret_802_11_tx_rate_query(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_ret_remain_on_channel(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_ret_wifi_direct_mode(pmpriv, resp, pioctl_buf);
+		break;
+	case HOST_CMD_P2P_PARAMS_CONFIG:
+		ret = wlan_ret_p2p_params_config(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_RF_ANTENNA:
+		ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_ret_11ac_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_802_11_EEPROM_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;
+	case HostCmd_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_ret_multi_chan_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_ret_multi_chan_policy(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_ret_drcs_cfg(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 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;
+
+#ifdef STA_SUPPORT
+	case HostCmd_CMD_ACS:
+		ret = wlan_ret_acs(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	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;
+	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(IN 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;
+
+	ENTER();
+
+	/* 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,
+			       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;
+		memcpy(pmadapter, pmpriv->curr_addr, pmadapter->event_body + 2,
+		       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);
+		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->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(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(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(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		sta_ptr = wlan_add_station_entry(pmpriv, sta_addr);
+		PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_ASSOC " MACSTR "\n",
+		       MAC2STR(sta_addr));
+		if (!sta_ptr)
+			break;
+		if (pmpriv->is_11n_enabled) {
+			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);
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + 4, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		memcpy(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		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));
+		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(MEVENT, "EVENT: Radar Detected\n");
+
+		/* 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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		pevent->event_id = 0;	/* clear to avoid resending at end of fcn */
+
+		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,
+							MNULL);
+			} else {
+				PRINTM(MEVENT,
+				       "Ignore Event Radar Detected - handling"
+				       " already in progress.\n");
+			}
+		} else {
+
+#ifdef DFS_TESTING_SUPPORT
+			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 {
+#endif
+				pmpriv->intf_state_11h.tx_disabled = MTRUE;
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_FW_RADAR_DETECTED,
+						MNULL);
+
+#ifdef DFS_TESTING_SUPPORT
+			}
+#endif
+		}
+
+		break;
+	case EVENT_CHANNEL_REPORT_RDY:
+		PRINTM(MEVENT, "EVENT: Channel Report Ready\n");
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause),
+		       pevent->event_len);
+		/* Handle / pass event data, and free buffer */
+		ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent);
+
+		if (pmpriv->intf_state_11h.is_11h_host) {
+			*((t_u8 *)pevent->event_buf) =
+				pmpriv->adapter->state_dfs.dfs_radar_found;
+			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(MEVENT, "EVENT: CHANNEL_SWITCH new channel %d\n",
+		       channel);
+		pmpriv->uap_channel = channel;
+
+		if ((pmpriv->adapter->state_rdh.stage != RDH_OFF &&
+		     !pmpriv->intf_state_11h.is_11h_host)
+#ifdef DFS_TESTING_SUPPORT
+		    || pmpriv->adapter->dfs_test_params.
+		    no_channel_change_on_radar ||
+		    pmpriv->adapter->dfs_test_params.fixed_new_channel_on_radar
+#endif
+			) {
+			/* 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(pmadapter, (t_u8 *)&pchan_band_info->bandcfg,
+			       (t_u8 *)&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;
+#ifdef WIFI_DIRECT_SUPPORT
+	case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+		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;
+#endif
+	case EVENT_MULTI_CHAN_INFO:
+		PRINTM(MEVENT, "EVENT: MULTI_CHAN_INFO\n");
+		wlan_handle_event_multi_chan_info(pmpriv, pmbuf);
+		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(pmadapter,
+		       (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause),
+		       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;
+	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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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 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(IN t_void *priv, IN 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;
+		}
+	}
+
+	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_sd8897/mlan/mlan_uap_ioctl.c b/wlan_sd8897/mlan/mlan_uap_ioctl.c
new file mode 100644
index 0000000..7856b37
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_uap_ioctl.c
@@ -0,0 +1,2031 @@
+/** @file mlan_uap_ioctl.c
+ *
+ *  @brief This file contains the handling of AP mode ioctls
+ *
+ *  Copyright (C) 2009-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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_sdio.h"
+#include "mlan_11n.h"
+#include "mlan_fw.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+
+/********************************************************
+			Global Variables
+********************************************************/
+extern t_u8 tos_to_tid_inv[];
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief Stop BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_stop(IN pmlan_adapter pmadapter,
+			IN 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 (!priv->adapter->mc_policy &&
+	    (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(IN 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)) {
+
+		/* first check if channel is under NOP */
+		if (wlan_11h_is_channel_under_nop(pmpriv->adapter,
+						  puap_state_chan_cb->
+						  channel)) {
+			/* recently we've seen radar on this channel */
+			ret = MLAN_STATUS_FAILURE;
+			under_nop = MTRUE;
+		}
+
+		/* Check cached radar check on the channel */
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = wlan_11h_check_chan_report(pmpriv,
+							 puap_state_chan_cb->
+							 channel);
+
+		/* Found radar: try to switch to a non-dfs channel */
+		if (ret != MLAN_STATUS_SUCCESS) {
+			old_channel = puap_state_chan_cb->channel;
+			ret = wlan_11h_switch_non_dfs_chan(pmpriv,
+							   &puap_state_chan_cb->
+							   channel);
+
+			if (ret == MLAN_STATUS_SUCCESS) {
+
+				wlan_11h_update_bandcfg(&pmpriv->
+							uap_state_chan_cb.
+							bandcfg,
+							puap_state_chan_cb->
+							channel);
+				PRINTM(MCMD_D,
+				       "NOP: uap band config:0x%x  channel=%d\n",
+				       pmpriv->uap_state_chan_cb.bandcfg,
+				       puap_state_chan_cb->channel);
+
+				ret = wlan_uap_set_channel(pmpriv,
+							   pmpriv->
+							   uap_state_chan_cb.
+							   bandcfg,
+							   puap_state_chan_cb->
+							   channel);
+				if (ret == MLAN_STATUS_SUCCESS) {
+					if (under_nop) {
+						PRINTM(MMSG,
+						       "Channel %d under NOP,"
+						       " switched to new channel %d successfully.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					} else {
+						PRINTM(MMSG,
+						       "Radar found on channel %d,"
+						       " switched to new channel %d successfully.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					}
+				} else {
+					if (under_nop) {
+						PRINTM(MMSG,
+						       "Channel %d under NOP,"
+						       " switch to new channel %d failed.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					} else {
+						PRINTM(MMSG,
+						       "Radar found on channel %d,"
+						       " switch to new channel %d failed.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					}
+					pcb->moal_ioctl_complete(pmpriv->
+								 adapter->
+								 pmoal_handle,
+								 puap_state_chan_cb->
+								 pioctl_req_curr,
+								 MLAN_STATUS_FAILURE);
+					goto done;
+				}
+			} else {
+				if (under_nop) {
+					PRINTM(MMSG,
+					       "Channel %d under NOP, no switch channel available.\n",
+					       old_channel);
+				} else {
+					PRINTM(MMSG,
+					       "Radar found on channel %d, no switch channel available.\n",
+					       old_channel);
+				}
+				/* No command sent with the ioctl, need manually signal completion */
+				pcb->moal_ioctl_complete(pmpriv->adapter->
+							 pmoal_handle,
+							 puap_state_chan_cb->
+							 pioctl_req_curr,
+							 MLAN_STATUS_FAILURE);
+				goto done;
+			}
+		} else {
+			PRINTM(MINFO, "No Radar found on channel %d\n",
+			       puap_state_chan_cb->channel);
+		}
+	}
+
+	/* 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			 IN 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 =
+		pmadapter->psdio_device->ampdu_info->ampdu_uap_txwinsize;
+	pmpriv->add_ba_param.rx_win_size =
+		pmadapter->psdio_device->ampdu_info->ampdu_uap_rxwinsize;
+	pmpriv->user_rxwinsize = pmpriv->add_ba_param.rx_win_size;
+
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		pmpriv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i];
+		pmpriv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i];
+		pmpriv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+	}
+	pmpriv->aggr_prio_tbl[6].ampdu_user =
+		pmpriv->aggr_prio_tbl[7].ampdu_user = BA_STREAM_NOT_ALLOWED;
+	pmpriv->addba_reject[6] =
+		pmpriv->addba_reject[7] = ADDBA_RSP_STATUS_REJECT;
+
+	/* hs_configured, hs_activated are reset by main loop */
+	pmadapter->hs_cfg.conditions = HOST_SLEEP_DEF_COND;
+	pmadapter->hs_cfg.gpio = HOST_SLEEP_DEF_GPIO;
+	pmadapter->hs_cfg.gap = HOST_SLEEP_DEF_GAP;
+
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_APCMD_SYS_RESET,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 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(IN pmlan_adapter pmadapter,
+			       IN 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(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+		       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(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get scan channels
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_scan_channels(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get UAP channel
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_channel(IN pmlan_adapter pmadapter,
+			       IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get UAP operation control vaule
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_oper_ctrl(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pmadapter->fw_ver == HOST_API_VERSION_V15
+	    && pmadapter->fw_min_ver >= FW_MINOR_VERSION_1) {
+		bss = (mlan_ds_bss *)pioctl_req->pbuf;
+		if (pioctl_req->action == MLAN_ACT_SET)
+			cmd_action = HostCmd_ACT_GEN_SET;
+		else
+			cmd_action = HostCmd_ACT_GEN_GET;
+		/* Send request to firmware */
+		ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_OPER_CTRL,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       (t_void *)pioctl_req->pbuf);
+
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	} else {
+		PRINTM(MMSG, "FW don't support uap oper ctrl\n");
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Uap statistics
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_get_stats(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			      IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(priv->adapter, priv->wapi_ie, misc->param.gen_ie.ie_data,
+		       misc->param.gen_ie.len);
+		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(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;
+	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(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_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(IN pmlan_adapter pmadapter,
+				    IN 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(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_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(IN pmlan_adapter pmadapter, IN 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(pmadapter, &info->param.bss_info.bssid, pmpriv->curr_addr,
+	       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(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_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 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(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_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(IN 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(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];
+
+	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(IN 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(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_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) {
+#ifdef DFS_TESTING_SUPPORT
+			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;
+			}
+#endif
+			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(IN 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_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);
+		}
+	}
+
+	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;
+
+	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(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_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_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;
+}
+
+/********************************************************
+			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(IN 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(IN pmlan_private pmpriv,
+		     IN Band_Config_t uap_band_cfg, IN 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(IN pmlan_private pmpriv)
+{
+	t_u8 tlv_buffer[sizeof(MrvlIEtypes_beacon_period_t) +
+			sizeof(MrvlIEtypes_dtim_period_t)];
+	MrvlIEtypes_beacon_period_t *ptlv_beacon_pd;
+	MrvlIEtypes_dtim_period_t *ptlv_dtim_pd;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(pmpriv->adapter, &tlv_buffer, 0, sizeof(tlv_buffer));
+	ptlv_beacon_pd = (MrvlIEtypes_beacon_period_t *)tlv_buffer;
+	ptlv_beacon_pd->header.type = TLV_TYPE_UAP_BEACON_PERIOD;
+	ptlv_beacon_pd->header.len = sizeof(MrvlIEtypes_beacon_period_t)
+		- sizeof(MrvlIEtypesHeader_t);
+
+	ptlv_dtim_pd = (MrvlIEtypes_dtim_period_t *)(tlv_buffer
+						     +
+						     sizeof
+						     (MrvlIEtypes_beacon_period_t));
+	ptlv_dtim_pd->header.type = TLV_TYPE_UAP_DTIM_PERIOD;
+	ptlv_dtim_pd->header.len = sizeof(MrvlIEtypes_dtim_period_t)
+		- sizeof(MrvlIEtypesHeader_t);
+
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, tlv_buffer);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get deauth control.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_uap_snmp_mib_ctrl_deauth(IN pmlan_adapter pmadapter,
+			      IN 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_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)
+	mlan_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_OPER_CTRL)
+			status = wlan_uap_bss_ioctl_uap_oper_ctrl(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(pmadapter, &pget_info->param.fw_info.mac_addr,
+			       pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
+			pget_info->param.fw_info.fw_ver =
+				pmadapter->fw_release_number;
+			pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+			pget_info->param.fw_info.ecsa_enable =
+				pmadapter->ecsa_enable;
+			pget_info->param.fw_info.getlog_enable =
+				pmadapter->getlog_enable;
+			pget_info->param.fw_info.hw_dev_mcs_support =
+				pmadapter->hw_dev_mcs_support;
+			pget_info->param.fw_info.hw_dot_11n_dev_cap =
+				pmadapter->hw_dot_11n_dev_cap;
+			pget_info->param.fw_info.usr_dev_mcs_support =
+				pmpriv->usr_dev_mcs_support;
+			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.region_code =
+				pmadapter->region_code;
+			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);
+		if (misc->sub_command == MLAN_OID_MISC_MULTI_CHAN_CFG)
+			status = wlan_misc_ioctl_multi_chan_config(pmadapter,
+								   pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_MULTI_CHAN_POLICY)
+			status = wlan_misc_ioctl_multi_chan_policy(pmadapter,
+								   pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_DRCS_CFG)
+			status = wlan_misc_ioctl_drcs_config(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_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_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_NET_MONITOR)
+			status = wlan_misc_ioctl_net_monitor(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_ROBUSTCOEX)
+			status = wlan_misc_robustcoex(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);
+#ifdef STA_SUPPORT
+		if (misc->sub_command == MLAN_OID_MISC_ACS)
+			status = wlan_misc_acs(pmadapter, pioctl_req);
+#endif
+		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);
+		if (pm->sub_command == MLAN_OID_PM_CFG_FW_WAKEUP_METHOD)
+			status = wlan_fw_wakeup_method(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 defined(DFS_TESTING_SUPPORT)
+		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);
+#endif
+		if (cfg11h->sub_command == MLAN_OID_11H_CHAN_REPORT_REQUEST)
+			status = wlan_11h_ioctl_dfs_cancel_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);
+		break;
+	case MLAN_IOCTL_RADIO_CFG:
+		radiocfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+		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);
+		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_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;
+		status = MLAN_ERROR_IOCTL_INVALID;
+		break;
+	}
+	LEAVE();
+	return status;
+}
diff --git a/wlan_sd8897/mlan/mlan_uap_txrx.c b/wlan_sd8897/mlan/mlan_uap_txrx.c
new file mode 100644
index 0000000..d1f1599
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_uap_txrx.c
@@ -0,0 +1,705 @@
+/** @file mlan_uap_txrx.c
+ *
+ *  @brief This file contains AP mode transmit and receive functions
+ *
+ *  Copyright (C) 2009-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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_sdio.h"
+#include "mlan_wmm.h"
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+			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
+	UapRxPD *prx_pd;
+	ENTER();
+	prx_pd = (UapRxPD *)(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(UapRxPD), 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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	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(IN t_void *priv, IN pmlan_buffer pmbuf)
+{
+	pmlan_private pmpriv = (pmlan_private)priv;
+	UapTxPD *plocal_tx_pd;
+	t_u8 *head_ptr = MNULL;
+	t_u32 pkt_type;
+	t_u32 tx_control;
+
+	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(pmpriv->adapter, &pkt_type,
+		       pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type));
+		memcpy(pmpriv->adapter, &tx_control,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+		       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(UapTxPD) + pmpriv->intf_hr_len +
+				  DMA_ALIGNMENT)) {
+		PRINTM(MERROR,
+		       "not enough space for UapTxPD: headroom=%d pkt_len=%d, required=%d\n",
+		       pmbuf->data_offset, pmbuf->data_len,
+		       sizeof(UapTxPD) + 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(UapTxPD) -
+		pmpriv->intf_hr_len;
+	head_ptr = (t_u8 *)((t_ptr)head_ptr & ~((t_ptr)(DMA_ALIGNMENT - 1)));
+
+	plocal_tx_pd = (UapTxPD *)(head_ptr + pmpriv->intf_hr_len);
+	memset(pmpriv->adapter, plocal_tx_pd, 0, sizeof(UapTxPD));
+
+	/* 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;
+	}
+
+	uap_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(IN t_void *adapter, IN pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	UapRxPD *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;
+	t_u8 adj_rx_rate = 0;
+	t_u8 antenna = 0;
+	rxpd_extra_info *pextra_info = MNULL;
+
+	ENTER();
+
+	prx_pd = (UapRxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	/* Endian conversion */
+	uap_endian_convert_RxPD(prx_pd);
+	priv->rxpd_rate = prx_pd->rx_rate;
+	if (prx_pd->flags & RXPD_FLAG_EXTRA_HEADER) {
+		pextra_info =
+			(rxpd_extra_info *) ((t_u8 *)prx_pd + sizeof(*prx_pd));
+		endian_convert_RxPD_extra_header(pextra_info);
+	}
+
+	priv->rxpd_rate_info = prx_pd->rate_info;
+	if (!priv->adapter->psdio_device->v15_fw_api)
+		priv->rxpd_rate_info =
+			wlan_convert_v14_rate_ht_info(priv->rxpd_rate_info);
+
+	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);
+	}
+
+	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;
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		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);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		goto done;
+	}
+
+	pmbuf->priority = prx_pd->priority;
+	memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+	       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;
+	}
+	/* 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)) {
+		wlan_free_mlan_buffer(pmadapter, 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_uap_recv_packet(IN mlan_private *priv, IN 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(UapTxPD) + 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(pmadapter,
+				       (t_u8 *)newbuf->pbuf +
+				       newbuf->data_offset,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pmbuf->data_len);
+				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(UapTxPD) + 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(pmadapter,
+				       (t_u8 *)newbuf->pbuf +
+				       newbuf->data_offset,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pmbuf->data_len);
+				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(IN mlan_private *priv, IN pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	UapRxPD *prx_pd;
+	RxPacketHdr_t *prx_pkt;
+	pmlan_buffer newbuf = MNULL;
+
+	ENTER();
+
+	prx_pd = (UapRxPD *)(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(UapRxPD), 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));
+
+	if (pmadapter->enable_net_mon) {
+		/* set netmon flag only for a sniffed pkt */
+		if (prx_pd->rx_pkt_type == PKT_TYPE_802DOT11) {
+			pmbuf->flags |= MLAN_BUF_FLAG_NET_MONITOR;
+			goto upload;
+		}
+	}
+
+	/* 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(UapTxPD) + 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(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);
+				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 */
+			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;
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+			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);
+	if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
+		//Use some rxpd space to save rxpd info for radiotap header
+		//We should insure radiotap_info is not bigger than RxPD
+		wlan_rxpdinfo_to_radiotapinfo(priv, (RxPD *)prx_pd,
+					      (radiotap_info *) (pmbuf->pbuf +
+								 pmbuf->
+								 data_offset -
+								 sizeof
+								 (radiotap_info)));
+	}
+
+	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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+done:
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8897/mlan/mlan_util.h b/wlan_sd8897/mlan/mlan_util.h
new file mode 100644
index 0000000..baa9919
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_util.h
@@ -0,0 +1,537 @@
+/** @file mlan_util.h
+ *
+ *  @brief This file contains wrappers for linked-list,
+ *  spinlock and timer defines.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    10/28/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_UTIL_H_
+#define _MLAN_UTIL_H_
+
+/** Circular doubly linked list */
+typedef struct _mlan_linked_list {
+    /** Pointer to previous node */
+	struct _mlan_linked_list *pprev;
+    /** Pointer to next node */
+	struct _mlan_linked_list *pnext;
+} mlan_linked_list, *pmlan_linked_list;
+
+/** List head */
+typedef struct _mlan_list_head {
+    /** Pointer to previous node */
+	struct _mlan_linked_list *pprev;
+    /** Pointer to next node */
+	struct _mlan_linked_list *pnext;
+    /** Pointer to lock */
+	t_void *plock;
+} mlan_list_head, *pmlan_list_head;
+
+/**
+ *  @brief This function initializes a list without locking
+ *
+ *  @param phead		List head
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_init_list(pmlan_linked_list phead)
+{
+	/* Both next and prev point to self */
+	phead->pprev = phead->pnext = (pmlan_linked_list)phead;
+}
+
+/**
+ *  @brief This function initializes a list
+ *
+ *  @param phead		List head
+ *  @param lock_required	A flag for spinlock requirement
+ *  @param moal_init_lock	A pointer to init lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_init_list_head(t_void *pmoal_handle,
+		    pmlan_list_head phead,
+		    t_u8 lock_required,
+		    mlan_status (*moal_init_lock) (t_void *handle,
+						   t_void **pplock))
+{
+	/* Both next and prev point to self */
+	util_init_list((pmlan_linked_list)phead);
+	if (lock_required)
+		moal_init_lock(pmoal_handle, &phead->plock);
+	else
+		phead->plock = 0;
+}
+
+/**
+ *  @brief This function frees a list
+ *
+ *  @param phead		List head
+ *  @param moal_free_lock	A pointer to free lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_free_list_head(t_void *pmoal_handle,
+		    pmlan_list_head phead,
+		    mlan_status (*moal_free_lock) (t_void *handle,
+						   t_void *plock))
+{
+	phead->pprev = phead->pnext = 0;
+	if (phead->plock)
+		moal_free_lock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function peeks into a list
+ *
+ *  @param phead		List head
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			List node
+ */
+static INLINE pmlan_linked_list
+util_peek_list(t_void *pmoal_handle,
+	       pmlan_list_head phead,
+	       mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+	       mlan_status (*moal_spin_unlock) (t_void *handle, t_void *plock))
+{
+	pmlan_linked_list pnode = 0;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	if (phead->pnext != (pmlan_linked_list)phead)
+		pnode = phead->pnext;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+	return pnode;
+}
+
+/**
+ *  @brief This function queues a node at the list tail
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to queue
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_enqueue_list_tail(t_void *pmoal_handle,
+		       pmlan_list_head phead,
+		       pmlan_linked_list pnode,
+		       mlan_status (*moal_spin_lock) (t_void *handle,
+						      t_void *plock),
+		       mlan_status (*moal_spin_unlock) (t_void *handle,
+							t_void *plock))
+{
+	pmlan_linked_list pold_last;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pold_last = phead->pprev;
+	pnode->pprev = pold_last;
+	pnode->pnext = (pmlan_linked_list)phead;
+
+	phead->pprev = pold_last->pnext = pnode;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function adds a node at the list head
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to add
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_enqueue_list_head(t_void *pmoal_handle,
+		       pmlan_list_head phead,
+		       pmlan_linked_list pnode,
+		       mlan_status (*moal_spin_lock) (t_void *handle,
+						      t_void *plock),
+		       mlan_status (*moal_spin_unlock) (t_void *handle,
+							t_void *plock))
+{
+	pmlan_linked_list pold_first;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pold_first = phead->pnext;
+	pnode->pprev = (pmlan_linked_list)phead;
+	pnode->pnext = pold_first;
+
+	phead->pnext = pold_first->pprev = pnode;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function removes a node from the list
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to remove
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_unlink_list(t_void *pmoal_handle,
+		 pmlan_list_head phead,
+		 pmlan_linked_list pnode,
+		 mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		 mlan_status (*moal_spin_unlock) (t_void *handle,
+						  t_void *plock))
+{
+	pmlan_linked_list pmy_prev;
+	pmlan_linked_list pmy_next;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pmy_prev = pnode->pprev;
+	pmy_next = pnode->pnext;
+	pmy_next->pprev = pmy_prev;
+	pmy_prev->pnext = pmy_next;
+
+	pnode->pnext = pnode->pprev = 0;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function dequeues a node from the list
+ *
+ *  @param phead		List head
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			List node
+ */
+static INLINE pmlan_linked_list
+util_dequeue_list(t_void *pmoal_handle,
+		  pmlan_list_head phead,
+		  mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		  mlan_status (*moal_spin_unlock) (t_void *handle,
+						   t_void *plock))
+{
+	pmlan_linked_list pnode;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pnode = phead->pnext;
+	if (pnode && (pnode != (pmlan_linked_list)phead))
+		util_unlink_list(pmoal_handle, phead, pnode, 0, 0);
+	else
+		pnode = 0;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+	return pnode;
+}
+
+/** Access controlled scalar variable */
+typedef struct _mlan_scalar {
+    /** Value */
+	t_s32 value;
+    /** Pointer to lock */
+	t_void *plock;
+    /** Control flags */
+	t_u32 flags;
+} mlan_scalar, *pmlan_scalar;
+
+/** Flag to scalar lock acquired */
+#define MLAN_SCALAR_FLAG_UNIQUE_LOCK	MBIT(16)
+
+/** scalar conditional value list */
+typedef enum _MLAN_SCALAR_CONDITIONAL {
+	MLAN_SCALAR_COND_EQUAL,
+	MLAN_SCALAR_COND_NOT_EQUAL,
+	MLAN_SCALAR_COND_GREATER_THAN,
+	MLAN_SCALAR_COND_GREATER_OR_EQUAL,
+	MLAN_SCALAR_COND_LESS_THAN,
+	MLAN_SCALAR_COND_LESS_OR_EQUAL
+} MLAN_SCALAR_CONDITIONAL;
+
+/**
+ *  @brief This function initializes a scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param val				Initial scalar value
+ *  @param plock_to_use		A new lock is created if NULL, else lock to use
+ *  @param moal_init_lock	A pointer to init lock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_init(t_void *pmoal_handle,
+		 pmlan_scalar pscalar,
+		 t_s32 val,
+		 t_void *plock_to_use,
+		 mlan_status (*moal_init_lock) (t_void *handle,
+						t_void **pplock))
+{
+	pscalar->value = val;
+	pscalar->flags = 0;
+	if (plock_to_use) {
+		pscalar->flags &= ~MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+		pscalar->plock = plock_to_use;
+	} else {
+		pscalar->flags |= MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+		moal_init_lock(pmoal_handle, &pscalar->plock);
+	}
+}
+
+/**
+ *  @brief This function frees a scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_free_lock	A pointer to free lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_scalar_free(t_void *pmoal_handle,
+		 pmlan_scalar pscalar,
+		 mlan_status (*moal_free_lock) (t_void *handle, t_void *plock))
+{
+	if (pscalar->flags & MLAN_SCALAR_FLAG_UNIQUE_LOCK)
+		moal_free_lock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function reads value from scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					Stored value
+ */
+static INLINE t_s32
+util_scalar_read(t_void *pmoal_handle,
+		 pmlan_scalar pscalar,
+		 mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		 mlan_status (*moal_spin_unlock) (t_void *handle,
+						  t_void *plock))
+{
+	t_s32 val;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	val = pscalar->value;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+	return val;
+}
+
+/**
+ *  @brief This function writes value to scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param val				Value to write
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_write(t_void *pmoal_handle,
+		  pmlan_scalar pscalar,
+		  t_s32 val,
+		  mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		  mlan_status (*moal_spin_unlock) (t_void *handle,
+						   t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value = val;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function increments the value in scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_increment(t_void *pmoal_handle,
+		      pmlan_scalar pscalar,
+		      mlan_status (*moal_spin_lock) (t_void *handle,
+						     t_void *plock),
+		      mlan_status (*moal_spin_unlock) (t_void *handle,
+						       t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value++;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function decrements the value in scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_decrement(t_void *pmoal_handle,
+		      pmlan_scalar pscalar,
+		      mlan_status (*moal_spin_lock) (t_void *handle,
+						     t_void *plock),
+		      mlan_status (*moal_spin_unlock) (t_void *handle,
+						       t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value--;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function adds an offset to the value in scalar,
+ *         and returns the new value
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param offset			Offset value (can be negative)
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					Value after offset
+ */
+static INLINE t_s32
+util_scalar_offset(t_void *pmoal_handle,
+		   pmlan_scalar pscalar,
+		   t_s32 offset,
+		   mlan_status (*moal_spin_lock) (t_void *handle,
+						  t_void *plock),
+		   mlan_status (*moal_spin_unlock) (t_void *handle,
+						    t_void *plock))
+{
+	t_s32 newval;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	newval = (pscalar->value += offset);
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+	return newval;
+}
+
+/**
+ *  @brief This function writes the value to the scalar
+ *         if existing value compared with other value is true.
+ *
+ *  @param pscalar          Pointer to scalar
+ *  @param condition        Condition to check
+ *  @param val_compare      Value to compare against current value
+ *                          ((A X B), where B = val_compare)
+ *  @param val_to_set       Value to set if comparison is true
+ *  @param moal_spin_lock   A pointer to spin lock handler
+ *  @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ *  @return                 Comparison result (MTRUE or MFALSE)
+ */
+static INLINE t_u8
+util_scalar_conditional_write(t_void *pmoal_handle,
+			      pmlan_scalar pscalar,
+			      MLAN_SCALAR_CONDITIONAL condition,
+			      t_s32 val_compare,
+			      t_s32 val_to_set,
+			      mlan_status (*moal_spin_lock) (t_void *handle,
+							     t_void *plock),
+			      mlan_status (*moal_spin_unlock) (t_void *handle,
+							       t_void *plock))
+{
+	t_u8 update;
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+
+	switch (condition) {
+	case MLAN_SCALAR_COND_EQUAL:
+		update = (pscalar->value == val_compare);
+		break;
+	case MLAN_SCALAR_COND_NOT_EQUAL:
+		update = (pscalar->value != val_compare);
+		break;
+	case MLAN_SCALAR_COND_GREATER_THAN:
+		update = (pscalar->value > val_compare);
+		break;
+	case MLAN_SCALAR_COND_GREATER_OR_EQUAL:
+		update = (pscalar->value >= val_compare);
+		break;
+	case MLAN_SCALAR_COND_LESS_THAN:
+		update = (pscalar->value < val_compare);
+		break;
+	case MLAN_SCALAR_COND_LESS_OR_EQUAL:
+		update = (pscalar->value <= val_compare);
+		break;
+	default:
+		update = MFALSE;
+		break;
+	}
+	if (update)
+		pscalar->value = val_to_set;
+
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+	return (update) ? MTRUE : MFALSE;
+}
+
+/**
+ *  @brief This function counts the bits of unsigned int number
+ *
+ *  @param num  number
+ *  @return     number of bits
+ */
+static INLINE t_u32
+bitcount(t_u32 num)
+{
+	t_u32 count = 0;
+	static t_u32 nibblebits[] = {
+		0, 1, 1, 2, 1, 2, 2, 3,
+		1, 2, 2, 3, 2, 3, 3, 4
+	};
+	for (; num != 0; num >>= 4)
+		count += nibblebits[num & 0x0f];
+	return count;
+}
+
+#endif /* !_MLAN_UTIL_H_ */
diff --git a/wlan_sd8897/mlan/mlan_wmm.c b/wlan_sd8897/mlan/mlan_wmm.c
new file mode 100644
index 0000000..e2ff387
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_wmm.c
@@ -0,0 +1,3757 @@
+/** @file mlan_wmm.c
+ *
+ *  @brief This file contains functions for WMM.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/** Maximum value FW can accept for driver delay in packet transmission */
+#define DRV_PKT_DELAY_TO_FW_MAX   512
+
+/*
+ * Upper and Lower threshold for packet queuing in the driver
+
+ *    - When the number of packets queued reaches the upper limit,
+ *      the driver will stop the net queue in the app/kernel space.
+
+ *    - When the number of packets drops beneath the lower limit after
+ *      having reached the upper limit, the driver will restart the net
+ *      queue.
+ */
+
+/** Lower threshold for packet queuing in the driver.
+  * When the number of packets drops beneath the lower limit after having
+  * reached the upper limit, the driver will restart the net queue.
+  */
+#define WMM_QUEUED_PACKET_LOWER_LIMIT   180
+
+/** Upper threshold for packet queuing in the driver.
+  * When the number of packets queued reaches the upper limit, the driver
+  * will stop the net queue in the app/kernel space.
+  */
+#define WMM_QUEUED_PACKET_UPPER_LIMIT   200
+
+/** Offset for TOS field in the IP header */
+#define IPTOS_OFFSET 5
+
+/** WMM information IE */
+static const t_u8 wmm_info_ie[] = { WMM_IE, 0x07,
+	0x00, 0x50, 0xf2, 0x02,
+	0x00, 0x01, 0x00
+};
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _wmm_ac_e {
+	AC_BE,
+	AC_BK,
+	AC_VI,
+	AC_VO
+} MLAN_PACK_END wmm_ac_e;
+
+/**
+ * AC Priorities go from AC_BK to AC_VO.  The ACI enumeration for AC_BK (1)
+ *   is higher than the enumeration for AC_BE (0); hence the needed
+ *   mapping conversion for wmm AC to priority Queue Index
+ */
+static const t_u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE,
+	WMM_AC_BK,
+	WMM_AC_VI,
+	WMM_AC_VO
+};
+
+/**
+ * This table will be used to store the tid values based on ACs.
+ * It is initialized to default values per TID.
+ */
+t_u8 tos_to_tid[] = {
+	/* TID        DSCP_P2   DSCP_P1  DSCP_P0   WMM_AC   */
+	0x01,			/*    0         1        0       AC_BK   */
+	0x02,			/*    0         0        0       AC_BK   */
+	0x00,			/*    0         0        1       AC_BE   */
+	0x03,			/*    0         1        1       AC_BE   */
+	0x04,			/*    1         0        0       AC_VI   */
+	0x05,			/*    1         0        1       AC_VI   */
+	0x06,			/*    1         1        0       AC_VO   */
+	0x07			/*    1         1        1       AC_VO   */
+};
+
+/**
+ * This table inverses the tos_to_tid operation to get a priority
+ * which is in sequential order, and can be compared.
+ * Use this to compare the priority of two different TIDs.
+ */
+t_u8 tos_to_tid_inv[] = { 0x02,	/* from tos_to_tid[2] = 0 */
+	0x00,			/* from tos_to_tid[0] = 1 */
+	0x01,			/* from tos_to_tid[1] = 2 */
+	0x03,
+	0x04,
+	0x05,
+	0x06,
+	0x07
+};
+
+/**
+ * This table will provide the tid value for given ac. This table does not
+ * change and will be used to copy back the default values to tos_to_tid in
+ * case of disconnect.
+ */
+const t_u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} };
+
+/* Map of TOS UP values to WMM AC */
+static const mlan_wmm_ac_e tos_to_ac[] = { WMM_AC_BE,
+	WMM_AC_BK,
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VI,
+	WMM_AC_VO,
+	WMM_AC_VO
+};
+
+raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid,
+				    t_u8 *ra_addr);
+
+/********************************************************
+			Local Functions
+********************************************************/
+#ifdef DEBUG_LEVEL2
+/**
+ *  @brief Debug print function to display the priority parameters for a WMM AC
+ *
+ *  @param pac_param	Pointer to the AC parameters to display
+ *
+ *  @return		N/A
+ */
+static void
+wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t *pac_param)
+{
+	const char *ac_str[] = { "BK", "BE", "VI", "VO" };
+
+	ENTER();
+
+	PRINTM(MINFO, "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
+	       "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
+	       ac_str[wmm_aci_to_qidx_map[pac_param->aci_aifsn.aci]],
+	       pac_param->aci_aifsn.aci, pac_param->aci_aifsn.acm,
+	       pac_param->aci_aifsn.aifsn, pac_param->ecw.ecw_min,
+	       pac_param->ecw.ecw_max,
+	       wlan_le16_to_cpu(pac_param->tx_op_limit));
+
+	LEAVE();
+}
+
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param) wlan_wmm_ac_debug_print(pac_param)
+#else
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param)
+#endif
+
+/**
+ *  @brief Allocate route address
+ *
+ *  @param pmadapter       Pointer to the mlan_adapter structure
+ *  @param ra              Pointer to the route address
+ *
+ *  @return         ra_list
+ */
+static
+raListTbl *
+wlan_wmm_allocate_ralist_node(pmlan_adapter pmadapter, t_u8 *ra)
+{
+	raListTbl *ra_list = MNULL;
+
+	ENTER();
+
+	if (pmadapter->callbacks.
+	    moal_malloc(pmadapter->pmoal_handle, sizeof(raListTbl),
+			MLAN_MEM_DEF, (t_u8 **)&ra_list)) {
+		PRINTM(MERROR, "Fail to allocate ra_list\n");
+		goto done;
+	}
+	util_init_list((pmlan_linked_list)ra_list);
+	util_init_list_head((t_void *)pmadapter->pmoal_handle,
+			    &ra_list->buf_head, MFALSE,
+			    pmadapter->callbacks.moal_init_lock);
+
+	memcpy(pmadapter, ra_list->ra, ra, 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;
+#if defined(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;
+	}
+#if defined(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(MDATA, "Drop packets to unknown station\n");
+			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(priv->adapter, pout_buf, (t_u8 *)"TSPEC:", 6);
+	pout_buf += 6;
+
+	memcpy(priv->adapter, pout_buf, (t_u8 *)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(priv->adapter, pout_buf, (t_u8 *)"]:TID", 5);
+	pout_buf += 5;
+	*pout_buf++ = tid + '0';
+
+	memcpy(priv->adapter, pout_buf, (t_u8 *)":UP", 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 = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf,
+					     &tx_param);
+		switch (ret) {
+		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:
+			pmadapter->data_sent = MFALSE;
+			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;
+
+	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->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           N/A
+ */
+t_void
+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();
+}
+
+#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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       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);
+			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
+#define BA_SETUP_PACKET_OFFSET          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) +
+		BA_SETUP_PACKET_OFFSET;
+	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);
+	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(pmadapter, tos_to_tid, ac_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;
+#if defined(UAP_SUPPORT)
+	priv->num_drop_pkts = 0;
+#endif
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	memset(pmadapter, pmadapter->mpa_tx_count, 0,
+	       sizeof(pmadapter->mpa_tx_count));
+	pmadapter->mpa_sent_no_ports = 0;
+	pmadapter->mpa_sent_last_pkt = 0;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	memset(pmadapter, pmadapter->mpa_rx_count, 0,
+	       sizeof(pmadapter->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 =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_sta_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 =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_wfd_txrxwinsize;
+				priv->add_ba_param.rx_win_size =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_wfd_txrxwinsize;
+			}
+#endif
+			if (priv->bss_type == MLAN_BSS_TYPE_NAN) {
+				priv->add_ba_param.tx_win_size =
+					MLAN_NAN_AMPDU_DEF_TXRXWINSIZE;
+				priv->add_ba_param.rx_win_size =
+					MLAN_NAN_AMPDU_DEF_TXRXWINSIZE;
+			}
+#ifdef UAP_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+				priv->add_ba_param.tx_win_size =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_uap_txwinsize;
+				priv->add_ba_param.rx_win_size =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_uap_rxwinsize;
+			}
+#endif
+			priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
+			priv->add_ba_param.tx_amsdu = MTRUE;
+			priv->add_ba_param.rx_amsdu = MTRUE;
+			memset(priv->adapter, priv->rx_seq, 0xff,
+			       sizeof(priv->rx_seq));
+			wlan_wmm_default_queue_priorities(priv);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Setup the queue priorities and downgrade any queues as required
+ *         by the WMM info.  Setups default values if WMM is not active
+ *         for this association.
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         N/A
+ */
+void
+wlan_wmm_setup_queues(pmlan_private priv)
+{
+	ENTER();
+	wlan_wmm_setup_queue_priorities(priv, MNULL);
+	wlan_wmm_setup_ac_downgrade(priv);
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief  Send a command to firmware to retrieve the current WMM status
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         MLAN_STATUS_SUCCESS; MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_wmm_status_change(pmlan_private priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, 0, 0, 0,
+			       MNULL);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Check if wmm TX queue is empty
+ *
+ *  @param pmadapter  Pointer to the mlan_adapter driver data struct
+ *
+ *  @return         MFALSE if not empty; MTRUE if empty
+ */
+int
+wlan_wmm_lists_empty(pmlan_adapter pmadapter)
+{
+	int j;
+	pmlan_private priv;
+
+	ENTER();
+
+	for (j = 0; j < pmadapter->priv_num; ++j) {
+		priv = pmadapter->priv[j];
+		if (priv) {
+			if ((priv->port_ctrl_mode == MTRUE) &&
+			    (priv->port_open == MFALSE)) {
+				PRINTM(MINFO,
+				       "wmm_lists_empty: PORT_CLOSED Ignore pkts from BSS%d\n",
+				       j);
+				continue;
+			}
+			if (priv->tx_pause)
+				continue;
+
+			if (util_scalar_read(pmadapter->pmoal_handle,
+					     &priv->wmm.tx_pkts_queued,
+					     pmadapter->callbacks.
+					     moal_spin_lock,
+					     pmadapter->callbacks.
+					     moal_spin_unlock)) {
+				LEAVE();
+				return MFALSE;
+			}
+		}
+	}
+
+	LEAVE();
+	return MTRUE;
+}
+
+/**
+ *   @brief Get ralist node
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param tid      TID
+ *   @param ra_addr  Pointer to the route address
+ *
+ *   @return         ra_list or MNULL
+ */
+raListTbl *
+wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 *ra_addr)
+{
+	raListTbl *ra_list;
+	ENTER();
+	ra_list =
+		(raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					    &priv->wmm.tid_tbl_ptr[tid].ra_list,
+					    MNULL, MNULL);
+	while (ra_list && (ra_list != (raListTbl *)
+			   &priv->wmm.tid_tbl_ptr[tid].ra_list)) {
+		if (!memcmp
+		    (priv->adapter, ra_list->ra, ra_addr,
+		     MLAN_MAC_ADDR_LENGTH)) {
+			LEAVE();
+			return ra_list;
+		}
+		ra_list = ra_list->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *   @brief Check if RA list is valid or not
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param ra_list  Pointer to raListTbl
+ *   @param ptrindex TID pointer index
+ *
+ *   @return         MTRUE- valid. MFALSE- invalid.
+ */
+int
+wlan_is_ralist_valid(mlan_private *priv, raListTbl *ra_list, int ptrindex)
+{
+	raListTbl *rlist;
+
+	ENTER();
+
+	rlist = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					    &priv->wmm.tid_tbl_ptr[ptrindex].
+					    ra_list, MNULL, MNULL);
+
+	while (rlist && (rlist != (raListTbl *)
+			 &priv->wmm.tid_tbl_ptr[ptrindex].ra_list)) {
+		if (rlist == ra_list) {
+			LEAVE();
+			return MTRUE;
+		}
+
+		rlist = rlist->pnext;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief  Update an existing raList with a new RA and 11n capability
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *  @param old_ra   Old receiver address
+ *  @param new_ra   New receiver address
+ *
+ *  @return         integer count of updated nodes
+ */
+int
+wlan_ralist_update(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra)
+{
+	t_u8 tid;
+	int update_count;
+	raListTbl *ra_list;
+
+	ENTER();
+
+	update_count = 0;
+
+	for (tid = 0; tid < MAX_NUM_TID; ++tid) {
+
+		ra_list = wlan_wmm_get_ralist_node(priv, tid, old_ra);
+
+		if (ra_list) {
+			update_count++;
+
+			if (queuing_ra_based(priv))
+				ra_list->is_11n_enabled =
+					wlan_is_11n_enabled(priv, new_ra);
+			else
+				ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+			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(priv->adapter, ra_list->ra, new_ra,
+			       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;
+#if defined(UAP_SUPPORT)
+	sta_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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       MLAN_MAC_ADDR_LENGTH);
+	/** put multicast/broadcast packet in the same ralist */
+		if (ra[0] & 0x01)
+			memset(pmadapter, ra, 0xff, sizeof(ra));
+#if defined(UAP_SUPPORT)
+		else if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			sta_ptr = wlan_get_station_entry(priv, ra);
+			if (sta_ptr) {
+				if (!sta_ptr->is_wmm_enabled
+				    && !priv->is_11ac_enabled) {
+					tid_down =
+						wlan_wmm_downgrade_tid(priv,
+								       0xff);
+				}
+			}
+		}
+#endif
+		ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, ra);
+	}
+
+	if (!ra_list) {
+		PRINTM_NETINTF(MWARN, priv);
+		PRINTM(MWARN,
+		       "Drop packet %p, ra_list=%p, media_connected=%d\n",
+		       pmbuf, ra_list, priv->media_connected);
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+		LEAVE();
+		return;
+	}
+
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA,
+	       "Adding pkt %p (priority=%d, tid_down=%d) to ra_list %p\n",
+	       pmbuf, pmbuf->priority, tid_down, ra_list);
+	util_enqueue_list_tail(pmadapter->pmoal_handle, &ra_list->buf_head,
+			       (pmlan_linked_list)pmbuf, MNULL, MNULL);
+
+	ra_list->total_pkts++;
+	ra_list->packet_count++;
+
+	priv->wmm.pkts_queued[tid_down]++;
+	if (ra_list->tx_pause) {
+		priv->wmm.pkts_paused[tid_down]++;
+	} else {
+		util_scalar_increment(pmadapter->pmoal_handle,
+				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+		/* if highest_queued_prio < prio(tid_down), set it to prio(tid_down) */
+		util_scalar_conditional_write(pmadapter->pmoal_handle,
+					      &priv->wmm.highest_queued_prio,
+					      MLAN_SCALAR_COND_LESS_THAN,
+					      tos_to_tid_inv[tid_down],
+					      tos_to_tid_inv[tid_down],
+					      MNULL, MNULL);
+	}
+	/* Record the current time the packet was queued; used to determine
+	 *   the amount of time the packet was queued in the driver before it
+	 *   was sent to the firmware.  The delay is then sent along with the
+	 *   packet to the firmware for aggregate delay calculation for stats
+	 *   and MSDU lifetime expiry.
+	 */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmbuf->in_ts_sec,
+						  &pmbuf->in_ts_usec);
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Process the GET_WMM_STATUS command response from firmware
+ *
+ *  The GET_WMM_STATUS response may contain multiple TLVs for:
+ *      - AC Queue status TLVs
+ *      - Current WMM Parameter IE TLV
+ *      - Admission Control action frame TLVs
+ *
+ *  This function parses the TLVs and then calls further functions
+ *   to process any changes in the queue prioritize or state.
+ *
+ *  @param priv      Pointer to the mlan_private driver data struct
+ *  @param ptlv      Pointer to the tlv block returned in the response.
+ *  @param resp_len  Length of TLV block
+ *
+ *  @return MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_get_status(pmlan_private priv, t_u8 *ptlv, int resp_len)
+{
+	t_u8 *pcurrent = ptlv;
+	t_u32 tlv_len;
+	t_u8 send_wmm_event;
+	MrvlIEtypes_Data_t *ptlv_hdr;
+	MrvlIEtypes_WmmQueueStatus_t *ptlv_wmm_q_status;
+	IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
+	WmmAcStatus_t *pac_status;
+
+	MrvlIETypes_ActionFrame_t *ptlv_action;
+	IEEEtypes_Action_WMM_AddTsRsp_t *padd_ts_rsp;
+	IEEEtypes_Action_WMM_DelTs_t *pdel_ts;
+
+	ENTER();
+
+	send_wmm_event = MFALSE;
+
+	PRINTM(MINFO, "WMM: WMM_GET_STATUS cmdresp received: %d\n", resp_len);
+	HEXDUMP("CMD_RESP: WMM_GET_STATUS", pcurrent, resp_len);
+
+	while (resp_len >= sizeof(ptlv_hdr->header)) {
+		ptlv_hdr = (MrvlIEtypes_Data_t *)pcurrent;
+		tlv_len = wlan_le16_to_cpu(ptlv_hdr->header.len);
+		if ((tlv_len + sizeof(ptlv_hdr->header)) > resp_len) {
+			PRINTM(MERROR,
+			       "WMM get status: Error in processing  TLV buffer\n");
+			resp_len = 0;
+			continue;
+		}
+
+		switch (wlan_le16_to_cpu(ptlv_hdr->header.type)) {
+		case TLV_TYPE_WMMQSTATUS:
+			ptlv_wmm_q_status =
+				(MrvlIEtypes_WmmQueueStatus_t *)ptlv_hdr;
+			PRINTM(MEVENT, "WMM_STATUS: QSTATUS TLV: %d\n",
+			       ptlv_wmm_q_status->queue_index);
+
+			PRINTM(MINFO,
+			       "CMD_RESP: WMM_GET_STATUS: QSTATUS TLV: %d, %d, %d\n",
+			       ptlv_wmm_q_status->queue_index,
+			       ptlv_wmm_q_status->flow_required,
+			       ptlv_wmm_q_status->disabled);
+
+			pac_status =
+				&priv->wmm.ac_status[ptlv_wmm_q_status->
+						     queue_index];
+			pac_status->disabled = ptlv_wmm_q_status->disabled;
+			pac_status->flow_required =
+				ptlv_wmm_q_status->flow_required;
+			pac_status->flow_created =
+				ptlv_wmm_q_status->flow_created;
+			break;
+
+		case TLV_TYPE_VENDOR_SPECIFIC_IE:	/* WMM_IE */
+			/*
+			 * Point the regular IEEE IE 2 bytes into the Marvell 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(priv->adapter,
+			       (t_u8 *)&priv->curr_bss_params.bss_descriptor.
+			       wmm_ie, pwmm_param_ie,
+			       MIN(sizeof(IEEEtypes_WmmParameter_t),
+				   (pwmm_param_ie->vend_hdr.len + 2)));
+			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 Marvell 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(priv->adapter, pwmm_tlv->wmm_ie, &wmm_info_ie[2],
+		       pwmm_tlv->header.len);
+		if (pwmm_ie->qos_info.qos_uapsd)
+			memcpy(priv->adapter,
+			       (t_u8 *)(pwmm_tlv->wmm_ie +
+					pwmm_tlv->header.len -
+					sizeof(priv->wmm_qosinfo)),
+			       &priv->wmm_qosinfo, sizeof(priv->wmm_qosinfo));
+
+		ret_len = sizeof(pwmm_tlv->header) + pwmm_tlv->header.len;
+		pwmm_tlv->header.len = wlan_cpu_to_le16(pwmm_tlv->header.len);
+
+		HEXDUMP("ASSOC_CMD: WMM IE", (t_u8 *)pwmm_tlv, ret_len);
+		*ppassoc_buf += ret_len;
+	}
+
+	LEAVE();
+	return ret_len;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *   @brief Compute the time delay in the driver queues for a given packet.
+ *
+ *   When the packet is received at the OS/Driver interface, the current
+ *     time is set in the packet structure.  The difference between the present
+ *     time and that received time is computed in this function and limited
+ *     based on pre-compiled limits in the driver.
+ *
+ *   @param priv   Ptr to the mlan_private driver data struct
+ *   @param pmbuf  Ptr to the mlan_buffer which has been previously timestamped
+ *
+ *   @return  Time delay of the packet in 2ms units after having limit applied
+ */
+t_u8
+wlan_wmm_compute_driver_packet_delay(pmlan_private priv,
+				     const pmlan_buffer pmbuf)
+{
+	t_u8 ret_val = 0;
+	t_u32 out_ts_sec, out_ts_usec;
+	t_s32 queue_delay;
+
+	ENTER();
+
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &out_ts_sec,
+						      &out_ts_usec);
+
+	queue_delay = (t_s32)(out_ts_sec - pmbuf->in_ts_sec) * 1000;
+	queue_delay += (t_s32)(out_ts_usec - pmbuf->in_ts_usec) / 1000;
+
+	/*
+	 * Queue delay is passed as a uint8 in units of 2ms (ms shifted
+	 *  by 1). Min value (other than 0) is therefore 2ms, max is 510ms.
+	 *
+	 * Pass max value if queue_delay is beyond the uint8 range
+	 */
+	ret_val = (t_u8)(MIN(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1);
+
+	PRINTM(MINFO, "WMM: Pkt Delay: %d ms, %d ms sent to FW\n",
+	       queue_delay, ret_val);
+
+	LEAVE();
+	return ret_val;
+}
+
+/**
+ *  @brief Transmit the highest priority packet awaiting in the WMM Queues
+ *
+ *  @param pmadapter Pointer to the mlan_adapter driver data struct
+ *
+ *  @return        N/A
+ */
+void
+wlan_wmm_process_tx(pmlan_adapter pmadapter)
+{
+	ENTER();
+
+	do {
+		if (wlan_dequeue_tx_packet(pmadapter))
+			break;
+		if (pmadapter->sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) {
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+			wlan_send_mp_aggr_buf(pmadapter);
+#endif
+			break;
+		}
+
+		/* 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(IN pmlan_private pmpriv,
+		       OUT HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter,
+	       pcmd_addts->tspec_data,
+	       paddts->ie_data, MIN(WMM_TSPEC_SIZE, paddts->ie_data_len));
+
+	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(IN pmlan_private pmpriv,
+		       const IN HostCmd_DS_COMMAND *resp,
+		       OUT 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(pmpriv->adapter,
+			       paddts->ie_data,
+			       presp_addts->tspec_data, paddts->ie_data_len);
+		} 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(IN pmlan_private pmpriv,
+		       OUT HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter,
+	       pcmd_delts->tspec_data,
+	       pdelts->ie_data, MIN(WMM_TSPEC_SIZE, pdelts->ie_data_len));
+
+	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(IN pmlan_private pmpriv,
+		       const IN HostCmd_DS_COMMAND *resp,
+		       OUT 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(IN pmlan_private pmpriv,
+			 OUT HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			 const IN HostCmd_DS_COMMAND *resp,
+			 OUT 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(IN pmlan_private pmpriv,
+		       OUT HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, (t_void *)pcmd_ts_status, (t_void *)pts_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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       OUT 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(pmpriv->adapter,
+		       (t_void *)&pwmm->param.ts_status,
+		       (t_void *)presp_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(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_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(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_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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_private pmpriv,
+			  OUT HostCmd_DS_COMMAND *cmd,
+			  IN t_u8 cmd_action, IN 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(pmpriv->adapter, pcmd_cfg->ac_params, ac_params,
+		       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(IN pmlan_private pmpriv,
+			  const IN HostCmd_DS_COMMAND *resp,
+			  OUT 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(pmpriv->adapter, pwmm->param.ac_params, pcfg->ac_params,
+		       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(IN pmlan_private pmpriv,
+			  OUT HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			  const IN HostCmd_DS_COMMAND *resp,
+			  OUT 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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter, IN 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(priv->adapter, plist->ra, ra_list->ra,
+				       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_sd8897/mlan/mlan_wmm.h b/wlan_sd8897/mlan/mlan_wmm.h
new file mode 100644
index 0000000..8cb1a9a
--- /dev/null
+++ b/wlan_sd8897/mlan/mlan_wmm.h
@@ -0,0 +1,241 @@
+/** @file mlan_wmm.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of wmm functionalities
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/****************************************************
+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, raListTbl *ptr)
+{
+	pmlan_buffer mbuf;
+
+	ENTER();
+	mbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+					    &ptr->buf_head, MNULL, MNULL);
+	LEAVE();
+
+	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(IN mlan_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(IN mlan_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(IN pmlan_private pmpriv,
+				      OUT HostCmd_DS_COMMAND *cmd,
+				      IN t_u8 cmd_action, IN t_void *pdata_buf);
+
+/* process wmm_param_config command response */
+mlan_status wlan_ret_wmm_param_config(IN pmlan_private pmpriv,
+				      const IN HostCmd_DS_COMMAND *resp,
+				      OUT 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(IN pmlan_private pmpriv,
+					  OUT HostCmd_DS_COMMAND *cmd,
+					  IN t_void *pdata_buf);
+/** WMM DELTS request command handler */
+extern mlan_status wlan_cmd_wmm_delts_req(IN pmlan_private pmpriv,
+					  OUT HostCmd_DS_COMMAND *cmd,
+					  IN t_void *pdata_buf);
+/** WMM QUEUE_STATS command handler */
+extern mlan_status wlan_cmd_wmm_queue_stats(IN pmlan_private pmpriv,
+					    OUT HostCmd_DS_COMMAND *cmd,
+					    IN t_void *pdata_buf);
+/** WMM TS_STATUS command handler */
+extern mlan_status wlan_cmd_wmm_ts_status(IN pmlan_private pmpriv,
+					  OUT HostCmd_DS_COMMAND *cmd,
+					  IN 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(IN pmlan_private priv,
+					   IN t_u8 *ptlv, IN int resp_len);
+/** WMM ADDTS request command response handler */
+extern mlan_status wlan_ret_wmm_addts_req(IN pmlan_private pmpriv,
+					  const IN HostCmd_DS_COMMAND *resp,
+					  OUT mlan_ioctl_req *pioctl_buf);
+/** WMM DELTS request command response handler */
+extern mlan_status wlan_ret_wmm_delts_req(IN pmlan_private pmpriv,
+					  const IN HostCmd_DS_COMMAND *resp,
+					  OUT mlan_ioctl_req *pioctl_buf);
+/** WMM QUEUE_STATS command response handler */
+extern mlan_status wlan_ret_wmm_queue_stats(IN pmlan_private pmpriv,
+					    const IN HostCmd_DS_COMMAND *resp,
+					    OUT mlan_ioctl_req *pioctl_buf);
+/** WMM TS_STATUS command response handler */
+extern mlan_status wlan_ret_wmm_ts_status(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  OUT mlan_ioctl_req *pioctl_buf);
+#endif /* STA_SUPPORT */
+
+/** WMM QUEUE_CONFIG command handler */
+extern mlan_status wlan_cmd_wmm_queue_config(IN pmlan_private pmpriv,
+					     OUT HostCmd_DS_COMMAND *cmd,
+					     IN t_void *pdata_buf);
+
+/** WMM QUEUE_CONFIG command response handler */
+extern mlan_status wlan_ret_wmm_queue_config(IN pmlan_private pmpriv,
+					     const IN HostCmd_DS_COMMAND *resp,
+					     OUT mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_wmm_cfg_ioctl(IN pmlan_adapter pmadapter,
+			       IN pmlan_ioctl_req pioctl_req);
+#endif /* !_MLAN_WMM_H_ */
diff --git a/wlan_sd8897/mlinux/mlan.h b/wlan_sd8897/mlinux/mlan.h
new file mode 100644
index 0000000..2afcb54
--- /dev/null
+++ b/wlan_sd8897/mlinux/mlan.h
@@ -0,0 +1,35 @@
+/** @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 (C) 2008-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+/******************************************************
+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_sd8897/mlinux/mlan_decl.h b/wlan_sd8897/mlinux/mlan_decl.h
new file mode 100644
index 0000000..da16ed0
--- /dev/null
+++ b/wlan_sd8897/mlinux/mlan_decl.h
@@ -0,0 +1,1725 @@
+/** @file mlan_decl.h
+ *
+ *  @brief This file declares the generic data structures and APIs.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    11/07/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_DECL_H_
+#define _MLAN_DECL_H_
+
+/** MLAN release version */
+#define MLAN_RELEASE_VERSION		 "C534"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef signed char t_s8;
+/** Unsigned char (1-byte) */
+typedef unsigned char t_u8;
+/** Signed short (2-bytes) */
+typedef short t_s16;
+/** Unsigned short (2-bytes) */
+typedef unsigned short t_u16;
+/** Signed long (4-bytes) */
+typedef int t_s32;
+/** Unsigned long (4-bytes) */
+typedef unsigned int t_u32;
+/** Signed long long 8-bytes) */
+typedef long long t_s64;
+/** Unsigned long long 8-bytes) */
+typedef unsigned long long t_u64;
+/** Void pointer (4-bytes) */
+typedef void t_void;
+/** 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)
+
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM         (16)
+
+/** NET IP alignment */
+#define MLAN_NET_IP_ALIGN        2
+
+/** DMA alignment */
+/* SDIO3.0 Inrevium Adapter require 32 bit DMA alignment */
+#define DMA_ALIGNMENT            32
+
+/** max size of TxPD */
+#define MAX_TXPD_SIZE            32
+
+/** Minimum data header length */
+#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT+MAX_TXPD_SIZE)
+
+/** rx data header length */
+#define MLAN_RX_HEADER_LEN       MLAN_MIN_DATA_HEADER_LEN
+
+/** This is current limit on Maximum Tx AMPDU allowed */
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED          16
+#define MLAN_MAX_TX_BASTREAM_DEFAULT            2
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED_NOV15    2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED     16
+
+/** station ampdu tx win size */
+#define MLAN_STA_AMPDU_DEF_TXWINSIZE_NOV15      32
+/** uap ampdu tx win size */
+#define MLAN_UAP_AMPDU_DEF_TXWINSIZE_NOV15      32
+/** uap ampdu rx win size */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE_NOV15      32
+#ifdef WIFI_DIRECT_SUPPORT
+/** wfd ampdu tx/rx win size */
+#define MLAN_WFD_AMPDU_DEF_TXRXWINSIZE_NOV15    32
+#endif
+
+#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       48
+/** Default Win size attached during ADDBA response */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE       32
+/** 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
+
+/** NAN use the same window size for tx/rx */
+#define MLAN_NAN_AMPDU_DEF_TXRXWINSIZE     16
+/** RX winsize for COEX */
+#define MLAN_NAN_COEX_AMPDU_DEF_RXWINSIZE  16
+
+/** 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 7 */
+#define MLAN_RATE_INDEX_MCS7    7
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9    9
+/** 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 */
+#define MLAN_RX_DATA_BUF_SIZE     (4 * 1024)
+/** Size of rx command buffer */
+#define MLAN_RX_CMD_BUF_SIZE      (2 * 1024)
+
+#define MLAN_USB_RX_DATA_BUF_SIZE       MLAN_RX_DATA_BUF_SIZE
+
+/** 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
+
+/** 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           (4 * 1024)
+/** 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)
+/** SDIO MP aggr pkt limit 16*/
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_16	 (16)
+/** max SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX	 (16)
+
+/** SDIO IO Port mask */
+#define MLAN_SDIO_IO_PORT_MASK		0xfffff
+/** SDIO Block/Byte mode mask */
+#define MLAN_SDIO_BYTE_MODE_MASK	0x80000000
+
+/** Max retry number of IO write */
+#define MAX_WRITE_IOMEM_RETRY		2
+
+/** 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)
+
+/** 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 NET_MONITOR */
+#define MLAN_BUF_FLAG_NET_MONITOR        MBIT(11)
+
+/** Buffer flag for NULL data packet */
+#define MLAN_BUF_FLAG_NULL_PKT        MBIT(12)
+
+#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 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,
+	MLAN_STATUS_COMPLETE,
+} 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,
+} mlan_buf_type;
+
+/** 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_NAN = 4,
+	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 bit mask */
+#define BSS_ROLE_BIT_MASK    MBIT(0)
+
+/** Get BSS role */
+#define GET_BSS_ROLE(priv)   ((priv)->bss_role & BSS_ROLE_BIT_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,
+	/* 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_NAN_STARTED = 0x80000024,
+	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;
+
+/** Data Structures */
+/** mlan_image data structure */
+typedef struct _mlan_fw_image {
+    /** Helper image buffer pointer */
+	t_u8 *phelper_buf;
+    /** Helper image length */
+	t_u32 helper_len;
+    /** 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;
+
+#define OID_TYPE_CAL    0x2
+#define OID_TYPE_DPD    0xa
+
+/** 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 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,
+};
+
+/** 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;
+
+/** 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[0];
+} mlan_event, *pmlan_event;
+
+/** 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;
+
+/** mix rate information structure */
+typedef MLAN_PACK_START struct _mix_rate_info {
+    /**  bit0: LGI: gi=0, SGI: gi= 1 */
+    /**  bit1-2: 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3  */
+    /**  bit3-4: LG: format=0, HT: format=1, VHT: format=2 */
+    /**  bit5: LDPC: 0-not support,  1-support */
+    /**  bit6-7:reserved */
+	t_u8 rate_info;
+    /** MCS index */
+	t_u8 mcs_index;
+    /** bitrate, in 500Kbps */
+	t_u16 bitrate;
+} MLAN_PACK_END mix_rate_info, *pmix_rate_info;
+
+/** rxpd extra information structure */
+typedef MLAN_PACK_START struct _rxpd_extra_info {
+    /** flags */
+	t_u8 flags;
+    /** channel.flags */
+	t_u16 channel_flags;
+    /** mcs.known */
+	t_u8 mcs_known;
+    /** mcs.flags */
+	t_u8 mcs_flags;
+} MLAN_PACK_END rxpd_extra_info, *prxpd_extra_info;
+
+/** rdaio tap information structure */
+typedef MLAN_PACK_START struct _radiotap_info {
+    /** Rate Info */
+	mix_rate_info rate_info;
+    /** SNR */
+	t_s8 snr;
+    /** Noise Floor */
+	t_s8 nf;
+    /** band config */
+	t_u8 band_config;
+    /** chan number */
+	t_u8 chan_num;
+    /** antenna */
+	t_u8 antenna;
+    /** extra rxpd info from FW */
+	rxpd_extra_info extra_info;
+} MLAN_PACK_END radiotap_info, *pradiotap_info;
+
+/** 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;
+    /** Offset to data */
+	t_u32 data_offset;
+    /** Data length */
+	t_u32 data_len;
+    /** Buffer type: data, cmd, event etc. */
+	mlan_buf_type buf_type;
+
+    /** Fields below are valid for data packet only */
+    /** QoS priority */
+	t_u32 priority;
+    /** Time stamp when packet is received (seconds) */
+	t_u32 in_ts_sec;
+    /** Time stamp when packet is received (micro seconds) */
+	t_u32 in_ts_usec;
+    /** Time stamp when packet is processed (seconds) */
+	t_u32 out_ts_sec;
+    /** Time stamp when packet is processed (micro seconds) */
+	t_u32 out_ts_usec;
+    /** tx_seq_num */
+	t_u32 tx_seq_num;
+
+    /** Fields below are valid for MLAN module only */
+    /** Pointer to parent mlan_buffer */
+	struct _mlan_buffer *pparent;
+    /** Use count for this buffer */
+	t_u32 use_count;
+} mlan_buffer, *pmlan_buffer;
+
+/** mlan_fw_info data structure */
+typedef struct _mlan_hw_info {
+    /** Firmware capabilities */
+	t_u32 fw_cap;
+} mlan_hw_info, *pmlan_hw_info;
+
+/** mlan_bss_attr data structure */
+typedef struct _mlan_bss_attr {
+    /** BSS type */
+	t_u32 bss_type;
+    /** Data frame type: Ethernet II, 802.11, etc. */
+	t_u32 frame_type;
+    /** The BSS is active (non-0) or not (0). */
+	t_u32 active;
+    /** BSS Priority */
+	t_u32 bss_priority;
+    /** BSS number */
+	t_u32 bss_num;
+    /** The BSS is virtual */
+	t_u32 bss_virtual;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+/** bss tbl data structure */
+typedef struct _mlan_bss_tbl {
+    /** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+} mlan_bss_tbl, *pmlan_bss_tbl;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** Type enumeration for the command result */
+typedef MLAN_PACK_START enum _mlan_cmd_result_e {
+	MLAN_CMD_RESULT_SUCCESS = 0,
+	MLAN_CMD_RESULT_FAILURE = 1,
+	MLAN_CMD_RESULT_TIMEOUT = 2,
+	MLAN_CMD_RESULT_INVALID_DATA = 3
+} MLAN_PACK_END mlan_cmd_result_e;
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} MLAN_PACK_END mlan_wmm_ac_e;
+
+/** Type enumeration for the action field in the Queue Config command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e {
+	MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_config_action_e;
+
+/** Type enumeration for the action field in the queue stats command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e {
+	MLAN_WMM_STATS_ACTION_START = 0,
+	MLAN_WMM_STATS_ACTION_STOP = 1,
+	MLAN_WMM_STATS_ACTION_GET_CLR = 2,
+	MLAN_WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_stats_action_e;
+
+/**
+ *  @brief IOCTL structure for a Traffic stream status.
+ *
+ */
+typedef MLAN_PACK_START struct {
+    /** TSID: Range: 0->7 */
+	t_u8 tid;
+    /** TSID specified is valid */
+	t_u8 valid;
+    /** AC TSID is active on */
+	t_u8 access_category;
+    /** UP specified for the TSID */
+	t_u8 user_priority;
+    /** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 psb;
+    /** Upstream(0), Downlink(1), Bidirectional(3) */
+	t_u8 flow_dir;
+    /** Medium time granted for the TSID */
+	t_u16 medium_time;
+} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t,
+/** Type definition of mlan_ds_wmm_ts_status for MLAN_OID_WMM_CFG_TS_STATUS */
+mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status;
+
+/** Max Ie length */
+#define MAX_IE_SIZE             256
+
+/** custom IE */
+typedef MLAN_PACK_START struct _custom_ie {
+    /** IE Index */
+	t_u16 ie_index;
+    /** Mgmt Subtype Mask */
+	t_u16 mgmt_subtype_mask;
+    /** IE Length */
+	t_u16 ie_length;
+    /** IE buffer */
+	t_u8 ie_buffer[MAX_IE_SIZE];
+} MLAN_PACK_END custom_ie;
+
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW         4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX               26
+
+/** custom IE info */
+typedef MLAN_PACK_START struct _custom_ie_info {
+    /** size of buffer */
+	t_u16 buf_size;
+    /** no of buffers of buf_size */
+	t_u16 buf_count;
+} MLAN_PACK_END custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** No of tuples */
+	t_u16 count;
+    /** custom IE info tuples */
+	custom_ie_info info[MAX_MGMT_IE_INDEX];
+} MLAN_PACK_END tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef MLAN_PACK_START struct _tlvbuf_custom_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** IE data */
+	custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW];
+    /** Max mgmt IE TLV */
+	tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+/** 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[0];
+} 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[0];
+		} 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[0];
+		} 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[0];
+		} 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;
+
+#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 {
+	WIFI_DISCONNECTED = 0,
+	WIFI_AUTHENTICATING = 1,
+	WIFI_ASSOCIATING = 2,
+	WIFI_ASSOCIATED = 3,
+    /** if done by firmware/driver */
+	WIFI_EAPOL_STARTED = 4,
+    /** if done by firmware/driver */
+	WIFI_EAPOL_COMPLETED = 5,
+} wifi_connection_state;
+/** roam state */
+typedef enum {
+	WIFI_ROAMING_IDLE = 0,
+	WIFI_ROAMING_ACTIVE = 1,
+} wifi_roam_state;
+/** interface mode */
+typedef enum {
+	WIFI_INTERFACE_STA = 0,
+	WIFI_INTERFACE_SOFTAP = 1,
+	WIFI_INTERFACE_IBSS = 2,
+	WIFI_INTERFACE_P2P_CLIENT = 3,
+	WIFI_INTERFACE_P2P_GO = 4,
+	WIFI_INTERFACE_NAN = 5,
+	WIFI_INTERFACE_MESH = 6,
+} wifi_interface_mode;
+
+/** set for QOS association */
+#define WIFI_CAPABILITY_QOS          0x00000001
+/** set for protected association (802.11 beacon frame control protected bit set) */
+#define WIFI_CAPABILITY_PROTECTED    0x00000002
+/** set if 802.11 Extended Capabilities element interworking bit is set */
+#define WIFI_CAPABILITY_INTERWORKING 0x00000004
+/** set for HS20 association */
+#define WIFI_CAPABILITY_HS20         0x00000008
+/** set is 802.11 Extended Capabilities element UTF-8 SSID bit is set */
+#define WIFI_CAPABILITY_SSID_UTF8    0x00000010
+/** set is 802.11 Country Element is present */
+#define WIFI_CAPABILITY_COUNTRY      0x00000020
+
+/** link layer status */
+typedef struct {
+    /** interface mode */
+	wifi_interface_mode mode;
+    /** interface mac address (self) */
+	t_u8 mac_addr[6];
+    /** connection state (valid for STA, CLI only) */
+	wifi_connection_state state;
+    /** roaming state */
+	wifi_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];
+} wifi_interface_link_layer_info;
+
+typedef wifi_interface_link_layer_info *wifi_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;
+
+/** 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 */
+	wifi_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) */
+
+#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) (IN t_void *pmoal_handle,
+					 IN t_u32 offset,
+					 IN t_u32 len, OUT t_u8 *pbuf);
+    /** moal_get_hw_spec_complete */
+	mlan_status (*moal_get_hw_spec_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status,
+						  IN mlan_hw_info * phw,
+						  IN pmlan_bss_tbl ptbl);
+    /** moal_init_fw_complete */
+	mlan_status (*moal_init_fw_complete) (IN t_void *pmoal_handle,
+					      IN mlan_status status);
+    /** moal_shutdown_fw_complete */
+	mlan_status (*moal_shutdown_fw_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status);
+    /** moal_send_packet_complete */
+	mlan_status (*moal_send_packet_complete) (IN t_void *pmoal_handle,
+						  IN pmlan_buffer pmbuf,
+						  IN mlan_status status);
+    /** moal_recv_complete */
+	mlan_status (*moal_recv_complete) (IN t_void *pmoal_handle,
+					   IN pmlan_buffer pmbuf,
+					   IN t_u32 port,
+					   IN mlan_status status);
+    /** moal_recv_packet */
+	mlan_status (*moal_recv_packet) (IN t_void *pmoal_handle,
+					 IN pmlan_buffer pmbuf);
+    /** moal_recv_event */
+	mlan_status (*moal_recv_event) (IN t_void *pmoal_handle,
+					IN pmlan_event pmevent);
+    /** moal_ioctl_complete */
+	mlan_status (*moal_ioctl_complete) (IN t_void *pmoal_handle,
+					    IN pmlan_ioctl_req pioctl_req,
+					    IN mlan_status status);
+
+    /** moal_alloc_mlan_buffer */
+	mlan_status (*moal_alloc_mlan_buffer) (IN t_void *pmoal_handle,
+					       IN t_u32 size,
+					       OUT pmlan_buffer *pmbuf);
+    /** moal_free_mlan_buffer */
+	mlan_status (*moal_free_mlan_buffer) (IN t_void *pmoal_handle,
+					      IN pmlan_buffer pmbuf);
+
+    /** moal_write_reg */
+	mlan_status (*moal_write_reg) (IN t_void *pmoal_handle,
+				       IN t_u32 reg, IN t_u32 data);
+    /** moal_read_reg */
+	mlan_status (*moal_read_reg) (IN t_void *pmoal_handle,
+				      IN t_u32 reg, OUT t_u32 *data);
+    /** moal_write_data_sync */
+	mlan_status (*moal_write_data_sync) (IN t_void *pmoal_handle,
+					     IN pmlan_buffer pmbuf,
+					     IN t_u32 port, IN t_u32 timeout);
+    /** moal_read_data_sync */
+	mlan_status (*moal_read_data_sync) (IN t_void *pmoal_handle,
+					    IN OUT pmlan_buffer pmbuf,
+					    IN t_u32 port, IN t_u32 timeout);
+    /** moal_malloc */
+	mlan_status (*moal_malloc) (IN t_void *pmoal_handle,
+				    IN t_u32 size,
+				    IN t_u32 flag, OUT t_u8 **ppbuf);
+    /** moal_mfree */
+	mlan_status (*moal_mfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_vmalloc */
+	mlan_status (*moal_vmalloc) (IN t_void *pmoal_handle,
+				     IN t_u32 size, OUT t_u8 **ppbuf);
+    /** moal_vfree */
+	mlan_status (*moal_vfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_memset */
+	t_void *(*moal_memset) (IN t_void *pmoal_handle,
+				IN t_void *pmem, IN t_u8 byte, IN t_u32 num);
+    /** moal_memcpy */
+	t_void *(*moal_memcpy) (IN t_void *pmoal_handle,
+				IN t_void *pdest,
+				IN const t_void *psrc, IN t_u32 num);
+    /** moal_memmove */
+	t_void *(*moal_memmove) (IN t_void *pmoal_handle,
+				 IN t_void *pdest,
+				 IN const t_void *psrc, IN t_u32 num);
+    /** moal_memcmp */
+	t_s32 (*moal_memcmp) (IN t_void *pmoal_handle,
+			      IN const t_void *pmem1,
+			      IN const t_void *pmem2, IN t_u32 num);
+    /** moal_udelay */
+	t_void (*moal_udelay) (IN t_void *pmoal_handle, IN t_u32 udelay);
+    /** moal_get_system_time */
+	mlan_status (*moal_get_system_time) (IN t_void *pmoal_handle,
+					     OUT t_u32 *psec, OUT t_u32 *pusec);
+    /** moal_init_timer*/
+	mlan_status (*moal_init_timer) (IN t_void *pmoal_handle,
+					OUT t_void **pptimer,
+					IN t_void (*callback) (t_void
+							       *pcontext),
+					IN t_void *pcontext);
+    /** moal_free_timer */
+	mlan_status (*moal_free_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_start_timer*/
+	mlan_status (*moal_start_timer) (IN t_void *pmoal_handle,
+					 IN t_void *ptimer,
+					 IN t_u8 periodic, IN t_u32 msec);
+    /** moal_stop_timer*/
+	mlan_status (*moal_stop_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_init_lock */
+	mlan_status (*moal_init_lock) (IN t_void *pmoal_handle,
+				       OUT t_void **pplock);
+    /** moal_free_lock */
+	mlan_status (*moal_free_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_lock */
+	mlan_status (*moal_spin_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_unlock */
+	mlan_status (*moal_spin_unlock) (IN t_void *pmoal_handle,
+					 IN t_void *plock);
+    /** moal_print */
+	t_void (*moal_print) (IN t_void *pmoal_handle,
+			      IN t_u32 level, IN char *pformat, IN ...
+		);
+    /** moal_print_netintf */
+	t_void (*moal_print_netintf) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index, IN t_u32 level);
+    /** moal_assert */
+	t_void (*moal_assert) (IN t_void *pmoal_handle, IN t_u32 cond);
+    /** moal_hist_data_add */
+	t_void (*moal_hist_data_add) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index,
+				      IN t_u8 rx_rate,
+				      IN t_s8 snr,
+				      IN t_s8 nflr, IN t_u8 antenna);
+	t_void (*moal_updata_peer_signal) (IN t_void *pmoal_handle,
+					   IN t_u32 bss_index,
+					   IN t_u8 *peer_addr,
+					   IN t_s8 snr, IN t_s8 nflr);
+} 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
+
+/** 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
+
+/** 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(6)
+/** Control bit for DFS support */
+#define FEATURE_CTRL_DFS_SUPPORT    MBIT(7)
+
+/** Default feature control */
+#define FEATURE_CTRL_DEFAULT        0xffffffff
+
+/** 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
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#ifdef DEBUG_LEVEL1
+    /** Driver debug bit masks */
+	t_u32 drvdbg;
+#endif
+    /** allocate fixed buffer size for scan beacon buffer*/
+	t_u32 fixed_beacon_buffer;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** SDIO MPA Rx */
+	t_u32 mpa_rx_cfg;
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/* 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
+    /** FW download CRC check flag */
+	t_u32 fw_crc_check;
+    /** 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;
+    /** Host sleep wakeup interval */
+	t_u32 hs_wake_interval;
+    /** GPIO to indicate wakeup source */
+	t_u8 indication_gpio;
+    /** channel time and mode for DRCS*/
+	t_u32 drcs_chantime_mode;
+} mlan_device, *pmlan_device;
+
+/** MLAN API function prototype */
+#define MLAN_API
+
+/** Registration */
+MLAN_API mlan_status mlan_register(IN pmlan_device pmdevice,
+				   OUT t_void **ppmlan_adapter);
+
+/** Un-registration */
+MLAN_API mlan_status mlan_unregister(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Downloading */
+MLAN_API mlan_status mlan_dnld_fw(IN t_void *pmlan_adapter,
+				  IN pmlan_fw_image pmfw);
+
+/** Custom data pass API */
+MLAN_API mlan_status mlan_set_init_param(IN t_void *pmlan_adapter,
+					 IN pmlan_init_param pparam);
+
+/** Firmware Initialization */
+MLAN_API mlan_status mlan_init_fw(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Shutdown */
+MLAN_API mlan_status mlan_shutdown_fw(IN t_void *pmlan_adapter
+	);
+
+/** Main Process */
+MLAN_API mlan_status mlan_main_process(IN t_void *pmlan_adapter
+	);
+
+/** Rx process */
+mlan_status mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts);
+
+/** Packet Transmission */
+MLAN_API mlan_status mlan_send_packet(IN t_void *pmlan_adapter,
+				      IN pmlan_buffer pmbuf);
+
+/** Packet Reception complete callback */
+MLAN_API mlan_status mlan_recv_packet_complete(IN t_void *pmlan_adapter,
+					       IN pmlan_buffer pmbuf,
+					       IN mlan_status status);
+
+/** interrupt handler */
+MLAN_API mlan_status mlan_interrupt(IN t_void *pmlan_adapter);
+
+#if defined(SYSKT)
+/** GPIO IRQ callback function */
+MLAN_API t_void mlan_hs_callback(IN t_void *pctx);
+#endif /* SYSKT_MULTI || SYSKT */
+
+MLAN_API t_void mlan_pm_wakeup_card(IN t_void *pmlan_adapter);
+
+MLAN_API t_u8 mlan_is_main_process_running(IN t_void *adapter);
+
+/** mlan ioctl */
+MLAN_API mlan_status mlan_ioctl(IN t_void *pmlan_adapter,
+				IN pmlan_ioctl_req pioctl_req);
+/** mlan select wmm queue */
+MLAN_API t_u8 mlan_select_wmm_queue(IN t_void *pmlan_adapter,
+				    IN t_u8 bss_num, IN t_u8 tid);
+#endif /* !_MLAN_DECL_H_ */
diff --git a/wlan_sd8897/mlinux/mlan_ieee.h b/wlan_sd8897/mlinux/mlan_ieee.h
new file mode 100644
index 0000000..4ffb54d
--- /dev/null
+++ b/wlan_sd8897/mlinux/mlan_ieee.h
@@ -0,0 +1,1918 @@
+/** @file mlan_ieee.h
+ *
+ *  @brief This file contains IEEE information element related
+ *  definitions used in MLAN and MOAL module.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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
+
+/** 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,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	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_IE = VENDOR_SPECIFIC_221,
+	RSN_IE = 48,
+	VS_IE = VENDOR_SPECIFIC_221,
+	WAPI_IE = 68,
+} 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;
+
+/** 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[0];
+} MLAN_PACK_END IEEEtypes_Auth_framebody;
+
+/*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[0];
+} 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[0];
+} MLAN_PACK_END IEEEtypes_Ft_action_request;
+
+/*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_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_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_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
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN    4
+/** AKM Suite length */
+#define AKM_SUITE_LEN    4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT    7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT    6
+/** PMF ORing mask */
+#define PMF_MASK    0x00c0
+#endif
+
+/** wpa_suite_t */
+typedef MLAN_PACK_START struct _wpa_suite_t {
+    /** OUI */
+	t_u8 oui[3];
+    /** tyep */
+	t_u8 type;
+} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t;
+
+/** wpa_suite_ucast_t */
+typedef MLAN_PACK_START struct {
+	/* count */
+	t_u16 count;
+    /** wpa_suite list */
+	wpa_suite list[1];
+} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+
+/** IEEEtypes_Rsn_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t {
+    /** Rsn : Element ID */
+	t_u8 element_id;
+    /** Rsn : Length */
+	t_u8 len;
+    /** Rsn : version */
+	t_u16 version;
+    /** Rsn : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Rsn : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t;
+
+/** IEEEtypes_Wpa_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t {
+    /** Wpa : Element ID */
+	t_u8 element_id;
+    /** Wpa : Length */
+	t_u8 len;
+    /** Wpa : oui */
+	t_u8 oui[4];
+    /** version */
+	t_u16 version;
+    /** Wpa : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Wpa : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Reserved */
+	t_u8 reserved:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aifsn */
+	t_u8 aifsn:4;
+#else
+    /** Aifsn */
+	t_u8 aifsn:4;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn;   /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;		    /**< Ecw */
+	t_u16 tx_op_limit;		      /**< Tx op limit */
+} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t {
+
+    /**
+     * WMM Info IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [7]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [0]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+
+} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t {
+    /**
+     * WMM Parameter IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [24]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [1]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+    /** Reserved */
+	t_u8 reserved;
+
+    /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/** Enumerator for TSPEC direction */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e {
+
+	TSPEC_DIR_UPLINK = 0,
+	TSPEC_DIR_DOWNLINK = 1,
+	/* 2 is a reserved value */
+	TSPEC_DIR_BIDIRECT = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e;
+
+/** Enumerator for TSPEC PSB */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e {
+
+	TSPEC_PSB_LEGACY = 0,
+	TSPEC_PSB_TRIG = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e;
+
+/** Enumerator for TSPEC Ack Policy */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e {
+
+	TSPEC_ACKPOLICY_NORMAL = 0,
+	TSPEC_ACKPOLICY_NOACK = 1,
+	/* 2 is reserved */
+	TSPEC_ACKPOLICY_BLOCKACK = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e;
+
+/** Enumerator for TSPEC Trafffice type */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e {
+
+	TSPEC_TRAFFIC_APERIODIC = 0,
+	TSPEC_TRAFFIC_PERIODIC = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e;
+
+/** Data structure of WMM TSPEC information */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+	t_u8 Schedule:1;
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 AccessPolicy1:1;	/* ! */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+#else
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 AccessPolicy1:1;	/* ! */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 Schedule:1;
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t;
+
+/** Data structure of WMM TSPEC Nominal Size */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+	t_u16 Size:15;		/* ! Nominal size in octets */
+#else
+	t_u16 Size:15;		/* ! Nominal size in octets */
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t;
+
+/** Data structure of WMM TSPEC SBWA */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Whole:3;		/* ! Whole portion */
+	t_u16 Fractional:13;	/* ! Fractional portion */
+#else
+	t_u16 Fractional:13;	/* ! Fractional portion */
+	t_u16 Whole:3;		/* ! Whole portion */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA;
+
+/** Data structure of WMM TSPEC Body */
+typedef MLAN_PACK_START struct {
+
+    /** TS Information */
+	IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo;
+    /** NomMSDU size */
+	IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize;
+    /** MAximum MSDU size */
+	t_u16 MaximumMSDUSize;
+    /** Minimum Service Interval */
+	t_u32 MinServiceInterval;
+    /** Maximum Service Interval */
+	t_u32 MaxServiceInterval;
+    /** Inactivity Interval */
+	t_u32 InactivityInterval;
+    /** Suspension Interval */
+	t_u32 SuspensionInterval;
+    /** Service Start Time */
+	t_u32 ServiceStartTime;
+    /** Minimum Data Rate */
+	t_u32 MinimumDataRate;
+    /** Mean Data Rate */
+	t_u32 MeanDataRate;
+    /** Peak Data Rate */
+	t_u32 PeakDataRate;
+    /** Maximum Burst Size */
+	t_u32 MaxBurstSize;
+    /** Delay Bound */
+	t_u32 DelayBound;
+    /** Minimum Phy Rate */
+	t_u32 MinPHYRate;
+    /** Surplus BA Allowance */
+	IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance;
+    /** Medium Time */
+	t_u16 MediumTime;
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t;
+
+/** Data structure of WMM TSPEC all elements */
+typedef MLAN_PACK_START struct {
+    /** Element ID */
+	t_u8 ElementId;
+    /** Length */
+	t_u8 Len;
+    /** Oui Type */
+	t_u8 OuiType[4];	/* 00:50:f2:02 */
+    /** Ouisubtype */
+	t_u8 OuiSubType;	/* 01 */
+    /** Version */
+	t_u8 Version;
+
+    /** TspecBody */
+	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 {
+
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+    /** Action */
+	IEEEtypes_WMM_Tspec_Action_e action;
+    /** Dialog Token */
+	t_u8 dialogToken;
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t;
+
+/** WMM TSPEC AddTS request structure */
+typedef MLAN_PACK_START struct {
+
+    /** Tspec action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Status Code */
+	t_u8 statusCode;
+    /** tspecIE */
+	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 {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Reason Code */
+	t_u8 reasonCode;
+    /** tspecIE */
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t;
+
+/** union of WMM TSPEC structures */
+typedef MLAN_PACK_START union {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+
+    /** add TS request */
+	IEEEtypes_Action_WMM_AddTsReq_t addTsReq;
+    /** add TS response */
+	IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp;
+    /** Delete TS */
+	IEEEtypes_Action_WMM_DelTs_t delTs;
+
+} MLAN_PACK_END IEEEtypes_Action_WMMAC_t;
+
+/** union of WMM TSPEC & Action category */
+typedef MLAN_PACK_START union {
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+
+    /** wmmAc */
+	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;
+
+/** 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;
+    /** Channel width */
+	t_u8 chan_width;
+    /** Channel center frequency 1 */
+	t_u8 chan_center_freq_1;
+    /** Channel center frequency 2 */
+	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;
+    /** maximum tx power */
+	t_u8 max_tx_power;
+    /** channel center frequency */
+	t_u8 chan_center_freq;
+    /** channel width */
+	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;
+    /** MIMO capability count */
+	t_u8 MU_MIMO_capa_count;
+    /** stream under utilization */
+	t_u8 stream_underutilization;
+    /** VHT 40 util */
+	t_u8 VHT40_util;
+    /** VHT 80 util */
+	t_u8 VHT80_util;
+    /** VHT 160 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;
+    /** AP quiet mode */
+	t_u8 AP_quiet_mode;
+    /** Quiet count */
+	t_u8 quiet_count;
+    /** Quiet period */
+	t_u8 quiet_period;
+    /** Quiet duration */
+	t_u16 quiet_dur;
+    /** Quiet offset */
+	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;
+    /** New channel width */
+	t_u8 new_chan_width;
+    /** New channel center frequency 1 */
+	t_u8 new_chan_center_freq_1;
+    /** New channel center frequency 2 */
+	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;
+
+/** Maximum number of subbands in the IEEEtypes_SupportedChannels_t structure */
+#define WLAN_11H_MAX_SUBBANDS  5
+
+/** Maximum number of DFS channels configured in IEEEtypes_IBSS_DFS_t */
+#define WLAN_11H_MAX_IBSS_DFS_CHANNELS 25
+
+/**  IEEE Power Constraint element (7.3.2.15) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;    /**< IEEE Element ID = 32 */
+	t_u8 len;	    /**< Element length after id and len */
+	t_u8 local_constraint;
+			    /**< Local power constraint applied to 11d
+                             chan info */
+} MLAN_PACK_END IEEEtypes_PowerConstraint_t;
+
+/**  IEEE Power Capability element (7.3.2.16) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;	    /**< IEEE Element ID = 33 */
+	t_u8 len;		    /**< Element length after id and len */
+	t_s8 min_tx_power_capability;
+				    /**< Minimum Transmit power (dBm) */
+	t_s8 max_tx_power_capability;
+				    /**< Maximum Transmit power (dBm) */
+} MLAN_PACK_END IEEEtypes_PowerCapability_t;
+
+/**  IEEE TPC Report element (7.3.2.18) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;/**< IEEE Element ID = 35 */
+	t_u8 len;	/**< Element length after id and len */
+	t_s8 tx_power;	/**< Max power used to transmit the TPC Report frame (dBm) */
+	t_s8 link_margin;
+			/**< Link margin when TPC Request received (dB) */
+} MLAN_PACK_END IEEEtypes_TPCReport_t;
+
+/*  IEEE Supported Channel sub-band description (7.3.2.19) */
+/**
+ *  Sub-band description used in the supported channels element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 start_chan;/**< Starting channel in the subband */
+	t_u8 num_chans;	/**< Number of channels in the subband */
+
+} MLAN_PACK_END IEEEtypes_SupportChan_Subband_t;
+
+/*  IEEE Supported Channel element (7.3.2.19) */
+/**
+ *  Sent in association requests. Details the sub-bands and number
+ *    of channels supported in each subband
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;/**< IEEE Element ID = 36 */
+	t_u8 len;	/**< Element length after id and len */
+
+    /** Configured sub-bands information in the element */
+	IEEEtypes_SupportChan_Subband_t subband[WLAN_11H_MAX_SUBBANDS];
+
+} MLAN_PACK_END IEEEtypes_SupportedChannels_t;
+
+/** default channel switch count */
+#define DEF_CHAN_SWITCH_COUNT       5
+
+/*  IEEE Channel Switch Announcement Element (7.3.2.20) */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a chan switch element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;	/**< IEEE Element ID = 37 */
+	t_u8 len;		/**< Element length after id and len */
+	t_u8 chan_switch_mode;	/**< STA should not transmit any frames if 1 */
+	t_u8 new_channel_num;	/**< Channel # that AP/IBSS is moving to */
+	t_u8 chan_switch_count;	/**< # of TBTTs before channel switch */
+
+} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t;
+
+/** data structure for extended channel switch */
+typedef MLAN_PACK_START struct {
+   /** IEEE element ID = 60 */
+	t_u8 element_id;
+    /** Element length after id and len, set to 4 */
+	t_u8 len;
+    /** STA should not transmit any frames if 1 */
+	t_u8 chan_switch_mode;
+    /** Operate class # that AP/IBSS is moving to */
+	t_u8 new_oper_class;
+    /** Channel # that AP/IBSS is moving to */
+	t_u8 new_channel_num;
+    /** of TBTTs before channel switch */
+	t_u8 chan_switch_count;
+} MLAN_PACK_END IEEEtypes_ExtChanSwitchAnn_t;
+
+/*  IEEE Wide Bandwidth Channel Switch Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a wide bandwidth chan
+ *    switch element.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 194*/
+	IEEEtypes_Header_t ieee_hdr;
+    /** New channel width */
+	t_u8 new_channel_width;
+    /** New channel center frequency 0*/
+	t_u8 new_channel_center_freq0;
+    /** New channel center frequency 1*/
+	t_u8 new_channel_center_freq1;
+} MLAN_PACK_END IEEEtypes_WideBWChanSwitch_t;
+
+/*  IEEE VHT Transmit Power Envelope Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise the max
+ *    TX power in sepeate bandwidth and as a sub element of Channel Switch
+ *    Wrapper IE.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 195*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 tpc_info;		/**< Transmit Power Information>*/
+	t_u8 local_max_tp_20mhz;/**< Local Maximum Transmit Power for 20 MHZ>*/
+	t_u8 local_max_tp_40mhz;/**< Local Maximum Transmit Power for 40 MHZ>*/
+	t_u8 local_max_tp_80mhz;/**< Local Maximum Transmit Power for 80 MHZ>*/
+} MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t;
+
+/*  IEEE Quiet Period Element (7.3.2.23) */
+/**
+ *  Provided in beacons and probe responses.  Indicates times during
+ *    which the STA should not be transmitting data.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a quiet element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;    /**< IEEE Element ID = 40 */
+	t_u8 len;	    /**< Element length after id and len */
+	t_u8 quiet_count;   /**< Number of TBTTs until beacon with the quiet period */
+	t_u8 quiet_period;  /**< Regular quiet period, # of TBTTS between periods */
+	t_u16 quiet_duration;
+			    /**< Duration of the quiet period in TUs */
+	t_u16 quiet_offset; /**< Offset in TUs from the TBTT for the quiet period */
+
+} MLAN_PACK_END IEEEtypes_Quiet_t;
+
+/**
+***  @brief Map octet of the basic measurement report (7.3.2.22.1)
+**/
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+    /**< Reserved */
+	t_u8 rsvd5_7:3;
+    /**< Channel is unmeasured */
+	t_u8 unmeasured:1;
+    /**< Radar detected on channel */
+	t_u8 radar:1;
+    /**< Unidentified signal found on channel */
+	t_u8 unidentified_sig:1;
+    /**< OFDM preamble detected on channel */
+	t_u8 ofdm_preamble:1;
+    /**< At least one valid MPDU received on channel */
+	t_u8 bss:1;
+#else
+    /**< At least one valid MPDU received on channel */
+	t_u8 bss:1;
+    /**< OFDM preamble detected on channel */
+	t_u8 ofdm_preamble:1;
+    /**< Unidentified signal found on channel */
+	t_u8 unidentified_sig:1;
+    /**< Radar detected on channel */
+	t_u8 radar:1;
+    /**< Channel is unmeasured */
+	t_u8 unmeasured:1;
+    /**< Reserved */
+	t_u8 rsvd5_7:3;
+#endif				/* BIG_ENDIAN_SUPPORT */
+
+} MLAN_PACK_END MeasRptBasicMap_t;
+
+/*  IEEE DFS Channel Map field (7.3.2.24) */
+/**
+ *  Used to list supported channels and provide a octet "map" field which
+ *    contains a basic measurement report for that channel in the
+ *    IEEEtypes_IBSS_DFS_t element
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 channel_number;	/**< Channel number */
+	MeasRptBasicMap_t rpt_map;
+				/**< Basic measurement report for the channel */
+
+} MLAN_PACK_END IEEEtypes_ChannelMap_t;
+
+/*  IEEE IBSS DFS Element (7.3.2.24) */
+/**
+ *  IBSS DFS element included in ad hoc beacons and probe responses.
+ *    Provides information regarding the IBSS DFS Owner as well as the
+ *    originating STAs supported channels and basic measurement results.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;		    /**< IEEE Element ID = 41 */
+	t_u8 len;			    /**< Element length after id and len */
+	t_u8 dfs_owner[MLAN_MAC_ADDR_LENGTH];
+					    /**< DFS Owner STA Address */
+	t_u8 dfs_recovery_interval;	    /**< DFS Recovery time in TBTTs */
+
+    /** Variable length map field, one Map entry for each supported channel */
+	IEEEtypes_ChannelMap_t channel_map[WLAN_11H_MAX_IBSS_DFS_CHANNELS];
+
+} MLAN_PACK_END IEEEtypes_IBSS_DFS_t;
+
+/* 802.11h BSS information kept for each BSSID received in scan results */
+/**
+ * IEEE BSS information needed from scan results for later processing in
+ *    join commands
+ */
+typedef struct {
+	t_u8 sensed_11h;
+		      /**< Capability bit set or 11h IE found in this BSS */
+
+	IEEEtypes_PowerConstraint_t power_constraint;
+						  /**< Power Constraint IE */
+	IEEEtypes_PowerCapability_t power_capability;
+						  /**< Power Capability IE */
+	IEEEtypes_TPCReport_t tpc_report;	  /**< TPC Report IE */
+	IEEEtypes_ChanSwitchAnn_t chan_switch_ann;/**< Channel Switch Announcement IE */
+	IEEEtypes_Quiet_t quiet;		  /**< Quiet IE */
+	IEEEtypes_IBSS_DFS_t ibss_dfs;		  /**< IBSS DFS Element IE */
+
+} wlan_11h_bss_info_t;
+
+/** 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
+
+/** 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;
+
+/**
+ *  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;
+    /** flag to filer only probe response */
+	t_u8 proberesp_only;
+} 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
+
+/**
+ *  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;
+} MLAN_PACK_END wlan_bgscan_cfg;
+#endif /* STA_SUPPORT */
+
+/** 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;
+} MLAN_PACK_END ChanStatistics_t;
+
+#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 */
+	t_u32 channel;
+
+    /** Freq */
+	t_u32 freq;
+
+    /** Beacon period */
+	t_u16 beacon_period;
+
+    /** ATIM window */
+	t_u32 atim_window;
+
+    /** ERP flags */
+	t_u8 erp_flags;
+
+    /** Type of network in use */
+	WLAN_802_11_NETWORK_TYPE network_type_use;
+
+    /** Network infrastructure mode */
+	t_u32 bss_mode;
+
+    /** Network supported rates */
+	WLAN_802_11_RATES supported_rates;
+
+    /** Supported data rates */
+	t_u8 data_rates[WLAN_SUPPORTED_RATES];
+
+    /** Current channel bandwidth
+     *  0 : 20MHZ
+     *  1 : 40MHZ
+     *  2 : 80MHZ
+     *  3 : 160MHZ
+     */
+	t_u8 curr_bandwidth;
+
+    /** Network band.
+     * BAND_B(0x01): 'b' band
+     * BAND_G(0x02): 'g' band
+     * BAND_A(0X04): 'a' band
+     */
+	t_u16 bss_band;
+
+    /** TSF timestamp from the current firmware TSF */
+	t_u64 network_tsf;
+
+    /** TSF value included in the beacon/probe response */
+	t_u8 time_stamp[8];
+
+    /** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+
+    /** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+
+    /** Capability information */
+	IEEEtypes_CapInfo_t cap_info;
+
+    /** WMM IE */
+	IEEEtypes_WmmParameter_t wmm_ie;
+
+    /** 802.11h BSS information */
+	wlan_11h_bss_info_t wlan_11h_bss_info;
+
+    /** Indicate disabling 11n when associate with AP */
+	t_u8 disable_11n;
+    /** 802.11n BSS information */
+    /** HT Capabilities IE */
+	IEEEtypes_HTCap_t *pht_cap;
+    /** HT Capabilities Offset */
+	t_u16 ht_cap_offset;
+    /** HT Information IE */
+	IEEEtypes_HTInfo_t *pht_info;
+    /** HT Information Offset */
+	t_u16 ht_info_offset;
+    /** 20/40 BSS Coexistence IE */
+	IEEEtypes_2040BSSCo_t *pbss_co_2040;
+    /** 20/40 BSS Coexistence Offset */
+	t_u16 bss_co_2040_offset;
+    /** Extended Capabilities IE */
+	IEEEtypes_ExtCap_t *pext_cap;
+    /** Extended Capabilities Offset */
+	t_u16 ext_cap_offset;
+    /** Overlapping BSS Scan Parameters IE */
+	IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param;
+    /** Overlapping BSS Scan Parameters Offset */
+	t_u16 overlap_bss_offset;
+
+    /** VHT Capabilities IE */
+	IEEEtypes_VHTCap_t *pvht_cap;
+    /** VHT Capabilities IE offset */
+	t_u16 vht_cap_offset;
+    /** VHT Operations IE */
+	IEEEtypes_VHTOprat_t *pvht_oprat;
+    /** VHT Operations IE offset */
+	t_u16 vht_oprat_offset;
+    /** VHT Transmit Power Envelope IE */
+	IEEEtypes_VHTtxpower_t *pvht_txpower;
+    /** VHT Transmit Power Envelope IE offset */
+	t_u16 vht_txpower_offset;
+    /** Extended Power Constraint IE */
+	IEEEtypes_ExtPwerCons_t *pext_pwer;
+    /** Extended Power Constraint IE offset */
+	t_u16 ext_pwer_offset;
+    /** Extended BSS Load IE  */
+	IEEEtypes_ExtBSSload_t *pext_bssload;
+    /** Extended BSS Load IE offset */
+	t_u16 ext_bssload_offset;
+    /** Quiet Channel IE */
+	IEEEtypes_QuietChan_t *pquiet_chan;
+    /** Quiet Channel IE offset */
+	t_u16 quiet_chan_offset;
+    /** Operating Mode Notification IE */
+	IEEEtypes_OperModeNtf_t *poper_mode;
+    /** Operating Mode Notification IE offset */
+	t_u16 oper_mode_offset;
+
+#ifdef STA_SUPPORT
+    /** Country information set */
+	IEEEtypes_CountryInfoFullSet_t country_info;
+#endif				/* STA_SUPPORT */
+
+    /** WPA IE */
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+    /** WPA IE offset in the beacon buffer */
+	t_u16 wpa_offset;
+    /** RSN IE */
+	IEEEtypes_Generic_t *prsn_ie;
+    /** RSN IE offset in the beacon buffer */
+	t_u16 rsn_offset;
+#ifdef STA_SUPPORT
+    /** WAPI IE */
+	IEEEtypes_Generic_t *pwapi_ie;
+    /** WAPI IE offset in the beacon buffer */
+	t_u16 wapi_offset;
+#endif
+	/* Hotspot 2.0 OSEN AKM  IE */
+	IEEEtypes_Generic_t *posen_ie;
+    /** osen IE offset in the beacon buffer */
+	t_u16 osen_offset;
+	/* Mobility domain IE */
+	IEEEtypes_MobilityDomain_t *pmd_ie;
+	/** Mobility domain IE offset in the beacon buffer */
+	t_u16 md_offset;
+
+    /** Pointer to the returned scan response */
+	t_u8 *pbeacon_buf;
+    /** Length of the stored scan response */
+	t_u32 beacon_buf_size;
+    /** Max allocated size for updated scan response */
+	t_u32 beacon_buf_size_max;
+
+} BSSDescriptor_t, *pBSSDescriptor_t;
+
+/**
+ *  Type definitions for TCLAS element
+ */
+#define TCLAS_CLASSIFIER_TYPE_4      4
+
+/**
+ *  IEEE TCLAS Classifier Type 4
+ *
+ *  Type definition for Classifier Type 4 in TCLAS element
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_IPv4_t {
+    /** Version */
+	t_u8 version;
+    /** Source IP address */
+	t_u8 source_ip_addr[4];
+    /** Dest IP address */
+	t_u8 dest_ip_addr[4];
+    /** Source port */
+	t_u8 source_port[2];
+    /** Dest port */
+	t_u8 dest_port[2];
+    /** DSCP value */
+	t_u8 dscp;
+    /** Protocol value */
+	t_u8 protocol;
+    /** Reserved */
+	t_u8 reserved;
+} MLAN_PACK_END IEEEtypes_TCLAS_IPv4_t;
+
+/**
+ *  IEEE TCLAS base
+ *
+ *  Type definition for common parameters for every
+ *    classifier type
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_Base_t {
+    /** Element id */
+	t_u8 element_id;
+    /** Element len */
+	t_u8 element_len;
+    /** User priority */
+	t_u8 user_priority;
+    /** Classifier type */
+	t_u8 classifier_type;
+    /** Classifier mask */
+	t_u8 classifier_mask;
+} MLAN_PACK_END IEEEtypes_TCLAS_Base_t;
+
+/**
+ *  IEEE TCLAS element
+ *
+ *  Type definition for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_t {
+    /** Base structure for TCLAS */
+	IEEEtypes_TCLAS_Base_t tclas_base;
+
+	union MLAN_PACK_START {
+	/** Classifier type 4 */
+		IEEEtypes_TCLAS_IPv4_t ipv4;
+	} MLAN_PACK_END classifier;
+} MLAN_PACK_END IEEEtypes_TCLAS_t;
+
+/**
+ *  TCLAS element TLV
+ *
+ *  Structure that defines TLV for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _tclasElemen_tlv {
+    /** Type */
+	t_u16 type;
+    /** Length of TLV */
+	t_u16 len;
+    /** Tclas Ie */
+	IEEEtypes_TCLAS_t tclas_ie;
+} MLAN_PACK_END tclas_element_tlv_t;
+
+#endif /* !_MLAN_IEEE_H_ */
diff --git a/wlan_sd8897/mlinux/mlan_ioctl.h b/wlan_sd8897/mlinux/mlan_ioctl.h
new file mode 100644
index 0000000..394fe26
--- /dev/null
+++ b/wlan_sd8897/mlinux/mlan_ioctl.h
@@ -0,0 +1,4334 @@
+/** @file mlan_ioctl.h
+ *
+ *  @brief This file declares the IOCTL data structures and APIs.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_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
+
+	/* 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,
+
+	/* 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,
+
+	/* 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_FW_WAKEUP_METHOD = 0x00090007,
+	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,
+
+	/* 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,
+#if defined(DFS_TESTING_SUPPORT)
+	MLAN_OID_11H_DFS_TESTING = 0x00110003,
+#endif
+	MLAN_OID_11H_CHAN_REPORT_REQUEST = 0x00110004,
+	MLAN_OID_11H_CHAN_SWITCH_COUNT = 0x00110005,
+#ifdef DFS_TESTING_SUPPORT
+	MLAN_OID_11H_CHAN_NOP_INFO = 0x00110006,
+#endif
+
+	/* 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,
+
+	/* 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,
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	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_COALESCING_STATUS = 0x0020000E,
+	MLAN_OID_MISC_CUSTOM_IE = 0x0020000F,
+	MLAN_OID_MISC_TDLS_CONFIG = 0x00200010,
+	MLAN_OID_MISC_NET_MONITOR = 0x00200011,
+	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,
+	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
+	MLAN_OID_MISC_MULTI_CHAN_CFG = 0x00200023,
+	MLAN_OID_MISC_MULTI_CHAN_POLICY = 0x00200024,
+#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,
+#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_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_OPER_CLASS_CHECK = 0x00200049,
+	MLAN_OID_MISC_DRCS_CFG = 0x00200050,
+
+	MLAN_OID_MISC_CWMODE_CTRL = 0x00200051,
+	MLAN_OID_MISC_DYN_BW = 0x00200053,
+	MLAN_OID_MISC_FW_DUMP_EVENT = 0x00200054,
+	MLAN_OID_MISC_ROBUSTCOEX = 0x00200056,
+	MLAN_OID_MISC_CFP_INFO = 0x00200060,
+	MLAN_OID_MISC_BOOT_SLEEP = 0x00200061,
+	MLAN_OID_MISC_ACS = 0x00200063,
+};
+
+/** 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
+};
+
+/** 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
+};
+
+/** Max number of supported rates */
+#define MLAN_SUPPORTED_RATES	32
+
+/** 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
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES      4
+
+/** Default number of probes to send on each channel */
+#define DEFAULT_PROBES  4
+
+/** MAX BG channel */
+#define MAX_BG_CHANNEL 14
+
+/**
+ *  @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;
+    /** 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;
+
+/** tx status event structure */
+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[0]; */
+} 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;
+
+/** 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;
+    /** Ext_scan:  0 disable, 1: enable, 2: enhance scan*/
+	t_u32 ext_scan;
+} 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)
+
+/** mlan_ssid_bssid  data structure for
+ *  MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS
+ */
+typedef struct _mlan_ssid_bssid {
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+    /** index in BSSID list, start from 1 */
+	t_u32 idx;
+    /** Receive signal strength in dBm */
+	t_s32 rssi;
+    /**channel*/
+	t_u16 channel;
+    /**mobility domain value*/
+	t_u16 ft_md;
+    /**ft capability*/
+	t_u8 ft_cap;
+    /**band*/
+	t_u16 bss_band;
+	t_u32 channel_flags;
+} mlan_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
+/** 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   10
+/** 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  300
+/** 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           16
+
+/* 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
+
+/** 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
+
+/** 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;
+
+/** 5G band */
+#define BAND_CONFIG_5G        0x01
+/** 2.4 G band */
+#define BAND_CONFIG_2G        0x00
+/** 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;
+
+} mlan_uap_bss_param;
+
+/** mlan_uap_scan_channels */
+typedef struct _mlan_uap_scan_channels {
+    /** flag for remove nop channel*/
+	t_u8 remove_nop_channel;
+	/** num of removed channel */
+	t_u8 num_remvoed_channel;
+    /** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+    /** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+} mlan_uap_scan_channels;
+
+/** mlan_uap_oper_ctrl */
+typedef struct _mlan_uap_oper_ctrl {
+    /** control value
+      *  0: do nothing,
+      *  2: uap stops and restarts automaticaly
+     */
+	t_u16 ctrl_value;
+    /** channel opt
+      *  1: uap restart on default 2.4G/channel 6
+      *  2: uap restart on the band/channel configured by driver previously
+      *  3: uap restart on the band/channel specified by band_cfg and channel
+	*/
+	t_u16 chan_opt;
+    /** band cfg   0
+      *  0: 20Mhz  2: 40 Mhz  3: 80Mhz
+     */
+	t_u8 band_cfg;
+    /** channel */
+	t_u8 channel;
+} mlan_uap_oper_ctrl;
+
+#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 uap flag for MLAN_OID_BSS_START */
+		t_u8 host_based;
+	/** BSS param for AP mode for MLAN_OID_UAP_BSS_CONFIG */
+		mlan_uap_bss_param bss_config;
+	/** AP Wmm parameters for MLAN_OID_UAP_CFG_WMM_PARAM */
+		wmm_parameter_t ap_wmm_para;
+	/** ap scan channels for MLAN_OID_UAP_SCAN_CHANNELS*/
+		mlan_uap_scan_channels ap_scan_channels;
+	/** ap channel for MLAN_OID_UAP_CHANNEL*/
+		chan_band_info ap_channel;
+	/** ap operation control for MLAN_OID_UAP_OPER_CTRL*/
+		mlan_uap_oper_ctrl ap_oper_ctrl;
+#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
+	} param;
+} mlan_ds_bss, *pmlan_ds_bss;
+
+/*-----------------------------------------------------------------*/
+/** 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,
+};
+
+/** 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;
+    /** Ad-hoc channel bandwidth */
+	t_u32 adhoc_chan_bandwidth;
+    /** 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_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 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
+
+/** filt field param structure */
+struct filt_field_param {
+	/** Operation */
+	t_u8 operation;
+	/** Operand len */
+	t_u8 operand_len;
+	/** offset */
+	t_u16 offset;
+	/** Operand byte stream */
+	t_u8 operand_byte_stream[COALESCE_MAX_BYTESEQ];
+};
+
+/** coalesce rule structure */
+struct coalesce_rule {
+	/** max coalescing delay */
+	t_u16 max_coalescing_delay;
+	/** number of fields */
+	t_u8 num_of_fields;
+	/** packet type */
+	t_u8 pkt_type;
+	struct filt_field_param params[COALESCE_MAX_FILTERS];
+};
+
+/** coalesce configuration structure */
+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
+};
+
+/** Get stats org structure */
+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;
+} mlan_ds_get_stats, *pmlan_ds_get_stats;
+
+/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_uap_stats {
+    /** tkip mic failures */
+	t_u32 tkip_mic_failures;
+    /** ccmp decrypt errors */
+	t_u32 ccmp_decrypt_errors;
+    /** wep undecryptable count */
+	t_u32 wep_undecryptable_count;
+    /** wep icv error count */
+	t_u32 wep_icv_error_count;
+    /** decrypt failure count */
+	t_u32 decrypt_failure_count;
+    /** dot11 multicast tx count */
+	t_u32 mcast_tx_count;
+    /** dot11 failed count */
+	t_u32 failed_count;
+    /** dot11 retry count */
+	t_u32 retry_count;
+    /** dot11 multi retry count */
+	t_u32 multi_retry_count;
+    /** dot11 frame duplicate count */
+	t_u32 frame_dup_count;
+    /** dot11 rts success count */
+	t_u32 rts_success_count;
+    /** dot11 rts failure count */
+	t_u32 rts_failure_count;
+    /** dot11 ack failure count */
+	t_u32 ack_failure_count;
+    /** dot11 rx ragment count */
+	t_u32 rx_fragment_count;
+    /** dot11 mcast rx frame count */
+	t_u32 mcast_rx_frame_count;
+    /** dot11 fcs error count */
+	t_u32 fcs_error_count;
+    /** dot11 tx frame count */
+	t_u32 tx_frame_count;
+    /** dot11 rsna tkip cm invoked */
+	t_u32 rsna_tkip_cm_invoked;
+    /** dot11 rsna 4way handshake failures */
+	t_u32 rsna_4way_hshk_failures;
+} mlan_ds_uap_stats, *pmlan_ds_uap_stats;
+
+/** Mask of last beacon RSSI */
+#define BCN_RSSI_LAST_MASK              0x00000001
+/** Mask of average beacon RSSI */
+#define BCN_RSSI_AVG_MASK               0x00000002
+/** Mask of last data RSSI */
+#define DATA_RSSI_LAST_MASK             0x00000004
+/** Mask of average data RSSI */
+#define DATA_RSSI_AVG_MASK              0x00000008
+/** Mask of last beacon SNR */
+#define BCN_SNR_LAST_MASK               0x00000010
+/** Mask of average beacon SNR */
+#define BCN_SNR_AVG_MASK                0x00000020
+/** Mask of last data SNR */
+#define DATA_SNR_LAST_MASK              0x00000040
+/** Mask of average data SNR */
+#define DATA_SNR_AVG_MASK               0x00000080
+/** Mask of last beacon NF */
+#define BCN_NF_LAST_MASK                0x00000100
+/** Mask of average beacon NF */
+#define BCN_NF_AVG_MASK                 0x00000200
+/** Mask of last data NF */
+#define DATA_NF_LAST_MASK               0x00000400
+/** Mask of average data NF */
+#define DATA_NF_AVG_MASK                0x00000800
+/** Mask of all RSSI_INFO */
+#define ALL_RSSI_INFO_MASK              0x00000fff
+#define MAX_PATH_NUM                    3
+/** path A */
+#define PATH_A							0x01
+/** path B */
+#define PATH_B							0x02
+/** path AB */
+#define PATH_AB							0x03
+/** ALL the path */
+#define PATH_ALL						0
+/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */
+typedef struct _mlan_ds_get_signal {
+    /** Selector of get operation */
+	/*
+	 * Bit0:  Last Beacon RSSI,  Bit1:  Average Beacon RSSI,
+	 * Bit2:  Last Data RSSI,    Bit3:  Average Data RSSI,
+	 * Bit4:  Last Beacon SNR,   Bit5:  Average Beacon SNR,
+	 * Bit6:  Last Data SNR,     Bit7:  Average Data SNR,
+	 * Bit8:  Last Beacon NF,    Bit9:  Average Beacon NF,
+	 * Bit10: Last Data NF,      Bit11: Average Data NF
+	 *
+	 * Bit0: PATH A
+	 * Bit1: PATH B
+	 */
+	t_u16 selector;
+
+    /** RSSI */
+    /** RSSI of last beacon */
+	t_s16 bcn_rssi_last;
+    /** RSSI of beacon average */
+	t_s16 bcn_rssi_avg;
+    /** RSSI of last data packet */
+	t_s16 data_rssi_last;
+    /** RSSI of data packet average */
+	t_s16 data_rssi_avg;
+
+    /** SNR */
+    /** SNR of last beacon */
+	t_s16 bcn_snr_last;
+    /** SNR of beacon average */
+	t_s16 bcn_snr_avg;
+    /** SNR of last data packet */
+	t_s16 data_snr_last;
+    /** SNR of data packet average */
+	t_s16 data_snr_avg;
+
+    /** NF */
+    /** NF of last beacon */
+	t_s16 bcn_nf_last;
+    /** NF of beacon average */
+	t_s16 bcn_nf_avg;
+    /** NF of last data packet */
+	t_s16 data_nf_last;
+    /** NF of data packet average */
+	t_s16 data_nf_avg;
+} mlan_ds_get_signal, *pmlan_ds_get_signal;
+
+/** bit for 2.4 G antenna diversity */
+#define ANT_DIVERSITY_2G   MBIT(3)
+/** bit for 5 G antenna diversity */
+#define ANT_DIVERSITY_5G   MBIT(7)
+
+/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */
+typedef struct _mlan_fw_info {
+    /** Firmware version */
+	t_u32 fw_ver;
+    /** MAC address */
+	mlan_802_11_mac_addr mac_addr;
+    /** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+    /** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+    /** user's MCS setting */
+	t_u8 usr_dev_mcs_support;
+    /** 802.11ac device capabilities */
+	t_u32 hw_dot_11ac_dev_cap;
+    /** 802.11ac device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11ac_dev_cap_bg;
+    /** 802.11ac device Capabilities for 5GHz */
+	t_u32 usr_dot_11ac_dev_cap_a;
+    /** 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_u8 fw_bands;
+	/** region code */
+	t_u16 region_code;
+    /** 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;
+} mlan_fw_info, *pmlan_fw_info;
+
+/** Version string buffer length */
+#define MLAN_MAX_VER_STR_LEN    128
+
+/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */
+typedef struct _mlan_ver_ext {
+    /** Selected version string */
+	t_u32 version_str_sel;
+    /** Version string */
+	char version_str[MLAN_MAX_VER_STR_LEN];
+} mlan_ver_ext, *pmlan_ver_ext;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+    /** Extended Capabilities value */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit77: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 MaxAMSDU:2;	/* bit 63-bit 64 */
+	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 MaxAMSDU:2;	/* bit 63-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 rsvdBit77:1;	/* bit 77 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#endif
+
+/** ExtCap : TDLS prohibited */
+#define IS_EXTCAP_TDLS_PROHIBITED(ext_cap) (ext_cap.TDLSProhibited)
+/** ExtCap : TDLS channel switch prohibited */
+#define IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ext_cap) (ext_cap.TDLSChlSwitchProhib)
+
+/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */
+typedef struct _mlan_bss_info {
+    /** BSS mode */
+	t_u32 bss_mode;
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** Table index */
+	t_u32 scan_table_idx;
+    /** Channel */
+	t_u32 bss_chan;
+    /** Band */
+	t_u8 bss_band;
+    /** Region code */
+	t_u32 region_code;
+    /** Connection status */
+	t_u32 media_connected;
+    /** Radio on */
+	t_u32 radio_on;
+    /** Max power level in dBm */
+	t_s32 max_power_level;
+    /** Min power level in dBm */
+	t_s32 min_power_level;
+    /** Adhoc state */
+	t_u32 adhoc_state;
+    /** NF of last beacon */
+	t_s32 bcn_nf_last;
+    /** wep status */
+	t_u32 wep_status;
+    /** scan block status */
+	t_u8 scan_block;
+     /** Host Sleep configured flag */
+	t_u32 is_hs_configured;
+    /** Deep Sleep flag */
+	t_u32 is_deep_sleep;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+#ifdef STA_SUPPORT
+    /** Capability Info */
+	t_u16 capability_info;
+    /** Beacon Interval */
+	t_u16 beacon_interval;
+    /** Listen Interval */
+	t_u16 listen_interval;
+    /** Association Id  */
+	t_u16 assoc_id;
+    /** AP/Peer supported rates */
+	t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES];
+    /** extend capability for AP */
+	ExtCap_t ext_cap;
+#endif				/* STA_SUPPORT */
+    /** Mobility Domain ID */
+	t_u16 mdid;
+    /** FT Capability policy */
+	t_u8 ft_cap;
+    /** 11h active */
+	t_bool is_11h_active;
+    /** dfs check channel */
+	t_u8 dfs_check_channel;
+} mlan_bss_info, *pmlan_bss_info;
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID     8
+
+/** Max RX Win size */
+#define MAX_RX_WINSIZE  64
+
+/** rx_reorder_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** TA */
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+    /** Start window */
+	t_u32 start_win;
+    /** Window size */
+	t_u32 win_size;
+    /** amsdu flag */
+	t_u8 amsdu;
+    /** buffer status */
+	t_u32 buffer[MAX_RX_WINSIZE];
+} rx_reorder_tbl;
+
+/** tx_ba_stream_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** RA */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+    /** amsdu flag */
+	t_u8 amsdu;
+} tx_ba_stream_tbl;
+
+/** Debug command number */
+#define DBG_CMD_NUM	10
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** 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;
+
+/** 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;
+    /** Corresponds to is_hs_configured member of mlan_adapter */
+	t_u8 is_hs_configured;
+    /** Corresponds to hs_activated member of mlan_adapter */
+	t_u8 hs_activated;
+    /** Corresponds to pps_uapsd_mode member of mlan_adapter */
+	t_u16 pps_uapsd_mode;
+    /** Corresponds to sleep_period.period member of mlan_adapter */
+	t_u16 sleep_pd;
+    /** Corresponds to wmm_qosinfo member of mlan_private */
+	t_u8 qos_cfg;
+    /** Corresponds to tx_lock_flag member of mlan_adapter */
+	t_u8 tx_lock_flag;
+    /** Corresponds to port_open member of mlan_private */
+	t_u8 port_open;
+    /** bypass pkt count */
+	t_u16 bypass_pkt_count;
+    /** Corresponds to scan_processing member of mlan_adapter */
+	t_u32 scan_processing;
+    /** Corresponds to mlan_processing member of mlan_adapter */
+	t_u32 mlan_processing;
+    /** Corresponds to main_lock_flag member of mlan_adapter */
+	t_u32 main_lock_flag;
+    /** Corresponds to main_process_cnt member of mlan_adapter */
+	t_u32 main_process_cnt;
+	/** Corresponds to delay_task_flag member of mlan_adapter */
+	t_u32 delay_task_flag;
+    /** mlan_rx_processing */
+	t_u32 mlan_rx_processing;
+    /** rx pkts queued */
+	t_u32 rx_pkts_queued;
+    /** Number of host to card command failures */
+	t_u32 num_cmd_host_to_card_failure;
+    /** Number of host to card sleep confirm failures */
+	t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+    /** Number of host to card Tx failures */
+	t_u32 num_tx_host_to_card_failure;
+    /** Number of allocate buffer failure */
+	t_u32 num_alloc_buffer_failure;
+	/** Number of pkt dropped */
+	t_u32 num_pkt_dropped;
+    /** 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;
+    /** 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;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** Number of packets tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+    /** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+	/** last recv wr_bitmap */
+	t_u32 last_recv_wr_bitmap;
+    /** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+    /** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+	/** last len for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+    /** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+    /** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** last mp_index */
+	t_u8 last_mp_index;
+    /** buffer for mp debug */
+	t_u8 *mpa_buf;
+    /** length info for mp buf size */
+	t_u32 mpa_buf_size;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** Number of packets rx aggr */
+	t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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 Tx timeouts */
+	t_u32 num_tx_timeout;
+    /** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+    /** Number of command timeouts */
+	t_u32 dbg_num_cmd_timeout;
+    /** Timeout command ID */
+	t_u16 timeout_cmd_id;
+    /** Timeout command action */
+	t_u16 timeout_cmd_act;
+    /** List of last command IDs */
+	t_u16 last_cmd_id[DBG_CMD_NUM];
+    /** List of last command actions */
+	t_u16 last_cmd_act[DBG_CMD_NUM];
+    /** Last command index */
+	t_u16 last_cmd_index;
+    /** List of last command response IDs */
+	t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+    /** Last command response index */
+	t_u16 last_cmd_resp_index;
+    /** List of last events */
+	t_u16 last_event[DBG_CMD_NUM];
+    /** Last event index */
+	t_u16 last_event_index;
+    /** Number of no free command node */
+	t_u16 num_no_cmd_node;
+    /** pending command id */
+	t_u16 pending_cmd;
+    /** time stamp for dnld last cmd */
+	t_u32 dnld_cmd_in_secs;
+    /** Corresponds to data_sent member of mlan_adapter */
+	t_u8 data_sent;
+    /** Corresponds to cmd_sent member of mlan_adapter */
+	t_u8 cmd_sent;
+    /** SDIO multiple port read bitmap */
+	t_u32 mp_rd_bitmap;
+    /** SDIO multiple port write bitmap */
+	t_u32 mp_wr_bitmap;
+    /** Current available port for read */
+	t_u8 curr_rd_port;
+    /** Current available port for write */
+	t_u8 curr_wr_port;
+    /** 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
+    /** mlan_adapter pointer */
+	t_void *mlan_adapter;
+    /** mlan_adapter_size */
+	t_u32 mlan_adapter_size;
+    /** mlan_priv vector */
+	t_void *mlan_priv[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_size */
+	t_u32 mlan_priv_size[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_num */
+	t_u8 mlan_priv_num;
+} mlan_debug_info, *pmlan_debug_info;
+
+#ifdef UAP_SUPPORT
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS         MAX_STA_COUNT
+
+/** station info */
+typedef struct _sta_info {
+    /** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+    /** station bandmode */
+	t_u8 bandmode;
+} sta_info;
+
+/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */
+typedef struct _mlan_ds_sta_list {
+    /** station count */
+	t_u16 sta_count;
+    /** station list */
+	sta_info info[MAX_NUM_CLIENTS];
+} mlan_ds_sta_list, *pmlan_ds_sta_list;
+#endif
+
+/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */
+typedef struct _mlan_ds_get_info {
+    /** Sub-command */
+	t_u32 sub_command;
+
+    /** Status information parameter */
+	union {
+	/** Signal information for MLAN_OID_GET_SIGNAL */
+		mlan_ds_get_signal signal;
+		/** Signal path id for MLAN_OID_GET_SIGNAL_EXT */
+		t_u16 path_id;
+	/** Signal information for MLAN_OID_GET_SIGNAL_EXT */
+		mlan_ds_get_signal signal_ext[MAX_PATH_NUM];
+	/** Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_get_stats stats;
+	/** Statistics information for MLAN_OID_LINK_STATS*/
+		t_u8 link_statistic[1];
+	/** Firmware information for MLAN_OID_GET_FW_INFO */
+		mlan_fw_info fw_info;
+	/** Extended version information for MLAN_OID_GET_VER_EXT */
+		mlan_ver_ext ver_ext;
+	/** BSS information for MLAN_OID_GET_BSS_INFO */
+		mlan_bss_info bss_info;
+	/** Debug information for MLAN_OID_GET_DEBUG_INFO */
+		t_u8 debug_info[1];
+#ifdef UAP_SUPPORT
+	/** UAP Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_uap_stats ustats;
+	/** UAP station list for MLAN_OID_UAP_STA_LIST */
+		mlan_ds_sta_list sta_list;
+#endif
+	} param;
+} mlan_ds_get_info, *pmlan_ds_get_info;
+
+/*-----------------------------------------------------------------*/
+/** Security Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for authentication mode */
+enum _mlan_auth_mode {
+	MLAN_AUTH_MODE_OPEN = 0x00,
+	MLAN_AUTH_MODE_SHARED = 0x01,
+	MLAN_AUTH_MODE_FT = 0x02,
+	MLAN_AUTH_MODE_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_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,
+};
+
+/** Enumeration for PSK */
+enum _mlan_psk_type {
+	MLAN_PSK_PASSPHRASE = 1,
+	MLAN_PSK_PMK,
+	MLAN_PSK_CLEAR,
+	MLAN_PSK_QUERY,
+};
+
+/** 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
+/** 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
+/** 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 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;
+	/** 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;
+
+/*-----------------------------------------------------------------*/
+/** 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_AUTO = 0xFF,
+};
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE   18
+
+/** 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;
+} 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;
+	} param;
+} mlan_ds_power_cfg, *pmlan_ds_power_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 adhoc awake period */
+#define MIN_ADHOC_AWAKE_PD      0
+/** Maximum adhoc awake period */
+#define MAX_ADHOC_AWAKE_PD      31
+/** Special adhoc awake period */
+#define SPECIAL_ADHOC_AWAKE_PD  255
+
+/** 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;
+    /** Adhoc awake period */
+	t_u32 adhoc_awake_period;
+    /** 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_fw_wakeup_params for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+typedef struct _mlan_fw_wakeup_params {
+    /** FW wakeup method */
+	t_u16 method;
+    /** GPIO pin NO.*/
+	t_u8 gpio_pin;
+} mlan_fw_wakeup_params, *pmlan_fw_wakeup_params;
+
+/** 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;
+	/** FW wakeup method for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+		mlan_fw_wakeup_params fw_wakeup_params;
+	/** 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;
+	} 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;
+
+/** 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,
+};
+
+/** 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 */
+/*-----------------------------------------------------------------*/
+#if defined(DFS_TESTING_SUPPORT)
+/** 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;
+} 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;
+#endif
+
+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;
+
+/** 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;
+#if defined(DFS_TESTING_SUPPORT)
+	/** 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;
+#endif
+		mlan_ds_11h_chan_rep_req chan_rpt_req;
+		t_s8 cs_count;
+	} param;
+} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Miscellaneous Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** CMD buffer size */
+#define MLAN_SIZE_OF_CMD_BUFFER 2048
+
+/** 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;
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** 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[MLAN_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;
+
+/** 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;
+
+/** Enumeration for function init/shutdown */
+enum _mlan_func_cmd {
+	MLAN_FUNC_INIT = 1,
+	MLAN_FUNC_SHUTDOWN,
+};
+
+/** Enumeration for Coalescing status */
+enum _mlan_coal_status {
+	MLAN_MISC_COALESCING_ENABLE = 1,
+	MLAN_MISC_COALESCING_DISABLE = 0
+};
+
+/* Net monitor filters: */
+/* management frame */
+#define MLAN_NETMON_MANAGEMENT    MBIT(0)
+/* control frame */
+#define MLAN_NETMON_CONTROL       MBIT(1)
+/* data frame */
+#define MLAN_NETMON_DATA          MBIT(2)
+/* only unicast frame (no promiscuous) */
+#define MLAN_NETMON_NOPROM        MBIT(3)
+/* decrypted frame */
+#define MLAN_NETMON_DECRYPTED     MBIT(4)
+
+typedef struct _mlan_ds_misc_net_monitor {
+    /** Enable/disable network monitor */
+	t_u32 enable_net_mon;
+    /** Set net monitor filer flag */
+	t_u32 filter_flag;
+   /** Radio type */
+	t_u32 band;
+    /** Channel */
+	t_u32 channel;
+    /** Secondary channel bandwidth */
+	t_u32 chan_bandwidth;
+} mlan_ds_misc_net_monitor;
+
+/** 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;
+
+/** 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;
+
+/* 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_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;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** flag for NOA */
+#define WIFI_DIRECT_NOA         1
+/** flag for OPP_PS */
+#define WIFI_DIRECT_OPP_PS      2
+/** Type definition of mlan_ds_wifi_direct_config
+ *  for MLAN_OID_MISC_WIFI_DIRECT_CONFIG
+ */
+typedef struct _mlan_ds_wifi_direct_config {
+    /** flags for NOA/OPP_PS */
+	t_u8 flags;
+     /** NoA enable/disable */
+	t_u8 noa_enable;
+    /** index */
+	t_u16 index;
+    /** NoA count */
+	t_u8 noa_count;
+    /** NoA duration */
+	t_u32 noa_duration;
+    /** NoA interval */
+	t_u32 noa_interval;
+    /** opp ps enable/disable */
+	t_u8 opp_ps_enable;
+    /** CT window value */
+	t_u8 ct_window;
+} mlan_ds_wifi_direct_config;
+#endif
+
+#if defined(STA_SUPPORT)
+/** mlan_ds_misc_pmfcfg structure */
+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
+
+/** mlan_ds_multi_chan_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_multi_chan_cfg {
+    /** Channel Time */
+	t_u32 channel_time;
+    /** Buffer Weight */
+	t_u8 buffer_weight;
+    /** tlv len */
+	t_u16 tlv_len;
+    /** TLV buffer */
+	t_u8 tlv_buf[0];
+} MLAN_PACK_END mlan_ds_multi_chan_cfg;
+
+/** mlan_ds_drcs_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_drcs_cfg {
+    /** Channel Index*/
+	t_u16 chan_idx;
+    /** Channel time (in TU) for chan_idx */
+	t_u8 chantime;
+    /** Channel swith time (in TU) for chan_idx */
+	t_u8 switchtime;
+    /** Undoze time (in TU) for chan_idx */
+	t_u8 undozetime;
+    /** Rx traffic control scheme when channel switch*/
+    /** only valid for GC/STA interface*/
+	t_u8 mode;
+} MLAN_PACK_END mlan_ds_drcs_cfg;
+
+#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
+
+#define WOWLAN_MAX_PATTERN_LEN		20
+#define WOWLAN_MAX_OFFSET_LEN		50
+#define MAX_NUM_FILTERS              10
+
+/** Temperature Sensor structure */
+typedef struct _mlan_ds_sensor_temp {
+    /** Temperature */
+	t_u32 temperature;
+} mlan_ds_sensor_temp;
+
+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;
+
+/** 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;
+
+/** channel statictics */
+typedef struct _ChStat_t {
+    /** channle number */
+	t_u8 chan_num;
+    /** total network */
+	t_u16 total_networks;
+    /** busy duration */
+	t_u16 cca_busy_duration;
+} ChStat_t, *pChStat_t;
+
+#define MAX_CH_STATS    MAX_BG_CHANNEL
+/** Type definition of mlan_acs_scan */
+typedef struct _mlan_ds_misc_acs {
+    /** Best Channel Number */
+	t_u8 best_ch;
+    /** Scan channel gap */
+	t_u16 scan_chan_gap;
+    /** Channel Statistics Number */
+	t_u8 ch_stats_num;
+    /** Channel Statistics */
+	ChStat_t ch_stats[MAX_CH_STATS];
+} mlan_ds_misc_acs, *pmlan_ds_misc_acs;
+
+/** 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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;
+	/** Coalescing status for MLAN_OID_MISC_COALESCING_STATUS */
+		t_u16 coalescing_status;
+	/** 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;
+	/** Net monitor for MLAN_OID_MISC_NET_MONITOR */
+		mlan_ds_misc_net_monitor net_mon;
+	/** Tx data pause for MLAN_OID_MISC_TX_DATAPAUSE */
+		mlan_ds_misc_tx_datapause tx_datapause;
+	/** IP address configuration */
+		mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
+	/** MAC control for MLAN_OID_MISC_MAC_CONTROL */
+		t_u32 mac_ctrl;
+	/** MEF configuration for MLAN_OID_MISC_MEF_CFG */
+		mlan_ds_misc_mef_cfg mef_cfg;
+	/** CFP code for MLAN_OID_MISC_CFP_CODE */
+		mlan_ds_misc_cfp_code cfp_code;
+	/** Country code for MLAN_OID_MISC_COUNTRY_CODE */
+		mlan_ds_misc_country_code country_code;
+	/** Thermal reading for MLAN_OID_MISC_THERMAL */
+		t_u32 thermal;
+	/** Mgmt subtype mask for MLAN_OID_MISC_RX_MGMT_IND */
+		t_u32 mgmt_subtype_mask;
+	/** subscribe event for MLAN_OID_MISC_SUBSCRIBE_EVENT */
+		mlan_ds_subscribe_evt subscribe_event;
+#ifdef DEBUG_LEVEL1
+	/** Driver debug bit masks */
+		t_u32 drvdbg;
+#endif
+	/** Hotspot config param set */
+		t_u32 hotspot_cfg;
+#ifdef STA_SUPPORT
+		ExtCap_t ext_cap;
+#endif
+		mlan_ds_misc_otp_user_data otp_user_data;
+	/** Tx control */
+		t_u32 tx_control;
+#if defined(STA_SUPPORT)
+		mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+	/** Multi-channel config for MLAN_OID_MISC_MULTI_CHAN_CFG */
+		mlan_ds_multi_chan_cfg multi_chan_cfg;
+	/** Multi-channel policy for MLAN_OID_MISC_MULTI_CHAN_POLICY */
+		t_u16 multi_chan_policy;
+	/** channel drcs time slicing config for MLAN_OID_MISC_DRCS_CFG */
+		mlan_ds_drcs_cfg drcs_cfg[2];
+#ifdef WIFI_DIRECT_SUPPORT
+		mlan_ds_wifi_direct_config p2p_config;
+#endif
+		mlan_ds_coalesce_cfg coalesce_cfg;
+		t_u8 low_pwr_mode;
+#ifdef RX_PACKET_COALESCE
+		mlan_ds_misc_rx_packet_coalesce rx_coalesce;
+#endif
+	/** FW reload flag */
+		t_u8 fw_reload;
+	/** Sensor temperature */
+		mlan_ds_sensor_temp sensor_temp;
+	/** Bandwidth Channel operation */
+		mlan_ds_bw_chan_oper bw_chan_oper;
+    /** Independent Reset Configuration */
+		mlan_ds_ind_rst_cfg ind_rst_cfg;
+    /** misc tsf */
+		t_u64 misc_tsf;
+		mlan_ds_misc_robustcoex_params robustcoexparams;
+    /** boot sleep enable or disable */
+		t_u16 boot_sleep;
+    /** ACS */
+		mlan_ds_misc_acs acs;
+	} 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_sd8897/mlinux/moal_cfg80211.c b/wlan_sd8897/mlinux/moal_cfg80211.c
new file mode 100644
index 0000000..9ce2f25
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_cfg80211.c
@@ -0,0 +1,3872 @@
+/** @file moal_cfg80211.c
+  *
+  * @brief This file contains the functions for CFG80211.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include    "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},
+};
+
+/********************************************************
+				Global Variables
+********************************************************/
+extern int cfg80211_wext;
+
+struct ieee80211_supported_band cfg80211_band_2ghz = {
+	.channels = cfg80211_channels_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,
+	.n_channels = ARRAY_SIZE(cfg80211_channels_5ghz),
+	.bitrates = cfg80211_rates + 4,
+	.n_bitrates = ARRAY_SIZE(cfg80211_rates) - 4,
+};
+
+#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
+********************************************************/
+
+/********************************************************
+				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;
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+								      ,
+								      (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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+								      ,
+								      (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:
+	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;
+			memcpy(priv->uap_wep_key[key_index].key, key, key_len);
+			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 &&
+		    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) {
+			memcpy(sec->param.encrypt_key.key_material, key,
+			       key_len);
+			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) {
+				memcpy(sec->param.encrypt_key.pn, seq, PN_SIZE);
+				DBG_HEXDUMP(MCMD_D, "WAPI PN",
+					    sec->param.encrypt_key.pn, seq_len);
+			}
+		}
+		if (addr) {
+			memcpy(sec->param.encrypt_key.mac_addr, addr, ETH_ALEN);
+			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;
+		} else {
+			memcpy(sec->param.encrypt_key.mac_addr, bcast_addr,
+			       ETH_ALEN);
+			sec->param.encrypt_key.key_flags =
+				KEY_FLAG_GROUP_KEY | KEY_FLAG_SET_TX_KEY;
+		}
+		if (seq && seq_len) {
+			memcpy(sec->param.encrypt_key.pn, seq, seq_len);
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_RX_SEQ_VALID;
+		}
+
+		if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_AES_MCAST_IGTK;
+		}
+	} 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)
+			memcpy(sec->param.encrypt_key.mac_addr, addr, ETH_ALEN);
+	}
+
+	/* 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);
+		/* 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
+
+#if defined(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, channnel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		default:
+			PRINTM(MMSG,
+			       "wlan: %s Unknow P2P Action Frame, channel=%d, subtype=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0, subtype);
+			break;
+		}
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @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 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;
+	}
+
+	/* 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 && V14_FEATURE */
+
+/**
+ * @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 CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
+				  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 (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_MONITOR) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	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);
+
+#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 = 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 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
+
+	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_ADHOC:
+		bss->param.bss_mode = MLAN_BSS_MODE_IBSS;
+		priv->wdev->iftype = NL80211_IFTYPE_ADHOC;
+		PRINTM(MINFO, "Setting interface type to adhoc\n");
+		break;
+	case NL80211_IFTYPE_STATION:
+#if defined(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 && V14_FEATURE */
+#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;
+#if defined(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 && V14_FEATURE */
+	case NL80211_IFTYPE_AP:
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	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 (MLAN_STATUS_SUCCESS != status) {
+		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
+	mlan_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 == MLAN_FRAG_RTS_DISABLED)
+		rts_thr = MLAN_RTS_MAX_VALUE;
+	if (frag_thr == 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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+		      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;
+	}
+	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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+		      bool pairwise,
+#endif
+		      const t_u8 *mac_addr)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
+
+	ENTER();
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_del_key in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+			      , bool ucast, bool mcast
+#endif
+	)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
+	mlan_bss_info bss_info;
+
+	ENTER();
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+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
+
+#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);
+		memcpy(entry->bssid, pmksa->bssid, ETH_ALEN);
+		memcpy(entry->pmkid, pmksa->pmkid, 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);
+		memcpy(entry->pmkid, pmksa->pmkid, 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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+			  struct net_device *dev,
+#endif
+			  struct ieee80211_channel *chan,
+			  enum nl80211_channel_type channel_type)
+{
+	int ret = 0;
+	moal_private *priv = NULL;
+
+	ENTER();
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+/**
+ * @brief Functions check whether the pattern is supported
+ *
+ * @param pat             A pointer to cfg80211_pkt_pattern structure
+ * @param byte_seq        Byte sequence
+ * @param max_byte_seq    Maximum byte sequence
+ *
+ * @return                true -- success, otherwise false
+ */
+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) {
+				memcpy(byte_seq + valid_byte_cnt,
+				       &pat->pattern[j * 8 + k], 1);
+				valid_byte_cnt++;
+				if (dont_care_byte)
+					return false;
+			} else {
+				if (valid_byte_cnt)
+					dont_care_byte = true;
+			}
+
+			if (valid_byte_cnt > max_byte_seq)
+				return false;
+		}
+	}
+
+	byte_seq[max_byte_seq] = valid_byte_cnt;
+
+	return true;
+}
+
+/**
+ * @brief Get coalesce packet type
+ *
+ * @param byte_seq        Byte Sequence
+
+ * @return                0 -- success, otherwise fail
+ */
+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;
+}
+
+/**
+ * @brief Functions fills the coalesce rule information
+ *
+ * @param crule           A pointer to cfg80211_coalesce_rules structure
+ * @param mrule           A pointer to coalesce_rules structure
+ *
+ * @return                0-- success, otherwise fail
+ */
+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];
+		memcpy(param->operand_byte_stream, byte_seq,
+		       param->operand_len);
+		param->offset = crule->patterns[i].pkt_offset;
+		param++;
+
+		mrule->num_of_fields++;
+	}
+
+	if (!mrule->pkt_type) {
+		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
+ */
+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;
+
+	memcpy(&misc_cfg->param.coalesce_cfg, 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	/* Fill MCS rates */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	rate_cfg->bitmap_rates[2] = mask->control[band].ht_mcs[0];
+#else
+	rate_cfg->bitmap_rates[2] = mask->control[band].mcs[0];
+#endif
+#if defined(SD_8XXX)
+	if (priv->phandle->card_type ==
+#if defined(SD_8XXX)
+	    CARD_TYPE_SD8797
+#endif
+		)
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		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 (MLAN_STATUS_SUCCESS != status) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+/**
+ * @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 (MLAN_STATUS_SUCCESS != status) {
+		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 (MLAN_STATUS_SUCCESS != status) {
+		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
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+/**
+ * @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
+/**
+ * @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
+{
+#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);
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	t_u32 mgmt_subtype_mask = 0x0;
+	t_u32 last_mgmt_subtype_mask = priv->mgmt_subtype_mask;
+
+	ENTER();
+	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: mgmt_subtype_mask=0x%x last_mgmt_subtype_mask=0x%x\n",
+	       dev->name, 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. */
+		status = 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+/**
+ * @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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		      struct net_device *dev,
+#else
+		      struct wireless_dev *wdev,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		      struct cfg80211_mgmt_tx_params *params,
+#else
+		      struct ieee80211_channel *chan, bool offchan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+		      enum nl80211_channel_type channel_type,
+		      bool channel_type_valid,
+#endif
+		      unsigned int wait, const u8 *buf, size_t len,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+		      bool no_cck,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+		      bool dont_wait_for_ack,
+#endif
+#endif
+		      u64 * cookie)
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct net_device *dev = wdev->netdev;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	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;
+
+	ENTER();
+
+	if (buf == NULL || len == 0) {
+		PRINTM(MERROR, "woal_cfg80211_mgmt_tx() corrupt data\n");
+		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) &&
+	    ieee80211_is_probe_resp(((struct ieee80211_mgmt *)buf)->
+				    frame_control)) {
+		PRINTM(MIOCTL, "Skip send probe_resp in GO/UAP mode\n");
+		goto done;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	if (ieee80211_is_action(((struct ieee80211_mgmt *)buf)->frame_control)) {
+#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 ((priv->phandle->chan.center_freq !=
+			     chan->center_freq)
+				) {
+				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 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;
+		}
+#ifdef STA_CFG80211
+		/** cancel pending scan */
+		woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+#endif
+
+		duration =
+			(wait >
+			 MGMT_TX_DEFAULT_WAIT_TIME) ? wait :
+			MGMT_TX_DEFAULT_WAIT_TIME;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+		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 connnection fail */
+			woal_sched_timeout(2);
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+			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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+			priv->phandle->channel_type = channel_type;
+#endif
+			memcpy(&priv->phandle->chan, chan,
+			       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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+	*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;
+	/* Add pkt_type and tx_control */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset, &pkt_type, sizeof(pkt_type));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type), &tx_control,
+	       sizeof(tx_control));
+	/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */
+#define PACKET_ADDR4_POS		(2 + 2 + 6 + 6 + 6 + 2)
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &packet_len,
+	       sizeof(packet_len));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
+	       sizeof(packet_len), buf, PACKET_ADDR4_POS);
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
+	       sizeof(packet_len)
+	       + PACKET_ADDR4_POS, addr, MLAN_MAC_ADDR_LENGTH);
+	memcpy(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);
+
+	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)) {
+		pmbuf->flags = MLAN_BUF_FLAG_TX_STATUS;
+		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) {
+				memcpy(skb->data, buf, 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;
+				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,
+		 * becuase 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 (tx_info)
+				break;
+			else
+				woal_sched_timeout(30);
+		}
+
+		/* Notify the mgmt tx status */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		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 int
+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 *custom_ie = NULL;
+	t_u8 *pos = NULL;
+	t_u16 len = 0;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	custom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), GFP_KERNEL);
+	if (!custom_ie) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	custom_ie->type = TLV_TYPE_MGMT_IE;
+
+	pos = (t_u8 *)custom_ie->ie_data_list;
+	if (beacon_ies_data) {
+		len = sizeof(*beacon_ies_data) - MAX_IE_SIZE
+			+ beacon_ies_data->ie_length;
+		memcpy(pos, beacon_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+
+	if (proberesp_ies_data) {
+		len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE
+			+ proberesp_ies_data->ie_length;
+		memcpy(pos, proberesp_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+
+	if (assocresp_ies_data) {
+		len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE
+			+ assocresp_ies_data->ie_length;
+		memcpy(pos, assocresp_ies_data, len);
+		custom_ie->len += len;
+	}
+
+	if (probereq_ies_data) {
+		len = sizeof(*probereq_ies_data) - MAX_IE_SIZE
+			+ probereq_ies_data->ie_length;
+		memcpy(pos, probereq_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+	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;
+
+	memcpy(&misc->param.cust_ie, custom_ie, sizeof(mlan_ds_misc_custom_ie));
+
+	status = woal_request_ioctl(priv, ioctl_req, wait_option);
+	if (MLAN_STATUS_SUCCESS != status) {
+		ret = -EFAULT;
+		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;
+	}
+
+	if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL)
+		ret = -EFAULT;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	kfree(custom_ie);
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,14,0)
+/**
+ * @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;
+
+		memcpy(qos_map_ie.data, (t_u8 *)qos_map->dscp_exception,
+		       2 * qos_map->num_des);
+		memcpy(&qos_map_ie.data[2 * qos_map->num_des],
+		       (t_u8 *)qos_map->up, sizeof(qos_map->up));
+		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);
+
+		/* 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 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_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 */
+					memcpy(ie_out + out_len, pos,
+					       length + 2);
+					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) {
+					memcpy(ie_out + out_len, pos,
+					       length + 2);
+					out_len += length + 2;
+				}
+			} 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) {
+					memcpy(ie_out + out_len, pos,
+					       length + 2);
+					out_len += length + 2;
+				}
+			} else if (mask & IE_MASK_VENDOR) {
+				memcpy(ie_out + out_len, pos, length + 2);
+				out_len += length + 2;
+			}
+		}
+		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 specifc 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;
+	t_u8 id = 0;
+
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		id = *pos;
+		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 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_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;
+
+	/* 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;
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+		case WLAN_EID_ERP_INFO:
+		case HT_CAPABILITY:
+		case HT_OPERATION:
+		case VHT_CAPABILITY:
+		case VHT_OPERATION:
+		case REGULATORY_CLASS:
+		case OVERLAPBSSSCANPARAM:
+		case WAPI_IE:
+			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;
+			}
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			break;
+		default:
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			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
+ */
+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 > sizeof(TLV_Generic_t)) {
+		tlv_type = ntohs(tlv->type);
+		tlv_len = ntohs(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,
+						       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 (MLAN_STATUS_SUCCESS !=
+		    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;
+	}
+
+	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;
+			assocresp_ies_data->ie_length = assocresp_ies_len;
+			pos = assocresp_ies_data->ie_buffer;
+			memcpy(pos, assocresp_ies, assocresp_ies_len);
+			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_SUCCESS !=
+		    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 (MLAN_CUSTOM_IE_AUTO_IDX_MASK == beacon_vendor_index)
+				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,
+						     IE_MASK_VENDOR);
+			DBG_HEXDUMP(MCMD_D, "beacon vendor IE",
+				    beacon_ies_data->ie_buffer,
+				    beacon_ies_data->ie_length);
+		} else if (beacon_vendor_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+			/* 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 &&
+		     (beacon_vendor_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK))) {
+			if (MLAN_STATUS_SUCCESS !=
+			    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,
+						       IE_MASK_WPS | IE_MASK_WFD
+						       | IE_MASK_P2P |
+						       IE_MASK_VENDOR,
+						       proberesp_ies,
+						       proberesp_ies_len);
+			DBG_HEXDUMP(MCMD_D, "beacon ie",
+				    beacon_ies_data->ie_buffer,
+				    beacon_ies_data->ie_length);
+		} 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, 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 &&
+		     (proberesp_p2p_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK))) {
+			if (MLAN_STATUS_SUCCESS !=
+			    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 (MLAN_CUSTOM_IE_AUTO_IDX_MASK == proberesp_index)
+				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,
+						       IE_MASK_P2P |
+						       IE_MASK_VENDOR, NULL, 0);
+			DBG_HEXDUMP(MCMD_D, "proberesp ie",
+				    proberesp_ies_data->ie_buffer,
+				    proberesp_ies_data->ie_length);
+		} 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 (MLAN_CUSTOM_IE_AUTO_IDX_MASK == assocresp_index)
+				assocresp_ies_data->mgmt_subtype_mask |=
+					MLAN_CUSTOM_IE_NEW_MASK;
+			assocresp_ies_data->ie_length = assocresp_ies_len;
+			pos = assocresp_ies_data->ie_buffer;
+			memcpy(pos, assocresp_ies, assocresp_ies_len);
+			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;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+			if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
+				/* filter out P2P/WFD ie */
+				probereq_ies_data->ie_length =
+					woal_filter_beacon_ies(priv,
+							       probereq_ies,
+							       probereq_ies_len,
+							       probereq_ies_data->
+							       ie_buffer,
+							       IE_MASK_P2P |
+							       IE_MASK_WFD,
+							       NULL, 0);
+			} else {
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+				probereq_ies_data->ie_length = probereq_ies_len;
+				pos = probereq_ies_data->ie_buffer;
+				memcpy(pos, probereq_ies, probereq_ies_len);
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+			}
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+			DBG_HEXDUMP(MCMD_D, "probereq ie",
+				    probereq_ies_data->ie_buffer,
+				    probereq_ies_data->ie_length);
+		} 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 (MLAN_STATUS_SUCCESS !=
+	    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 informations
+ *  @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)
+		memcpy(ht_info->mcs.rx_mask, mcs_set,
+		       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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+/**
+ *  @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 (MLAN_STATUS_SUCCESS != status) {
+		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 = (t_u16)cfg_11ac->param.vht_cfg.vht_rx_mcs;
+	vht_cap->vht_mcs.rx_highest =
+		(t_u16)cfg_11ac->param.vht_cfg.vht_rx_max_rate;
+	vht_cap->vht_mcs.tx_mcs_map = (t_u16)cfg_11ac->param.vht_cfg.vht_tx_mcs;
+	vht_cap->vht_mcs.tx_highest =
+		(t_u16)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();
+	return;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ * @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();
+	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
+
+/**
+ * @brief Get second channel offset
+ *
+ * @param chan             channel num
+ * @return                second channel offset
+ */
+t_u8
+woal_get_second_channel_offset(int chan)
+{
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+
+	switch (chan) {
+	case 36:
+	case 44:
+	case 52:
+	case 60:
+	case 100:
+	case 108:
+	case 116:
+	case 124:
+	case 132:
+	case 140:
+	case 149:
+	case 157:
+		chan2Offset = SEC_CHAN_ABOVE;
+		break;
+	case 40:
+	case 48:
+	case 56:
+	case 64:
+	case 104:
+	case 112:
+	case 120:
+	case 128:
+	case 136:
+	case 144:
+	case 153:
+	case 161:
+		chan2Offset = SEC_CHAN_BELOW;
+		break;
+	case 165:
+		/* Special Case: 20Mhz-only Channel */
+		chan2Offset = SEC_CHAN_NONE;
+		break;
+	}
+	return chan2Offset;
+}
diff --git a/wlan_sd8897/mlinux/moal_cfg80211.h b/wlan_sd8897/mlinux/moal_cfg80211.h
new file mode 100644
index 0000000..e5ed6ab
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_cfg80211.h
@@ -0,0 +1,442 @@
+/** @file moal_cfg80211.h
+  *
+  * @brief This file contains the CFG80211 specific defines.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _MOAL_CFG80211_H_
+#define _MOAL_CFG80211_H_
+
+#include    "moal_main.h"
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR
+#define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+#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
+
+/* define for custom ie operation */
+#define MLAN_CUSTOM_IE_AUTO_IDX_MASK    0xffff
+#define MLAN_CUSTOM_IE_DELETE_MASK      0x0
+#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 MRVL_PKT_TYPE_MGMT_FRAME 0xE5
+
+/**
+ * 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 */
+moal_private *woal_get_scan_interface(moal_handle *handle);
+#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 CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
+				      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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+			  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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+			  bool pairwise,
+#endif
+			  const t_u8 *mac_addr);
+#ifdef STA_SUPPORT
+/** Opportunistic Key Caching APIs support */
+struct pmksa_entry *woal_get_pmksa_entry(moal_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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+	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,
+					     mlan_ssid_bssid *ssid_bssid,
+					     t_u8 wait_option);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+int woal_cfg80211_set_channel(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+			      struct net_device *dev,
+#endif
+			      struct ieee80211_channel *chan,
+			      enum nl80211_channel_type channel_type);
+#endif
+
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
+				       struct net_device *netdev,
+				       t_u8 key_index);
+#endif
+
+void woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+				       struct wireless_dev *wdev,
+#else
+				       struct net_device *dev,
+#endif
+				       t_u16 frame_type, bool reg);
+
+int woal_cfg80211_mgmt_tx(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+			  struct wireless_dev *wdev,
+#else
+			  struct net_device *dev,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			  struct cfg80211_mgmt_tx_params *params,
+#else
+			  struct ieee80211_channel *chan, bool offchan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+			  enum nl80211_channel_type channel_type,
+			  bool channel_type_valid,
+#endif
+			  unsigned int wait, const u8 *buf, size_t len,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+			  bool no_cck,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+			  bool dont_wait_for_ack,
+#endif
+#endif
+			  u64 * cookie);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+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;
+
+#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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+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);
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+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)
+/* 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);
+
+void woal_remove_virtual_interface(moal_handle *handle);
+
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+
+/** Define for remain on channel duration timer */
+#define MAX_REMAIN_ON_CHANNEL_DURATION      (1000)
+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 nl80211_channel_type channel_type,
+					t_u32 duration);
+
+#ifdef UAP_CFG80211
+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);
+
+int woal_uap_cfg80211_dump_station(struct wiphy *wiphy,
+				   struct net_device *dev, int idx,
+				   t_u8 *mac, struct station_info *sinfo);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+int woal_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
+			     struct bss_parameters *params);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+int woal_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *dev,
+			      const struct cfg80211_acl_data *params);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+int woal_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev,
+				 struct ieee80211_txq_params *params);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+int woal_cfg80211_set_coalesce(struct wiphy *wiphy,
+			       struct cfg80211_coalesce *coalesce);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+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 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, 12, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+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_cac_timer_func(void *context);
+void woal_csa_work_queue(struct work_struct *work);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+void woal_cfg80211_notify_uap_channel(moal_private *priv,
+				      chan_band_info * pchan_info);
+#endif
+#endif /* UAP_CFG80211 */
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+mlan_status woal_chandef_create(moal_private *priv,
+				struct cfg80211_chan_def *chandef,
+				chan_band_info * pchan_info);
+#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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+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);
+
+t_u8 woal_get_second_channel_offset(int chan);
+
+#endif /* _MOAL_CFG80211_H_ */
diff --git a/wlan_sd8897/mlinux/moal_cfgvendor.c b/wlan_sd8897/mlinux/moal_cfgvendor.c
new file mode 100644
index 0000000..c495bfd
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_cfgvendor.c
@@ -0,0 +1,4246 @@
+/** @file moal_cfgvendor.c
+  *
+  * @brief This file contains the functions for CFG80211 vendor.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include    "moal_cfgvendor.h"
+#include    "moal_cfg80211.h"
+
+/********************************************************
+				Local Variables
+********************************************************/
+
+/********************************************************
+				Global Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+/********************************************************
+				Local Functions
+********************************************************/
+
+/********************************************************
+				Global Functions
+********************************************************/
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+/**marvell vendor command and event*/
+#define MRVL_VENDOR_ID  0x005043
+/** vendor events */
+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_rssi_monitor,},	/*event_id 0x1501 */
+	{.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,},
+	{.vendor_id = MRVL_VENDOR_ID,.subcmd = event_nan_cb,},
+	/**add vendor event here*/
+};
+
+/**
+ * @brief get the event id of the events array
+ *
+ * @param event     vendor event
+ *
+ * @return    index of events array
+ */
+int
+woal_get_event_id(int event)
+{
+	int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(vendor_events); i++) {
+		if (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(IN moal_private *priv,
+			   IN int event, IN t_u8 *data, IN 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL, 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);
+	memcpy(pos, data, len);
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief send vendor event to kernel
+ *
+ * @param priv       A pointer to moal_private
+ * @param event    vendor event
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+struct sk_buff *
+woal_cfg80211_alloc_vendor_event(IN moal_private *priv,
+				 IN int event, IN int len)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int event_id = 0;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "Not find this event %d \n", event_id);
+		goto done;
+	}
+	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);
+		goto done;
+	}
+
+	/**allocate skb*/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL, 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");
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return skb;
+}
+
+/**
+ * @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();
+	return;
+}
+
+/**
+ * @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));
+	memcpy(pos, &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];
+	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 woal_cfg80211_subcmd_get_valid_channels\n");
+
+	err = nla_parse(tb, ATTR_WIFI_MAX, data, len, NULL
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err) {
+		PRINTM(MERROR, "%s: nla_parse fail\n", __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+
+	if (!tb[ATTR_CHANNELS_BAND]) {
+		PRINTM(MERROR, "%s: null attr: tb[ATTR_GET_CH]=%p\n",
+		       __FUNCTION__, 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", __FUNCTION__, 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;
+	}
+
+	nla_put_u32(skb, ATTR_NUM_CHANNELS, nchannel);
+	nla_put(skb, ATTR_CHANNEL_LIST, nchannel * sizeof(ch_out[0]), ch_out);
+	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();
+	memcpy(drv_version, &priv->phandle->driver_version,
+	       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)
+		memcpy(pos, pos + 3, strlen(pos) - 3);
+
+	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->firmware_dump_file) {
+		memset(handle->firmware_dump_file, 0,
+		       sizeof(handle->firmware_dump_file));
+	}
+	woal_dump_firmware_info_v3(handle);
+
+	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];
+	char path_name[64];
+	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(path_name, 0, sizeof(path_name));
+	woal_create_dump_dir(handle, path_name, sizeof(path_name));
+	PRINTM(MMSG, "driver dump path name is %s\n", path_name);
+	woal_dump_drv_info(handle, path_name);
+	memset(driver_dump_file, 0, sizeof(driver_dump_file));
+	sprintf(driver_dump_file, "%s/%s", path_name, "file_drv_info");
+	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;
+	}
+	nla_put_string(skb, ATTR_DRV_DUMP_PATH, driver_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 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;
+	t_u32 reply_len = 0;
+	int ret = 0;
+	t_u32 supp_feature_set = 0;
+	ENTER();
+
+	supp_feature_set = WIFI_FEATURE_INFRA
+#if defined(UAP_SUPPORT) && defined(STA_SUPPORT)
+		| WIFI_FEATURE_AP_STA
+#endif
+		| WIFI_FEATURE_LINK_LAYER_STATS
+		| WIFI_FEATURE_LOGGER | WIFI_FEATURE_RSSI_MONITOR;
+
+	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;
+	}
+	nla_put_u32(skb, ATTR_FEATURE_SET, supp_feature_set);
+	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 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(sizeof(country) - 1, nla_len(iter)));
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			return ret;
+		}
+	}
+
+	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;
+	}
+	nla_put_u32(skb, ATTR_WIFI_LOGGER_FEATURE_SET, supp_feature_set);
+	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 (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",
+			       __FUNCTION__, status->name, status->ring_id,
+			       status->ring_buffer_byte_size,
+			       status->written_bytes, status->written_records,
+			       status->read_bytes);
+			break;
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ * @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;
+	}
+
+	/* shoud 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);
+		memcpy(&status[ring_cnt++], &ring_status,
+		       sizeof(wifi_ring_buffer_status));
+	}
+
+	nla_put_u32(skb, ATTR_NUM_RINGS, ring_cnt);
+	nla_put(skb, ATTR_RING_BUFFER_STATUS,
+		sizeof(wifi_ring_buffer_status) * ring_cnt, status);
+
+	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 (!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",
+	       __FUNCTION__, log_level, time_intval, threshold);
+
+	ring_buffer = (wifi_ring_buffer *) priv->rings[ring_id];
+	if (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 {
+		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->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 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);
+
+	ENTER();
+
+	if (!entry->entry_size) {
+		entry = (wifi_ring_buffer_entry *) ring->ring_buf;
+		LEAVE();
+		return ENTRY_LENGTH(entry);
+	}
+
+	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 avail_len, r_len = 0;
+	unsigned long flags;
+	wifi_ring_buffer *ring;
+	wifi_ring_buffer_entry *hdr;
+
+	ENTER();
+
+	ring = (wifi_ring_buffer *) priv->rings[ring_id];
+	if (ring->state != RING_ACTIVE) {
+		PRINTM(MERROR, "Ring is not active!\n");
+		goto done;
+	}
+
+	spin_lock_irqsave(&ring->lock, flags);
+
+	/* get a fresh pending length */
+	avail_len = READ_AVAIL_SPACE(ring->wp, ring->rp, ring->ring_size);
+	while (avail_len > 0 && buf_len > 0) {
+		hdr = woal_get_ring_entry(ring, ring->rp);
+		memcpy(data, hdr, ENTRY_LENGTH(hdr));
+		r_len += ENTRY_LENGTH(hdr);
+		/* update read pointer */
+		ring->rp = woal_get_ring_next_entry(ring, ring->rp);
+		data += ENTRY_LENGTH(hdr);
+		avail_len -= ENTRY_LENGTH(hdr);
+		buf_len -= ENTRY_LENGTH(hdr);
+		ring->ctrl.read_bytes += ENTRY_LENGTH(hdr);
+		PRINTM(MINFO, "%s read_bytes  %d\n", __FUNCTION__,
+		       ring->ctrl.read_bytes);
+	}
+	spin_unlock_irqrestore(&ring->lock, flags);
+
+done:
+	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
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_ring_buffer_data_vendor_event(IN moal_private *priv, IN int ring_id,
+				   IN t_u8 *data, IN int len)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int event_id = 0;
+	int ret = 0;
+	wifi_ring_buffer_status ring_status;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "priv is null \n");
+		ret = -EINVAL;
+		goto done;
+	}
+	wiphy = priv->wdev->wiphy;
+	PRINTM(MEVENT, "woal_ring_buffer_data_vendor_event ring_id:%d\n",
+	       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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL,
+					  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;
+	}
+
+	woal_get_ring_status(priv, ring_id, &ring_status);
+
+	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, const 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);
+
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ * @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;
+	wifi_ring_buffer_entry *hdr;
+	t_s32 buflen, rlen;
+
+	ENTER();
+
+	woal_get_ring_status(priv, ringid, &ring_status);
+	PRINTM(MINFO, "woal_ring_poll_worker write %d, read %d, size %d\n",
+	       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;
+	else if (ring_status.written_bytes < ring_status.read_bytes)
+		buflen = ring_status.ring_buffer_byte_size +
+			ring_status.written_bytes - ring_status.read_bytes;
+	else {
+		PRINTM(MERROR, "No new records\n");
+		goto exit;
+	}
+
+	buf = kmalloc(buflen, GFP_KERNEL);
+	if (!buf) {
+		PRINTM(MERROR, "%s failed to allocate read buf\n",
+		       __FUNCTION__);
+		LEAVE();
+		return;
+	}
+	rlen = woal_ring_pull_data(priv, ringid, buf, buflen);
+	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));
+	}
+	kfree(buf);
+
+	if (!ring_info->interval) {
+		LEAVE();
+		return;
+	}
+	woal_get_ring_status(priv, ring_info->ring_id, &ring_status);
+
+exit:
+	if (ring_info->interval) {
+		/* retrigger the work at same interval */
+		if (READ_AVAIL_SPACE
+		    (ring_info->wp, ring_info->rp, ring_info->ring_size) <= 0)
+			schedule_delayed_work(d_work, ring_info->interval);
+		else
+			schedule_delayed_work(d_work, 0);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @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->state != RING_ACTIVE) {
+		PRINTM(MERROR, "Ring is not active\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	spin_lock_irqsave(&ring->lock, flags);
+
+	w_len = ENTRY_LENGTH(hdr);
+	/* prep the space */
+	do {
+		if (ring->rp == ring->wp)
+			break;
+		if (ring->rp < ring->wp) {
+			if (ring->ring_size - ring->wp == w_len) {
+				if (ring->rp == 0)
+					ring->rp =
+						woal_get_ring_next_entry(ring,
+									 ring->
+									 rp);
+				break;
+			} else if (ring->ring_size - ring->wp < w_len) {
+				if (ring->rp == 0)
+					ring->rp =
+						woal_get_ring_next_entry(ring,
+									 ring->
+									 rp);
+				ring->wp = 0;
+				continue;
+			} else {
+				break;
+			}
+		}
+		if (ring->rp > ring->wp) {
+			if (ring->rp - ring->wp <= w_len) {
+				ring->rp =
+					woal_get_ring_next_entry(ring,
+								 ring->rp);
+				if (ring->rp >= ring->ring_size) {
+					PRINTM(MINFO,
+					       "log size exceed ring size\n");
+					ring->rp = 0;
+					break;
+				} else
+					continue;
+			} else {
+				break;
+			}
+		}
+	} while (1);
+
+	w_entry = (wifi_ring_buffer_entry *) (ring->ring_buf + ring->wp);
+	/* header */
+	memcpy(w_entry, hdr, RING_ENTRY_SIZE);
+	/* payload */
+	memcpy((char *)w_entry + RING_ENTRY_SIZE, data, 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(MINFO, "%s : written_records %d, written_bytes %d\n",
+	       __FUNCTION__, ring->ctrl.written_records,
+	       ring->ctrl.written_bytes);
+
+	/* if the current pending size is bigger than threshold */
+	if (ring->threshold > 0 &&
+	    (READ_AVAIL_SPACE(ring->wp, ring->rp, ring->ring_size) >=
+	     ring->threshold) && ring->interval != 0)
+		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));
+	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");
+	}
+	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);
+	memcpy(ring_buff->name, name, MIN(strlen(name), RING_NAME_MAX));
+	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);
+
+	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 - 1; i++) {
+		ring_buff = (wifi_ring_buffer *) priv->rings[i];
+		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->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;
+			if (pbss_desc->oui) {
+				tlv = (tlv_log *) pos;
+				tlv->tag = WIFI_TAG_VENDOR_SPECIFIC;
+				tlv->length = MLAN_MAC_ADDR_LENGTH / 2;
+				memcpy(tlv->value, pbss_desc->oui, tlv->length);
+				msg_hdr.entry_size +=
+					tlv->length + TLV_LOG_HEADER_LEN;
+				pos = pos + tlv->length + TLV_LOG_HEADER_LEN;
+			}
+			if (pbss_desc->bssid) {
+				tlv = (tlv_log *) pos;
+				tlv->tag = WIFI_TAG_BSSID;
+				tlv->length = sizeof(pbss_desc->bssid);
+				memcpy(tlv->value, pbss_desc->bssid,
+				       sizeof(pbss_desc->bssid));
+				msg_hdr.entry_size +=
+					tlv->length + TLV_LOG_HEADER_LEN;
+				pos = pos + tlv->length + TLV_LOG_HEADER_LEN;
+			}
+			if (pbss_desc->ssid) {
+				tlv = (tlv_log *) pos;
+				tlv->tag = WIFI_TAG_SSID;
+				tlv->length = strlen(pbss_desc->ssid);
+				memcpy(tlv->value, pbss_desc->ssid,
+				       tlv->length);
+				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);
+				memcpy(tlv->value, &pbss_desc->rssi,
+				       tlv->length);
+				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);
+				memcpy(tlv->value, &pbss_desc->channel,
+				       sizeof(pbss_desc->channel));
+				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);
+			memcpy(tlv->value, &status_code, sizeof(status_code));
+			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);
+			memcpy(tlv->value, &reason_code, sizeof(reason_code));
+			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(IN moal_private *priv,
+			      IN 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL,
+					  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 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;
+
+	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;
+	}
+
+	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(IN moal_private *priv,
+			      IN packet_fate_packet_type pkt_type, IN t_u8 fate,
+			      IN frame_type payload_type, IN t_u32 drv_ts_usec,
+			      IN t_u32 fw_ts_usec, IN t_u8 *data, IN 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL,
+					  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(pkt_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(MCMD_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;
+	}
+
+	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);
+	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
+accept_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 memory[MEMORY_ITEMS] = { };
+	/* Register values. */
+	t_u32 registers[2] = { };
+	/* Count of instructions remaining to execute. This is done to ensure an
+	 * 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_remaining = 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_packet_offs;
+	t_u32 imm = 0;
+	int32_t signed_imm = 0;
+	t_u32 offs = 0;
+	t_u32 i;
+	t_u32 load_size;
+
+/* Is offset within program bounds? */
+#define IN_PROGRAM_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < program_len)
+/* Is offset within packet bounds? */
+#define IN_PACKET_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < packet_len)
+/* Verify an internal condition and accept packet if it fails. */
+#define ASSERT_RETURN(c) if (!(c)) return PASS_PACKET
+/* Accept packet if not within program bounds */
+#define ASSERT_IN_PROGRAM_BOUNDS(p) ASSERT_RETURN(IN_PROGRAM_BOUNDS(p))
+/* Accept packet if not within packet bounds */
+#define ASSERT_IN_PACKET_BOUNDS(p) ASSERT_RETURN(IN_PACKET_BOUNDS(p))
+/* Accept packet if not within program or not ahead of program counter */
+#define ASSERT_FORWARD_IN_PROGRAM(p) ASSERT_RETURN(IN_PROGRAM_BOUNDS(p) && (p) >= pc)
+
+	/* Fill in pre-filled memory slot values. */
+	memory[MEMORY_OFFSET_PACKET_SIZE] = packet_len;
+	memory[MEMORY_OFFSET_FILTER_AGE] = filter_age;
+	ASSERT_IN_PACKET_BOUNDS(APF_FRAME_HEADER_SIZE);
+
+	/* Only populate if IP version is IPv4. */
+	if ((packet[APF_FRAME_HEADER_SIZE] & 0xf0) == 0x40) {
+		memory[MEMORY_OFFSET_IPV4_HEADER_SIZE] =
+			(packet[APF_FRAME_HEADER_SIZE] & 15) * 4;
+	}
+
+	do {
+		if (pc == program_len) {
+			return PASS_PACKET;
+		} else if (pc == (program_len + 1)) {
+			return DROP_PACKET;
+		}
+		ASSERT_IN_PROGRAM_BOUNDS(pc);
+		bytecode = program[pc++];
+		opcode = EXTRACT_OPCODE(bytecode);
+		reg_num = EXTRACT_REGISTER(bytecode);
+
+		/* All instructions have immediate fields, so load them now. */
+		len_field = EXTRACT_IMM_LENGTH(bytecode);
+		imm = 0;
+		signed_imm = 0;
+
+#define REG (registers[reg_num])
+#define OTHER_REG (registers[reg_num ^ 1])
+
+		if (len_field != 0) {
+			imm_len = 1 << (len_field - 1);
+			ASSERT_FORWARD_IN_PROGRAM(pc + imm_len - 1);
+			for (i = 0; i < imm_len; i++)
+				imm = (imm << 8) | program[pc++];
+			/* Sign extend imm into signed_imm. */
+			signed_imm = imm << ((4 - imm_len) * 8);
+			signed_imm >>= (4 - imm_len) * 8;
+		}
+		switch (opcode) {
+		case LDB_OPCODE:
+		case LDH_OPCODE:
+		case LDW_OPCODE:
+		case LDBX_OPCODE:
+		case LDHX_OPCODE:
+		case LDWX_OPCODE:{
+				offs = imm;
+				if (opcode >= LDBX_OPCODE) {
+					/* Note: this can overflow and actually decrease offs. */
+					offs += registers[1];
+				}
+				ASSERT_IN_PACKET_BOUNDS(offs);
+				switch (opcode) {
+				case LDB_OPCODE:
+				case LDBX_OPCODE:
+					load_size = 1;
+					break;
+				case LDH_OPCODE:
+				case LDHX_OPCODE:
+					load_size = 2;
+					break;
+				case LDW_OPCODE:
+				case 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_IN_PACKET_BOUNDS(end_offs);
+				val = 0;
+				while (load_size--)
+					val = (val << 8) | packet[offs++];
+				REG = val;
+				break;
+			}
+		case JMP_OPCODE:
+			/* This can jump backwards. Infinite looping prevented by instructions_remaining. */
+			pc += imm;
+			break;
+		case JEQ_OPCODE:
+		case JNE_OPCODE:
+		case JGT_OPCODE:
+		case JLT_OPCODE:
+		case JSET_OPCODE:
+		case JNEBS_OPCODE:{
+				/* Load second immediate field. */
+				t_u32 cmp_imm = 0;
+				if (reg_num == 1) {
+					cmp_imm = registers[1];
+				} else if (len_field != 0) {
+					t_u32 cmp_imm_len =
+						1 << (len_field - 1);
+					ASSERT_FORWARD_IN_PROGRAM(pc +
+								  cmp_imm_len -
+								  1);
+					for (i = 0; i < cmp_imm_len; i++)
+						cmp_imm =
+							(cmp_imm << 8) |
+							program[pc++];
+				}
+				switch (opcode) {
+				case JEQ_OPCODE:
+					if (registers[0] == cmp_imm)
+						pc += imm;
+					break;
+				case JNE_OPCODE:
+					if (registers[0] != cmp_imm)
+						pc += imm;
+					break;
+				case JGT_OPCODE:
+					if (registers[0] > cmp_imm)
+						pc += imm;
+					break;
+				case JLT_OPCODE:
+					if (registers[0] < cmp_imm)
+						pc += imm;
+					break;
+				case JSET_OPCODE:
+					if (registers[0] & cmp_imm)
+						pc += imm;
+					break;
+				case 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_IN_PROGRAM(pc +
+									  cmp_imm
+									  - 1);
+						ASSERT_IN_PACKET_BOUNDS(REG);
+						last_packet_offs =
+							REG + cmp_imm - 1;
+						ASSERT_RETURN(last_packet_offs
+							      >= REG);
+						ASSERT_IN_PACKET_BOUNDS
+							(last_packet_offs);
+						if (memcmp
+						    (program + pc, packet + REG,
+						     cmp_imm))
+							pc += imm;
+						/* skip past comparison bytes */
+						pc += cmp_imm;
+						break;
+					}
+				}
+				break;
+			}
+		case ADD_OPCODE:
+			registers[0] += reg_num ? registers[1] : imm;
+			break;
+		case MUL_OPCODE:
+			registers[0] *= reg_num ? registers[1] : imm;
+			break;
+		case DIV_OPCODE:{
+				const t_u32 div_operand =
+					reg_num ? registers[1] : imm;
+				ASSERT_RETURN(div_operand);
+				registers[0] /= div_operand;
+				break;
+			}
+		case AND_OPCODE:
+			registers[0] &= reg_num ? registers[1] : imm;
+			break;
+		case OR_OPCODE:
+			registers[0] |= reg_num ? registers[1] : imm;
+			break;
+		case SH_OPCODE:{
+				const int32_t shift_val =
+					reg_num ? (int32_t) registers[1] :
+					signed_imm;
+				if (shift_val > 0)
+					registers[0] <<= shift_val;
+				else
+					registers[0] >>= -shift_val;
+				break;
+			}
+		case LI_OPCODE:
+			REG = signed_imm;
+			break;
+		case 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 LDM_EXT_OPCODE == 0
+				   ENFORCE_UNSIGNED(imm) &&
+#else
+				   imm >= LDM_EXT_OPCODE &&
+#endif
+				   imm < (LDM_EXT_OPCODE + MEMORY_ITEMS)) {
+				REG = memory[imm - LDM_EXT_OPCODE];
+			} else if (imm >= STM_EXT_OPCODE &&
+				   imm < (STM_EXT_OPCODE + MEMORY_ITEMS)) {
+				memory[imm - STM_EXT_OPCODE] = REG;
+			} else
+				switch (imm) {
+				case NOT_EXT_OPCODE:
+					REG = ~REG;
+					break;
+				case NEG_EXT_OPCODE:
+					REG = -REG;
+					break;
+				case SWAP_EXT_OPCODE:{
+						t_u32 tmp = REG;
+						REG = OTHER_REG;
+						OTHER_REG = tmp;
+						break;
+					}
+				case MOV_EXT_OPCODE:
+					REG = OTHER_REG;
+					break;
+					/* Unknown extended opcode */
+				default:
+					/* Bail out */
+					return PASS_PACKET;
+				}
+			break;
+			/* Unknown opcode */
+		default:
+			/* Bail out */
+			return PASS_PACKET;
+		}
+	} while (instructions_remaining--);
+	return PASS_PACKET;
+}
+
+/**
+ * @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_PACKET;
+	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(MCMD_D, "packet_filter_program",
+		    pkt_filter->packet_filter_program,
+		    pkt_filter->packet_filter_len);
+	DBG_HEXDUMP(MCMD_D, "packet_filter_data", data, len);
+	spin_lock_irqsave(&pkt_filter->lock, flags);
+	ret = accept_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 send vendor event to kernel
+ *
+ * @param priv     A pointer to moal_private
+ * @param cmd      nan_cmd
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_nan_vendor_event(IN moal_private *priv, nan_cmd cmd)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int ret = 0;
+	int event_id = 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, "woal_nan_worker\n");
+	event_id = woal_get_event_id(event_nan_cb);
+	if (event_max == event_id) {
+		PRINTM(MERROR, "Not find this event %d \n", event_id);
+		ret = -EINVAL;
+		goto done;
+	}
+
+/**allocate skb*/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL, sizeof(nan_cmd),
+					  event_id, GFP_ATOMIC);
+#else
+	skb = cfg80211_vendor_event_alloc(wiphy, sizeof(nan_cmd), event_id,
+					  GFP_ATOMIC);
+#endif
+
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor event\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	nla_put(skb, ATTR_NAN_FAKE, sizeof(NanHeader_Ext), &cmd.nan_header_ext);
+
+	if (cmd.indicate_enable) {
+		nla_put_u32(skb, ATTR_NAN_IND, cmd.indicate_type);
+	}
+
+	PRINTM(MCMND, "woal_nan_vendor_event %d, %d, %d,%d\n",
+	       cmd.nan_header_ext.nan_header.MsgId,
+	       cmd.nan_header_ext.nan_header.transactionId, cmd.indicate_enable,
+	       cmd.indicate_type);
+
+    /**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief worker to send vendor event
+ *
+ * @param work       A pointer to work_struct struct
+ *
+ * @return void
+ */
+void
+woal_nan_worker(struct work_struct *work)
+{
+	struct delayed_work *d_work = to_delayed_work(work);
+	nan_cb *nan = container_of(d_work, nan_cb, response_work);
+	moal_private *priv = nan->priv;
+	nan_cmd cmd;
+	int ret;
+	ENTER();
+
+	PRINTM(MCMND, "fifo len: %u\n", kfifo_len(&nan->cmd_fifo));
+
+	ret = kfifo_out_peek(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+	PRINTM(MCMND, "fifo ret: %u\n", ret);
+
+	if (ret) {
+		kfifo_out(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+	} else {
+		PRINTM(MERROR, "not enough element:\n");
+		goto done;
+	}
+
+	woal_nan_vendor_event(priv, cmd);
+
+	ret = kfifo_out_peek(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+
+	if (ret)
+		schedule_delayed_work(&nan->response_work, 0);
+
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief init nan in moal_private
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_init_nan(moal_private *priv)
+{
+	int ret = 0;
+	nan_cb *nan;
+	moal_handle *phandle = priv->phandle;
+	ENTER();
+
+	nan = vmalloc(sizeof(nan_cb));
+	if (!unlikely(nan)) {
+		PRINTM(MERROR, "WiFi Logger: packet_filter alloc failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (!unlikely(phandle)) {
+		PRINTM(MERROR, "WiFi Logger: phandle is null\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	memset(nan, 0, sizeof(nan_cb));
+	INIT_DELAYED_WORK(&nan->response_work, woal_nan_worker);
+	nan->priv = priv;
+
+	ret = kfifo_alloc(&nan->cmd_fifo, CMD_FIFO_SIZE * sizeof(nan_cmd),
+			  GFP_KERNEL);
+	if (ret) {
+		PRINTM(MERROR, "error kfifo_alloc\n");
+		goto done;
+	}
+
+	priv->nan_cb = nan;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief deinit nan in moal_private
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_deinit_nan(moal_private *priv)
+{
+	int ret = 0;
+	nan_cb *nan = NULL;
+
+	ENTER();
+
+	nan = priv->nan_cb;
+
+	if (!unlikely(nan)) {
+		goto done;
+	}
+
+	cancel_delayed_work_sync(&nan->response_work);
+
+	kfifo_free(&nan->cmd_fifo);
+
+	vfree(nan);
+	priv->nan_cb = NULL;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to enable nan
+ *
+ * @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
+nan_handler(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;
+	t_u32 reply_len = 0;
+	int ret = 0;
+	int rem, type;
+
+	const struct nlattr *iter;
+	nan_cb *nan = priv->nan_cb;
+	nan_cmd cmd;
+	t_u32 indicate_number_total = 0;
+	t_u32 indicate_array[MAX_INDICATE_ARRAY_SIZE] = { 0 };
+	int i = 0;
+
+	ENTER();
+
+	memset(&cmd, 0, sizeof(nan_cmd));
+    /** 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 (!unlikely(nan)) {
+		PRINTM(MERROR, "WiFi hal: nan not init\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case ATTR_NAN_FAKE:
+			memcpy(&cmd, nla_data(iter), sizeof(NanHeader));
+			PRINTM(MCMND, "ATTR_NAN_FAKE %d, %d\n",
+			       cmd.nan_header_ext.nan_header.MsgId,
+			       cmd.nan_header_ext.nan_header.transactionId);
+			break;
+		case ATTR_NAN_IND:
+			indicate_array[indicate_number_total] =
+				nla_get_u32(iter);
+			indicate_number_total++;
+			PRINTM(MCMND, "ATTR_NAN_IND %d, %d\n",
+			       indicate_array[indicate_number_total - 1],
+			       indicate_number_total);
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	cmd.indicate_enable = 0;
+	kfifo_in(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+	PRINTM(MCMND, "fifo len: %u\n", kfifo_len(&nan->cmd_fifo));
+
+	for (i = 0; i < MAX_INDICATE_ARRAY_SIZE && i < indicate_number_total;
+	     i++) {
+		cmd.indicate_enable = 1;
+		cmd.indicate_type = indicate_array[i];
+		kfifo_in(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+		PRINTM(MCMND, "fifo len: %u\n", kfifo_len(&nan->cmd_fifo));
+		DBG_HEXDUMP(MCMD_D, "nan_cmd", (t_u8 *)&cmd, sizeof(nan_cmd));
+	}
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+
+	schedule_delayed_work(&nan->response_work, 0);
+
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to enable nan
+ *
+ * @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_nan_enable_req(struct wiphy *wiphy,
+				    struct wireless_dev *wdev, const void *data,
+				    int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to disable nan
+ *
+ * @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_nan_disable_req(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to nan publish req
+ *
+ * @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_nan_publish_req(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to cancel nan publish
+ *
+ * @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_nan_publish_cancel(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to nan subscribe req
+ *
+ * @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_nan_subscribe_req(struct wiphy *wiphy,
+				       struct wireless_dev *wdev,
+				       const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to cancel nan subscribe
+ *
+ * @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_nan_subscribe_cancel(struct wiphy *wiphy,
+					  struct wireless_dev *wdev,
+					  const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to trasmit followup
+ *
+ * @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_nan_trasmit_followup(struct wiphy *wiphy,
+					  struct wireless_dev *wdev,
+					  const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to req nan stats
+ *
+ * @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_nan_stats_req(struct wiphy *wiphy,
+				   struct wireless_dev *wdev, const void *data,
+				   int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to config nan
+ *
+ * @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_nan_config_req(struct wiphy *wiphy,
+				    struct wireless_dev *wdev, const void *data,
+				    int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to nan tca req
+ *
+ * @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_nan_tca_req(struct wiphy *wiphy, struct wireless_dev *wdev,
+				 const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to beacon sdf payload
+ *
+ * @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_nan_beacon_sdf_payload(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get nan 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_nan_get_version(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get nan 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_nan_get_capability(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to data if create
+ *
+ * @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_nan_data_if_create(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to data if delete
+ *
+ * @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_nan_data_if_delete(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to data req initor
+ *
+ * @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_nan_data_req_initor(struct wiphy *wiphy,
+					 struct wireless_dev *wdev,
+					 const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to data indication resp
+ *
+ * @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_nan_data_indi_resp(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to date end
+ *
+ * @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_nan_data_end(struct wiphy *wiphy,
+				  struct wireless_dev *wdev, const void *data,
+				  int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	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);
+	woal_init_nan(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);
+	woal_deinit_nan(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_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;
+	mlan_ds_get_stats stats;
+
+	/* 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;
+	}
+
+	/* Get Log 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");
+		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);
+
+	iface_stat =
+		(wifi_iface_stat *) (info->param.link_statistic +
+				     sizeof(num_radio) + radio_stat_len);
+	iface_stat_len = sizeof(wifi_iface_stat);
+	/* Fill some fileds */
+	iface_stat->beacon_rx = stats.bcn_rcv_cnt;
+
+	/* could get peer info with seperate 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);
+		goto done;
+	}
+	PRINTM(MCMD_D, "num_radio=%d\n", num_radio);
+	DBG_HEXDUMP(MCMD_D, "radio_stat", (t_u8 *)radio_stat, radio_stat_len);
+	DBG_HEXDUMP(MCMD_D, "iface_stat", (t_u8 *)iface_stat, iface_stat_len);
+
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err)
+		return err;
+
+	if (!tb[ATTR_LL_STATS_MPDU_SIZE_THRESHOLD] ||
+	    !tb[ATTR_LL_STATS_AGGRSSIVE_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_AGGRSSIVE_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 */
+	memcpy(info->param.link_statistic, &ll_params, sizeof(ll_params));
+
+	/* 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, 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, "enable 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);
+		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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, 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);
+	memcpy(pos, data, 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:
+			memcpy((t_u8 *)&blacklist, nla_data(iter),
+			       sizeof(wifi_bssid_params));
+			break;
+		case MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONFIG_SSID:
+			memcpy((t_u8 *)&whitelist, nla_data(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 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;
+	int ret = 1;
+
+	ENTER();
+
+	/** 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;
+}
+
+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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+#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,
+	 },
+#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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+
+	{
+	 .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,
+	 },
+
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_enable_req,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_enable_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_disable_req,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_disable_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_publish_req,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_publish_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_publish_cancel,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_publish_cancel,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_subscribe_req,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_subscribe_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_subscribe_cancel,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_subscribe_cancel,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_trasmit_followup,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_trasmit_followup,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_stats_req,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_stats_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_config_req,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_config_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_tca_req,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_tca_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_beacon_sdf_payload,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_beacon_sdf_payload,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_get_version,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_get_version,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_get_capa,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_get_capability,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_data_if_create,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_if_create,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_data_if_delete,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_if_delete,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_data_req_initor,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_req_initor,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_data_indi_resp,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_indi_resp,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_data_end,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_end,
+	 },
+};
+
+/**
+ * @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_sd8897/mlinux/moal_cfgvendor.h b/wlan_sd8897/mlinux/moal_cfgvendor.h
new file mode 100644
index 0000000..badf982
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_cfgvendor.h
@@ -0,0 +1,798 @@
+/** @file moal_cfgvendor.h
+  *
+  * @brief This file contains the CFG80211 vendor specific defines.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _MOAL_CFGVENDOR_H_
+#define _MOAL_CFGVENDOR_H_
+
+#include   "moal_main.h"
+#include   "linux/kfifo.h"
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#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(w, r, d) ((w >= r) ? (w - r) : (d - r))
+
+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 {
+	RING_BUFFER_ENTRY_FLAGS_HAS_BINARY = (1 << (0)),	// set for binary entries
+	RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP = (1 << (1))	// set if 64 bits timestamp is present
+};
+
+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[0];
+} __attribute__ ((packed)) tlv_log;
+
+/** WiFi ring buffer driver structure */
+typedef struct {
+    /** event */
+	u16 event;
+    /** TLV log structure array */
+	tlv_log tlvs[0];
+    /** 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 MEMORY_ITEMS 16
+/* Upon program execution starting some memory slots are prefilled: */
+/* 4*([APF_FRAME_HEADER_SIZE]&15) */
+#define MEMORY_OFFSET_IPV4_HEADER_SIZE 13
+/* Size of packet in bytes. */
+#define MEMORY_OFFSET_PACKET_SIZE 14
+/* Age since filter installed in seconds. */
+#define MEMORY_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 LDB_OPCODE 1
+/* Load 2 bytes from immediate offset, e.g. "ldh R0, [5]" */
+#define LDH_OPCODE 2
+/* Load 4 bytes from immediate offset, e.g. "ldw R0, [5]" */
+#define LDW_OPCODE 3
+/* Load 1 byte from immediate offset plus register, e.g. "ldbx R0, [5]R0" */
+#define LDBX_OPCODE 4
+/* Load 2 byte from immediate offset plus register, e.g. "ldhx R0, [5]R0" */
+#define LDHX_OPCODE 5
+/* Load 4 byte from immediate offset plus register, e.g. "ldwx R0, [5]R0" */
+#define LDWX_OPCODE 6
+/* Add, e.g. "add R0,5" */
+#define ADD_OPCODE 7
+/* Multiply, e.g. "mul R0,5" */
+#define MUL_OPCODE 8
+/* Divide, e.g. "div R0,5" */
+#define DIV_OPCODE 9
+/* And, e.g. "and R0,5" */
+#define AND_OPCODE 10
+/* Or, e.g. "or R0,5" */
+#define OR_OPCODE 11
+/* Left shift, e.g, "sh R0, 5" or "sh R0, -5" (shifts right) */
+#define SH_OPCODE 12
+/* Load immediate, e.g. "li R0,5" (immediate encoded as signed value) */
+#define LI_OPCODE 13
+/* Unconditional jump, e.g. "jmp label" */
+#define JMP_OPCODE 14
+/* Compare equal and branch, e.g. "jeq R0,5,label" */
+#define JEQ_OPCODE 15
+/* Compare not equal and branch, e.g. "jne R0,5,label" */
+#define JNE_OPCODE 16
+/* Compare greater than and branch, e.g. "jgt R0,5,label" */
+#define JGT_OPCODE 17
+/* Compare less than and branch, e.g. "jlt R0,5,label" */
+#define JLT_OPCODE 18
+/* Compare any bits set and branch, e.g. "jset R0,5,label" */
+#define JSET_OPCODE 19
+/* Compare not equal byte sequence, e.g. "jnebs R0,5,label,0x1122334455" */
+#define 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 EXT_OPCODE 21
+/* Load from memory, e.g. "ldm R0,5"
+ * Values 0-15 represent loading the different memory slots. */
+#define LDM_EXT_OPCODE 0
+/* Store to memory, e.g. "stm R0,5" *
+ * Values 16-31 represent storing to the different memory slots. */
+#define STM_EXT_OPCODE 16
+/* Not, e.g. "not R0" */
+#define NOT_EXT_OPCODE 32
+/* Negate, e.g. "neg R0" */
+#define NEG_EXT_OPCODE 33
+/* Swap, e.g. "swap R0,R1" */
+#define SWAP_EXT_OPCODE 34
+/* Move, e.g. "move R0,R1" */
+#define MOV_EXT_OPCODE 35
+
+#define EXTRACT_OPCODE(i) (((i) >> 3) & 31)
+#define EXTRACT_REGISTER(i) ((i)&1)
+#define EXTRACT_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_PACKET 1
+/* Return code indicating "packet" should be dropped. */
+#define DROP_PACKET 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_MAX,
+};
+
+/** 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);
+
+#define CMD_FIFO_SIZE 8
+#define MAX_INDICATE_ARRAY_SIZE 5
+
+enum {
+	ATTR_NAN_FAKE = 1,
+	ATTR_NAN_IND = 2,
+};
+
+/** nan_cb */
+typedef struct _nan_cb {
+    /** Delayed work response */
+	struct delayed_work response_work;
+    /** Priv */
+	moal_private *priv;
+    /** CMD fifo */
+	struct kfifo cmd_fifo;
+} nan_cb;
+
+/** NanHeader */
+typedef struct _NanHeader {
+    /** Msg ID */
+	t_u16 MsgId;
+    /** Msg length */
+	t_u16 MsgLen;
+    /** Handle */
+	t_u16 handle;
+    /** Transaction ID */
+	t_u16 transactionId;
+} NanHeader;
+
+/** NanHeader_Ext */
+typedef struct _NanHeader_Ext {
+	NanHeader nan_header;
+    /** Status */
+	t_u16 status;
+    /** Value */
+	t_u16 value;
+} NanHeader_Ext;
+
+/** nan_cmd */
+typedef struct _nan_cmd {
+	NanHeader_Ext nan_header_ext;
+    /** Enable Indication */
+	t_u16 indicate_enable;
+    /** Type Indicate */
+	t_u16 indicate_type;
+} nan_cmd;
+
+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)
+
+/* Feature enums */
+#define WIFI_FEATURE_INFRA              0x0001	// Basic infrastructure mode
+#define WIFI_FEATURE_INFRA_5G           0x0002	// Support for 5 GHz Band
+#define WIFI_FEATURE_HOTSPOT            0x0004	// Support for GAS/ANQP
+#define WIFI_FEATURE_P2P                0x0008	// Wifi-Direct
+#define WIFI_FEATURE_SOFT_AP            0x0010	// Soft AP
+#define WIFI_FEATURE_GSCAN              0x0020	// Google-Scan APIs
+#define WIFI_FEATURE_NAN                0x0040	// Neighbor Awareness Networking
+#define WIFI_FEATURE_D2D_RTT            0x0080	// Device-to-device RTT
+#define WIFI_FEATURE_D2AP_RTT           0x0100	// Device-to-AP RTT
+#define WIFI_FEATURE_BATCH_SCAN         0x0200	// Batched Scan (legacy)
+#define WIFI_FEATURE_PNO                0x0400	// Preferred network offload
+#define WIFI_FEATURE_ADDITIONAL_STA     0x0800	// Support for two STAs
+#define WIFI_FEATURE_TDLS               0x1000	// Tunnel directed link setup
+#define WIFI_FEATURE_TDLS_OFFCHANNEL    0x2000	// Support for TDLS off channel
+#define WIFI_FEATURE_EPR                0x4000	// Enhanced power reporting
+#define WIFI_FEATURE_AP_STA             0x8000	// Support for AP STA Concurrency
+#define WIFI_FEATURE_LINK_LAYER_STATS   0x10000	// Link layer stats collection
+#define WIFI_FEATURE_LOGGER             0x20000	// WiFi Logger
+#define WIFI_FEATURE_HAL_EPNO           0x40000	// WiFi PNO enhanced
+#define WIFI_FEATURE_RSSI_MONITOR       0x80000	// RSSI Monitor
+#define WIFI_FEATURE_MKEEP_ALIVE        0x100000	// WiFi mkeep_alive
+#define WIFI_FEATURE_CONFIG_NDO         0x200000	// ND offload configure
+#define WIFI_FEATURE_TX_TRANSMIT_POWER  0x400000	// Capture Tx transmit power levels
+#define WIFI_FEATURE_CONTROL_ROAMING    0x800000	// Enable/Disable firmware roaming
+#define WIFI_FEATURE_IE_WHITELIST       0x1000000	// Support Probe IE white listing
+#define WIFI_FEATURE_SCAN_RAND          0x2000000	// Support MAC & Probe Sequence Number randomization
+// 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_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_MAX,
+} 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_rssi_monitor = 0x1501,
+	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_nan_cb = 0x10010,
+	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_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_MAX,
+};
+void woal_cfg80211_rssi_monitor_event(moal_private *priv, t_s16 rssi);
+
+enum ATTR_LINK_LAYER_STAT {
+	ATTR_LL_STATS_INVALID,
+	ATTR_LL_STATS_MPDU_SIZE_THRESHOLD,
+	ATTR_LL_STATS_AGGRSSIVE_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_MAX,
+};
+
+/**vendor sub command*/
+enum vendor_sub_command {
+	sub_cmd_set_drvdbg = 0,
+	sub_cmd_dfs_capability = 0x0005,
+	sub_cmd_set_packet_filter = 0x0011,
+	sub_cmd_get_packet_filter_capability,
+	sub_cmd_get_valid_channels = 0x1009,
+	sub_cmd_get_wifi_supp_feature_set = 0x100a,
+	sub_cmd_set_country_code = 0x100d,
+	sub_cmd_link_statistic_set = 0x1200,
+	sub_cmd_link_statistic_get = 0x1201,
+	sub_cmd_link_statistic_clr = 0x1202,
+	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,
+	subcmd_nan_enable_req = 0x1800,
+	subcmd_nan_disable_req,
+	subcmd_nan_publish_req,
+	subcmd_nan_publish_cancel,
+	subcmd_nan_subscribe_req,
+	subcmd_nan_subscribe_cancel,
+	subcmd_nan_trasmit_followup,
+	subcmd_nan_stats_req,
+	subcmd_nan_config_req,
+	subcmd_nan_tca_req,
+	subcmd_nan_beacon_sdf_payload,
+	subcmd_nan_get_version,
+	subcmd_nan_get_capa,
+	subcmd_nan_data_if_create,
+	subcmd_nan_data_if_delete,
+	subcmd_nan_data_req_initor,
+	subcmd_nan_data_indi_resp,
+	subcmd_nan_data_end,
+	sub_cmd_max,
+};
+
+void woal_register_cfg80211_vendor_command(struct wiphy *wiphy);
+int woal_cfg80211_vendor_event(IN moal_private *priv,
+			       IN int event, IN t_u8 *data, IN 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,
+};
+
+/** 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_sd8897/mlinux/moal_debug.c b/wlan_sd8897/mlinux/moal_debug.c
new file mode 100644
index 0000000..b205c84
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_debug.c
@@ -0,0 +1,1301 @@
+/** @file moal_debug.c
+  *
+  * @brief This file contains functions for debug proc file.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    11/03/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+
+/********************************************************
+		Global Variables
+********************************************************/
+/** MLAN debug info */
+extern mlan_debug_info info;
+
+/********************************************************
+		Local Variables
+********************************************************/
+#ifdef CONFIG_PROC_FS
+
+/** Get info item size */
+#define item_size(n) (sizeof(info.n))
+/** Get info item address */
+#define item_addr(n) ((t_ptr) &(info.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 STA_SUPPORT
+static struct debug_data items[] = {
+#ifdef DEBUG_LEVEL1
+	{"drvdbg", sizeof(drvdbg), (t_ptr)&drvdbg},
+#endif
+	{"mlan_processing", item_size(mlan_processing),
+	 item_addr(mlan_processing)},
+	{"main_process_cnt", item_size(main_process_cnt),
+	 item_addr(main_process_cnt)},
+	{"main_lock_flag", item_size(main_lock_flag),
+	 item_addr(main_lock_flag)},
+	{"delay_task_flag", item_size(delay_task_flag),
+	 item_addr(delay_task_flag)},
+	{"mlan_rx_processing", item_size(mlan_rx_processing),
+	 item_addr(mlan_rx_processing)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"wmm_ac_vo", item_size(wmm_ac_vo), item_addr(wmm_ac_vo)},
+	{"wmm_ac_vi", item_size(wmm_ac_vi), item_addr(wmm_ac_vi)},
+	{"wmm_ac_be", item_size(wmm_ac_be), item_addr(wmm_ac_be)},
+	{"wmm_ac_bk", item_size(wmm_ac_bk), item_addr(wmm_ac_bk)},
+	{"max_tx_buf_size", item_size(max_tx_buf_size),
+	 item_addr(max_tx_buf_size)},
+	{"tx_buf_size", item_size(tx_buf_size), item_addr(tx_buf_size)},
+	{"curr_tx_buf_size", item_size(curr_tx_buf_size),
+	 item_addr(curr_tx_buf_size)},
+	{"ps_mode", item_size(ps_mode), item_addr(ps_mode)},
+	{"ps_state", item_size(ps_state), item_addr(ps_state)},
+	{"is_deep_sleep", item_size(is_deep_sleep), item_addr(is_deep_sleep)},
+	{"wakeup_dev_req", item_size(pm_wakeup_card_req),
+	 item_addr(pm_wakeup_card_req)},
+	{"wakeup_tries", item_size(pm_wakeup_fw_try),
+	 item_addr(pm_wakeup_fw_try)},
+	{"hs_configured", item_size(is_hs_configured),
+	 item_addr(is_hs_configured)},
+	{"hs_activated", item_size(hs_activated), item_addr(hs_activated)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"tx_pkts_queued", item_size(tx_pkts_queued),
+	 item_addr(tx_pkts_queued)},
+	{"pps_uapsd_mode", item_size(pps_uapsd_mode),
+	 item_addr(pps_uapsd_mode)},
+	{"sleep_pd", item_size(sleep_pd), item_addr(sleep_pd)},
+	{"qos_cfg", item_size(qos_cfg), item_addr(qos_cfg)},
+	{"tx_lock_flag", item_size(tx_lock_flag), item_addr(tx_lock_flag)},
+	{"port_open", item_size(port_open), item_addr(port_open)},
+	{"bypass_pkt_count", item_size(bypass_pkt_count),
+	 item_addr(bypass_pkt_count)},
+	{"scan_processing", item_size(scan_processing),
+	 item_addr(scan_processing)},
+	{"num_tx_timeout", item_size(num_tx_timeout),
+	 item_addr(num_tx_timeout)},
+	{"num_cmd_timeout", item_size(num_cmd_timeout),
+	 item_addr(num_cmd_timeout)},
+	{"dbg.num_cmd_timeout", item_size(dbg_num_cmd_timeout),
+	 item_addr(dbg_num_cmd_timeout)},
+	{"timeout_cmd_id", item_size(timeout_cmd_id),
+	 item_addr(timeout_cmd_id)},
+	{"timeout_cmd_act", item_size(timeout_cmd_act),
+	 item_addr(timeout_cmd_act)},
+	{"last_cmd_id", item_size(last_cmd_id), item_addr(last_cmd_id)},
+	{"last_cmd_act", item_size(last_cmd_act), item_addr(last_cmd_act)},
+	{"last_cmd_index", item_size(last_cmd_index),
+	 item_addr(last_cmd_index)},
+	{"last_cmd_resp_id", item_size(last_cmd_resp_id),
+	 item_addr(last_cmd_resp_id)},
+	{"last_cmd_resp_index", item_size(last_cmd_resp_index),
+	 item_addr(last_cmd_resp_index)},
+	{"last_event", item_size(last_event), item_addr(last_event)},
+	{"last_event_index", item_size(last_event_index),
+	 item_addr(last_event_index)},
+	{"num_no_cmd_node", item_size(num_no_cmd_node),
+	 item_addr(num_no_cmd_node)},
+	{"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
+	 item_addr(num_cmd_host_to_card_failure)},
+	{"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)},
+	{"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
+	 item_addr(num_tx_host_to_card_failure)},
+	{"num_alloc_buffer_failure", item_size(num_alloc_buffer_failure),
+	 item_addr(num_alloc_buffer_failure)},
+	{"num_cmdevt_c2h_fail", item_size(num_cmdevt_card_to_host_failure),
+	 item_addr(num_cmdevt_card_to_host_failure)},
+	{"num_rx_c2h_fail", item_size(num_rx_card_to_host_failure),
+	 item_addr(num_rx_card_to_host_failure)},
+	{"num_int_read_fail", item_size(num_int_read_failure),
+	 item_addr(num_int_read_failure)},
+	{"last_int_status", item_size(last_int_status),
+	 item_addr(last_int_status)},
+	{"num_of_irq", item_size(num_of_irq), item_addr(num_of_irq)},
+	{"mp_invalid_update", item_size(mp_invalid_update),
+	 item_addr(mp_invalid_update)},
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	{"mpa_sent_last_pkt", item_size(mpa_sent_last_pkt),
+	 item_addr(mpa_sent_last_pkt)},
+	{"mpa_sent_no_ports", item_size(mpa_sent_no_ports),
+	 item_addr(mpa_sent_no_ports)},
+#endif
+	{"num_evt_deauth", item_size(num_event_deauth),
+	 item_addr(num_event_deauth)},
+	{"num_evt_disassoc", item_size(num_event_disassoc),
+	 item_addr(num_event_disassoc)},
+	{"num_evt_link_lost", item_size(num_event_link_lost),
+	 item_addr(num_event_link_lost)},
+	{"num_cmd_deauth", item_size(num_cmd_deauth),
+	 item_addr(num_cmd_deauth)},
+	{"num_cmd_assoc_ok", item_size(num_cmd_assoc_success),
+	 item_addr(num_cmd_assoc_success)},
+	{"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure),
+	 item_addr(num_cmd_assoc_failure)},
+	{"cmd_sent", item_size(cmd_sent), item_addr(cmd_sent)},
+	{"data_sent", item_size(data_sent), item_addr(data_sent)},
+	{"mp_rd_bitmap", item_size(mp_rd_bitmap), item_addr(mp_rd_bitmap)},
+	{"curr_rd_port", item_size(curr_rd_port), item_addr(curr_rd_port)},
+	{"mp_wr_bitmap", item_size(mp_wr_bitmap), item_addr(mp_wr_bitmap)},
+	{"curr_wr_port", item_size(curr_wr_port), item_addr(curr_wr_port)},
+	{"cmd_resp_received", item_size(cmd_resp_received),
+	 item_addr(cmd_resp_received)},
+	{"event_received", item_size(event_received),
+	 item_addr(event_received)},
+
+	{"ioctl_pending", item_handle_size(ioctl_pending),
+	 item_handle_addr(ioctl_pending)},
+	{"tx_pending", item_handle_size(tx_pending),
+	 item_handle_addr(tx_pending)},
+	{"rx_pending", item_handle_size(rx_pending),
+	 item_handle_addr(rx_pending)},
+	{"lock_count", item_handle_size(lock_count),
+	 item_handle_addr(lock_count)},
+	{"malloc_count", item_handle_size(malloc_count),
+	 item_handle_addr(malloc_count)},
+	{"vmalloc_count", item_handle_size(vmalloc_count),
+	 item_handle_addr(vmalloc_count)},
+	{"mbufalloc_count", item_handle_size(mbufalloc_count),
+	 item_handle_addr(mbufalloc_count)},
+	{"main_state", item_handle_size(main_state),
+	 item_handle_addr(main_state)},
+	{"driver_state", item_handle_size(driver_state),
+	 item_handle_addr(driver_state)},
+#ifdef SDIO_MMC_DEBUG
+	{"sdiocmd53w", item_handle_size(cmd53w), item_handle_addr(cmd53w)},
+	{"sdiocmd53r", item_handle_size(cmd53r), item_handle_addr(cmd53r)},
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+	{"hs_skip_count", item_handle_size(hs_skip_count),
+	 item_handle_addr(hs_skip_count)},
+	{"hs_force_count", item_handle_size(hs_force_count),
+	 item_handle_addr(hs_force_count)},
+#endif
+};
+
+#endif
+
+#ifdef UAP_SUPPORT
+static struct debug_data uap_items[] = {
+#ifdef DEBUG_LEVEL1
+	{"drvdbg", sizeof(drvdbg), (t_ptr)&drvdbg},
+#endif
+	{"mlan_processing", item_size(mlan_processing),
+	 item_addr(mlan_processing)},
+	{"main_process_cnt", item_size(main_process_cnt),
+	 item_addr(main_process_cnt)},
+	{"main_lock_flag", item_size(main_lock_flag),
+	 item_addr(main_lock_flag)},
+	{"delay_task_flag", item_size(delay_task_flag),
+	 item_addr(delay_task_flag)},
+	{"mlan_rx_processing", item_size(mlan_rx_processing),
+	 item_addr(mlan_rx_processing)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"wmm_ac_vo", item_size(wmm_ac_vo), item_addr(wmm_ac_vo)},
+	{"wmm_ac_vi", item_size(wmm_ac_vi), item_addr(wmm_ac_vi)},
+	{"wmm_ac_be", item_size(wmm_ac_be), item_addr(wmm_ac_be)},
+	{"wmm_ac_bk", item_size(wmm_ac_bk), item_addr(wmm_ac_bk)},
+	{"max_tx_buf_size", item_size(max_tx_buf_size),
+	 item_addr(max_tx_buf_size)},
+	{"tx_buf_size", item_size(tx_buf_size), item_addr(tx_buf_size)},
+	{"curr_tx_buf_size", item_size(curr_tx_buf_size),
+	 item_addr(curr_tx_buf_size)},
+	{"ps_mode", item_size(ps_mode), item_addr(ps_mode)},
+	{"ps_state", item_size(ps_state), item_addr(ps_state)},
+	{"wakeup_dev_req", item_size(pm_wakeup_card_req),
+	 item_addr(pm_wakeup_card_req)},
+	{"wakeup_tries", item_size(pm_wakeup_fw_try),
+	 item_addr(pm_wakeup_fw_try)},
+	{"hs_configured", item_size(is_hs_configured),
+	 item_addr(is_hs_configured)},
+	{"hs_activated", item_size(hs_activated), item_addr(hs_activated)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"tx_pkts_queued", item_size(tx_pkts_queued),
+	 item_addr(tx_pkts_queued)},
+	{"bypass_pkt_count", item_size(bypass_pkt_count),
+	 item_addr(bypass_pkt_count)},
+	{"num_bridge_pkts", item_size(num_bridge_pkts),
+	 item_addr(num_bridge_pkts)},
+	{"num_drop_pkts", item_size(num_drop_pkts), item_addr(num_drop_pkts)},
+	{"num_tx_timeout", item_size(num_tx_timeout),
+	 item_addr(num_tx_timeout)},
+	{"num_cmd_timeout", item_size(num_cmd_timeout),
+	 item_addr(num_cmd_timeout)},
+	{"timeout_cmd_id", item_size(timeout_cmd_id),
+	 item_addr(timeout_cmd_id)},
+	{"timeout_cmd_act", item_size(timeout_cmd_act),
+	 item_addr(timeout_cmd_act)},
+	{"last_cmd_id", item_size(last_cmd_id), item_addr(last_cmd_id)},
+	{"last_cmd_act", item_size(last_cmd_act), item_addr(last_cmd_act)},
+	{"last_cmd_index", item_size(last_cmd_index),
+	 item_addr(last_cmd_index)},
+	{"last_cmd_resp_id", item_size(last_cmd_resp_id),
+	 item_addr(last_cmd_resp_id)},
+	{"last_cmd_resp_index", item_size(last_cmd_resp_index),
+	 item_addr(last_cmd_resp_index)},
+	{"last_event", item_size(last_event), item_addr(last_event)},
+	{"last_event_index", item_size(last_event_index),
+	 item_addr(last_event_index)},
+	{"num_no_cmd_node", item_size(num_no_cmd_node),
+	 item_addr(num_no_cmd_node)},
+	{"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
+	 item_addr(num_cmd_host_to_card_failure)},
+	{"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)},
+	{"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
+	 item_addr(num_tx_host_to_card_failure)},
+	{"num_alloc_buffer_failure", item_size(num_alloc_buffer_failure),
+	 item_addr(num_alloc_buffer_failure)},
+	{"num_cmdevt_c2h_fail", item_size(num_cmdevt_card_to_host_failure),
+	 item_addr(num_cmdevt_card_to_host_failure)},
+	{"num_rx_c2h_fail", item_size(num_rx_card_to_host_failure),
+	 item_addr(num_rx_card_to_host_failure)},
+	{"num_int_read_fail", item_size(num_int_read_failure),
+	 item_addr(num_int_read_failure)},
+	{"last_int_status", item_size(last_int_status),
+	 item_addr(last_int_status)},
+	{"num_of_irq", item_size(num_of_irq), item_addr(num_of_irq)},
+	{"mp_invalid_update", item_size(mp_invalid_update),
+	 item_addr(mp_invalid_update)},
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	{"mpa_sent_last_pkt", item_size(mpa_sent_last_pkt),
+	 item_addr(mpa_sent_last_pkt)},
+	{"mpa_sent_no_ports", item_size(mpa_sent_no_ports),
+	 item_addr(mpa_sent_no_ports)},
+#endif
+	{"cmd_sent", item_size(cmd_sent), item_addr(cmd_sent)},
+	{"data_sent", item_size(data_sent), item_addr(data_sent)},
+	{"mp_rd_bitmap", item_size(mp_rd_bitmap), item_addr(mp_rd_bitmap)},
+	{"curr_rd_port", item_size(curr_rd_port), item_addr(curr_rd_port)},
+	{"mp_wr_bitmap", item_size(mp_wr_bitmap), item_addr(mp_wr_bitmap)},
+	{"curr_wr_port", item_size(curr_wr_port), item_addr(curr_wr_port)},
+	{"cmd_resp_received", item_size(cmd_resp_received),
+	 item_addr(cmd_resp_received)},
+	{"event_received", item_size(event_received),
+	 item_addr(event_received)},
+
+	{"ioctl_pending", item_handle_size(ioctl_pending),
+	 item_handle_addr(ioctl_pending)},
+	{"tx_pending", item_handle_size(tx_pending),
+	 item_handle_addr(tx_pending)},
+	{"rx_pending", item_handle_size(rx_pending),
+	 item_handle_addr(rx_pending)},
+	{"lock_count", item_handle_size(lock_count),
+	 item_handle_addr(lock_count)},
+	{"malloc_count", item_handle_size(malloc_count),
+	 item_handle_addr(malloc_count)},
+	{"vmalloc_count", item_handle_size(vmalloc_count),
+	 item_handle_addr(vmalloc_count)},
+	{"mbufalloc_count", item_handle_size(mbufalloc_count),
+	 item_handle_addr(mbufalloc_count)},
+	{"main_state", item_handle_size(main_state),
+	 item_handle_addr(main_state)},
+	{"driver_state", item_handle_size(driver_state),
+	 item_handle_addr(driver_state)},
+#ifdef SDIO_MMC_DEBUG
+	{"sdiocmd53w", item_handle_size(cmd53w), item_handle_addr(cmd53w)},
+	{"sdiocmd53r", item_handle_size(cmd53r), item_handle_addr(cmd53r)},
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+	{"hs_skip_count", item_handle_size(hs_skip_count),
+	 item_handle_addr(hs_skip_count)},
+	{"hs_force_count", item_handle_size(hs_force_count),
+	 item_handle_addr(hs_force_count)},
+#endif
+};
+#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_u8 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->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
+ *  @param antenna             Antenna
+ *  @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);
+}
+
+/**
+ *  @brief This function set histogram data
+ *
+ *  @param priv 		A pointer to moal_private
+ *  @param rx_rate              rx rate
+ *  @param snr			snr
+ *  @param nflr			NF
+ *  @param antenna              Antenna
+ *  @return   N/A
+ */
+static void
+woal_hist_data_set(moal_private *priv, t_u8 rx_rate, t_s8 snr, t_s8 nflr,
+		   t_u8 antenna)
+{
+	hgm_data *phist_data = priv->hist_data[antenna];
+
+	atomic_inc(&(phist_data->num_samples));
+	atomic_inc(&(phist_data->rx_rate[rx_rate]));
+	atomic_inc(&(phist_data->snr[snr]));
+	atomic_inc(&(phist_data->noise_flr[128 + nflr]));
+	atomic_inc(&(phist_data->sig_str[nflr - snr]));
+}
+
+/**
+ *  @brief This function add histogram data
+ *
+ *  @param priv 		A pointer to moal_private
+ *  @param rx_rate              rx rate
+ *  @param snr			snr
+ *  @param nflr			NF
+ *  @param antenna              Antenna
+ *  @return   N/A
+ */
+void
+woal_hist_data_add(moal_private *priv, t_u8 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->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 RATE_INDEX_MCS0   12
+/**
+ *  @brief histogram info in proc
+ *
+ *  @param sfp     A pointer to seq_file structure
+ *  @param data    void pointer to 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;
+	wlan_hist_proc_data *hist_data = (wlan_hist_proc_data *) sfp->private;
+	moal_private *priv = (moal_private *)hist_data->priv;
+	t_u8 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");
+
+	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" : "");
+			}
+		}
+	}
+	for (i = 0; i < SNR_MAX; i++) {
+		value = atomic_read(&(phist_data->snr[i]));
+		if (value)
+			seq_printf(sfp, "snr[%02ddB] = %d\n", i, 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", i,
+				   value);
+	}
+
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc read function for histogram
+ *
+ *  @param sfp     A pointer to seq_file structure
+ *  @param data    Void pointer to 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 (!priv->hist_data) {
+		LEAVE();
+		return -EFAULT;
+	}
+	if (hist_data->ant_idx < priv->phandle->histogram_table_num)
+		woal_histogram_info(sfp, priv->hist_data[hist_data->ant_idx]);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc open function for histogram
+ *
+ *  @param inode     A pointer to inode structure
+ *  @param file      A pointer to file structure
+ *
+ *  @return         0--sucess, otherise fail
+**/
+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     A pointer to seq_file structure
+ *  @param data    void pointer to 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     A pointer to seq_file structure
+ *  @param data    Void pointer to 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;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	unsigned int j;
+	t_u8 mp_aggr_pkt_limit = 0;
+#endif
+
+	ENTER();
+
+	if (priv == NULL) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	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 (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 {
+			unsigned int j;
+			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")
+			)
+			seq_printf(sfp, "%s=0x%x\n", d[i].name, val);
+		else
+			seq_printf(sfp, "%s=%d\n", d[i].name, val);
+	}
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	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);
+	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");
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	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");
+#endif
+	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");
+	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);
+#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++) {
+			unsigned int j;
+
+			seq_printf(sfp,
+				   "tid = %d, ta =  %02x:%02x:%02x:%02x:%02x:%02x, start_win = %d, "
+				   "win_size = %d, amsdu=%d\n",
+				   (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, "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++) {
+		unsigned int j;
+		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;
+#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;
+	}
+
+	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;
+}
+
+/**
+ *  @brief debug proc open function
+ *
+ *  @param inode     A pointer to inode structure
+ *  @param file      A pointer to file structure
+ *
+ *  @return         0--sucess, otherise fail
+**/
+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
+}
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+/********************************************************
+		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;
+	int handle_items;
+	char hist_entry[50];
+
+	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;
+		}
+		memcpy(priv->items_priv.items, 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;
+		}
+		memcpy(priv->items_priv.items, uap_items, sizeof(uap_items));
+		priv->items_priv.num_of_items = ARRAY_SIZE(uap_items);
+	}
+#endif
+
+	priv->items_priv.priv = priv;
+	handle_items = 9;
+#ifdef SDIO_MMC_DEBUG
+	handle_items += 2;
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+	handle_items += 2;
+#endif
+	for (i = 1; i <= handle_items; i++)
+		priv->items_priv.items[priv->items_priv.num_of_items -
+				       i].addr += (t_ptr)(priv->phandle);
+
+	/* 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->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->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_sd8897/mlinux/moal_eth_ioctl.c b/wlan_sd8897/mlinux/moal_eth_ioctl.c
new file mode 100644
index 0000000..1dc5379
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_eth_ioctl.c
@@ -0,0 +1,14531 @@
+/** @file  moal_eth_ioctl.c
+  *
+  * @brief This file contains private ioctl functions
+  *
+  * Copyright (C) 2014-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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
+#include	"moal_sdio.h"
+#ifdef STA_CFG80211
+#include    "moal_sta_cfg80211.h"
+#endif
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#include    "moal_cfgvendor.h"
+#endif
+#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_GAC,
+		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_GN, BAND_B | BAND_G | BAND_GN, BAND_G | BAND_GN,
+	BAND_GN | BAND_GAC, BAND_B | BAND_G | BAND_GN | BAND_GAC,
+		BAND_G | BAND_GN | BAND_GAC,
+	BAND_A,
+	BAND_AN, BAND_A | BAND_AN,
+	BAND_AN | BAND_AAC, BAND_A | BAND_AN | BAND_AAC,
+};
+
+/********************************************************
+			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
+extern int cfg80211_wext;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+extern int hw_test;
+extern int cntry_txpwr;
+/********************************************************
+			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
+ */
+mlan_status
+parse_arguments(t_u8 *pos, int *data, int datalen, int *user_data_len)
+{
+	unsigned 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 <= strlen(pos); i++) {
+		if ((k == 0) && (i <= (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 {
+			cdata[k] = pos[i];
+			k++;
+		}
+	}
+
+	*user_data_len = j;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/** Convert character to integer */
+#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0'))
+/**
+ * @brief Converts a string to hex value
+ *
+ * @param str      A pointer to the string
+ * @param raw      A pointer to the raw data buffer
+ * @return         Number of bytes read
+ **/
+int
+string2raw(char *str, unsigned char *raw)
+{
+	int len = (strlen(str) + 1) / 2;
+
+	do {
+		if (!isxdigit(*str)) {
+			return -1;
+		}
+		*str = toupper(*str);
+		*raw = CHAR2INT(*str) << 4;
+		++str;
+		*str = toupper(*str);
+		if (*str == '\0')
+			break;
+		*raw |= CHAR2INT(*str);
+		++raw;
+	} while (*++str != '\0');
+	return len;
+}
+
+#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;
+	t_u32 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
+ */
+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) {
+		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.
+ */
+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, (respbuflen - 1));
+		memcpy(respbuf, buf, ret);
+	} 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_MARVELL) + strlen(PRIV_CMD_HOSTCMD));
+	buf_len = *((t_u32 *)data_ptr);
+	memcpy(&cmd_header, data_ptr + sizeof(buf_len), 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) > MLAN_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 */
+	memcpy(misc_cfg->param.hostcmd.cmd, data_ptr + sizeof(buf_len),
+	       misc_cfg->param.hostcmd.len);
+
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto error;
+	}
+	memcpy(data_ptr + sizeof(buf_len), misc_cfg->param.hostcmd.cmd,
+	       misc_cfg->param.hostcmd.len);
+	ret = misc_cfg->param.hostcmd.len + sizeof(buf_len) +
+		strlen(CMD_MARVELL) + strlen(PRIV_CMD_HOSTCMD);
+	memcpy(data_ptr, (t_u8 *)&misc_cfg->param.hostcmd.len, sizeof(t_u32));
+
+error:
+	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.
+ */
+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 *custom_ie = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	data_ptr = respbuf + (strlen(CMD_MARVELL) + strlen(PRIV_CMD_CUSTOMIE));
+
+	custom_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 ((custom_ie->len == 0)||(custom_ie->len ==
+				    sizeof(custom_ie->ie_data_list[0].
+					   ie_index)))
+		ioctl_req->action = MLAN_ACT_GET;
+	else
+		ioctl_req->action = MLAN_ACT_SET;
+
+	memcpy(&misc->param.cust_ie, 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;
+	}
+	custom_ie = (mlan_ds_misc_custom_ie *)data_ptr;
+	memcpy(custom_ie, &misc->param.cust_ie, sizeof(mlan_ds_misc_custom_ie));
+	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.
+ */
+int
+woal_setget_priv_bandcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	unsigned int i;
+	int data[4];
+	int user_data_len = 0;
+	t_u32 infra_band = 0;
+	t_u32 adhoc_band = 0;
+	t_u32 adhoc_channel = 0;
+	t_u32 adhoc_chan_bandwidth = 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_MARVELL) + strlen(PRIV_CMD_BANDCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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); 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;
+			}
+		}
+		if (user_data_len == 4) {
+			if (!(adhoc_band & (BAND_GN
+					    | BAND_GAC | BAND_AN | BAND_AAC))) {
+				PRINTM(MERROR,
+				       "11n is not enabled for adhoc, can not set HT/VHT channel bandwidth\n");
+				ret = -EINVAL;
+				goto error;
+			}
+			adhoc_chan_bandwidth = data[3];
+			/* sanity test */
+			if ((adhoc_chan_bandwidth != CHANNEL_BW_20MHZ) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_ABOVE) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_BELOW)
+			    && (adhoc_chan_bandwidth != CHANNEL_BW_80MHZ)
+				) {
+				PRINTM(MERROR,
+				       "Invalid secondary channel bandwidth, only allowed 0, 1, 3 or 4\n");
+				ret = -EINVAL;
+				goto error;
+			}
+
+			/* VHT 80 MHz is valid only for 5G band */
+			if ((adhoc_chan_bandwidth == CHANNEL_BW_80MHZ) &&
+			    ((adhoc_band & BAND_AAC) == 0)) {
+				PRINTM(MERROR,
+				       "Invalid adhoc band for 11ac 80 Mhz, only 5G is allowed.\n");
+				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;
+		radio_cfg->param.band_cfg.adhoc_chan_bandwidth =
+			adhoc_chan_bandwidth;
+	}
+
+	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;
+
+	memcpy(band_cfg, &radio_cfg->param.band_cfg, sizeof(mlan_ds_band_cfg));
+
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_HTTXCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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]);
+	}
+
+	memcpy(respbuf, data, sizeof(data));
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_HTCAPINFO))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ADDBAPARA))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DELBA);
+
+	if (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)
+		memcpy(del_ba->peer_mac_addr, peer_mac, ETH_ALEN);
+
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_REJECTADDBAREQ))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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
+ */
+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)
+		memcpy(cfg_11n->param.addba_reject, 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)
+		memcpy(addba_reject, cfg_11n->param.addba_reject,
+		       sizeof(cfg_11n->param.addba_reject));
+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
+ */
+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)
+		memcpy(&cfg_11n->param.aggr_prio_tbl, 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)
+		memcpy(aggr_prio_tbl, &cfg_11n->param.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
+ */
+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)
+		memcpy(&cfg_11n->param.addba_param, 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)
+		memcpy(addba_param, &cfg_11n->param.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
+ */
+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] != 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
+ */
+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] != 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_AGGRPRIOTBL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ADDBAREJECT))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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_MARVELL) + 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);
+	memcpy(vhtcfg, &cfg_11ac->param.vht_cfg, sizeof(mlan_ds_11ac_vht_cfg));
+	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++;
+		memcpy(vhtcfg, &cfg_11ac->param.vht_cfg,
+		       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.
+ */
+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_MARVELL) +
+			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;
+	memcpy(opermodecfg, &(cfg_11ac->param.opermode_cfg),
+	       sizeof(*opermodecfg));
+	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.
+ */
+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;
+
+	memcpy(data_rate, &rate->param.data_rate, sizeof(mlan_data_rate));
+
+	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.
+ */
+int
+woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[3];
+	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;
+
+	ENTER();
+
+	if (strlen(respbuf) ==
+	    (strlen(CMD_MARVELL) + strlen(PRIV_CMD_TXRATECFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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] >= 3)) {
+			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_VHT)
+				) {
+				PRINTM(MERROR, "Invalid format selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			rate->param.rate_cfg.rate_format = data[0];
+		}
+
+		if ((user_data_len >= 2) && (data[0] != AUTO_RATE)) {
+			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))
+				) {
+				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 ((user_data_len >= 3) && (data[0] != AUTO_RATE)) {
+			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];
+		}
+	}
+
+	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)
+			ratecfg->nss = rate->param.rate_cfg.nss;
+	}
+
+	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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+			memcpy(stats, &info->param.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.
+ */
+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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ESUPPMODE))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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_MARVELL) + 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);
+			strncpy((char *)sec->param.passphrase.ssid.ssid, end,
+				MIN(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;
+			memcpy(sec->param.passphrase.psk.passphrase.passphrase,
+			       end,
+			       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;
+	}
+
+	memset(respbuf, 0, respbuflen);
+	if (sec->param.passphrase.ssid.ssid_len) {
+		len += sprintf(respbuf + len, "ssid:");
+		memcpy(respbuf + len, sec->param.passphrase.ssid.ssid,
+		       sec->param.passphrase.ssid.ssid_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);
+
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DEAUTH))) {
+		/* Deauth mentioned BSSID */
+		woal_mac2u8(mac,
+			    respbuf + strlen(CMD_MARVELL) +
+			    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_MARVELL) + strlen(PRIV_CMD_AP_DEAUTH));
+	memset(&deauth_param, 0, sizeof(mlan_deauth_param));
+	memcpy(&deauth_param, data_ptr, 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;
+
+	memcpy(&bss->param.deauth_param, &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;
+	}
+
+	memcpy(data_ptr, &ioctl_req->status_code, sizeof(t_u32));
+	ret = sizeof(t_u32);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap get station list 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_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_MARVELL) +
+				     strlen(PRIV_CMD_GET_STA_LIST));
+	memcpy(sta_list, &info->param.sta_list, sizeof(mlan_ds_sta_list));
+	ret = sizeof(mlan_ds_sta_list);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap bss_config 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_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_MARVELL) + strlen(PRIV_CMD_BSS_CONFIG);
+	memcpy((u8 *)&action, respbuf + offset, 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 */
+		memcpy(&bss->param.bss_config, respbuf + offset,
+		       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) {
+		memcpy(respbuf + offset, &bss->param.bss_config,
+		       sizeof(mlan_uap_bss_param));
+	}
+	ret = sizeof(mlan_uap_bss_param);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if defined(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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_BSSROLE))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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 && V14_FEATURE */
+
+#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.
+ */
+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 */
+	memcpy((char *)&scan_cfg,
+	       respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_SETUSERSCAN),
+	       sizeof(wlan_user_scan_cfg));
+	/* Call for scan */
+	if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_cfg))
+		ret = -EFAULT;
+
+	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
+ */
+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.
+ */
+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 */
+	memcpy(&scan_start,
+	       respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_GETSCANTABLE),
+	       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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_EXTCAPCFG);
+	if (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));
+		memcpy(&cfg->param.ext_cap, ie + 1, ie->len);
+	}
+
+	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);
+	memcpy(ie + 1, &cfg->param.ext_cap, sizeof(ExtCap_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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DEEPSLEEP))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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);
+		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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_WPSSESSION))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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_MARVELL) +
+			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]);
+		memcpy(respbuf, otp->user_data, ret);
+	}
+
+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.
+ */
+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_MARVELL) + 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);
+		memcpy(country_code->country_code, respbuf + header,
+		       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);
+		memcpy(respbuf, country_code->country_code, COUNTRY_CODE_LEN);
+	}
+
+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.
+ */
+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;
+	int header = 0, data_length = 0;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header = strlen(CMD_MARVELL) + strlen(PRIV_CMD_CFPINFO);
+	data_length = strlen(respbuf) - header;
+
+	/* 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;
+	}
+	memcpy(respbuf, (t_u8 *)req->pbuf, req->data_read_written);
+	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.
+ */
+int
+woal_priv_setgettcpackenh(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[1];
+	int ret = 0;
+	int user_data_len = 0;
+
+	ENTER();
+
+	if (strlen(respbuf) ==
+	    (strlen(CMD_MARVELL) + strlen(PRIV_CMD_TCPACKENH))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				strlen(PRIV_CMD_TCPACKENH), data,
+				ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len >= 2) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (user_data_len == 0) {
+		/* get operation */
+		respbuf[0] = priv->enable_tcp_ack_enh;
+	} else {
+		/* set operation */
+		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);
+		} else {
+			PRINTM(MERROR, "Unknown option = %u\n", data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		respbuf[0] = priv->enable_tcp_ack_enh;
+	}
+	ret = 1;
+
+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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ASSOCBSSID);
+	else
+		header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ASSOCESSID);
+
+	if (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, (sizeof(buf) - 1));
+	memset(buf, 0, sizeof(buf));
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+	memcpy(buf, respbuf + header_len, buflen);
+	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 */
+	memcpy(ssid_bssid.ssid.ssid, buf + i,
+	       MIN(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;
+	}
+	memcpy(&priv->prev_ssid_bssid, &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.
+ */
+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_MARVELL) + 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_LISTENINTERVAL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DRVDBG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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);
+
+	memcpy(respbuf, &drvdbg, sizeof(drvdbg));
+
+	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 "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
+ */
+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_MARVELL);
+
+	if (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 >
+		    MAX_MGMT_FRAME_FILTER * sizeof(mlan_mgmt_frame_wakeup)) {
+			PRINTM(MERROR, "%d: Invalid arguments\n", __LINE__);
+			ret = -EINVAL;
+			goto done;
+		}
+		memcpy((t_u8 *)pm_cfg->param.mgmt_filter, argument, data_len);
+		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
+ */
+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_MARVELL) + strlen(PRIV_CMD_HSCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		arguments =
+			respbuf + strlen(CMD_MARVELL) + 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] != 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 */
+		memcpy(respbuf, &hscfg, sizeof(mlan_ds_hs_cfg));
+		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
+ */
+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_MARVELL) + 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_MARVELL) +
+				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_MARVELL, PRIV_CMD_HSCFG,
+			respbuf + (strlen(CMD_MARVELL) +
+				   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
+ */
+int
+woal_priv_set_get_scancfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0;
+	int arg_len = 7;
+	int data[arg_len];
+	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_MARVELL) + strlen(PRIV_CMD_SCANCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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] > 1)) {
+			PRINTM(MERROR, "Invalid argument for extended scan\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		memcpy(&scan->param.scan_cfg, data, sizeof(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) {
+		memcpy(respbuf, &scan->param.scan_cfg, sizeof(mlan_scan_cfg));
+		ret = sizeof(mlan_scan_cfg);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#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_MARVELL) + 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;
+		}
+		memcpy(&ssid_bssid.bssid, awrq->sa_data, ETH_ALEN);
+	}
+
+	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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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_MARVELL) + 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 (hw_test) {
+		PRINTM(MIOCTL, "block set power in hw_test mode\n");
+		LEAVE();
+		return ret;
+	}
+
+	data_ptr = respbuf + (strlen(CMD_MARVELL) + 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_MARVELL) + 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 */
+		memcpy(req_ssid.ssid, mwr->u.essid.pointer,
+		       MIN(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);
+		memcpy(&ssid_bssid.ssid, &req_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;
+		}
+	} 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);
+
+	/* 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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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_MARVELL) + 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)
+{
+	int ret = 0;
+	mlan_bss_info bss_info;
+	struct mwreq *mwr;
+	t_u8 *data_ptr;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_MARVELL) + 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) {
+		memcpy(mwr->u.ap_addr.sa_data, &bss_info.bssid,
+		       MLAN_MAC_ADDR_LENGTH);
+	} else {
+		memset(mwr->u.ap_addr.sa_data, 0, MLAN_MAC_ADDR_LENGTH);
+	}
+
+	mwr->u.ap_addr.sa_family = ARPHRD_ETHER;
+	ret = strlen(CMD_MARVELL) + 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_MARVELL) + 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_MARVELL) + 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_MARVELL) + strlen(PRIV_CMD_PSMODE);
+
+	if (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;
+	}
+
+	/* 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;
+
+	memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+	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;
+	int intf_num;
+	moal_handle *handle = priv->phandle;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+#if defined(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 && V14_FEATURE */
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	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);
+#if defined(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 && V14_FEATURE */
+	}
+
+	/* 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;
+		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) {
+			ret = -EFAULT;
+			if (status != MLAN_STATUS_PENDING)
+				kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+
+	/* 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 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_MARVELL) + strlen(PRIV_CMD_TXPOWERCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		arguments =
+			respbuf + strlen(CMD_MARVELL) +
+			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 */
+		memcpy(respbuf, (t_u8 *)&pcfg->param.power_ext,
+		       sizeof(pcfg->param.power_ext.num_pwr_grp) +
+		       (pcfg->param.power_ext.num_pwr_grp *
+			sizeof(mlan_power_group)));
+		ret = sizeof(pcfg->param.power_ext.num_pwr_grp) +
+			(pcfg->param.power_ext.num_pwr_grp *
+			 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 ad-hoc awake period parameter */
+	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_MARVELL) + strlen(PRIV_CMD_PSCFG);
+
+	if (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] != SPECIAL_ADHOC_AWAKE_PD) &&
+		    ((data[i] < MIN_ADHOC_AWAKE_PD) ||
+		     (data[i] > MAX_ADHOC_AWAKE_PD))) {
+			PRINTM(MERROR,
+			       "Invalid argument for adhoc awake period\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		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;
+		memcpy(&pm_cfg->param.ps_cfg, data,
+		       MIN(sizeof(pm_cfg->param.ps_cfg), sizeof(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;
+	}
+	memcpy(data, &pm_cfg->param.ps_cfg,
+	       MIN((sizeof(int) * allowed), sizeof(pm_cfg->param.ps_cfg)));
+	memcpy(respbuf, (t_u8 *)data, sizeof(int) * allowed);
+	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_MARVELL) + 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_MARVELL) + strlen(PRIV_CMD_SLEEPPD);
+
+	if (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");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	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;
+		memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_TXCONTROL);
+
+	if (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");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	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;
+		memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_REGRDWR);
+
+	if (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) {
+		memcpy(respbuf, &reg_mem->param.reg_rw,
+		       sizeof(reg_mem->param.reg_rw));
+		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_MARVELL) + strlen(PRIV_CMD_RDEEPROM);
+
+	if (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) {
+		memcpy(respbuf, &reg_mem->param.rd_eeprom,
+		       sizeof(reg_mem->param.rd_eeprom));
+		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_MARVELL) + strlen(PRIV_CMD_MEMRDWR);
+
+	if (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) {
+		memcpy(respbuf, &reg_mem->param.mem_rw,
+		       sizeof(reg_mem->param.mem_rw));
+		ret = sizeof(reg_mem->param.mem_rw);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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_MARVELL) + strlen(PRIV_CMD_SDCMD52RW);
+	memset((t_u8 *)buf, 0, sizeof(buf));
+
+	if (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) {
+		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 {
+		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;
+		}
+	}
+
+	/* Action = GET */
+	buf[0] = data;
+
+	memcpy(respbuf, &buf, sizeof(int));
+	ret = sizeof(int);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#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_MARVELL) + strlen(PRIV_CMD_ARPFILTER));
+	buf_len = *((t_u16 *)data_ptr);
+	misc->param.gen_ie.len = buf_len;
+	memcpy((void *)(misc->param.gen_ie.ie_data), data_ptr + sizeof(buf_len),
+	       buf_len);
+
+	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 */
+
+#if defined(SDIO_SUSPEND_RESUME)
+/**
+ *  @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.
+ */
+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_MARVELL) + 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_MARVELL) +
+				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");
+	}
+
+	memcpy(respbuf, &handle->hs_auto_arp, sizeof(handle->hs_auto_arp));
+	ret = sizeof(handle->hs_auto_arp);
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @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_MARVELL) + strlen(PRIV_CMD_DEAUTH_CTRL);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	ret = sizeof(data);
+
+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
+ */
+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_MARVELL) + strlen(PRIV_CMD_HOTSPOTCFG);
+	if (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;
+	memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+	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
+ */
+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_MARVELL) + strlen(PRIV_CMD_MGMT_FRAME_CTRL);
+	if (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;
+	memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+	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_MARVELL) + 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));
+
+	memcpy((t_u8 *)&addts_ioctl, data_ptr, sizeof(addts_ioctl));
+
+	cfg->param.addts.timeout = addts_ioctl.timeout_ms;
+	cfg->param.addts.ie_data_len = addts_ioctl.ie_data_len;
+
+	memcpy(cfg->param.addts.ie_data,
+	       addts_ioctl.ie_data, cfg->param.addts.ie_data_len);
+
+	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;
+
+	memcpy(addts_ioctl.ie_data,
+	       cfg->param.addts.ie_data, cfg->param.addts.ie_data_len);
+
+	copy_len = (sizeof(addts_ioctl)
+		    - sizeof(addts_ioctl.ie_data)
+		    + cfg->param.addts.ie_data_len);
+
+	memcpy(respbuf, (t_u8 *)&addts_ioctl, copy_len);
+	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_MARVELL) + 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 (strlen(respbuf) > header_len) {
+		copy_len = MIN(strlen(data_ptr), sizeof(delts_ioctl));
+		memcpy((t_u8 *)&delts_ioctl, data_ptr, copy_len);
+
+		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;
+
+		memcpy(cfg->param.delts.ie_data,
+		       delts_ioctl.ie_data, cfg->param.delts.ie_data_len);
+
+		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);
+		memcpy(respbuf, (t_u8 *)&delts_ioctl, copy_len);
+		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_MARVELL) + strlen(PRIV_CMD_QCONFIG));
+
+	memcpy((t_u8 *)&qcfg_ioctl, data_ptr, 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;
+	memcpy(data_ptr, (t_u8 *)&qcfg_ioctl, sizeof(qcfg_ioctl));
+	ret = strlen(CMD_MARVELL) + 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_MARVELL) + 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 (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));
+		memcpy((void *)&qstatus_ioctl, (void *)&pwmm->param.q_status,
+		       sizeof(qstatus_ioctl));
+		memcpy(respbuf, (t_u8 *)&qstatus_ioctl, sizeof(qstatus_ioctl));
+		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_MARVELL) + 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));
+
+	memcpy((t_u8 *)&ts_status_ioctl, data_ptr, 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));
+	memcpy((void *)&ts_status_ioctl, (void *)&pwmm->param.ts_status,
+	       sizeof(ts_status_ioctl));
+	memcpy(respbuf, (t_u8 *)&ts_status_ioctl, sizeof(ts_status_ioctl));
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_MAC_CTRL);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.mac_ctrl, sizeof(data));
+	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
+ */
+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) {
+			memcpy(respbuf, (t_u8 *)&bss_info.bssid,
+			       MLAN_MAC_ADDR_LENGTH);
+		} 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) {
+			memcpy(respbuf, priv->current_addr,
+			       MLAN_MAC_ADDR_LENGTH);
+		} 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_REGION_CODE);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.region_code, sizeof(data));
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get channel time and buffer weight
+ *
+ *  @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.
+ */
+int
+woal_priv_multi_chan_config(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	t_u8 *data_ptr;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr =
+		respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_MULTI_CHAN_CFG);
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_MULTI_CHAN_CFG);
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		user_data_len = sizeof(mlan_ds_multi_chan_cfg);
+	}
+
+	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_MULTI_CHAN_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		memcpy(&cfg->param.multi_chan_cfg, data_ptr,
+		       sizeof(mlan_ds_multi_chan_cfg));
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, (mlan_ds_multi_chan_cfg *)&cfg->param.multi_chan_cfg,
+	       req->buf_len);
+	ret = req->buf_len;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get multi_channel policy 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.
+ */
+int
+woal_priv_multi_chan_policy(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	int data = 0;
+	t_u16 enable;
+	t_u8 action;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_MULTI_CHAN_POLICY);
+	if (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;
+	}
+
+	if (user_data_len == 0) {
+		action = MLAN_ACT_GET;
+	} else {
+		action = MLAN_ACT_SET;
+		enable = (t_u16)data;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_mc_policy_cfg(priv, &enable, MOAL_IOCTL_WAIT, action)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memcpy(respbuf, &enable, sizeof(t_u16));
+	ret = sizeof(t_u16);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get drcs time slicing 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.
+ */
+int
+woal_priv_drcs_time_slicing_cfg(moal_private *priv, t_u8 *respbuf,
+				t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_ds_drcs_cfg *drcs_cfg = NULL;
+	t_u8 *data_ptr;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	int data[8];
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr = respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_DRCS_CFG);
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_DRCS_CFG);
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(data_ptr, data, ARRAY_SIZE(data),
+				&user_data_len);
+	}
+
+	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_DRCS_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		drcs_cfg = (mlan_ds_drcs_cfg *) & cfg->param.drcs_cfg[0];
+		drcs_cfg->chantime = (t_u8)data[0];
+		drcs_cfg->switchtime = (t_u8)data[1];
+		drcs_cfg->undozetime = (t_u8)data[2];
+		drcs_cfg->mode = (t_u8)data[3];
+		/* Set the same parameters for two channels */
+		if (user_data_len < ARRAY_SIZE(data))
+			drcs_cfg->chan_idx = 0x03;
+		else {
+			/* Set the different parameters for two channels */
+			drcs_cfg->chan_idx = 0x1;
+			drcs_cfg =
+				(mlan_ds_drcs_cfg *) & cfg->param.drcs_cfg[1];
+			drcs_cfg->chan_idx = 0x2;
+			drcs_cfg->chantime = (t_u8)data[4];
+			drcs_cfg->switchtime = (t_u8)data[5];
+			drcs_cfg->undozetime = (t_u8)data[6];
+			drcs_cfg->mode = (t_u8)data[7];
+		}
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.drcs_cfg, req->buf_len);
+	ret = req->buf_len;
+
+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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_RX_COAL_CFG);
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_RX_COAL_CFG);
+	if (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;
+	}
+
+	memcpy(respbuf,
+	       (mlan_ds_misc_rx_packet_coalesce *)&cfg->param.rx_coalesce,
+	       req->buf_len);
+	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
+ */
+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_MARVELL) + 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 (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);
+		memcpy(bss->param.mac_addr, data, ETH_ALEN);
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, bss->param.mac_addr, sizeof(data));
+	ret = sizeof(data);
+	HEXDUMP("FW MAC Addr:", respbuf, ETH_ALEN);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_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
+ */
+int
+woal_priv_offchannel(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[3];
+	int ret = 0;
+	t_u8 status = 1;
+	int user_data_len = 0, header_len = 0;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_OFFCHANNEL);
+
+	if (header_len == 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 (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
+					   )), 0, (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
+ */
+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_MARVELL) + strlen(PRIV_CMD_DSCP_MAP);
+	if (strlen(respbuf) != header_len) {
+		/* SET operation */
+		pos = respbuf + header_len;
+		memcpy(priv->dscp_map, pos, sizeof(priv->dscp_map));
+	}
+
+	copy_size = MIN(sizeof(priv->dscp_map), respbuflen);
+	memcpy(respbuf, priv->dscp_map, copy_size);
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_VEREXT);
+
+	if (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);
+	memcpy(respbuf, info->param.ver_ext.version_str, copy_size);
+	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;
+}
+
+#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_MARVELL) + strlen(PRIV_CMD_RADIO_CTRL);
+
+	if (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);
+		memcpy(respbuf, &bss_info.radio_on, sizeof(bss_info.radio_on));
+		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_MARVELL) + strlen(PRIV_CMD_WMM_CFG);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &wmm->param.wmm_enable, sizeof(wmm->param.wmm_enable));
+	ret = sizeof(wmm->param.wmm_enable);
+
+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_MARVELL) + strlen(PRIV_CMD_11D_CFG);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &pcfg_11d->param.enable_11d,
+	       sizeof(pcfg_11d->param.enable_11d));
+	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_MARVELL) + strlen(PRIV_CMD_11D_CLR_TBL);
+
+	if (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
+
+/**
+ *  @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_MARVELL) + strlen(PRIV_CMD_WWS_CFG);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &wws->param.wws_cfg, sizeof(wws->param.wws_cfg));
+	ret = sizeof(wws->param.wws_cfg);
+
+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 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_MARVELL) + strlen(PRIV_CMD_REASSOCTRL);
+
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		data = (int)(priv->reassoc_on);
+		memcpy(respbuf, &data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_TXBUF_CFG);
+
+	if (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;
+	memcpy(respbuf, &buf_size, sizeof(buf_size));
+	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_MARVELL) + strlen(PRIV_CMD_AUTH_TYPE);
+
+	if (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;
+		memcpy(respbuf, &auth_type, sizeof(auth_type));
+		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_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;
+			}
+		} 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_MARVELL) + strlen(PRIV_CMD_POWER_CONS);
+
+	if (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;
+		memcpy(respbuf, &data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_HT_STREAM_CFG);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	ret = sizeof(data);
+
+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_MARVELL) + strlen(PRIV_CMD_THERMAL);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	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_MARVELL) + strlen(PRIV_CMD_BCN_INTERVAL);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	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 buflen = 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_MARVELL) + strlen(PRIV_CMD_GET_SIGNAL);
+
+	if (strlen(respbuf) != header_len)
+		parse_arguments(respbuf + header_len, in_data, IN_DATA_SIZE,
+				&user_data_len);
+	buflen = MIN(user_data_len, IN_DATA_SIZE);
+
+	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;
+	}
+
+	memcpy(respbuf, out_data, (data_length * sizeof(int)));
+	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_MARVELL) + strlen(PRIV_CMD_GET_SIGNAL_EXT);
+
+	if (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) {
+		memcpy(signal_get, info->param.signal_ext, sizeof(signal_get));
+		path_num = MAX_PATH_NUM;
+	} else
+		memcpy(signal_get, info->param.signal_ext,
+		       sizeof(mlan_ds_get_signal));
+
+	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;
+	}
+	memcpy(respbuf, out_data,
+	       (MIN((PATH_SIZE * MAX_PATH_NUM), data_len) * sizeof(int)));
+	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_MARVELL) + strlen(PRIV_CMD_GET_SIGNAL_EXT_V2);
+	if (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) {
+		memcpy(signal_get, info->param.signal_ext, sizeof(signal_get));
+		path_num = MAX_PATH_NUM;
+	} else
+		memcpy(signal_get, info->param.signal_ext,
+		       sizeof(mlan_ds_get_signal));
+
+	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;
+	}
+	memcpy(respbuf, out_data,
+	       (MIN((PATH_SIZE * MAX_PATH_NUM), data_len) * sizeof(int)));
+	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_MARVELL) + strlen(PRIV_CMD_SIGNALEXT_CFG);
+	if (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
+ */
+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_MARVELL) + strlen(PRIV_CMD_PMFCFG);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.pmfcfg,
+	       sizeof(mlan_ds_misc_pmfcfg));
+	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_MARVELL) + strlen(PRIV_CMD_INACTIVITYTO);
+	memset(data, 0, sizeof(data));
+	if (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;
+
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		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];
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + 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 (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;
+
+	memcpy(respbuf, (t_u8 *)data, sizeof(data));
+	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_MARVELL) + 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 (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;
+
+	memcpy(respbuf, (t_u8 *)&bf_cap, sizeof(bf_cap));
+	ret = sizeof(bf_cap);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @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_MARVELL) + strlen(PRIV_CMD_SDIO_CLOCK);
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		memcpy(respbuf, (t_u8 *)&clock_state, sizeof(clock_state));
+		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;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ * @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_MARVELL) + strlen(PRIV_CMD_MPA_CTRL);
+	if (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]);
+
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		ret = sizeof(data);
+		goto done;
+	}
+
+	switch (user_data_len) {
+	case 6:
+		misc->param.mpa_ctrl.rx_max_ports = data[5];
+	case 5:
+		misc->param.mpa_ctrl.tx_max_ports = data[4];
+	case 4:
+		misc->param.mpa_ctrl.rx_buf_size = data[3];
+	case 3:
+		misc->param.mpa_ctrl.tx_buf_size = data[2];
+	case 2:
+		misc->param.mpa_ctrl.rx_enable = data[1];
+	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[][35] = { {"sleep clock error in ppm"},
+	{"wakeup offset in usec"},
+	{"clock stabilization time in usec"},
+	{"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_MARVELL) + strlen(PRIV_CMD_SLEEP_PARAMS);
+	if (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;
+
+	memcpy(respbuf, (t_u8 *)data, sizeof(data));
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get network monitor configurations
+ *
+ * @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_net_monitor_ioctl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int user_data_len = 0, header_len = 0;
+	int data_length = 0;
+	int data[5] = { 0 };
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_net_monitor *net_mon = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = priv->phandle;
+	monitor_iface *mon_if = NULL;
+	struct net_device *ndev = NULL;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_NET_MON);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
+	misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if (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 || user_data_len == 2 ||
+		    user_data_len == 4 || user_data_len == 5) {
+			if (data[0] != MTRUE && data[0] != MFALSE) {
+				PRINTM(MERROR,
+				       "NET_MON: Activity should be enable(=1)/"
+				       "disable(=0)\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			net_mon->enable_net_mon = data[0];
+			if (data[0] == MTRUE) {
+				int i;
+				if (user_data_len != 2 && user_data_len != 4
+				    && user_data_len != 5) {
+					PRINTM(MERROR,
+					       "NET_MON: Invalid number of args!\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				/* Supported filter flags */
+				if (!data[1] || data[1] &
+				    ~(MLAN_NETMON_DATA | MLAN_NETMON_MANAGEMENT
+				      | MLAN_NETMON_CONTROL | MLAN_NETMON_NOPROM
+				      | MLAN_NETMON_DECRYPTED)) {
+					PRINTM(MERROR,
+					       "NET_MON: Invalid filter flag\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				if (user_data_len > 2) {
+					/* Supported bands */
+					for (i = 0;
+					     i < sizeof(SupportedAdhocBand);
+					     i++)
+						if (data[2] ==
+						    SupportedAdhocBand[i])
+							break;
+					if (i == sizeof(SupportedAdhocBand)) {
+						PRINTM(MERROR,
+						       "NET_MON: Invalid band\n");
+						ret = -EINVAL;
+						goto done;
+					}
+				}
+				/* Supported channel */
+				if (user_data_len > 3 &&
+				    (data[3] < 1 ||
+				     data[3] > MLAN_MAX_CHANNEL)) {
+					PRINTM(MERROR,
+					       "NET_MON: Invalid channel number\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				if (user_data_len == 5) {
+					/* Secondary channel offset */
+					if (!(data[2] & (BAND_GN | BAND_AN))) {
+						PRINTM(MERROR,
+						       "No 11n in band, can not set "
+						       "secondary channel offset\n");
+						ret = -EINVAL;
+						goto done;
+					}
+					if ((data[4] != CHANNEL_BW_20MHZ) &&
+					    (data[4] != CHANNEL_BW_40MHZ_ABOVE)
+					    && (data[4] !=
+						CHANNEL_BW_40MHZ_BELOW)
+					    && (data[4] != CHANNEL_BW_80MHZ)
+						) {
+						PRINTM(MERROR,
+						       "Invalid secondary channel bandwidth, "
+						       "only allowed 0, 1, 3 or 4\n");
+						ret = -EINVAL;
+						goto done;
+					}
+					net_mon->chan_bandwidth = data[4];
+				}
+
+				net_mon->filter_flag = data[1];
+				net_mon->band = data[2];
+				net_mon->channel = data[3];
+			}
+			req->action = MLAN_ACT_SET;
+		} else {
+			PRINTM(MERROR, "NET_MON: Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "NET_MON: woal_request_ioctl fail\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_SET) {
+		if (data[0]) {
+			/* Enable sniffer mode */
+			if (!handle->mon_if) {
+				mon_if = woal_prepare_mon_if(priv, "rtap", 0);
+				if (!mon_if) {
+					PRINTM(MFATAL,
+					       "Prepare mon_if fail.\n");
+					ret = -EFAULT;
+					goto done;
+				}
+				ndev = mon_if->mon_ndev;
+				ret = register_netdevice(ndev);
+				if (ret) {
+					PRINTM(MFATAL,
+					       "register net_device failed, ret=%d\n",
+					       ret);
+					free_netdev(ndev);
+					ret = -EFAULT;
+					goto done;
+				}
+				handle->mon_if = mon_if;
+			}
+			/* Save band channel config */
+			handle->mon_if->band_chan_cfg.band = net_mon->band;
+			handle->mon_if->band_chan_cfg.channel =
+				net_mon->channel;
+			handle->mon_if->band_chan_cfg.chan_bandwidth =
+				net_mon->chan_bandwidth;
+		} else {
+			/* Disable sniffer mode */
+			if (handle->mon_if) {
+				ndev = handle->mon_if->mon_ndev;
+				handle->mon_if = NULL;
+				unregister_netdevice(ndev);
+			}
+		}
+	}
+
+	data[0] = net_mon->enable_net_mon;
+	data[1] = net_mon->filter_flag;
+	data[2] = net_mon->band;
+	data[3] = net_mon->channel;
+	data[4] = net_mon->chan_bandwidth;
+	data_length = 5;
+	memcpy(respbuf, (t_u8 *)data, sizeof(int) * data_length);
+	ret = sizeof(int) * data_length;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ * @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[4];
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + 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 (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 != 4) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[0] > 0xFFFFF) {
+			PRINTM(MERROR,
+			       "The maximum user CAC is 1048575 msec (17 mins approx).\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[1] > 0xFFFFF) {
+			PRINTM(MERROR,
+			       "The maximum user NOP is 1048575 msec (17 mins approx).\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_u32)data[0];
+		ds_11hcfg->param.dfs_testing.usr_nop_period_sec =
+			(t_u32)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 / 1000;
+		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;
+		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;
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif /* DFS_SUPPORT && DFS_TESTING_SUPPORT */
+
+/**
+ * @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];
+	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_MARVELL) + 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 (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;
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		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_MARVELL) + 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 (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];
+		} 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;
+			memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		} 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;
+			memcpy(respbuf, (t_u8 *)data, sizeof(data));
+			ret = sizeof(data);
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(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_MARVELL) + 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 (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 || data[1] > 15)) {
+					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;
+	memcpy(respbuf, (t_u8 *)data, sizeof(data));
+	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_MARVELL) + strlen(PRIV_CMD_SYSCLOCK);
+	memset(data, 0, sizeof(data));
+	if (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++;
+
+		memcpy(respbuf, data, sizeof(int) * data_length);
+		ret = data_length * sizeof(int);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/** AES key length */
+#define AES_KEY_LEN 16
+/**
+ * @brief               Adhoc AES control
+ * @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_adhoc_aes(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	static char buf[256];
+	int ret = 0, action = -1;
+	unsigned int i;
+	t_u8 key_ascii[32];
+	t_u8 key_hex[16];
+	t_u8 *tmp;
+	mlan_bss_info bss_info;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	int header_len = 0;
+	int copy_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ADHOC_AES);
+	memset(key_ascii, 0x00, sizeof(key_ascii));
+	memset(key_hex, 0x00, sizeof(key_hex));
+	memset(buf, 0x00, sizeof(buf));
+
+	/* Get current BSS information */
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (bss_info.bss_mode != MLAN_BSS_MODE_IBSS ||
+	    bss_info.media_connected == MTRUE) {
+		PRINTM(MERROR, "STA is connected or not in IBSS mode.\n");
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (strlen(respbuf) == header_len) {
+		/* Get Adhoc AES 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_CFG_ENCRYPT_KEY;
+		sec->param.encrypt_key.key_len = AES_KEY_LEN;
+		sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_UNICAST;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memcpy(key_hex, sec->param.encrypt_key.key_material,
+		       sizeof(key_hex));
+		HEXDUMP("Adhoc AES Key (HEX)", key_hex, sizeof(key_hex));
+
+		tmp = key_ascii;
+		for (i = 0; i < sizeof(key_hex); i++)
+			tmp += sprintf((char *)tmp, "%02x", key_hex[i]);
+	} else {
+		/* SET operation */
+		copy_len = (strlen(respbuf) - header_len);
+		if (copy_len >= sizeof(buf)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		memcpy(buf, respbuf + header_len, copy_len);
+
+		/* Parse the buf to get the cmd_action */
+		action = woal_atox(&buf[0]);
+		if (action < 1 || action > 2) {
+			PRINTM(MERROR, "Invalid action argument %d\n", action);
+			ret = -EINVAL;
+			goto done;
+		}
+
+		req->req_id = MLAN_IOCTL_SEC_CFG;
+		req->action = MLAN_ACT_SET;
+		sec = (mlan_ds_sec_cfg *)req->pbuf;
+		sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+
+		if (action == 1) {
+			/* Set Adhoc AES Key  */
+			memcpy(key_ascii, &buf[2], sizeof(key_ascii));
+			woal_ascii2hex(key_hex, (char *)key_ascii,
+				       sizeof(key_hex));
+			HEXDUMP("Adhoc AES Key (HEX)", key_hex,
+				sizeof(key_hex));
+
+			sec->param.encrypt_key.key_len = AES_KEY_LEN;
+			sec->param.encrypt_key.key_index =
+				MLAN_KEY_INDEX_UNICAST;
+			sec->param.encrypt_key.key_flags =
+				KEY_FLAG_SET_TX_KEY | KEY_FLAG_GROUP_KEY;
+			memcpy(sec->param.encrypt_key.mac_addr,
+			       (u8 *)bcast_addr, ETH_ALEN);
+			memcpy(sec->param.encrypt_key.key_material, key_hex,
+			       sec->param.encrypt_key.key_len);
+
+			status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				ret = -EFAULT;
+				goto done;
+			}
+		} else {
+			/* Clear Adhoc AES Key */
+			sec->param.encrypt_key.key_len = AES_KEY_LEN;
+			sec->param.encrypt_key.key_index =
+				MLAN_KEY_INDEX_UNICAST;
+			sec->param.encrypt_key.key_flags = KEY_FLAG_REMOVE_KEY;
+			memcpy(sec->param.encrypt_key.mac_addr,
+			       (u8 *)bcast_addr, ETH_ALEN);
+			memset(sec->param.encrypt_key.key_material, 0,
+			       sizeof(sec->param.encrypt_key.key_material));
+
+			status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	}
+
+	HEXDUMP("Adhoc AES Key (ASCII)", key_ascii, sizeof(key_ascii));
+	copy_len = sizeof(key_ascii);
+	memcpy(respbuf, &key_ascii, copy_len);
+	ret = copy_len;
+
+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_MARVELL) + strlen(PRIV_CMD_GET_KEY);
+	if (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;
+	memcpy(respbuf, &key_ascii, copy_len);
+	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_MARVELL) + strlen(PRIV_CMD_ASSOCIATE);
+	if (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, (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;
+	}
+
+	memcpy(buf, respbuf + header_len, buflen);
+
+	/* 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;
+	memcpy(ssid_bssid.ssid.ssid, buf + i, 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)) {
+		memcpy(&priv->prev_ssid_bssid.ssid,
+		       &bss_info.ssid, sizeof(mlan_802_11_ssid));
+		memcpy(&priv->prev_ssid_bssid.bssid,
+		       &bss_info.bssid, MLAN_MAC_ADDR_LENGTH);
+	}
+#endif /* REASSOCIATION */
+
+done:
+	LEAVE();
+	return 0;
+}
+
+/* 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 MAX_TX_BF_GLOBAL_ARGS   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;
+	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_MARVELL) + strlen(PRIV_CMD_TX_BF_CFG);
+	if (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 > sizeof(buf)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		memcpy(buf, respbuf + header_len, copy_len);
+
+		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:
+		memcpy(respbuf, bf_global, sizeof(mlan_bf_global_cfg_args));
+		ret = sizeof(mlan_bf_global_cfg_args);
+		break;
+	case TRIGGER_SOUNDING_FOR_PEER:
+		memcpy(respbuf, bf_sound, sizeof(mlan_bf_global_cfg_args));
+		ret = sizeof(mlan_bf_global_cfg_args);
+		break;
+	case SET_GET_BF_PERIODICITY:
+		memcpy(respbuf, bf_periodicity,
+		       sizeof(mlan_bf_periodicity_args));
+		ret = sizeof(mlan_bf_periodicity_args);
+		break;
+	case TX_BF_FOR_PEER_ENBL:
+		memcpy(respbuf, tx_bf_peer, sizeof(mlan_tx_bf_peer_args));
+		ret = sizeof(mlan_tx_bf_peer_args);
+		break;
+	case SET_SNR_THR_PEER:
+		memcpy(respbuf, bf_snr, sizeof(mlan_snr_thr_args));
+		ret = sizeof(mlan_snr_thr_args);
+		break;
+	default:
+		ret = 0;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @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, func, 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_MARVELL) + 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;
+	}
+	memcpy(&cmd_len, respbuf + header_len, sizeof(cmd_len));
+	buf = respbuf + header_len + sizeof(cmd_len);
+
+	rw = buf[0];		/* read/write (0/1) */
+	func = buf[1];		/* func (0/1/2) */
+	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, func = %d, addr = %#x, mode = %d, "
+	       "block size = %d, block(byte) number = %d\n",
+	       func, 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 < 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;
+}
+
+/**
+ * @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_MARVELL) + strlen(PRIV_CMD_PORT_CTRL);
+	if (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) {
+		memcpy(respbuf, &sec->param.port_ctrl_enabled, sizeof(int));
+		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_MARVELL) + 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);
+
+	memcpy(skb_put(skb, copyLen), respbuf + header_len, 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               Control Coalescing status Enable/Disable
+ * @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_coalescing_status(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data = 0;
+	mlan_ds_misc_cfg *pcoal = 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;
+	}
+	pcoal = (mlan_ds_misc_cfg *)req->pbuf;
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_COALESCE_STATUS);
+	if (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) {
+			if (data == 1)
+				pcoal->param.coalescing_status =
+					MLAN_MISC_COALESCING_ENABLE;
+			else
+				pcoal->param.coalescing_status =
+					MLAN_MISC_COALESCING_DISABLE;
+			req->action = MLAN_ACT_SET;
+		} else {
+			PRINTM(MERROR, "Invalid number of parameters\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	pcoal->sub_command = MLAN_OID_MISC_COALESCING_STATUS;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	data = (int)(((mlan_ds_misc_cfg *)req->pbuf)->param.coalescing_status);
+
+	memcpy(respbuf, &data, sizeof(int));
+	ret = sizeof(int);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get module 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_fw_wakeup_method(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[2];
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	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;
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_FW_WAKEUP_METHOD);
+	if (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 > 2) {
+			PRINTM(MERROR, "Invalid parameter number\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] != FW_WAKEUP_METHOD_INTERFACE &&
+		    data[0] != FW_WAKEUP_METHOD_GPIO) {
+			PRINTM(MERROR, "Invalid FW wake up method:%d\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == FW_WAKEUP_METHOD_GPIO) {
+			if (user_data_len == 1) {
+				PRINTM(MERROR,
+				       "Please provide gpio pin number for FW_WAKEUP_METHOD gpio\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			pm_cfg->param.fw_wakeup_params.gpio_pin = data[1];
+		}
+
+		req->action = MLAN_ACT_SET;
+		pm_cfg->param.fw_wakeup_params.method = data[0];
+	}
+
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_FW_WAKEUP_METHOD;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = ((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.method;
+	data[1] =
+		((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.gpio_pin;
+	memcpy(respbuf, &data, sizeof(data));
+	ret = sizeof(int) * 2;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	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];
+	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 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_MARVELL) + strlen(PRIV_CMD_BOOTSLEEP);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &misc->param.boot_sleep,
+	       sizeof(misc->param.boot_sleep));
+	ret = sizeof(misc->param.boot_sleep);
+
+	PRINTM(MIOCTL, "boot sleep cfg: 0x%u\n", misc->param.boot_sleep);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief                    Keep connect to refuse disconnect
+ * @param priv            Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return                 0 for success, negative for failure.
+ */
+static int
+woal_priv_keep_connect(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int user_data_len = 0;
+	int keep_connect_en = 0;
+	int ret = 0;
+
+	ENTER();
+	parse_arguments(respbuf, &keep_connect_en,
+			sizeof(keep_connect_en) / sizeof(int), &user_data_len);
+	if (!user_data_len) {
+		PRINTM(MERROR, "Invalid parameter number\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (keep_connect_en != 0 && keep_connect_en != 1) {
+		PRINTM(MERROR, "Invalid agrs!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (keep_connect_en == 1) {
+		priv->keep_connect = MTRUE;
+	} else {
+		priv->keep_connect = MFALSE;
+	}
+
+done:
+	LEAVE();
+	return 0;
+}
+
+#if defined(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_MARVELL) + 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 (strlen(respbuf) == header_len) {
+		/* GET operation */
+		memcpy(respbuf, &noa_cfg, sizeof(noa_cfg));
+		ret = sizeof(noa_cfg);
+	} else {
+		switch (user_data_len) {
+		case 5:
+			noa_cfg.noa_interval = (t_u32)data[4];
+		case 4:
+			noa_cfg.noa_duration = (t_u32)data[3];
+		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];
+		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];
+		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_MARVELL) + 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 (strlen(respbuf) == header_len) {
+		/* GET operation */
+		memcpy(respbuf, &opp_ps_cfg, sizeof(opp_ps_cfg));
+		ret = sizeof(opp_ps_cfg);
+	} else {
+		switch (user_data_len) {
+		case 2:
+			opp_ps_cfg.ct_window = (t_u8)data[1];
+		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;
+		default:
+			break;
+		}
+		woal_p2p_config(priv, MLAN_ACT_SET, &opp_ps_cfg);
+	}
+
+done:
+
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+#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
+
+#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_MARVELL) + strlen(PRIV_CMD_MIRACAST_CFG);
+
+	if (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;
+
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		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
+ */
+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_MARVELL) + 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 (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) {
+		memcpy(respbuf, (t_u8 *)&cfg_11n->param.coex_rx_winsize,
+		       sizeof(t_u32));
+		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_MARVELL) + 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 (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) {
+		memcpy(respbuf, (t_u8 *)&cfg_11n->param.txaggrctrl,
+		       sizeof(t_u32));
+		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_MARVELL) + strlen(PRIV_CMD_AUTO_TDLS);
+
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		data = priv->enable_auto_tdls;
+		memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+		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;
+}
+
+/**
+ * @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);
+	memcpy(respbuf, &pcfg->param.sensor_temp.temperature, sizeof(t_u32));
+
+	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;
+
+	ENTER();
+
+	if (priv && priv->wdev)
+		wiphy = priv->wdev->wiphy;
+	if (!wiphy) {
+		PRINTM(MERROR, "wiphy is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	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_MARVELL) + 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;
+		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 (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_MARVELL) + strlen(PRIV_CMD_TDLS_IDLE_TIME);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&misc->param.tdls_idle_time, sizeof(t_u16));
+	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_MARVELL) + strlen(PRIV_CMD_DYN_BW);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&misc->param.dyn_bw, sizeof(t_u16));
+	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 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
+ */
+
+t_u8
+woal_get_center_freq_idx(IN moal_private *priv,
+			 IN t_u8 band, IN t_u32 pri_chan, IN 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;
+			}
+		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;
+			}
+		case 52:
+		case 56:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 54;
+				break;
+			}
+		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;
+			}
+		case 68:
+		case 72:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 70;
+				break;
+			}
+		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;
+			}
+		case 84:
+		case 88:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 86;
+				break;
+			}
+		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;
+			}
+		case 100:
+		case 104:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 102;
+				break;
+			}
+		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;
+			}
+		case 116:
+		case 120:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 118;
+				break;
+			}
+		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;
+			}
+		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;
+			}
+		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;
+			}
+		case 165:
+		case 169:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 167;
+				break;
+			}
+		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;
+			}
+		case 184:
+		case 188:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 186;
+				break;
+			}
+		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;
+			}
+
+		default:	/* error. go to the default */
+			center_freq_idx = 42;
+		}
+	}
+	return center_freq_idx;
+}
+
+/**
+ ** @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 };
+	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;
+
+	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_ChanSwitchAnn_t);
+	pcust_chansw_ie->mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP;	/*Add IE for BEACON/probe resp */
+
+	parse_arguments(respbuf + strlen(CMD_MARVELL) +
+			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;
+		goto done;
+	}
+	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 = data[0];
+	chan_switch->new_channel_num = data[2];
+	chan_switch->chan_switch_count = data[3];
+	DBG_HEXDUMP(MCMD_D, "CSA IE", (t_u8 *)pcust_chansw_ie->ie_buffer,
+		    pcust_chansw_ie->ie_length);
+
+	if (data[1] != 0) {
+		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 = data[0];
+		ext_chan_switch->new_oper_class = data[1];
+		ext_chan_switch->new_channel_num = data[2];
+		ext_chan_switch->chan_switch_count = data[3];
+		if (woal_check_valid_channel_operclass(priv, data[2], data[1])) {
+			PRINTM(MERROR, "Wrong channel switch parameters!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		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 (data[4] && data[2] > 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, data[2],
+						 data[4]);
+		if (data[4] == CHANNEL_BW_40MHZ_ABOVE ||
+		    data[4] == CHANNEL_BW_40MHZ_BELOW) {
+			pbwchansw_ie->new_channel_width = 0;
+			pbwchansw_ie->new_channel_center_freq0 =
+				center_freq_idx;
+		} else if (data[4] == 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 (data[4] == 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;
+		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 (data[0]) {
+		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 * (data[3] + 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;
+}
+
+/**
+ * @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               Issue ACS command to FW to get best channel and channel stats
+ *
+ * @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_acs(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0;
+	int data[MAX_BG_CHANNEL + 1];
+	int user_data_len = 0;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_acs *acs = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int i = 0, j = 0;
+	int ch_cnt = 0;
+	int resp_len = 0;
+	acs_result *pacs_result = NULL;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ACS_SCAN);
+
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+	if (user_data_len < 0 || user_data_len > MAX_CH_STATS) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+    /** Input format: [channels on 2.4G] */
+    /** Check validity of input channels if enable */
+	if (user_data_len < 2 && user_data_len != 0) {
+		PRINTM(MERROR,
+		       "If specify channels, at least specify 2 channels.\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	for (i = 0; i < user_data_len; i++) {
+		if (data[i] < 1 || data[i] > MAX_BG_CHANNEL) {
+			PRINTM(MERROR, "Invalid input channel %d.\n", data[i]);
+			ret = -EINVAL;
+			goto done;
+		}
+		for (j = 0; j < i; j++) {
+			if (data[j] == data[i]) {
+				PRINTM(MERROR, "Duplicate input channel %d.\n",
+				       data[i]);
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		ch_cnt++;
+	}
+
+	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;
+	req->action = MLAN_ACT_SET;
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_ACS;
+	acs = &(misc->param.acs);
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	acs->scan_chan_gap = priv->phandle->scan_chan_gap;
+#endif
+	for (i = 0; i < ch_cnt; i++)
+		acs->ch_stats[i].chan_num = data[i];
+	acs->ch_stats_num = ch_cnt;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	resp_len = sizeof(acs_result) + acs->ch_stats_num * sizeof(ChStat_t);
+	if (respbuflen < resp_len) {
+		PRINTM(MERROR, "response buffer length is too short!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+    /** Fill respond buf */
+	pacs_result = (acs_result *) respbuf;
+	pacs_result->best_ch = acs->best_ch;
+	pacs_result->ch_stats_num = acs->ch_stats_num;
+	memcpy(pacs_result->ch_stats, acs->ch_stats,
+	       sizeof(ChStat_t) * MIN(MAX_CH_STATS, pacs_result->ch_stats_num));
+
+	ret = resp_len;
+
+done:
+	if (req && status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	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;
+
+	ENTER();
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&priv_cmd, req->ifr_data,
+			   sizeof(android_wifi_priv_cmd))) {
+		ret = -EFAULT;
+		goto done;
+	}
+#define CMD_BUF_LEN   2048
+	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
+	memcpy(&cmd_buf, &priv_cmd.buf, sizeof(cmd_buf));
+#else
+	cmd_buf = priv_cmd.buf;
+#endif
+	if (copy_from_user(buf, 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_MARVELL, strlen(CMD_MARVELL)) &&
+	    woal_check_driver_status(priv->phandle)) {
+		PRINTM(MERROR, "%s fail when driver hang\n", buf);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (strncmp(buf, CMD_MARVELL, strlen(CMD_MARVELL)) == 0) {
+		/* This command has come from mlanutl app */
+
+		/* Check command */
+		if (strnicmp
+		    (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_MEMRDWR,
+			    strlen(PRIV_CMD_MEMRDWR)) == 0) {
+			/* Memory Read/Write */
+			len = woal_priv_memrdwr(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_SDCMD52RW,
+			    strlen(PRIV_CMD_SDCMD52RW)) == 0) {
+			/* Cmd52 read/write register */
+			len = woal_priv_sdcmd52rw(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#ifdef STA_SUPPORT
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_ARPFILTER,
+			    strlen(PRIV_CMD_ARPFILTER)) == 0) {
+			/* ARPFilter Configuration */
+			len = woal_priv_arpfilter(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#endif
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_QOS_CFG,
+			    strlen(PRIV_CMD_QOS_CFG)) == 0) {
+			t_u32 action = MLAN_ACT_GET;
+			if (strlen(buf) ==
+			    strlen(CMD_MARVELL) + strlen(PRIV_CMD_QOS_CFG)) {
+				pdata = buf;	/* GET operation */
+			} else {
+				pdata = buf + strlen(CMD_MARVELL) +
+					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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_DRCS_CFG,
+			    strlen(PRIV_CMD_DRCS_CFG)) == 0) {
+			/* DRCS configuration for mc_cfg_ext */
+			len = woal_priv_drcs_time_slicing_cfg(priv, buf,
+							      priv_cmd.
+							      total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_MULTI_CHAN_CFG,
+			    strlen(PRIV_CMD_MULTI_CHAN_CFG)) == 0) {
+			/* Channel time and buffer weight configuration */
+			len = woal_priv_multi_chan_config(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL),
+			    PRIV_CMD_MULTI_CHAN_POLICY,
+			    strlen(PRIV_CMD_MULTI_CHAN_POLICY)) == 0) {
+			/* Multi-channel Policy enable/disable */
+			len = woal_priv_multi_chan_policy(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_FWMACADDR,
+			    strlen(PRIV_CMD_FWMACADDR)) == 0) {
+			/* Set FW MAC address */
+			len = woal_priv_fwmacaddr(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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;
+#if defined(STA_SUPPORT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#if defined(REASSOCIATION)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL),
+			    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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#endif
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), PRIV_CMD_NET_MON,
+			    strlen(PRIV_CMD_NET_MON)) == 0) {
+			/* Set/Get network monitor configurations */
+			len = woal_priv_net_monitor_ioctl(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+#if defined(DFS_TESTING_SUPPORT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#endif
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_ADHOC_AES,
+			    strlen(PRIV_CMD_ADHOC_AES)) == 0) {
+			/* Adhoc AES control */
+			len = woal_priv_adhoc_aes(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_ROBUSTCOEX,
+			    strlen(PRIV_CMD_ROBUSTCOEX)) == 0) {
+			/* Set Robustcoex GPIOcfg */
+			pdata = buf + strlen(CMD_MARVELL) +
+				strlen(PRIV_CMD_ROBUSTCOEX);
+			len = priv_cmd.total_len - strlen(PRIV_CMD_ROBUSTCOEX) -
+				strlen(CMD_MARVELL);
+			len = woal_priv_robustcoex(priv, pdata, len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), PRIV_CMD_KEEP_CONNECT,
+			    strlen(PRIV_CMD_KEEP_CONNECT)) == 0) {
+			pdata = buf + strlen(CMD_MARVELL) +
+				strlen(PRIV_CMD_KEEP_CONNECT);
+			len = woal_priv_keep_connect(priv, pdata, len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_COALESCE_STATUS,
+			    strlen(PRIV_CMD_COALESCE_STATUS)) == 0) {
+			/* Control Coalescing status Enable/Disable */
+			len = woal_priv_coalescing_status(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL),
+			    PRIV_CMD_FW_WAKEUP_METHOD,
+			    strlen(PRIV_CMD_FW_WAKEUP_METHOD)) == 0) {
+			/* Set/Get module configuration */
+			len = woal_priv_fw_wakeup_method(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(UAP_CFG80211)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL),
+			    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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_ACS_SCAN,
+			    strlen(PRIV_CMD_ACS_SCAN)) == 0) {
+			len = woal_priv_acs(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else {
+			PRINTM(MERROR,
+			       "Unknown MARVELL 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 (!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 (*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 (*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));
+		memcpy(country_code, buf + strlen("COUNTRY") + 1, copy_len);
+		PRINTM(MIOCTL, "Set COUNTRY %s\n", country_code);
+		if (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);
+			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 <= 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);
+		memcpy(buf, priv->current_addr, ETH_ALEN);
+		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 {
+		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(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();
+
+	memcpy(ptmp_buf, pbss_desc->time_stamp, sizeof(pbss_desc->time_stamp));
+	ptmp_buf += sizeof(pbss_desc->time_stamp);
+
+	memcpy(ptmp_buf, &pbss_desc->beacon_period,
+	       sizeof(pbss_desc->beacon_period));
+	ptmp_buf += sizeof(pbss_desc->beacon_period);
+
+	memcpy(ptmp_buf, &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;
+	memcpy(ptmp_buf, tmp_ssid_hdr, sizeof(tmp_ssid_hdr));
+	ptmp_buf += sizeof(tmp_ssid_hdr);
+
+	memcpy(ptmp_buf, pbss_desc->ssid.ssid, 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;
+		memcpy(ptmp_buf, &pbss_desc->wmm_ie, 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;
+			memcpy(ptmp_buf, pbss_desc->pwpa_ie, 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;
+			memcpy(ptmp_buf, pbss_desc->prsn_ie, 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));
+
+	memcpy(tmp_rsp_entry.fixed_fields.bssid,
+	       pbss_desc->mac_address, 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.network_tsf = pbss_desc->network_tsf;
+	tmp_rsp_entry.bss_info_length = variable_size;
+
+	/*
+	 *  Copy fixed fields to user space
+	 */
+	memcpy(pcurrent, &tmp_rsp_entry, fixed_size);
+	pcurrent += fixed_size;
+
+	if (pbss_desc->pbeacon_buf) {
+		/*
+		 *  Copy variable length elements to user space
+		 */
+		memcpy(pcurrent, pbss_desc->pbeacon_buf,
+		       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
+ */
+int
+woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	int ret = 0;
+
+	ENTER();
+
+	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_sd8897/mlinux/moal_eth_ioctl.h b/wlan_sd8897/mlinux/moal_eth_ioctl.h
new file mode 100644
index 0000000..9f3aa4e
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_eth_ioctl.h
@@ -0,0 +1,475 @@
+
+/** @file moal_eth_ioctl.h
+ *
+ * @brief This file contains definition for private IOCTL call.
+ *
+ * Copyright (C) 2014-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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
+
+/** Marvell private command identifier string */
+#define CMD_MARVELL     "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
+#if defined(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_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_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"
+#define PRIV_CMD_SDCMD52RW      "sdcmd52rw"
+#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"
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+#define PRIV_CMD_RADIO_CTRL     "radioctrl"
+#endif
+#define PRIV_CMD_WMM_CFG        "wmmcfg"
+#if defined(STA_SUPPORT)
+#define PRIV_CMD_11D_CFG        "11dcfg"
+#define PRIV_CMD_11D_CLR_TBL    "11dclrtbl"
+#endif
+#define PRIV_CMD_WWS_CFG        "wwscfg"
+#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_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"
+#define PRIV_CMD_SDIO_CLOCK         "sdioclock"
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+#define PRIV_CMD_MPA_CTRL           "mpactrl"
+#endif
+#define PRIV_CMD_SLEEP_PARAMS       "sleepparams"
+#define PRIV_CMD_NET_MON            "netmon"
+#if defined(DFS_TESTING_SUPPORT)
+#define PRIV_CMD_DFS_TESTING        "dfstesting"
+#endif
+#define PRIV_CMD_CFP_CODE           "cfpcode"
+#define PRIV_CMD_ANT_CFG            "antcfg"
+#define PRIV_CMD_SYSCLOCK       "sysclock"
+#define PRIV_CMD_ADHOC_AES      "adhocaes"
+#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"
+#define PRIV_CMD_COALESCE_STATUS    "coalesce_status"
+#define PRIV_CMD_FW_WAKEUP_METHOD   "fwwakeupmethod"
+#define PRIV_CMD_SD_CMD53_RW        "sdcmd53rw"
+#ifdef RX_PACKET_COALESCE
+#define PRIV_CMD_RX_COAL_CFG "rxpktcoal_cfg"
+#endif
+#define PRIV_CMD_MULTI_CHAN_CFG "mc_cfg"
+#define PRIV_CMD_MULTI_CHAN_POLICY "mc_policy"
+#define PRIV_CMD_DRCS_CFG "mc_cfg_ext"
+#if defined(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
+#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"
+
+#define PRIV_CMD_GET_SENSOR_TEMP        "get_sensor_temp"
+
+#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
+
+#if defined(SDIO_SUSPEND_RESUME)
+#define PRIV_CMD_AUTO_ARP	"auto_arp"
+#endif
+
+#define PRIV_CMD_DEAUTH_CTRL    "ctrldeauth"
+
+/**Private command ID to set/get independent reset*/
+#define PRIV_CMD_IND_RST_CFG            "indrstcfg"
+
+/** 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_KEEP_CONNECT         "keep_connect"
+
+#define PRIV_CMD_BOOTSLEEP            "bootsleep"
+
+int woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+
+/*
+ * 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 {
+  /** The value of the parameter itself */
+	t_s32 value;
+  /** Hardware should not use auto select */
+	t_u8 fixed;
+  /** Disable the feature */
+	t_u8 disabled;
+  /** Various specifc flags (if any) */
+	t_u16 flags;
+};
+
+/*
+ *  For all data larger than 16 octets, we need to use a
+ *  pointer to memory allocated in user space.
+ */
+struct mw_point {
+  /** Pointer to the data  (in user space) */
+	t_u8 *pointer;
+  /** number of fields or size in bytes */
+	t_u16 length;
+  /** Optional params */
+	t_u16 flags;
+};
+
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ */
+union mwreq_data {
+    /** Config - generic */
+	char name[IFNAMSIZ];
+
+    /** Extended network name */
+	struct mw_point essid;
+    /** Operation mode */
+	t_u32 mode;
+    /** PM duration/timeout */
+	struct mw_param power;
+    /** Access point address */
+	struct sockaddr ap_addr;
+    /** Other small parameters */
+	struct mw_param param;
+    /** Other large parameters */
+	struct mw_point data;
+};
+
+ /* The structure to exchange data for ioctl */
+struct mwreq {
+	union {
+	/** if name, e.g. "eth0" */
+		char ifrn_name[IFNAMSIZ];
+	} ifr_ifrn;
+
+    /** Data part */
+	union mwreq_data u;
+};
+
+/** woal HT capacity info structure */
+typedef struct woal_priv_ht_cap_info {
+    /** HT capacity info for bg */
+	t_u32 ht_cap_info_bg;
+    /** HT capacity info for a */
+	t_u32 ht_cap_info_a;
+} woal_ht_cap_info;
+
+/** woal private addba structure */
+typedef struct woal_priv_addba {
+    /** Time out */
+	t_u32 time_out;
+    /** Transmission window size */
+	t_u32 tx_win_size;
+    /** Receiver window size */
+	t_u32 rx_win_size;
+    /** Tx amsdu */
+	t_u32 tx_amsdu;
+    /** Rx amsdu */
+	t_u32 rx_amsdu;
+} woal_addba;
+
+/** 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;
+} woal_tx_rate_cfg;
+
+/** woal embedded supplicant structure */
+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);
+mlan_status woal_ioctl_aggr_prio_tbl(moal_private *priv, t_u32 action,
+				     mlan_ds_11n_aggr_prio_tbl *aggr_prio_tbl);
+
+int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req);
+
+#define PRIV_CMD_ACS_SCAN "acs"
+
+/** Type definition of mlan_acs_scan */
+typedef struct _acs_result {
+    /** Best Channel Number */
+	t_u8 best_ch;
+    /** Channel Statistics Number */
+	t_u8 ch_stats_num;
+    /** Channel Statistics */
+	ChStat_t ch_stats[0];
+} acs_result, *pacs_result;
+
+#endif /** _WOAL_ETH_PRIV_H_ */
diff --git a/wlan_sd8897/mlinux/moal_ioctl.c b/wlan_sd8897/mlinux/moal_ioctl.c
new file mode 100644
index 0000000..5b2bd31
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_ioctl.c
@@ -0,0 +1,6285 @@
+/** @file moal_ioctl.c
+  *
+  * @brief This file contains ioctl function to MLAN
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include    "moal_main.h"
+#include    "moal_eth_ioctl.h"
+#include    "moal_sdio.h"
+#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_cfgvendor.h"
+#endif
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+#define MRVL_TLV_HEADER_SIZE            4
+/* Marvell 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[] = {
+	{"US ", 0x10},		/* US FCC            */
+	{"CA ", 0x20},		/* IC Canada         */
+	{"SG ", 0x10},		/* Singapore         */
+	{"EU ", 0x30},		/* ETSI              */
+	{"AU ", 0x30},		/* Australia         */
+	{"KR ", 0x30},		/* Republic Of Korea */
+	{"CN ", 0x50},		/* China             */
+	{"JP ", 0xFF},		/* Japan special     */
+};
+
+/** EEPROM Region code mapping table */
+static region_code_mapping_t hw_region_code_mapping[] = {
+	{"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"
+};
+
+/********************************************************
+			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
+extern int cfg80211_wext;
+int disconnect_on_suspend;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+extern int dfs_offload;
+#endif
+#endif
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief This function converts region string to region code
+ *
+ *  @param region_string    Region string
+ *
+ *  @return                 Region code
+ */
+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 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)
+{
+	int 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)
+		memcpy(&mlist->mac_list[mlist->num_multicast_addr], mac,
+		       ETH_ALEN);
+	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)
+			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_IOCTL_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 = *(t_u32 *)req->pbuf;
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (sub_command != MLAN_OID_GET_DEBUG_INFO) {
+		if (priv->phandle->surprise_removed == MTRUE ||
+		    priv->phandle->driver_state) {
+			PRINTM(MERROR,
+			       "IOCTL is not allowed while the device is not present or hang\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#if defined(SDIO_SUSPEND_RESUME)
+		if (priv->phandle->is_suspended == MTRUE) {
+			PRINTM(MERROR,
+			       "IOCTL is not allowed while suspended\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);
+#ifdef DFS_TESTING_SUPPORT
+		if (priv->phandle->cac_period_jiffies) {
+			cac_left_jiffies = priv->phandle->cac_period_jiffies -
+				(jiffies - priv->phandle->meas_start_jiffies);
+		}
+#endif
+		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 && 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;
+				memcpy(&priv->phandle->delay_ssid_bssid,
+				       &bss->param.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:
+		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
+ *
+ *  @return       MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ *                  -- success, otherwise fail
+ */
+mlan_status
+woal_request_set_mac_address(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_MAC_ADDR;
+	memcpy(&bss->param.mac_addr, priv->current_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, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
+		HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
+	} else {
+		PRINTM(MERROR,
+		       "set mac address failed! status=%d, error_code=0x%x\n",
+		       status, req->status_code);
+	}
+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;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_NO_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)
+		memcpy(&bss->param.deauth_param.mac_addr, mac,
+		       sizeof(mlan_802_11_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 Check current uap/go connection status
+ *         Need handle channel switch if current channel is DFS channel
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param new channel 		new channel
+ *  @return              N/A
+ */
+void
+woal_check_uap_dfs_status(moal_private *priv, t_u8 wait_option,
+			  t_u8 new_channel)
+{
+	chan_band_info channel;
+	mlan_bss_info bss_info;
+#if defined(UAP_SUPPORT)
+	IEEEtypes_ChanSwitchAnn_t *chan_switch = NULL;
+	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;
+	t_u8 bw = 0, oper_class = 0;
+#endif
+
+	/* Get BSS information */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, wait_option, &bss_info))
+		goto done;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_ap_channel(priv, MLAN_ACT_GET, wait_option, &channel))
+		goto done;
+	PRINTM(MCMND, "is_11h_active=%d dfs_check_channel=%d\n",
+	       bss_info.is_11h_active, bss_info.dfs_check_channel);
+	PRINTM(MCMND, "uap current channel=%d new_channel=%d\n",
+	       channel.channel, new_channel);
+#if defined(UAP_SUPPORT)
+	if (new_channel == channel.channel)
+		goto done;
+	if (bss_info.is_11h_active &&
+	    (bss_info.dfs_check_channel == channel.channel)) {
+		if (new_channel < MAX_BG_CHANNEL) {
+			bw = 20;
+		} else {
+			switch (channel.bandcfg.chanWidth) {
+			case CHAN_BW_20MHZ:
+				bw = 20;
+				break;
+			case CHAN_BW_40MHZ:
+				bw = 40;
+				break;
+			case CHAN_BW_80MHZ:
+				bw = 80;
+				break;
+			default:
+				break;
+			}
+		}
+		woal_priv_get_nonglobal_operclass_by_bw_channel(priv, bw,
+								new_channel,
+								&oper_class);
+		PRINTM(MCMND,
+		       "Switch the uap channel from %d to %d, oper_class=%d bw=%d\n",
+		       channel.channel, new_channel, oper_class, bw);
+		ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+		if (ioctl_req) {
+			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 */
+			if (!oper_class) {
+				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 =
+					sizeof(IEEEtypes_ChanSwitchAnn_t) -
+					sizeof(IEEEtypes_Header_t);
+				chan_switch->chan_switch_mode = 1;	/* STA should not transmit */
+				chan_switch->new_channel_num = new_channel;
+				chan_switch->chan_switch_count =
+					DEF_CHAN_SWITCH_COUNT;
+				DBG_HEXDUMP(MCMD_D, "CSA IE",
+					    (t_u8 *)pcust_chansw_ie->ie_buffer,
+					    pcust_chansw_ie->ie_length);
+			} else {
+				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;
+				ext_chan_switch->element_id =
+					EXTEND_CHANNEL_SWITCH_ANN;
+				ext_chan_switch->len =
+					sizeof(IEEEtypes_ExtChanSwitchAnn_t) -
+					sizeof(IEEEtypes_Header_t);
+				ext_chan_switch->chan_switch_mode = 1;	/* STA should not transmit */
+				ext_chan_switch->new_channel_num = new_channel;
+				ext_chan_switch->chan_switch_count =
+					DEF_CHAN_SWITCH_COUNT;
+				ext_chan_switch->new_oper_class = oper_class;
+				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,
+						    wait_option);
+			if (status != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Failed to set CSA IE\n");
+				goto done;
+			}
+			PRINTM(MCMND, "CSA/ECSA ie index=%d\n",
+			       pcust_chansw_ie->ie_index);
+			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 *
+							 (DEF_CHAN_SWITCH_COUNT
+							  + 2) * 110 / 1000);
+
+			pcust_chansw_ie->ie_index = 0xffff;
+			pcust_chansw_ie->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			status = woal_request_ioctl(priv, ioctl_req,
+						    MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Failed to clear CSA/ECSA IE\n");
+			}
+		}
+	}
+#endif
+done:
+#if defined(UAP_SUPPORT)
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+#endif
+	return;
+}
+
+/**
+ *  @brief Check current multi-channel connections
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param new channel 	new channel
+ *
+ *  @return              N/A
+ */
+void
+woal_check_mc_connection(moal_private *priv, t_u8 wait_option, t_u8 new_channel)
+{
+	moal_handle *handle = priv->phandle;
+#ifdef UAP_SUPPORT
+	int i;
+#endif
+	t_u16 enable = 0;
+
+	woal_mc_policy_cfg(priv, &enable, wait_option, MLAN_ACT_GET);
+	if (!enable)
+		return;
+#ifdef UAP_SUPPORT
+	for (i = 0; i < handle->priv_num; i++) {
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
+			if (handle->priv[i]->bss_started == MTRUE)
+				woal_check_uap_dfs_status(handle->priv[i],
+							  wait_option,
+							  new_channel);
+		}
+	}
+#endif
+	return;
+}
+
+/**
+ *  @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;
+	mlan_ssid_bssid temp_ssid_bssid;
+
+	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);
+	}
+	memcpy(&temp_ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_find_best_network(priv, wait_option, &temp_ssid_bssid))
+		woal_check_mc_connection(priv, wait_option,
+					 temp_ssid_bssid.channel);
+
+	/* 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)
+		memcpy(&bss->param.ssid_bssid, 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);
+#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)
+			memcpy(bss_info, &info->param.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)
+			memcpy(misc->param.gen_ie.ie_data, ie, *ie_len);
+	}
+
+	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)
+			memcpy(ie, misc->param.gen_ie.ie_data, *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(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 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(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(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)
+		memcpy(&pcfg->param.power_cfg, power_cfg,
+		       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)
+		memcpy(power_cfg, &pcfg->param.power_cfg,
+		       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(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 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();
+	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))
+		memcpy(&rate->param.rate_cfg, datarate,
+		       sizeof(mlan_rate_cfg_t));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret == MLAN_STATUS_SUCCESS && datarate && action == MLAN_ACT_GET)
+		memcpy(datarate, &rate->param.rate_cfg,
+		       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)
+		memcpy(assoc_rsp, &misc->param.assoc_resp,
+		       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_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)
+			memcpy(priv->current_addr,
+			       &info->param.fw_info.mac_addr,
+			       sizeof(mlan_802_11_mac_addr));
+		memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
+		if (fw_info)
+			memcpy(fw_info, &info->param.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);
+	memcpy(buf, &cfg->param.ext_cap, sizeof(ExtCap_t));
+	ret = sizeof(ExtCap_t);
+out:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef PROC_DEBUG
+/**
+ *  @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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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) {
+			memcpy(debug_info, &info->param.debug_info,
+			       sizeof(mlan_debug_info));
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+#endif /* PROC_DEBUG */
+
+#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 > MLAN_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) > MLAN_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 *custom_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;
+	custom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), flag);
+	if (!custom_ie) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (copy_from_user
+	    (custom_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 ((custom_ie->len == 0)||(custom_ie->len ==
+				    sizeof(custom_ie->ie_data_list[0].
+					   ie_index)))
+		ioctl_req->action = MLAN_ACT_GET;
+	else
+		ioctl_req->action = MLAN_ACT_SET;
+
+	memcpy(&misc->param.cust_ie, 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(custom_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;
+	memcpy(pcust_bcn_ie->ie_buffer, ie, ie_len);
+
+	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;
+
+	memcpy(&misc->param.tdls_config, tdls_data,
+	       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_IOCTL_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(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(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)
+#if defined(WIFI_DIRECT_SUPPORT)
+		    || (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
+#endif
+			) {
+			PRINTM(MWARN, "Invalid BSS role\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (bss_role == 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(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 */
+
+#if defined(SDIO_SUSPEND_RESUME)
+#endif
+
+/**
+ *  @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_IOCTL_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)
+		memcpy(&pmcfg->param.hs_cfg, hscfg, 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) {
+			memcpy(hscfg, &pmcfg->param.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);
+	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 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)
+{
+	moal_handle *handle = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_hs_cfg hscfg;
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	handle = priv->phandle;
+	/* 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 defined(SDIO_SUSPEND_RESUME)
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO_SUSPEND_RESUME)
+/**  @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
+
+	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 (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_IOCTL_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
+
+	/* 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_interruptible_timeout(handle->hs_activate_wait_q,
+						   handle->
+						   hs_activate_wait_q_woken,
+						   HS_ACTIVE_TIMEOUT);
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	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 {
+		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 */
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	if (hs_actived != MTRUE) {
+		handle->hs_skip_count++;
+#ifdef SDIO_SUSPEND_RESUME
+		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;
+}
+#endif
+
+#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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	union {
+		t_u32 l;
+		t_u8 c[4];
+	} ver;
+	char fw_ver[32];
+
+	ENTER();
+
+	ver.l = handle->fw_release_number;
+	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 drvdbg       Driver debug level
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_set_drvdbg(moal_private *priv, t_u32 drvdbg)
+{
+	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 = drvdbg;
+
+	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_IOCTL_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)
+		memcpy(&misc->param.mgmt_subtype_mask,
+		       pmgmt_subtype_mask,
+		       sizeof(misc->param.mgmt_subtype_mask));
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+
+	if (req->action == MLAN_ACT_GET)
+		memcpy(pmgmt_subtype_mask, &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;
+	memcpy(&bf_cfg->param.tx_bf, 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)
+		memcpy(tx_bf_cfg, &bf_cfg->param.tx_bf,
+		       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)
+{
+	ENTER();
+
+	if (priv == NULL) {
+		LEAVE();
+		return;
+	}
+	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) {
+			memcpy(pm_info, &pmcfg->param.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 && 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;
+	chan_band_info chan;
+	chan_band_info uapchan;
+	ENTER();
+
+	if (woal_is_any_interface_active(priv->phandle)) {
+		/* When any other interface is active
+		 * Get rid of CAC timer when drcs is disabled */
+		t_u16 enable = 0;
+		if (priv->phandle->card_info->drcs)
+			ret = woal_mc_policy_cfg(priv, &enable, wait_option,
+						 MLAN_ACT_GET);
+		if (!enable) {
+			LEAVE();
+			return ret;
+		} else {
+			woal_get_active_intf_channel(priv, &chan);
+			woal_set_get_ap_channel(priv, MLAN_ACT_GET,
+						MOAL_IOCTL_WAIT, &uapchan);
+			if (chan.channel != uapchan.channel) {
+				if (uapchan.is_dfs_chan) {
+					PRINTM(MERROR,
+					       "DFS channel is not allowed when another connection exists on different channel\n");
+					PRINTM(MERROR,
+					       "Another connection's channel=%d, dfs channel=%d\n",
+					       chan.channel, uapchan.channel);
+					return -EINVAL;
+				} else {
+					//check if we need move first uap0 from DFS channel to new non dfs channel
+					woal_check_mc_connection(priv,
+								 wait_option,
+								 uapchan.
+								 channel);
+				}
+			}
+		}
+	}
+
+	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 && 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();
+
+	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;
+	memcpy(&radio_cfg->param.remain_chan, pchan,
+	       sizeof(mlan_ds_remain_chan));
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		memcpy(pchan, &radio_cfg->param.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;
+}
+
+#if defined(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;
+	memcpy(&misc_cfg->param.p2p_config, p2p_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)
+			memcpy(p2p_config, &misc_cfg->param.p2p_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)
+{
+	int ret = 0;
+	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");
+		ret = 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)
+		memcpy(channel, &(bss->param.sta_channel), sizeof(*channel));
+
+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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+			memcpy(signal, &info->param.signal,
+			       sizeof(mlan_ds_get_signal));
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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;
+	memcpy((void *)&scan->param.scan_resp, (void *)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) {
+			memcpy(scan_resp, &scan->param.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;
+
+		memcpy(scan->param.scan_req.scan_ssid.ssid,
+		       req_ssid->ssid,
+		       MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len));
+		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));
+	memcpy(&bss->param.ssid_bssid.ssid, &bss_info.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;
+	t_u8 *mac = 0;
+
+	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;
+
+	memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		memcpy(ssid_bssid, &bss->param.ssid_bssid,
+		       sizeof(mlan_ssid_bssid));
+		mac = (t_u8 *)&ssid_bssid->bssid;
+		PRINTM(MINFO, "Find network: ssid=%s, " MACSTR ", idx=%d\n",
+		       ssid_bssid->ssid.ssid, MAC2STR(mac),
+		       (int)ssid_bssid->idx);
+	}
+
+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;
+	t_u8 *mac = 0;
+
+	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;
+
+	memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
+
+	mac = (t_u8 *)&ssid_bssid->bssid;
+	PRINTM(MINFO, "ssid=%s, " MACSTR ", idx=%d\n",
+	       ssid_bssid->ssid.ssid, MAC2STR(mac), (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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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;
+	memcpy(scan->param.user_scan.scan_cfg_buf, 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);
+
+	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)
+		memcpy(scan_cfg, &scan->param.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);
+	memcpy(&scan->param.scan_cfg, &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(cfg80211_wext) && handle->scan_request) {
+	    /** 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;
+	struct 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) {
+	/** skip check the scan age out */
+		ret = woal_find_best_network(priv, wait_option, ssid_bssid);
+		LEAVE();
+		return ret;
+	}
+#endif
+	do_gettimeofday(&t);
+/** scan result timeout value */
+#define SCAN_RESULT_AGEOUT      10
+	if (t.tv_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;
+	memcpy(scan->param.user_scan.scan_cfg_buf, scan_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;
+		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();
+	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;
+	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;
+		sprintf(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;
+}
+
+/**
+ *  @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)
+		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);
+	memcpy(&scan->param.scan_cfg, &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);
+	memcpy(&scan->param.scan_cfg, &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;
+
+	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 */
+
+/**
+ * @brief Set/Get configure multi-channel policy
+ *
+ * @param priv		A pointer to moal_private structure
+ * @param enable	A pointer to enable
+ * @param wait_option	wait_option of ioctl
+ * @param action	action of ioctl
+ *
+ * @return          MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_mc_policy_cfg(moal_private *priv, t_u16 *enable,
+		   t_u8 wait_option, t_u8 action)
+{
+	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) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_MULTI_CHAN_POLICY;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = action;
+	if (MLAN_ACT_SET == action)
+		cfg->param.multi_chan_policy = *enable;
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (MLAN_ACT_GET == action)
+		*enable = cfg->param.multi_chan_policy;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @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;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ * @brief               Set/Get network monitor configurations
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param wait_option  wait option
+ * @param enable	    Enable/Disable
+ * @param filter	    Filter flag - Management/Control/Data
+ * @param band_chan_cfg           Network monitor band channel config
+ *
+ * @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_net_monitor(moal_private *priv, t_u8 wait_option,
+		     t_u8 enable, t_u8 filter,
+		     netmon_band_chan_cfg * band_chan_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_net_monitor *net_mon = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	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;
+	net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
+	misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	net_mon->enable_net_mon = enable;
+	if (net_mon->enable_net_mon) {
+		net_mon->filter_flag = filter;
+		if (band_chan_cfg && band_chan_cfg->channel) {
+			/* fill TLV only if chan band is specified */
+			net_mon->band = band_chan_cfg->band;
+			net_mon->channel = band_chan_cfg->channel;
+			net_mon->chan_bandwidth = band_chan_cfg->chan_bandwidth;
+		}
+	}
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* update chan band values from response in band_chan_cfg */
+	if (net_mon->enable_net_mon) {
+		if (band_chan_cfg) {
+			band_chan_cfg->band = net_mon->band;
+			band_chan_cfg->channel = net_mon->channel;
+			band_chan_cfg->chan_bandwidth = net_mon->chan_bandwidth;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @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;
+	memcpy(del_ba->peer_mac_addr, zero_mac, ETH_ALEN);
+
+	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;
+	}
+}
+
+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");
diff --git a/wlan_sd8897/mlinux/moal_main.c b/wlan_sd8897/mlinux/moal_main.c
new file mode 100644
index 0000000..fd19a68
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_main.c
@@ -0,0 +1,10115 @@
+/** @file moal_main.c
+  *
+  * @brief This file contains the major functions in WLAN
+  * driver.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+#include    "moal_sdio.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include    "moal_cfg80211.h"
+#include    "moal_cfgvendor.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
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/** card info for sd877 */
+static struct _card_info card_info_sd8777 = {
+	.embedded_supp = 1,
+	.drcs = 0,
+	.go_noa = 0,
+	.v15_update = 0,
+	.v16_fw_api = 0,
+	.rx_rate_max = 76,
+};
+
+/** card info for sd8787 */
+static struct _card_info card_info_sd8787 = {
+	.embedded_supp = 1,
+	.drcs = 0,
+	.go_noa = 0,
+	.v15_update = 0,
+	.v16_fw_api = 0,
+	.rx_rate_max = 76,
+};
+
+/** card info for sd8797 */
+static struct _card_info card_info_sd8797 = {
+	.embedded_supp = 1,
+	.drcs = 0,
+	.go_noa = 0,
+	.v15_update = 0,
+	.v16_fw_api = 0,
+	.rx_rate_max = 76,
+};
+
+/** card info for sd887 */
+static struct _card_info card_info_sd8887 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v15_update = 1,
+	.v16_fw_api = 0,
+	.rx_rate_max = 196,
+};
+
+/** card info for sd8801 */
+static struct _card_info card_info_sd8801 = {
+	.embedded_supp = 0,
+	.drcs = 0,
+	.go_noa = 0,
+	.v15_update = 0,
+	.v16_fw_api = 0,
+	.rx_rate_max = 76,
+};
+
+/** card info for sd8897 */
+static struct _card_info card_info_sd8897 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v15_update = 1,
+	.v16_fw_api = 0,
+	.rx_rate_max = 196,
+};
+
+/** card info for sd8977 */
+static struct _card_info card_info_sd8977 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v15_update = 1,
+	.v16_fw_api = 1,
+	.rx_rate_max = 76,
+};
+
+static struct _card_info card_info_sd8997 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v15_update = 1,
+	.v16_fw_api = 1,
+	.rx_rate_max = 196,
+};
+
+static struct _card_info card_info_sd8987 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 0,
+	.v15_update = 1,
+	.v16_fw_api = 1,
+	.rx_rate_max = 196,
+};
+
+#define KERN_VERSION    "3X"
+
+/** Driver version */
+char driver_version[] =
+	"SD8XXX-%s-C" KERN_VERSION "15" MLAN_RELEASE_VERSION
+	"-GPL" "-(" "FP" FPNUM ")"
+#ifdef	DEBUG_LEVEL2
+	"-dbg"
+#endif
+	" ";
+
+/** SD8787 Card */
+#define CARD_SD8787     "SD8787"
+/** SD8777 Card */
+#define CARD_SD8777     "SD8777"
+/** SD8887 Card */
+#define CARD_SD8887     "SD8887"
+/** SD8801 Card */
+#define CARD_SD8801     "SD8801"
+/** SD8897 Card */
+#define CARD_SD8897     "SD8897"
+/** SD8797 Card */
+#define CARD_SD8797     "SD8797"
+/** SD8977 Card */
+#define CARD_SD8977     "SD8977"
+/** SD8997 Card */
+#define CARD_SD8997     "SD8997"
+/** SD8987 Card */
+#define CARD_SD8987     "SD8987"
+
+/** Firmware name */
+char *fw_name;
+int req_fw_nowait;
+int fw_reload;
+
+/** MAC address */
+char *mac_addr;
+
+#ifdef MFG_CMD_SUPPORT
+/** Mfg mode */
+int mfg_mode;
+#endif
+
+/** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+int intmode = INT_MODE_SDIO;
+/** GPIO interrupt pin number */
+int gpiopin;
+
+#ifdef CONFIG_OF
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+/** Region alpha2 string */
+extern char *reg_alpha2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int country_ie_ignore;
+extern int beacon_hints;
+#endif
+#endif
+extern int cfg80211_drcs;
+#endif
+
+int drcs_chantime_mode = 0;
+
+/** Auto deep sleep */
+int auto_ds;
+
+/** IEEE PS mode */
+int ps_mode;
+
+/** Max Tx buffer size */
+int max_tx_buf;
+
+#ifdef STA_SUPPORT
+/** Max STA interfaces */
+int max_sta_bss = DEF_STA_BSS;
+/** STA interface name */
+char *sta_name;
+#endif
+
+#ifdef UAP_SUPPORT
+/** Max uAP interfaces */
+int max_uap_bss = DEF_UAP_BSS;
+/** uAP interface name */
+char *uap_name;
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+/** Max WIFIDIRECT interfaces */
+int max_wfd_bss = DEF_WIFIDIRECT_BSS;
+/** WIFIDIRECT interface name */
+char *wfd_name;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+/** max VIRTUAL bss */
+int max_vir_bss = DEF_VIRTUAL_BSS;
+#endif
+#endif
+
+/** Max NAN interfaces */
+int max_nan_bss = DEF_NAN_BSS;
+/** NAN interface name */
+char *nan_name;
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+int pm_keep_power = 1;
+/** HS when shutdown */
+int shutdown_hs;
+#endif
+
+/** SDIO slew rate */
+int slew_rate = 3;
+
+#if defined(STA_SUPPORT)
+/** 802.11d configuration */
+int cfg_11d;
+#endif
+
+/** FW download CRC check */
+int fw_crc_check = 1;
+
+/** fw serial download check */
+int fw_serial = 1;
+
+/** napi support*/
+int napi;
+
+/** DPD data config file */
+char *dpd_data_cfg;
+
+/** CAL data config file */
+char *cal_data_cfg;
+/** Init config file (MAC address, register etc.) */
+char *init_cfg;
+
+/** Set configuration data of Tx power limitation */
+char *txpwrlimit_cfg;
+/** Set configuration data of Tx power limitatio */
+char *country_txpwrlimit;
+/** Allow setting tx power table of country */
+int cntry_txpwr = 0;
+
+/** Init hostcmd file */
+char *init_hostcmd_cfg;
+
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+/** CFG80211 and WEXT mode */
+int cfg80211_wext = STA_WEXT_MASK | UAP_WEXT_MASK;
+#else
+/** CFG80211 mode */
+int cfg80211_wext = STA_CFG80211_MASK | UAP_CFG80211_MASK;
+#endif
+
+/** Work queue priority */
+int wq_sched_prio;
+/** Work queue scheduling policy */
+int wq_sched_policy = SCHED_NORMAL;
+/** rx_work flag */
+int rx_work;
+
+int low_power_mode_enable;
+
+int hw_test;
+
+#ifdef CONFIG_OF
+int dts_enable = 1;
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+int p2p_enh;
+#endif
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+int dfs_offload = 0;
+#endif
+
+#ifdef ANDROID_KERNEL
+int wakelock_timeout = WAKE_LOCK_TIMEOUT;
+#endif
+
+/** woal_callbacks */
+static mlan_callbacks woal_callbacks = {
+	.moal_get_fw_data = moal_get_fw_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_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,
+
+	.moal_write_reg = moal_write_reg,
+	.moal_read_reg = moal_read_reg,
+	.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,
+	.moal_memset = moal_memset,
+	.moal_memcpy = moal_memcpy,
+	.moal_memmove = moal_memmove,
+	.moal_memcmp = moal_memcmp,
+	.moal_udelay = moal_udelay,
+	.moal_get_system_time = moal_get_system_time,
+	.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,
+};
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#if defined(WIFI_DIRECT_SUPPORT)
+int drv_mode = (DRV_MODE_STA | DRV_MODE_UAP | DRV_MODE_WIFIDIRECT);
+#else
+int drv_mode = (DRV_MODE_STA | DRV_MODE_UAP);
+#endif
+#else
+#ifdef STA_SUPPORT
+int drv_mode = DRV_MODE_STA;
+#else
+int drv_mode = DRV_MODE_UAP;
+#endif /* STA_SUPPORT */
+#endif /* STA_SUPPORT & UAP_SUPPORT */
+
+int pmic = 0;
+
+int antcfg = 0;
+
+t_u32 uap_oper_ctrl = 0;
+
+int hs_wake_interval = 400;
+int indication_gpio = 0xff;
+
+int indrstcfg = 0xffffffff;
+
+/** all the feature are enabled */
+#define DEFAULT_DEV_CAP_MASK 0xffffffff
+t_u32 dev_cap_mask = DEFAULT_DEV_CAP_MASK;
+/********************************************************
+		Global Variables
+********************************************************/
+
+/** 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];
+
+/** The global variable of scan beacon buffer **/
+int fixed_beacon_buffer = 0;
+/** the pointer of new fwdump fname for each dump**/
+char *fwdump_fname = NULL;
+
+#ifdef WIFI_DIRECT_SUPPORT
+int GoAgeoutTime = 0;
+#endif
+
+t_u16 multi_dtim = 0;
+
+t_u16 inact_tmo = 0;
+
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define	DEFAULT_DEBUG_MASK	(0xffffffff)
+#else
+#define DEFAULT_DEBUG_MASK	(MMSG | MFATAL | MERROR)
+#endif /* DEBUG_LEVEL2 */
+t_u32 drvdbg = DEFAULT_DEBUG_MASK;
+
+#endif /* DEBUG_LEVEL1 */
+
+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);
+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)
+u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb,
+		      void *accel_priv, select_queue_fallback_t fallback);
+#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
+
+void woal_sdio_reg_dbg(moal_handle *phandle);
+
+mlan_debug_info info;
+
+static moal_handle *reset_handle;
+/** Hang workqueue */
+static struct workqueue_struct *hang_workqueue;
+/** Hang work */
+static struct work_struct hang_work;
+
+/**
+ *  @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;
+	ENTER();
+	if (!reset_handle) {
+		LEAVE();
+		return;
+	}
+	for (i = 0; i < reset_handle->priv_num; i++) {
+		if (reset_handle->priv[i] && reset_handle->priv[i]->netdev) {
+			PRINTM(MMSG, "Close netdev %s\n",
+			       reset_handle->priv[i]->netdev->name);
+			rtnl_lock();
+			dev_close(reset_handle->priv[i]->netdev);
+			rtnl_unlock();
+			break;
+		}
+	}
+	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;
+		mlan_ioctl(handle->pmlan_adapter, NULL);
+		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, 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++) {
+#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 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
+
+#if defined(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)) {
+					memcpy(&ssid_bssid->ssid,
+					       &bss_info.ssid,
+					       sizeof(bss_info.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)) {
+				memcpy(&ssid_bssid->bssid, &bss_info.bssid,
+				       MLAN_MAC_ADDR_LENGTH);
+				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 Get mode
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option   Wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
+ *
+ *  @return              Wireless mode
+ */
+t_u32
+woal_get_mode(moal_private *priv, t_u8 wait_option)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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
+ */
+static void
+woal_update_firmware_name(moal_handle *handle)
+{
+	if (fw_name) {
+		handle->drv_mode.fw_name = fw_name;
+	} else {
+#if defined(UAP_SUPPORT) && defined(STA_SUPPORT)
+		if (handle->card_type == CARD_TYPE_SD8777)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8777;
+		else if (handle->card_type == CARD_TYPE_SD8787)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8787;
+		else if (handle->card_type == CARD_TYPE_SD8887)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8887;
+		else if (handle->card_type == CARD_TYPE_SD8801)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8801;
+		else if (handle->card_type == CARD_TYPE_SD8897)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8897;
+		else if (handle->card_type == CARD_TYPE_SD8797)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8797;
+		else if (handle->card_type == CARD_TYPE_SD8977)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8977;
+		else if (handle->card_type == CARD_TYPE_SD8997)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8997;
+		else if (handle->card_type == CARD_TYPE_SD8987)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8987;
+		else
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME;
+#else
+#ifdef UAP_SUPPORT
+		if (handle->card_type == CARD_TYPE_SD8777)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8777;
+		else if (handle->card_type == CARD_TYPE_SD8787)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8787;
+		else if (handle->card_type == CARD_TYPE_SD8887)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8887;
+		else if (handle->card_type == CARD_TYPE_SD8801)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8801;
+		else if (handle->card_type == CARD_TYPE_SD8897)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8897;
+		else if (handle->card_type == CARD_TYPE_SD8797)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8797;
+		else if (handle->card_type == CARD_TYPE_SD8977)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8977;
+		else if (handle->card_type == CARD_TYPE_SD8997)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8997;
+		else if (handle->card_type == CARD_TYPE_SD8987)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8987;
+		else
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME;
+#else
+		if (handle->card_type == CARD_TYPE_SD8777)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8777;
+		else if (handle->card_type == CARD_TYPE_SD8787)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8787;
+		else if (handle->card_type == CARD_TYPE_SD8887)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8887;
+		else if (handle->card_type == CARD_TYPE_SD8801)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8801;
+		else if (handle->card_type == CARD_TYPE_SD8897)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8897;
+		else if (handle->card_type == CARD_TYPE_SD8797)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8797;
+		else if (handle->card_type == CARD_TYPE_SD8977)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8977;
+		else if (handle->card_type == CARD_TYPE_SD8997)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8997;
+		else if (handle->card_type == CARD_TYPE_SD8987)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8987;
+		else
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME;
+#endif /* UAP_SUPPORT */
+#endif /* UAP_SUPPORT && STA_SUPPORT */
+	}
+}
+
+/**
+ *  @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;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	int last_wfd_index = 0;
+#endif
+#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;
+	}
+#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;
+	}
+#endif /* UAP_SUPPORT */
+
+#if defined(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;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+		intf_num += max_vir_bss;
+#endif
+	}
+#endif /* WIFI_DIRECT_SUPPORT  && V14_FEATURE */
+
+	if (drv_mode_local & DRV_MODE_NAN) {
+		if ((max_nan_bss < 1) || (max_nan_bss > MAX_NAN_BSS)) {
+			PRINTM(MWARN,
+			       "Unsupported max_nan_bss (%d), setting to default\n",
+			       max_nan_bss);
+			max_nan_bss = DEF_NAN_BSS;
+		}
+		intf_num += max_nan_bss;
+	}
+
+	/* 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 >= 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 >= 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 */
+
+#if defined(WIFI_DIRECT_SUPPORT)
+	if (drv_mode_local & DRV_MODE_WIFIDIRECT) {
+		for (j = 0; j < max_wfd_bss; j++) {
+			if (i >= 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 && V14_FEATURE */
+
+	if (drv_mode_local & DRV_MODE_NAN) {
+		for (j = 0; j < max_nan_bss; j++) {
+			if (i >= intf_num)
+				break;
+			bss_tbl[i].bss_type = MLAN_BSS_TYPE_NAN;
+			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(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 >= 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 = 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;
+}
+
+#ifdef CONFIG_OF
+/**
+ *  @brief This function read the initial parameter from device tress
+ *
+ *  @return         N/A
+ */
+static 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, "sd8xxx-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;
+			}
+		}
+#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);
+			}
+		}
+#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
+#if defined(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, "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
+#if defined(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;
+			}
+		} else if (!strncmp(prop->name, "p2p_enh", strlen("p2p_enh"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "p2p_enh=0x%x\n", data);
+				p2p_enh = data;
+			}
+		} else if (!strncmp
+			   (prop->name, "cfg80211_drcs",
+			    strlen("cfg80211_drcs"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "cfg80211_drcs=0x%x\n", data);
+				cfg80211_drcs = 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, "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);
+			}
+		}
+#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, "drcs_chantime_mode",
+			    strlen("drcs_chantime_mode"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				drcs_chantime_mode = data;
+				PRINTM(MIOCTL, "drcs_chantime_mode=%d\n",
+				       drcs_chantime_mode);
+			}
+		} 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
+	}
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function initializes software
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_init_sw(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	unsigned int i;
+	mlan_device device;
+	t_void *pmlan;
+
+	ENTER();
+
+	/* Initialize moal_handle structure */
+	handle->hardware_status = HardwareStatusInitializing;
+	handle->main_state = MOAL_STATE_IDLE;
+
+#ifdef STA_SUPPORT
+	if ((drv_mode & DRV_MODE_STA)
+#ifdef STA_WEXT
+	    && !IS_STA_WEXT(cfg80211_wext)
+#endif
+#ifdef STA_CFG80211
+	    && !IS_STA_CFG80211(cfg80211_wext)
+#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
+
+	/* Update driver version */
+	if (handle->card_type == CARD_TYPE_SD8787)
+		memcpy(driver_version, CARD_SD8787, strlen(CARD_SD8787));
+	else if (handle->card_type == CARD_TYPE_SD8777)
+		memcpy(driver_version, CARD_SD8777, strlen(CARD_SD8777));
+	else if (handle->card_type == CARD_TYPE_SD8887)
+		memcpy(driver_version, CARD_SD8887, strlen(CARD_SD8887));
+	else if (handle->card_type == CARD_TYPE_SD8801)
+		memcpy(driver_version, CARD_SD8801, strlen(CARD_SD8801));
+	else if (handle->card_type == CARD_TYPE_SD8897)
+		memcpy(driver_version, CARD_SD8897, strlen(CARD_SD8897));
+	else if (handle->card_type == CARD_TYPE_SD8797)
+		memcpy(driver_version, CARD_SD8797, strlen(CARD_SD8797));
+	else if (handle->card_type == CARD_TYPE_SD8977)
+		memcpy(driver_version, CARD_SD8977, strlen(CARD_SD8977));
+	else if (handle->card_type == CARD_TYPE_SD8997)
+		memcpy(driver_version, CARD_SD8997, strlen(CARD_SD8997));
+	else if (handle->card_type == CARD_TYPE_SD8987)
+		memcpy(driver_version, CARD_SD8987, strlen(CARD_SD8987));
+	memcpy(handle->driver_version, driver_version, strlen(driver_version));
+
+	if (woal_update_drv_tbl(handle, 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);
+
+#if defined(SDIO_SUSPEND_RESUME)
+	handle->is_suspended = MFALSE;
+	handle->hs_activated = MFALSE;
+	handle->hs_auto_arp = MTRUE;
+	handle->suspend_fail = MFALSE;
+#ifdef SDIO_SUSPEND_RESUME
+	handle->suspend_notify_req = MFALSE;
+#endif
+	handle->hs_skip_count = 0;
+	handle->hs_force_count = 0;
+	handle->cmd52_func = 0;
+	handle->cmd52_reg = 0;
+	handle->cmd52_val = 0;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	handle->scan_chan_gap = DEF_SCAN_CHAN_GAP;
+#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
+	init_waitqueue_head(&handle->hs_activate_wait_q);
+#endif
+
+	/* 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
+
+#ifdef DFS_TESTING_SUPPORT
+	handle->cac_period_jiffies = 0;
+#endif
+#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
+	handle->mon_if = NULL;
+
+#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 */
+
+#if defined(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;
+
+#ifdef MFG_CMD_SUPPORT
+	device.mfg_mode = (t_u32)mfg_mode;
+#endif
+	device.int_mode = (t_u32)intmode;
+	device.gpio_pin = (t_u32)gpiopin;
+#ifdef DEBUG_LEVEL1
+	device.drvdbg = drvdbg;
+#endif
+	device.fixed_beacon_buffer = (t_u32)fixed_beacon_buffer;
+	device.auto_ds = (t_u32)auto_ds;
+	device.ps_mode = (t_u32)ps_mode;
+	device.max_tx_buf = (t_u32)max_tx_buf;
+#if defined(STA_SUPPORT)
+	device.cfg_11d = (t_u32)cfg_11d;
+#endif
+	if (handle->card_type == CARD_TYPE_SD8787 ||
+	    handle->card_type == CARD_TYPE_SD8777)
+		device.fw_crc_check = (t_u32)fw_crc_check;
+	device.indrstcfg = (t_u32)indrstcfg;
+	device.drcs_chantime_mode = (t_u32)drcs_chantime_mode;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+#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);
+#endif
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+#ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
+	device.mpa_tx_cfg = MLAN_INIT_PARA_ENABLED;
+#else
+	device.mpa_tx_cfg = MLAN_INIT_PARA_DISABLED;
+#endif
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+#ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
+	device.mpa_rx_cfg = MLAN_INIT_PARA_ENABLED;
+#else
+	device.mpa_rx_cfg = MLAN_INIT_PARA_DISABLED;
+#endif
+#endif
+	device.feature_control = FEATURE_CTRL_DEFAULT;
+	if (handle->card_type == CARD_TYPE_SD8777 ||
+	    handle->card_type == CARD_TYPE_SD8787 ||
+	    handle->card_type == CARD_TYPE_SD8801 ||
+	    handle->card_type == CARD_TYPE_SD8887 ||
+	    handle->card_type == CARD_TYPE_SD8977 ||
+	    handle->card_type == CARD_TYPE_SD8987)
+		device.feature_control &= ~FEATURE_CTRL_STREAM_2X2;
+	handle->feature_control = device.feature_control;
+
+	if (rx_work == MLAN_INIT_PARA_ENABLED)
+		device.rx_work = MTRUE;
+	else if (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 (napi)
+		device.rx_work = MTRUE;
+
+	device.dev_cap_mask = dev_cap_mask;
+
+	device.multi_dtim = multi_dtim;
+
+	device.inact_tmo = inact_tmo;
+	device.hs_wake_interval = hs_wake_interval;
+	device.indication_gpio = indication_gpio;
+
+	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;
+	}
+	memcpy(&device.callbacks, &woal_callbacks, sizeof(mlan_callbacks));
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	if (MLAN_STATUS_SUCCESS == mlan_register(&device, &pmlan))
+		handle->pmlan_adapter = pmlan;
+	else
+		ret = MLAN_STATUS_FAILURE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees the structure of moal_handle
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         N/A
+ */
+static void
+woal_free_moal_handle(moal_handle *handle)
+{
+	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);
+		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);
+
+	/* 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));
+	}
+	/* Free allocated memory for fwdump filename */
+	kfree(handle->fwdump_fname);
+	if (fwdump_fname) {
+		kfree(fwdump_fname);
+		fwdump_fname = 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 >= 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 < 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;
+}
+
+/**
+ * @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 (slew_rate > 3 || slew_rate < 0)
+		return MLAN_STATUS_FAILURE;
+	ret = woal_getset_regrdwr(priv, MLAN_ACT_GET, MLAN_REG_MAC, 0x8000231C,
+				  &value);
+	if (ret < 0) {
+		PRINTM(MERROR, "woal_getset_regrdwr get REG_MAC failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	new_value = value & ~0xC000;
+	new_value |= (t_u32)slew_rate << 14;
+	/* Set 0x8000231C[15:14] = 0-3 */
+	if (value != new_value) {
+		PRINTM(MMSG, "Set REG 0x8000231C: 0x%x slew_rate=%d\n",
+		       new_value, slew_rate);
+		ret = woal_getset_regrdwr(priv, MLAN_ACT_SET, MLAN_REG_MAC,
+					  0x8000231C, &new_value);
+		if (ret < 0) {
+			PRINTM(MERROR,
+			       "woal_getset_regrdwr get REG_MAC failed\n");
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+done:
+	return ret;
+}
+
+#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;
+
+	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;
+	}
+
+	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 ((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);
+#if defined(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])) {
+							PRINTM(MERROR,
+							       "Set MAC address failed\n");
+							goto done;
+						}
+						memcpy(handle->priv[i]->netdev->
+						       dev_addr,
+						       handle->priv[i]->
+						       current_addr, 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 */
+			strncpy(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)));
+			memcpy(buf + strlen(CMD_STR), &cmd_len, sizeof(t_u32));
+
+			/* 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
+
+/**
+ * @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_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
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+woal_set_user_init_data(moal_handle *handle, int type, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 *cfg_data = NULL;
+	t_size len;
+
+	ENTER();
+
+	if (type == INIT_CFG_DATA) {
+		if (req_fw_nowait) {
+#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
+				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 (req_fw_nowait) {
+#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
+				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 {
+			int status =
+				request_firmware(&handle->user_data,
+						 country_txpwrlimit,
+						 handle->hotplug_device);
+			/* File does not exist, skip download */
+			if (status == -ENOENT) {
+				PRINTM(MIOCTL,
+				       "Country power table file does not exist\n");
+				LEAVE();
+				return MLAN_STATUS_SUCCESS;
+			} else if (status) {
+				PRINTM(MERROR,
+				       "country txpwrlimit config file request_firmware() failed\n");
+				goto done;
+			}
+		}
+	} else if (type == INIT_HOSTCMD_CFG_DATA) {
+		if (req_fw_nowait) {
+#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
+				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 (handle->user_data) {
+		cfg_data = (t_u8 *)(handle->user_data)->data;
+		len = (handle->user_data)->size;
+		if (type == INIT_HOSTCMD_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;
+}
+
+/**
+ * @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();
+
+#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);
+
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode == MLAN_INIT_PARA_ENABLED)
+		goto done;
+#endif
+
+	if (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;
+		}
+	}
+
+	/* Add low power mode check */
+	if ((handle->card_type == CARD_TYPE_SD8801 ||
+	     handle->card_type == CARD_TYPE_SD8887) && low_power_mode_enable &&
+	    woal_set_low_pwr_mode(handle, MOAL_IOCTL_WAIT)) {
+		/* Proceed with Warning */
+		PRINTM(MERROR, "Unable to set Low Power Mode\n");
+	}
+
+	if (handle->card_type == CARD_TYPE_SD8801)
+		woal_set_sdio_slew_rate(handle);
+
+	if (pmic
+	    && ((handle->card_type == CARD_TYPE_SD8997) ||
+		(handle->card_type == CARD_TYPE_SD8987) ||
+		(handle->card_type == CARD_TYPE_SD8977))
+		) {
+		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 (antcfg
+	    && ((handle->card_type == CARD_TYPE_SD8887) ||
+		(handle->card_type == CARD_TYPE_SD8897) ||
+		(handle->card_type == CARD_TYPE_SD8987) ||
+		(handle->card_type == CARD_TYPE_SD8997))
+		) {
+		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 (uap_oper_ctrl)
+		woal_set_uap_operation_ctrl(handle);
+#endif
+
+#ifdef MFG_CMD_SUPPORT
+done:
+#endif
+err:
+	if (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");
+
+		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 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;
+	t_u8 retry = 0;
+
+	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 (fw_reload == FW_RELOAD_SDIO_INBAND_RESET)
+			fw.fw_reload = fw_reload;
+		else
+			fw.fw_reload = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+		ret = mlan_dnld_fw(handle->pmlan_adapter, &fw);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+		if (ret == MLAN_STATUS_FAILURE) {
+			PRINTM(MERROR,
+			       "WLAN: Fail download FW with nowwait: %d\n",
+			       req_fw_nowait);
+			woal_sdio_reg_dbg(handle);
+			goto done;
+		}
+		PRINTM(MMSG, "WLAN FW is active\n");
+	}
+
+    /** data request */
+	memset(&param, 0, sizeof(mlan_init_param));
+
+	if (dpd_data_cfg && strncmp(dpd_data_cfg, "none", strlen("none"))) {
+		if (req_fw_nowait) {
+#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
+				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 {
+			if ((request_firmware
+			     (&handle->dpd_data, dpd_data_cfg,
+			      handle->hotplug_device)) < 0) {
+				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;
+		}
+	}
+	if (txpwrlimit_cfg && strncmp(txpwrlimit_cfg, "none", strlen("none"))) {
+		if (req_fw_nowait) {
+#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
+				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;
+		}
+	}
+
+	if (cal_data_cfg && strncmp(cal_data_cfg, "none", strlen("none"))) {
+		if (req_fw_nowait) {
+#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
+				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) {
+		if (handle->card_type == CARD_TYPE_SD8887 ||
+		    handle->card_type == CARD_TYPE_SD8977 ||
+		    handle->card_type == CARD_TYPE_SD8997 ||
+		    handle->card_type == CARD_TYPE_SD8987) {
+			PRINTM(MERROR,
+			       "Please add cal_data_cfg for 8887/8977/8997/8987/9098\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;
+	}
+
+	handle->hardware_status = HardwareStatusFwReady;
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (handle->fw_reload)
+		goto done;
+	handle->init_wait_q_woken = MFALSE;
+
+	ret = mlan_set_init_param(handle->pmlan_adapter, &param);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	ret = mlan_init_fw(handle->pmlan_adapter);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	if (ret == MLAN_STATUS_FAILURE)
+		goto done;
+	else if (ret == MLAN_STATUS_SUCCESS) {
+		handle->hardware_status = HardwareStatusReady;
+		goto done;
+	}
+	/* Wait for mlan_init to complete */
+	while (wait_event_interruptible(handle->init_wait_q,
+					handle->init_wait_q_woken) ==
+	       -ERESTARTSYS && retry < MAX_RETRY_CNT) {
+		retry++;
+	}
+	if (handle->hardware_status != HardwareStatusReady) {
+		woal_moal_debug_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
+				     handle, MTRUE);
+#if defined(DEBUG_LEVEL1)
+		if (drvdbg & MFW_D) {
+			drvdbg &= ~MFW_D;
+			woal_dump_firmware_info(handle);
+		}
+#endif
+		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;
+	struct timeval tstamp;
+
+	ENTER();
+
+	if (!firmware) {
+		do_gettimeofday(&tstamp);
+		if (tstamp.tv_sec >
+		    (handle->req_fw_time.tv_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)
+{
+	ENTER();
+	woal_request_fw_dpc((moal_handle *)context, firmware);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+	if (firmware)
+		release_firmware(firmware);
+#endif
+	LEAVE();
+	return;
+}
+
+#define SD8887_REV_REG  0xc8
+#define SD8887_A0       0x0
+#define SD8887_A2       0x2
+#define SD8977_V0       0x0
+#define SD8977_V1       0x8
+#define SD8977_V2       0x9
+#define SD8997_Z       0x02
+#define SD8997_V2       0x10
+#define MAGIC_REG		0xf0
+#define MAGIC_VAL		0x24
+/**
+ * @brief   Get FW name for differnt chip revision
+ *
+ * @param handle  A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+void
+woal_check_fw_name(moal_handle *handle)
+{
+	t_u32 rev_id_reg = 0;
+	t_u32 revision_id = 0;
+	t_u32 magic_val = 0;
+
+	if (handle->card_type == CARD_TYPE_SD8887 ||
+	    handle->card_type == CARD_TYPE_SD8977 ||
+	    handle->card_type == CARD_TYPE_SD8987 ||
+	    handle->card_type == CARD_TYPE_SD8997)
+		rev_id_reg = SD8887_REV_REG;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	woal_read_reg(handle, rev_id_reg, &revision_id);
+	woal_read_reg(handle, MAGIC_REG, &magic_val);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	/* Check revision ID */
+	if (handle->card_type == CARD_TYPE_SD8887) {
+		switch (revision_id) {
+		case SD8887_A0:
+			if (fw_serial)
+				handle->drv_mode.fw_name = SD8887_A0_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8887_WLAN_A0_FW_NAME;
+			break;
+		case SD8887_A2:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8887_A2_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8887_WLAN_A2_FW_NAME;
+			break;
+		default:
+			break;
+		}
+	} else if (handle->card_type == CARD_TYPE_SD8977) {
+		switch (revision_id) {
+		case SD8977_V0:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8977_V0_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8977_WLAN_V0_FW_NAME;
+			break;
+		case SD8977_V1:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8977_V1_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8977_WLAN_V1_FW_NAME;
+			break;
+		case SD8977_V2:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8977_V2_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8977_WLAN_V2_FW_NAME;
+			break;
+		default:
+			break;
+		}
+	} else if (handle->card_type == CARD_TYPE_SD8997) {
+		switch (revision_id) {
+		case SD8997_Z:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8997_Z_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8997_WLAN_Z_FW_NAME;
+			break;
+		case SD8997_V2:
+			if (fw_serial && !handle->fw_reload && !fw_reload) {
+				if ((magic_val & 0xff) == MAGIC_VAL)
+					handle->drv_mode.fw_name =
+						SD8997_V3_FW_NAME;
+				else
+					handle->drv_mode.fw_name =
+						SD8997_V2_FW_NAME;
+			} else {
+				if ((magic_val & 0xff) == MAGIC_VAL)
+					handle->drv_mode.fw_name =
+						SD8997_WLAN_V3_FW_NAME;
+				else
+					handle->drv_mode.fw_name =
+						SD8997_WLAN_V2_FW_NAME;
+			}
+			break;
+		default:
+			break;
+		}
+	} else if (handle->card_type == CARD_TYPE_SD8987) {
+		if (fw_serial && !handle->fw_reload && !fw_reload)
+			handle->drv_mode.fw_name = SD8987_FW_NAME;
+		else
+			handle->drv_mode.fw_name = SD8987_WLAN_FW_NAME;
+	}
+	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)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err;
+
+	ENTER();
+
+	if (!fw_name &&
+	    (handle->card_type == CARD_TYPE_SD8887 ||
+	     handle->card_type == CARD_TYPE_SD8977 ||
+	     handle->card_type == CARD_TYPE_SD8987 ||
+	     handle->card_type == CARD_TYPE_SD8997))
+		woal_check_fw_name(handle);
+	PRINTM(MMSG, "Request firmware: %s\n", handle->drv_mode.fw_name);
+	if (req_fw_nowait) {
+#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
+		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);
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes firmware
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_init_fw(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	do_gettimeofday(&handle->req_fw_time);
+
+	ret = woal_request_fw(handle);
+	if (ret < 0) {
+		PRINTM(MFATAL, "woal_request_fw failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+done:
+	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
+ */
+static void
+woal_fill_mlan_buffer(moal_private *priv,
+		      mlan_buffer *pmbuf, struct sk_buff *skb)
+{
+	struct timeval tstamp;
+	struct ethhdr *eth;
+	t_u8 tid;
+	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;
+			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.
+	 */
+	do_gettimeofday(&tstamp);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+	skb->tstamp = timeval_to_ktime(tstamp);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+	skb_set_timestamp(skb, &tstamp);
+#else
+	memcpy(&skb->stamp, &tstamp, sizeof(skb->stamp));
+#endif
+
+	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 = 0;
+	pmbuf->in_ts_sec = (t_u32)tstamp.tv_sec;
+	pmbuf->in_ts_usec = (t_u32)tstamp.tv_usec;
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief This function opens the network device for monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_mon_open(struct net_device *ndev)
+{
+	ENTER();
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief This function closes the network device for monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_mon_close(struct net_device *ndev)
+{
+	ENTER();
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief This function sets the MAC address to firmware for monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ * @param addr            MAC address to set
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_mon_set_mac_address(struct net_device *ndev, void *addr)
+{
+	ENTER();
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief This function sets multicast address to firmware for monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+void
+woal_mon_set_multicast_list(struct net_device *ndev)
+{
+	ENTER();
+	LEAVE();
+}
+
+/**
+ * @brief This function handles packet transmission for monitor interface
+ *
+ * @param skb             A pointer to sk_buff structure
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	int len_rthdr;
+	int qos_len = 0;
+	int dot11_hdr_len = 24;
+	int snap_len = 6;
+	unsigned char *pdata;
+	unsigned short fc;
+	unsigned char src_mac_addr[6];
+	unsigned char dst_mac_addr[6];
+	struct ieee80211_hdr *dot11_hdr;
+	struct ieee80211_radiotap_header *prthdr =
+		(struct ieee80211_radiotap_header *)skb->data;
+	monitor_iface *mon_if = netdev_priv(ndev);
+
+	ENTER();
+
+	if (mon_if == NULL || mon_if->base_ndev == NULL) {
+		goto fail;
+	}
+
+	/* check for not even having the fixed radiotap header part */
+	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) {
+		PRINTM(MERROR, "Invalid radiotap hdr length,"
+		       "skb->len: %d\n", skb->len);
+		goto fail;	/* too short to be possibly valid */
+	}
+
+	/* is it a header version we can trust to find length from? */
+	if (unlikely(prthdr->it_version))
+		goto fail;	/* only version 0 is supported */
+
+	/* then there must be a radiotap header with a length we can use */
+	len_rthdr = ieee80211_get_radiotap_len(skb->data);
+
+	/* does the skb contain enough to deliver on the alleged length? */
+	if (unlikely(skb->len < len_rthdr)) {
+		PRINTM(MERROR, "Invalid data length,"
+		       "skb->len: %d\n", skb->len);
+		goto fail;	/* skb too short for claimed rt header extent */
+	}
+
+	/* Skip the ratiotap header */
+	skb_pull(skb, len_rthdr);
+
+	dot11_hdr = (struct ieee80211_hdr *)skb->data;
+	fc = le16_to_cpu(dot11_hdr->frame_control);
+	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
+		/* Check if this ia a Wireless Distribution System (WDS) frame
+		 * which has 4 MAC addresses
+		 */
+		if (dot11_hdr->frame_control & 0x0080)
+			qos_len = 2;
+		if ((dot11_hdr->frame_control & 0x0300) == 0x0300)
+			dot11_hdr_len += 6;
+
+		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
+		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
+
+		/* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for
+		 * for two MAC addresses
+		 */
+		skb_pull(skb,
+			 dot11_hdr_len + qos_len + snap_len -
+			 sizeof(src_mac_addr) * 2);
+		pdata = (unsigned char *)skb->data;
+		memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));
+		memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr,
+		       sizeof(src_mac_addr));
+
+		LEAVE();
+		return woal_hard_start_xmit(skb, mon_if->base_ndev);
+	}
+
+fail:
+	dev_kfree_skb(skb);
+	LEAVE();
+	return NETDEV_TX_OK;
+}
+
+/**
+ *  @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_mon_get_stats(struct net_device *dev)
+{
+	monitor_iface *mon_if = (monitor_iface *)netdev_priv(dev);
+	return &mon_if->stats;
+}
+
+static const struct net_device_ops woal_cfg80211_mon_if_ops = {
+	.ndo_open = woal_mon_open,
+	.ndo_start_xmit = woal_mon_hard_start_xmit,
+	.ndo_stop = woal_mon_close,
+	.ndo_get_stats = woal_mon_get_stats,
+	.ndo_set_mac_address = woal_mon_set_mac_address,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	.ndo_set_rx_mode = woal_mon_set_multicast_list,
+#else
+	.ndo_set_multicast_list = woal_mon_set_multicast_list,
+#endif
+};
+
+/**
+ * @brief This function setup monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ * @param addr            MAC address to set
+ *
+ * @return                0 -- success, otherwise fail
+ */
+
+void
+woal_mon_if_setup(struct net_device *dev)
+{
+	ENTER();
+	ether_setup(dev);
+	dev->netdev_ops = &woal_cfg80211_mon_if_ops;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 9)
+	dev->needs_free_netdev = true;
+#else
+	dev->destructor = free_netdev;
+#endif
+	LEAVE();
+}
+
+/**
+ * @brief Request the driver to add a monitor interface
+ *
+ * @param priv             A pointer to moal_private
+ * @param name              Virtual interface name
+ * @param name_assign_type  Interface name assignment type
+ *
+ * @return                  A pointer to monitor_iface
+ */
+monitor_iface *
+woal_prepare_mon_if(moal_private *priv,
+		    const char *name, unsigned char name_assign_type)
+{
+	int ret = 0;
+	struct net_device *ndev = NULL;
+	monitor_iface *mon_if = NULL;
+
+	ENTER();
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	ndev = alloc_netdev_mq(sizeof(*mon_if), name, name_assign_type,
+			       woal_mon_if_setup, 1);
+#else
+	ndev = alloc_netdev_mq(sizeof(*mon_if), name, NET_NAME_UNKNOWN,
+			       woal_mon_if_setup, 1);
+#endif
+#else
+	ndev = alloc_netdev_mq(sizeof(*mon_if), name, woal_mon_if_setup, 1);
+#endif
+#else
+	ndev = alloc_netdev_mq(sizeof(*mon_if), name, woal_mon_if_setup);
+#endif
+	if (!ndev) {
+		PRINTM(MFATAL, "Init virtual ethernet device failed\n");
+		ret = -EFAULT;
+		goto fail;
+	}
+
+	ret = dev_alloc_name(ndev, ndev->name);
+	if (ret < 0) {
+		PRINTM(MFATAL, "Net device alloc name fail.\n");
+		ret = -EFAULT;
+		goto fail;
+	}
+	//?memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
+
+	mon_if = netdev_priv(ndev);
+	memcpy(mon_if->ifname, ndev->name, IFNAMSIZ);
+
+	ndev->type = ARPHRD_IEEE80211_RADIOTAP;
+	ndev->netdev_ops = &woal_cfg80211_mon_if_ops;
+
+	mon_if->priv = priv;
+	mon_if->mon_ndev = ndev;
+	mon_if->base_ndev = priv->netdev;
+	mon_if->radiotap_enabled = 1;
+	mon_if->flag = 1;
+
+fail:
+	if (ret) {
+		if (ndev)
+			free_netdev(ndev);
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return mon_if;
+}
+
+#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,
+	.ndo_do_ioctl = woal_do_ioctl,
+	.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(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(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,
+	.ndo_do_ioctl = woal_uap_do_ioctl,
+	.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(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 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 (sta_name)
+		snprintf(name, sizeof(name), "%s%%d", sta_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 (uap_name)
+		snprintf(name, sizeof(name), "%s%%d", 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
+#if defined(WIFI_DIRECT_SUPPORT)
+	memset(name, 0, sizeof(name));
+	if (wfd_name)
+		snprintf(name, sizeof(name), "%s%%d", 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
+	memset(name, 0, sizeof(name));
+	if (nan_name)
+		snprintf(name, sizeof(name), "%s%%d", nan_name);
+	else
+		snprintf(name, sizeof(name), "%s", default_nan_name);
+	if ((bss_type == MLAN_BSS_TYPE_NAN) && (dev_alloc_name(dev, name) < 0)) {
+		PRINTM(MERROR, "Could not allocate nan 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->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;
+#if defined(WIFI_DIRECT_SUPPORT)
+	else if (bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+		priv->bss_role = MLAN_BSS_ROLE_STA;
+#endif
+	else if (bss_type == MLAN_BSS_TYPE_NAN)
+		priv->bss_role = MLAN_BSS_ROLE_STA;
+
+	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 LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	SET_MODULE_OWNER(dev);
+#endif
+#ifdef STA_SUPPORT
+	if (bss_type == MLAN_BSS_TYPE_STA
+#if defined(WIFI_DIRECT_SUPPORT)
+	    || bss_type == MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+	    || bss_type == MLAN_BSS_TYPE_NAN)
+		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
+	    && (mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		) {
+		if (init_cfg) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_user_init_data(handle, INIT_CFG_DATA,
+						    MOAL_IOCTL_WAIT)) {
+				PRINTM(MFATAL,
+				       "Set user init data and param failed\n");
+				goto error;
+			}
+		}
+		if (init_hostcmd_cfg) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_user_init_data(handle,
+						    INIT_HOSTCMD_CFG_DATA,
+						    MOAL_IOCTL_WAIT)) {
+				PRINTM(MFATAL,
+				       "Set user init hostcmd data and param failed\n");
+				goto error;
+			}
+		}
+	}
+
+	handle->priv_num++;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	if (!priv->phandle->wiphy && IS_STA_OR_UAP_CFG80211(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(cfg80211_wext)) {
+		if (bss_type == MLAN_BSS_TYPE_STA
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+		    || bss_type == MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+#endif
+		    || bss_type == MLAN_BSS_TYPE_NAN)
+			/* 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;
+			}
+	}
+#endif /* STA_SUPPORT */
+#endif /* STA_CFG80211 */
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+	if ((priv->bss_role == MLAN_BSS_ROLE_UAP) &&
+	    IS_UAP_CFG80211(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 */
+
+	/* 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: Marvell 802.11 Adapter\n", dev->name);
+	/* Set MAC address from the insmod command line */
+	if (handle->set_mac_addr) {
+		memset(priv->current_addr, 0, ETH_ALEN);
+		memcpy(priv->current_addr, handle->mac_addr, ETH_ALEN);
+#if defined(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)) {
+			PRINTM(MERROR, "Set MAC address failed\n");
+			goto error;
+		}
+		memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
+	}
+	/* Set MAC address for UAPx/MLANx/WFDx and let them different with each other */
+	if (priv->bss_index > 0
+#ifdef WIFI_DIRECT_SUPPORT
+	    && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+		) {
+		priv->current_addr[4] += priv->bss_index;
+		woal_request_set_mac_address(priv);
+		memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
+		PRINTM(MCMND, "Set %s interface addr: " MACSTR "\n", dev->name,
+		       MAC2STR(priv->current_addr));
+	}
+	if (bss_type == MLAN_BSS_TYPE_STA ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		mlan_fw_info fw_info;
+		woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+		if (handle->card_type == CARD_TYPE_SD8887 ||
+		    handle->card_type == CARD_TYPE_SD8987) {
+
+			if ((fw_info.antinfo & ANT_DIVERSITY_2G)&&(fw_info.
+								   antinfo &
+								   ANT_DIVERSITY_5G))
+				handle->histogram_table_num = 4;
+		}
+
+		for (i = 0; i < handle->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;
+			}
+		}
+		if (priv->hist_data)
+			woal_hist_data_reset(priv);
+	}
+#ifdef CONFIG_PROC_FS
+	woal_create_proc_entry(priv);
+#ifdef PROC_DEBUG
+	woal_debug_entry(priv);
+#endif /* PROC_DEBUG */
+#endif /* CONFIG_PROC_FS */
+
+	LEAVE();
+	return priv;
+error:
+	handle->priv_num = bss_index;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	/* Unregister wiphy device and free */
+	if (priv) {
+		if (priv->wdev && IS_STA_OR_UAP_CFG80211(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(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);
+
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_flush_tdls_list(priv);
+#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 ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		for (i = 0; i < handle->histogram_table_num; i++) {
+			kfree(priv->hist_data[i]);
+			priv->hist_data[i] = NULL;
+		}
+	}
+#ifdef CONFIG_PROC_FS
+#ifdef PROC_DEBUG
+	/* Remove proc debug */
+	woal_debug_remove(priv);
+#endif /* PROC_DEBUG */
+	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 defined(STA_CFG80211) || defined(UAP_CFG80211)
+	/* Unregister wiphy device and free */
+	if (priv->wdev && IS_STA_OR_UAP_CFG80211(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)
+		woal_deinit_wifi_hal(priv);
+#endif
+
+	/* Clear the priv in handle */
+	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;
+
+	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_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) {
+		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 = low_power_mode_enable;
+	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
+ */
+static 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 cancel all works in the queue
+ *  and destroy the main workqueue.
+ *
+ *  @param handle    A pointer to moal_handle
+ *
+ *  @return        N/A
+ */
+static 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;
+	}
+	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);
+	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(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. */
+	{
+		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 defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (!p2p_enh) {
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+		    IS_STA_CFG80211(cfg80211_wext)) {
+			priv->phandle->wiphy->interface_modes |=
+				MBIT(NL80211_IFTYPE_P2P_GO) |
+				MBIT(NL80211_IFTYPE_P2P_CLIENT);
+		}
+	}
+#endif
+#endif
+#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);
+
+	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)
+		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);
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (!p2p_enh) {
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+		    !priv->bss_virtual &&
+		    IS_STA_CFG80211(cfg80211_wext) &&
+		    IS_UAP_CFG80211(cfg80211_wext)) {
+			priv->phandle->wiphy->interface_modes &=
+				~(MBIT(NL80211_IFTYPE_P2P_GO) |
+				  MBIT(NL80211_IFTYPE_P2P_CLIENT));
+		}
+	}
+#endif
+#endif
+#endif
+	MODULE_PUT;
+
+	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;
+	}
+
+	memcpy(prev_addr, priv->current_addr, 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);
+	memcpy(priv->current_addr, phw_addr->sa_data, ETH_ALEN);
+#if defined(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)) {
+		PRINTM(MERROR, "Set MAC address failed\n");
+		/* For failure restore the MAC address */
+		memcpy(priv->current_addr, prev_addr, ETH_ALEN);
+		ret = -EFAULT;
+		goto done;
+	}
+	HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
+	memcpy(dev->dev_addr, priv->current_addr, 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;
+	struct timeval t;
+	int i = 0;
+	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
+	do_gettimeofday(&t);
+	if (info.pending_cmd &&
+	    (t.tv_sec > (info.dnld_cmd_in_secs + MOAL_CMD_TIMEOUT_MAX))) {
+		if (t.tv_sec > (info.dnld_cmd_in_secs + MOAL_CMD_TIMEOUT) &&
+		    !info.num_cmd_timeout) {
+			PRINTM(MERROR, "Ignore invalid time, wait=%d\n",
+			       (int)(t.tv_sec - info.dnld_cmd_in_secs));
+		} else {
+			PRINTM(MERROR, "Timeout cmd id = 0x%x wait=%d\n",
+			       info.pending_cmd,
+			       (int)(t.tv_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.tv_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.tv_sec - info.pm_wakeup_in_secs));
+			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_MULTI_PORT_TX_AGGR
+	int j;
+	t_u8 mp_aggr_pkt_limit = 0;
+#endif
+	char str[512] = { 0 };
+	char *s;
+
+	ENTER();
+
+	if (!priv || 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, "num_cmd_timeout = %d\n", info.num_cmd_timeout);
+	PRINTM(MERROR, "dbg.num_cmd_timeout = %d\n", info.dbg_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);
+
+	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, "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, "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, "data_sent=%d cmd_sent=%d\n", info.data_sent,
+	       info.cmd_sent);
+
+	PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", info.ps_mode, info.ps_state);
+	PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d\n",
+	       info.pm_wakeup_card_req, info.pm_wakeup_fw_try);
+	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);
+
+	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_invalid_update=%d\n", info.mp_invalid_update);
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	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
+	for (i = 0; i < 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);
+	}
+
+	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
+ */
+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)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+
+	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) {
+		woal_mlan_debug_info(priv);
+		woal_moal_debug_info(priv, NULL, MFALSE);
+		woal_broadcast_event(priv, CUS_EVT_DRIVER_HANG,
+				     strlen(CUS_EVT_DRIVER_HANG));
+#if defined(STA_CFG80211) || defined(UAP_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
+		priv->phandle->driver_state = MTRUE;
+		woal_process_hang(priv->phandle);
+	}
+
+	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)
+		  , void *accel_priv
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 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();
+
+	/*
+	 * 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);
+}
+
+/**
+ *  @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();
+}
+
+/**
+ *  @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
+ */
+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();
+	memcpy(ra, skb->data, MLAN_MAC_ADDR_LENGTH);
+	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
+
+/**
+ *  @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
+ */
+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);
+				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
+ */
+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);
+			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
+ */
+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) {
+			/* 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, iph->saddr,
+						tcph->source, iph->daddr,
+						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 = iph->saddr;
+			tcp_session->dst_ip_addr = iph->daddr;
+			tcp_session->src_tcp_port = tcph->source;
+			tcp_session->dst_tcp_port = 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)) {
+			memcpy(skb->data, pmbuf->pbuf + pmbuf->data_offset,
+			       pmbuf->data_len);
+			tcp_session->ack_seq = ack_seq;
+			ret = DROP_TCP_ACK;
+			skb->cb[0]++;
+//We will drop 90% tcp ack
+#define TCP_ACK_MAX_HOLD    9
+			if (skb->cb[0] >= 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
+ */
+int
+woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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();
+	PRINTM(MDATA, "%lu : %s (bss=%d): Data <= kernel\n",
+	       jiffies, dev->name, priv->bss_index);
+
+	if (priv->phandle->surprise_removed == MTRUE) {
+		dev_kfree_skb_any(skb);
+		priv->stats.tx_dropped++;
+		goto done;
+	}
+	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;
+	}
+	if (skb->cloned || (skb_headroom(skb) < (MLAN_MIN_DATA_HEADER_LEN +
+						 sizeof(mlan_buffer) +
+						 priv->extra_tx_head_len))) {
+		PRINTM(MWARN,
+		       "Tx: skb cloned %d or Insufficient skb headroom %d\n",
+		       skb->cloned, skb_headroom(skb));
+		/* 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);
+		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;
+	}
+#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
+
+	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);
+			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 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;
+	}
+	memcpy(mac_buff, buf, strlen(buf));
+
+	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();
+	woal_request_set_multicast_list(priv, dev);
+	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;
+		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;
+#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
+#endif
+	}
+#endif
+
+	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;
+#endif
+
+	priv->enable_tcp_ack_enh = MTRUE;
+
+	priv->enable_auto_tdls = MFALSE;
+	priv->tdls_check_tx = MFALSE;
+
+	woal_request_get_fw_info(priv, wait_option, NULL);
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+			if (priv->bss_virtual) {
+				if (priv->pa_netdev) {
+					memcpy(priv->current_addr,
+					       priv->pa_netdev->dev_addr,
+					       ETH_ALEN);
+					priv->current_addr[4] ^= 0x80;
+					woal_request_set_mac_address(priv);
+					memcpy(priv->netdev->dev_addr,
+					       priv->current_addr, ETH_ALEN);
+					PRINTM(MCMND,
+					       "Set WFD interface addr: " MACSTR
+					       "\n",
+					       MAC2STR(priv->current_addr));
+				}
+			} else {
+				priv->current_addr[0] |= 0x02;
+				woal_request_set_mac_address(priv);
+				memcpy(priv->netdev->dev_addr,
+				       priv->current_addr, ETH_ALEN);
+				PRINTM(MCMND,
+				       "Set WFD device addr: " MACSTR "\n",
+				       MAC2STR(priv->current_addr));
+			}
+		}
+#endif
+#endif
+#endif
+#ifdef UAP_SUPPORT
+#if defined(DFS_TESTING_SUPPORT)
+	priv->user_cac_period_msec = 0;
+#endif
+#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;
+
+	/* 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);
+
+#ifdef STA_SUPPORT
+	woal_cancel_scan(priv, wait_option);
+#endif
+
+	/* 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 defined(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;
+}
+
+#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
+		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);
+		memcpy(NLMSG_DATA(nlh), netdev->name, IFNAMSIZ);
+		memcpy(((t_u8 *)(NLMSG_DATA(nlh))) + IFNAMSIZ, payload, len);
+
+		/* 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);
+
+		/* 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));
+			memcpy(&req_ssid,
+			       &priv->prev_ssid_bssid.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");
+					memcpy(&ssid_bssid.bssid,
+					       &priv->prev_ssid_bssid.bssid,
+					       MLAN_MAC_ADDR_LENGTH);
+				} else {
+					/* Search AP by ESSID for asynced essid setting */
+					PRINTM(MINFO,
+					       "Set asynced essid: Search AP by ESSID\n");
+				}
+
+				memcpy(&ssid_bssid.ssid,
+				       &priv->prev_ssid_bssid.ssid,
+				       sizeof(mlan_802_11_ssid));
+			} else {
+				/* Search AP by BSSID first */
+				PRINTM(MINFO,
+				       "Reassoc: Search AP by BSSID first\n");
+				memcpy(&ssid_bssid.bssid,
+				       &priv->prev_ssid_bssid.bssid,
+				       MLAN_MAC_ADDR_LENGTH);
+			}
+
+			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));
+				memcpy(&ssid_bssid.ssid,
+				       &priv->prev_ssid_bssid.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 {
+						memcpy(&priv->prev_ssid_bssid.
+						       ssid, &bss_info.ssid,
+						       sizeof
+						       (mlan_802_11_ssid));
+						memcpy(&priv->prev_ssid_bssid.
+						       bssid, &bss_info.bssid,
+						       MLAN_MAC_ADDR_LENGTH);
+					}
+					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 */
+
+#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;
+		}
+		memcpy(dscp_except,
+		       (t_u8 *)qos_mapping_ie + sizeof(IEEEtypes_Header_t),
+		       dscp_except_num * sizeof(DSCP_Exception_t));
+		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
+	t_u16 reason_code = 0;
+
+	ENTER();
+	priv->media_connected = MFALSE;
+	if (!disconnect_reason)
+		reason_code = MLAN_REASON_DEAUTH_LEAVING;
+	else
+		reason_code = disconnect_reason;
+	woal_stop_queue(priv->netdev);
+	if (netif_carrier_ok(priv->netdev))
+		netif_carrier_off(priv->netdev);
+	woal_flush_tcp_sess_queue(priv);
+
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_flush_tdls_list(priv);
+#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 && priv->hist_data)
+		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->iftype != NL80211_IFTYPE_ADHOC
+		    && ((priv->bss_type != MLAN_BSS_TYPE_STA) ||
+			(priv->bss_type == MLAN_BSS_TYPE_STA &&
+			 priv->sme_current.ssid))
+			) {
+			PRINTM(MMSG,
+			       "wlan: Disconnected from " MACSTR
+			       ": Reason code %d\n", MAC2STR(priv->cfg_bssid),
+			       reason_code);
+			spin_unlock_irqrestore(&priv->connect_lock, flags);
+			/* 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 */
+			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;
+		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);
+	strncpy(event_buf, CUS_EVT_AP_CONNECTED,
+		MIN((sizeof(event_buf) - 1), custom_len));
+	woal_broadcast_event(priv, event_buf, custom_len + ETH_ALEN);
+	LEAVE();
+}
+#endif /* STA_SUPPORT */
+
+#define OFFSET_SEQNUM 4
+/**
+ *  @brief  This function stores the FW dumps received from events in a file
+ *
+ *  @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)
+{
+	struct file *pfile_fwdump = NULL;
+	loff_t pos = 0;
+	t_u16 seqnum;
+	t_u8 path_name[64];
+
+	ENTER();
+	if (phandle->fwdump_fname)
+		pfile_fwdump =
+			filp_open(phandle->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+	else {
+		seqnum = woal_le16_to_cpu(*(t_u16 *)
+					  (pmevent->event_buf + OFFSET_SEQNUM));
+		if (seqnum == 1) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	    /** Create dump directort*/
+			woal_create_dump_dir(phandle, path_name,
+					     sizeof(path_name));
+#else
+			memset(path_name, 0, sizeof(path_name));
+			strcpy(path_name, "/data");
+#endif
+			PRINTM(MMSG, "Firmware Dump directory name is %s\n",
+			       path_name);
+			woal_dump_drv_info(phandle, path_name);
+			if (fwdump_fname) {
+				memset(fwdump_fname, 0, 64);
+			} else {
+				gfp_t flag;
+				flag = (in_atomic() ||
+					irqs_disabled())? GFP_ATOMIC :
+					GFP_KERNEL;
+				fwdump_fname = kzalloc(64, flag);
+			}
+			sprintf(fwdump_fname, "%s/file_fwdump", path_name);
+			pfile_fwdump =
+				filp_open(fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+			if (IS_ERR(pfile_fwdump)) {
+				memset(fwdump_fname, 0, 64);
+				sprintf(fwdump_fname, "%s/%s", "/var",
+					"file_fwdump");
+				pfile_fwdump =
+					filp_open(fwdump_fname,
+						  O_CREAT | O_WRONLY | O_APPEND,
+						  0644);
+			}
+		} else
+			pfile_fwdump =
+				filp_open(fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+	}
+	if (IS_ERR(pfile_fwdump)) {
+		PRINTM(MERROR, "Cannot create firmware dump file\n");
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile_fwdump, pmevent->event_buf, pmevent->event_len, &pos);
+#else
+	kernel_write(pfile_fwdump, pmevent->event_buf, pmevent->event_len,
+		     &pos);
+#endif
+	filp_close(pfile_fwdump, NULL);
+	LEAVE();
+	return;
+}
+
+#define DRV_INFO_SIZE 0x40000
+#define ROW_SIZE_16      16
+#define ROW_SIZE_32      32
+/**
+ *  @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 < (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;
+}
+
+#define SDIO_SCRATCH_REG 0x60
+/**
+ *  @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_dump_sdio_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 = SDIO_SCRATCH_REG;
+	unsigned int reg_table_8887_8977_8997[] =
+		{ 0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62,
+		0x64, 0x65, 0x66, 0x68, 0x69, 0x6a
+	};
+	unsigned int reg_table_8897[] =
+		{ 0x4C, 0x50, 0x54, 0x55, 0x58, 0x59, 0x5c,
+		0x5d
+	};
+    /** for sd8787/sd8777 */
+	unsigned int reg_table_other[] = { 0x28, 0x30, 0x34, 0x38, 0x3c };
+	unsigned int *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;
+	}
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+#define SDIO_SCRATCH_REG_8887 0x90
+#define SDIO_SCRATCH_REG_8897 0xC0
+#define SDIO_SCRATCH_REG_8977_8997 0xE8
+#define SDIO_SCRATCH_REG_OTHER 0x60
+	if (phandle->card_type == CARD_TYPE_SD8887) {
+		reg_table = reg_table_8887_8977_8997;
+		reg_table_size = sizeof(reg_table_8887_8977_8997) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8887;
+	} else if (phandle->card_type == CARD_TYPE_SD8897) {
+		reg_table = reg_table_8897;
+		reg_table_size = sizeof(reg_table_8897) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8897;
+	} else if ((phandle->card_type == CARD_TYPE_SD8977) ||
+		   (phandle->card_type == CARD_TYPE_SD8997) ||
+		   (phandle->card_type == CARD_TYPE_SD8987)) {
+		reg_table = reg_table_8887_8977_8997;
+		reg_table_size = sizeof(reg_table_8887_8977_8997) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8977_8997;
+	} else {
+		reg_table = reg_table_other;
+		reg_table_size = sizeof(reg_table_other) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_OTHER;
+	}
+
+	drv_ptr += sprintf(drv_ptr, "--------sdio_reg_debug_info---------\n");
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+	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;
+			if (phandle->card_type == CARD_TYPE_SD8897) {
+				reg_start = 4;
+				reg_end = 0xB;
+			} else if ((phandle->card_type == CARD_TYPE_SD8887) ||
+				   (phandle->card_type == CARD_TYPE_SD8977) ||
+				   (phandle->card_type == CARD_TYPE_SD8997) ||
+				   (phandle->card_type == CARD_TYPE_SD8987)) {
+				reg_start = 0x10;
+				reg_end = 0x17;
+			} else {
+				reg_start = 4;
+				reg_end = 9;
+			}
+		} 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)
+				data = sdio_f0_readb(((struct sdio_mmc_card *)
+						      phandle->card)->func, reg,
+						     &ret);
+			else
+				data = sdio_readb(((struct sdio_mmc_card *)
+						   phandle->card)->func, reg,
+						  &ret);
+			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);
+	}
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+
+	drv_ptr +=
+		sprintf(drv_ptr, "--------sdio_reg_debug_info End---------\n");
+
+	LEAVE();
+	return drv_ptr - (char *)drv_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;
+	char str_buf[MLAN_MAX_VER_STR_LEN];
+
+	ENTER();
+	if (!phandle || !buf) {
+		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
+		LEAVE();
+		return 0;
+	}
+	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);
+	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));
+#if defined(SDIO_SUSPEND_RESUME)
+	ptr += sprintf(ptr, "hs_skip_count = %u\n", phandle->hs_skip_count);
+	ptr += sprintf(ptr, "hs_force_count = %u\n", phandle->hs_force_count);
+#endif
+
+	ptr += woal_dump_priv_drv_info(phandle, ptr);
+	ptr += sprintf(ptr, "------------moal_debug_info End-------------\n");
+
+	ptr += woal_dump_sdio_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_MULTI_PORT_TX_AGGR
+	int j;
+	t_u8 mp_aggr_pkt_limit = 0;
+#endif
+	char str[11 * DBG_CMD_NUM + 1] = { 0 };
+	char *s;
+
+	ENTER();
+	if (!priv || 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, "num_cmd_timeout = %d\n", info.num_cmd_timeout);
+	ptr += sprintf(ptr, "dbg.num_cmd_timeout = %d\n",
+		       info.dbg_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);
+	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, "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, "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, "data_sent=%d cmd_sent=%d\n", info.data_sent,
+		       info.cmd_sent);
+	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\n",
+		       info.pm_wakeup_card_req, info.pm_wakeup_fw_try);
+	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);
+
+	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_invalid_update=%d\n", info.mp_invalid_update);
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	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
+	ptr += sprintf(ptr, "------------mlan_debug_info End-------------\n");
+
+	LEAVE();
+	return ptr - (char *)buf;
+}
+
+/**
+ *  @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 < len; i += rowsize) {
+		linelen = min(remaining, rowsize);
+		remaining -= rowsize;
+
+		hex_dump_to_buffer(ptr + i, linelen, rowsize, 1, linebuf,
+				   sizeof(linebuf), ascii);
+
+		pos += sprintf(pos, "%p: %s\n", ptr + i, linebuf);
+	}
+
+	return pos - (char *)save_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++) {
+		ptr += sprintf(ptr, "<--moal_private(%d)-->\n", i);
+		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
+ *  @param pfile  A pointer to file structure
+ *
+ *  @return          The length of this log
+ */
+static int
+woal_dump_mlan_hex(moal_private *priv, t_u8 *buf, struct file *pfile)
+{
+	char *ptr = (char *)buf;
+	int i;
+	int len = 0;
+
+	ENTER();
+
+	if (!buf || !priv || !pfile ||
+	    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");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#else
+	kernel_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#endif
+	len += ptr - (char *)buf;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	if (info.mpa_buf && info.mpa_buf_size) {
+		ptr = (char *)buf;
+		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");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+		vfs_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#else
+		kernel_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#endif
+		len += ptr - (char *)buf;
+	}
+#endif
+	for (i = 0; i < info.mlan_priv_num; i++) {
+		ptr = (char *)buf;
+		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);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+		vfs_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#else
+		kernel_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#endif
+		len += ptr - (char *)buf;
+	}
+
+	LEAVE();
+	return len;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+/**
+ *  @brief This function create dump directory
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param dir_buf   A pointer to dir_buf buffer
+ *  @param buf_size  Size of dir_buf buffer
+ *
+ *  @return         N/A
+ */
+void
+woal_create_dump_dir(moal_handle *phandle, char *dir_buf, int buf_size)
+{
+	struct dentry *dentry;
+	struct path path;
+	t_u32 sec, usec;
+	int ret;
+
+	ENTER();
+
+	if (!phandle || !dir_buf) {
+		PRINTM(MERROR, "Can't create directory\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	moal_get_system_time(phandle, &sec, &usec);
+	memset(dir_buf, 0, buf_size);
+	sprintf(dir_buf, "%s%u", "/data/dump_", sec);
+
+	dentry = kern_path_create(AT_FDCWD, dir_buf, &path, 1);
+	if (IS_ERR(dentry)) {
+		PRINTM(MERROR,
+		       "Create directory %s error, try create dir in /var",
+		       dir_buf);
+		memset(dir_buf, 0, buf_size);
+		sprintf(dir_buf, "%s%u", "/var/dump_", sec);
+		dentry = kern_path_create(AT_FDCWD, dir_buf, &path, 1);
+	}
+	if (IS_ERR(dentry)) {
+		PRINTM(MERROR, "Create directory %s error, use default folder",
+		       dir_buf);
+		goto default_dir;
+	}
+	ret = vfs_mkdir(path.dentry->d_inode, dentry, 0777);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&path.dentry->d_inode->i_mutex);
+#else
+	inode_unlock(path.dentry->d_inode);
+#endif
+
+	if (ret < 0) {
+		PRINTM(MERROR,
+		       "Create directory failure, use default folder\n");
+		PRINTM(MERROR, "Create directory failure, ret = %d\n", ret);
+		goto default_dir;
+	} else {
+		PRINTM(MERROR, "Create directory %s successfully\n", dir_buf);
+		goto done;
+	}
+
+default_dir:
+	memset(dir_buf, 0, buf_size);
+	sprintf(dir_buf, "%s", "/data");
+done:
+	LEAVE();
+}
+#endif
+
+/**
+ *  @brief This function save dump buf to file
+ *
+ *  @param dir_name  A pointer to directory name
+ *  @param file_name A pointer to file name
+ *  @param buf       A pointer to dump data
+ *  @param buf_len   The length of dump buf
+ *
+ *  @return         SUCCESS OR FAILURE
+ */
+mlan_status
+woal_save_dump_info_to_file(char *dir_name, char *file_name, t_u8 *buf,
+			    t_u32 buf_len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	struct file *pfile = NULL;
+	t_u8 name[64];
+	loff_t pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	if (!dir_name || !file_name || !buf) {
+		PRINTM(MERROR, "Can't save dump info to file\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(name, 0, sizeof(name));
+	sprintf(name, "%s/%s", dir_name, file_name);
+	pfile = filp_open(name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR,
+		       "Create file %s error, try to save dump file in /var\n",
+		       name);
+		memset(name, 0, sizeof(name));
+		sprintf(name, "%s/%s", "/var", file_name);
+		pfile = filp_open(name, O_CREAT | O_RDWR, 0644);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR, "Create Dump file for %s error\n", name);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MERROR, "Dump data %s saved in %s\n", file_name, name);
+
+	pos = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	vfs_write(pfile, buf, buf_len, &pos);
+	set_fs(fs);
+#else
+	kernel_write(pfile, buf, buf_len, &pos);
+#endif
+	filp_close(pfile, NULL);
+
+	PRINTM(MERROR, "Dump data %s saved in %s successfully\n", file_name,
+	       name);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function dump drv info to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param dir_name   A pointer to directory name
+ *
+ *  @return         N/A
+ */
+void
+woal_dump_drv_info(moal_handle *phandle, t_u8 *dir_name)
+{
+	int ret = 0;
+	struct file *pfile = NULL;
+	t_u8 *drv_buf;
+	t_u8 file_name[64];
+	t_u32 len = 0;
+	t_u32 total_len = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	PRINTM(MERROR, "=== START DRIVER INFO DUMP===");
+	ret = moal_vmalloc(phandle, DRV_INFO_SIZE + 1, &drv_buf);
+	if ((ret != MLAN_STATUS_SUCCESS) || !drv_buf) {
+		PRINTM(MERROR, "Error: vmalloc drv buffer failed!\n");
+		goto done;
+	}
+	memset(file_name, 0, sizeof(file_name));
+	sprintf(file_name, "%s/%s", dir_name, "file_drv_info");
+	pfile = filp_open(file_name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR,
+		       "Create file %s error, try create /var/file_drv_info",
+		       file_name);
+		pfile = filp_open("/var/file_drv_info", O_CREAT | O_RDWR, 0644);
+	} else {
+		PRINTM(MERROR, "DRV dump data in %s\n", file_name);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR, "Create file_drv_info file failed\n");
+		goto done;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+#endif
+
+	len = woal_dump_moal_drv_info(phandle, drv_buf);
+	total_len += len;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile, drv_buf, len, &pfile->f_pos);
+#else
+	kernel_write(pfile, drv_buf, len, &pfile->f_pos);
+#endif
+
+	len = woal_dump_mlan_drv_info(woal_get_priv(phandle, MLAN_BSS_ROLE_ANY),
+				      drv_buf);
+	total_len += len;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile, drv_buf, len, &pfile->f_pos);
+#else
+	kernel_write(pfile, drv_buf, len, &pfile->f_pos);
+#endif
+
+	len = woal_dump_moal_hex(phandle, drv_buf);
+	total_len += len;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile, drv_buf, len, &pfile->f_pos);
+#else
+	kernel_write(pfile, drv_buf, len, &pfile->f_pos);
+#endif
+
+	len = woal_dump_mlan_hex(woal_get_priv(phandle, MLAN_BSS_ROLE_ANY),
+				 drv_buf, pfile);
+	total_len += len;
+
+	PRINTM(MERROR, "Drv info total bytes = %ld (0x%lx)\n",
+	       (long int)total_len, (long unsigned int)total_len);
+
+	filp_close(pfile, NULL);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	set_fs(fs);
+#endif
+	PRINTM(MERROR, "=== DRIVER INFO DUMP END===");
+done:
+	if (drv_buf)
+		moal_vfree(phandle, drv_buf);
+	LEAVE();
+}
+
+#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
+/* SD8777 */
+#define SQRAM_SIZE_8777                        0x33000
+#define DTCM_SIZE_8777                         0x14000
+/* SD8787 */
+#define SQRAM_SIZE_8787                        0x33000
+#define DTCM_SIZE_8787                         0xA700
+/* SD8801 */
+#define SQRAM_SIZE_8801                        0x33000
+#define DTCM_SIZE_8801                         0x14000
+/* SD8797 */
+#define SQRAM_SIZE_8797                        0x7c000
+#define DTCM_SIZE_8797                         0x14000
+
+#define DEBUG_HOST_READY_8977_8997     0xCC
+#define DEBUG_HOST_READY_OTHER     0xEE
+
+#define SQRAM_SIZE                        0x33500
+
+#define DTCM_SIZE                         0x10000
+
+/**
+ *  @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 path_name[64], file_name[32];
+	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 = 0;
+	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->card_type == CARD_TYPE_SD8887) ||
+	    (phandle->card_type == CARD_TYPE_SD8897)) {
+		woal_dump_firmware_info_v2(phandle);
+		return;
+	} else if ((phandle->card_type == CARD_TYPE_SD8977) ||
+		   (phandle->card_type == CARD_TYPE_SD8997) ||
+		   (phandle->card_type == CARD_TYPE_SD8987)) {
+		woal_dump_firmware_info_v3(phandle);
+		return;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+    /** Create dump directort*/
+	woal_create_dump_dir(phandle, path_name, sizeof(path_name));
+#else
+	memset(path_name, 0, sizeof(path_name));
+	strcpy(path_name, "/data");
+#endif
+	PRINTM(MMSG, "Directory name is %s\n", path_name);
+
+	woal_dump_drv_info(phandle, path_name);
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+	phandle->fw_dump = MTRUE;
+	/* 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;
+	}
+	if (phandle->card_type == CARD_TYPE_SD8787) {
+		dtcm_size = DTCM_SIZE_8787;
+		sqram_size = SQRAM_SIZE_8787;
+	} else if (phandle->card_type == CARD_TYPE_SD8777) {
+		dtcm_size = DTCM_SIZE_8777;
+		sqram_size = SQRAM_SIZE_8777;
+	} else if (phandle->card_type == CARD_TYPE_SD8801) {
+		dtcm_size = DTCM_SIZE_8801;
+		sqram_size = SQRAM_SIZE_8801;
+	} else if (phandle->card_type == CARD_TYPE_SD8797) {
+		dtcm_size = DTCM_SIZE_8797;
+		sqram_size = SQRAM_SIZE_8797;
+	} else
+		dtcm_size = DTCM_SIZE;
+
+	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 {
+		sdio_writeb(((struct sdio_mmc_card *)phandle->card)->func,
+			    DEBUG_HOST_READY, DEBUG_DUMP_CTRL_REG, &ret);
+		if (ret) {
+			PRINTM(MERROR, "SDIO Write ERR\n");
+			goto done;
+		}
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			ctrl_data =
+				sdio_readb(((struct sdio_mmc_card *)phandle->
+					    card)->func, DEBUG_DUMP_CTRL_REG,
+					   &ret);
+			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) {
+				sdio_writeb(((struct sdio_mmc_card *)phandle->
+					     card)->func, DEBUG_HOST_READY,
+					    DEBUG_DUMP_CTRL_REG, &ret);
+				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;
+		*dbg_ptr =
+			sdio_readb(((struct sdio_mmc_card *)phandle->card)->
+				   func, reg, &ret);
+		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++) {
+			*dbg_ptr =
+				sdio_readb(((struct sdio_mmc_card *)phandle->
+					    card)->func, reg, &ret);
+			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
+			memset(file_name, 0, sizeof(file_name));
+			sprintf(file_name, "%s", "file_sdio_ITCM");
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_save_dump_info_to_file(path_name, file_name,
+							ITCM_Ptr, ITCM_SIZE))
+				PRINTM(MMSG, "Can't save dump file %s in %s\n",
+				       file_name, path_name);
+			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
+			memset(file_name, 0, sizeof(file_name));
+			sprintf(file_name, "%s", "file_sdio_DTCM");
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_save_dump_info_to_file(path_name, file_name,
+							DTCM_Ptr, dtcm_size))
+				PRINTM(MMSG, "Can't save dump file %s in %s\n",
+				       file_name, path_name);
+			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
+			memset(file_name, 0, sizeof(file_name));
+			sprintf(file_name, "%s", "file_sdio_SQRAM");
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_save_dump_info_to_file(path_name, file_name,
+							SQRAM_Ptr, sqram_size))
+				PRINTM(MMSG, "Can't save dump file %s in %s\n",
+				       file_name, path_name);
+			PRINTM(MMSG, "End output!\n");
+			break;
+		default:
+			break;
+		}
+	} while (ctrl_data != DEBUG_SQRAM_DONE);
+
+	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:
+	phandle->fw_dump = MFALSE;
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+	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;
+}
+
+#define DEBUG_DUMP_CTRL_REG_8887               0xA2
+#define DEBUG_DUMP_START_REG_8887              0xA3
+#define DEBUG_DUMP_END_REG_8887                0xAA
+
+#define DEBUG_DUMP_CTRL_REG_8897               0xE2
+#define DEBUG_DUMP_START_REG_8897              0xE3
+#define DEBUG_DUMP_END_REG_8897                0xEA
+
+#define DEBUG_DUMP_CTRL_REG_8977_8997               0xF9
+#define DEBUG_DUMP_START_REG_8977_8997              0xF1
+#define DEBUG_DUMP_END_REG_8977_8997                0xF8
+
+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
+#define MAX_FULL_NAME_LEN               32
+t_u8 *name_prefix = "/data/file_";
+
+typedef struct {
+	t_u8 mem_name[MAX_NAME_LEN];
+	t_u8 *mem_Ptr;
+	struct file *pfile_mem;
+	t_u8 done_flag;
+} memory_type_mapping;
+
+memory_type_mapping mem_type_mapping_tbl[] = {
+	{"ITCM", NULL, NULL, 0xF0},
+	{"DTCM", NULL, NULL, 0xF1},
+	{"SQRAM", NULL, NULL, 0xF2},
+	{"APU", NULL, NULL, 0xF3},
+	{"CIU", NULL, NULL, 0xF4},
+	{"ICU", NULL, NULL, 0xF5},
+	{"MAC", NULL, NULL, 0xF6},
+	{"EXT7", NULL, NULL, 0xF7},
+	{"EXT8", NULL, NULL, 0xF8},
+	{"EXT9", NULL, NULL, 0xF9},
+	{"EXT10", NULL, NULL, 0xFA},
+	{"EXT11", NULL, NULL, 0xFB},
+	{"EXT12", NULL, NULL, 0xFC},
+	{"EXT13", NULL, NULL, 0xFD},
+	{"EXTLAST", NULL, NULL, 0xFE},
+};
+memory_type_mapping mem_type_mapping_tbl_8977_8997 =
+	{ "DUMP", NULL, NULL, 0xDD };
+
+typedef enum {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+} rdwr_status;
+
+/**
+ *  @brief This function read/write firmware via cmd52
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param doneflag  A flag
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+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 = 0;
+	t_u8 debug_host_ready = 0;
+
+	if (phandle->card_type == CARD_TYPE_SD8887) {
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8887;
+		debug_host_ready = DEBUG_HOST_READY_OTHER;
+	} else if (phandle->card_type == CARD_TYPE_SD8897) {
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8897;
+		debug_host_ready = DEBUG_HOST_READY_OTHER;
+	} else if ((phandle->card_type == CARD_TYPE_SD8977) ||
+		   (phandle->card_type == CARD_TYPE_SD8997) ||
+		   (phandle->card_type == CARD_TYPE_SD8987)) {
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8977_8997;
+		debug_host_ready = DEBUG_HOST_READY_8977_8997;
+	}
+	sdio_writeb(((struct sdio_mmc_card *)phandle->card)->func,
+		    debug_host_ready, dbg_dump_ctrl_reg, &ret);
+	if (ret) {
+		PRINTM(MERROR, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+		ctrl_data =
+			sdio_readb(((struct sdio_mmc_card *)phandle->card)->
+				   func, dbg_dump_ctrl_reg, &ret);
+		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");
+			sdio_writeb(((struct sdio_mmc_card *)phandle->card)->
+				    func, debug_host_ready, dbg_dump_ctrl_reg,
+				    &ret);
+			if (ret) {
+				PRINTM(MERROR, "SDIO Write ERR\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		udelay(100);
+	}
+	if (ctrl_data == debug_host_ready) {
+		PRINTM(MERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	return RDWR_STATUS_SUCCESS;
+}
+
+/**
+ *  @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 path_name[64], file_name[32];
+	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;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+    /** Create dump directort*/
+	woal_create_dump_dir(phandle, path_name, sizeof(path_name));
+#else
+	memset(path_name, 0, sizeof(path_name));
+	strcpy(path_name, "/data");
+#endif
+	PRINTM(MMSG, "Directory name is %s\n", path_name);
+
+	woal_dump_drv_info(phandle, path_name);
+	if (phandle->card_type == CARD_TYPE_SD8887) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8887;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8887;
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8887;
+	} else if (phandle->card_type == CARD_TYPE_SD8897) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8897;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8897;
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8897;
+	}
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+	phandle->fw_dump = MTRUE;
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+	/* 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;
+	dump_num =
+		sdio_readb(((struct sdio_mmc_card *)phandle->card)->func, reg,
+			   &ret);
+	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++) {
+			read_reg =
+				sdio_readb(((struct sdio_mmc_card *)phandle->
+					    card)->func, reg, &ret);
+			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_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++) {
+				*dbg_ptr =
+					sdio_readb(((struct sdio_mmc_card *)
+						    phandle->card)->func, reg,
+						   &ret);
+				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) {
+				PRINTM(MMSG, "%s done:"
+#ifdef MLAN_64BIT
+				       "size = 0x%lx\n",
+#else
+				       "size = 0x%x\n",
+#endif
+				       mem_type_mapping_tbl[idx].mem_name,
+				       dbg_ptr -
+				       mem_type_mapping_tbl[idx].mem_Ptr);
+				memset(file_name, 0, sizeof(file_name));
+				sprintf(file_name, "%s%s", "file_sdio_",
+					mem_type_mapping_tbl[idx].mem_name);
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_save_dump_info_to_file(path_name,
+								file_name,
+								mem_type_mapping_tbl
+								[idx].mem_Ptr,
+								memory_size))
+					PRINTM(MMSG,
+					       "Can't save dump file %s in %s\n",
+					       file_name, path_name);
+				moal_vfree(phandle,
+					   mem_type_mapping_tbl[idx].mem_Ptr);
+				mem_type_mapping_tbl[idx].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:
+	phandle->fw_dump = MFALSE;
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+	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 path_name[64], file_name[32], firmware_dump_file[128];
+	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;
+	memory_type_mapping *pmem_type_mapping_tbl =
+		&mem_type_mapping_tbl_8977_8997;
+
+	if (!phandle) {
+		PRINTM(MERROR, "Could not dump firmwware info\n");
+		return;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+    /** Create dump directort*/
+	woal_create_dump_dir(phandle, path_name, sizeof(path_name));
+#else
+	memset(path_name, 0, sizeof(path_name));
+	strcpy(path_name, "/data");
+#endif
+	PRINTM(MERROR, "Directory name is %s\n", path_name);
+
+	woal_dump_drv_info(phandle, path_name);
+
+	dbg_dump_start_reg = DEBUG_DUMP_START_REG_8977_8997;
+	dbg_dump_end_reg = DEBUG_DUMP_END_REG_8977_8997;
+	dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8977_8997;
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+	phandle->fw_dump = MTRUE;
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+	/* 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++) {
+			start_flag =
+				sdio_readb(((struct sdio_mmc_card *)phandle->
+					    card)->func, reg, &ret);
+			if (ret) {
+				PRINTM(MMSG, "SDIO READ ERR\n");
+				goto done;
+			}
+	     /** 0 means dump starting*/
+			if (start_flag == 0)
+				break;
+			if (tries == MAX_POLL_TRIES) {
+				PRINTM(MMSG, "FW not ready to dump\n");
+				goto done;
+			}
+			udelay(100);
+		}
+	}
+
+	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++) {
+			*dbg_ptr =
+				sdio_readb(((struct sdio_mmc_card *)phandle->
+					    card)->func, reg, &ret);
+			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(phandle, temp_Ptr,
+					    pmem_type_mapping_tbl->mem_Ptr,
+					    memory_size);
+				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) {
+			PRINTM(MMSG, "%s done:"
+#ifdef MLAN_64BIT
+			       "size = 0x%lx\n",
+#else
+			       "size = 0x%x\n",
+#endif
+			       pmem_type_mapping_tbl->mem_name,
+			       dbg_ptr - pmem_type_mapping_tbl->mem_Ptr);
+
+			memset(file_name, 0, sizeof(file_name));
+			sprintf(file_name, "%s%s", "file_sdio_",
+				pmem_type_mapping_tbl->mem_name);
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_save_dump_info_to_file(path_name, file_name,
+							pmem_type_mapping_tbl->
+							mem_Ptr,
+							dbg_ptr -
+							pmem_type_mapping_tbl->
+							mem_Ptr))
+				PRINTM(MERROR,
+				       "Can't save dump file %s in %s\n",
+				       file_name, path_name);
+			moal_vfree(phandle, 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 */
+	memset(firmware_dump_file, 0, sizeof(firmware_dump_file));
+	sprintf(firmware_dump_file, "%s/%s", path_name, file_name);
+	memcpy(phandle->firmware_dump_file, firmware_dump_file,
+	       sizeof(firmware_dump_file));
+done:
+	phandle->fw_dump = MFALSE;
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+	if (pmem_type_mapping_tbl->mem_Ptr) {
+		moal_vfree(phandle, pmem_type_mapping_tbl->mem_Ptr);
+		pmem_type_mapping_tbl->mem_Ptr = NULL;
+	}
+	PRINTM(MERROR, "==== DEBUG MODE END ====\n");
+	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;
+	t_u16 card_type = phandle->card_type;
+
+	ENTER();
+
+	switch (card_type) {
+	case CARD_TYPE_SD8777:
+		phandle->card_info = &card_info_sd8777;
+		break;
+	case CARD_TYPE_SD8787:
+		phandle->card_info = &card_info_sd8787;
+		break;
+	case CARD_TYPE_SD8887:
+		phandle->card_info = &card_info_sd8887;
+		break;
+	case CARD_TYPE_SD8801:
+		phandle->card_info = &card_info_sd8801;
+		break;
+	case CARD_TYPE_SD8897:
+		phandle->card_info = &card_info_sd8897;
+		break;
+	case CARD_TYPE_SD8797:
+		phandle->card_info = &card_info_sd8797;
+		break;
+	case CARD_TYPE_SD8977:
+		phandle->card_info = &card_info_sd8977;
+		break;
+	case CARD_TYPE_SD8997:
+		phandle->card_info = &card_info_sd8997;
+		break;
+	case CARD_TYPE_SD8987:
+		phandle->card_info = &card_info_sd8987;
+		break;
+	default:
+		PRINTM(MERROR,
+		       "woal_get_card_info can't get right card type \n");
+		ret = -1;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads and displays SDIO registers for debugging
+ *
+ *  @param phandle  A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_sdio_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 = SDIO_SCRATCH_REG;
+	unsigned int reg_table_8887_8977_8997[] =
+		{ 0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62,
+		0x64, 0x65, 0x66, 0x68, 0x69, 0x6a
+	};
+	unsigned int reg_table_8897[] =
+		{ 0x4C, 0x50, 0x54, 0x55, 0x58, 0x59, 0x5c, 0x5d };
+	unsigned int reg_table_other[] = { 0x28, 0x30, 0x34, 0x38, 0x3c };
+	unsigned int *reg_table = NULL;
+	t_u8 reg_table_size = 0;
+	char buf[256], *ptr;
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+#define SDIO_SCRATCH_REG_8887 0x90
+#define SDIO_SCRATCH_REG_8897 0xC0
+#define SDIO_SCRATCH_REG_8977_8997 0xE8
+#define SDIO_SCRATCH_REG_OTHER 0x60
+	if (phandle->card_type == CARD_TYPE_SD8887) {
+		reg_table = reg_table_8887_8977_8997;
+		reg_table_size = sizeof(reg_table_8887_8977_8997) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8887;
+	} else if (phandle->card_type == CARD_TYPE_SD8897) {
+		reg_table = reg_table_8897;
+		reg_table_size = sizeof(reg_table_8897) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8897;
+	} else if ((phandle->card_type == CARD_TYPE_SD8977) ||
+		   (phandle->card_type == CARD_TYPE_SD8997) ||
+		   (phandle->card_type == CARD_TYPE_SD8987)) {
+		reg_table = reg_table_8887_8977_8997;
+		reg_table_size = sizeof(reg_table_8887_8977_8997) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8977_8997;
+	} else {
+		reg_table = reg_table_other;
+		reg_table_size = sizeof(reg_table_other) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_OTHER;
+	}
+
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+	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;
+			if (phandle->card_type == CARD_TYPE_SD8897) {
+				reg_start = 4;
+				reg_end = 0xB;
+			} else if ((phandle->card_type == CARD_TYPE_SD8887) ||
+				   (phandle->card_type == CARD_TYPE_SD8977) ||
+				   (phandle->card_type == CARD_TYPE_SD8997) ||
+				   (phandle->card_type == CARD_TYPE_SD8987)) {
+				reg_start = 0x10;
+				reg_end = 0x17;
+			} else {
+				reg_start = 4;
+				reg_end = 9;
+			}
+		} 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)
+				data = sdio_f0_readb(((struct sdio_mmc_card *)
+						      phandle->card)->func, reg,
+						     &ret);
+			else
+				data = sdio_readb(((struct sdio_mmc_card *)
+						   phandle->card)->func, reg,
+						  &ret);
+			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);
+	}
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+}
+
+/**
+ *  @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;
+	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;
+	}
+
+	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));
+#if defined(SDIO_SUSPEND_RESUME)
+	PRINTM(MERROR, "hs_skip_count = %u\n", phandle->hs_skip_count);
+	PRINTM(MERROR, "hs_force_count = %u\n", phandle->hs_force_count);
+#endif
+
+	if (priv) {
+		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 < (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)
+			PRINTM(MERROR, "%s: num_tx_timeout = %d\n",
+			       priv->netdev->name, priv->num_tx_timeout);
+	}
+
+#if defined(SDIO_SUSPEND_RESUME)
+	if (phandle->is_suspended == MTRUE) {
+		LEAVE();
+		return;
+	}
+#endif
+
+	/* Display SDIO registers */
+	if (flag &&
+	    ((phandle->main_state == MOAL_END_MAIN_PROCESS) ||
+	     (phandle->main_state == MOAL_STATE_IDLE))) {
+		woal_sdio_reg_dbg(phandle);
+	} else {
+		phandle->sdio_reg_dbg = MTRUE;
+		queue_work(phandle->workqueue, &phandle->main_work);
+	}
+
+	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[] = "txpower_XX.bin";
+	char file_path[256];
+	char *last_slash = 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;
+
+	/* Replace XX with ISO 3166-1 alpha-2 country code */
+	strncpy(strstr(country_name, "XX"), country, strlen(country));
+
+	memset(file_path, 0, sizeof(file_path));
+	/* file_path should be Null terminated */
+	if (fw_name && (strlen(fw_name) < sizeof(file_path))) {
+		strncpy(file_path, fw_name,
+			MIN((sizeof(file_path) - 1), strlen(fw_name)));
+		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 {
+		strncpy(file_path, "mrvl/", sizeof(file_path));
+	}
+	strncpy(file_path + strlen(file_path), country_name,
+		strlen(country_name));
+	country_txpwrlimit = file_path;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_user_init_data(handle, COUNTRY_POWER_TABLE,
+				    MOAL_IOCTL_WAIT)) {
+		PRINTM(MFATAL, "Download power table to firmware failed\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	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
+ */
+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 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)
+	moal_private *priv;
+#endif
+#endif
+	ENTER();
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return;
+	}
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	if (handle->rx_bgscan_stop) {
+		handle->rx_bgscan_stop = MFALSE;
+		priv = handle->bg_scan_priv;
+		handle->bg_scan_priv = NULL;
+		if (priv && priv->sched_scanning) {
+			cfg80211_sched_scan_stopped(priv->wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+						    , priv->bg_scan_reqid
+#endif
+				);
+			PRINTM(MEVENT, "Report sched_Scan stopped\n");
+			priv->sched_scanning = MFALSE;
+		}
+	}
+#endif
+#endif
+	mlan_rx_process(handle->pmlan_adapter, NULL);
+	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);
+#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->sdio_reg_dbg == MTRUE) {
+		handle->sdio_reg_dbg = MFALSE;
+		woal_sdio_reg_dbg(handle);
+#if defined(DEBUG_LEVEL1)
+		if (drvdbg & MFW_D) {
+			drvdbg &= ~MFW_D;
+			woal_dump_firmware_info(handle);
+		}
+#endif
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	/* Change the priority and scheduling policy of main work queue */
+	if ((wq_sched_prio != current->rt_priority) ||
+	    (wq_sched_policy != current->policy)) {
+		PRINTM(MMSG,
+		       "Set work queue priority %d and scheduling policy %d\n",
+		       wq_sched_prio, wq_sched_policy);
+		sched_setscheduler(current, wq_sched_policy, &sp);
+	}
+#endif
+
+	handle->main_state = MOAL_ENTER_WORK_QUEUE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#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;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+
+	LEAVE();
+}
+
+/**
+ * @brief Handles interrupt
+ *
+ */
+/**
+ * @param handle  A pointer to moal_handle struct
+ *
+ * @return        MLAN_STATUS_FAILURE-- when the interrupt is not for us.
+ */
+mlan_status
+woal_interrupt(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	handle->main_state = MOAL_RECV_INT;
+	PRINTM(MINTR, "*\n");
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* call mlan_interrupt to read int status */
+	mlan_interrupt(handle->pmlan_adapter);
+#ifdef SDIO_SUSPEND_RESUME
+	if (handle->is_suspended) {
+		PRINTM(MINTR, "Receive interrupt in hs_suspended\n");
+		LEAVE();
+		return ret;
+	}
+#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();
+	return ret;
+}
+
+/**
+ * @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
+ *
+ *  @return        A pointer to moal_handle structure
+ */
+moal_handle *
+woal_add_card(void *card)
+{
+	moal_handle *handle = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int netlink_num = NETLINK_MARVELL;
+	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;
+
+	/* 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 */
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
+		if (m_handle[index] == NULL)
+			break;
+	}
+	if (index < MAX_MLAN_ADAPTER) {
+		m_handle[index] = handle;
+		handle->handle_idx = index;
+	} else {
+		PRINTM(MERROR, "Exceeded maximum cards supported!\n");
+		goto err_kmalloc;
+	}
+
+	if (mac_addr
+#ifdef MFG_CMD_SUPPORT
+	    && mfg_mode != MLAN_INIT_PARA_ENABLED
+#endif
+		) {
+		t_u8 temp[20];
+		t_u8 len = strlen(mac_addr) + 1;
+		if (len < sizeof(temp)) {
+			memcpy(temp, mac_addr, len);
+			handle->set_mac_addr = 1;
+			/* note: the following function overwrites the temp buffer */
+			woal_mac2u8(handle->mac_addr, temp);
+		}
+	}
+
+	/* Update card type */
+	woal_sdio_update_card_type(handle, card);
+	/* Get card info */
+	woal_get_card_info(handle);
+	if ((handle->card_type == CARD_TYPE_SD8887) ||
+	    (handle->card_type == CARD_TYPE_SD8997) ||
+	    (handle->card_type == CARD_TYPE_SD8997))
+		handle->histogram_table_num = 3;
+	else
+		handle->histogram_table_num = 1;
+
+	((struct sdio_mmc_card *)card)->handle = handle;
+#ifdef SPI_SUPPORT
+	((struct woal_spi_card *)card)->handle = handle;
+#endif
+
+#ifdef STA_SUPPORT
+	handle->scan_pending_on_block = MFALSE;
+	MOAL_INIT_SEMAPHORE(&handle->async_sem);
+#endif
+
+	/* 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);
+
+	if (!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 (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);
+	}
+
+#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 (woal_register_dev(handle) != MLAN_STATUS_SUCCESS) {
+		PRINTM(MFATAL, "Failed to register wlan device!\n");
+		goto err_registerdev;
+	}
+#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;
+	}
+
+	if (handle->card_type == CARD_TYPE_SD8777 ||
+	    handle->card_type == CARD_TYPE_SD8887) {
+		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 SD8777/8887-FP75\n");
+		}
+	}
+	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");
+	woal_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 (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;
+	((struct sdio_mmc_card *)card)->handle = 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;
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode == MLAN_INIT_PARA_ENABLED)
+		fw_name = NULL;
+#endif
+	/* 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;
+	handle->surprise_removed = MTRUE;
+
+	flush_workqueue(handle->workqueue);
+	if (handle->rx_workqueue)
+		flush_workqueue(handle->rx_workqueue);
+
+	if (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) {
+			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");
+	}
+	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));
+	}
+#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
+#if defined(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
+	/* 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 */
+#ifdef CONFIG_PROC_FS
+	woal_proc_exit(handle);
+#endif
+	/* Unregister device */
+	PRINTM(MINFO, "unregister device\n");
+	woal_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;
+	}
+
+	/* 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");
+	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));
+	}
+
+	/* Remove interface */
+	for (i = 0; i < MIN(MLAN_MAX_BSS_NUM, 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));
+		}
+		handle->pmlan_adapter = NULL;
+	}
+
+	handle->priv_num = 0;
+	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
+
+#define FW_POLL_TRIES 100
+#define SD8897_FW_RESET_REG  0x0E8
+#define SD8887_FW_RESET_REG  0x0B6
+#define SD8977_SD8997_FW_RESET_REG  0x0EE
+#define SD8887_SD8897_FW_RESET_VAL  1
+#define SD8977_SD8997_FW_RESET_VAL  0x99
+
+/**
+ *  @brief This function reload fw
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return        0--success, otherwise failure
+ */
+static int
+woal_reset_and_reload_fw(moal_handle *handle)
+{
+	int ret = 0, tries = 0;
+	t_u32 value = 1;
+	t_u32 reset_reg = 0;
+	t_u8 reset_val = 0;
+
+	ENTER();
+	if ((handle->card_type != CARD_TYPE_SD8887)
+	    && (handle->card_type != CARD_TYPE_SD8897)
+	    && (handle->card_type != CARD_TYPE_SD8977)
+	    && (handle->card_type != CARD_TYPE_SD8997)
+	    && (handle->card_type != CARD_TYPE_SD8987)) {
+		PRINTM(MERROR, "Card type=%d, Don't support FW reload\n",
+		       handle->card_type);
+		LEAVE();
+		return -EFAULT;
+	}
+	mlan_pm_wakeup_card(handle->pmlan_adapter);
+
+	if (handle->card_type == CARD_TYPE_SD8887) {
+		reset_reg = SD8887_FW_RESET_REG;
+		reset_val = SD8887_SD8897_FW_RESET_VAL;
+	} else if (handle->card_type == CARD_TYPE_SD8897) {
+		reset_reg = SD8897_FW_RESET_REG;
+		reset_val = SD8887_SD8897_FW_RESET_VAL;
+	} else if ((handle->card_type == CARD_TYPE_SD8977) ||
+		   (handle->card_type == CARD_TYPE_SD8997) ||
+		   (handle->card_type == CARD_TYPE_SD8987)) {
+		reset_reg = SD8977_SD8997_FW_RESET_REG;
+		reset_val = SD8977_SD8997_FW_RESET_VAL;
+	}
+    /** wait SOC fully wake up */
+	for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+		ret = woal_write_reg(handle, reset_reg, 0xba);
+		if (ret == MLAN_STATUS_SUCCESS) {
+			woal_read_reg(handle, reset_reg, &value);
+			if (value == 0xba) {
+				PRINTM(MMSG, "FW wake up\n");
+				break;
+			}
+		}
+		udelay(1000);
+	}
+	/* Write register to notify FW */
+	if (woal_write_reg(handle, reset_reg, reset_val) != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to write register.\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	/* Poll register around 100 ms */
+	for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+		woal_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;
+	}
+	/* 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 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 reload fw
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param mode     FW reload mode
+ *
+ *  @return        0--success, otherwise failure
+ */
+void
+woal_request_fw_reload(moal_handle *handle, t_u8 mode)
+{
+	int intf_num;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+#if defined(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 && V14_FEATURE */
+
+	ENTER();
+
+    /** start block IOCTL */
+	handle->driver_state = MTRUE;
+	if (mode == FW_RELOAD_WITH_EMULATION) {
+		fw_reload = FW_RELOAD_WITH_EMULATION;
+		PRINTM(MMSG, "FW reload with re-emulation...\n");
+		LEAVE();
+		return;
+	}
+
+    /** detach network interface */
+	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);
+	}
+	handle->fw_reload = MTRUE;
+	woal_update_firmware_name(handle);
+	if (mode == FW_RELOAD_NO_EMULATION) {
+		ret = woal_reload_fw(handle);
+	} else if (mode == FW_RELOAD_SDIO_INBAND_RESET)
+		ret = woal_reset_and_reload_fw(handle);
+	else
+		ret = -EFAULT;
+	if (ret) {
+		PRINTM(MERROR, "FW reload fail\n");
+		goto done;
+	}
+    /** un-block IOCTL */
+	handle->fw_reload = MFALSE;
+	handle->driver_state = 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)) {
+			ret = -EFAULT;
+			kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+	handle->hardware_status = HardwareStatusReady;
+	/* Reset all interfaces */
+	ret = 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++) {
+		woal_init_priv(handle->priv[intf_num], MOAL_IOCTL_WAIT);
+#if defined(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 && V14_FEATURE */
+	}
+
+	/* 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;
+}
+
+/**
+ *  @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);
+
+#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);
+
+	/* Register with bus */
+	ret = woal_bus_register();
+	if (ret == MLAN_STATUS_SUCCESS)
+		PRINTM(MMSG, "wlan: Driver loaded successfully\n");
+	else
+		PRINTM(MMSG, "wlan: Driver loading failed\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 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 */
+
+		/* Unregister all connected radiotap net devices */
+		if (handle->mon_if) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			woal_set_net_monitor(handle->mon_if->priv,
+					     MOAL_IOCTL_WAIT, MFALSE, 0, NULL);
+			if (handle->ioctl_timeout) {
+				woal_ioctl_timeout(handle);
+				goto exit;
+			}
+#endif
+			netif_device_detach(handle->mon_if->mon_ndev);
+			if (handle->mon_if->mon_ndev->reg_state ==
+			    NETREG_REGISTERED)
+				unregister_netdev(handle->mon_if->mon_ndev);
+			handle->mon_if = NULL;
+		}
+
+		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(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(cfg80211_wext) &&
+				    handle->scan_request) {
+					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(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 (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 (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 (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;
+	}
+
+	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(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(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_crc_check, int, 0);
+MODULE_PARM_DESC(fw_crc_check,
+		 "1: Enable FW download CRC check (default); 0: Disable FW download CRC check");
+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);
+#if defined(WIFI_DIRECT_SUPPORT)
+MODULE_PARM_DESC(drv_mode,
+		 "Bit 0: STA; Bit 1: uAP; Bit 2: WIFIDIRECT; Bit 4: NAN");
+#else
+MODULE_PARM_DESC(drv_mode, "Bit 0: STA; Bit 1: uAP; Bit 4: NAN");
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+#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 */
+#if defined(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 && V14_FEATURE */
+module_param(nan_name, charp, 0);
+MODULE_PARM_DESC(nan_name, "NAN interface name");
+module_param(max_nan_bss, int, 0);
+MODULE_PARM_DESC(max_nan_bss, "Number of NAN interfaces (1)");
+#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(ps_mode, int, 0660);
+MODULE_PARM_DESC(ps_mode,
+		 "0: MLAN default; 1: Enable IEEE PS mode; 2: Disable IEEE PS mode");
+module_param(max_tx_buf, int, 0);
+MODULE_PARM_DESC(max_tx_buf, "Maximum Tx buffer size (2048/4096/8192)");
+
+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");
+
+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");
+#ifdef SDIO_SUSPEND_RESUME
+module_param(pm_keep_power, int, 0);
+MODULE_PARM_DESC(pm_keep_power, "1: PM keep power; 0: PM no power");
+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
+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,
+		 "Allow setting tx power table of country; 0: disable (default), 1: enable.");
+module_param(init_hostcmd_cfg, charp, 0);
+MODULE_PARM_DESC(init_hostcmd_cfg, "Init hostcmd file name");
+module_param(cfg80211_wext, int, 0660);
+MODULE_PARM_DESC(cfg80211_wext,
+#ifdef STA_WEXT
+		 "Bit 0: STA WEXT; "
+#endif
+#ifdef UAP_WEXT
+		 "Bit 1: UAP WEXT; "
+#endif
+#ifdef STA_CFG80211
+		 "Bit 2: STA CFG80211; "
+#endif
+#ifdef UAP_CFG80211
+		 "Bit 3: UAP CFG80211;"
+#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");
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+module_param(p2p_enh, int, 0);
+MODULE_PARM_DESC(p2p_enh, "1: Enable enhanced P2P; 0: Disable enhanced P2P");
+#endif
+#endif
+#endif
+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(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]");
+
+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(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(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
+
+module_param(drcs_chantime_mode, int, 0);
+MODULE_PARM_DESC(drcs_chantime_mode,
+		 "0: use default value;Bit31~Bit24:Channel time for channel index0;Bit23~Bit16:mode for channel index0;Bit15~Bit8:Channel time for channel index1;Bit7~Bit0:mode for channel index1; mode:0--PM1,1--Null2Self.");
+
+MODULE_DESCRIPTION("M-WLAN Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_VERSION(MLAN_RELEASE_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/wlan_sd8897/mlinux/moal_main.h b/wlan_sd8897/mlinux/moal_main.h
new file mode 100644
index 0000000..e1d75b8
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_main.h
@@ -0,0 +1,2646 @@
+/** @file moal_main.h
+  *
+  * @brief This file contains wlan driver specific defines etc.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+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
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include       <linux/config.h>
+#endif
+
+/* 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 <net/ieee80211_radiotap.h>
+
+#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
+
+#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"
+
+#ifdef OPENWRT
+#ifdef mwiphy_name
+#undef mwiphy_name
+#define mwiphy_name          "phy%d"
+#endif
+#ifdef default_mlan_name
+#undef default_mlan_name
+#define default_mlan_name "wlan%d"
+#endif
+#endif
+
+/**
+ * define write_can_lock() to fix compile issue on ACTIA platform
+ */
+#if !defined(write_can_lock) && defined(CONFIG_PREEMPT_RT_FULL)
+#define write_can_lock(X) 1
+#endif
+
+/** Define BOOLEAN */
+typedef t_u8 BOOLEAN;
+
+/** Driver version */
+extern char driver_version[];
+
+/** Private structure for MOAL */
+typedef struct _moal_private moal_private;
+/** Handle data structure for MOAL  */
+typedef struct _moal_handle moal_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 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);
+}
+
+#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;
+	memcpy(dst, 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(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 */
+#define NUM_TX_TIMEOUT_THRESHOLD      5
+
+/** Custom event : DRIVER HANG */
+#define CUS_EVT_DRIVER_HANG	            "EVENT=DRIVER_HANG"
+
+/** 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"
+
+/** 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"
+
+#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
+
+/** 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
+
+/** 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_MARVELL     (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 HIGH_RX_PENDING         100
+/** low rx pending packets */
+#define LOW_RX_PENDING          80
+
+/** MAX Tx Pending count */
+#define MAX_TX_PENDING      100
+
+/** LOW Tx Pending count */
+#define LOW_TX_PENDING      80
+
+/** 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
+
+/** 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        2
+/** Default uAP BSS */
+#define DEF_UAP_BSS        1
+#endif
+#if defined(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 && V14_FEATURE */
+/** Driver mode NAN bit */
+#define DRV_MODE_NAN              MBIT(4)
+/** Maximum NAN BSS */
+#define MAX_NAN_BSS               1
+/** Default NAN BSS */
+#define DEF_NAN_BSS               1
+
+#define DRV_MODE_WLAN            (MBIT(0)|MBIT(1)|MBIT(2)|MBIT(3)|MBIT(4))
+
+/**
+ * the maximum number of adapter supported
+ **/
+#define MAX_MLAN_ADAPTER    2
+
+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;
+
+#ifdef PROC_DEBUG
+/** Debug data */
+struct debug_data {
+    /** Name */
+	char name[32];
+    /** Size */
+	t_u32 size;
+    /** Address */
+	t_ptr addr;
+};
+
+/** 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;
+};
+#endif
+
+/** Maximum IP address buffer length */
+#define IPADDR_MAX_BUF          20
+/** IP address operation: Remove */
+#define IPADDR_OP_REMOVE        0
+
+#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;
+};
+
+/** TX status info structure */
+struct tx_status_info {
+	struct list_head link;
+    /** cookie */
+	t_u64 tx_cookie;
+    /** seq_num */
+	t_u8 tx_seq_num;
+	/**          skb */
+	void *tx_skb;
+};
+
+/** timesync packet info structure */
+
+#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;
+};
+
+/** Number of samples in histogram (/proc/mwlan/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[0];
+} hgm_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;
+	/** 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;
+#ifdef UAP_SUPPORT
+	/** uAP started or not */
+	BOOLEAN bss_started;
+    /** host based uap flag */
+	BOOLEAN uap_host_based;
+	/** tx block flag */
+	BOOLEAN uap_tx_blocked;
+#if defined(DFS_TESTING_SUPPORT)
+    /** user cac period */
+	t_u32 user_cac_period_msec;
+    /** channel under nop */
+	BOOLEAN chan_under_nop;
+#endif
+#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
+#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;
+    /** bgscan request id */
+	t_u64 bg_scan_reqid;
+#ifdef STA_CFG80211
+    /** roaming enabled flag */
+	t_u8 roaming_enabled;
+	/** 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];
+	/** key data */
+	t_u8 conn_wep_key[MAX_WEP_KEY_SIZE];
+    /** connection param */
+	struct cfg80211_connect_params sme_current;
+    /** roaming required flag */
+	t_u8 roaming_required;
+#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;
+	/** Keep connect */
+	bool keep_connect;
+    /** 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;
+    /**mobility domain value*/
+	t_u16 ft_md;
+    /**ft capability*/
+	t_u8 ft_cap;
+    /**set true during ft connection*/
+	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 */
+#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];
+#ifdef PROC_DEBUG
+    /** MLAN debug info */
+	struct debug_data_priv items_priv;
+#endif
+
+    /** tcp session queue */
+	struct list_head tcp_sess_queue;
+    /** TCP Ack enhance flag */
+	t_u8 enable_tcp_ack_enh;
+    /** 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 LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	atomic_t wmm_tx_pending[4];
+#endif
+    /** 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 */
+	hgm_data *hist_data[3];
+	BOOLEAN assoc_with_mac;
+	void *rings[RING_ID_MAX];
+	t_u8 pkt_fate_monitor_enable;
+	void *packet_filter;
+	void *nan_cb;
+};
+/** 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 V15_UPDATE*/
+	t_bool v15_update;
+	/** support V16_FW_API*/
+	t_bool v16_fw_api;
+	/** rx_rate_max for hist_data:11AC-ON:196, 11AC-OFF:76*/
+	t_u8 rx_rate_max;
+} card_info;
+
+/** channel_field.flags */
+#define CHANNEL_FLAGS_TURBO 0x0010
+#define CHANNEL_FLAGS_CCK   0x0020
+#define CHANNEL_FLAGS_OFDM  0x0040
+#define CHANNEL_FLAGS_2GHZ  0x0080
+#define CHANNEL_FLAGS_5GHZ  0x0100
+#define CHANNEL_FLAGS_ONLY_PASSIVSCAN_ALLOW  0x0200
+#define CHANNEL_FLAGS_DYNAMIC_CCK_OFDM  0x0400
+#define CHANNEL_FLAGS_GFSK  0x0800
+struct channel_field {
+	t_u16 frequency;
+	t_u16 flags;
+} __packed;
+
+/** mcs_field.known */
+#define MCS_KNOWN_BANDWIDTH   0x01
+#define MCS_KNOWN_MCS_INDEX_KNOWN  0x02
+#define MCS_KNOWN_GUARD_INTERVAL   0x04
+#define MCS_KNOWN_HT_FORMAT   0x08
+#define MCS_KNOWN_FEC_TYPE    0x10
+#define MCS_KNOWN_STBC_KNOWN  0x20
+#define MCS_KNOWN_NESS_KNOWN  0x40
+#define MCS_KNOWN_NESS_DATA   0x80
+/** bandwidth */
+#define RX_BW_20   0
+#define RX_BW_40   1
+#define RX_BW_20L  2
+#define RX_BW_20U  3
+/** mcs_field.flags
+The flags field is any combination of the following:
+0x03    bandwidth - 0: 20, 1: 40, 2: 20L, 3: 20U
+0x04    guard interval - 0: long GI, 1: short GI
+0x08    HT format - 0: mixed, 1: greenfield
+0x10    FEC type - 0: BCC, 1: LDPC
+0x60    Number of STBC streams
+0x80    Ness - bit 0 (LSB) of Number of extension spatial streams */
+struct mcs_field {
+	t_u8 known;
+	t_u8 flags;
+	t_u8 mcs;
+} __packed;
+
+/** radiotap_body.flags */
+#define RADIOTAP_FLAGS_DURING_CFG  0x01
+#define RADIOTAP_FLAGS_SHORT_PREAMBLE  0x02
+#define RADIOTAP_FLAGS_WEP_ENCRYPTION  0x04
+#define RADIOTAP_FLAGS_WITH_FRAGMENT   0x08
+#define RADIOTAP_FLAGS_INCLUDE_FCS  0x10
+#define RADIOTAP_FLAGS_PAD_BTW_HEADER_PAYLOAD  0x20
+#define RADIOTAP_FLAGS_FAILED_FCS_CHECK  0x40
+#define RADIOTAP_FLAGS_USE_SGI_HT  0x80
+struct radiotap_body {
+	t_u64 timestamp;
+	t_u8 flags;
+	t_u8 rate;
+	struct channel_field channel;
+	t_s8 antenna_signal;
+	t_s8 antenna_noise;
+	t_u8 antenna;
+	struct mcs_field mcs;
+} __packed;
+
+struct radiotap_header {
+	struct ieee80211_radiotap_header hdr;
+	struct radiotap_body body;
+} __packed;
+
+/** Monitor Band Channel Config */
+typedef struct _netmon_band_chan_cfg {
+	t_u32 band;
+	t_u32 channel;
+	t_u32 chan_bandwidth;
+} netmon_band_chan_cfg;
+
+typedef struct _monitor_iface {
+	/* The priv data of interface on which the monitor iface is based */
+	moal_private *priv;
+	struct wireless_dev wdev;
+	int radiotap_enabled;
+	/* The net_device on which the monitor iface is based. */
+	struct net_device *base_ndev;
+	struct net_device *mon_ndev;
+	char ifname[IFNAMSIZ];
+	int flag;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	struct cfg80211_chan_def chandef;
+#endif
+	/** Netmon Band Channel Config */
+	netmon_band_chan_cfg band_chan_cfg;
+	/** Monitor device statistics structure */
+	struct net_device_stats stats;
+} monitor_iface;
+
+/** 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;
+
+	/** Monitor interface */
+	monitor_iface *mon_if;
+
+	/** 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_mwlan;
+#endif
+	/** Firmware */
+	const struct firmware *firmware;
+	/** Firmware request start time */
+	struct 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;
+	/** 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__;
+#if defined(SDIO_SUSPEND_RESUME)
+	/** Device suspend flag */
+	BOOLEAN is_suspended;
+#ifdef SDIO_SUSPEND_RESUME
+	/** suspend notify flag */
+	BOOLEAN suspend_notify_req;
+#endif
+	/** 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;
+#endif
+	/** 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;
+#if defined(SDIO_SUSPEND_RESUME)
+	/** hs skip count */
+	t_u32 hs_skip_count;
+	/** hs force count */
+	t_u32 hs_force_count;
+	/** suspend_fail flag */
+	BOOLEAN suspend_fail;
+#endif
+#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;
+    /** Driver workqueue */
+	struct workqueue_struct *rx_workqueue;
+	/** main work */
+	struct work_struct rx_work;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	struct wiphy *wiphy;
+	/** Country code for regulatory domain */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+    /** band */
+	enum ieee80211_band band;
+    /** first scan done flag */
+	t_u8 first_scan_done;
+    /** scan channel gap */
+	t_u16 scan_chan_gap;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+    /** recieve bgscan stop */
+	t_u8 rx_bgscan_stop;
+    /** bg scan Private pointer */
+	moal_private *bg_scan_priv;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+    /** remain on channel flag */
+	t_u8 remain_on_channel;
+	/** bss index for remain on channel */
+	t_u8 remain_bss_index;
+	/** 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
+	/** Read SDIO registers for debugging */
+	t_u32 sdio_reg_dbg;
+	/** 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;
+    /** 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
+#ifdef DFS_TESTING_SUPPORT
+    /** cac period length, valid only when dfs testing is enabled */
+	long cac_period_jiffies;
+#endif
+    /** handle index - for multiple card supports */
+	t_u8 handle_idx;
+#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;
+#ifdef STA_CFG80211
+	/** CFG80211 scan request description */
+	struct cfg80211_scan_request *scan_request;
+#endif
+#endif
+	/** main state */
+	t_u8 main_state;
+    /** driver state */
+	t_u8 driver_state;
+    /** ioctl timeout */
+	t_u8 ioctl_timeout;
+    /** FW dump state */
+	t_u8 fw_dump;
+    /** FW dump full name */
+	t_u8 firmware_dump_file[128];
+	/** cmd52 function */
+	t_u8 cmd52_func;
+	/** cmd52 register */
+	t_u8 cmd52_reg;
+	/** cmd52 value */
+	t_u8 cmd52_val;
+#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;
+	/** Card type */
+	t_u16 card_type;
+	/** 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_u8 histogram_table_num;
+	/* feature_control */
+	t_u8 feature_control;
+	struct notifier_block woal_notifier;
+	struct net_device napi_dev;
+	struct napi_struct napi_rx;
+};
+/**
+ *  @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;
+}
+
+/* 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
+
+/** Host command DS gen structure */
+typedef struct _HostCmd_DS_GEN {
+    /** Command */
+	t_u16 command;
+    /** Size */
+	t_u16 size;
+    /** Sequence number */
+	t_u16 seq_num;
+    /** Result */
+	t_u16 result;
+} HostCmd_DS_GEN;
+
+/** Host command DS 802.11 cfg data structure */
+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;
+
+/** SD8787 card type */
+#define CARD_TYPE_SD8787   0x01
+/** SD8777 card type */
+#define CARD_TYPE_SD8777   0x02
+/** SD8887 card type */
+#define CARD_TYPE_SD8887   0x03
+/** SD8801 card type */
+#define CARD_TYPE_SD8801   0x04
+/** SD8897 card type */
+#define CARD_TYPE_SD8897   0x05
+/** SD8797 card type */
+#define CARD_TYPE_SD8797   0x06
+/** SD8977 card type */
+#define CARD_TYPE_SD8977   0x07
+/** SD8997 card type */
+#define CARD_TYPE_SD8997   0x08
+/** SD8987 card type */
+#define CARD_TYPE_SD8987   0x09
+
+/** 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);
+/**  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 interface module */
+/** Add card */
+moal_handle *woal_add_card(void *card);
+/** 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
+
+/** Interrupt handler */
+mlan_status woal_interrupt(moal_handle *handle);
+
+/** 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 drvdbg);
+#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);
+/** 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);
+#ifdef CONFIG_PROC_FS
+mlan_status woal_request_soft_reset(moal_handle *handle);
+#endif
+void woal_request_fw_reload(moal_handle *handle, t_u8 mode);
+/** 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 PROC_DEBUG
+/** 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);
+#endif
+/** 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);
+#if defined(SDIO_SUSPEND_RESUME)
+/** Enable Host Sleep configuration */
+int woal_enable_hs(moal_private *priv);
+/** hs active timeout 2 second */
+#define HS_ACTIVE_TIMEOUT  (2 * HZ)
+#endif
+/** Get wakeup reason */
+mlan_status woal_get_wakeup_reason(moal_private *priv,
+				   mlan_ds_hs_wakeup_reason *wakeup_reason);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+void woal_create_dump_dir(moal_handle *phandle, char *dir_buf, int buf_size);
+#endif
+mlan_status woal_save_dump_info_to_file(char *dir_name, char *file_name,
+					t_u8 *buf, t_u32 buf_len);
+void woal_dump_drv_info(moal_handle *phandle, t_u8 *dir_name);
+
+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);
+/* Store the FW dumps received from events in a file */
+void woal_store_firmware_dump(moal_handle *phandle, mlan_event *pmevent);
+
+/** 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);
+/** 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);
+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,
+				moal_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);
+
+#if defined(STA_SUPPORT) || defined(UAP_SUPPORT)
+/** Get statistics information */
+mlan_status woal_get_stats_info(moal_private *priv, t_u8 wait_option,
+				mlan_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
+/** 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,
+					  mlan_ds_remain_chan *pchan);
+void woal_remain_timer_func(void *context);
+
+#if defined(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 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
+
+#ifdef PROC_DEBUG
+/** Create debug proc fs */
+void woal_debug_entry(moal_private *priv);
+/** Remove debug proc fs */
+void woal_debug_remove(moal_private *priv);
+#endif /* PROC_DEBUG */
+
+/** 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 REASSOCIATION
+int woal_reassociation_thread(void *data);
+void woal_reassoc_timer_func(void *context);
+#endif /* REASSOCIATION */
+
+t_void woal_main_work_queue(struct work_struct *work);
+t_void woal_rx_work_queue(struct work_struct *work);
+
+int 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);
+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_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_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);
+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
+#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
+mlan_status woal_request_bgscan(moal_private *priv, t_u8 wait_option,
+				wlan_bgscan_cfg *scan_cfg);
+#endif
+
+void woal_flush_tcp_sess_queue(moal_private *priv);
+void woal_flush_tdls_list(moal_private *priv);
+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);
+mlan_status woal_mc_policy_cfg(moal_private *priv, t_u16 *enable,
+			       t_u8 wait_option, t_u8 action);
+void woal_check_mc_connection(moal_private *priv, t_u8 wait_option,
+			      t_u8 new_channel);
+#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_u8 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);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+mlan_status woal_set_net_monitor(moal_private *priv, t_u8 wait_option,
+				 t_u8 enable, t_u8 filter,
+				 netmon_band_chan_cfg * band_chan_cfg);
+#endif
+mlan_status woal_delba_all(moal_private *priv, t_u8 wait_option);
+
+monitor_iface *woal_prepare_mon_if(moal_private *priv,
+				   const char *name,
+				   unsigned char name_assign_type);
+
+void woal_ioctl_get_misc_conf(moal_private *priv, mlan_ds_misc_cfg *info);
+#endif /* _MOAL_MAIN_H */
diff --git a/wlan_sd8897/mlinux/moal_priv.c b/wlan_sd8897/mlinux/moal_priv.c
new file mode 100644
index 0000000..9ed9b89
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_priv.c
@@ -0,0 +1,7499 @@
+/** @file  moal_priv.c
+  *
+  * @brief This file contains standard ioctl functions
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+Change log:
+    10/30/2008: initial version
+************************************************************************/
+
+#include	"moal_main.h"
+#include	"moal_sdio.h"
+
+#include    "moal_eth_ioctl.h"
+
+/********************************************************
+			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_GN, BAND_B | BAND_G | BAND_GN, BAND_G | BAND_GN,
+	BAND_GN | BAND_GAC, BAND_B | BAND_G | BAND_GN | BAND_GAC,
+		BAND_G | BAND_GN | BAND_GAC,
+	BAND_A,
+	BAND_AN, BAND_A | BAND_AN,
+	BAND_AN | BAND_AAC, BAND_A | BAND_AN | BAND_AAC,
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+extern int cfg80211_wext;
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ * @brief Associated to a specific indexed entry in the ScanTable
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param wrq          A pointer to iwreq 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;
+	memcpy(ssid_bssid.ssid.ssid, buf + i, 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)) {
+		memcpy(&priv->prev_ssid_bssid.ssid,
+		       &bss_info.ssid, sizeof(mlan_802_11_ssid));
+		memcpy(&priv->prev_ssid_bssid.bssid,
+		       &bss_info.bssid, MLAN_MAC_ADDR_LENGTH);
+	}
+#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;
+	int intf_num;
+	moal_handle *handle = priv->phandle;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+#if defined(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 && V14_FEATURE */
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	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);
+#if defined(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 && V14_FEATURE */
+	}
+
+	/* 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;
+		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) {
+			ret = -EFAULT;
+			if (status != MLAN_STATUS_PENDING)
+				kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+
+	/* 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 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];
+	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 (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] != 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[4];
+	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;
+	t_u32 adhoc_chan_bandwidth = 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 (radio_cfg->param.band_cfg.adhoc_start_band & BAND_GN
+		    || radio_cfg->param.band_cfg.adhoc_start_band & BAND_AN
+		    || radio_cfg->param.band_cfg.adhoc_start_band & BAND_GAC
+		    || radio_cfg->param.band_cfg.adhoc_start_band & BAND_AAC) {
+			/* secondary bandwidth */
+			data[3] =
+				radio_cfg->param.band_cfg.adhoc_chan_bandwidth;
+			wrq->u.data.length = 4;
+		}
+
+		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;
+			}
+		}
+		if (user_data_len == 4) {
+			if (!(adhoc_band & (BAND_GN
+					    | BAND_GAC | BAND_AN | BAND_AAC))) {
+				PRINTM(MERROR,
+				       "11n is not enabled for adhoc, can not set HT/VHT channel bandwidth\n");
+				ret = -EINVAL;
+				goto error;
+			}
+			adhoc_chan_bandwidth = data[3];
+			if ((adhoc_chan_bandwidth != CHANNEL_BW_20MHZ) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_ABOVE) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_BELOW)
+			    && (adhoc_chan_bandwidth != CHANNEL_BW_80MHZ)
+				) {
+				PRINTM(MERROR,
+				       "Invalid secondary channel bandwidth, only allowed 0, 1, 3 or 4\n");
+				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;
+		radio_cfg->param.band_cfg.adhoc_chan_bandwidth =
+			adhoc_chan_bandwidth;
+		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 Set/Get network monitor configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_net_monitor_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int user_data_len = wrq->u.data.length;
+	int data[5] = { 0 }, copy_len;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_net_monitor *net_mon = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	copy_len = MIN(sizeof(data), sizeof(int) * user_data_len);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
+	misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (!user_data_len) {
+		req->action = MLAN_ACT_GET;
+	} else if (user_data_len == 1 || user_data_len == 2 ||
+		   user_data_len == 4 || user_data_len == 5) {
+		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] != MTRUE && data[0] != MFALSE) {
+			PRINTM(MERROR,
+			       "NET_MON: Activity should be enable(=1)/disable(=0)\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		net_mon->enable_net_mon = data[0];
+		if (data[0] == MTRUE) {
+			int i;
+			if (user_data_len != 2 && user_data_len != 4
+			    && user_data_len != 5) {
+				PRINTM(MERROR,
+				       "NET_MON: Invalid number of args!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+
+			/* Supported filter flags */
+			if (!data[1] || data[1] &
+			    ~(MLAN_NETMON_DATA | MLAN_NETMON_MANAGEMENT |
+			      MLAN_NETMON_CONTROL | MLAN_NETMON_NOPROM |
+			      MLAN_NETMON_DECRYPTED)) {
+				PRINTM(MERROR,
+				       "NET_MON: Invalid filter flag\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (user_data_len > 2) {
+				/* Supported bands */
+				for (i = 0; i < sizeof(SupportedAdhocBand); i++)
+					if (data[2] == SupportedAdhocBand[i])
+						break;
+				if (i == sizeof(SupportedAdhocBand)) {
+					PRINTM(MERROR,
+					       "NET_MON: Invalid band\n");
+					ret = -EINVAL;
+					goto done;
+				}
+			}
+			/* Supported channel */
+			if (user_data_len > 3 &&
+			    (data[3] < 1 || data[3] > MLAN_MAX_CHANNEL)) {
+				PRINTM(MERROR,
+				       "NET_MON: Invalid channel number\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (user_data_len == 5) {
+				/* Secondary channel offset */
+				if (!(data[2] & (BAND_GN | BAND_AN))) {
+					PRINTM(MERROR,
+					       "No 11n in band, can not set "
+					       "secondary channel offset\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				if ((data[4] != CHANNEL_BW_20MHZ) &&
+				    (data[4] != CHANNEL_BW_40MHZ_ABOVE) &&
+				    (data[4] != CHANNEL_BW_40MHZ_BELOW)
+				    && (data[4] != CHANNEL_BW_80MHZ)
+					) {
+					PRINTM(MERROR,
+					       "Invalid secondary channel bandwidth, "
+					       "only allowed 0, 1, 3 or 4\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				net_mon->chan_bandwidth = data[4];
+			}
+			net_mon->filter_flag = data[1];
+			net_mon->band = data[2];
+			net_mon->channel = data[3];
+		}
+		req->action = MLAN_ACT_SET;
+	} else {
+		PRINTM(MERROR, "NET_MON: Invalid number of args!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = net_mon->enable_net_mon;
+	data[1] = net_mon->filter_flag;
+	data[2] = net_mon->band;
+	data[3] = net_mon->channel;
+	data[4] = net_mon->chan_bandwidth;
+	wrq->u.data.length = 5;
+	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:
+	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 = 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 < pcfg->param.power_ext.num_pwr_grp) &&
+		       (power_ext_len < 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;
+}
+
+/**
+ *  @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;
+}
+
+/**
+ *  @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 "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;
+}
+
+/**
+ * @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;
+}
+
+/**
+ * @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 Set/Get module configuration
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_fw_wakeup_method(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data[2];
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	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;
+
+	if (wrq->u.data.length > 2) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (!wrq->u.data.length) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		if (copy_from_user
+		    (data, wrq->u.data.pointer,
+		     sizeof(int) * wrq->u.data.length)) {
+			PRINTM(MINFO, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data[0] != FW_WAKEUP_METHOD_INTERFACE &&
+		    data[0] != FW_WAKEUP_METHOD_GPIO) {
+			PRINTM(MERROR, "Invalid FW wake up method:%d\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == FW_WAKEUP_METHOD_GPIO) {
+			if (wrq->u.data.length == 1) {
+				PRINTM(MERROR,
+				       "Please provide gpio pin number for FW_WAKEUP_METHOD gpio\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			pm_cfg->param.fw_wakeup_params.gpio_pin = data[1];
+		}
+
+		pm_cfg->param.fw_wakeup_params.method = data[0];
+	}
+
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_FW_WAKEUP_METHOD;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = ((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.method;
+	data[1] =
+		((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.gpio_pin;
+
+	if (data[0] == FW_WAKEUP_METHOD_INTERFACE)
+		wrq->u.data.length = 1;
+	else
+		wrq->u.data.length = 2;
+	if (copy_to_user
+	    (wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Configure 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_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[][35] = { {"sleep clock error in ppm"},
+	{"wakeup offset in usec"},
+	{"clock stabilization time in usec"},
+	{"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");
+			LEAVE();
+			return -EINVAL;
+		}
+#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 Control Coalescing status 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_coalescing_status_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_misc_cfg *pcoal = NULL;
+	mlan_ioctl_req *req = NULL;
+	char buf[8];
+	struct iwreq *wreq = (struct iwreq *)wrq;
+	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;
+	}
+	pcoal = (mlan_ds_misc_cfg *)req->pbuf;
+
+	memset(buf, 0, sizeof(buf));
+	if (!wrq->u.data.length) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		if (copy_from_user(buf, wrq->u.data.pointer,
+				   MIN(sizeof(buf) - 1, wreq->u.data.length))) {
+			PRINTM(MINFO, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (buf[0] == 1)
+			pcoal->param.coalescing_status =
+				MLAN_MISC_COALESCING_ENABLE;
+		else
+			pcoal->param.coalescing_status =
+				MLAN_MISC_COALESCING_DISABLE;
+	}
+
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	pcoal->sub_command = MLAN_OID_MISC_COALESCING_STATUS;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	buf[0] = ((mlan_ds_misc_cfg *)req->pbuf)->param.coalescing_status;
+
+	if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
+		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 the iwreq structure
+ *
+ *  @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 the iwreq structure
+ *
+ *  @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 the iwreq structure
+ *
+ *  @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 the iwreq structure
+ *
+ *  @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      Pointer to the iwreq structure
+ *
+ *  @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 >= sizeof(buf)) {
+		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;
+	}
+
+	/* 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);
+			strncpy((char *)sec->param.passphrase.ssid.ssid, end,
+				MIN(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;
+			memcpy(sec->param.passphrase.psk.passphrase.passphrase,
+			       end,
+			       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:");
+			memcpy(buf + len, sec->param.passphrase.ssid.ssid,
+			       sec->param.passphrase.ssid.ssid_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;
+}
+
+/** AES key length */
+#define AES_KEY_LEN 16
+/**
+ *  @brief Adhoc AES control
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to the iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_adhoc_aes_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	static char buf[256];
+	int ret = 0, action = -1;
+	unsigned int i;
+	t_u8 key_ascii[32];
+	t_u8 key_hex[16];
+	t_u8 *tmp = NULL;
+	mlan_bss_info bss_info;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	int data_length = wrq->u.data.length, copy_len;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	memset(key_ascii, 0x00, sizeof(key_ascii));
+	memset(key_hex, 0x00, sizeof(key_hex));
+	memset(buf, 0x00, sizeof(buf));
+
+	/* Get current BSS information */
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (bss_info.bss_mode != MLAN_BSS_MODE_IBSS ||
+	    bss_info.media_connected == MTRUE) {
+		PRINTM(MERROR, "STA is connected or not in IBSS mode.\n");
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	copy_len = data_length;
+
+	if (data_length > 0) {
+		if (data_length >= sizeof(buf)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (copy_from_user(buf, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		if (data_length == 1) {
+			/* Get Adhoc AES 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_CFG_ENCRYPT_KEY;
+			sec->param.encrypt_key.key_len = AES_KEY_LEN;
+			sec->param.encrypt_key.key_index =
+				MLAN_KEY_INDEX_UNICAST;
+			status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				ret = -EFAULT;
+				goto done;
+			}
+
+			memcpy(key_hex, sec->param.encrypt_key.key_material,
+			       sizeof(key_hex));
+			HEXDUMP("Adhoc AES Key (HEX)", key_hex,
+				sizeof(key_hex));
+
+			wrq->u.data.length = sizeof(key_ascii) + 1;
+
+			tmp = key_ascii;
+			for (i = 0; i < sizeof(key_hex); i++)
+				tmp += sprintf((char *)tmp, "%02x", key_hex[i]);
+		} else if (data_length >= 2) {
+			/* Parse the buf to get the cmd_action */
+			action = woal_atox(buf);
+			if (action < 1 || action > 2) {
+				PRINTM(MERROR, "Invalid action argument %d\n",
+				       action);
+				ret = -EINVAL;
+				goto done;
+			}
+
+			req->req_id = MLAN_IOCTL_SEC_CFG;
+			req->action = MLAN_ACT_SET;
+			sec = (mlan_ds_sec_cfg *)req->pbuf;
+			sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+
+			if (action == 1) {
+				/* Set Adhoc AES Key  */
+				memcpy(key_ascii, &buf[2], sizeof(key_ascii));
+				woal_ascii2hex(key_hex, (char *)key_ascii,
+					       sizeof(key_hex));
+				HEXDUMP("Adhoc AES Key (HEX)", key_hex,
+					sizeof(key_hex));
+
+				sec->param.encrypt_key.key_len = AES_KEY_LEN;
+				sec->param.encrypt_key.key_index =
+					MLAN_KEY_INDEX_UNICAST;
+				sec->param.encrypt_key.key_flags =
+					KEY_FLAG_SET_TX_KEY |
+					KEY_FLAG_GROUP_KEY;
+				memcpy(sec->param.encrypt_key.mac_addr,
+				       (u8 *)bcast_addr, ETH_ALEN);
+				memcpy(sec->param.encrypt_key.key_material,
+				       key_hex, sec->param.encrypt_key.key_len);
+
+				status = woal_request_ioctl(priv, req,
+							    MOAL_IOCTL_WAIT);
+				if (status != MLAN_STATUS_SUCCESS) {
+					ret = -EFAULT;
+					goto done;
+				}
+			} else {
+				/* Clear Adhoc AES Key */
+				sec->param.encrypt_key.key_len = AES_KEY_LEN;
+				sec->param.encrypt_key.key_index =
+					MLAN_KEY_INDEX_UNICAST;
+				sec->param.encrypt_key.key_flags =
+					KEY_FLAG_REMOVE_KEY;
+				memcpy(sec->param.encrypt_key.mac_addr,
+				       (u8 *)bcast_addr, ETH_ALEN);
+				memset(sec->param.encrypt_key.key_material, 0,
+				       sizeof(sec->param.encrypt_key.
+					      key_material));
+
+				status = woal_request_ioctl(priv, req,
+							    MOAL_IOCTL_WAIT);
+				if (status != MLAN_STATUS_SUCCESS) {
+					ret = -EFAULT;
+					goto done;
+				}
+			}
+		}
+
+		HEXDUMP("Adhoc AES Key (ASCII)", key_ascii, sizeof(key_ascii));
+		wrq->u.data.length = sizeof(key_ascii);
+		if (wrq->u.data.pointer) {
+			if (copy_to_user(wrq->u.data.pointer, &key_ascii,
+					 sizeof(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 Get GTK/PTK
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to the iwreq structure
+ *
+ *  @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 MAX_TX_BF_GLOBAL_ARGS   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;
+	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 > 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 < 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 < 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 *)wrq->u.data.pointer;
+	pcurrent = (t_u8 *)prsp_info->scan_table_entry_buf;
+
+	pbuffer_end = 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 *)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)
+{
+	int ret = 0;
+	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) {
+		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 */
+	if (copy_from_user
+	    (&scan_start, wrq->u.data.pointer, sizeof(scan_start))) {
+		PRINTM(MERROR, "copy from user failed\n");
+		ret = -EFAULT;
+		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");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	/* 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);
+	}
+	handle->scan_pending_on_block = MFALSE;
+	handle->scan_priv = NULL;
+	MOAL_REL_SEMAPHORE(&handle->async_sem);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @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) {
+		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 {
+		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;
+		}
+	}
+
+	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, func, 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) */
+	func = buf[1];		/* func (0/1/2) */
+	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, func = %d, addr = %#x, mode = %d, block size = %d, block(byte) number = %d\n",
+	       func, 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 > total_len)
+			pattern_len = total_len;
+		memset(data, 0, WOAL_2K_BYTES);
+
+		/* Copy/duplicate the pattern to data buffer */
+		for (pos = 0; pos < 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;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ * @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];
+	case 5:
+		misc->param.mpa_ctrl.tx_max_ports = data[4];
+	case 4:
+		misc->param.mpa_ctrl.rx_buf_size = data[3];
+	case 3:
+		misc->param.mpa_ctrl.tx_buf_size = data[2];
+	case 2:
+		misc->param.mpa_ctrl.rx_enable = data[1];
+	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 /* SDIO_MULTI_PORT_TX_AGGR || SDIO_MULTI_PORT_RX_AGGR */
+
+/**
+ * @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 arg_len = 7;
+	int data[arg_len], 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;
+
+	ENTER();
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (data_length > arg_len) {
+		ret = -EINVAL;
+		goto done;
+	}
+	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;
+		memcpy(&scan->param.scan_cfg, data, sizeof(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 (!data_length) {
+		memcpy(data, &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 = ARRAY_SIZE(data);
+	}
+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 ad-hoc awake period parameter */
+	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] != SPECIAL_ADHOC_AWAKE_PD) &&
+		    ((data[i] < MIN_ADHOC_AWAKE_PD) ||
+		     (data[i] > MAX_ADHOC_AWAKE_PD))) {
+			PRINTM(MERROR,
+			       "Invalid argument for adhoc awake period\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		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;
+		memcpy(&pm_cfg->param.ps_cfg, data,
+		       MIN(sizeof(pm_cfg->param.ps_cfg), sizeof(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;
+	}
+	memcpy(data, &pm_cfg->param.ps_cfg,
+	       MIN((sizeof(int) * allowed), sizeof(pm_cfg->param.ps_cfg)));
+	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;
+		}
+
+		memcpy(cfg->param.addts.ie_data,
+		       addts_ioctl.ie_data, cfg->param.addts.ie_data_len);
+
+		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;
+
+		memcpy(addts_ioctl.ie_data,
+		       cfg->param.addts.ie_data, cfg->param.addts.ie_data_len);
+
+		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;
+		}
+
+		memcpy(cfg->param.delts.ie_data,
+		       delts_ioctl.ie_data, cfg->param.delts.ie_data_len);
+
+		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;
+		}
+
+		memcpy((void *)pqstats, (void *)&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));
+		memcpy((void *)&qstats_ioctl, (void *)pqstats,
+		       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));
+		memcpy((void *)&qstatus_ioctl, (void *)&pwmm->param.q_status,
+		       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));
+		memcpy((void *)&ts_status_ioctl, (void *)&pwmm->param.ts_status,
+		       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;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ *  @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] > 0xFFFF) {
+			PRINTM(MERROR, "The maximum user CAC is 65535 msec.\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 / 1000;
+		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;
+}
+#endif /* DFS_SUPPORT && DFS_TESTING_SUPPORT */
+
+/**
+ *  @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 wrq          A pointer to iwreq 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");
+			LEAVE();
+			return -EINVAL;
+		}
+
+		/* 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 || data[1] > 15)) {
+				PRINTM(MERROR,
+				       "Invalid gpio pin no (0-15 , 0xFF for default)!\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(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;
+		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;
+		case WOAL_SET_GET_WWS_CFG:
+			ret = woal_wws_cfg(priv, wrq);
+			break;
+		case WOAL_SLEEP_PD:
+			ret = woal_sleep_pd(priv, wrq);
+			break;
+		case WOAL_FW_WAKEUP_METHOD:
+			ret = woal_fw_wakeup_method(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;
+		case WOAL_COALESCING_STATUS:
+			ret = woal_coalescing_status_ioctl(priv, wrq);
+			break;
+#if defined(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;
+		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_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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+		case WOAL_SDIO_MPA_CTRL:
+			ret = woal_do_sdio_mpa_ctrl(priv, wrq);
+			break;
+#endif
+		case WOAL_SLEEP_PARAMS:
+			ret = woal_sleep_params_ioctl(priv, wrq);
+			break;
+		case WOAL_NET_MONITOR:
+			ret = woal_net_monitor_ioctl(priv, wrq);
+			break;
+#if defined(DFS_TESTING_SUPPORT)
+		case WOAL_DFS_TESTING:
+			ret = woal_dfs_testing(priv, wrq);
+			break;
+#endif
+		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_ADHOC_AES:
+			ret = woal_adhoc_aes_ioctl(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) {
+		case WOAL_CMD_53RDWR:
+			ret = woal_cmd53rdwr_ioctl(priv, wrq);
+			break;
+		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(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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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) {
+			memcpy(chan_list, &bss->param.chanlist,
+			       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_sd8897/mlinux/moal_priv.h b/wlan_sd8897/mlinux/moal_priv.h
new file mode 100644
index 0000000..8a7cc81
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_priv.h
@@ -0,0 +1,784 @@
+
+/** @file moal_priv.h
+ *
+ * @brief This file contains definition for extended private IOCTL call.
+ *
+ * Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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
+
+/** 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
+/** 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
+/** 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
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** 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 network monitor */
+#define WOAL_NET_MONITOR            30
+/** Private command ID to set/get TX BF capabilities */
+#define WOAL_TX_BF_CAP              31
+#if defined(DFS_TESTING_SUPPORT)
+/** Private command ID to set/get dfs testing settings */
+#define WOAL_DFS_TESTING            33
+#endif
+/** 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 firmware wakeup method */
+#define WOAL_FW_WAKEUP_METHOD       15
+/** 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
+/** Private command ID for coalesced status */
+#define WOAL_COALESCING_STATUS      20
+#if defined(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
+/** Private command to get/set Ad-Hoc AES */
+#define WOAL_ADHOC_AES              2
+#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              512
+
+/** 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)
+
+/** Private command ID to read/write Command 53 */
+#define WOAL_CMD_53RDWR             2
+
+/** 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
+
+/**
+ * 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"},
+	{
+	 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"},
+	{
+	 WOAL_SET_GET_WWS_CFG,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "wwscfg"},
+#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_FW_WAKEUP_METHOD,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "fwwakeupmethod"},
+	{
+	 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"},
+	{
+	 WOAL_COALESCING_STATUS,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "coalesce_status"},
+#if defined(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"},
+	{
+	 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"},
+	{
+	 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"},
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	{
+	 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_NET_MONITOR,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "netmon"},
+#if defined(DFS_TESTING_SUPPORT)
+	{
+	 WOAL_DFS_TESTING,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "dfstesting"},
+#endif
+	{
+	 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_ADHOC_AES,
+	 IW_PRIV_TYPE_CHAR | 256,
+	 IW_PRIV_TYPE_CHAR | 256,
+	 "adhocaes"},
+	{
+	 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,
+	 ""},
+	{
+	 WOAL_CMD_53RDWR,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 "sdcmd53rw"},
+	{
+	 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
+};
+
+/** 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;
+
+#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_sd8897/mlinux/moal_proc.c b/wlan_sd8897/mlinux/moal_proc.c
new file mode 100644
index 0000000..fe3cfb0
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_proc.c
@@ -0,0 +1,783 @@
+/**  @file moal_proc.c
+  *
+  * @brief This file contains functions for proc file.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#include    "moal_sdio.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+#ifdef CONFIG_PROC_FS
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+#define PROC_DIR	NULL
+#define MWLAN_PROC_DIR  "mwlan/"
+#define MWLAN_PROC  "mwlan"
+/** Proc top level directory entry */
+struct proc_dir_entry *proc_mwlan;
+int proc_dir_entry_use_count;
+#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
+
+extern int drv_mode;
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief Proc read function for info
+ *
+ *  @param sfp      pointer to seq_file structure
+ *  @param data     void pointer to 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
+
+	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
+	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);
+#if defined(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 < 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 */
+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
+}
+
+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,
+};
+
+#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;
+
+	memcpy(string, buffer + strlen("sdcmd52rw="),
+	       MIN((CMD52_STR_LEN - 1), (len - strlen("sdcmd52rw="))));
+	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;
+}
+
+/**
+ *  @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;
+
+	int func = 0, reg = 0, val = 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)drv_mode)
+			if (woal_switch_drv_mode(handle, config_data) !=
+			    MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Could not switch drv mode\n");
+			}
+	}
+	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);
+	}
+	if (!strncmp(databuf, "debug_dump", strlen("debug_dump"))) {
+		priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+		if (priv) {
+			PRINTM(MERROR, "Recevie debug_dump command\n");
+#ifdef DEBUG_LEVEL1
+			drvdbg &= ~MFW_D;
+#endif
+			woal_mlan_debug_info(priv);
+			woal_moal_debug_info(priv, NULL, MFALSE);
+
+			woal_dump_firmware_info(handle);
+		}
+	}
+
+	if (handle->card_info->v15_update) {
+		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)
+					memcpy(handle->fwdump_fname,
+					       databuf + strlen("fwdump_file="),
+					       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);
+			} else
+				config_data = FW_RELOAD_SDIO_INBAND_RESET;
+			PRINTM(MMSG, "Request fw_reload=%d\n", config_data);
+			woal_request_fw_reload(handle, config_data);
+		}
+	}
+	MODULE_PUT;
+	LEAVE();
+	return (int)count;
+}
+
+/**
+ *  @brief config proc read function
+ *
+ *  @param sfp      pointer to seq_file structure
+ *  @param data     Void pointer to data
+ *
+ *  @return         number of output data
+ */
+static int
+woal_config_read(struct seq_file *sfp, void *data)
+{
+	moal_handle *handle = (moal_handle *)sfp->private;
+
+	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)drv_mode);
+	seq_printf(sfp, "sdcmd52rw=%d 0x%0x 0x%02X\n", handle->cmd52_func,
+		   handle->cmd52_reg, handle->cmd52_val);
+
+	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
+}
+
+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,
+};
+
+/********************************************************
+		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; *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 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_DIR;
+#endif
+	char config_proc_dir[20];
+
+	ENTER();
+
+	PRINTM(MINFO, "Create Proc Interface\n");
+	if (!handle->proc_mwlan) {
+#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(MWLAN_PROC, pde->name)) {
+				/* Directory exists */
+				PRINTM(MWARN,
+				       "proc interface already exists!\n");
+				handle->proc_mwlan = pde;
+				break;
+			}
+		}
+		if (pde == NULL) {
+			handle->proc_mwlan = proc_mkdir(MWLAN_PROC, PROC_DIR);
+			if (!handle->proc_mwlan)
+				PRINTM(MERROR,
+				       "Cannot create proc interface!\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+			else
+				atomic_set(&handle->proc_mwlan->count, 1);
+#endif
+		}
+#else
+		if (!proc_mwlan) {
+			handle->proc_mwlan = proc_mkdir(MWLAN_PROC, PROC_DIR);
+			if (!handle->proc_mwlan) {
+				PRINTM(MERROR,
+				       "Cannot create proc interface!\n");
+			}
+		} else {
+			handle->proc_mwlan = proc_mwlan;
+		}
+#endif
+		if (handle->proc_mwlan) {
+			if (handle->handle_idx)
+				sprintf(config_proc_dir, "config%d",
+					handle->handle_idx);
+			else
+				strcpy(config_proc_dir, "config");
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			r = proc_create_data(config_proc_dir, 0644,
+					     handle->proc_mwlan,
+					     &config_proc_fops, handle);
+			if (r == NULL)
+#else
+			r = create_proc_entry(config_proc_dir, 0644,
+					      handle->proc_mwlan);
+			if (r) {
+				r->data = handle;
+				r->proc_fops = &config_proc_fops;
+			} else
+#endif
+				PRINTM(MMSG, "Fail to create proc config\n");
+			proc_dir_entry_use_count++;
+		}
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+		proc_mwlan = handle->proc_mwlan;
+#endif
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Remove the top level proc directory
+ *
+ *  @param handle   pointer moal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_proc_exit(moal_handle *handle)
+{
+	ENTER();
+
+	PRINTM(MINFO, "Remove Proc Interface\n");
+	if (handle->proc_mwlan) {
+		char config_proc_dir[20];
+		if (handle->handle_idx)
+			sprintf(config_proc_dir, "config%d",
+				handle->handle_idx);
+		else
+			strcpy(config_proc_dir, "config");
+		remove_proc_entry(config_proc_dir, handle->proc_mwlan);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		/* Remove only if we are the only instance using this */
+		if (atomic_read(&(handle->proc_mwlan->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_mwlan->count));
+#endif
+			if (!--proc_dir_entry_use_count) {
+				remove_proc_entry(MWLAN_PROC, PROC_DIR);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+				proc_mwlan = NULL;
+#endif
+			}
+
+			handle->proc_mwlan = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		}
+#endif
+	}
+
+	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));
+		strcpy(proc_dir_name, MWLAN_PROC_DIR);
+
+		if (strlen(dev->name) >
+		    ((sizeof(proc_dir_name) - 1) - strlen(MWLAN_PROC_DIR))) {
+			PRINTM(MERROR,
+			       "Failed to create proc entry, device name is too long\n");
+			LEAVE();
+			return;
+		}
+		strcat(proc_dir_name, dev->name);
+		/* Try to create mwlan/mlanX first */
+		priv->proc_entry = proc_mkdir(proc_dir_name, PROC_DIR);
+		if (priv->proc_entry) {
+			/* Success. Continue normally */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+			if (!priv->phandle->proc_mwlan) {
+				priv->phandle->proc_mwlan =
+					priv->proc_entry->parent;
+			}
+			atomic_inc(&(priv->phandle->proc_mwlan->count));
+#endif
+		} else {
+			/* Failure. mwlan may not exist. Try to create that first */
+			priv->phandle->proc_mwlan =
+				proc_mkdir(MWLAN_PROC, PROC_DIR);
+			if (!priv->phandle->proc_mwlan) {
+				/* Failure. Something broken */
+				LEAVE();
+				return;
+			} else {
+				/* Success. Now retry creating mlanX */
+				priv->proc_entry =
+					proc_mkdir(proc_dir_name, PROC_DIR);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+				atomic_inc(&(priv->phandle->proc_mwlan->count));
+#endif
+			}
+		}
+#else
+	if (priv->phandle->proc_mwlan && !priv->proc_entry) {
+		priv->proc_entry =
+			proc_mkdir(dev->name, priv->phandle->proc_mwlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		atomic_inc(&(priv->phandle->proc_mwlan->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);
+			if (r == NULL)
+#else
+			r = create_proc_entry("info", 0, priv->proc_entry);
+			if (r) {
+				r->data = dev;
+				r->proc_fops = &info_proc_fops;
+			} else
+#endif
+				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_mwlan && priv->proc_entry) {
+		remove_proc_entry("info", priv->proc_entry);
+		remove_proc_entry(priv->proc_entry_name,
+				  priv->phandle->proc_mwlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		atomic_dec(&(priv->phandle->proc_mwlan->count));
+#endif
+		priv->proc_entry = NULL;
+	}
+	LEAVE();
+}
+#endif
diff --git a/wlan_sd8897/mlinux/moal_sdio.h b/wlan_sd8897/mlinux/moal_sdio.h
new file mode 100644
index 0000000..865d612
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_sdio.h
@@ -0,0 +1,180 @@
+/** @file moal_sdio.h
+  *
+  * @brief This file contains definitions for SDIO interface.
+  * driver.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/****************************************************
+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
+
+#ifdef STA_SUPPORT
+/** Default firmware name */
+
+#define DEFAULT_FW_NAME_8777 "mrvl/sd8777_uapsta.bin"
+#define DEFAULT_FW_NAME_8787 "mrvl/sd8787_uapsta.bin"
+#define DEFAULT_FW_NAME_8887 "mrvl/sd8887_uapsta.bin"
+#define DEFAULT_FW_NAME_8801 "mrvl/sd8801_uapsta.bin"
+#define DEFAULT_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"
+#define DEFAULT_FW_NAME_8897 "mrvl/sd8897_uapsta.bin"
+#define DEFAULT_FW_NAME_8977 "mrvl/sdsd8977_combo.bin"
+#define SD8977_V2_FW_NAME "mrvl/sdsd8977_combo_v2.bin"
+#define SD8977_V1_FW_NAME "mrvl/sdsd8977_combo_v1.bin"
+#define SD8977_V0_FW_NAME "mrvl/sdsd8977_combo.bin"
+#define DEFAULT_FW_NAME_8997 "mrvl/sdsd8997_combo.bin"
+#define SD8997_Z_FW_NAME "mrvl/sdsd8997_combo.bin"
+#define SD8997_V2_FW_NAME "mrvl/sdsd8997_combo_v2.bin"
+#define SD8997_V3_FW_NAME "mrvl/sdsd8997_combo_v3.bin"
+#define DEFAULT_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"
+#define SD8987_FW_NAME 		 "mrvl/sdsd8987_combo.bin"
+#define DEFAULT_FW_NAME_8797 "mrvl/sd8797_uapsta.bin"
+#define SD8887_A0_FW_NAME    "mrvl/sd8887_uapsta.bin"
+#define SD8887_A2_FW_NAME    "mrvl/sd8887_uapsta_a2.bin"
+#define SD8887_WLAN_A2_FW_NAME "mrvl/sd8887_wlan_a2.bin"
+#define SD8887_WLAN_A0_FW_NAME "mrvl/sd8887_wlan.bin"
+#define SD8977_WLAN_V2_FW_NAME "mrvl/sd8977_wlan_v2.bin"
+#define SD8977_WLAN_V1_FW_NAME "mrvl/sd8977_wlan_v1.bin"
+#define SD8977_WLAN_V0_FW_NAME "mrvl/sd8977_wlan.bin"
+#define SD8997_WLAN_Z_FW_NAME "mrvl/sd8997_wlan.bin"
+#define SD8997_WLAN_V2_FW_NAME "mrvl/sd8997_wlan_v2.bin"
+#define SD8997_WLAN_V3_FW_NAME "mrvl/sd8997_wlan_v3.bin"
+#define SD8987_WLAN_FW_NAME    "mrvl/sd8987_wlan.bin"
+#ifndef DEFAULT_FW_NAME
+#define DEFAULT_FW_NAME ""
+#endif
+#endif /* STA_SUPPORT */
+
+#ifdef UAP_SUPPORT
+/** Default firmware name */
+
+#define DEFAULT_AP_FW_NAME_8777 "mrvl/sd8777_uapsta.bin"
+#define DEFAULT_AP_FW_NAME_8787 "mrvl/sd8787_uapsta.bin"
+#define DEFAULT_AP_FW_NAME_8887 "mrvl/sd8887_uapsta.bin"
+#define DEFAULT_AP_FW_NAME_8801 "mrvl/sd8801_uapsta.bin"
+#define DEFAULT_AP_FW_NAME_8897 "mrvl/sd8897_uapsta.bin"
+#define DEFAULT_AP_FW_NAME_8977 "mrvl/sdsd8977_combo.bin"
+#define DEFAULT_AP_FW_NAME_8997 "mrvl/sdsd8997_combo.bin"
+#define DEFAULT_AP_FW_NAME_8797 "mrvl/sd8797_uapsta.bin"
+#define DEFAULT_AP_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"
+#define DEFAULT_WLAN_FW_NAME_8977 "mrvl/sd8977_wlan.bin"
+#define DEFAULT_WLAN_FW_NAME_8997 "mrvl/sd8997_wlan.bin"
+#define DEFAULT_WLAN_FW_NAME_8987 "mrvl/sd8987_wlan.bin"
+#ifndef DEFAULT_AP_FW_NAME
+#define DEFAULT_AP_FW_NAME ""
+#endif
+#endif /* UAP_SUPPORT */
+
+/** Default firmaware name */
+
+#define DEFAULT_AP_STA_FW_NAME_8777 "mrvl/sd8777_uapsta.bin"
+#define DEFAULT_AP_STA_FW_NAME_8787 "mrvl/sd8787_uapsta.bin"
+#define DEFAULT_AP_STA_FW_NAME_8887 "mrvl/sd8887_uapsta.bin"
+#define DEFAULT_AP_STA_FW_NAME_8801 "mrvl/sd8801_uapsta.bin"
+#define DEFAULT_AP_STA_FW_NAME_8897 "mrvl/sd8897_uapsta.bin"
+#define DEFAULT_AP_STA_FW_NAME_8797 "mrvl/sd8797_uapsta.bin"
+#define DEFAULT_AP_STA_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"
+#define DEFAULT_AP_STA_FW_NAME_8977 "mrvl/sdsd8977_combo.bin"
+#define DEFAULT_AP_STA_FW_NAME_8997 "mrvl/sdsd8997_combo.bin"
+#define DEFAULT_AP_STA_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"
+#define DEFAULT_WLAN_FW_NAME_8977 "mrvl/sd8977_wlan.bin"
+#define DEFAULT_WLAN_FW_NAME_8997 "mrvl/sd8997_wlan.bin"
+#define DEFAULT_WLAN_FW_NAME_8987 "mrvl/sd8987_wlan.bin"
+#ifndef DEFAULT_AP_STA_FW_NAME
+#define DEFAULT_AP_STA_FW_NAME ""
+#endif
+
+/********************************************************
+		Global Functions
+********************************************************/
+/** Function to update the SDIO card type */
+t_void woal_sdio_update_card_type(moal_handle *handle, t_void *card);
+
+/** Function to write register */
+mlan_status woal_write_reg(moal_handle *handle, t_u32 reg, t_u32 data);
+/** Function to read register */
+mlan_status woal_read_reg(moal_handle *handle, t_u32 reg, t_u32 *data);
+/** Function to write data to IO memory */
+mlan_status woal_write_data_sync(moal_handle *handle, mlan_buffer *pmbuf,
+				 t_u32 port, t_u32 timeout);
+/** Function to read data from IO memory */
+mlan_status woal_read_data_sync(moal_handle *handle, mlan_buffer *pmbuf,
+				t_u32 port, t_u32 timeout);
+
+/** Register to bus driver function */
+mlan_status woal_bus_register(void);
+/** Unregister from bus driver function */
+void woal_bus_unregister(void);
+
+/** Register device function */
+mlan_status woal_register_dev(moal_handle *handle);
+/** Unregister device function */
+void woal_unregister_dev(moal_handle *handle);
+
+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 */
+
+/** 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;
+};
+
+/** 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_sd8897/mlinux/moal_sdio_mmc.c b/wlan_sd8897/mlinux/moal_sdio_mmc.c
new file mode 100644
index 0000000..8bb5318
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_sdio_mmc.c
@@ -0,0 +1,1075 @@
+/** @file moal_sdio_mmc.c
+ *
+ *  @brief This file contains SDIO MMC IF (interface) module
+ *  related functions.
+ *
+ * Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+/****************************************************
+Change log:
+	02/25/09: Initial creation -
+		  This file supports SDIO MMC only
+****************************************************/
+
+#include <linux/firmware.h>
+
+#include "moal_sdio.h"
+
+/** define marvell vendor id */
+#define MARVELL_VENDOR_ID 0x02df
+
+/* The macros below are hardware platform dependent.
+   The definition should match the actual platform */
+/** Initialize GPIO port */
+#define GPIO_PORT_INIT()
+/** Set GPIO port to high */
+#define GPIO_PORT_TO_HIGH()
+/** Set GPIO port to low */
+#define GPIO_PORT_TO_LOW()
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+extern int pm_keep_power;
+extern int shutdown_hs;
+#endif
+
+extern int disconnect_on_suspend;
+
+/** Device ID for SD8777 */
+#define SD_DEVICE_ID_8777   (0x9131)
+/** Device ID for SD8787 */
+#define SD_DEVICE_ID_8787   (0x9119)
+/** Device ID for SD8887 */
+#define SD_DEVICE_ID_8887   (0x9135)
+/** Device ID for SD8801 FN1 */
+#define SD_DEVICE_ID_8801   (0x9139)
+/** Device ID for SD8897 */
+#define SD_DEVICE_ID_8897   (0x912d)
+/** Device ID for SD8797 */
+#define SD_DEVICE_ID_8797   (0x9129)
+/** Device ID for SD8977 */
+#define SD_DEVICE_ID_8977   (0x9145)
+/** Device ID for SD8997 */
+#define SD_DEVICE_ID_8997   (0x9141)
+/** Device ID for SD8987 */
+#define SD_DEVICE_ID_8987   (0x9149)
+
+/** WLAN IDs */
+static const struct sdio_device_id wlan_ids[] = {
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8777)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8787)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8887)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8801)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8897)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8797)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8977)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8997)},
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8987)},
+	{},
+};
+
+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_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
+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
+};
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**  @brief This function dump the sdio register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @return         N/A
+ */
+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;
+	int fun1_reg_8897[] = { 0x03, 0x04, 0x05, 0x06, 0x07, 0xC0, 0xC1 };
+	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);
+	}
+
+	if (handle->card_type == CARD_TYPE_SD8897) {
+		fun1_reg = fun1_reg_8897;
+		array_size = sizeof(fun1_reg_8897) / sizeof(int);
+	} else {
+		fun1_reg = fun1_reg_other;
+		array_size = sizeof(fun1_reg_other) / sizeof(int);
+	}
+	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;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**  @brief This function updates the SDIO card types
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param card     A Pointer to card
+ *
+ *  @return         N/A
+ */
+t_void
+woal_sdio_update_card_type(moal_handle *handle, t_void *card)
+{
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)card;
+
+	/* Update card type */
+	if (cardp->func->device == SD_DEVICE_ID_8777)
+		handle->card_type = CARD_TYPE_SD8777;
+	else if (cardp->func->device == SD_DEVICE_ID_8787)
+		handle->card_type = CARD_TYPE_SD8787;
+	else if (cardp->func->device == SD_DEVICE_ID_8887)
+		handle->card_type = CARD_TYPE_SD8887;
+	else if (cardp->func->device == SD_DEVICE_ID_8801)
+		handle->card_type = CARD_TYPE_SD8801;
+	else if (cardp->func->device == SD_DEVICE_ID_8897)
+		handle->card_type = CARD_TYPE_SD8897;
+	else if (cardp->func->device == SD_DEVICE_ID_8797)
+		handle->card_type = CARD_TYPE_SD8797;
+	else if (cardp->func->device == SD_DEVICE_ID_8977)
+		handle->card_type = CARD_TYPE_SD8977;
+	else if (cardp->func->device == SD_DEVICE_ID_8997)
+		handle->card_type = CARD_TYPE_SD8997;
+	else if (cardp->func->device == SD_DEVICE_ID_8987)
+		handle->card_type = CARD_TYPE_SD8987;
+}
+
+/**
+ *  @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;
+
+	PRINTM(MINFO, "*** IN SDIO IRQ ***\n");
+	woal_interrupt(handle);
+
+	LEAVE();
+}
+
+/**  @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;
+
+	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_disable_func(func);
+		sdio_release_host(func);
+		kfree(card);
+		PRINTM(MFATAL, "sdio_enable_func() failed: ret=%d\n", ret);
+		LEAVE();
+		return -EIO;
+	}
+	sdio_release_host(func);
+	if (NULL == woal_add_card(card)) {
+		PRINTM(MERROR, "woal_add_card failed\n");
+		kfree(card);
+		sdio_claim_host(func);
+		sdio_disable_func(func);
+		sdio_release_host(func);
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	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) {
+			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
+
+#define SHUTDOWN_HOST_SLEEP_DEF_GAP      100
+#define SHUTDOWN_HOST_SLEEP_DEF_GPIO     0x3
+#define SHUTDOWN_HOST_SLEEP_DEF_COND     0x0
+
+/**  @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 timeout = 0;
+	int i, retry_num = 8;
+	moal_private *priv = NULL;
+
+	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 (shutdown_hs) {
+		priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+		if (priv)
+			priv->keep_connect = 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,
+					       "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));
+
+		timeout =
+			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);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(MERROR,
+		       "%s: cannot remain alive while host is suspended\n",
+		       sdio_func_id(func));
+		LEAVE();
+		return -ENOSYS;
+	}
+	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 == 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 (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) {
+#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;
+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);
+	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
+ */
+mlan_status
+woal_write_reg(moal_handle *handle, t_u32 reg, t_u32 data)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	sdio_writeb(((struct sdio_mmc_card *)handle->card)->func, (t_u8)data,
+		    reg, (int *)&ret);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+ */
+mlan_status
+woal_read_reg(moal_handle *handle, t_u32 reg, t_u32 *data)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 val;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	val = sdio_readb(((struct sdio_mmc_card *)handle->card)->func, reg,
+			 (int *)&ret);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	*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
+ */
+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;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+		return MLAN_STATUS_FAILURE;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+ */
+mlan_status
+woal_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
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+#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
+ */
+mlan_status
+woal_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
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+#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_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;
+	}
+
+	/* init GPIO PORT for wakeup purpose */
+	GPIO_PORT_INIT();
+	/* set default value */
+	GPIO_PORT_TO_HIGH();
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function de-registers the IF module in bus driver
+ *
+ *  @return         N/A
+ */
+void
+woal_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
+ */
+void
+woal_unregister_dev(moal_handle *handle)
+{
+	ENTER();
+	if (handle->card) {
+		/* Release the SDIO IRQ */
+		sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+		sdio_release_irq(((struct sdio_mmc_card *)handle->card)->func);
+		sdio_disable_func(((struct sdio_mmc_card *)handle->card)->func);
+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+
+		sdio_set_drvdata(((struct sdio_mmc_card *)handle->card)->func,
+				 NULL);
+
+		GPIO_PORT_TO_LOW();
+		PRINTM(MWARN, "Making the sdio dev card as NULL\n");
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function registers the device
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_register_dev(moal_handle *handle)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = handle->card;
+	struct sdio_func *func;
+
+	ENTER();
+
+	GPIO_PORT_INIT();
+	GPIO_PORT_TO_HIGH();
+
+	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);
+
+	handle->hotplug_device = &func->dev;
+
+	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;
+}
diff --git a/wlan_sd8897/mlinux/moal_shim.c b/wlan_sd8897/mlinux/moal_shim.c
new file mode 100644
index 0000000..0e14be8
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_shim.c
@@ -0,0 +1,2753 @@
+/** @file moal_shim.c
+  *
+  * @brief This file contains the callback functions registered to MLAN
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+#include	"moal_sdio.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include "moal_cfg80211.h"
+#include "moal_cfgvendor.h"
+#endif
+extern int drv_mode;
+
+/********************************************************
+		Local Variables
+********************************************************/
+/** moal_lock */
+typedef struct _moal_lock {
+	/** Lock */
+	spinlock_t lock;
+	/** Flags */
+	unsigned long flags;
+} moal_lock;
+
+/********************************************************
+		Global Variables
+********************************************************/
+extern int cfg80211_wext;
+
+extern int hw_test;
+
+#ifdef ANDROID_KERNEL
+extern int wakelock_timeout;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+extern int dfs_offload;
+#endif
+#endif
+
+/** napi support*/
+extern int napi;
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Alloc a buffer
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+	    IN t_u32 size, IN t_u32 flag, OUT t_u8 **ppbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	t_u32 mem_flag = (in_interrupt() || irqs_disabled())?
+		GFP_ATOMIC : GFP_KERNEL;
+
+	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_handle 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(IN t_void *pmoal_handle, IN t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	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_handle 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(IN t_void *pmoal_handle, IN t_u32 size, OUT t_u8 **ppbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	*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_handle 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(IN t_void *pmoal_handle, IN t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	if (!pbuf)
+		return MLAN_STATUS_FAILURE;
+	vfree(pbuf);
+	atomic_dec(&handle->vmalloc_count);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Fill memory with constant byte
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+	    IN t_void *pmem, IN t_u8 byte, IN 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_handle 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(IN t_void *pmoal_handle,
+	    IN t_void *pdest, IN const t_void *psrc, IN t_u32 num)
+{
+	t_void *p = pdest;
+
+	if (pdest && psrc && num)
+		p = memcpy(pdest, psrc, num);
+
+	return p;
+}
+
+/**
+ *  @brief Move memory from one area to another
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+	     IN t_void *pdest, IN const t_void *psrc, IN 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_handle 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(IN t_void *pmoal_handle,
+	    IN const t_void *pmem1, IN const t_void *pmem2, IN t_u32 num)
+{
+	t_s32 result;
+
+	result = memcmp(pmem1, pmem2, num);
+
+	return result;
+}
+
+/**
+ *  @brief Delay function
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param delay  delay in micro-second
+ *
+ *  @return       N/A
+ */
+t_void
+moal_udelay(IN t_void *pmoal_handle, IN t_u32 delay)
+{
+	if (delay >= 1000)
+		mdelay(delay / 1000);
+	if (delay % 1000)
+		udelay(delay % 1000);
+}
+
+/**
+ *  @brief Retrieves the current system time
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, OUT t_u32 *psec, OUT t_u32 *pusec)
+{
+	struct timeval t;
+
+	do_gettimeofday(&t);
+	*psec = (t_u32)t.tv_sec;
+	*pusec = (t_u32)t.tv_usec;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Initializes the timer
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		OUT t_void **pptimer,
+		IN t_void (*callback) (t_void *pcontext), IN t_void *pcontext)
+{
+	moal_drv_timer *timer = NULL;
+	t_u32 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_handle Pointer to the MOAL context
+ *  @param ptimer   Pointer to the timer
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_free_timer(IN t_void *pmoal_handle, IN 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_handle 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(IN t_void *pmoal_handle,
+		 IN t_void *ptimer, IN t_u8 periodic, IN 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_handle Pointer to the MOAL context
+ *  @param ptimer   Pointer to the timer
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_stop_timer(IN t_void *pmoal_handle, IN 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_handle Pointer to the MOAL context
+ *  @param pplock   Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_init_lock(IN t_void *pmoal_handle, OUT t_void **pplock)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle Pointer to the MOAL context
+ *  @param plock    Lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_free_lock(IN t_void *pmoal_handle, IN t_void *plock)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	moal_lock *mlock = plock;
+
+	kfree(mlock);
+	if (mlock)
+		atomic_dec(&handle->lock_count);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Request a spin lock
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param plock    Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_spin_lock(IN t_void *pmoal_handle, IN t_void *plock)
+{
+	moal_lock *mlock = plock;
+	unsigned long flags = 0;
+
+	if (mlock) {
+		spin_lock_irqsave(&mlock->lock, flags);
+		mlock->flags = flags;
+		return MLAN_STATUS_SUCCESS;
+	} else {
+		return MLAN_STATUS_FAILURE;
+	}
+}
+
+/**
+ *  @brief Request a spin_unlock
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param plock    Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_spin_unlock(IN t_void *pmoal_handle, IN t_void *plock)
+{
+	moal_lock *mlock = (moal_lock *)plock;
+
+	if (mlock) {
+		spin_unlock_irqrestore(&mlock->lock, mlock->flags);
+
+		return MLAN_STATUS_SUCCESS;
+	} else {
+		return MLAN_STATUS_FAILURE;
+	}
+}
+
+/**
+ *  @brief This function reads one block of firmware data from MOAL
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		 IN t_u32 offset, IN t_u32 len, OUT t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	if (!pbuf || !len)
+		return MLAN_STATUS_FAILURE;
+
+	if (offset + len > handle->firmware->size)
+		return MLAN_STATUS_FAILURE;
+
+	memcpy(pbuf, handle->firmware->data + offset, len);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN completes the initialization firmware.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN mlan_status status,
+			  IN mlan_hw_info * phw, IN pmlan_bss_tbl ptbl)
+{
+	ENTER();
+	if (status == MLAN_STATUS_SUCCESS) {
+		PRINTM(MCMND, "Get Hw Spec done, fw_cap=0x%x\n", phw->fw_cap);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN completes the initialization firmware.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	ENTER();
+	if (status == MLAN_STATUS_SUCCESS)
+		handle->hardware_status = HardwareStatusReady;
+	handle->init_wait_q_woken = MTRUE;
+	wake_up_interruptible(&handle->init_wait_q);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN shutdown firmware is completed.
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param status   The status code for mlan_shutdown request
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_shutdown_fw_complete(IN t_void *pmoal_handle, IN mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle 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(IN t_void *pmoal_handle,
+		    IN pmlan_ioctl_req pioctl_req, IN mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle 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(IN t_void *pmoal_handle,
+		       IN t_u32 size, OUT pmlan_buffer *pmbuf)
+{
+	*pmbuf = woal_alloc_mlan_buffer((moal_handle *)pmoal_handle, size);
+	if (NULL == *pmbuf)
+		return MLAN_STATUS_FAILURE;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function frees mlan_buffer.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf)
+{
+	if (!pmbuf)
+		return MLAN_STATUS_FAILURE;
+	woal_free_mlan_buffer((moal_handle *)pmoal_handle, pmbuf);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN complete send data packet.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+			  IN pmlan_buffer pmbuf, IN mlan_status status)
+{
+	moal_private *priv = NULL;
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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);
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	if (pmbuf) {
+		priv = woal_bss_index_to_priv(pmoal_handle, 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);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function write a command/data packet to card.
+ *         This function blocks the call until it finishes
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		     IN pmlan_buffer pmbuf, IN t_u32 port, IN t_u32 timeout)
+{
+	return woal_write_data_sync((moal_handle *)pmoal_handle, pmbuf, port,
+				    timeout);
+}
+
+/**
+ *  @brief This function read data packet/event/command from card.
+ *         This function blocks the call until it finish
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		    IN OUT pmlan_buffer pmbuf, IN t_u32 port, IN t_u32 timeout)
+{
+	return woal_read_data_sync((moal_handle *)pmoal_handle, pmbuf, port,
+				   timeout);
+}
+
+/**
+ *  @brief This function writes data into card register.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN t_u32 reg, IN t_u32 data)
+{
+	return woal_write_reg((moal_handle *)pmoal_handle, reg, data);
+}
+
+/**
+ *  @brief This function reads data from card register.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN t_u32 reg, OUT t_u32 *data)
+{
+	return woal_read_reg((moal_handle *)pmoal_handle, reg, data);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ *  @brief This function uploads the packet to the network stack monitor interface
+ *
+ *  @param handle Pointer to the MOAL context
+ *  @param pmbuf    Pointer to mlan_buffer
+ *
+ *  @return  MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING/MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_recv_packet_to_mon_if(IN moal_handle *handle, IN pmlan_buffer pmbuf)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	struct radiotap_header *rth = NULL;
+	radiotap_info rt_info;
+	t_u8 format = 0;
+	t_u8 bw = 0;
+	t_u8 gi = 0;
+	t_u8 ldpc = 0;
+	t_u8 chan_num;
+	t_u8 band = 0;
+	struct ieee80211_hdr *dot11_hdr = NULL;
+	t_u8 *payload = NULL;
+	ENTER();
+	if (!pmbuf->pdesc) {
+		LEAVE();
+		return status;
+	}
+
+	skb = (struct sk_buff *)pmbuf->pdesc;
+
+	if ((handle->mon_if) && netif_running(handle->mon_if->mon_ndev)) {
+		if (handle->mon_if->radiotap_enabled) {
+			if (skb_headroom(skb) < sizeof(*rth)) {
+				PRINTM(MERROR,
+				       "%s No space to add Radio TAP header\n",
+				       __func__);
+				status = MLAN_STATUS_FAILURE;
+				handle->mon_if->stats.rx_dropped++;
+				goto done;
+			}
+			dot11_hdr =
+				(struct ieee80211_hdr *)(pmbuf->pbuf +
+							 pmbuf->data_offset);
+			memcpy(&rt_info,
+			       pmbuf->pbuf + pmbuf->data_offset -
+			       sizeof(rt_info), sizeof(rt_info));
+			ldpc = (rt_info.rate_info.rate_info & 0x20) >> 5;
+			format = (rt_info.rate_info.rate_info & 0x18) >> 3;
+			bw = (rt_info.rate_info.rate_info & 0x06) >> 1;
+			gi = rt_info.rate_info.rate_info & 0x01;
+			skb_push(skb, sizeof(*rth));
+			rth = (struct radiotap_header *)skb->data;
+			memset(skb->data, 0, sizeof(*rth));
+			rth->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+			rth->hdr.it_pad = 0;
+			rth->hdr.it_len = cpu_to_le16(sizeof(*rth));
+			rth->hdr.it_present =
+				cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
+					    (1 << IEEE80211_RADIOTAP_FLAGS) |
+					    (1 << IEEE80211_RADIOTAP_CHANNEL) |
+					    (1 <<
+					     IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+					    (1 <<
+					     IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+					    (1 << IEEE80211_RADIOTAP_ANTENNA));
+			//Timstamp
+			rth->body.timestamp = cpu_to_le64(jiffies);
+			//Flags
+			rth->body.flags = (rt_info.extra_info.flags &
+					   ~(RADIOTAP_FLAGS_USE_SGI_HT |
+					     RADIOTAP_FLAGS_WITH_FRAGMENT |
+					     RADIOTAP_FLAGS_WEP_ENCRYPTION |
+					     RADIOTAP_FLAGS_FAILED_FCS_CHECK));
+			//reverse fail fcs, 1 means pass FCS in FW, but means fail FCS in radiotap
+			rth->body.flags |=
+				(~rt_info.extra_info.
+				 flags) & RADIOTAP_FLAGS_FAILED_FCS_CHECK;
+			if ((format == MLAN_RATE_FORMAT_HT) && (gi == 1))
+				rth->body.flags |= RADIOTAP_FLAGS_USE_SGI_HT;
+			if (ieee80211_is_mgmt(dot11_hdr->frame_control) ||
+			    ieee80211_is_data(dot11_hdr->frame_control)) {
+				if ((ieee80211_has_morefrags
+				     (dot11_hdr->frame_control)) ||
+				    (!ieee80211_is_first_frag
+				     (dot11_hdr->seq_ctrl))) {
+					rth->body.flags |=
+						RADIOTAP_FLAGS_WITH_FRAGMENT;
+				}
+			}
+			if (ieee80211_is_data(dot11_hdr->frame_control) &&
+			    ieee80211_has_protected(dot11_hdr->frame_control)) {
+				payload =
+					(t_u8 *)dot11_hdr +
+					ieee80211_hdrlen(dot11_hdr->
+							 frame_control);
+				if (!(*(payload + 3) & 0x20))	//ExtIV bit shall be 0 for WEP frame
+					rth->body.flags |=
+						RADIOTAP_FLAGS_WEP_ENCRYPTION;
+			}
+			//Rate, t_u8 only apply for LG mode
+			if (format == MLAN_RATE_FORMAT_LG) {
+				rth->hdr.it_present |=
+					cpu_to_le32(1 <<
+						    IEEE80211_RADIOTAP_RATE);
+				rth->body.rate = rt_info.rate_info.bitrate;
+			}
+			//Channel
+			rth->body.channel.flags = 0;
+			if (rt_info.chan_num)
+				chan_num = rt_info.chan_num;
+			else
+				chan_num =
+					handle->mon_if->band_chan_cfg.channel;
+			band = (chan_num <=
+				14) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+			rth->body.channel.frequency =
+				cpu_to_le16(ieee80211_channel_to_frequency
+					    (chan_num, band));
+			rth->body.channel.flags |=
+				cpu_to_le16((band ==
+					     IEEE80211_BAND_2GHZ) ?
+					    CHANNEL_FLAGS_2GHZ :
+					    CHANNEL_FLAGS_5GHZ);
+			if (rth->body.channel.
+			    flags & cpu_to_le16(CHANNEL_FLAGS_2GHZ))
+				rth->body.channel.flags |=
+					cpu_to_le16
+					(CHANNEL_FLAGS_DYNAMIC_CCK_OFDM);
+			else
+				rth->body.channel.flags |=
+					cpu_to_le16(CHANNEL_FLAGS_OFDM);
+			if (handle->mon_if->chandef.chan &&
+			    (handle->mon_if->chandef.chan->
+			     flags & (IEEE80211_CHAN_PASSIVE_SCAN |
+				      IEEE80211_CHAN_RADAR)))
+				rth->body.channel.flags |=
+					cpu_to_le16
+					(CHANNEL_FLAGS_ONLY_PASSIVSCAN_ALLOW);
+			//Antenna
+			rth->body.antenna_signal = -(rt_info.nf - rt_info.snr);
+			rth->body.antenna_noise = -rt_info.nf;
+			rth->body.antenna = rt_info.antenna;
+			//MCS
+			if (format == MLAN_RATE_FORMAT_HT) {
+				rth->hdr.it_present |=
+					cpu_to_le32(1 <<
+						    IEEE80211_RADIOTAP_MCS);
+				rth->body.mcs.known =
+					rt_info.extra_info.mcs_known;
+				rth->body.mcs.flags =
+					rt_info.extra_info.mcs_flags;
+				//MCS mcs
+				rth->body.mcs.known |=
+					MCS_KNOWN_MCS_INDEX_KNOWN;
+				rth->body.mcs.mcs = rt_info.rate_info.mcs_index;
+				//MCS bw
+				rth->body.mcs.known |= MCS_KNOWN_BANDWIDTH;
+				rth->body.mcs.flags &= ~(0x03);	//Clear, 20MHz as default
+				if (bw == 1)
+					rth->body.mcs.flags |= RX_BW_40;
+				//MCS gi
+				rth->body.mcs.known |= MCS_KNOWN_GUARD_INTERVAL;
+				rth->body.mcs.flags &= ~(1 << 2);
+				if (gi)
+					rth->body.mcs.flags |= gi << 2;
+				//MCS FEC
+				rth->body.mcs.known |= MCS_KNOWN_FEC_TYPE;
+				rth->body.mcs.flags &= ~(1 << 4);
+				if (ldpc)
+					rth->body.mcs.flags |= ldpc << 4;
+			}
+		}
+		skb_set_mac_header(skb, 0);
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		skb->pkt_type = PACKET_OTHERHOST;
+		skb->protocol = htons(ETH_P_802_2);
+		memset(skb->cb, 0, sizeof(skb->cb));
+		skb->dev = handle->mon_if->mon_ndev;
+
+		handle->mon_if->stats.rx_bytes += skb->len;
+		handle->mon_if->stats.rx_packets++;
+
+		if (in_interrupt())
+			netif_rx(skb);
+		else
+			netif_rx_ni(skb);
+
+		status = MLAN_STATUS_PENDING;
+	}
+
+done:
+
+	LEAVE();
+	return status;
+}
+#endif
+
+/**
+ *  @brief This function uploads the packet to the network stack
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+	struct sk_buff *skb = NULL;
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	ENTER();
+	if (pmbuf) {
+
+		priv = woal_bss_index_to_priv(pmoal_handle, pmbuf->bss_index);
+		skb = (struct sk_buff *)pmbuf->pdesc;
+		if (priv) {
+			if (skb) {
+				skb_reserve(skb, pmbuf->data_offset);
+				skb_put(skb, pmbuf->data_len);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+				if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
+					status = moal_recv_packet_to_mon_if
+						(pmoal_handle, pmbuf);
+					if (status == MLAN_STATUS_PENDING)
+						atomic_dec(&handle->
+							   mbufalloc_count);
+					goto done;
+				}
+#endif
+				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__);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		/** drop the packet without skb in monitor mode */
+				if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
+					PRINTM(MINFO,
+					       "%s Drop packet without skb\n",
+					       __func__);
+					status = MLAN_STATUS_FAILURE;
+					priv->stats.rx_dropped++;
+					goto done;
+				}
+#endif
+				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);
+				memcpy(skb->data,
+				       (t_u8 *)(pmbuf->pbuf +
+						pmbuf->data_offset),
+				       pmbuf->data_len);
+				skb_put(skb, pmbuf->data_len);
+
+			}
+			skb->dev = priv->netdev;
+			skb->protocol = eth_type_trans(skb, priv->netdev);
+			skb->ip_summed = CHECKSUM_NONE;
+
+#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 (wakelock_timeout) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+				__pm_wakeup_event(&handle->ws,
+						  wakelock_timeout);
+#else
+				wake_lock_timeout(&handle->wake_lock,
+						  wakelock_timeout);
+#endif
+			}
+#endif
+			if (in_interrupt())
+				netif_rx(skb);
+			else {
+				if (atomic_read(&handle->rx_pending) >
+				    MAX_RX_PENDING_THRHLD)
+					netif_rx(skb);
+				else
+					netif_rx_ni(skb);
+			}
+		}
+	}
+done:
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function handles event receive
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param pmevent  Pointer to the mlan event structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_recv_event(IN t_void *pmoal_handle, IN 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
+#if defined(SDIO_SUSPEND_RESUME)
+	mlan_ds_ps_info pm_info;
+#endif
+
+	ENTER();
+
+	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 (pmevent->event_id == MLAN_EVENT_ID_FW_DUMP_INFO) {
+		woal_store_firmware_dump(pmoal_handle, pmevent);
+		goto done;
+	}
+	priv = woal_bss_index_to_priv(pmoal_handle, 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;
+	}
+	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);
+			memcpy(wrqu.ap_addr.sa_data, pmevent->event_buf,
+			       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)) {
+			memcpy(priv->cfg_bssid, pmevent->event_buf, 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);
+		memcpy(pmevent->event_buf, CUS_EVT_AP_CONNECTED, 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);
+
+		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) {
+						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 (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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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_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 */
+		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);
+			if (!hw_test && priv->roaming_enabled)
+				woal_config_bgscan_and_rssi(priv, MFALSE);
+			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
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+		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 (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 (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_state = MTRUE;
+		woal_moal_debug_info(priv, NULL, MFALSE);
+		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
+		woal_process_hang(priv->phandle);
+		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;
+				woal_get_scan_table(priv, MOAL_NO_WAIT,
+						    &scan_resp);
+				PRINTM(MIOCTL,
+				       "Trigger 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,
+						  ROAMING_WAKE_LOCK_TIMEOUT);
+#endif
+#endif
+				wake_up_interruptible(&priv->phandle->
+						      reassoc_thread.wait_q);
+			}
+		}
+#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) {
+				priv->phandle->rx_bgscan_stop = MTRUE;
+				priv->phandle->bg_scan_priv = priv;
+				queue_work(priv->phandle->rx_workqueue,
+					   &priv->phandle->rx_work);
+				PRINTM(MEVENT, "Sched_Scan stopped\n");
+			}
+		}
+#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);
+				cfg80211_sched_scan_results(priv->wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+							    ,
+							    priv->bg_scan_reqid
+#endif
+					);
+				priv->last_event = 0;
+				PRINTM(MEVENT,
+				       "Reporting Sched_Scan results\n");
+			}
+		}
+#endif
+#endif
+		break;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	case MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY:
+		if (priv->phandle->is_cac_timer_set) {
+			t_u8 radar_detected = pmevent->event_buf[0];
+			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;
+		}
+		break;
+	case MLAN_EVENT_ID_FW_RADAR_DETECTED:
+		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 {
+			PRINTM(MEVENT, "radar detected during BSS active \n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			if (dfs_offload)
+				woal_cfg80211_dfs_vendor_event(priv,
+							       event_dfs_radar_detected,
+							       &priv->chan);
+			else
+#endif
+				cfg80211_radar_event(priv->wdev->wiphy,
+						     &priv->chan, GFP_KERNEL);
+		}
+		break;
+#endif
+#endif
+	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;
+#endif /* STA_SUPPORT */
+	case MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE:
+#ifdef UAP_SUPPORT
+		if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
+#ifdef UAP_CFG80211
+			chan_band_info *pchan_info =
+				(chan_band_info *) pmevent->event_buf;
+			if (IS_UAP_CFG80211(cfg80211_wext)) {
+				PRINTM(MMSG,
+				       "CSA/ECSA: Switch to new channel %d complete!\n",
+				       pchan_info->channel);
+				priv->channel = pchan_info->channel;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,12,0)
+				if (priv->csa_chan.chan &&
+				    (pchan_info->channel ==
+				     priv->csa_chan.chan->hw_value)) {
+					memcpy(&priv->chan, &priv->csa_chan,
+					       sizeof(struct
+						      cfg80211_chan_def));
+				}
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,8,0)
+				if (priv->uap_host_based) {
+					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);
+					woal_cfg80211_notify_uap_channel(priv,
+									 pchan_info);
+				}
+#endif
+			}
+#endif
+		}
+		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_handle,
+				       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_handle,
+				       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_handle,
+				       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_handle,
+				       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
+#if defined(SDIO_SUSPEND_RESUME)
+		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_interruptible(&priv->phandle->
+					      hs_activate_wait_q);
+		}
+#endif
+		break;
+	case MLAN_EVENT_ID_DRV_HS_DEACTIVATED:
+#ifdef STA_SUPPORT
+		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
+				       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_handle,
+				       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
+#if defined(SDIO_SUSPEND_RESUME)
+		priv->phandle->hs_activated = MFALSE;
+#endif
+		break;
+#ifdef UAP_SUPPORT
+	case MLAN_EVENT_ID_UAP_FW_BSS_START:
+		if (priv->hist_data)
+			woal_hist_data_reset(priv);
+		priv->bss_started = MTRUE;
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+		woal_start_queue(priv->netdev);
+		memcpy(priv->current_addr, pmevent->event_buf + 6, ETH_ALEN);
+		memcpy(priv->netdev->dev_addr, priv->current_addr, 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_handle,
+				       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 defined(DFS_TESTING_SUPPORT)
+#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
+#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)) {
+			chan_band_info *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_cfg80211_notify_uap_channel(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);
+		break;
+	case MLAN_EVENT_ID_UAP_FW_BSS_IDLE:
+		priv->media_connected = MFALSE;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+		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)
+	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);
+			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
+	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;
+			t_u8 addr[ETH_ALEN];
+
+			sinfo.filled = 0;
+			sinfo.generation = 0;
+			/* copy the station mac address */
+			memset(addr, 0xFF, ETH_ALEN);
+			memcpy(addr, pmevent->event_buf, 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
+				/* 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);
+		}
+#endif /* UAP_CFG80211 */
+		memmove((pmevent->event_buf + strlen(CUS_EVT_STA_CONNECTED) +
+			 1), pmevent->event_buf, pmevent->event_len);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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)
+			/* skip 2 bytes extra header will get the mac address */
+			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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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, 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;
+				memcpy(&bss->param.ssid_bssid,
+				       &priv->phandle->delay_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 && 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;
+				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);
+			memcpy(priv->target_ap_bssid, pmevent->event_buf,
+			       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_handle Pointer to the MOAL context
+ *  @param level    debug level
+ *  @param pformat  point to string format buf
+ *
+ *  @return         N/A
+ */
+t_void
+moal_print(IN t_void *pmoal_handle, IN t_u32 level, IN 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_handle Pointer to the MOAL context
+ *  @param bss_index    BSS index
+ *  @param level        debug level
+ *
+ *  @return            N/A
+ */
+t_void
+moal_print_netintf(IN t_void *pmoal_handle, IN t_u32 bss_index, IN t_u32 level)
+{
+#ifdef DEBUG_LEVEL1
+	moal_handle *phandle = (moal_handle *)pmoal_handle;
+
+	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_handle     A pointer to moal_private structure
+ *  @param cond             Condition to check
+ *
+ *  @return                 N/A
+ */
+t_void
+moal_assert(IN t_void *pmoal_handle, IN t_u32 cond)
+{
+	if (!cond) {
+		panic("Assert failed: Panic!");
+	}
+}
+
+/**
+ *  @brief This function save the histogram data
+ *
+ *  @param pmoal_handle     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(IN t_void *pmoal_handle, IN t_u32 bss_index, IN t_u8 rx_rate,
+		   IN t_s8 snr, IN t_s8 nflr, IN t_u8 antenna)
+{
+	moal_private *priv = NULL;
+	priv = woal_bss_index_to_priv(pmoal_handle, bss_index);
+	if (priv && antenna >= priv->phandle->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_handle     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(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			IN t_u8 *peer_addr, IN t_s8 snr, IN t_s8 nflr)
+{
+	moal_private *priv = NULL;
+	struct tdls_peer *peer = NULL;
+	unsigned long flags;
+	priv = woal_bss_index_to_priv(pmoal_handle, 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
+ */
diff --git a/wlan_sd8897/mlinux/moal_shim.h b/wlan_sd8897/mlinux/moal_shim.h
new file mode 100644
index 0000000..19ee1d0
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_shim.h
@@ -0,0 +1,109 @@
+/** @file moal_shim.h
+  *
+  * @brief This file contains declaration referring to
+  * functions defined in moal module
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change Log:
+    10/21/2008: initial version
+************************************************************/
+
+#ifndef _MOAL_H
+#define _MOAL_H
+
+mlan_status moal_get_fw_data(IN t_void *pmoal_handle,
+			     IN t_u32 offset, IN t_u32 len, OUT t_u8 *pbuf);
+mlan_status moal_get_hw_spec_complete(IN t_void *pmoal_handle,
+				      IN mlan_status status,
+				      IN mlan_hw_info * phw,
+				      IN pmlan_bss_tbl ptbl);
+mlan_status moal_init_fw_complete(IN t_void *pmoal_handle,
+				  IN mlan_status status);
+mlan_status moal_shutdown_fw_complete(IN t_void *pmoal_handle,
+				      IN mlan_status status);
+mlan_status moal_ioctl_complete(IN t_void *pmoal_handle,
+				IN pmlan_ioctl_req pioctl_req,
+				IN mlan_status status);
+mlan_status moal_alloc_mlan_buffer(IN t_void *pmoal_handle, IN t_u32 size,
+				   OUT pmlan_buffer *pmbuf);
+mlan_status moal_free_mlan_buffer(IN t_void *pmoal_handle,
+				  IN pmlan_buffer pmbuf);
+mlan_status moal_send_packet_complete(IN t_void *pmoal_handle,
+				      IN pmlan_buffer pmbuf,
+				      IN mlan_status status);
+
+/** moal_write_reg */
+mlan_status moal_write_reg(IN t_void *pmoal_handle,
+			   IN t_u32 reg, IN t_u32 data);
+/** moal_read_reg */
+mlan_status moal_read_reg(IN t_void *pmoal_handle,
+			  IN t_u32 reg, OUT t_u32 *data);
+mlan_status moal_write_data_sync(IN t_void *pmoal_handle,
+				 IN pmlan_buffer pmbuf,
+				 IN t_u32 port, IN t_u32 timeout);
+mlan_status moal_read_data_sync(IN t_void *pmoal_handle,
+				IN OUT pmlan_buffer pmbuf,
+				IN t_u32 port, IN t_u32 timeout);
+mlan_status moal_recv_packet(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf);
+mlan_status moal_recv_event(IN t_void *pmoal_handle, IN pmlan_event pmevent);
+mlan_status moal_malloc(IN t_void *pmoal_handle,
+			IN t_u32 size, IN t_u32 flag, OUT t_u8 **ppbuf);
+mlan_status moal_mfree(IN t_void *pmoal_handle, IN t_u8 *pbuf);
+mlan_status moal_vmalloc(IN t_void *pmoal_handle,
+			 IN t_u32 size, OUT t_u8 **ppbuf);
+mlan_status moal_vfree(IN t_void *pmoal_handle, IN t_u8 *pbuf);
+t_void *moal_memset(IN t_void *pmoal_handle,
+		    IN t_void *pmem, IN t_u8 byte, IN t_u32 num);
+t_void *moal_memcpy(IN t_void *pmoal_handle,
+		    IN t_void *pdest, IN const t_void *psrc, IN t_u32 num);
+t_void *moal_memmove(IN t_void *pmoal_handle,
+		     IN t_void *pdest, IN const t_void *psrc, IN t_u32 num);
+t_s32 moal_memcmp(IN t_void *pmoal_handle,
+		  IN const t_void *pmem1, IN const t_void *pmem2, IN t_u32 num);
+/** moal_udelay */
+t_void moal_udelay(IN t_void *pmoal_handle, IN t_u32 udelay);
+mlan_status moal_get_system_time(IN t_void *pmoal_handle, OUT t_u32 *psec,
+				 OUT t_u32 *pusec);
+mlan_status moal_init_lock(IN t_void *pmoal_handle, OUT t_void **pplock);
+mlan_status moal_free_lock(IN t_void *pmoal_handle, IN t_void *plock);
+mlan_status moal_spin_lock(IN t_void *pmoal_handle, IN t_void *plock);
+mlan_status moal_spin_unlock(IN t_void *pmoal_handle, IN t_void *plock);
+t_void moal_print(IN t_void *pmoal_handle, IN t_u32 level, IN char *pformat,
+		  IN ...);
+t_void moal_print_netintf(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			  IN t_u32 level);
+t_void moal_assert(IN t_void *pmoal_handle, IN t_u32 cond);
+t_void moal_hist_data_add(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			  IN t_u8 rx_rate, IN t_s8 snr, IN t_s8 nflr,
+			  IN t_u8 antenna);
+
+t_void moal_updata_peer_signal(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			       IN t_u8 *peer_addr, IN t_s8 snr, IN t_s8 nflr);
+
+mlan_status moal_init_timer(IN t_void *pmoal_handle,
+			    OUT t_void **pptimer,
+			    IN t_void (*callback) (t_void *pcontext),
+			    IN t_void *pcontext);
+mlan_status moal_free_timer(IN t_void *pmoal_handle, IN t_void *ptimer);
+mlan_status moal_start_timer(IN t_void *pmoal_handle,
+			     IN t_void *ptimer,
+			     IN t_u8 periodic, IN t_u32 msec);
+mlan_status moal_stop_timer(IN t_void *pmoal_handle, IN t_void *ptimer);
+
+#endif /*_MOAL_H */
diff --git a/wlan_sd8897/mlinux/moal_sta_cfg80211.c b/wlan_sd8897/mlinux/moal_sta_cfg80211.c
new file mode 100644
index 0000000..2eccad1
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_sta_cfg80211.c
@@ -0,0 +1,7376 @@
+/** @file moal_sta_cfg80211.c
+  *
+  * @brief This file contains the functions for STA CFG80211.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include "moal_cfg80211.h"
+#include "moal_cfgvendor.h"
+#include "moal_sta_cfg80211.h"
+#include "moal_eth_ioctl.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+
+extern int cfg80211_wext;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+
+extern int cntry_txpwr;
+
+/* Supported crypto cipher suits to be advertised to cfg80211 */
+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(3, 8, 0)
+static int woal_cfg80211_set_monitor_channel(struct wiphy *wiphy,
+					     struct cfg80211_chan_def *chandef);
+#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 t_u8 *mac,
+#else
+				     t_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
+
+static int woal_cfg80211_join_ibss(struct wiphy *wiphy,
+				   struct net_device *dev,
+				   struct cfg80211_ibss_params *params);
+
+static int woal_cfg80211_leave_ibss(struct wiphy *wiphy,
+				    struct net_device *dev);
+
+#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 */
+
+#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);
+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);
+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);
+#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,10,0)
+int woal_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev,
+				struct cfg80211_update_ft_ies_params *ftie);
+#endif
+/** 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,
+	.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
+	.join_ibss = woal_cfg80211_join_ibss,
+	.leave_ibss = woal_cfg80211_leave_ibss,
+	.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
+	.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,
+	.add_station = woal_cfg80211_add_station,
+	.change_station = woal_cfg80211_change_station,
+#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,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
+		.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
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+		.mgmt_frame_register =
+		woal_cfg80211_mgmt_frame_register,.mgmt_tx =
+		woal_cfg80211_mgmt_tx,
+#endif
+#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
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		.set_monitor_channel = woal_cfg80211_set_monitor_channel,
+#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),}
+};
+
+/********************************************************
+				Local Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static const struct ieee80211_txrx_stypes
+ ieee80211_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+	[NL80211_IFTYPE_ADHOC] = {
+				  .tx = BIT(IEEE80211_STYPE_ACTION >> 4),
+				  .rx = BIT(IEEE80211_STYPE_ACTION >> 4),
+				  },
+	[NL80211_IFTYPE_STATION] = {
+				    .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				    BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				    .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				    BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+				    },
+	[NL80211_IFTYPE_AP] = {
+			       .tx = 0xffff,
+			       .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+			       BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+			       BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+			       BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+			       BIT(IEEE80211_STYPE_AUTH >> 4) |
+			       BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+			       BIT(IEEE80211_STYPE_ACTION >> 4),
+			       },
+	[NL80211_IFTYPE_AP_VLAN] = {
+				    .tx = 0x0000,
+				    .rx = 0x0000,
+				    },
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	[NL80211_IFTYPE_P2P_CLIENT] = {
+				       .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				       BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				       .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				       BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+				       },
+	[NL80211_IFTYPE_P2P_GO] = {
+				   .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				   BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				   .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+				   BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+				   BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+				   BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+				   BIT(IEEE80211_STYPE_AUTH >> 4) |
+				   BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+				   BIT(IEEE80211_STYPE_ACTION >> 4),
+				   },
+#endif
+#endif
+	[NL80211_IFTYPE_MESH_POINT] = {
+				       .tx = 0x0000,
+				       .rx = 0x0000,
+				       },
+
+};
+#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) | MBIT(NL80211_IFTYPE_MONITOR) |
+#endif
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	 MBIT(NL80211_IFTYPE_P2P_GO) | MBIT(NL80211_IFTYPE_P2P_CLIENT) |
+#endif
+#endif
+	 MBIT(NL80211_IFTYPE_ADHOC)
+	 }
+};
+
+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 moal_handle *m_handle[];
+extern int hw_test;
+extern int ps_mode;
+/** Region alpha2 string */
+char *reg_alpha2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+int country_ie_ignore = 0;
+int beacon_hints = 0;
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+extern int p2p_enh;
+#endif
+#endif
+
+int cfg80211_drcs = 0;
+
+#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,
+};
+#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
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int
+woal_cfg80211_set_monitor_channel(struct wiphy *wiphy,
+				  struct cfg80211_chan_def *chandef)
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv =
+		(moal_private *)woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+	netmon_band_chan_cfg band_chan_cfg;
+	t_u32 bandwidth = 0;
+	int ret = -EFAULT;
+
+	ENTER();
+
+	if (handle->mon_if) {
+		if (cfg80211_chandef_identical
+		    (&handle->mon_if->chandef, chandef)) {
+			ret = 0;
+			goto done;
+		}
+		if (woal_is_any_interface_active(handle)) {
+			PRINTM(MERROR,
+			       "Cannot change monitor channel for an active"
+			       " interface\n");
+			goto done;
+		}
+		memset(&band_chan_cfg, 0x00, sizeof(band_chan_cfg));
+		/* Set channel */
+		band_chan_cfg.channel =
+			ieee80211_frequency_to_channel(chandef->chan->
+						       center_freq);
+		/* Set band */
+		if (chandef->chan->band == IEEE80211_BAND_2GHZ)
+			band_chan_cfg.band |= (BAND_B | BAND_G);
+		if (chandef->chan->band == IEEE80211_BAND_5GHZ)
+			band_chan_cfg.band |= BAND_A;
+		if (chandef->chan->band == IEEE80211_BAND_2GHZ)
+			band_chan_cfg.band |= BAND_GN;
+		if (chandef->chan->band == IEEE80211_BAND_5GHZ)
+			band_chan_cfg.band |= BAND_AN;
+		if (chandef->chan->band == IEEE80211_BAND_2GHZ)
+			band_chan_cfg.band |= BAND_GAC;
+		if (chandef->chan->band == IEEE80211_BAND_5GHZ)
+			band_chan_cfg.band |= BAND_AAC;
+		/* Set bandwidth */
+		if (chandef->width == NL80211_CHAN_WIDTH_20)
+			bandwidth = CHANNEL_BW_20MHZ;
+		else if (chandef->width == NL80211_CHAN_WIDTH_40)
+			bandwidth =
+				chandef->center_freq1 >
+				chandef->chan->
+				center_freq ? CHANNEL_BW_40MHZ_ABOVE :
+				CHANNEL_BW_40MHZ_BELOW;
+		else if (chandef->width == NL80211_CHAN_WIDTH_80)
+			bandwidth = CHANNEL_BW_80MHZ;
+		band_chan_cfg.chan_bandwidth = bandwidth;
+
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_net_monitor(priv, MOAL_IOCTL_WAIT, MTRUE, 0x7,
+					 &band_chan_cfg)) {
+			PRINTM(MERROR, "%s: woal_set_net_monitor fail\n",
+			       __func__);
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memcpy(&handle->mon_if->band_chan_cfg, &band_chan_cfg,
+		       sizeof(handle->mon_if->band_chan_cfg));
+		handle->mon_if->chandef = *chandef;
+
+		if (handle->mon_if->chandef.chan)
+			PRINTM(MINFO,
+			       "set_monitor_channel+++ chan[band=%d center_freq=%d hw_value=%d] width=%d center_freq1=%d center_freq2=%d\n",
+			       handle->mon_if->chandef.chan->band,
+			       handle->mon_if->chandef.chan->center_freq,
+			       handle->mon_if->chandef.chan->hw_value,
+			       handle->mon_if->chandef.width,
+			       handle->mon_if->chandef.center_freq1,
+			       handle->mon_if->chandef.center_freq2);
+		PRINTM(MINFO,
+		       "set_monitor_channel+++ band=%x channel=%d bandwidth=%d\n",
+		       handle->mon_if->band_chan_cfg.band,
+		       handle->mon_if->band_chan_cfg.channel,
+		       handle->mon_if->band_chan_cfg.chan_bandwidth);
+		ret = 0;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function check cfg80211 special region code.
+ *
+ *  @param region_string         Region string
+ *
+ *  @return     MTRUE/MFALSE
+ */
+t_u8
+is_cfg80211_special_region_code(char *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;
+	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 NL802.11 channel type into driver channel type
+ *
+ * The mapping is as follows -
+ *      NL80211_CHAN_NO_HT     -> CHANNEL_BW_20MHZ
+ *      NL80211_CHAN_HT20      -> CHANNEL_BW_20MHZ
+ *      NL80211_CHAN_HT40PLUS  -> CHANNEL_BW_40MHZ_ABOVE
+ *      NL80211_CHAN_HT40MINUS -> CHANNEL_BW_40MHZ_BELOW
+ *      Others                 -> CHANNEL_BW_20MHZ
+ *
+ *  @param channel_type     Channel type
+ *
+ *  @return                 Driver channel type
+ */
+static int
+woal_cfg80211_channel_type_to_channel(enum nl80211_channel_type channel_type)
+{
+	int channel;
+
+	ENTER();
+
+	switch (channel_type) {
+	case NL80211_CHAN_NO_HT:
+	case NL80211_CHAN_HT20:
+		channel = CHANNEL_BW_20MHZ;
+		break;
+	case NL80211_CHAN_HT40PLUS:
+		channel = CHANNEL_BW_40MHZ_ABOVE;
+		break;
+	case NL80211_CHAN_HT40MINUS:
+		channel = CHANNEL_BW_40MHZ_BELOW;
+		break;
+	default:
+		channel = CHANNEL_BW_20MHZ;
+	}
+	LEAVE();
+	return channel;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ *  @brief get nl80211_channel_type from cfg80211_chan_def
+ *
+ *  @param chan_def     struct cfg80211_chan_def
+ *
+ *  @return                 nl80211_channel_type type
+ */
+static enum nl80211_channel_type
+woal_channel_to_nl80211_channel_type(struct cfg80211_chan_def *chan_def)
+{
+	enum nl80211_channel_type channel_type = 0;
+
+	ENTER();
+
+	switch (chan_def->width) {
+	case NL80211_CHAN_WIDTH_20:
+		/** Channel width 20MHz**/
+		channel_type = NL80211_CHAN_HT20;
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		/** Channel width 40MHz**/
+		if (chan_def->center_freq1 < chan_def->chan->center_freq)
+			channel_type = NL80211_CHAN_HT40MINUS;
+		else if (chan_def->center_freq1 > chan_def->chan->center_freq)
+			channel_type = NL80211_CHAN_HT40PLUS;
+		break;
+	default:
+		channel_type = NL80211_CHAN_HT20;
+		break;
+	}
+	LEAVE();
+	return channel_type;
+}
+#endif
+
+/**
+ *  @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_ADHOC:
+		return MLAN_BSS_MODE_IBSS;
+	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(hs20_oui))) {
+				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;
+		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;
+}
+
+/**
+ * @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;
+	}
+
+	if (MTRUE ==
+	    is_cfg80211_special_region_code(priv->phandle->country_code)) {
+		PRINTM(MIOCTL,
+		       "skip region code config, cfg80211 special region code: %s\n",
+		       priv->phandle->country_code);
+		goto done;
+	}
+	PRINTM(MIOCTL, "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;
+
+	/* 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;
+
+	/* 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;
+	int chan_width = 0;
+
+	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;
+	chan_width = woal_cfg80211_channel_type_to_channel(channel_type);
+	/* 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);
+	}
+	/* Set channel offset */
+	radio_cfg->param.band_cfg.adhoc_chan_bandwidth = chan_width;
+
+	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, channel bandwidth %d and mode = %d channel=%d\n",
+	       config_bands, radio_cfg->param.band_cfg.adhoc_chan_bandwidth,
+	       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
+ */
+mlan_status
+woal_set_ewpa_mode(moal_private *priv, t_u8 wait_option,
+		   mlan_ssid_bssid *ssid_bssid)
+{
+	int ret = 0;
+	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) {
+		ret = -EOPNOTSUPP;
+		goto error;
+	}
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		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));
+	memcpy(&sec->param.passphrase.ssid, &ssid_bssid->ssid,
+	       sizeof(sec->param.passphrase.ssid));
+	memcpy(&sec->param.passphrase.bssid, &ssid_bssid->bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+	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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	struct timespec tstamp;
+#endif
+	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 < 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 CFG80211_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. */
+			get_monotonic_boottime(&tstamp);
+			ts = (t_u64)tstamp.tv_sec * 1000000 +
+				tstamp.tv_nsec / 1000;
+#else
+			memcpy(&ts, scan_table[i].time_stamp, sizeof(ts));
+#endif
+			memcpy(&cap_info, &scan_table[i].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;
+
+	memcpy(&ie_buf[sizeof(IEEEtypes_Header_t)],
+	       &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
+	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();
+	country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
+	if (!country_ie) {
+		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) {
+		PRINTM(MIOCTL, "Wrong Country IE length!\n");
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		LEAVE();
+		return 0;
+	}
+	PRINTM(MIOCTL, "Find bss country IE: %c%c band=%d\n", country_ie[2],
+	       country_ie[3], priv->phandle->band);
+	priv->phandle->country_code[0] = country_ie[2];
+	priv->phandle->country_code[1] = country_ie[3];
+	priv->phandle->country_code[2] = ' ';
+	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) {
+		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)));
+	memcpy((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));
+
+	/* 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
+ */
+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));
+	memcpy(scan_req.ssid_list[0].ssid, conn_param->ssid,
+	       conn_param->ssid_len);
+	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 |
+			     IEEE80211_CHAN_RADAR))
+			scan_req.chan_list[0].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE;
+		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 |
+					     IEEE80211_CHAN_RADAR))
+					scan_req.chan_list[chan_idx].scan_type =
+						MLAN_SCAN_TYPE_PASSIVE;
+				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++;
+			}
+		}
+	}
+	ret = woal_request_userscan(priv, wait_option, &scan_req);
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+	LEAVE();
+	return ret;
+
+}
+
+/**
+ * @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
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_assoc(moal_private *priv, void *sme, t_u8 wait_option)
+{
+	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;
+	enum nl80211_channel_type chan_type = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	struct cfg80211_chan_def *chan_def = NULL;
+#endif
+	struct ieee80211_channel *channel = NULL;
+	t_u16 beacon_interval = 0;
+	bool privacy;
+	struct cfg80211_bss *bss = 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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+		chan_type = ibss_param->channel_type;
+#else
+		chan_type = 0;
+#endif
+#else
+		chan_def = &ibss_param->chandef;
+		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;
+		bss = cfg80211_get_bss(priv->wdev->wiphy, channel, bssid, ssid,
+				       ssid_len, WLAN_CAPABILITY_ESS,
+				       WLAN_CAPABILITY_ESS);
+		if (bss) {
+			if (!reg_alpha2 ||
+			    strncmp(reg_alpha2, "99", strlen("99")))
+				woal_process_country_ie(priv, bss);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+			cfg80211_put_bss(priv->wdev->wiphy, bss);
+#else
+			cfg80211_put_bss(bss);
+#endif
+		} else
+			woal_send_domain_info_cmd_fw(priv, wait_option);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(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;
+	}
+
+	memcpy(req_ssid.ssid, ssid, ssid_len);
+	if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
+		PRINTM(MERROR, "Invalid SSID - aborting\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if ((mode == MLAN_BSS_MODE_IBSS) && channel) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		chan_type = woal_channel_to_nl80211_channel_type(chan_def);
+#endif
+		if (MLAN_STATUS_SUCCESS != woal_set_rf_channel(priv,
+							       channel,
+							       chan_type,
+							       wait_option)) {
+			ret = -EFAULT;
+			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(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;
+		}
+	}
+	memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(mlan_802_11_ssid));
+	if (bssid)
+		memcpy(&ssid_bssid.bssid, bssid, ETH_ALEN);
+	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;
+		PRINTM(MCMND, "channel flags=0x%x\n", channel->flags);
+	}
+	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;
+		}
+	}
+
+done:
+	if (ret) {
+		/* clear the encryption mode */
+		woal_cfg80211_set_auth(priv, MLAN_ENCRYPTION_MODE_NONE, MFALSE,
+				       wait_option);
+		/* 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 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;
+	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
+	};
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	mlan_bss_info bss_info;
+	t_u8 dtim_period = 0;
+#endif
+
+	ENTER();
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	sinfo->filled =
+		BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES)
+		| BIT(NL80211_STA_INFO_RX_PACKETS) |
+		BIT(NL80211_STA_INFO_TX_PACKETS) | BIT(NL80211_STA_INFO_SIGNAL)
+		| BIT(NL80211_STA_INFO_TX_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 |= BIT(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;
+	}
+
+	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 (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;
+	}
+	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 |= BIT(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
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	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)
+{
+	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 (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", dfs_offload);
+}
+#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];
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+	int ret = 0;
+#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(MIOCTL, "cfg80211 regulatory domain callback "
+	       "%c%c\n", request->alpha2[0], request->alpha2[1]);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (dfs_offload)
+		woal_update_radar_chans_dfs_state(wiphy);
+#endif
+	memset(region, 0, sizeof(region));
+	memcpy(region, request->alpha2, sizeof(request->alpha2));
+	region[2] = ' ';
+	if (MTRUE == is_cfg80211_special_region_code(region)) {
+		PRINTM(MIOCTL, "Skip configure special region code\n");
+		LEAVE();
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+		return ret;
+#else
+		return;
+#endif
+	}
+	if ((handle->country_code[0] != request->alpha2[0]) ||
+	    (handle->country_code[1] != request->alpha2[1])) {
+		t_u8 country_code[COUNTRY_CODE_LEN];
+		memset(country_code, 0, sizeof(country_code));
+		country_code[0] = request->alpha2[0];
+		country_code[1] = request->alpha2[1];
+		if (cntry_txpwr) {
+			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
+			}
+		}
+	}
+	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(MIOCTL, "Regulatory domain BY_DRIVER\n");
+		break;
+	case NL80211_REGDOM_SET_BY_CORE:
+		PRINTM(MIOCTL, "Regulatory domain BY_CORE\n");
+		break;
+	case NL80211_REGDOM_SET_BY_USER:
+		PRINTM(MIOCTL, "Regulatory domain BY_USER\n");
+		break;
+		/* TODO: apply driver specific changes in channel flags based
+		   on the request initiator if necessory. * */
+	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+		PRINTM(MIOCTL, "Regulatory domain BY_COUNTRY_IE\n");
+		break;
+	}
+	if (priv->wdev && priv->wdev->wiphy &&
+	    (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE))
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+
+	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_IOCTL_WAIT or MOAL_NO_WAIT)
+ * @param bss_role      bss role
+ *
+ * @return         0 --success, otherwise fail
+ */
+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 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_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;
+
+	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);
+#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);
+	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;
+}
+
+/**
+ *  @brief check if the scan result expired
+ *
+ *  @param priv         A pointer to moal_private
+ *
+ *
+ *  @return             MTRUE/MFALSE;
+ */
+t_u8
+woal_is_scan_result_expired(moal_private *priv)
+{
+	mlan_scan_resp scan_resp;
+	struct timeval t;
+	ENTER();
+	if (!woal_is_any_interface_active(priv->phandle)) {
+		LEAVE();
+		return MTRUE;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
+		LEAVE();
+		return MTRUE;
+	}
+	do_gettimeofday(&t);
+/** scan result expired value */
+#define SCAN_RESULT_EXPIRTED      1
+	if (t.tv_sec > (scan_resp.age_in_secs + SCAN_RESULT_EXPIRTED)) {
+		LEAVE();
+		return MTRUE;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+#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;
+	mlan_bss_info bss_info;
+	struct ieee80211_channel *chan;
+	int ret = 0, i;
+	unsigned long flags;
+
+	ENTER();
+
+	PRINTM(MINFO, "Received scan request on %s\n", dev->name);
+	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
+	if (priv->fake_scan_complete || !woal_is_scan_result_expired(priv)) {
+		PRINTM(MEVENT, "Reporting fake scan results\n");
+		woal_inform_bss_from_scan_result(priv, NULL, MOAL_IOCTL_WAIT);
+		woal_cfg80211_scan_done(request, MFALSE);
+		return ret;
+	}
+	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");
+			woal_inform_bss_from_scan_result(priv, NULL,
+							 MOAL_IOCTL_WAIT);
+			woal_cfg80211_scan_done(request, MFALSE);
+			return ret;
+		}
+	}
+	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);
+	memset(&scan_req, 0x00, sizeof(scan_req));
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+	if (!is_broadcast_ether_addr(request->bssid)) {
+		memcpy(scan_req.specific_bssid, request->bssid, ETH_ALEN);
+		PRINTM(MIOCTL, "scan: bssid=" MACSTR "\n",
+		       MAC2STR(scan_req.specific_bssid));
+	}
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->phandle->miracast_mode ||
+	    woal_is_any_interface_active(priv->phandle))
+		scan_req.scan_chan_gap = priv->phandle->scan_chan_gap;
+	else
+		scan_req.scan_chan_gap = 0;
+#endif
+	for (i = 0; i < priv->phandle->scan_request->n_ssids; i++) {
+		memcpy(scan_req.ssid_list[i].ssid,
+		       priv->phandle->scan_request->ssids[i].ssid,
+		       priv->phandle->scan_request->ssids[i].ssid_len);
+		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 < 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 |
+			      IEEE80211_CHAN_RADAR))
+		    || !priv->phandle->scan_request->n_ssids)
+			scan_req.chan_list[i].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE;
+		else
+			scan_req.chan_list[i].scan_type = MLAN_SCAN_TYPE_ACTIVE;
+#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))
+			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)
+			scan_req.chan_list[i].scan_time =
+				MIN_SPECIFIC_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) {
+			LEAVE();
+			return ret;
+		} else {
+			PRINTM(MERROR, "Uap SCAN failure\n");
+			goto done;
+		}
+	}
+#endif
+	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);
+	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 */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset, &pkt_type, sizeof(pkt_type));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type), &tx_control,
+	       sizeof(tx_control));
+	/*Add packet len */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &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 = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_ACTION);
+	memcpy(mgmt->da, bssid, ETH_ALEN);
+	memcpy(mgmt->sa, priv->current_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, bssid, ETH_ALEN);
+	memcpy(mgmt->addr4, addr, ETH_ALEN);
+
+	mgmt->u.ft_req.category = 0x06;	/**ft action code 0x6*/
+	mgmt->u.ft_req.action = 0x1; /**ft action request*/
+	memcpy(mgmt->u.ft_req.sta_addr, priv->current_addr, ETH_ALEN);
+	memcpy(mgmt->u.ft_req.target_ap_addr, target_ap, ETH_ALEN);
+
+	if (ie && len)
+		memcpy((t_u8 *)(&mgmt->u.ft_req.variable), 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;
+
+	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 */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset, &pkt_type, sizeof(pkt_type));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type), &tx_control,
+	       sizeof(tx_control));
+	/*Add packet len */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &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 = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_AUTH);
+	memcpy(mgmt->da, bssid, ETH_ALEN);
+	memcpy(mgmt->sa, priv->current_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, bssid, ETH_ALEN);
+	memcpy(mgmt->addr4, addr, ETH_ALEN);
+
+	mgmt->u.auth.auth_alg = cpu_to_le16(WLAN_AUTH_FT);
+	mgmt->u.auth.auth_transaction = cpu_to_le16(1);
+	mgmt->u.auth.status_code = cpu_to_le16(0);
+	if (ie && len)
+		memcpy((t_u8 *)(&mgmt->u.auth.variable), 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;
+
+	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)
+{
+	struct wiphy *wiphy = priv->wdev->wiphy;
+	mlan_bss_info bss_info;
+#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;
+	}
+
+	if (!priv->ft_roaming_triggered_by_driver) {
+		wait_option = MOAL_IOCTL_WAIT;
+		memset(&bss_info, 0, sizeof(bss_info));
+		woal_get_bss_info(priv, wait_option, &bss_info);
+	}
+
+	if (priv->ft_roaming_triggered_by_driver || (priv->media_connected &&
+						     bss_info.mdid ==
+						     priv->ft_md &&
+						     bss_info.ft_cap ==
+						     priv->ft_cap)) {
+		ret = MTRUE;
+
+		/*enable auth register frame */
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		woal_cfg80211_mgmt_frame_register(wiphy, priv->netdev,
+						  IEEE80211_STYPE_AUTH, MTRUE);
+#else
+		woal_cfg80211_mgmt_frame_register(wiphy, priv->wdev,
+						  IEEE80211_STYPE_AUTH, MTRUE);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+#define AUTH_TX_DEFAULT_WAIT_TIME  1200
+		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");
+			memcpy(priv->target_ap_bssid, bssid, ETH_ALEN);
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		woal_cfg80211_remain_on_channel_cfg(priv, wait_option, MTRUE,
+						    &status, NULL, 0, 0);
+#endif
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		woal_cfg80211_mgmt_frame_register(wiphy, priv->netdev,
+						  IEEE80211_STYPE_AUTH, MFALSE);
+#else
+		woal_cfg80211_mgmt_frame_register(wiphy, priv->wdev,
+						  IEEE80211_STYPE_AUTH, MFALSE);
+#endif
+	}
+
+	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;
+	struct ieee80211_channel chan;
+	mlan_bss_info bss_info;
+	int ret = 0;
+	long timeout = 0;
+
+	ENTER();
+
+	if (!priv->ft_roaming_triggered_by_driver)
+		wait_option = MOAL_IOCTL_WAIT;
+
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, wait_option, &bss_info);
+	chan.band = (bss_info.bss_chan < 36) ?
+		IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	chan.center_freq = ieee80211_channel_to_frequency(bss_info.bss_chan
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+							  , chan.band
+#endif
+		);
+
+	if (priv->media_connected) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		woal_cfg80211_remain_on_channel_cfg(priv, wait_option, MFALSE,
+						    &status, &chan, 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");
+			memcpy(priv->target_ap_bssid, bssid, ETH_ALEN);
+		}
+#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
+		);
+
+	priv->ft_roaming_triggered_by_driver = MTRUE;
+	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;
+	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);
+#ifdef UAP_CFG80211
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		LEAVE();
+		return 0;
+	}
+#endif
+	if (priv->wdev->iftype != NL80211_IFTYPE_STATION
+#if defined(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 && V14_FEATURE */
+		) {
+		PRINTM(MERROR,
+		       "Received infra assoc request when station not in infra mode\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	memset(&ssid_bssid, 0, sizeof(ssid_bssid));
+	memcpy(&ssid_bssid.ssid.ssid, sme->ssid, sme->ssid_len);
+	ssid_bssid.ssid.ssid_len = sme->ssid_len;
+	if (sme->bssid)
+		memcpy(&ssid_bssid.bssid, sme->bssid, ETH_ALEN);
+	/* 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);
+
+#if defined(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
+	/*Fast BSS Transition use ft-over-air */
+	if (priv->media_connected && priv->ft_ie_len &&
+	    !(priv->ft_cap & MBIT(0))) {
+		ret = woal_connect_ft_over_air(priv, (t_u8 *)sme->bssid,
+					       sme->channel);
+		if (ret == MTRUE) {
+			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;
+	ret = woal_cfg80211_assoc(priv, (void *)sme, MOAL_IOCTL_WAIT);
+
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
+	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;
+		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;
+	}
+	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);
+		priv->ft_ie_len = 0;
+		priv->ft_pre_connect = MFALSE;
+		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);
+
+	}
+	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);
+	long start_time;
+
+	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
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_disconnect in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (priv->cfg_disconnect) {
+		PRINTM(MERROR, "Disassociation already in progress\n");
+		LEAVE();
+		return -EBUSY;
+	}
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MMSG, " Already disconnected\n");
+		LEAVE();
+		return 0;
+	}
+
+	if (priv->keep_connect) {
+		LEAVE();
+		return 0;
+	}
+
+	priv->cfg_disconnect = MTRUE;
+	start_time = jiffies;
+	if (woal_disconnect
+	    (priv, MOAL_IOCTL_WAIT_TIMEOUT, priv->cfg_bssid,
+	     reason_code) != MLAN_STATUS_SUCCESS) {
+		priv->cfg_disconnect = MFALSE;
+		LEAVE();
+		return -EFAULT;
+	}
+       /**Add delay to avoid auth failure after wps success */
+	if ((jiffies - start_time) < 1 * HZ)
+		woal_sched_timeout(1500);
+
+	priv->cfg_disconnect = MFALSE;
+
+#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 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 t_u8 *mac,
+#else
+			  t_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;
+	}
+
+	memcpy(mac, priv->cfg_bssid, 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 bandcfg  Driver band configuration
+ *
+ *  @return         IEEE band type
+ */
+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 > scan_resp.num_in_chan_stats || idx < 0) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (idx == 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)
+/**
+ * @brief Function gets channel info from cfg80211
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param wdev            A pointer to wireless_dev structure
+ * @param chandef         A pointer to cfg80211_chan_def
+ *
+ * @return                0 -- success, otherwise fail
+ */
+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;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+
+	memset(&channel, 0x00, sizeof(channel));
+
+	if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
+		if ((handle->mon_if) &&
+		    (handle->mon_if->mon_ndev == wdev->netdev)) {
+			*chandef = handle->mon_if->chandef;
+			return 0;
+		}
+		return -EFAULT;
+	}
+#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(MERROR, "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(MINFO,
+			       "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 Join the specified
+ * IBSS (or create if necessary)
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params          A pointer to cfg80211_ibss_params structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+			struct cfg80211_ibss_params *params)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+
+	ENTER();
+
+	if (priv->wdev->iftype != NL80211_IFTYPE_ADHOC) {
+		PRINTM(MERROR,
+		       "Request IBSS join received when station not in ibss mode\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	ret = woal_cfg80211_assoc(priv, (void *)params, MOAL_IOCTL_WAIT);
+
+	if (!ret) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
+				     params->chandef.chan, GFP_KERNEL);
+#else
+		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
+#endif
+		PRINTM(MINFO, "Joined/created adhoc network with bssid"
+		       MACSTR " successfully\n", MAC2STR(priv->cfg_bssid));
+	} else {
+		PRINTM(MINFO, "Failed creating/joining adhoc network\n");
+		memset(priv->cfg_bssid, 0, ETH_ALEN);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to leave the IBSS
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+	if (priv->cfg_disconnect) {
+		PRINTM(MERROR, "IBSS leave already in progress\n");
+		LEAVE();
+		return -EBUSY;
+	}
+
+	if (priv->media_connected == MFALSE) {
+		LEAVE();
+		return -EINVAL;
+	}
+
+	priv->cfg_disconnect = 1;
+
+	PRINTM(MINFO, "Leaving from IBSS " MACSTR "\n",
+	       MAC2STR(priv->cfg_bssid));
+	if (woal_disconnect
+	    (priv, MOAL_IOCTL_WAIT, priv->cfg_bssid,
+	     DEF_DEAUTH_REASON_CODE) != MLAN_STATUS_SUCCESS) {
+		priv->cfg_disconnect = 0;
+		LEAVE();
+		return -EFAULT;
+	}
+	priv->cfg_disconnect = 0;
+	memset(priv->cfg_bssid, 0, ETH_ALEN);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @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 (hw_test || (ps_mode == MLAN_INIT_PARA_DISABLED)) {
+		PRINTM(MIOCTL, "block set power hw_test=%d ps_mode=%d\n",
+		       hw_test, ps_mode);
+		LEAVE();
+		return -EFAULT;
+	}
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_set_power_mgmt in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+#if defined(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 nl80211_channel_type channel_type,
+				    t_u32 duration)
+{
+	mlan_ds_remain_chan chan_cfg;
+	int ret = 0;
+
+	ENTER();
+
+	if (!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 NL80211_CHAN_HT40MINUS:
+			chan_cfg.bandcfg.chan2Offset = SEC_CHAN_BELOW;
+			break;
+		case NL80211_CHAN_HT40PLUS:
+			chan_cfg.bandcfg.chan2Offset = SEC_CHAN_ABOVE;
+			break;
+
+		case NL80211_CHAN_NO_HT:
+		case NL80211_CHAN_HT20:
+		default:
+			break;
+		}
+		chan_cfg.channel =
+			ieee80211_frequency_to_channel(chan->center_freq);
+		chan_cfg.remain_period = duration;
+	}
+	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 CFG80211_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
+	memcpy(&priv->phandle->chan, chan, sizeof(struct ieee80211_channel));
+
+	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;
+	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 < 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)
+	/* only support 1 scan plan now */
+	if (request->scan_plans[0].interval > MIN_BGSCAN_INTERVAL)
+		priv->scan_cfg.scan_interval = request->scan_plans[0].interval;
+#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 (MLAN_STATUS_SUCCESS ==
+	    woal_request_bgscan(priv, MOAL_IOCTL_WAIT, &priv->scan_cfg)) {
+		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(MIOCTL, "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_STA);
+#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");
+	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);
+					cfg80211_sched_scan_results(handle->
+								    priv[i]->
+								    wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+								    , 0
+#endif
+						);
+					handle->priv[i]->last_event = 0;
+					PRINTM(MIOCTL,
+					       "Report sched scan result in cfg80211 resume\n");
+				}
+				if (!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,
+							  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(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->disconnect)
+			wakeup_report.disconnect = true;
+		break;
+	case MAGIC_PATTERN_MATCHED:
+		if (wiphy->wowlan_config->magic_pkt)
+			wakeup_report.magic_pkt = true;
+		if (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->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
+
+	handle->cfg80211_suspend = MFALSE;
+	PRINTM(MCMND, "<--- Leave woal_cfg80211_resume --->\n");
+	return 0;
+}
+
+/**
+ * @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;
+
+	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;
+
+	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;
+	memcpy(misc->param.tdls_oper.peer_mac, peer, ETH_ALEN);
+	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;
+	memcpy(misc->param.tdls_ies.peer_mac, peer, ETH_ALEN);
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (tdls_ies)
+		memcpy(tdls_ies, &misc->param.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(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));
+		memcpy(pos, tdls_ies->ext_cap, 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)
+		memcpy(pos, basic_rates, rate_num);
+	else
+		memcpy(pos, basic_rates_5G, 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;
+	memcpy(pos, ext_rates, 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 = 24;
+	t_u8 wmmInfoIe_len = 7;
+	t_u8 len = 0;
+	t_u8 *pos;
+
+	if (skb_tailroom(skb) < wmmParamIe_len + 2)
+		return;
+
+	qosInfo = (pQosInfo == NULL) ? 0xf : (*pQosInfo);
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		pos = skb_put(skb, wmmParamIe_len + 2);
+		len = wmmParamIe_len;
+	} else {
+		pos = skb_put(skb, wmmInfoIe_len + 2);
+		len = wmmInfoIe_len;
+	}
+
+	*pos++ = wmm_id;
+	*pos++ = len;
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		memcpy(pos, wmmParamElement, sizeof(wmmParamElement));
+		pos += sizeof(wmmParamElement);
+	} else {
+		memcpy(pos, wmmInfoElement, sizeof(wmmInfoElement));
+		pos += sizeof(wmmInfoElement);
+	}
+	*pos++ = qosInfo;
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		*pos++ = reserved;
+		memcpy(pos, ac_be, sizeof(ac_be));
+		pos += sizeof(ac_be);
+		memcpy(pos, ac_bk, sizeof(ac_bk));
+		pos += sizeof(ac_bk);
+		memcpy(pos, ac_vi, sizeof(ac_vi));
+		pos += sizeof(ac_vi);
+		memcpy(pos, 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
+*/
+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
+*/
+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) {
+				memcpy(tdls_peer->peer_addr, peer, ETH_ALEN);
+				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 *tf;
+	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;
+
+	tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+	memcpy(tf->da, peer, ETH_ALEN);
+	memcpy(tf->sa, priv->current_addr, ETH_ALEN);
+	tf->ether_type = cpu_to_be16(MLAN_ETHER_PKT_TYPE_TDLS_ACTION);
+	tf->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);
+
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_REQUEST;
+		skb_put(skb, sizeof(tf->u.setup_req));
+		tf->u.setup_req.dialog_token = dialog_token;
+		tf->u.setup_req.capability = cpu_to_le16(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);
+
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
+
+		skb_put(skb, sizeof(tf->u.setup_resp));
+		tf->u.setup_resp.status_code = cpu_to_le16(status_code);
+		tf->u.setup_resp.dialog_token = dialog_token;
+		tf->u.setup_resp.capability = cpu_to_le16(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);
+
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
+
+		skb_put(skb, sizeof(tf->u.setup_cfm));
+		tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
+		tf->u.setup_cfm.dialog_token = dialog_token;
+
+		break;
+	case WLAN_TDLS_TEARDOWN:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_TEARDOWN;
+
+		skb_put(skb, sizeof(tf->u.teardown));
+		tf->u.teardown.reason_code = cpu_to_le16(status_code);
+		break;
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
+
+		skb_put(skb, sizeof(tf->u.discover_req));
+		tf->u.discover_req.dialog_token = dialog_token;
+		break;
+	default:
+		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]);
+			memcpy(pSupp_chan, tdls_ies->supp_chan,
+			       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]);
+			memcpy(pRegulatory_class, tdls_ies->regulatory_class,
+			       sizeof(IEEEtypes_Header_t) +
+			       tdls_ies->regulatory_class[1]);
+		}
+		woal_tdls_add_ext_capab(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));
+			memcpy(HTcap, tdls_ies->ht_cap,
+			       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));
+			memcpy(VHTcap, tdls_ies->vht_cap,
+			       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));
+			memcpy(AidInfo, tdls_ies->aid_info,
+			       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));
+			memcpy(HTInfo, tdls_ies->ht_info,
+			       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));
+			memcpy(vht_oprat, tdls_ies->vht_oprat,
+			       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);
+	memcpy(mgmt->da, peer, ETH_ALEN);
+	memcpy(mgmt->sa, priv->current_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
+
+	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_ACTION);
+	/* add address 4 */
+	pos = skb_put(skb, ETH_ALEN);
+
+	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.category,
+			1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
+		/** init address 4 */
+		memcpy(pos, addr, ETH_ALEN);
+
+		woal_add_supported_rates_ie(priv, skb, band);
+		woal_add_ext_supported_rates_ie(priv, skb, band);
+		woal_tdls_add_ext_capab(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]);
+			memcpy(pSupp_chan, tdls_ies->supp_chan,
+			       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]);
+			memcpy(pRegulatory_class, tdls_ies->regulatory_class,
+			       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(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;
+
+	memcpy(lnkid->bssid, bssid, ETH_ALEN);
+	memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
+	memcpy(lnkid->resp_sta, peer, ETH_ALEN);
+}
+
+/**
+ * @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));
+	memcpy(pos, &pkt_type, sizeof(pkt_type));
+	memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
+
+	woal_construct_tdls_action_frame(priv, peer, action_code,
+					 dialog_token, status_code, skb);
+
+	if (extra_ies_len)
+		memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
+
+	/* the TDLS link IE is always added last */
+	/* we are the responder */
+	woal_tdls_add_link_ie(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);
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &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)
+		memcpy(skb_put(skb, extra_ies_len), extra_ies, 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(skb, priv->current_addr, peer,
+				      priv->cfg_bssid);
+		break;
+	case WLAN_TDLS_SETUP_RESPONSE:
+		/* we are the responder */
+		woal_tdls_add_link_ie(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);
+		memcpy(event_buf, CUS_EVT_TDLS_CONNECTED, custom_len);
+		memcpy(event_buf + custom_len, peer, ETH_ALEN);
+		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);
+		memcpy(event_buf, CUS_EVT_TDLS_TEARDOWN, custom_len);
+		memcpy(event_buf + custom_len, peer, ETH_ALEN);
+		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;
+}
+
+/**
+ * @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 (!(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:
+	return ret;
+}
+
+/**
+ * @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;
+}
+
+#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;
+	memcpy(tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr, addr, ETH_ALEN);
+	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;
+	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_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;
+	memcpy(tdls_data->tdls_data, addr, ETH_ALEN);
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		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,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;
+	memset(priv->ft_ie, 0, MAX_IE_SIZE);
+	memcpy(priv->ft_ie, ftie->ie, MIN(ftie->ie_len, MAX_IE_SIZE));
+	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;
+	memcpy((void *)priv->sme_current.bssid, &priv->target_ap_bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+	ret = woal_cfg80211_assoc(priv, (void *)&priv->sme_current,
+				  MOAL_IOCTL_WAIT);
+
+	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);
+			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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			memset(&roam_info, 0,
+			       sizeof(struct cfg80211_roam_info));
+			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));
+			priv->ft_ie_len = 0;
+		}
+		priv->ft_roaming_triggered_by_driver = MFALSE;
+
+	} else {
+		PRINTM(MMSG, "Fast BSS Transition use ft-over-air\n");
+		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->cfg_bssid));
+			cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
+						NULL, 0, NULL, 0,
+						woal_get_assoc_status(priv),
+						GFP_KERNEL);
+			memset(priv->cfg_bssid, 0, ETH_ALEN);
+			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);
+	memcpy(&priv->sme_current, sme, sizeof(struct cfg80211_connect_params));
+	if (sme->channel) {
+		priv->sme_current.channel = &priv->conn_chan;
+		memcpy(priv->sme_current.channel, sme->channel,
+		       sizeof(struct ieee80211_channel));
+	}
+	if (sme->bssid) {
+		priv->sme_current.bssid = priv->conn_bssid;
+		memcpy((void *)priv->sme_current.bssid, sme->bssid,
+		       MLAN_MAC_ADDR_LENGTH);
+	}
+	if (sme->ssid && sme->ssid_len) {
+		priv->sme_current.ssid = priv->conn_ssid;
+		memset(priv->conn_ssid, 0, MLAN_MAX_SSID_LENGTH);
+		memcpy((void *)priv->sme_current.ssid, sme->ssid,
+		       sme->ssid_len);
+	}
+	if (sme->ie && sme->ie_len) {
+		priv->sme_current.ie = kzalloc(sme->ie_len, GFP_KERNEL);
+		memcpy((void *)priv->sme_current.ie, sme->ie, sme->ie_len);
+	}
+	if (sme->key && sme->key_len && (sme->key_len <= MAX_WEP_KEY_SIZE)) {
+		priv->sme_current.key = priv->conn_wep_key;
+		memcpy((t_u8 *)priv->sme_current.key, sme->key, sme->key_len);
+	}
+}
+
+/**
+ * @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;
+	LEAVE();
+}
+
+/**
+ * @brief Build new roaming connect ie for okc
+ *
+ * @param priv            A pointer to moal_private
+ * @param entry           A pointer to pmksa_entry
+ **/
+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);
+
+			memcpy(okc_ie_pos, sme_pos, 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);
+			memcpy(okc_ie_pos, entry->pmkid, 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);
+					memcpy(okc_ie_pos, sme_ptr,
+					       (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 {
+			memcpy(okc_ie_pos, sme_pos, 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;
+	memcpy(ssid_bssid.ssid.ssid, priv->sme_current.ssid,
+	       priv->sme_current.ssid_len);
+	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)) {
+		woal_start_ft_roaming(priv, &ssid_bssid);
+		goto done;
+	}
+	/* start roaming to new AP */
+	priv->sme_current.bssid = priv->conn_bssid;
+	memcpy((void *)priv->sme_current.bssid, &ssid_bssid.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	if (IS_STA_CFG80211(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
+
+	ret = woal_cfg80211_assoc(priv, (void *)&priv->sme_current,
+				  MOAL_IOCTL_WAIT);
+	if (!ret) {
+		const t_u8 *ie;
+		int ie_len;
+
+		woal_inform_bss_from_scan_result(priv, NULL, MOAL_IOCTL_WAIT);
+		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;
+
+	/** 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(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)
+		memset(&roam_info, 0, sizeof(struct cfg80211_roam_info));
+		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));
+	}
+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;
+}
+
+/**
+ * @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;
+
+	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;
+	}
+#if defined(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
+	if (bss_type == MLAN_BSS_TYPE_NAN)
+		wdev->iftype = NL80211_IFTYPE_STATION;
+	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;
+	}
+	woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Initialize the wiphy
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param wait_option     Wait option
+ *
+ * @return                MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_cfg80211_init_wiphy(moal_private *priv, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int retry_count, rts_thr, frag_thr;
+	struct wiphy *wiphy = NULL;
+	mlan_ioctl_req *req = NULL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	mlan_ds_radio_cfg *radio = NULL;
+#endif
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	t_u32 hw_dev_cap;
+#ifdef UAP_SUPPORT
+	mlan_uap_bss_param *sys_cfg = NULL;
+#endif
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 0, 0)
+	t_u16 enable = 0;
+#endif
+
+	ENTER();
+
+	wiphy = priv->phandle->wiphy;
+	/* 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])
+		woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_2GHZ]->
+					   ht_cap, hw_dev_cap,
+					   cfg_11n->param.supported_mcs_set);
+	/* For 2.4G band only card, this shouldn't be set */
+	if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
+		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
+	}
+	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 */
+	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;
+			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;
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 0, 0)
+	/* Enable multi-channel by default if multi-channel is supported */
+	if (cfg80211_iface_comb_ap_sta.num_different_channels > 1)
+		enable = 1;
+	if (priv->phandle->card_info->drcs)
+		ret = woal_mc_policy_cfg(priv, &enable, wait_option,
+					 MLAN_ACT_SET);
+#endif
+
+done:
+	LEAVE();
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	return ret;
+}
+
+/*
+ * 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;
+	int index = 0;
+
+	ENTER();
+
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+
+	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;
+	}
+#ifdef CONFIG_PM
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+	wiphy->wowlan = &wowlan_support;
+#else
+	wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT;
+	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_ADHOC) |
+		MBIT(NL80211_IFTYPE_AP);
+	wiphy->interface_modes |= MBIT(NL80211_IFTYPE_MONITOR);
+
+#if defined(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) {
+		wiphy->bands[IEEE80211_BAND_5GHZ] = &cfg80211_band_5ghz;
+		priv->phandle->band = IEEE80211_BAND_5GHZ;
+	}
+	/* Supported bands */
+	if (fw_info.fw_bands & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
+		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)
+	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;
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	if (cfg80211_drcs && priv->phandle->card_info->drcs) {
+		cfg80211_iface_comb_ap_sta.num_different_channels = 2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		cfg80211_iface_comb_ap_sta.radar_detect_widths = 0;
+#endif
+	}
+	/* Initialize interface combinations */
+	wiphy->iface_combinations = &cfg80211_iface_comb_ap_sta;
+	wiphy->n_iface_combinations = 1;
+#endif
+
+	memcpy(wiphy->perm_addr, priv->current_addr, ETH_ALEN);
+	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;
+#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_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+	wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+#endif
+#ifdef ANDROID_KERNEL
+	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#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 = 1;
+#endif
+#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(3,4,0)
+	wiphy->features |= NL80211_FEATURE_HT_IBSS;
+#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(4, 8, 0)
+	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+#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 (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 (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
+	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
+	if (wiphy_register(wiphy) < 0) {
+		PRINTM(MERROR, "Wiphy device registration failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err_wiphy;
+	}
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (!p2p_enh)
+		wiphy->interface_modes &= ~(MBIT(NL80211_IFTYPE_P2P_GO) |
+					    MBIT(NL80211_IFTYPE_P2P_CLIENT));
+#endif
+#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]);
+			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]);
+					regulatory_hint(wiphy, country);
+				}
+			} else
+				PRINTM(MERROR,
+				       "hw region code=%d not supported\n",
+				       fw_info.region_code);
+		}
+	}
+	priv->phandle->wiphy = wiphy;
+	woal_cfg80211_init_wiphy(priv, MOAL_IOCTL_WAIT);
+	return ret;
+err_wiphy:
+	if (wiphy)
+		wiphy_free(wiphy);
+	LEAVE();
+	return ret;
+}
+
+module_param(cfg80211_drcs, int, 0);
+MODULE_PARM_DESC(cfg80211_drcs,
+		 "1: Enable DRCS support; 0: Disable DRCS support");
+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
diff --git a/wlan_sd8897/mlinux/moal_sta_cfg80211.h b/wlan_sd8897/mlinux/moal_sta_cfg80211.h
new file mode 100644
index 0000000..31a3ee5
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_sta_cfg80211.h
@@ -0,0 +1,42 @@
+/** @file moal_sta_cfg80211.h
+  *
+  * @brief This file contains the STA CFG80211 specific defines.
+  *
+  * Copyright (C) 2014-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _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);
+
+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);
+
+#endif /* _MOAL_STA_CFG80211_H_ */
diff --git a/wlan_sd8897/mlinux/moal_uap.c b/wlan_sd8897/mlinux/moal_uap.c
new file mode 100644
index 0000000..8440207
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_uap.c
@@ -0,0 +1,3994 @@
+/** @file moal_uap.c
+  *
+  * @brief This file contains the major functions in UAP
+  * driver.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include    "moal_main.h"
+#include    "moal_uap.h"
+#include    "moal_sdio.h"
+#include    "moal_eth_ioctl.h"
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#include    "moal_cfg80211.h"
+#endif
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+/********************************************************
+		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;
+	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;
+	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);
+	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 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;
+}
+
+/**
+ *  @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);
+		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;
+		}
+		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);
+		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;
+		}
+	}
+	/* 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;
+}
+
+/**
+ *  @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) > 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;
+		memcpy(cfg11d->param.domain_tlv, tlv,
+		       MIN(MAX_IE_SIZE, (TLV_HEADER_LEN + tlv_data_len)));
+	}
+	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;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ *  @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;
+		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;
+		priv->phandle->cac_period_jiffies =
+			param.usr_cac_period * HZ / 1000;
+		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;
+		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;
+	}
+	/* 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;
+	memcpy(&ds_11hcfg->param.ch_nop_info, ch_info,
+	       sizeof(mlan_ds_11h_chan_nop_info));
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_FAILURE) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memcpy(ch_info, &ds_11hcfg->param.ch_nop_info,
+	       sizeof(mlan_ds_11h_chan_nop_info));
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+#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;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
+	} else {
+		/* Set HT Tx configurations */
+		cfg_11n->param.tx_cfg.httxcap = httx_cfg.httxcap;
+		PRINTM(MINFO, "SET: httxcap:0x%x\n", httx_cfg.httxcap);
+		cfg_11n->param.tx_cfg.misc_cfg = httx_cfg.misc_cfg;
+		PRINTM(MINFO, "SET: httxcap band:0x%x\n", httx_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;
+	}
+	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);
+		cfg_11n->param.tx_cfg.httxcap = 0;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
+		status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		httx_cfg.misc_cfg = cfg_11n->param.tx_cfg.httxcap;
+		PRINTM(MINFO, "GET: httxcap for 5GHz:0x%x\n",
+		       httx_cfg.misc_cfg);
+	}
+	/* 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);
+	memcpy(vhtcfg, &cfg_11ac->param.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++;
+		memcpy(vhtcfg, &cfg_11ac->param.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
+ *  @invoke_hostcmd Argument
+ *
+ *  @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 dev          A pointer to net_device structure
+ *  @param req          A pointer to ifreq 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 > 3)) {
+			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_VHT)
+				) {
+				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))
+					) {
+					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.user_data_cnt == 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;
+			}
+		}
+	}
+
+	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)
+				tx_rate_config.nss = rate->param.rate_cfg.nss;
+		}
+		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;
+	}
+
+	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_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;
+	case UAP_SDCMD52_RW:
+		ret = woal_uap_sdcmd52_rw(dev, req);
+		break;
+	case UAP_SNMP_MIB:
+		ret = woal_uap_snmp_mib(dev, req);
+		break;
+#ifdef DFS_TESTING_SUPPORT
+	case UAP_DFS_TESTING:
+		ret = woal_uap_dfs_testing(dev, req);
+		break;
+#endif
+	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_CAC_TIMER_STATUS:
+		ret = woal_uap_cac_timer_status(dev, req);
+		break;
+	case UAP_OPERATION_CTRL:
+		ret = woal_uap_operation_ctrl(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;
+
+	memcpy(&bss->param.deauth_param, &deauth_param,
+	       sizeof(mlan_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;
+	memcpy(sec->param.sta_mac, mac_addr, MLAN_MAC_ADDR_LENGTH);
+
+	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;
+
+	memcpy(sec->param.encrypt_key.mac_addr, key.mac_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+	sec->param.encrypt_key.key_index = key.key_index;
+	sec->param.encrypt_key.key_len = key.key_len;
+	memcpy(sec->param.encrypt_key.key_material, key.key_material,
+	       key.key_len);
+	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)
+		memcpy(&pm_cfg->param.ps_mgmt, ps_mgmt,
+		       sizeof(mlan_ds_ps_mgmt));
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (action == MLAN_ACT_GET)
+			memcpy(ps_mgmt, &pm_cfg->param.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;
+	}
+
+	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;
+		memcpy(&pm_cfg->param.ps_mgmt, &ps_mgmt,
+		       sizeof(mlan_ds_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,
+		     sizeof(mlan_ds_sta_list))) {
+			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;
+	memcpy(sec->param.encrypt_key.mac_addr, key_msg->mac_addr, ETH_ALEN);
+	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;
+	memcpy(sec->param.encrypt_key.key_material, key_msg->key,
+	       sec->param.encrypt_key.key_len);
+
+	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) {
+		memcpy(misc->param.gen_ie.ie_data, wapi_psk_ie,
+		       misc->param.gen_ie.len);
+	} else if (msg->msg[0] & WAPI_MODE_CERT) {
+		memcpy(misc->param.gen_ie.ie_data, wapi_cert_ie,
+		       misc->param.gen_ie.len);
+	} 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)
+		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
+ */
+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;
+	}
+	memcpy(sys_cfg, &info->param.bss_config, 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_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 = 0x20;
+		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 = 0x6f;
+		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();
+	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;
+		sys_cfg->supported_mcs_set[4] = 0x01;
+		if (fw_info.usr_dev_mcs_support == HT_STREAM_MODE_2X2) {
+			sys_cfg->supported_mcs_set[1] = 0xFF;
+			sys_cfg->supported_mcs_set[12] |= MBIT(2);
+		} else {
+			sys_cfg->supported_mcs_set[1] = 0;
+			sys_cfg->supported_mcs_set[12] &= ~(MBIT(2) | MBIT(3));
+		}
+	}
+
+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();
+
+	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;
+	}
+	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 Parse AP configuration from ASCII string
+ *
+ *  @param ap_cfg   A pointer to mlan_uap_bss_param structure
+ *  @param buf      A pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_uap_ap_cfg_parse_data(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);
+				memcpy(ap_cfg->wep_cfg.key0.key, value,
+				       MIN(sizeof(ap_cfg->wep_cfg.key0.key),
+					   strlen(value)));
+				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);
+			memcpy(ap_cfg->wpa_cfg.passphrase, value,
+			       MIN(sizeof(ap_cfg->wpa_cfg.passphrase),
+				   strlen(value)));
+			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);
+	memcpy(buf, data, MIN(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(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
+ */
+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;
+
+	memcpy(&bss->param.ap_scan_channels, scan_channels,
+	       sizeof(mlan_uap_scan_channels));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		memcpy(scan_channels, &bss->param.ap_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;
+
+	memcpy(&bss->param.ap_channel, uap_channel, sizeof(chan_band_info));
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		memcpy(uap_channel, &bss->param.ap_channel,
+		       sizeof(chan_band_info));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	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)
+			   || dfs_offload
+#endif
+			) {
+			/* 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");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		bss->sub_command = MLAN_OID_BSS_START;
+		bss->param.host_based = priv->uap_host_based;
+		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);
+		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
+ */
+int
+woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	int ret = 0;
+	ENTER();
+	PRINTM(MIOCTL, "uap_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 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)
+			memcpy(ustats, &info->param.ustats,
+			       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)
+		memcpy(&bss->param.ap_wmm_para, ap_wmm_para,
+		       sizeof(wmm_parameter_t));
+
+	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)
+		memcpy(ap_wmm_para, &bss->param.ap_wmm_para,
+		       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)
+		memcpy(&bss->param.bss_config, sys_cfg,
+		       sizeof(mlan_uap_bss_param));
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (action == MLAN_ACT_GET)
+		memcpy(sys_cfg, &bss->param.bss_config,
+		       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_sd8897/mlinux/moal_uap.h b/wlan_sd8897/mlinux/moal_uap.h
new file mode 100644
index 0000000..e536b62
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_uap.h
@@ -0,0 +1,521 @@
+/** @file moal_uap.h
+  *
+  * @brief This file contains uap driver specific defines etc.
+  *
+  * Copyright (C) 2009-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+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
+/** sdcmd52 read write subcommand */
+#define UAP_SDCMD52_RW      6
+/** 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
+#ifdef DFS_TESTING_SUPPORT
+/** dfs testing subcommand */
+#define UAP_DFS_TESTING     10
+#endif
+/** 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_CAC_TIMER_STATUS	17
+
+#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
+
+/** 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
+
+/** TX rate cfg structure */
+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];
+} 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;
+
+/** CAC timer status structure */
+typedef struct _cac_timer_status {
+	/** subcmd */
+	t_u32 subcmd;
+	/** set/get */
+	t_u32 action;
+	/** mode */
+	t_u32 mode;
+} cac_timer_status;
+
+/** 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;
+
+/** Packet inject command ioctl number */
+/** 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)
+#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 _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;
+} addba_param;
+
+/** aggr_prio_tbl */
+typedef struct _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];
+} 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 _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;
+} fw_info;
+
+/** HT TX cfg header parameter structure */
+typedef struct _ht_tx_cfg_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} ht_tx_cfg_para_hdr;
+
+/** TX beamformer parameter header structure */
+typedef struct _tx_bf_cfg_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} tx_bf_cfg_para_hdr;
+
+/** VHT cfg parameter header structure */
+typedef struct _vht_cfg_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} vht_cfg_para_hdr;
+
+/** UAP operation parameter header structure */
+typedef struct _uap_oper_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} uap_oper_para_hdr;
+
+/** 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;
+
+/** 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;
+
+/** 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;
+
+/** SNMP mib parameter structure */
+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[0];
+} 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
+
+#ifdef DFS_TESTING_SUPPORT
+/** 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;
+} dfs_testing_para;
+#endif
+
+/** 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[0];
+} 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);
+int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+int woal_uap_bss_ctrl(moal_private *priv, t_u8 wait_option, int data);
+#ifdef UAP_CFG80211
+#if defined(DFS_TESTING_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+int woal_uap_get_channel_nop_info(moal_private *priv, t_u8 wait_option,
+				  mlan_ds_11h_chan_nop_info * ch_info);
+#endif
+#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,
+			       mlan_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(mlan_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_set_uap_ht_tx_cfg(moal_private *priv, Band_Config_t bandcfg, 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, mlan_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_sd8897/mlinux/moal_uap_cfg80211.c b/wlan_sd8897/mlinux/moal_uap_cfg80211.c
new file mode 100644
index 0000000..acf489c
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_uap_cfg80211.c
@@ -0,0 +1,3348 @@
+/** @file moal_uap_cfg80211.c
+  *
+  * @brief This file contains the functions for uAP CFG80211.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include "moal_cfg80211.h"
+#include "moal_uap_cfg80211.h"
+/** deauth reason code */
+#define  REASON_CODE_DEAUTH_LEAVING 3
+/********************************************************
+				Local Variables
+********************************************************/
+
+/********************************************************
+				Global Variables
+********************************************************/
+#ifdef WIFI_DIRECT_SUPPORT
+extern int GoAgeoutTime;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+/********************************************************
+				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;
+
+	memcpy(bss->param.deauth_param.mac_addr, mac_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+	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 all station
+ *
+ * @param priv            A pointer to moal_private structure
+ *
+ * @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 IEEEtypes_Rsn_t structure
+ * @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 < 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 = 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 < 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 = le16_to_cpu(key_mgmt->count);
+	if (left <
+	    (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;
+		}
+	}
+	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 < 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 = 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 < 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 = le16_to_cpu(key_mgmt->count);
+	if (left <
+	    (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 ie              Pointer IE buffer
+ * @param sys_config      Pointer to mlan_uap_bss_param structure
+ *
+ * @return                N/A
+ */
+static t_void
+woal_set_wmm_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;
+	IEEEtypes_VendorSpecific_t *pvendor_ie;
+	IEEEtypes_ElementId_e element_id;
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	t_u8 *poui;
+
+	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;
+			poui = pvendor_ie->vend_hdr.oui;
+			if (!memcmp(poui, wmm_oui, sizeof(wmm_oui))) {
+				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.
+					 */
+					memcpy(&sys_config->wmm_para,
+					       pcurrent_ptr +
+					       sizeof(IEEEtypes_Header_t),
+					       element_len);
+				}
+			}
+
+			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 params          A pointer to cfg80211_ap_settings structure
+ * @return                0 -- success, otherwise fail
+ */
+t_u8
+woal_check_11ac_capability(moal_private *priv,
+			   struct cfg80211_ap_settings *params)
+#else
+/**
+ * @brief initialize AP or GO bss config
+ * @param priv            A pointer to moal private structure
+ * @return                0 -- success, otherwise fail
+ */
+t_u8
+woal_check_11ac_capability(moal_private *priv)
+#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();
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (!(fw_info.fw_bands & BAND_AAC)) {
+		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;
+}
+
+/**
+ * @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;
+}
+
+#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 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(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(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(&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 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(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));
+		memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
+		rate_len = rate_ie->len;
+	}
+	ext_rate_ie =
+		(void *)woal_parse_ie_tlv(tail_ie, tail_len,
+					  WLAN_EID_EXT_SUPP_RATES);
+	if (ext_rate_ie) {
+		memcpy(&bss_cfg->rates[rate_len], ext_rate_ie + 1,
+		       ext_rate_ie->len);
+		rate_len += ext_rate_ie->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;
+	t_u8 *wapi_ie = NULL;
+	int wapi_ie_len = 0;
+#if defined(DFS_TESTING_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	mlan_ds_11h_chan_nop_info chan_nop_info;
+	Band_Config_t bandcfg;
+#endif
+#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;
+		woal_set_get_gen_ie(priv, MLAN_ACT_SET, wapi_ie, &wapi_ie_len,
+				    MOAL_IOCTL_WAIT);
+	}
+	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;
+	}
+
+	/* Setting the default values */
+	sys_config->channel = 6;
+	sys_config->preamble_type = 0;
+	sys_config->mgmt_ie_passthru_mask = priv->mgmt_subtype_mask;
+	memcpy(sys_config->mac_addr, priv->current_addr, ETH_ALEN);
+
+#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 == MLAN_FRAG_RTS_DISABLED) {
+		sys_config->frag_threshold = MLAN_FRAG_MAX_VALUE;
+	}
+	if (sys_config->rts_threshold == 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 */
+	memcpy(&priv->chan, &params->chandef, sizeof(struct cfg80211_chan_def));
+#endif
+
+#if defined(DFS_TESTING_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	PRINTM(MCMND, "Checking if AP's channel %d is under NOP\n",
+	       priv->channel);
+	woal_convert_chan_to_bandconfig(&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
+#endif
+
+	if (priv->channel) {
+		woal_check_mc_connection(priv, MOAL_IOCTL_WAIT, 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->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)
+				memcpy(sys_config->rates, rates_wfd,
+				       sizeof(rates_wfd));
+			else
+#endif
+				memcpy(sys_config->rates, rates_bg,
+				       sizeof(rates_bg));
+		} else {
+			sys_config->bandcfg.chanBand = BAND_5GHZ;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+			chan2Offset =
+				woal_get_second_channel_offset(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->
+								       channel);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			enable_11ac = woal_check_11ac_capability(priv, 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);
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+				memcpy(sys_config->rates, rates_wfd,
+				       sizeof(rates_wfd));
+			else
+#endif
+				memcpy(sys_config->rates, rates_a,
+				       sizeof(rates_a));
+		}
+
+		/* Replaced with rate from userspace, if exist */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+		woal_set_uap_rates(sys_config, params->beacon.head,
+				   params->beacon.head_len, params->beacon.tail,
+				   params->beacon.tail_len);
+#else
+		woal_set_uap_rates(sys_config, params->head, params->head_len,
+				   params->tail, params->tail_len);
+#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;
+		}
+		if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			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;
+	}
+	memcpy(sys_config->ssid.ssid, params->ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len));
+	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;
+			memcpy(&sys_config->wep_cfg.key0, &priv->uap_wep_key[0],
+			       sizeof(wep_key));
+			memcpy(&sys_config->wep_cfg.key1, &priv->uap_wep_key[1],
+			       sizeof(wep_key));
+			memcpy(&sys_config->wep_cfg.key2, &priv->uap_wep_key[2],
+			       sizeof(wep_key));
+			memcpy(&sys_config->wep_cfg.key3, &priv->uap_wep_key[3],
+			       sizeof(wep_key));
+		}
+		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;
+	}
+	memcpy(sys_config->ssid.ssid, ssid_ie + 2, *(ssid_ie + 1));
+	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;
+		memcpy(&sys_config->wep_cfg.key0, &priv->uap_wep_key[0],
+		       sizeof(wep_key));
+		memcpy(&sys_config->wep_cfg.key1, &priv->uap_wep_key[1],
+		       sizeof(wep_key));
+		memcpy(&sys_config->wep_cfg.key2, &priv->uap_wep_key[2],
+		       sizeof(wep_key));
+		memcpy(&sys_config->wep_cfg.key3, &priv->uap_wep_key[3],
+		       sizeof(wep_key));
+	} 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 (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		/*find and set wmm ie */
+		woal_set_wmm_ies(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, MFALSE);
+		woal_uap_set_11n_status(priv, sys_config, MLAN_ACT_DISABLE);
+	} else {
+		woal_set_uap_ht_tx_cfg(priv, sys_config->bandcfg, 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 (sys_config->bandcfg.chanBand == BAND_5GHZ) {
+		if (enable_11ac && enable_11n) {
+			vhtcap_ie = woal_get_vhtcap_info(ie, ie_len);
+			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 (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv,
+							   MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_config)) {
+		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;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+/**
+ * @brief Request the driver to add a monitor interface
+ *
+ * @param wiphy             A pointer to wiphy structure
+ * @param name              Virtual interface name
+ * @param name_assign_type  Interface name assignment type
+ * @param flags             Flags for the virtual interface
+ * @param params            A pointer to vif_params structure
+ * @param new_dev           Netdevice to be passed out
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_add_mon_if(struct wiphy *wiphy,
+			 const char *name,
+			 unsigned char name_assign_type,
+			 u32 *flags, struct vif_params *params,
+			 struct net_device **new_dev)
+#else
+/**
+ * @brief Request the driver to add a monitor interface
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param name            Virtual interface name
+ * @param flags           Flags for the virtual interface
+ * @param params          A pointer to vif_params structure
+ * @param new_dev         Netdevice to be passed out
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_add_mon_if(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+			 const
+#endif
+			 char *name, u32 *flags, struct vif_params *params,
+			 struct net_device **new_dev)
+#endif
+{
+	int ret = 0;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv =
+		(moal_private *)woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+	monitor_iface *mon_if = NULL;
+	struct net_device *ndev = NULL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	chan_band_info chan_info;
+#endif
+	unsigned char name_assign_type_tmp = 0;
+
+	ENTER();
+
+	ASSERT_RTNL();
+
+	if (handle->mon_if) {
+		PRINTM(MERROR, "%s: monitor interface exist: %s basedev %s\n",
+		       __func__, handle->mon_if->mon_ndev->name,
+		       handle->mon_if->base_ndev->name);
+		ret = -EFAULT;
+		goto fail;
+	}
+
+	if (!priv) {
+		PRINTM(MERROR, "add_mon_if: priv is NULL\n");
+		ret = -EFAULT;
+		goto fail;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	name_assign_type_tmp = name_assign_type;
+#endif
+	mon_if = woal_prepare_mon_if(priv, name, name_assign_type_tmp);
+	if (!mon_if) {
+		PRINTM(MFATAL, "Prepare mon_if fail.\n");
+		goto fail;
+	}
+
+	ndev = mon_if->mon_ndev;
+	dev_net_set(ndev, wiphy_net(wiphy));
+	memcpy(ndev->perm_addr, wiphy->perm_addr, ETH_ALEN);
+	memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
+	SET_NETDEV_DEV(ndev, wiphy_dev(wiphy));
+	ndev->ieee80211_ptr = &mon_if->wdev;
+	mon_if->wdev.iftype = NL80211_IFTYPE_MONITOR;
+	mon_if->wdev.wiphy = wiphy;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	/* if any interface is active, the sniffer will always operate
+	 * on the same channel as that of active connection, else will
+	 * operate on the specified channel and band
+	 */
+	memset(&chan_info, 0x00, sizeof(chan_info));
+	mon_if->band_chan_cfg.channel = 0;
+	if (!woal_is_any_interface_active(handle)) {
+		/* Set default band channel config */
+		mon_if->band_chan_cfg.band = BAND_B | BAND_G;
+		mon_if->band_chan_cfg.band |= BAND_GN;
+		mon_if->band_chan_cfg.channel = 1;
+		mon_if->band_chan_cfg.chan_bandwidth = CHANNEL_BW_20MHZ;
+		chan_info.channel = 1;
+		chan_info.is_11n_enabled = MTRUE;
+	}
+	if (MLAN_STATUS_SUCCESS != woal_set_net_monitor(priv, MOAL_IOCTL_WAIT,
+							MTRUE, 0x7,
+							&mon_if->
+							band_chan_cfg)) {
+		PRINTM(MERROR, "%s: woal_set_net_monitor fail\n", __func__);
+		ret = -EFAULT;
+		goto fail;
+	}
+	if (woal_is_any_interface_active(handle)) {
+		/* set current band channel config */
+		chan_info.bandcfg.chanBand = mon_if->band_chan_cfg.band;
+		if (mon_if->band_chan_cfg.band & (BAND_B | BAND_G
+						  | BAND_GN | BAND_GAC))
+			chan_info.bandcfg.chanBand = BAND_2GHZ;
+		else
+			/* TODO: Add support for BAND_4GHZ */
+			chan_info.bandcfg.chanBand = BAND_5GHZ;
+		chan_info.bandcfg.chanWidth =
+			mon_if->band_chan_cfg.chan_bandwidth;
+		chan_info.channel = mon_if->band_chan_cfg.channel;
+		chan_info.is_11n_enabled = MTRUE;
+	}
+	if (MLAN_STATUS_FAILURE == woal_chandef_create(priv, &mon_if->chandef,
+						       &chan_info)) {
+		/* stop monitor mode on error */
+		woal_set_net_monitor(priv, MOAL_IOCTL_WAIT, MFALSE, 0, NULL);
+		ret = -EFAULT;
+		goto fail;
+	}
+#endif
+
+	ret = register_netdevice(ndev);
+	if (ret) {
+		PRINTM(MFATAL, "register net_device failed, ret=%d\n", ret);
+		free_netdev(ndev);
+		goto fail;
+	}
+
+	handle->mon_if = mon_if;
+
+	if (new_dev)
+		*new_dev = ndev;
+
+fail:
+	LEAVE();
+	return ret;
+}
+
+#if defined(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
+ */
+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
+ */
+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 = (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;
+
+	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);
+	ret = register_netdevice(ndev);
+	if (ret) {
+		handle->priv[new_priv->bss_index] = NULL;
+		handle->priv_num--;
+		if (ndev->reg_state == NETREG_REGISTERED) {
+			unregister_netdevice(ndev);
+			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);
+#ifdef PROC_DEBUG
+	woal_debug_entry(new_priv);
+#endif /* PROC_DEBUG */
+#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
+ */
+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);
+
+	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;
+			}
+		}
+	}
+
+	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
+		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
+#ifdef PROC_DEBUG
+		/* Remove proc debug */
+		woal_debug_remove(vir_priv);
+#endif /* PROC_DEBUG */
+		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)
+			unregister_netdevice(dev);
+	}
+	return ret;
+}
+#endif
+#endif
+
+/**
+ *  @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
+#ifdef PROC_DEBUG
+				/* Remove proc debug */
+				woal_debug_remove(priv);
+#endif /* PROC_DEBUG */
+				woal_proc_remove(priv);
+#endif /* CONFIG_PROC_FS */
+				netif_device_detach(priv->netdev);
+				if (priv->netdev->reg_state ==
+				    NETREG_REGISTERED)
+					unregister_netdevice(priv->netdev);
+				handle->priv[i] = NULL;
+				vir_intf++;
+			}
+		}
+	}
+#endif
+	if (handle->mon_if) {
+		netif_device_detach(handle->mon_if->mon_ndev);
+		if (handle->mon_if->mon_ndev->reg_state == NETREG_REGISTERED)
+			unregister_netdevice(handle->mon_if->mon_ndev);
+		handle->mon_if = NULL;
+	}
+	rtnl_unlock();
+#ifdef WIFI_DIRECT_SUPPORT
+	handle->priv_num -= vir_intf;
+#endif
+	LEAVE();
+}
+
+/**
+ *  @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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+	u32 *flags = &params->flags;
+#endif
+
+	ENTER();
+	PRINTM(MIOCTL, "add virtual intf: %d name: %s\n", type, name);
+	switch (type) {
+	case NL80211_IFTYPE_MONITOR:
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+		ret = woal_cfg80211_add_mon_if(wiphy, name, name_assign_type,
+					       flags, params, &ndev);
+#else
+		ret = woal_cfg80211_add_mon_if(wiphy, name, flags, params,
+					       &ndev);
+#endif
+		break;
+#if defined(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_MONITOR) {
+		if ((handle->mon_if) && (handle->mon_if->mon_ndev == dev)) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_net_monitor(handle->mon_if->priv,
+						 MOAL_IOCTL_WAIT, MFALSE, 0,
+						 NULL)) {
+				PRINTM(MERROR,
+				       "%s: woal_set_net_monitor fail\n",
+				       __func__);
+				ret = -EFAULT;
+			}
+#endif
+			handle->mon_if = NULL;
+		}
+		unregister_netdevice(dev);
+		LEAVE();
+		return ret;
+	}
+	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;
+	}
+#if defined(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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	t_u8 wait_option = MOAL_IOCTL_WAIT;
+#endif
+	ENTER();
+
+	PRINTM(MMSG, "wlan: Starting AP\n");
+#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 (dfs_offload)
+			wait_option = MOAL_NO_WAIT;
+#endif
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, 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();
+
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block  woal_cfg80211_del_beacon in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	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 (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 (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_RESET)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		/* Set WLAN MAC addresses */
+		if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(priv)) {
+			PRINTM(MERROR, "Set MAC address failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_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 (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, 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 (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 ||
+		    priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
+#endif
+			woal_deauth_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;
+
+	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_SIGNAL);
+#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;
+		}
+	}
+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;
+
+	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;
+	memcpy(mac, info->param.sta_list.info[idx].mac_address, 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
+	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;
+	memcpy(sys_config->filter.mac_list, params->mac_addrs,
+	       sys_config->filter.mac_count * sizeof(mlan_802_11_mac_addr));
+	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, 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
+ */
+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:
+		break;
+	case NL80211_CHAN_WIDTH_20:
+		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;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+	case NL80211_CHAN_WIDTH_80P80:
+	case NL80211_CHAN_WIDTH_160:
+		chan2Offset =
+			woal_get_second_channel_offset(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, wait_option, 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;
+	memcpy(&priv->chan, &priv->csa_chan, sizeof(struct cfg80211_chan_def));
+	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();
+}
+
+#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;
+	chan_band_info channel;
+	t_u16 enable = 0;
+
+	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;
+	}
+	ret = woal_mc_policy_cfg(priv, &enable, MOAL_IOCTL_WAIT, MLAN_ACT_GET);
+	if (enable) {
+		if (MLAN_STATUS_SUCCESS ==
+		    woal_get_active_intf_channel(priv, &channel)) {
+			if (channel.channel != chandef->chan->hw_value) {
+				PRINTM(MERROR,
+				       "DFS channel is not allowed when another connection exists on different channel\n");
+				PRINTM(MERROR,
+				       "Another connection's channel=%d, dfs channel=%d\n",
+				       channel.channel,
+				       chandef->chan->hw_value);
+				ret = -EINVAL;
+				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(&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 defined(DFS_TESTING_SUPPORT)
+	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);
+	}
+#endif
+
+	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 {
+		memcpy(&handle->dfs_channel, chandef,
+		       sizeof(struct cfg80211_chan_def));
+		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;
+	}
+
+	memcpy(&priv->csa_chan, &params->chandef,
+	       sizeof(struct cfg80211_chan_def));
+	memcpy(&priv->beacon_after, &params->beacon_after,
+	       sizeof(struct cfg80211_beacon_data));
+
+	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
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+/**
+ * @brief Notify cfg80211 uap 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_uap_channel(moal_private *priv,
+				 chan_band_info * pchan_info)
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	struct cfg80211_chan_def chandef;
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+	enum nl80211_channel_type type;
+	enum ieee80211_band band;
+	int freq = 0;
+#endif
+#endif
+	ENTER();
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_chandef_create(priv, &chandef, pchan_info)) {
+		cfg80211_ch_switch_notify(priv->netdev, &chandef);
+		priv->channel = pchan_info->channel;
+		memcpy(&priv->chan, &chandef, sizeof(struct cfg80211_chan_def));
+	}
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+	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
+
+/**
+ * @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_sd8897/mlinux/moal_uap_cfg80211.h b/wlan_sd8897/mlinux/moal_uap_cfg80211.h
new file mode 100644
index 0000000..f28cdb7
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_uap_cfg80211.h
@@ -0,0 +1,29 @@
+/** @file moal_uap_cfg80211.h
+  *
+  * @brief This file contains the uAP CFG80211 specific defines.
+  *
+  * Copyright (C) 2014-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _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_sd8897/mlinux/moal_uap_priv.c b/wlan_sd8897/mlinux/moal_uap_priv.c
new file mode 100644
index 0000000..d8d51fa
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_uap_priv.c
@@ -0,0 +1,180 @@
+/** @file  moal_uap_priv.c
+  *
+  * @brief This file contains standard ioctl functions
+  *
+  * Copyright (C) 2010-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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, wrq->u.data.pointer,
+						  wrq->u.data.length);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	case WOAL_UAP_SETONEINT_GETONEINT:
+		switch (wrq->u.data.flags) {
+		case WOAL_UAP_SET_GET_BSS_ROLE:
+			ret = woal_set_get_bss_role(priv, wrq);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+#endif
+#endif
+	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, 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_sd8897/mlinux/moal_uap_priv.h b/wlan_sd8897/mlinux/moal_uap_priv.h
new file mode 100644
index 0000000..ea5e984
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_uap_priv.h
@@ -0,0 +1,194 @@
+/** @file  moal_uap_priv.h
+  *
+  * @brief This file contains definition for extended private IOCTL call.
+  *
+  * Copyright (C) 2010-2018, Marvell International Lt.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/** Private command ID to set one int/get one int */
+#define WOAL_UAP_SETONEINT_GETONEINT            (WOAL_UAP_IOCTL + 5)
+/** 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)
+
+/**
+ * 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"},
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	{
+	 WOAL_UAP_SETONEINT_GETONEINT,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 ""},
+	{
+	 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"},
+};
+
+#endif /* _MOAL_UAP_PRIV_H_ */
diff --git a/wlan_sd8897/mlinux/moal_uap_wext.c b/wlan_sd8897/mlinux/moal_uap_wext.c
new file mode 100644
index 0000000..70c5cba
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_uap_wext.c
@@ -0,0 +1,1879 @@
+/** @file  moal_uap_wext.c
+  *
+  * @brief This file contains wireless extension standard ioctl functions
+  *
+  * Copyright (C) 2010-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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;
+
+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},
+};
+
+/** 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 < 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, char *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,
+	      char *cwrq, char *extra)
+{
+	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,
+	     struct sockaddr *awrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+
+	ENTER();
+
+	if (priv->bss_started)
+		memcpy(awrq->sa_data, priv->current_addr, MLAN_MAC_ADDR_LENGTH);
+	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,
+	     struct sockaddr *awrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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 < ap_cfg->num_of_chan; i++)
+		if (ap_cfg->chan_list[i].chan_number == chan)
+			break;
+	if (i == 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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+		  t_u32 *uwrq, char *extra)
+{
+	int ret = 0;
+	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,
+		  t_u32 *uwrq, char *extra)
+{
+	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)
+			memcpy(pkey->key, extra, dwrq->length);
+		/* 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)
+					memcpy(pkey, &ap_cfg->wep_cfg.key0,
+					       sizeof(wep_key));
+				if (key_index == 1)
+					memcpy(pkey, &ap_cfg->wep_cfg.key1,
+					       sizeof(wep_key));
+				if (key_index == 2)
+					memcpy(pkey, &ap_cfg->wep_cfg.key2,
+					       sizeof(wep_key));
+				if (key_index == 3)
+					memcpy(pkey, &ap_cfg->wep_cfg.key3,
+					       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,
+		struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+			memcpy(extra, pkey->key, pkey->length);
+			dwrq->flags &= ~IW_ENCODE_DISABLED;
+		} else {
+			ret = -EFAULT;
+		}
+		break;
+	case PROTOCOL_WPA:
+	case PROTOCOL_WPA2:
+	case PROTOCOL_WPA2_MIXED:
+		memcpy(extra, ap_cfg->wpa_cfg.passphrase,
+		       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,
+		struct iw_point *dwrq, 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,
+		struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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");
+			}
+			memcpy(priv->bcn_ie_buf + priv->bcn_ie_len,
+			       ((t_u8 *)tlv),
+			       sizeof(IEEEtypes_Header_t) + tlv->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);
+			}
+			memcpy(priv->bcn_ie_buf + priv->bcn_ie_len,
+			       ((t_u8 *)tlv),
+			       sizeof(IEEEtypes_Header_t) + tlv->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,
+		    struct iw_point *dwrq, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+			memcpy(pwep_key->key, pkey_material, ext->key_len);
+		}
+	} 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;
+		memcpy(sec->param.encrypt_key.key_material, pkey_material,
+		       ext->key_len);
+		memcpy(sec->param.encrypt_key.mac_addr, ext->addr.sa_data,
+		       ETH_ALEN);
+		sec->param.encrypt_key.key_flags = ext->ext_flags;
+		if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->rx_seq,
+			       SEQ_MAX_SIZE);
+			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) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->tx_seq,
+			       SEQ_MAX_SIZE);
+			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,
+		    struct iw_point *dwrq, 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, struct iw_point *dwrq, 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)) {
+		memcpy(sta_addr, (t_u8 *)mlme->addr.sa_data, ETH_ALEN);
+		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;
+			}
+			memcpy(sta_list, &pinfo->param.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 (!memcmp(bc_addr, sta_addr, ETH_ALEN)) {
+			for (i = 0; i < sta_list->sta_count; i++) {
+				memcpy(bss->param.deauth_param.mac_addr,
+				       sta_list->info[i].mac_address, ETH_ALEN);
+				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 {
+			memcpy(bss->param.deauth_param.mac_addr, sta_addr,
+			       ETH_ALEN);
+			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,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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");
+		ret = -EFAULT;
+		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,
+	      struct iw_param *vwrq, 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");
+		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,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_point *dwrq, 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,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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
+
+	memcpy(sys_cfg->ssid.ssid, extra,
+	       MIN(sys_cfg->ssid.ssid_len, MLAN_MAX_SSID_LENGTH));
+	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);
+		memcpy(extra, ap_cfg->ssid.ssid, 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
+********************************************************/
+
+/** 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
+};
+
+/**
+ *  @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_sd8897/mlinux/moal_wext.c b/wlan_sd8897/mlinux/moal_wext.c
new file mode 100644
index 0000000..b1ad6be
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_wext.c
@@ -0,0 +1,3157 @@
+/** @file  moal_wext.c
+  *
+  * @brief This file contains wireless extension standard ioctl functions
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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 */
+/** Macro for minimum size of scan buffer */
+#define MIN_ACCEPTED_GET_SCAN_BUF 8000
+
+/********************************************************
+			Global Variables
+********************************************************/
+extern int hw_test;
+/********************************************************
+			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));
+	memcpy(priv->nick_name, extra, dwrq->length);
+	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, char *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,
+	      char *cwrq, char *extra)
+{
+	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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+		  t_u32 *uwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	     struct sockaddr *awrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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)
+		memcpy(awrq->sa_data, &bss_info.bssid, MLAN_MAC_ADDR_LENGTH);
+	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 sockaddr 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,
+	     struct sockaddr *awrq, 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);
+	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;
+		}
+		memcpy(&ssid_bssid.bssid, awrq->sa_data, ETH_ALEN);
+	}
+
+	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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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,
+		  t_u32 *uwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_param *vwrq, 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,
+	      struct iw_param *vwrq, 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 (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;
+	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;
+		memcpy(sec->param.encrypt_key.key_material, extra,
+		       dwrq->length);
+		/* 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,
+		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;
+	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) {
+		memcpy(extra, sec->param.encrypt_key.key_material,
+		       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,
+		struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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);
+	memcpy(extra, ie, 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,
+		struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+		    struct iw_point *dwrq, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+	memcpy(sec->param.encrypt_key.mac_addr, (u8 *)ext->addr.sa_data,
+	       ETH_ALEN);
+	/* 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;
+		memcpy(sec->param.encrypt_key.key_material, pkey_material,
+		       ext->key_len);
+		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) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->rx_seq,
+			       SEQ_MAX_SIZE);
+			DBG_HEXDUMP(MCMD_D, "Rx PN", sec->param.encrypt_key.pn,
+				    SEQ_MAX_SIZE);
+		}
+		if (ext->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->tx_seq,
+			       SEQ_MAX_SIZE);
+			DBG_HEXDUMP(MCMD_D, "Tx PN", sec->param.encrypt_key.pn,
+				    SEQ_MAX_SIZE);
+		}
+		memcpy(sec->param.encrypt_key.key_material, pkey_material,
+		       ext->key_len);
+		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;
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->tx_seq,
+			       SEQ_MAX_SIZE);
+			memcpy(&sec->param.encrypt_key.pn[SEQ_MAX_SIZE],
+			       (t_u8 *)ext->rx_seq, 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,
+		    struct iw_point *dwrq, 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, struct iw_point *dwrq, 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,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	       struct iw_point *dwrq, char *extra)
+{
+	int i;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+	}
+	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 (!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;
+		}
+		memcpy(country_code, buf + strlen("COUNTRY") + 1,
+		       COUNTRY_CODE_LEN - 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(dwrq->pointer, buf, dwrq->length))
+		ret = -EFAULT;
+done:
+	kfree(buf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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;
+			memcpy(req_ssid.ssid,
+			       (t_u8 *)req->essid, req->essid_len);
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_request_scan(priv, MOAL_NO_WAIT, &req_ssid)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	} else {
+#endif
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_request_scan(priv, MOAL_NO_WAIT, NULL)) {
+			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,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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 */
+		memcpy(req_ssid.ssid, extra,
+		       MIN(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);
+		memcpy(&ssid_bssid.ssid, &req_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 (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) {
+		memcpy(&priv->prev_ssid_bssid.ssid, &req_ssid,
+		       sizeof(mlan_802_11_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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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);
+		memcpy(extra, bss_info.ssid.ssid, 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;
+		memcpy(iwe.u.ap_addr.sa_data, &scan_table[i].mac_address,
+		       ETH_ALEN);
+
+		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;
+					memcpy(buf, praw_data,
+					       element_len +
+					       sizeof(IEEEtypes_Header_t));
+					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 = 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 = &mic;
+	iwrq.data.length = sizeof(mic);
+
+	wireless_send_event(priv->netdev, IWEVMICHAELMICFAILURE, &iwrq,
+			    (char *)&mic);
+
+	LEAVE();
+	return;
+}
+#endif
+
+#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
+};
+
+/**
+ *  @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;
+	woal_get_stats_info(priv, wait_option, NULL);
+
+	LEAVE();
+	return &priv->w_stats;
+}
+#endif /* STA_SUPPORT */
diff --git a/wlan_sd8897/mlinux/moal_wext.h b/wlan_sd8897/mlinux/moal_wext.h
new file mode 100644
index 0000000..00c6be6
--- /dev/null
+++ b/wlan_sd8897/mlinux/moal_wext.h
@@ -0,0 +1,51 @@
+/** @file moal_wext.h
+ *
+ * @brief This file contains definition for wireless extension IOCTL call.
+ *
+ * Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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_ */
diff --git a/wlan_sd8897/script/wifidirect/start_auto_go.sh b/wlan_sd8897/script/wifidirect/start_auto_go.sh
new file mode 100755
index 0000000..78aa8a8
--- /dev/null
+++ b/wlan_sd8897/script/wifidirect/start_auto_go.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# iwpriv mlan0 drvdbg 0x20037
+# change the mac address
+./wifidirect/update_mac.sh
+echo "wfd0 Mac address updated in config/wifidirect.conf"
+
+
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 1
+#else
+# iwpriv wfd0 bssrole 1
+#endif
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 0
+#else
+# iwpriv wfd0 bssrole 0
+#endif
+# iwpriv wfd0 bssrole 1
+# change the group owner parameters
+# either in uaputl_wifidirect.conf or using CLI below
+#./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+#./uaputl.exe -i wfd0 sys_cfg_eapol_gwk_hsk 2000 3
+#./uaputl.exe -i wfd0 sys_cfg_eapol_pwk_hsk 2000 3
+# iwpriv wfd0 bssrole 0
+./wifidirectutl wfd0 wifidirect_mode 1
+iwpriv wfd0 bssrole 1
+./wifidirectutl wfd0 wifidirect_mode 2
+./uaputl.exe -i wfd0 bss_start
diff --git a/wlan_sd8897/script/wifidirect/start_find_phase.sh b/wlan_sd8897/script/wifidirect/start_find_phase.sh
new file mode 100755
index 0000000..26ddd60
--- /dev/null
+++ b/wlan_sd8897/script/wifidirect/start_find_phase.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# iwpriv wfd0 drvdbg 0x20037
+#change the mac address
+./wifidirect/update_mac.sh
+echo "wfd0 Mac address updated in config/wifidirect.conf"
+
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 1
+#else
+# iwpriv wfd0 bssrole 1
+#endif
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 0
+#else
+# iwpriv wfd0 bssrole 0
+#endif
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+# change the passphrase
+# either in uaputl_wifidirect.conf or using CLI below
+#./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+./wifidirectutl wfd0 wifidirect_mode 1
+./wifidirectutl wfd0 wifidirect_params_config config/wifidirect.conf
+./mlanutl wfd0 hostcmd config/bg_scan_wifidirect.conf bgscfg
+./wifidirectutl wfd0 wifidirect_mode 4
diff --git a/wlan_sd8897/script/wifidirect/start_listen_state.sh b/wlan_sd8897/script/wifidirect/start_listen_state.sh
new file mode 100755
index 0000000..91c1e4d
--- /dev/null
+++ b/wlan_sd8897/script/wifidirect/start_listen_state.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+iwpriv wfd0 drvdbg 0x20037
+# change the mac address
+ifconfig mlan0 hw ether 00:50:43:21:0e:08
+ifconfig wfd0 hw ether 00:50:43:21:0e:08
+ifconfig uap0 hw ether 00:50:43:21:0e:08
+
+iwpriv wfd0 deepsleep 0
+iwconfig wfd0 power off
+
+iwpriv wfd0 bssrole 1
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+iwpriv wfd0 bssrole 0
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+./uaputl.exe -i wfd0 sys_cfg_protocol 32
+./uaputl.exe -i wfd0 sys_cfg_cipher 8 8
+./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+./wifidirectutl wfd0 wifidirect_mode 1
diff --git a/wlan_sd8897/script/wifidirect/stop_auto_go.sh b/wlan_sd8897/script/wifidirect/stop_auto_go.sh
new file mode 100755
index 0000000..eda03ef
--- /dev/null
+++ b/wlan_sd8897/script/wifidirect/stop_auto_go.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+./uaputl.exe -i wfd0 bss_stop
+sleep 1
+iwpriv wfd0 bssrole 0
+./wifidirectutl wfd0 wifidirect_mode 0
+# IE clear assume index 0, 1
+./uaputl.exe -i wfd0 sys_cfg_custom_ie 0 0
+./uaputl.exe -i wfd0 sys_cfg_custom_ie 1 0
diff --git a/wlan_sd8897/script/wifidirect/stop_wifidirect_client.sh b/wlan_sd8897/script/wifidirect/stop_wifidirect_client.sh
new file mode 100755
index 0000000..5ae1ad5
--- /dev/null
+++ b/wlan_sd8897/script/wifidirect/stop_wifidirect_client.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# deauth the GO first
+./wifidirectutl wfd0 wifidirect_mode 0
+# IE clear assume index 0, 1
+./uaputl.exe -i wfd0 sys_cfg_custom_ie 0 0
+./uaputl.exe -i wfd0 sys_cfg_custom_ie 1 0
diff --git a/wlan_sd8897/script/wifidirect/update_mac.sh b/wlan_sd8897/script/wifidirect/update_mac.sh
new file mode 100755
index 0000000..d744db9
--- /dev/null
+++ b/wlan_sd8897/script/wifidirect/update_mac.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+MAC=`ifconfig wfd0 | grep wfd0 | tr -s ' ' | cut -d ' ' -f5`
+MAC26=`echo $MAC | cut -d ':' -f2-6`
+LAA=`echo $MAC | cut -d ':' -f1`
+LAA=$((0x$LAA+2))
+if [ $LAA -lt 16 ] ; then
+LAA=`printf "%X\n" $LAA`
+MACLAA=0$LAA:$MAC26
+else
+LAA=`printf "%X\n" $LAA`
+MACLAA=$LAA:$MAC26
+fi
+sed "s/00:50:43:00:00:00/$MAC/" config/wifidirect.conf > tmp$$
+mv tmp$$ config/wifidirect.conf
+sed "s/02:50:43:00:00:00/$MACLAA/" config/wifidirect.conf > tmp$$
+mv tmp$$ config/wifidirect.conf
diff --git a/wlan_sd8897/script/wifidisplay/start_auto_go.sh b/wlan_sd8897/script/wifidisplay/start_auto_go.sh
new file mode 100755
index 0000000..cc8b49a
--- /dev/null
+++ b/wlan_sd8897/script/wifidisplay/start_auto_go.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# iwpriv mlan0 drvdbg 0x20037
+# change the mac address
+./wifidirect/update_mac.sh
+echo "wfd0 Mac address updated in config/wifidirect.conf"
+
+
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 1
+#else
+# iwpriv wfd0 bssrole 1
+#endif
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 0
+#else
+# iwpriv wfd0 bssrole 0
+#endif
+# iwpriv wfd0 bssrole 1
+# change the group owner parameters
+# either in uaputl_wifidirect.conf or using CLI below
+#./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+#./uaputl.exe -i wfd0 sys_cfg_eapol_gwk_hsk 2000 3
+#./uaputl.exe -i wfd0 sys_cfg_eapol_pwk_hsk 2000 3
+# iwpriv wfd0 bssrole 0
+./wifidirectutl wfd0 wifidirect_mode 1
+./wifidirectutl wfd0 wifidirect_mode 5
+
+#enable wifi-display
+./wifidirectutl wfd0 wifidisplay_mode 1
+./wifidirectutl wfd0 wifidisplay_config config/wifidisplay.conf
+
+iwpriv wfd0 bssrole 1
+./wifidirectutl wfd0 wifidirect_mode 2
+./uaputl.exe -i wfd0 bss_start
diff --git a/wlan_sd8897/script/wifidisplay/start_find_phase.sh b/wlan_sd8897/script/wifidisplay/start_find_phase.sh
new file mode 100755
index 0000000..8fef6d0
--- /dev/null
+++ b/wlan_sd8897/script/wifidisplay/start_find_phase.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# iwpriv wfd0 drvdbg 0x20037
+#change the mac address
+./wifidirect/update_mac.sh
+echo "wfd0 Mac address updated in config/wifidirect.conf"
+
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 1
+#else
+# iwpriv wfd0 bssrole 1
+#endif
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 0
+#else
+# iwpriv wfd0 bssrole 0
+#endif
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+# change the passphrase
+# either in uaputl_wifidirect.conf or using CLI below
+#./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+./wifidirectutl wfd0 wifidirect_mode 1
+./wifidirectutl wfd0 wifidirect_params_config config/wifidirect.conf
+./mlanconfig wfd0 hostcmd config/bg_scan_wifidirect.conf bgscfg
+./wifidirectutl wfd0 wifidirect_mode 4
+
+#enable wifi-display
+./wifidirectutl wfd0 wifidisplay_mode 1
+./wifidirectutl wfd0 wifidisplay_config config/wifidisplay.conf
+
diff --git a/wlan_sd8897/script/wifidisplay/update_mac.sh b/wlan_sd8897/script/wifidisplay/update_mac.sh
new file mode 100755
index 0000000..d744db9
--- /dev/null
+++ b/wlan_sd8897/script/wifidisplay/update_mac.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+MAC=`ifconfig wfd0 | grep wfd0 | tr -s ' ' | cut -d ' ' -f5`
+MAC26=`echo $MAC | cut -d ':' -f2-6`
+LAA=`echo $MAC | cut -d ':' -f1`
+LAA=$((0x$LAA+2))
+if [ $LAA -lt 16 ] ; then
+LAA=`printf "%X\n" $LAA`
+MACLAA=0$LAA:$MAC26
+else
+LAA=`printf "%X\n" $LAA`
+MACLAA=$LAA:$MAC26
+fi
+sed "s/00:50:43:00:00:00/$MAC/" config/wifidirect.conf > tmp$$
+mv tmp$$ config/wifidirect.conf
+sed "s/02:50:43:00:00:00/$MACLAA/" config/wifidirect.conf > tmp$$
+mv tmp$$ config/wifidirect.conf
diff --git a/wlan_sd8987/Makefile b/wlan_sd8987/Makefile
new file mode 100644
index 0000000..dbbaf0c
--- /dev/null
+++ b/wlan_sd8987/Makefile
@@ -0,0 +1,591 @@
+# File: Makefile
+#
+# Copyright (C) 2008-2018, Marvell International Ltd.
+#
+# This software file (the "File") is distributed by Marvell International
+# Ltd. under the terms of the GNU General Public License Version 2, June 1991
+# (the "License").  You may use, redistribute and/or modify this File in
+# accordance with the terms and conditions of the License, a copy of which
+# is available by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# A copy of the GPL is available in file gpl-2.0.txt accompanying in this
+# deliverables.
+#
+# 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.
+
+CC=		$(CROSS_COMPILE)clang
+LD=		$(CROSS_COMPILE)ld.lld
+BACKUP=		/root/backup
+YMD=		`date +%Y%m%d%H%M`
+
+ifneq ($(COMPAT_VERSION_CODE),)
+DRV_DIR ?= $(shell pwd)
+export DRV_DIR
+COMPAT_VERSION=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$1}')
+COMPAT_PATCHLEVEL=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$2}')
+COMPAT_SUBLEVEL=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$3}')
+DECL_HEADER_FILE=$(DRV_DIR)/mlinux/moal_main.h
+$(shell sed -i 's/COMPAT_VERSION_CODE KERNEL_VERSION.*/COMPAT_VERSION_CODE KERNEL_VERSION(\
+		$(COMPAT_VERSION), $(COMPAT_PATCHLEVEL), $(COMPAT_SUBLEVEL))/g' $(DECL_HEADER_FILE))
+endif
+
+#############################################################################
+# Configuration Options
+#############################################################################
+
+# Debug Option
+# DEBUG LEVEL n/1/2:
+# n: NO DEBUG
+# 1: Only PRINTM(MMSG,...), PRINTM(MFATAL,...), ...
+# 2: All PRINTM()
+CONFIG_DEBUG=1
+
+# Proc debug file
+CONFIG_PROC_DEBUG=y
+
+# 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 WIFIDISPLAY support
+CONFIG_WIFI_DISPLAY_SUPPORT=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
+
+# Enable SDIO multi-port Tx aggregation
+CONFIG_SDIO_MULTI_PORT_TX_AGGR=y
+
+# Enable SDIO multi-port Rx aggregation
+CONFIG_SDIO_MULTI_PORT_RX_AGGR=y
+
+# SDIO suspend/resume
+CONFIG_SDIO_SUSPEND_RESUME=y
+
+# DFS testing support
+CONFIG_DFS_TESTING_SUPPORT=y
+
+# Multi-channel support
+CONFIG_MULTI_CHAN_SUPPORT=y
+
+
+CONFIG_ANDROID_KERNEL=n
+
+
+#32bit app over 64bit kernel support
+CONFIG_USERSPACE_32BIT_OVER_KERNEL_64BIT=n
+
+
+#############################################################################
+# Select Platform Tools
+#############################################################################
+
+MODEXT = ko
+ccflags-y += -I$(M)/mlan
+ccflags-y += -DLINUX
+
+
+
+
+LD += -S
+
+BINDIR = ../bin_sd8xxx
+APPDIR= $(shell if test -d "mapp"; then echo mapp; fi)
+
+#############################################################################
+# Compiler Flags
+#############################################################################
+
+	ccflags-y += -I$(KERNELDIR)/include
+
+	ccflags-y += -DFPNUM='"100"'
+
+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_PROC_DEBUG),y)
+	ccflags-y += -DPROC_DEBUG
+	export CONFIG_PROC_DEBUG
+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_WIFI_DISPLAY_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_WIFI_DISPLAY_SUPPORT=n
+CONFIG_UAP_WEXT=n
+CONFIG_UAP_CFG80211=n
+endif
+
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	ccflags-y += -DWIFI_DIRECT_SUPPORT
+endif
+ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y)
+	ccflags-y += -DWIFI_DISPLAY_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
+
+ifeq ($(CONFIG_SDIO_MULTI_PORT_TX_AGGR),y)
+	ccflags-y += -DSDIO_MULTI_PORT_TX_AGGR
+endif
+
+ifeq ($(CONFIG_SDIO_MULTI_PORT_RX_AGGR),y)
+	ccflags-y += -DSDIO_MULTI_PORT_RX_AGGR
+endif
+
+ifeq ($(CONFIG_SDIO_SUSPEND_RESUME),y)
+	ccflags-y += -DSDIO_SUSPEND_RESUME
+endif
+
+ifeq ($(CONFIG_MULTI_CHAN_SUPPORT),y)
+	ccflags-y += -DMULTI_CHAN_SUPPORT
+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
+
+# 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
+
+#############################################################################
+# 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_UAP_CFG80211=y
+else
+ifeq ($(CPTCFG_CFG80211),m)
+	CONFIG_UAP_CFG80211=y
+else
+	CONFIG_UAP_CFG80211=n
+endif
+endif
+endif
+
+ifneq ($(CONFIG_STA_SUPPORT),y)
+	CONFIG_WIFI_DIRECT_SUPPORT=n
+	CONFIG_WIFI_DISPLAY_SUPPORT=n
+	CONFIG_STA_WEXT=n
+	CONFIG_STA_CFG80211=n
+endif
+
+ifneq ($(CONFIG_UAP_SUPPORT),y)
+	CONFIG_WIFI_DIRECT_SUPPORT=n
+	CONFIG_WIFI_DISPLAY_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
+
+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
+MLANOBJS += mlan/mlan_sdio.o
+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_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_cfgvendor.o
+MOALOBJS += mlinux/moal_sta_cfg80211.o
+endif
+ifeq ($(CONFIG_UAP_CFG80211),y)
+MOALOBJS += mlinux/moal_cfg80211.o
+MOALOBJS += mlinux/moal_cfgvendor.o
+MOALOBJS += mlinux/moal_uap_cfg80211.o
+endif
+
+ifdef CONFIG_PROC_FS
+MOALOBJS += mlinux/moal_proc.o
+ifeq ($(CONFIG_PROC_DEBUG),y)
+MOALOBJS += mlinux/moal_debug.o
+endif
+endif
+
+
+
+
+
+
+
+
+ifeq ($(CONFIG_MULTI_INTERFACE),y)
+obj-$(CONFIG_BERLIN_SDIO_WLAN_8987) := mlan_sdio.o
+mlan_sdio-objs := $(MLANOBJS)
+else
+obj-$(CONFIG_BERLIN_SDIO_WLAN_8987) := mlan.o
+mlan-objs := $(MLANOBJS)
+endif
+MOALOBJS += mlinux/moal_sdio_mmc.o
+obj-$(CONFIG_BERLIN_SDIO_WLAN_8987) += sd8xxx.o
+sd8xxx-objs := $(MOALOBJS)
+
+# Otherwise we were called directly from the command line; invoke the kernel build system.
+else
+
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+endif
+
+###############################################################
+
+export		CC LD ccflags-y KERNELDIR
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+.PHONY: mapp/mlanconfig mapp/mlan2040coex mapp/mlanevent mapp/uaputl mapp/mlanutl clean distclean
+else
+.PHONY: mapp/mlanconfig mapp/mlanevent mapp/mlan2040coex mapp/mlanutl clean distclean
+endif
+else
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+.PHONY: mapp/mlanevent mapp/uaputl clean distclean
+endif
+endif
+	@echo "Finished Making Marvell Wlan Linux Driver"
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+mapp/mlanconfig:
+	$(MAKE) -C $@
+mapp/mlanutl:
+	$(MAKE) -C $@
+mapp/mlan2040coex:
+	$(MAKE) -C $@
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+mapp/uaputl:
+	$(MAKE) -C $@
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+mapp/wifidirectutl:
+	$(MAKE) -C $@
+endif
+mapp/mlanevent:
+	$(MAKE) -C $@
+
+echo:
+
+build:		echo default
+
+	@if [ ! -d $(BINDIR) ]; then \
+		mkdir $(BINDIR); \
+	fi
+
+ifeq ($(CONFIG_MULTI_INTERFACE),y)
+	cp -f mlan_sdio.$(MODEXT) $(BINDIR)/mlan_sdio$(DBG).$(MODEXT)
+else
+	cp -f mlan.$(MODEXT) $(BINDIR)/mlan$(DBG).$(MODEXT)
+endif
+	cp -f sd8xxx.$(MODEXT) $(BINDIR)/sd8xxx$(DBG).$(MODEXT)
+	cp -rpf script/sdio_mmc/* $(BINDIR)/
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	cp -f README $(BINDIR)
+	cp -f README_MLAN $(BINDIR)
+	cp -f README_RBC $(BINDIR)
+ifeq ($(CONFIG_OPENWRT_SUPPORT),y)
+	cp -f README_OPENWRT $(BINDIR)
+endif
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/mlanconfig $@ INSTALLDIR=$(BINDIR)
+	$(MAKE) -C mapp/mlanutl $@ INSTALLDIR=$(BINDIR)
+	$(MAKE) -C mapp/mlan2040coex $@ INSTALLDIR=$(BINDIR)
+endif
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	cp -f README_UAP $(BINDIR)
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/uaputl $@ INSTALLDIR=$(BINDIR)
+endif
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	cp -f README_WIFIDIRECT $(BINDIR)
+	cp -rpf script/wifidirect $(BINDIR)
+ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y)
+	cp -rpf script/wifidisplay $(BINDIR)
+endif
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/wifidirectutl $@ INSTALLDIR=$(BINDIR)
+endif
+endif
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/mlanevent $@ 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),)
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	$(MAKE) -C mapp/mlanconfig $@
+	$(MAKE) -C mapp/mlanutl $@
+	$(MAKE) -C mapp/mlan2040coex $@
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	$(MAKE) -C mapp/uaputl $@
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	$(MAKE) -C mapp/wifidirectutl $@
+endif
+	$(MAKE) -C mapp/mlanevent $@
+endif
+
+install: default
+
+	cp -f mlan.$(MODEXT) $(INSTALLDIR)/mlan$(DBG).$(MODEXT)
+	cp -f ../io/sdio/$(PLATFORM)/sdio.$(MODEXT) $(INSTALLDIR)
+
+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),)
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	$(MAKE) -C mapp/mlanconfig $@
+	$(MAKE) -C mapp/mlanutl $@
+	$(MAKE) -C mapp/mlan2040coex $@
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	$(MAKE) -C mapp/uaputl $@
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	$(MAKE) -C mapp/wifidirectutl $@
+endif
+	$(MAKE) -C mapp/mlanevent $@
+endif
+
+# End of file
diff --git a/wlan_sd8987/README b/wlan_sd8987/README
new file mode 100644
index 0000000..afecbe4
--- /dev/null
+++ b/wlan_sd8987/README
@@ -0,0 +1,2249 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2008-2018, Marvell International Ltd.
+ All Rights Reserved
+
+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 up to 4.18.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy firmware image sd8786_uapsta.bin | sd8787_uapsta.bin | ... to
+	   /lib/firmware/mrvl/ directory, create the directory if it doesn't exist.
+	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
+		The default drv_mode is 7.
+
+		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 2)
+		uap_name: Name of the uAP interface (default: "uap")
+		uap_max_sta: Maximum number of STA for UAP/GO (default 0, max 10)
+		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)
+	   For example, to install SD8787 driver,
+		insmod mlan.ko
+		insmod sd8787.ko [drv_mode=3] [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in STA only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=1 [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in uAP only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=2 [fw_name=mrvl/sd8787_uapsta.bin]
+
+	   To switch mode between STA only, uAP only and uAPSTA etc. in run time,
+		echo drv_mode=1 > /proc/mwlan/config		// STA mode
+		echo drv_mode=2 > /proc/mwlan/config		// uAP mode
+		echo drv_mode=3 > /proc/mwlan/config		// STA+uAP mode
+		echo drv_mode=7 > /proc/mwlan/config		// STA+uAP+WIFIDIRECT mode
+	c) Uninstall WLAN driver,
+		ifconfig mlanX down
+		ifconfig uapX down
+		rmmod sd8xxx
+		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>
+	  p2p_enh=0|1 <Disable enhanced P2P (default) | Enable enhanced P2P>
+	  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)>
+	  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>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf
+	  sdio_rx_aggr=1|2 <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
+	cfg80211_drcs=1|0 <Enable DRCS support (default) | Disable DRCS support>
+	  reg_alpha2=<Regulatory alpha2 (default NULL)>
+	  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>
+	  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
+
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sd8xxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+
+	The following info are provided in /proc/net/mwlan/mlanX/info,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX/info.
+
+	driver_name = "wlan"
+	driver_version = <chip id, firmware version and driver version>
+	interface_name = "mlanX"
+	bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown"
+	media_state = "Disconnected" | "Connected"
+	mac_address = <6-byte adapter MAC address>
+	multicase_count = <multicast address count>
+	essid = <current SSID>
+	bssid = <current BSSID>
+	channel = <current channel>
+	region_code = <current region code>
+	multicast_address[n] = <multicast address>
+	num_tx_bytes = <number of bytes sent to device>
+	num_rx_bytes = <number of bytes received from device and sent to kernel>
+	num_tx_pkts = <number of packets sent to device>
+	num_rx_pkts = <number of packets received from device and sent to kernel>
+	num_tx_pkts_dropped = <number of Tx packets dropped by driver>
+	num_rx_pkts_dropped = <number of Rx packets dropped by driver>
+	num_tx_pkts_err = <number of Tx packets failed to send to device>
+	num_rx_pkts_err = <number of Rx packets failed to receive from device>
+	carrier "on" | "off"
+	tx queue "stopped" | "started"
+
+	The following debug info are provided in /proc/net/mwlan/mlanX/debug,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX/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>
+	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>
+	sleep_pd = <sleep period in milliseconds>
+	qos_cfg = <WMM QoS info>
+	tx_lock_flag = <0/1, Tx lock flag>
+	port_open = <0/1, port open flag>
+	scan_processing = <0/1, scan processing flag>
+	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>
+	num_evt_disassoc = <number of disassociated events received from device>
+	num_evt_link_lost = <number of link lost events received from device>
+	num_cmd_deauth = <number of deauthenticate commands sent to device>
+	num_cmd_assoc_ok = <number of associate commands with success return>
+	num_cmd_assoc_fail = <number of associate commands with failure return>
+	cmd_sent = <0/1, send command resources available/sending command to device>
+	data_sent = <0/1, send data resources available/sending data to device>
+	mp_rd_bitmap = <SDIO multi-port read bitmap>
+	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>
+	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>
+	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>
+	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/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/config      # read func 0 address 4
+		cat /proc/mwlan/config                          # display the register value
+		echo "sdcmd52rw= 1 3 0xf" > /proc/mwlan/config  # write 0xf to func 1 address 3
+
+	Use dmesg or cat /var/log/debug to check driver debug messages.
+	To log driver debug messages to file,
+	a) Edit /etc/syslog.conf, add one line "*.debug		/var/log/debug"
+	   on kernel 2.6.24 or later, edit /etc/rsyslog.conf instead
+	b) touch /var/log/debug (if the file doesn't exist)
+	c) service syslog restart
+	   on kernel 2.6.24 or later, service rsyslog restart
+
+	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 IWPRIV COMMAND
+
+NAME
+	This manual describes the usage of private commands used in Marvell MLAN
+	Linux Driver.
+
+	To use parameters as hex format, a '0x' must precede it for the parameters to
+	be parsed properly.
+
+SYNOPSIS
+	iwpriv <mlanX> <command> [sub-command] ...
+
+	iwpriv mlanX version
+	iwpriv mlanX verext
+	iwpriv mlanX getsignal [m] [n]
+	iwpriv mlanX antcfg [m] [n]
+	iwpriv mlanX regioncode [n]
+	iwpriv mlanX cfpcode [m] [n]
+	iwpriv mlanX wwscfg [m]
+	iwpriv mlanX esuppmode
+	iwpriv mlanX passphrase <ssid/psk/passphrase>
+	iwpriv mlanX httxcfg [<m>] [<n>]
+	iwpriv mlanX htcapinfo [<m>] [<n>]
+	iwpriv mlanX addbapara <m> <n> <o> <p> <q>
+	iwpriv mlanX aggrpriotbl <n>
+	iwpriv mlanX addbareject <n>
+	iwpriv mlanX txbufcfg
+	iwpriv mlanX amsduaggrctrl <n>
+	iwpriv mlanX httxbfcap [cap]
+	iwpriv mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData]"
+	iwpriv mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+	iwpriv mlanX deepsleep [n] [m]
+	iwpriv mlanX hscfg [condition [[GPIO# [gap]]]]
+	iwpriv mlanX hssetpara condition [GPIO# [gap]]
+	iwpriv mlanX deauth [n]
+	iwpriv mlanX radioctrl
+	iwpriv mlanX reassoctrl [n]
+	iwpriv mlanX bandcfg [l] [m] [n] [o]
+	iwpriv mlanX getlog
+	iwpriv mlanX 11dcfg
+	iwpriv mlanX 11dclrtbl
+	iwpriv mlanX wmmcfg [n]
+	iwpriv mlanX hotspotcfg [n]
+	iwpriv mlanX txpowercfg [<RateIndex> [<MinPwr> [<MaxPwr> <step>]]]
+	iwpriv mlanX qoscfg
+	iwpriv mlanX getdatarate
+	iwpriv mlanX txratecfg [n]
+	iwpriv mlanX bcninterval [n]
+	iwpriv mlanX sysclock [clk1] [clk2] [clk3] [clk4]
+	iwpriv mlanX drvdbg [n]
+	iwpriv mlanX mgmtframectrl
+	iwpriv mlanX warmreset
+	iwpriv mlanX regrdwr <type> <offset> [value]
+	iwpriv mlanX rdeeprom <offset> <length>
+	iwpriv mlanX memrdwr <address> [value]
+	iwpriv mlanX inactivityto <n> <m> <l> [k]
+	iwpriv mlanX sdioclock <n>
+	iwpriv mlanX sdcmd52rw <FN no.> <address> [data]
+	iwpriv mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+	iwpriv mlanX sleeppd [n]
+	iwpriv mlanX pscfg [k] [d] [l] ...
+	iwpriv mlanX getkey
+	iwpriv mlanX associate "<bssid> <ssid>"
+	iwpriv mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+	iwpriv mlanX authtype [n]
+	iwpriv mlanX powercons [n]
+	iwpriv mlanX htstreamcfg [n]
+	iwpriv mlanX ipaddr ["<op>;<ipaddr>"]
+	iwpriv mlanX macctrl [n]
+	iwpriv mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+	iwpriv mlanX thermal
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell 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.
+
+version
+	This is used to get the current version of the driver and the firmware.
+
+verext
+	Retrieve and display an extended version string from the firmware
+
+	Usage:
+		iwpriv mlanX verext [#]
+
+	where [#] is an optional argument to retrieve a specific version string,
+	omission of the argument retrieves the 0 indexed string.
+
+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:
+		iwpriv mlan0 getsignal 1        : Get the RSSI info (beacon last, beacon
+		                                  average, data last and data average)
+		iwpriv mlan0 getsignal 3 4      : Get the NF of data average
+		iwpriv mlan0 getsignal 2 1      : Get the SNR of beacon last
+		iwpriv 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
+
+antcfg
+	This command is used to set/get the mode of Tx/Rx path.
+
+	where value of m is:
+		Bit 0   -- Tx Path A
+		Bit 1   -- Tx Path B
+		Bit 0-1 -- Tx Path A+B
+
+	where value of n is:
+		Bit 0   -- Rx Path A
+		Bit 1   -- Rx Path B
+		Bit 0-1 -- Rx Path A+B
+	The Tx path setting (m) is used if Rx path (n) is not provided.
+
+	Examples:
+		iwpriv mlan0 antcfg             : Get Tx and Rx path
+		iwpriv mlan0 antcfg 3           : Set Tx and Rx path to A+B
+		iwpriv mlan0 antcfg 1 3         : Set Tx path to A and Rx path to A+B
+
+regioncode
+	This command is used to set/get the region code in the station.
+	Note: This command should be issued at beginning before band/channel selection
+	and association.
+
+	where value is 'region code' for various regions like
+	USA FCC, Canada IC, Europe ETSI, Japan ...
+	The special code (0xff) is used for Japan to support channel 1-14 in B/G/N mode.
+
+	Examples:
+		iwpriv mlan0 regioncode         : Get region code
+		iwpriv mlan0 regioncode 0x10    : Set region code to USA (0x10)
+
+	Note : in some case regioncode will be 0 after updated countycode or 80211d
+		i.e. mlanutl mlanX countrycode  (CA, JP, CN, DE, ES AT, BR, RU)
+		or uaputl.exe sys_cfg_80211d state 1 country (CA, JP, CN, DE, ES AT, BR, RU)
+		Please use cfp instead of it.
+
+cfpcode
+	This command is used to set/get the Channel-Frequency-Power table codes.
+	The region table can be selected through region code.
+	The current configuration is returned if no parameter provided.
+
+	where the parameters are,
+		[m]: code of the CFP table for 2.4GHz (0: unchanged)
+		[n]: code of the CFP table for 5GHz (0 or not provided: unchanged)
+
+	Examples:
+		iwpriv mlan0 cfpcode            : Get current configuration
+		iwpriv mlan0 cfpcode 0x30       : Set 2.4GHz CFP table code 0x30 (EU),
+		                                  keep 5GHz table unchanged
+		iwpriv mlan0 cfpcode 0x10 5     : Set 2.4GHz CFP table code 0x10 (USA)
+		                                  and 5GHz table code 5
+
+wwscfg
+	This command is used to set/get the WWS (World Wide Safe) mode.
+
+	where value of m is:
+		0       -- Disable WWS mode (default)
+		1       -- Enable WWS mode
+
+	Examples:
+		iwpriv mlan0 wwscfg             : Get WWS mode
+		iwpriv mlan0 wwscfg 1           : Enable WWS mode
+		iwpriv mlan0 wwscfg 0           : Disable WWS mode
+
+esuppmode
+	This command is used to get the current RSN mode and active pairwise/group
+    cipher for WPA/WPA2 mode.
+	Note: This command is available only when STA is connected.
+
+	These are bits settings used to indicate each RSN mode.
+		Bit 0    : No RSN
+		Bit 1-2  : RFU
+		Bit 3    : WPA
+		Bit 4    : WPA-NONE
+		Bit 5    : WPA2
+		Bit 6    : AES
+		Bit 7-15 : RFU
+
+	These are bits settings used to indicate each pairwise and group cipher.
+		Bit 0    : RFU
+		Bit 1    : RFU
+		Bit 2    : TKIP
+		Bit 3    : AES
+		Bit 2-7  : RFU
+
+	Example:
+		iwpriv mlan0 esuppmode          : Get RSN mode and pairwise/group cipher
+		8 4 4
+		(The current RSN mode is WPA, active pairwise cipher is TKIP and
+		 active group cipher is TKIP.)
+
+passphrase
+	This command is used to set/get passphrase for WPA-PSK/WPA2-PSK mode.
+
+	Where <n>
+		ASCII string for ssid/passphrase/psk.
+
+	1) "0;<ssid=valid ssid>" - This will get the passphrase, AKMP
+	   for specified ssid, if none specified then it will get all.
+
+	Example:
+		iwpriv mlan0 passphrase "0;ssid=marvell"
+
+	2) "1;<psk=64 byte hexpsk>;<passphrase=1-63 byte passphare>
+	   <ssid=valid ssid>" - Passphrase and psk cannot be provided for the same SSID.
+	   This command takes only one SSID at a time, If ssid= is present 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 ';' or '/' has to be used in an SSID then a '/' should be preceded
+	   to ';' or '/' as a escape.
+
+	Examples:
+		iwpriv mlan0 passphrase "1;ssid=mrvlAP;passphrase=abcdefgd"
+		iwpriv mlan0 passphrase "1;ssid=mrvl AP;psk=<64 bytes hexpsk>"
+
+		If user wants to input the ssid as "mrvl; AP" then command has to be
+		iwpriv mlan0 passphrase "1;ssid=mrvl/; AP;passphrase=abcdefgh"
+
+		If user wants to input the ssid as "//;" then command has to be
+		iwpriv mlan0 passphrase "1;ssid=/////;;passphrase=abcdefgh"
+
+	3) "2;<ssid=valid ssid>" - This will clear the passphrase
+	   for specified ssid, if none specified then it will clear all.
+
+	Examples:
+		iwpriv mlan0 passphrase "2;ssid=marvell"
+		iwpriv mlan0 passphrase "2"     : Clear all profiles and disable embedded supplicant
+
+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
+
+	Examples:
+		iwpriv mlanX httxcfg
+		This will display HT Tx configuration.
+		If the configurations for 2.4G and 5G are 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.
+
+		iwpriv mlanX httxcfg 0x62
+		This will enable 20/40 and Short GI but will disable Green field for 2.4G and 5G band.
+
+		iwpriv 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 24: Short GI in 40 Mhz enable/disable
+		Bit 23: Short GI in 20 Mhz 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
+
+	Examples:
+		iwpriv 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.
+
+		iwpriv mlanX htcapinfo 0x1820000
+		This will enable Short GI, Channel BW to 20/40 and disable Green field support for 2.4G and 5G band.
+
+		iwpriv 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).
+
+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:
+	iwpriv mlanX addbapara - This command will get the current addba params
+	iwpriv 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.
+
+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:
+	iwpriv 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
+	iwpriv 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.
+	iwpriv 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.
+
+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:
+	iwpriv 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.
+
+	iwpriv 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]
+
+	iwpriv 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.
+
+txbufcfg
+	This command can be used to get current buffer size.
+
+	eg:
+	iwpriv mlanX txbufcfg 	  - This will display the current buffer size.
+
+	Note:- The actual tx buf size will depends on AP's capability and max transmit buffer size.
+
+amsduaggrctrl
+	This command could be used to enable/disable a feature where firmware gives feedback to driver
+	regarding the optimal AMSDU buffer size to use with the current rate. Firmware will use the
+	current rate to decide the buffer size we could transmit. The max buffer size will still be
+	limited by buffer size provided in txbufcfg. (i.e. if the txbufcfg is 4K, then we could only transmit
+	4K/2K AMSDU packets, if the txbufcfg is 8K then we could transmit 8k/4k/2k based on current rate)
+
+	If enabled AMSDU buffer size at various rates will be as follows
+
+	1.	Legacy B/G rate.
+		No AMSDU aggregation.
+
+	2.	BW20 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 3, 2:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 1, 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 4, 3:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	3.	BW40 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4, 3, 2, 1:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5, 4, 3:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	where <n> is 0/1 (for disable/enable)
+
+	eg:
+	iwpriv mlanx amsduaggrctrl 1 - Enable this feature
+	iwpriv mlanx amsduaggrctrl 0 - Disable this feature
+	iwpriv mlanx amsduaggrctrl - This will get the enable/disable flag
+	and the current AMSDU buffer size). The AMSDU buffer size returned is only
+	valid after association as before association there is no rate info.
+
+	Note:- This command to enable/disable could be given anytime (before/after
+			association). This feature is enabled by default by the driver during
+			initialization.
+
+httxbfcap
+	This command is used to set/get the TX beamforming capabilities.
+
+	Usage:
+		iwpriv mlanX httxbfcap [cap]
+
+	where the parameters are,
+		cap: TX beamforming capabilities
+			 Bit 0    : Implicit TX BF receiving capable
+			 Bit 1    : RX staggered sounding capable
+			 Bit 2    : TX staggered sounding capable
+			 Bit 3    : RX NDP capable
+			 Bit 4    : TX NDP capable
+			 Bit 5    : Implicit TX BF capable
+			 Bit 6-7  : Calibration
+			         0: - not supported
+			         1: - STA can respond to a calibration request using
+			              the CSI Report, but cannot initiate calibration
+			         2: - reserved
+			         3: - STA can both initiate and respond to a calibration request
+			 Bit 8    : Explicit CSI TX BF capable
+			 Bit 9    : Explicit non-compressed steering capable
+			 Bit 10   : Explicit compressed steering capable
+			 Bit 11-12: Explicit TX BF CSI feedback
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 13-14: Explicit non-compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 15-16: Explicit compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 17-18: Minimal grouping
+			         0: - no grouping (STA supports groups of 1)
+			         1: - groups of 1, 2
+			         2: - groups of 1, 4
+			         3: - groups of 1, 2, 4
+			 Bit 19-20: CSI number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 21-22: Non-compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 23-24: Compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 25-26: CSI max number of rows beamformer supported
+			         0: - single row of CSI
+			         1: - 2 rows of CSI
+			         2: - 3 rows of CSI
+			         3: - 4 rows of CSI
+			 Bit 27-28: Channel estimation capability
+			         0: - 1 space time stream
+			         1: - 2 space time streams
+			         2: - 3 space time streams
+			         3: - 4 space time streams
+			 Bit 29-31: Reserved
+
+	Examples:
+		iwpriv mlan0 httxbfcap             : Get the current TX BF capabilities
+		iwpriv mlan0 httxbfcap 0x0000001F  : Set the TX BF capabilities of the
+		                                     Implicit TX BF receiving capable,
+		                                     RX staggered sounding capable,
+		                                     TX staggered sounding capable,
+		                                     RX NDP capable and TX NDP capable
+
+httxbfcfg
+	This command is used to configure the TX beamforming options.
+	Note: Any new subcommand should be inserted in the second
+		argument and each argument of the sub command should be
+		separated by semicolon. For global configuration, the
+		arguments should be separated by space.
+
+	Usage:
+		iwpriv mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData]"
+
+	where the parameters are,
+		action: TX beamforming action
+			0: Control global parameters for beamforming
+		        1: Performs NDP Sounding for PEER
+		        2: TX BF interval in milliseconds
+		        3: Enable/Disable beamforming/sounding for a particular peer
+		        4: TX BF SNR Threshold for peer
+		        .. <for new subcommand>
+		GlobalData: Global parameter arguments.
+		    It contains beamforming enable, sounding enable, FB type, snr_threshold
+		    sounding interval, Beamformig mode values seperated by space.
+		    Syntax:
+			iwpriv mlanX httxbfcfg <action>;<beamforming enable> <sounding enable> <FB type>
+			                       <snr_threshold>  <sounding interval> <Beamforming mode>
+		tsData: Trigger sounding for PEER specific arguments,
+		        it contains PEER MAC and status
+		interval: TX BF interval in milliseconds
+		txPeerData: Enable/Disable beamforming/sounding for the indicated peer,
+		          it contains PEER MAC, sounding, beamfoming options and FB type;
+		snrData: TX BF SNR Threshold for peer, it contains PEER MAC and SNR
+
+	Examples:
+		iwpriv mlan0 httxbfcfg "0"                          : Get current global configuration parameter
+		iwpriv mlan0 httxbfcfg "2;00:50:43:20:BF:64"        : Get the TX BF periodicity for a given peer
+		iwpriv mlan0 httxbfcfg "3"                          : Get the list of MAC addresses that have
+		                                                      beamforming and/or sounding enabled
+		iwpriv mlan0 httxbfcfg "4"                          : Get the list of PEER MAC, SNR tuples
+		                                                      programmed into the firmware.
+		iwpriv mlan0 httxbfcfg "0;0 0 3 10 500 5"           : Disable beamforming, sounding, set FB type
+		                                                      to 3, snr threshold to 10, sounding interval
+		                                                      to 500 ms and beamforming mode to 5
+		iwpriv mlan0 httxbfcfg "1;00:50:43:20:BF:64"        : Perform NDP Trigger sounding to peer
+		                                                      00:50:43:20:BF:64
+		iwpriv mlan0 httxbfcfg "2;00:50:43:20:BF:64;500"    : Set TX BF periodicity for peer 00:50:43:20:BF:64
+		                                                      to 500 milliseconds
+		iwpriv mlan0 httxbfcfg "3;00:50:43:20:BF:43;1;0;3"  : Enable beamforming, disable sounding and set
+		                                                      FB type to 3 for peer 00:50:43:20:BF:43
+		iwpriv mlan0 httxbfcfg "4;00:50:43:20:BF:24;43"     : Set TX BF SNR threshold to peer
+		                                                      00:50:43:20:BF:24 with SNR 43
+
+mgmtframectrl
+	This command is used to get/set mask for the management frames which needs to be forwarded to application layer.
+
+	Usage:
+		iwpriv mlanX mgmtframectrl [m]
+
+	where the parameter [m] is the bit mask of management frame reception.
+		Following are the bit definitions.
+		Bit 0 : Association Request
+		Bit 1 : Association Response
+		Bit 2 : Re-Association Request
+		Bit 3 : Re-Association Response
+		Bit 4 : Probe Request
+		Bit 5 : Probe Response
+		Bit 8 : Beacon Frames
+
+	Examples:
+		iwpriv mlan0 mgmtframectrl         : Get the current Mgmt Frame forwarding mask
+		iwpriv mlan0 mgmtframectrl 0x0020  : Bit 5 is set, Forward probe response
+											 frames to application layer
+
+mpactrl
+	This command is used to set/get the Tx, Rx SDIO aggregation parameters.
+	Note: The parameters can be set only in disconnected state.
+
+	Usage:
+		iwpriv mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+
+	where the parameter are:
+		[tx_ena]: Enable/disable (1/0) Tx MP-A
+		[rx_ena]: Enable/disable (1/0) Rx MP-A
+		[tx_size]: Size of Tx MP-A buffer
+		[rx_size]: Size of Rx MP-A buffer
+		[tx_ports]: Max ports (1-16) for Tx MP-A
+		[rx_ports]: Max ports (1-16) for Rx MP-A
+	default values are 1 1 16384 32768 16 16
+	The MP-A may be disabled by default at build time if the MMC driver byte mode patch
+	is not available in kernel.
+
+	Examples:
+		iwpriv mlan0 mpactrl       : Get MP aggregation parameters
+		iwpriv mlan0 mpactrl 0 0
+		                           : Disable MP aggregation for Tx, Rx respectively
+		iwpriv mlan0 mpactrl 1 1 8192 8192 8 8
+		                           : Enable MP aggregation for Tx, Rx
+		                           : Set Tx, Rx buffer size to 8192 bytes
+		                           : Set maximum Tx, Rx ports to 8
+
+deepsleep
+	This command is used to set/get auto deep sleep mode.
+
+	Usage:
+		iwpriv mlanX deepsleep [n] [m]
+
+	where the parameters are:
+		[n]: Enable/disable auto deep sleep mode (1/0)
+		[m]: Idle time in milliseconds after which firmware will put the device
+		     in deep sleep mode. Default value is 100 ms.
+
+	Examples:
+		iwpriv mlan0 deepsleep          : Display auto deep sleep mode
+		iwpriv mlan0 deepsleep 1        : Enable auto deep sleep mode, idle time unchanged
+		iwpriv mlan0 deepsleep 0        : Disable auto deep sleep mode
+		iwpriv mlan0 deepsleep 1 500    : Enable auto deep sleep mode with idle time 500 ms
+        Note:
+            Deepsleep must be disabled before changing idle time.
+
+hscfg
+	This command is used to configure the host sleep parameters.
+
+	Usage:
+		iwpriv mlanX hscfg [condition [[GPIO# [gap]]]]
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap) parameters for set. If no parameter provided,
+	get is performed.
+
+	where Condition is:
+		bit 0 = 1   -- broadcast data
+		bit 1 = 1   -- unicast data
+		bit 2 = 1   -- mac event
+		bit 3 = 1   -- multicast data
+		bit 6 = 1  --  Wakeup when mgmt frame received.
+		bit 7 = 1  --  Reserved
+		bit 8 = 1  --  Disable non maskable data wakeup.
+
+	The host sleep mode will be canceled if condition is set to -1. The default is 0x7.
+
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+	GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead).
+	The default is 0xff.
+
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff
+	for special setting (host acknowledge required) when GPIO is used to wakeup host.
+	The default is 200.
+
+	The host sleep set except for cancellation will be blocked if host sleep is
+	already activated.
+
+	Examples:
+		iwpriv mlan0 hscfg              : Get current host sleep mode
+		iwpriv mlan0 hscfg -1           : Cancel host sleep mode
+		iwpriv mlan0 hscfg 3            : Broadcast and unicast data
+		                                  Use GPIO and gap set previously
+		iwpriv mlan0 hscfg 2 3          : Unicast data
+		                                  Use GPIO 3 and gap set previously
+		iwpriv mlan0 hscfg 2 1 0xa0     : Unicast data
+		                                  Use GPIO 1 and gap 160 ms
+		iwpriv mlan0 hscfg 2 0xff       : Unicast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap set previously
+		iwpriv mlan0 hscfg 4 3 0xff     : MAC event
+		                                  Use GPIO 3
+		                                  Special host sleep mode
+		iwpriv mlan0 hscfg 1 0xff 0xff  : Broadcast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap 255ms
+
+hssetpara
+	This command is used to set host sleep parameters.
+
+	Usage:
+		iwpriv mlanX hssetpara Condition [GPIO# [gap]]
+
+	Note:
+	1) The usages of parameters are the same as "hscfg" command.
+	2) The parameters will be saved in the driver and be used when host suspends.
+
+deauth
+	This command is used to send a de-authentication to an arbitrary AP.
+	If [n] is omitted, the driver will deauth the associated AP.
+	If in ad-hoc mode this command is used to stop beacon transmission
+	from the station and go into idle state.
+
+	When <n> is supplied as a MAC address, the driver will deauth the
+	  specified AP.  If the AP address matches the driver's associated AP,
+	  the driver will disconnect. Otherwise, the driver remains connected.
+
+radioctrl
+	This command is used to turn on/off the radio.
+	Note: The radio can be disabled only in disconnected state.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 radioctrl 1        : Turn the radio on
+		iwpriv mlan0 radioctrl          : Get radio status
+
+reassoctrl
+	This command is used to turn on/off re-association in driver.
+
+	Usage:
+		iwpriv mlanX reassoctrl [n]
+
+	Where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 reassoctrl         : Get re-association status
+		iwpriv mlan0 reassoctrl 1       : Turn re-association on
+
+bandcfg
+	This command is used to set/get infra/ad-hoc band.
+	Note: This command is only available in disconnected state.
+
+	Usage:
+		iwpriv mlanX bandcfg [l] [m] [n] [o]
+
+	where the parameters:
+		[l]: Infrastructure band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+
+			 bit 5: AC 2.4G
+			 bit 6: AC 5G
+		[m]: Ad-hoc start band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+			 bit 5: AC 2.4G
+			 bit 6: AC 5G
+		[n]: Ad-hoc start channel
+		[o]: 0 - Bandwidth 20Mhz
+		     1 - HT Bandwidth 40Mhz above
+		     3 - HT Bandwidth 40Mhz below
+			 4 - VHT Bandwidth 80Mhz
+	Examples:
+		iwpriv mlan0 bandcfg            : Get infra/ad-hoc band and ad-hoc
+		                                  start channel configurations
+		iwpriv mlan0 bandcfg 1          : Set infra band to B only
+		iwpriv mlan0 bandcfg 3 2 6      : Set infra band to B/G, ad-hoc start band
+		                                  to G and ad-hoc start channel to 6
+		iwpriv mlan0 bandcfg 7 11 6 1   : Set infra band to B/G/A, ad-hoc start band
+		                                  to B/G/GN, ad-hoc start channel to 6 and
+		                                  secondary channel to above
+
+getlog
+	This command is used to get the statistics available in the station.
+
+11dcfg
+	This command is used to control 11D. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 11dcfg 1           : Enable 11D
+		iwpriv mlan0 11dcfg             : Get 11D status
+
+11dclrtbl
+	This command is used to clear the 11D channel table.
+
+	Usage:
+		iwpriv mlanX 11dclrtbl
+
+wmmcfg
+	This command is used to control WMM. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 wmmcfg 1           : Enable WMM
+		iwpriv mlan0 wmmcfg             : Get WMM status
+
+hotspotcfg
+	This command is used to get/set the HotSpot configuration.
+
+	WHere
+		<n> - Configuration bitset
+	This is a bitmap and should be used as following
+		Bit 31-10: Reserved set to 0
+		Bit 9: TDLS support indication enable/disable
+		Bit 8: Interworking indication enable/disable
+		Bit 7-1: Reserved set to 0
+		Bit 0: HotSpot feature enable/disable
+
+txpowercfg
+	This command is used to get/set the Tx power configuration.
+
+	Where
+		<RateIndex> - Data rate index
+			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
+			12	MCS0 (BW20)
+			13	MCS1 (BW20)
+			14	MCS2 (BW20)
+			15	MCS3 (BW20)
+			16	MCS4 (BW20)
+			17	MCS5 (BW20)
+			18	MCS6 (BW20)
+			19	MCS7 (BW20)
+			20	MCS8 (BW20)
+			21	MCS9 (BW20)
+			22	MCS10 (BW20)
+			23	MCS11 (BW20)
+			24	MCS12 (BW20)
+			25	MCS13 (BW20)
+			26	MCS14 (BW20)
+			27	MCS15 (BW20)
+			140	MCS0 (BW40)
+			141	MCS1 (BW40)
+			142	MCS2 (BW40)
+			143	MCS3 (BW40)
+			144	MCS4 (BW40)
+			145	MCS5 (BW40)
+			146	MCS6 (BW40)
+			147	MCS7 (BW40)
+  			148	MCS0 (BW40)
+			149	MCS1 (BW40)
+			150	MCS2 (BW40)
+			151	MCS3 (BW40)
+			152	MCS4 (BW40)
+			153	MCS5 (BW40)
+			154	MCS6 (BW40)
+			155	MCS7 (BW40)
+			0xff	Default
+		<MinPwr> - Minimum power level in dBm
+		<MaxPwr> - Maximum power level in dBm
+		<step>   - Power step
+
+	Note: Firmware may adjust the setting if over limit, final value can be
+	      verified using get command.
+
+	Examples:
+		iwpriv mlan0 txpowercfg 0xff        : Default power configuration
+		iwpriv mlan0 txpowercfg 11 12       : Set power level 12 dBm to data rate 54 Mbps
+		iwpriv mlan0 txpowercfg 7 11 16 1   : Set power level 11 dBm to 16 dBm with
+		                                      step 1 to data rate 18 Mbps
+		iwpriv mlan0 txpowercfg             : Get current configuration
+		mlan0     txpowercfg:2  3  13  18  2  1  1  13  18  2  0  0  13  18  2
+		10  11  13  15  2  8  9  13  16  2  6  7  13  17  2  4  5  13  17  2
+		17  19  13  15  2  15  16  13  16  2  13  14  13  17  2  12  12  13  17  2
+		145  147  13  14  1  143  144  13  14  1  141  142  13  14  1  140  140  13  14  1
+
+		 2 -> First rate index is 5.5 Mbps.
+		 3 -> Last rate index is 11 Mbps.
+		13 -> Min Tx power value is 13 dBm.
+		18 -> Max Tx power value is 18 dBm.
+		 2 -> Power adjustment step value is 2.
+
+		Similarly
+		17 -> First rate index is MCS5 (BW20).
+		19 -> Last rate index is MCS7 (BW20).
+		13 -> Min Tx power value is 13 dBm.
+		15 -> Max Tx power value is 15 dBm.
+		 2 -> Power adjustment step value is 2.
+
+		so on...
+
+qoscfg
+	This command sets WMM IE QOS info when an argument is given, and gets current WMM
+	IE QOS info when no argument is given.
+
+	Examples:
+		iwpriv mlan0 qoscfg 0x0f        : Set WMM IE QOS info to 0x0f
+		iwpriv mlan0 qoscfg             : Get WMM IE QOS info
+
+getdatarate
+	This command is used to get the data rate (index) being used in last Tx
+	packet and last Rx packet.
+
+bcninterval
+	This command is used to set/get the beacon interval in ad-hoc mode.
+	The valid beacon interval is between 20 - 1000, default beacon
+	interval is 100.
+
+	Where <n>
+		Beacon interval in TU (Time Unit: 1024 us).
+
+	Examples:
+		iwpriv mlan0 bcninterval 200    : Set ad-hoc beacon interval to 200
+		iwpriv mlan0 bcninterval        : Get ad-hoc beacon interval
+
+sysclock
+	This command is used to set/get system clocks in MHz.
+	The current system clock, configurable system clocks and all of the
+	supported system clocks will be returned if no parameter provided.
+
+	Examples:
+		iwpriv mlan0 sysclock           : Get system clocks
+		80 80 128 128 128 5 11 16 20 22 32 40 44 64 80 106 128 160 ...
+		(The current system clock is 80 MHz.
+		 The configurable system clocks of non-security, security, non-security
+		 A-MPDU and security A-MPDU are 80 MHz, 128 MHz, 128 MHz and 128 MHz.
+		 The supported system clocks are 5 MHz, 11 MHz, ..., 160 MHz, 182 MHz,
+		 213 MHz, 256 MHz, 320 Mhz, 366 MHz , ... . the Max system clocks is different
+		 for different chips, you could use this command to get the supported system clock)
+
+		iwpriv mlanX sysclock 80        : Set system clock in non-security mode
+		                                  to 80 MHz, no change for others
+		iwpriv mlanX sysclock 0 0 128   : Set system clock in non-security A-MPDU
+		                                  mode to 128 MHz, no changes for others
+
+drvdbg
+	This command is used to set/get the bit masks of driver debug message control.
+
+	Usage:
+		iwpriv 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:
+		iwpriv mlan0 drvdbg             : Get the current driver debug masks
+		iwpriv mlan0 drvdbg 0           : Disable all the debug messages
+		iwpriv mlan0 drvdbg 7           : Enable MMSG, MFATAL and MERROR messages
+		iwpriv mlan0 drvdbg 0x20037     : Enable MMSG, MFATAL, MEEROR,
+		                                  MCMND, MEVENT and MCMD_D messages
+		iwpriv mlan0 drvdbg -1          : Enable all the debug messages
+
+warmreset
+	This command is used for warm reset of the interface.
+
+	Usage:
+		iwpriv mlanX warmreset
+
+regrdwr
+	This command is used to read/write the adapter register.
+
+	Usage:
+		iwpriv mlanX regrdwr <type> <offset> [value]
+
+	where the parameters are,
+		<type>:     1:MAC/SOC, 2:BBP, 3:RF, 5:CAU
+		<offset>:   offset of register
+		[value]:    value to be written
+	Note: If highest bit of a 32-bit value needs to be set, use negative input.
+	The calculation is -(0xffffffff - value + 1). Range from -0x80000000 to -1.
+
+	Examples:
+		iwpriv mlan0 regrdwr 1 0xa060       : Read the MAC register
+		iwpriv mlan0 regrdwr 1 0xa060 0x12  : Write the MAC register
+		iwpriv mlan0 regrdwr 1 0xa794 -0x80000000
+		                                    : Write 0x80000000 to MAC register
+		iwpriv mlan0 regrdwr 1 0xa794 -0x00000001
+		                                    : Write 0xffffffff to MAC register
+
+rdeeprom
+	This command is used to read the EEPROM contents of the card.
+
+	Usage:
+		iwpriv mlanX rdeeprom <offset> <length>
+
+	where the parameters are,
+		<offset>:   multiples of 4
+		<length>:   4-20, multiples of 4
+
+	Example:
+		iwpriv mlan0 rdeeprom 0 20      : Read 20 bytes of EEPROM data from offset 0
+
+memrdwr
+	This command is used to read/write the adapter memory.
+
+	Usage:
+		iwpriv mlanX memrdwr <address> [value]
+
+	where the parameters are,
+		<address>:  memory address
+		[value]:    value to be written
+	Note: If highest bit of a 32-bit address/value needs to be set, use negitive input.
+	The calculation is -(0xffffffff - address/value + 1). Range from -0x80000000 to -1.
+
+	Examples:
+		iwpriv mlan0 memrdwr 0x4cf70    : Read memory address 0x4cf70
+		iwpriv mlan0 memrdwr -0x80000000
+		                                : Read memory address 0x80000000
+		iwpriv mlan0 memrdwr -0x7fff6000 -0x40000000
+		                                : Write 0xc0000000 to memory address 0x8000a000
+
+inactivityto
+	This command is used to set/get the inactivity timeout value, which specifies
+	when WLAN device is put to sleep.
+
+	Usage:
+		iwpriv mlanX inactivityto <n> <m> <l> [k]
+
+	where the parameter are:
+		<n>: timeout unit in microseconds.
+		<m>: Inactivity timeout for unicast data.
+		<l>: Inactivity timeout for multicast data.
+		[k]: Inactivity timeout for new Rx traffic after PS notification to AP.
+
+	Examples:
+		iwpriv mlan0 inactivityto           : Get the timeout value
+		iwpriv mlan0 inactivityto 1000 2 3  : Set timeout unit to 1000 us (1 ms),
+		                                      inactivity timeout for unicast data is 2 ms,
+		                                      inactivity timeout for multicast data is 3 ms
+
+sdioclock
+	Turn On(1) or Off(0) the SDIO clock.
+
+	Usage:
+		iwpriv mlanX sdioclock 1 (on)
+		iwpriv mlanX sdioclock 0 (off)
+		iwpriv mlanX sdioclock (get the current clock state)
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		iwpriv mlanX sdcmd52rw <function number> <register address> [value]
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+	Examples:
+		iwpriv mlan0 sdcmd52rw 1 3
+		iwpriv mlan0 sdcmd52rw 1 1 0x3f
+
+scancfg
+	This command is used to set/get scan configuration parameters.
+
+	Usage:
+		iwpriv mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+
+	where the parameters:
+		[t]: Scan Type (0: Unchanged, 1: Active, 2: Passive, default Active)
+		[m]: Scan Mode (0: Unchanged, 1: BSS, 2: IBSS, 3: Any, default Any)
+		[p]: Scan Probes (0: Unchanged, 1-4: Number of probes per channel, default 4)
+		[s]: Specific Scan Time (0: Unchanged, n: Value in ms, default 110 ms, max 500 ms)
+		[a]: Active Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 500 ms)
+		[b]: Passive Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 2000 ms)
+		[ext]: Extended scan (0: Legacy scan, 1: Extended scan)
+
+	No change if the parameter is 0 or the parameter is not provided.
+
+	Examples:
+		iwpriv mlan0 scancfg            : Get all the current scan configuration settings
+		iwpriv mlan0 scancfg 1 3        : Set scan type to active and scan mode to any,
+		                                  all the other scan configurations are unchanged
+		iwpriv mlan0 scancfg 0 1 2 200  : Set scan mode to BSS, number of probes to 2 and
+		                                  specific scan time to 200 ms, all the other scan
+		                                  configurations are unchanged
+
+sleeppd
+	This command is used to configure the sleep period of the WLAN device.
+
+	Usage:
+		iwpriv mlanX sleeppd [<period>]
+
+	Where the parameter is:
+		period: sleep period in milliseconds. Range 10~60. 0 for disable.
+
+	Examples:
+		iwpriv mlan0 sleeppd            : Get sleep period configuration
+		iwpriv mlan0 sleeppd 10         : Set sleep period to 10 ms
+
+pscfg
+	This command is used to set/get PS configuration parameters.
+
+	Usage:
+		iwpriv mlanX pscfg [k] [d] [l] ...
+
+	Where the parameters:
+		[k]: Keep alive null packet interval (0: Unchanged, -1: Disable, n: Interval in seconds)
+		[d]: DTIM interval (    0: Unchanged,
+		                      1-5: Value,
+		                    65534: DTIM will be ignored, listen interval will be used,
+		                    65533: Closest DTIM to the listen interval period will be used )
+		[l]: Local listen interval (     0: Unchanged,
+		                                -1: Disable,
+		                              1-49: Value in beacon intervals,
+		                             >= 50: Value in TUs )
+		[b]: Beacon miss timeout (0: Unchanged, 1-50: Value in milliseconds, 65535: Disable)
+		[p]: Delay to PS (0-65535: Value in milliseconds, default 1000ms)
+		[m]: PS mode (0: Unchanged, 1: Auto mode, 2: PS-Poll mode, 3: PS Null mode)
+	No change if parameters are not provided.
+
+	Examples:
+		iwpriv mlan0 pscfg              : Get all the current PS configuration settings
+		iwpriv mlan0 pscfg 3 4          : Set PS keep alive null packet interval to 3 seconds
+		                                  and DTIM interval to 4, all the other configurations
+		                                  are unchanged
+		iwpriv mlan0 pscfg 0 0 0 0 50 2 : Set delay to PS to 50 ms and PS mode to PS-Poll mode,
+		                                  keep the others unchanged
+
+getkey
+	This command is used to get PTK/GTK
+
+	iwpriv mlanX getkey
+associate
+	Request an association to a given SSID/BSSID pair. This the only accurate
+	way to pick a specific AP and ESS for an association. The entry must
+	already exist in the scan table for the association to be attempted.
+
+	iwpriv mlanX associate "xx:xx:xx:xx:xx:xx SSID"
+
+sleepparams
+	This command is used to set the sleepclock configurations
+
+	Usage:
+		iwpriv mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+
+	where:
+		p1 is Sleep clock error in ppm (0-65535)
+		p2 is Wakeup offset in usec (0-65535)
+		p3 is Clock stabilization time in usec (0-65535)
+		p4 is Control periodic calibration (0-2)
+		p5 is Control the use of external sleep clock (0-2)
+		p6 is reserved for debug (0-65535)
+
+	Examples:
+		iwpriv mlan0 sleepparams                      : Get current sleepclock configuration
+		iwpriv mlan0 sleepparams 10 1000 2000 1 0 128 : Set sleepclock configuration
+
+authtype
+	This command is used to set/get authentication type.
+
+	Usage:
+		iwpriv mlanX authtype [n]
+
+	where <n>
+		0: 802.11 open system authentication
+		1: 802.11 shared key authentication
+		255: allow open system or shared key authentication (default)
+
+	Examples:
+		iwpriv mlan0 authtype 0         : use open system authentication
+		iwpriv mlan0 authtype 1         : use shared key authentication
+		iwpriv mlan0 authtype 255       : allow open system or shared key authentication
+		iwpriv mlan0 authtype           : get current setting
+
+powercons
+	This command is used to set the local transmit power constraint.
+	Value is in dbm unit. This command is only used for ad-hoc start.
+
+	Usage:
+		iwpriv mlanX powercons [n]
+
+	Examples:
+		iwpriv mlanX powercons          : get the current setting
+		iwpriv mlanX powercons 12       : set local power constraint to 12 dbm
+
+htstreamcfg
+	This command is used to set/get HT stream configuration.
+	The setting only takes effect in next association.
+
+	Usage:
+		iwpriv mlanX htstreamcfg [n]
+
+	where <n>
+		0x11: HT stream 1x1 mode
+		0x22: HT stream 2x2 mode
+
+	Examples:
+		iwpriv mlan0 htstreamcfg        : Get current setting
+		iwpriv mlan0 htstreamcfg 0x11   : Set HT stream 1x1 mode
+		iwpriv mlan0 htstreamcfg 0x22   : Set HT stream 2x2 mode
+
+ipaddr
+	This command is used to set/get IP address.
+
+	Usage:
+		iwpriv mlanX ipaddr ["<op>;<ipaddr>"]
+
+	where <op>
+		0: Remove the IP address
+		bit 0: Set IP address for broadcast ARP filter, which will be auto enabled
+		       in next host sleep configuration
+		bit 1: Set IP address for auto broadcast ARP response
+
+	Examples:
+		iwpriv mlan0 ipaddr                 : Get current settings
+		iwpriv mlan0 ipaddr "0"             : Remove IP address
+		iwpriv mlan0 ipaddr "1;192.168.0.5" : Set IP address for ARP filter
+		iwpriv mlan0 ipaddr "3;192.168.0.6" : Set IP address for ARP filter
+		                                    : and auto ARP response
+
+macctrl
+	This command is used to set/get MAC control.
+	It's recommended to read the current setting first to avoid override issue.
+
+	Usage:
+		iwpriv mlanX macctrl [n]
+
+	where <n>
+		bit 0:  Rx enabled
+		bit 1:  Tx enabled
+		bit 3:  WEP enabled
+		bit 4:  EthernetII enabled
+		bit 7:  Promiscuous enabled
+		bit 8:  All multicast enabled
+		bit 9:  RTS/CTS enabled (0: CTS to self)
+		bit 11: Force 11n protection disabled
+		bit 12: Ad-hoc g protection disabled
+		...
+
+	Examples:
+		iwpriv mlan0 macctrl            : Get current MAC control
+		iwpriv mlan0 macctrl 0x13       : Set Tx/Rx on and EthernetII on
+		iwpriv mlan0 macctrl 0x813      : Set Tx/Rx on and EthernetII on
+		                                : Disable force 11n protection
+
+dfstesting
+	This command is used to set/get settings for DFS testing.
+
+	Usage:
+	    iwpriv mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+
+	where <user_cac_pd> is user-configured Channel Availability Check in msec
+                        0 = disable, use default period (60000)
+                        1-65535 = enable with that period
+	where <user_nop_pd> is user-configured Non-Occupancy Period in sec
+                        0 = disable, use default period (1800)
+                        1-65535 = enable with that period
+	where <no_chan_change> is enable/disable no channel change on radar
+                           0 = disable, 1 = enable (overrides below)
+	where <fixed_chan_num> is user-configured channel to change to on radar
+                           0 = disable, 1-255 = enable with that channel
+                           (channel validity for region, etc. is not checked)
+                           (only takes effect if no_chan_change = 0)
+
+	Examples:
+		iwpriv mlan0 dfstesting             : Get current dfstesting settings
+		iwpriv mlan0 dfstesting 2000 0 0 0  : user_cac=2sec, others disabled/default
+		iwpriv mlan0 dfstesting 0 0 1 0     : only no_chan_change enabled
+		iwpriv mlan0 dfstesting 0 120 0 64  : user_nop=2min, force chan 64 on radar
+
+thermal
+	This command is used to get the current thermal reading.
+
+	Examples:
+		iwpriv mlan0 thermal            : Get thermal reading
+
+
+===============================================================================
+		U S E R  M A N U A L  F O R  M L A N C O N F I G
+
+NAME
+mlanconfig - configure the additional parameters available for the Marvell mdriver.
+
+SYNOPSIS
+mlanconfig -v
+mlanconfig <mlanX> <command> [parameters] ...
+
+mlanconfig mlanX hostcmd <bg_scan.conf> bgscfg
+mlanconfig mlanX hostcmd <requesttpc.conf> requesttpc
+mlanconfig mlanX hostcmd <crypto_test.conf> crypto_test
+mlanconfig mlanX hostcmd <subevent.conf> subevent_get
+mlanconfig mlanX hostcmd <subevent.conf> subevent_set
+mlanconfig mlanX hostcmd <auto_tx.conf> auto_tx_get
+mlanconfig mlanX hostcmd <auto_tx.conf> nat_keep_alive
+mlanconfig mlanX hostcmd <auto_tx.conf> auto_tx_unreg
+mlanconfig mlanX hostcmd <txrate_cfg.conf> txrate_cfg_get
+mlanconfig mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bg
+mlanconfig mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bgn
+mlanconfig mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_cfg_get
+mlanconfig mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_2g_cfg_set
+mlanconfig mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_5g_cfg_set
+mlanconfig mlanX hostcmd <pad_cfg.conf> pad_cfg_get
+mlanconfig mlanX hostcmd <pad_cfg.conf> pad_cfg_set
+mlanconfig mlanX hostcmd <11n_2040coex.conf> 2040coex
+mlanconfig mlanX hostcmd <robust_btc.conf> mode_get
+mlanconfig mlanX hostcmd <robust_btc.conf> mode_timeshare
+mlanconfig mlanX hostcmd <robust_btc.conf> mode_spatial
+mlanconfig mlanX hostcmd <robust_btc.conf> generictime
+mlanconfig mlanX hostcmd <robust_btc.conf> a2dptime
+mlanconfig mlanX hostcmd <robust_btc.conf> inquirytim
+mlanconfig mlanX hostcmd <robust_btc.conf> ap_generictime
+mlanconfig mlanX hostcmd <robust_btc.conf> ap_a2dptime
+mlanconfig mlanX hostcmd <robust_btc.conf> ap_inquirytime
+mlanconfig mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_get
+mlanconfig mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_set
+mlanconfig mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_disable
+mlanconfig mlanX arpfilter <arpfilter.conf>
+mlanconfig mlanX mefcfg <mef.conf>
+mlanconfig mlanX cfgdata <register type> <conf file>
+mlanconfig mlanX sdcmd52rw <FN no.> <address> [data]
+mlanconfig mlanX sdcmd53rw <FN no.> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+mlanconfig mlanX setuserscan [ARGS]
+mlanconfig mlanX getscantable [ARGS]
+mlanconfig mlanX addts <filename.conf> <section# of tspec> <timeout in ms>
+mlanconfig mlanX delts <filename.conf> <section# of tspec>
+mlanconfig mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+mlanconfig mlanX qconfig get [Queue Id: 0-3]
+mlanconfig mlanX qconfig def [Queue Id: 0-3]
+mlanconfig mlanX qstats on  [Queue Id: 0-3]
+mlanconfig mlanX qstats off [Queue Id: 0-3]
+mlanconfig mlanX qstats get [Queue Id: 0-3]
+mlanconfig mlanX qstatus
+mlanconfig mlanX ts_status
+mlanconfig mlanX regrdwr <type> <offset> [value]
+mlanconfig mlanX memrdwr <address> [value]
+mlanconfig mlanX customie <index> <mask> <IE buffer>
+mlanconfig mlanX tdls_config <0/1>
+mlanconfig mlanX tdls_setinfo <tdls.conf>
+mlanconfig mlanX tdls_setup <tdls.conf>
+mlanconfig mlanX tdls_discovery <tdls.conf>
+mlanconfig mlanX tdls_teardown <tdls.conf>
+mlanconfig mlanX tdls_powermode <tdls.conf>
+mlanconfig mlanX tdls_channel_switch <tdls.conf>
+mlanconfig mlanX tdls_stop_channel_switch <tdls.conf>
+mlanconfig mlanX tdls_cs_params <tdls.conf>
+mlanconfig mlanX tdls_disable_cs <0/1>
+mlanconfig mlanX tdls_link_status
+mlanconfig mlanX tdls_debug "wrong_bss" <0/1>
+mlanconfig mlanX tdls_debug "setup_existing_link" <0/1>
+mlanconfig mlanX tdls_debug "fail_setup_confirm" <0/1>
+mlanconfig mlanX tdls_debug "setup_with_prohibited" <0/1>
+mlanconfig mlanX tdls_debug "higher_lower_mac" <0/1>
+mlanconfig mlanX tdls_debug "ignore_key_expiry" <0/1>
+mlanconfig mlanX tdls_debug "allow_weak_security" <0/1>
+mlanconfig mlanX tdls_debug "stop_rx" <0/1>
+mlanconfig mlanX tdls_debug "cs_im_return" <0/1>
+mlanconfig mlanX mgmtframetx <mgmt_frame.conf>
+
+
+DESCRIPTION
+
+Those commands are used in Marvell specific application called mlanconfig.
+
+===========
+-v
+	This command is used to display the version of mlanconfig utility.
+	Usage:
+		mlanconfig -v
+
+hostcmd bgscfg
+	This command is used to configure the various parameters for PPS/UAPSD
+	or normal background scan.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/bg_scan.conf bgscfg
+
+hostcmd requesttpc
+	This command is used to request 802.11H TPC info.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/requesttpc.conf requesttpc
+
+hostcmd crypto_test
+	This command is used to test the encryption/decryption API of the firmware.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/crypto_test.conf crypto_test
+
+hostcmd subevent_get
+hostcmd subevent_set
+	This command is used to get/set the configurations for event descriptor
+	interface command.
+	subsvent_get: get subscribed event parameters
+	subsvent_set: set subscribed event parameters
+
+	Usage:
+		mlanconfig mlanX hostcmd config/subevent.conf subevent_get
+		mlanconfig mlanX hostcmd config/subevent.conf subevent_set
+
+hostcmd auto_tx_get
+hostcmd nat_keep_alive
+hostcmd auto_tx_unreg
+	This command is used to configures the Frame Auto Transmission parameters.
+	auto_tx_get: get auto_tx parameters
+	nat_keep_alive: register to firmware for sending NAT Keep Alive packet
+	auto_tx_unreg: unregister to firmware auto_tx
+
+	Usage:
+		mlanconfig mlanX hostcmd config/auto_tx.conf auto_tx_get
+		mlanconfig mlanX hostcmd config/auto_tx.conf nat_keep_alive
+		mlanconfig mlanX hostcmd config/auto_tx.conf auto_tx_unreg
+
+hostcmd txrate_cfg_get
+hostcmd txrate_cfg_set_bg
+hostcmd txrate_cfg_set_bgn
+	This command is used to set/get the transmit data rate.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_get
+		mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bg
+		mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bgn
+
+hostcmd txpwrlimit_cfg_get
+hostcmd txpwrlimit_2g_cfg_set
+hostcmd txpwrlimit_5g_cfg_set
+	This command is used to set/get the configuration data of Tx power limitation.
+	Note: The configuration set should be issued when STA is disconnected.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get
+		mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set
+		mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set
+
+hostcmd pad_cfg_get
+hostcmd pad_cfg_set
+	This command is used to set/get the configuration data for PAD OR.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/pad_cfg.conf pad_cfg_get
+		mlanconfig mlanX hostcmd config/pad_cfg.conf pad_cfg_set
+
+hostcmd 2040coex
+	This command is used to send the 11n 20/40 Coex command to firmware.
+	Firmware will send 11n 20/40 Coex management action frame to AP.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/11n_2040coex.conf 2040coex
+
+hostcmd mode_get
+hostcmd mode_timeshare
+hostcmd mode_spatial
+	This command is used to get/set Robust BT Coex.
+	mode_get:       get the current mode
+	mode_timeshare: set Robust BT Coex to timeshare mode  (default on 1x1 chips)
+	mode_spatial:   set Robust BT Coex to spatial mode    (only for, and default on 2x2 chips)
+
+	Usage:
+		mlanconfig mlanX hostcmd config/robust_btc.conf mode_get
+		mlanconfig mlanX hostcmd config/robust_btc.conf mode_timeshare
+		mlanconfig mlanX hostcmd config/robust_btc.conf mode_spatial
+
+hostcmd generictime
+hostcmd a2dptime
+hostcmd inquirytime
+hostcmd ap_generictime
+hostcmd ap_a2dptime
+hostcmd ap_inquirytime
+        This command is used to configure the time slice of COEX (only works in timeshare mode)
+        generictime:       configure the Bttime and Wlantime in Station Generic case
+        a2dptime:          configure the Bttime and Wlantime in Station A2DP case
+        inquirytime:       configure the Bttime and Wlantime in Station Inquiry case
+        ap_generictime:    configure the Bttime and Wlantime in Ap Generic case
+        ap_a2dptime:       configure the Bttime and Wlantime in Ap A2DP case
+        ap_inquirytime:    configure the Bttime and Wlantime in Ap Inquiry case
+
+    Usage:
+                mlanutl mlanX hostcmd config/robust_btc.conf generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf inquirytim
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime
+
+hostcmd sdio_pulldown_get
+hostcmd sdio_pulldown_set
+hostcmd sdio_pulldown_disable
+	This command is used to set/get the settings of pulling up and
+	pulling down of SDIO lines.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_get
+		mlanconfig mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_set
+		mlanconfig mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_disable
+
+arpfilter
+	This command is used to configure the ARP filtering parameters.
+
+	Usage:
+		mlanconfig mlanX arpfilter config/arpfilter.conf
+
+mefcfg
+	This command is used to set MEF settings.
+
+	Usage:
+		mlanconfig mlanX mefcfg config/mef.conf
+
+cfgdata
+	This command is used to set/get the configuration data to/from firmware.
+
+	Usage:
+		mlanconfig mlanX cfgdata <type> <.conf file name>
+		This command is used to set the cfg data in the .conf file to firmware.
+
+		mlanconfig mlanX cfgdata <type>
+		This command is used to get the cfg data from firmware and display
+		on to the console.
+
+	Where the value of <type> field is:
+		2   -- Cal data download and <.conf file name> is cal_data.conf
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanconfig mlanX sdcmd52rw <function number> <register address> [value]
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+    Examples:
+		mlanconfig mlan0 sdcmd52rw 1 3
+		mlanconfig mlan0 sdcmd52rw 1 1 0x3f
+
+sdcmd53rw
+	This command is used to issue a CMD53 read/write data in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanconfig mlanX sdcmd53rw <func> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+
+	where the parameters are,
+		<func>:     function number (0/1/2/..)
+		<address>:  data address
+		<mode>:     byte mode/block mode (0/1)
+		<blksize>:  block size (32/64/../512, NA for byte mode)
+		<blknum>:   block number or byte number
+		<data1> ... <dataN>:  data for write
+
+	Note: The total data length is block size * block number for block mode
+	or byte number for byte mode. The max data length is 2000-byte.
+	For write the data pattern will be duplicated to data buffer.
+
+	Examples:
+		mlanconfig mlan0 sdcmd53rw 0 0x8000 1 0x40 2
+		mlanconfig mlan0 sdcmd53rw 1 0x10000 0 1 5 0x0a 0x0b 0x0c 0x0d 0x0e
+
+setuserscan
+	Initiate a customized scan and retrieve the results
+
+	Usage:
+		mlanconfig mlanX setuserscan [ARGS]
+
+	Where [ARGS]:
+	  ssid="[SSID]"            specify a SSID filter for the scan
+	  chan=[chan#][band][mode] where band is [a,b,g,n] and mode is
+	                           blank for active or 'p' for passive
+	  bssid=xx:xx:xx:xx:xx:xx  specify a BSSID filter for the scan
+	  wc="[WILDCARD SSID]"     specify a UNIX pattern matching filter (using *
+	                           and ?) for SSIDs found in a broadcast probe
+	  keep=[0 or 1]            keep the previous scan results (1), discard (0)
+	  dur=[scan time]          time to scan for each channel in milliseconds
+	  gap=[time gap]           Time gap between two scans in milliseconds
+	  probes=[#]               number of probe requests to send on each chan
+	                           for each broadcast probe required and each SSID
+	                           specific probe required (1-4)
+	  type=[1,2,3]             BSS type: 1 (Infra), 2(Adhoc), 3(Any)
+
+	Any combination of the above arguments can be supplied on the command line.
+	If the chan token is absent, a full channel scan will be completed by driver.
+	If the dur or probes tokens are absent, the driver default setting will be
+	used. The bssid and ssid fields, if blank, will produce an unfiltered scan.
+	It's allowed to input multiple ssid/wc entries, the max entry number is 10.
+	The type field will default to 3 (Any) and the keep field will default to 0
+	(Discard).
+
+	Examples:
+	1) Perform an active scan on channels 1, 6, and 11 in the 'g' band:
+		setuserscan chan=1g,6g,11g
+
+	2) Perform a passive scan on channel 11 for 20 ms:
+		setuserscan chan=11gp dur=20
+
+	3) Perform an active scan on channels 1, 6, and 11; and a passive scan on
+	   channel 36 in the 'a' band:
+		setuserscan chan=1g,6g,11g,36ap
+
+	4) Perform an active scan on channel 6 and 36 for specific SSID:
+		setuserscan chan=6g,36a ssid=TestAP1 ssid=TestAP2
+
+	5) Scan all available channels (B/G/N, A bands) for a specific BSSID, keep
+	   the current scan table intact, update existing or append new scan data:
+		setuserscan bssid=00:50:43:20:12:82 keep=1
+
+	6) Scan channel 6, for all infrastructure networks, sending two probe
+	   requests.  Keep the previous scan table intact. Update any duplicate
+	   BSSID/SSID matches with the new scan data:
+		setuserscan chan=6g type=1 probes=2 keep=1
+
+	7) Scan channel 1 and 6, for all networks matching the Mrvl*AP
+	   or AP*Mrvl? patterns and for MrvlTst SSID.  Generate 3 broadcast
+	   probes for the patterns and 3 SSID specific probes for MrvlTst on
+	   both channel 1 and channel 6.
+		setuserscan chan=1g,6g probes=3 wc="Mrvl*AP" wc="AP*Mrvl?" ssid="MrvlTst"
+
+	8) Scan all the channels for specified band.
+		setuserscan chan=0g
+
+	9) Scan channel 1 and 6, send 3 probe requests, scan each channel for 40 ms
+	   with time gap of 50ms between 2 scans
+		setuserscan chan=1g,6g probes=3 dur=40 gap=50
+
+	All entries in the scan table (not just the new scan data when keep=1)
+	will be displayed upon completion by use of the getscantable ioctl.
+
+getscantable
+	Display the current contents of the driver scan table
+
+	Usage:
+		mlanconfig mlanX getscantable
+		mlanconfig mlanX getscantable [#]
+		mlanconfig mlanX getscantable tsf
+		mlanconfig mlanX getscantable help
+
+	1) Without argument, the entire scantable is displayed.
+	2) Specifying a # will display detailed information about a specific scan
+	   table entry.  '0' displays driver cached information regarding the
+	   current association (if any).
+	3) The tsf argument will display the entire scan table with the recorded
+	   TSF timestamp for the entry.
+	4) The help argument will display the legend for the capability field.
+
+addts
+	Send an ADDTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in an ADDTS request to the associated AP.
+
+	Return the execution status of the command as well as the ADDTS response
+	  from the AP if any.
+
+	Usage:
+		mlanconfig mlanX addts <filename.conf> <section# of tspec> <timeout(ms)>
+
+delts
+	Send a DELTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in a DELTS request to the associated AP.
+
+	Return the execution status of the command.  There is no response to a
+	  DELTS from the AP.
+
+	Usage:
+		mlanconfig mlanX delts <filename.conf> <section# of tspec>
+
+qconfig
+	Send a WMM AC Queue configuration command to get/set/default params
+
+	Configure or get the parameters of a WMM AC queue. The command takes
+	  an optional Queue Id as a last parameter.  Without the queue id, all
+	  queues will be acted upon.
+
+	Usage:
+		mlanconfig mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+		mlanconfig mlanX qconfig get [Queue Id: 0-3]
+		mlanconfig mlanX qconfig def [Queue Id: 0-3]
+
+qstats
+	Turn on/off or retrieve and clear the queue statistics for an AC
+
+	Turn the queue statistics collection on/off for a given AC or retrieve the
+	  current accumulated stats and clear them from the firmware. The command
+	  takes an optional Queue Id as a last parameter. Without the queue id,
+	  all queues will be acted upon.
+
+	Usage:
+		mlanconfig mlanX qstats on  [Queue Id: 0-3]
+		mlanconfig mlanX qstats off [Queue Id: 0-3]
+		mlanconfig mlanX qstats get [Queue Id: 0-3]
+
+qstatus
+	This command retrieves the current status of the WMM queues. If WMM
+	  is enabled then it displays the information for each AC in a table.
+
+	Usage:
+		mlanconfig mlanX qstatus
+
+ts_status
+	This command queries the FW for the status of TSIDs 0 through 7
+	  configured via call admission control and displays the results in a
+	  table.
+
+	Usage:
+		mlanconfig mlanX ts_status
+
+regrdwr
+	This command is used to read/write the adapter register.
+
+	Usage:
+		mlanconfig mlanX regrdwr <type> <offset> [value]
+
+	where the parameters are,
+		<type>:     1:MAC/SOC, 2:BBP, 3:RF, 5:CAU
+		<offset>:   offset of register
+		[value]:    value to be written
+
+	Examples:
+		mlanconfig mlan0 regrdwr 1 0xa060   : Read the MAC register
+		mlanconfig mlan0 regrdwr 1 0xa794 0x80000000
+		                                    : Write 0x80000000 to MAC register
+
+memrdwr
+	This command is used to read/write the adapter memory.
+
+	Usage:
+		mlanconfig mlanX memrdwr <address> [value]
+
+	where the parameters are,
+		<address>:  memory address
+		[value]:    value to be written
+
+	Examples:
+		mlanconfig mlan0 memrdwr 0x80000000  : Read memory address 0x80000000
+		mlanconfig mlan0 memrdwr 0x80000000 0xffffffff
+		                                     : Write 0xffffffff to memory address 0x80000000
+
+customie
+	This command is used to set or get custom IEs for management frames.
+
+	Usage : customie [INDEX] [MASK] [IEBuffer]
+        empty - Get all IE settings
+        INDEX:  0 - Get/Set IE index 0 setting
+                1 - Get/Set IE index 1 setting
+                2 - Get/Set IE index 2 setting
+               MAX IE Index depends on device memory.
+
+               -1 - Append/Delete IE automatically
+                    Delete will delete the IE from the matching IE buffer
+                    Append will append the IE to the buffer with the same mask
+        MASK :  Management subtype mask value as per bit definitions
+             :  Bit 0 - Association request
+             :  Bit 1 - Association response
+             :  Bit 2 - Reassociation request
+             :  Bit 3 - Reassociation response
+             :  Bit 4 - Probe request
+             :  Bit 5 - Probe response
+             :  Bit 8 - Beacon
+        MASK :  MASK = 0 to clear the mask and the IE buffer
+        IEBuffer :  IE Buffer in hex (max 256 bytes)
+                    The Buffer should not be space separated.
+
+	Example:
+	 ./mlanconfig mlan0 customie
+		Get IE buffer, subtype mask settings for all indices.
+
+	./mlanconfig mlan0 customie 1
+		Get IE buffer and subtype mask for the Index = 1.
+
+	./mlanconfig mlan0 customie 2 0
+		Clear IE buffer and mask value for Index = 2.
+
+	./mlanconfig mlan0 customie 3 0x101 0xdd051234567890
+		Set IE buffer and mask value for Index = 3.
+
+	./mlanconfig mlan0 customie -1 0x101 0xdd051234567890
+		Append the specified IEBuffer at index with mask value of 0x101.
+
+	./mlanconfig mlan0 customie -1 0 0xdd051234567890
+		Delete the specified IEBuffer from all the IEs.
+
+	./mlanconfig mlan0 customie 2 0 0xdd051234567890
+		Delete the specified IEBuffer from the IEs at index 2.
+
+tdls_config
+	This command is used to enable/disable TDLS on device.
+
+	Usage : tdls_config <0/1>
+		1: Enable TDLS
+		0: Disable TDLS
+tdls_setinfo
+	This command is used for setting the capabilities of the TDLS station.
+
+        Usage : tdls_setinfo <tdls.conf>
+		Set capabilities of TDLS station.
+tdls_setup
+	This command is used to send TDLS setup request.
+
+	Usage: tdls_setup <tdls.conf>
+                Send TDLS setup request.
+tdls_discovery
+	This command is used to request TDLS discovery.
+
+	Usage : tdls_discovery <tdls.conf>
+        	Request TDLS discovery.
+tdls_teardown
+	This command is used to send TDLS teardown request.
+
+	Usage : tdls_teardown <tdls.conf>
+		Request teardown of TDLS link.
+tdls_powermode
+	This command is used to send TDLS powermode request.
+
+	Usage : tdls_powermode <tdls.conf>
+		Send TDLS powermode (either 0:Active, 1:PowerSave) command.
+tdls_channel_switch
+	This command is used to send TDLS channel switch request.
+
+	Usage : tdls_channel_switch <tdls.conf>
+		Send TDLS channel switch command.
+tdls_stop_channel_switch
+	This command is used to send stop TDLS channel switch request.
+
+	Usage : tdls_stop_channel_switch <tdls.conf>
+		Send stop TDLS channel switch command.
+tdls_cs_params
+	This command is used to set TDLS channel switch params
+
+	Usage : tdls_cs_params <tdls.conf>
+		Set TDLS channel switch params.
+tdls_disable_cs
+	This command is used to disable TDLS channel switch
+
+	Usage : tdls_disable_cs <0/1>
+		Disable TDLS channel switch.
+tdls_link_status [peer_mac_address]
+	This command is used to get link information about TDLS links or
+    a TDLS link correponding to peer mac address.
+
+	Usage : tdls_link_status
+		Send TDLS command to get current link status.
+tdls_debug
+	This command is used for FW debug functionality and tests.
+
+mgmtframetx
+	This command is used to send mgmt frame
+
+	Usage:
+		mlanconfig mlanX mgmtframetx <mgmt_frame.conf>
+
+
+===============================================================================
+		U S E R  M A N U A L  F O R  M L A N 2 0 4 0 C O E X
+
+NAME
+mlan2040coex - This application handles the 11n 20/40 coexistence operation for
+               the Marvell mdriver
+
+SYNOPSIS
+mlan2040coex [-d <n>] [-i <intfname>] [hvB]
+	-d = Device number (n)
+	-i = Interface name (intfname)
+	-h = Help
+	-v = Version
+	-B = Run the process in background
+Note: If device number (n) is not present, then 0 assumed.
+      If intfname is not present, then mlan0 assumed.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANEVENT
+
+NAME
+mlanevent.exe
+
+This tool can be used to listen for and obtain events from the driver
+through the netlink layer.
+
+----------------
+Supported events
+----------------
+STA_DEAUTH
+STA_ASSOC
+BSS_START
+BSS_IDLE
+BSS_ACTIVE
+
+-----------------
+Details of events
+-----------------
+
+STA_DEAUTH
+----------
+    For this event, the following information is shown:
+        + Deauthenticated STA MAC address.
+        + Reason for deauthentication.
+
+STA_ASSOC
+----------
+    For this event, the following information is shown:
+        + STA MAC address.
+
+BSS_START
+----------
+    For this event, the following information is shown:
+        + AP MAC address.
+
+BSS_IDLE
+----------
+    For this event, there is no associated information.
+
+BSS_ACTIVE
+----------
+    For this event, there is no associated information.
+
+===============================================================================
diff --git a/wlan_sd8987/README_MLAN b/wlan_sd8987/README_MLAN
new file mode 100644
index 0000000..a4203b4
--- /dev/null
+++ b/wlan_sd8987/README_MLAN
@@ -0,0 +1,3539 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2008-2018, Marvell International Ltd.
+ All Rights Reserved
+
+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 up to 4.18.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy firmware image sd8787_uapsta.bin | sd8797_uapsta.bin | ... to
+	   /lib/firmware/mrvl/ directory, create the directory if it doesn't exist.
+	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
+		The default drv_mode is 7.
+
+		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 2)
+		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)
+	   For example, to install SD8787 driver,
+		insmod mlan.ko
+		insmod sd8787.ko [drv_mode=3] [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in STA only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=1 [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in uAP only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=2 [fw_name=mrvl/sd8787_uapsta.bin]
+
+	   To switch mode between STA only, uAP only and uAPSTA etc. in run time,
+		echo drv_mode=1 > /proc/mwlan/config		// STA mode
+		echo drv_mode=2 > /proc/mwlan/config		// uAP mode
+		echo drv_mode=3 > /proc/mwlan/config		// STA+uAP mode
+		echo drv_mode=7 > /proc/mwlan/config		// STA+uAP+WIFIDIRECT mode
+	c) Uninstall WLAN driver,
+		ifconfig mlanX down
+		ifconfig uapX down
+		rmmod sd8xxx
+		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>
+	  p2p_enh=0|1 <Disable enhanced P2P (default) | Enable enhanced P2P>
+	  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)>
+	  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>
+	  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>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf
+          Note: Loading driver with 8887 must include correct cal_data_cfg parameter.
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.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
+	  cfg80211_drcs=1|0 <Enable DRCS support (default) | Disable DRCS support>
+	  reg_alpha2=<Regulatory alpha2 (default NULL)>
+	  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>
+	  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
+	  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.>
+      napi=0|1 <disable napi | enable napi>
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sd8xxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+
+	The following info are provided in /proc/net/mwlan/mlanX|uapX|wfdX/info,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX|uapX|wfdX/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/mlanX|uapX|wfdX/debug,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX|uapX|wfdX/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>
+	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>
+	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>
+	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/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/config      # read func 0 address 4
+		cat /proc/mwlan/config                          # display the register value
+		echo "sdcmd52rw= 1 3 0xf" > /proc/mwlan/config  # write 0xf to func 1 address 3
+
+	Issue debug_dump command through proc.
+	Usage:
+		echo "debug_dump" > /proc/mwlan/config
+
+	Examples:
+		echo "debug_dump" > /proc/mwlan/config      # dump driver internal debug status.
+
+	Use dmesg or cat /var/log/debug to check driver debug messages.
+	To log driver debug messages to file,
+	a) Edit /etc/syslog.conf, add one line "*.debug		/var/log/debug"
+	   on kernel 2.6.24 or later, edit /etc/rsyslog.conf instead
+	b) touch /var/log/debug (if the file doesn't exist)
+	c) service syslog restart
+	   on kernel 2.6.24 or later, service rsyslog restart
+
+	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 sd8xxx.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/config   trigger inband firmware reset and reload firmware
+       echo "fw_reload=2" > /proc/mwlan/config   trigger firmware reload
+       echo "fw_reload=3" > /proc/mwlan/config   set firmware reload flag in driver.
+
+    (Note: This feature will be supported on Robin3 and KF2.
+           For CAC-A2, it only work with the board which supports parallel fw download)
+
+
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANUTL
+
+NAME
+    mlanutl - configure the additional parameters available for Marvell mdriver.
+
+SYNOPSIS
+    mlanutl -v
+    mlanutl <mlanX|uapX|wfdx> <command> [parameters] ...
+
+	mlanutl mlanX 11dcfg
+	mlanutl mlanX 11dclrtbl
+	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 addts <filename.conf> <section# of tspec> <timeout in ms>
+	mlanutl mlanX aggrpriotbl [<m0> <n0> <m1> <n1> ... <m7> <n7>]
+	mlanutl uapX aggrpriotbl [<m0> <n0> <m1> <n1> ... <m7> <n7>]
+	mlanutl mlanX amsduaggrctrl <n>
+	mlanutl mlanX antcfg [m] [n]
+	mlanutl mlanX arpfilter <arpfilter.conf>
+	mlanutl mlanX assocessid <"[essid]">
+	mlanutl mlanX assocessid_bssid <"[bssid] [essid]">
+	mlanutl mlanX associate "<bssid> <ssid>"
+	mlanutl mlanX authtype [n]
+	mlanutl mlanX autotdls [n]
+        mlanutl mlanX tdls_idle_time [n]
+        mlanutl uapX dfs_offload [n]
+	mlanutl mlanX bandcfg [l] [m] [n] [o]
+	mlanutl mlanX bcninterval [n]
+	mlanutl wfdX bssrole [l]
+	mlanutl mlanX cfgdata <register type> [<conf file>]
+	mlanutl mlanX cfpcode [m] [n]
+	mlanutl mlanX changraph [<load | anpi | anpiload> <loops>]
+	mlanutl mlanX coex_rx_winsize [m]
+	mlanutl mlanX countrycode [l]
+
+	mlanutl	mlanX cfpinfo
+	mlanutl uapX cfpinfo
+
+	mlanutl	mlanX acs [<chX> <chY> ... <chZ>]
+	mlanutl	uapX acs [<chX> <chY> ... <chZ>]
+
+	mlanutl mlanX customie [[[<index>] <mask>] <IEBuffer>]
+	mlanutl mlanX deauth [l]
+	mlanutl uapX deauth [l]
+	mlanutl mlanX deepsleep [l] [m]
+	mlanutl mlanX delba <l> [<m> <n>]
+	mlanutl uapX delba <l> [<m> <n>]
+	mlanutl mlanX delts <filename.conf> <section# of tspec>
+	mlanutl mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+	mlanutl mlanX dfs_repeater [n]
+	mlanutl mlanX drvdbg [n]
+	mlanutl mlanX esuppmode [l] [m] [n]
+	mlanutl mlanX extcapcfg [<ext_cap>]
+	mlanutl mlanX fwmacaddr [mac_addr]
+	mlanutl mlanX getdatarate
+	mlanutl uapX getdatarate
+	mlanutl mlanX getkey
+	mlanutl mlanX getlog
+	mlanutl mlanX getscantable [ARGS]
+	mlanutl mlanX getsignal [m] [n]
+	mlanutl mlanX signalextcfg [m]
+	mlanutl mlanX getsignalextv2 [m]
+	mlanutl mlanX getsignalext [m]
+        mlanutl mlanX dyn_bw [n]
+	mlanutl uapX getstalist
+	mlanutl uapX channel_switch <switch mode> <oper class> <new channel> <switch count> <bandwidth>
+	mlanutl mlanX hostcmd <11n_2040coex.conf> 2040coex
+	mlanutl mlanX hostcmd <auto_tx.conf> auto_tx_get
+	mlanutl mlanX hostcmd <auto_tx.conf> auto_tx_unreg
+	mlanutl mlanX hostcmd <bg_scan.conf> bgscfg
+
+	mlanutl mlanX hostcmd <pkt_coalescing.conf> coalesce_cfg
+	mlanutl mlanX hostcmd <ed_mac_ctrl.conf> ed_mac_ctrl
+	mlanutl mlanX hostcmd <crypto_test.conf> crypto_test
+	mlanutl mlanX hostcmd <auto_tx.conf> nat_keep_alive
+	mlanutl mlanX hostcmd <pad_cfg.conf> pad_cfg_get
+	mlanutl mlanX hostcmd <pad_cfg.conf> pad_cfg_set
+	mlanutl mlanX hostcmd <requesttpc.conf> requesttpc
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_get
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_timeshare
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_spatial
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_none
+	mlanutl mlanX hostcmd <robust_btc.conf> gpio_cfg
+	mlanutl mlanX hostcmd <robust_btc.conf> generictime
+	mlanutl mlanX hostcmd <robust_btc.conf> a2dptime
+	mlanutl mlanX hostcmd <robust_btc.conf> inquirytim
+	mlanutl mlanX hostcmd <robust_btc.conf> ap_generictime
+	mlanutl mlanX hostcmd <robust_btc.conf> ap_a2dptime
+	mlanutl mlanX hostcmd <robust_btc.conf> ap_inquirytime
+	mlanutl mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_disable
+	mlanutl mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_get
+	mlanutl mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_set
+	mlanutl mlanX hostcmd <subevent.conf> subevent_get
+	mlanutl mlanX hostcmd <subevent.conf> subevent_set
+	mlanutl mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_2g_cfg_set
+	mlanutl mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_5g_cfg_set
+	mlanutl mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_cfg_get
+	mlanutl mlanX hostcmd <txrate_cfg.conf> txrate_cfg_get
+	mlanutl mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bg
+	mlanutl mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bgn
+	mlanutl mlanX hostcmd <conf> generate_raw <raw_data_file>
+	mlanutl mlanX hostcmd <fwdump.conf> fwdump
+
+	mlanutl mlanX hotspotcfg [<bitmap>]
+	mlanutl mlanX hscfg [condition [[GPIO# [gap]]]] [ind_GPIO# [level]]
+	mlanutl mlanX hssetpara condition [GPIO# [gap]] [ind_GPIO# [level]]
+	mlanutl mlanX mgmtfilter <mgmtfilter.conf>
+	mlanutl mlanX auto_arp [n]
+	mlanutl mlanX htcapinfo [<m>] [<n>]
+	mlanutl mlanX htstreamcfg [n]
+	mlanutl mlanX httxbfcap [cap]
+	mlanutl mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData]"
+	mlanutl mlanX httxcfg [<m>] [<n>]
+	mlanutl mlanX inactivityto <n> <m> <l> [k]
+	mlanutl mlanX ipaddr ["<op>;<ipaddr>"]
+	mlanutl mlanX linkstats
+	mlanutl mlanX listeninterval [l]
+	mlanutl mlanX macctrl [n]
+	mlanutl uapX macctrl [n]
+	mlanutl mlanX mefcfg <mef.conf>
+	mlanutl mlanX memrdwr <address> [value]
+	mlanutl mlanX miracastcfg [l] [m] [n]
+	mlanutl mlanX mgmtframectrl [<mask>]
+	mlanutl uapX mgmtframectrl [<mask>]
+	mlanutl mlanX mgmtframetx <mgmt_frame.conf>
+	mlanutl mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+	mlanutl mlanX netmon [<act> [<filter> <band> <chan> [offset]]]
+	mlanutl mlanX offchannel [<l> <m> <n>]
+	mlanutl mlanX otpuserdata <l>
+	mlanutl mlanX passphrase [l]
+	mlanutl mlanX pb_bypass [data_1, data_2, ... data_n]
+	mlanutl mlanX pmfcfg <mfpc> <mfpr>
+	mlanutl mlanX port_ctrl [n]
+	mlanutl mlanX powercons [n]
+	mlanutl mlanX pscfg [k] [d] [l] ...
+	mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p]
+	mlanutl mlanX psmode [l]
+        mlanutl <interface> robustcoex <gpiocfg> [Enable/Disable] [gpionum] [gpiopolarity]
+	mlanutl mlanX qconfig def [Queue Id: 0-3]
+	mlanutl mlanX qconfig get [Queue Id: 0-3]
+	mlanutl mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+	mlanutl mlanX qoscfg
+	mlanutl mlanX qstatus
+	mlanutl mlanX radioctrl [n]
+	mlanutl mlanX rdeeprom <offset> <length>
+	mlanutl mlanX reassoctrl [n]
+	mlanutl mlanX regioncode [n]
+	mlanutl mlanX regrdwr <type> <offset> [value]
+	mlanutl mlanX rejectaddbareq [conditions]
+	mlanutl uapX rejectaddbareq [conditions]
+	mlanutl mlanX scancfg [t] [m] [p] [s] [a] [b] [c] [ext]
+	mlanutl mlanX sdcmd52rw <FN no.> <address> [data]
+	mlanutl mlanX sdcmd53rw <FN no.> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+	mlanutl mlanX sdioclock <n>
+	mlanutl mlanX setuserscan [ARGS]
+	mlanutl mlanX cancelscan
+	mlanutl mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+	mlanutl mlanX sleeppd [n]
+	mlanutl mlanX sysclock [clk1] [clk2] [clk3] [clk4]
+	mlanutl mlanX tcpackenh [l]
+	mlanutl mlanX tdls_channel_switch <tdls.conf>
+	mlanutl mlanX tdls_config <0/1>
+	mlanutl mlanX tdls_cs_params <tdls.conf>
+	mlanutl mlanX tdls_debug "allow_weak_security" <0/1>
+	mlanutl mlanX tdls_debug "cs_im_return" <0/1>
+	mlanutl mlanX tdls_debug "fail_setup_confirm" <0/1>
+	mlanutl mlanX tdls_debug "higher_lower_mac" <0/1>
+	mlanutl mlanX tdls_debug "ignore_key_expiry" <0/1>
+	mlanutl mlanX tdls_debug "setup_existing_link" <0/1>
+	mlanutl mlanX tdls_debug "setup_with_prohibited" <0/1>
+	mlanutl mlanX tdls_debug "stop_rx" <0/1>
+	mlanutl mlanX tdls_debug "wrong_bss" <0/1>
+	mlanutl mlanX tdls_disable_cs <0/1>
+	mlanutl mlanX tdls_discovery <tdls.conf>
+	mlanutl mlanX tdls_link_status
+	mlanutl mlanX tdls_powermode <tdls.conf>
+	mlanutl mlanX tdls_setinfo <tdls.conf>
+	mlanutl mlanX tdls_setup <tdls.conf>
+	mlanutl mlanX tdls_stop_channel_switch <tdls.conf>
+	mlanutl mlanX tdls_teardown <tdls.conf>
+	mlanutl mlanX thermal
+	mlanutl mlanX ts_status
+	mlanutl mlanX tsf
+	mlanutl mlanX txaggrctrl [m]
+	mlanutl mlanX txbufcfg
+	mlanutl mlanX txratecfg [l] [m] [n]
+	mlanutl uapX txratecfg [l] [m] [n]
+    mlanutl mlanX verext
+    mlanutl mlanX version
+	mlanutl mlanX vhtcfg <j> <k> [l] [m] [n] [o]
+	mlanutl uapX vhtcfg <j> <k> [l] [m] [n] [o]
+	mlanutl mlanX wakeupreason
+	mlanutl uapX wakeupreason
+	mlanutl mlanX warmreset
+	mlanutl mlanX wpssession [n]
+	mlanutl mlanX wmmcfg [n]
+	mlanutl mlanX wmmparamcfg [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+				[AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+				[AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+				[AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+	mlanutl mlanX wwscfg [m]
+	mlanutl mlanX mc_cfg [n]
+	mlanutl mlanX mc_policy [n]
+	mlanutl mlanX mc_cfg_ext [c] [s] [u] [m] <a> <b> <d> <e>
+	mlanutl p2pX cfg_noa [h] [i] [j] [k] [l]
+	mlanutl p2pX cfg_opp_ps [m] [n]
+
+        mlanutl uapX ctrldeauth <n>
+
+        mlanutl mlanX/uapX bootsleep <1/0>
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell 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.
+
+11dcfg
+	This command is used to control 11D. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 11dcfg 1           : Enable 11D
+		mlanutl mlan0 11dcfg             : Get 11D status
+
+11dclrtbl
+	This command is used to clear the 11D channel table.
+
+	Usage:
+		mlanutl mlanX 11dclrtbl
+
+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.
+
+addts
+	Send an ADDTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in an ADDTS request to the associated AP.
+
+	Return the execution status of the command as well as the ADDTS response
+	  from the AP if any.
+
+	Usage:
+		mlanutl mlanX addts <filename.conf> <section# of tspec> <timeout(ms)>
+
+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.
+
+amsduaggrctrl
+	This command could be used to enable/disable a feature where firmware gives feedback to driver
+	regarding the optimal AMSDU buffer size to use with the current rate. Firmware will use the
+	current rate to decide the buffer size we could transmit. The max buffer size will still be
+	limited by buffer size provided in txbufcfg. (i.e. if the txbufcfg is 4K, then we could only transmit
+	4K/2K AMSDU packets, if the txbufcfg is 8K then we could transmit 8k/4k/2k based on current rate)
+
+	If enabled AMSDU buffer size at various rates will be as follows
+
+	1.	Legacy B/G rate.
+		No AMSDU aggregation.
+
+	2.	BW20 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 3, 2:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 1, 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 4, 3:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	3.	BW40 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4, 3, 2, 1:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5, 4, 3:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	where <n> is 0/1 (for disable/enable)
+
+	eg:
+	mlanutl mlan0 amsduaggrctrl 1 - Enable this feature
+	mlanutl mlan0 amsduaggrctrl 0 - Disable this feature
+	mlanutl mlan0 amsduaggrctrl - This will get the enable/disable flag
+	and the current AMSDU buffer size). The AMSDU buffer size returned is only
+	valid after association as before association there is no rate info.
+
+	Note:- This command to enable/disable could be given anytime (before/after
+			association). This feature is enabled by default by the driver during
+			initialization.
+
+antcfg
+	This command is used to set/get the mode of Tx/Rx path.
+
+    For chip which support STREAM_2X2
+	where value of m is:
+		Bit 0   -- Tx Path A or Tx/Rx Path A if [n] is not provided
+		Bit 1   -- Tx Path B or Tx/Rx Path B if [n] is not provided
+		Bit 0-1 -- Tx Path A+B or Tx/Rx Path A+B if [n] is not provided
+	where value of n is:
+		Bit 0   -- Rx Path A
+		Bit 1   -- Rx Path B
+		Bit 0-1 -- Rx Path A+B
+	The Tx path setting (m) is used for both Tx and Rx if Rx path (n) is not provided.
+
+	Examples:
+		mlanutl mlan0 antcfg             : Get Tx and Rx path
+		mlanutl mlan0 antcfg 3           : Set Tx and Rx path to A+B
+		mlanutl mlan0 antcfg 1 3         : Set Tx path to A and Rx path to A+B
+
+    For chip which support SAD
+    	where value of m is:
+		Bit 0   -- Tx/Rx antenna 1
+		Bit 1   -- Tx/Rx antenna 2
+		...
+		0xFFFF  -- Tx/Rx antenna diversity
+
+        where value of n is:
+                SAD evaluate time interval, only be provided when m = 0xFFFF, default value is 6s(0x1770)
+
+	Examples:
+		mlanutl mlan0 antcfg               : Get Tx/Rx antenna mode
+		mlanutl mlan0 antcfg 1             : Set Tx/Rx antenna 1
+		mlanutl mlan0 antcfg 0xFFFF        : Set Tx/Rx antenna diversity
+		mlanutl mlan0 antcfg 0xFFFF 0x1770 : Set antenna evaluate time interval to 6s
+
+arpfilter
+	This command is used to configure the ARP filtering parameters.
+
+	Usage:
+		mlanutl mlanX arpfilter <arpfilter.conf>
+
+	Where the parameter is:
+		arpfilter.conf : The configuration file specifying ARP filtering parameters.
+
+	Example:
+		mlanutl mlan0 arpfilter config/arpfilter.conf
+
+assocessid
+	This command is used to assoc essid with asynced mode,
+	and driver will auto retry if driver auto assoc enabled.
+
+	Usage:
+		mlanutl mlanX assocessid <"[essid]">
+
+	Where
+	<"[essid]"> is the essid which need to be associated with asynced mode.
+
+	Examples:
+		mlanutl mlan0 assocessid "Marvell Micro AP"    : Associate to the ESSID "Marvell Micro AP"
+
+assocessid_bssid
+	This command is used to assoc AP by ssid/bssid pair with asynced mode,
+	and driver will auto retry if driver auto assoc enabled.
+
+	Usage:
+		mlanutl mlanX assocessid_bssid <"[bssid] [essid]">
+
+	Where
+	<"[bssid]"> is the bssid which need to be associated with asynced mode.
+	<"[essid]"> is the essid which need to be associated with asynced mode.
+
+	Examples:
+		mlanutl mlan0 assocessid_bssid "xx:xx:xx:xx:xx:xx Marvell Micro AP"   : Associate to the AP which ssid = "Marvell Micro AP", bssid = "xx:xx:xx:xx:xx:xx"
+
+associate
+	Request an association to a given SSID/BSSID pair. This the only accurate
+	way to pick a specific AP and ESS for an association. The entry must
+	already exist in the scan table for the association to be attempted.
+
+	mlanutl mlanX associate "xx:xx:xx:xx:xx:xx SSID"
+
+authtype
+	This command is used to set/get authentication type.
+
+	Usage:
+		mlanutl mlanX authtype [n]
+
+	where <n>
+		0: 802.11 open system authentication
+		1: 802.11 shared key authentication
+		3: 802.11 WPA3 SAE authentication
+		255: allow open system or shared key authentication (default)
+
+	Examples:
+		mlanutl mlan0 authtype 0         : use open system authentication
+		mlanutl mlan0 authtype 1         : use shared key authentication
+		mlanutl mlan0 authtype 255       : allow open system or shared key authentication
+		mlanutl mlan0 authtype           : get current setting
+
+autotdls
+	This command is used to enable/disable auto TDLS.
+
+	Usage:
+		mlanutl mlanX autotdls [n]
+
+	where <n>
+		0: Disable auto tdls
+		1: Enable auto tdls
+
+	Examples:
+		mlanutl mlan0 autotdls 1         : enable auto TDLS
+		mlanutl mlan0 autotdls 0         : disable auto TDLS
+		mlanutl mlan0 autotdls           : get current setting
+
+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
+
+tdls_idle_time
+	This command is used to set/get TDLS idle timeout. The valid value is between 0-0xffff. When set to 0, the tdls_idle_time will use default value(60).
+
+	Usage:
+		mlanutl mlanX tdls_idle_time [n]
+
+	where <n>
+		TDLS idle timeout value
+
+	Examples:
+		mlanutl mlan0 tdls_idle_time 30        : set tdls_idle_time value to 30
+		mlanutl mlan0 tdls_idle_time 0         : use default tdls_idle_time value(60)
+		mlanutl mlan0 tdls_idle_time           : get current setting
+
+dfs_offload
+	This command is used to enable/disable DFS offload. The valid value is 0/1.
+	Note: The parameters can be set only in disconnected state.
+
+	Usage:
+		mlanutl uapX dfs_offload [n]
+
+	where <n>
+		Enable/disable
+
+	Examples:
+		mlanutl uap0 dfs_offload 1         : enable DFS offload
+		mlanutl uap0 dfs_offload 0         : disable DFS offload
+
+bandcfg
+	This command is used to set/get infra/ad-hoc band.
+	Note: This command is only available in disconnected state.
+
+	Usage:
+		mlanutl mlanX bandcfg [l] [m] [n] [o]
+
+	where the parameters:
+		[l]: Infrastructure band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+
+		     bit 5: AC 2.4G
+		     bit 6: AC 5G
+		[m]: Ad-hoc start band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+		     bit 5: AC 2.4G
+		     bit 6: AC 5G
+		[n]: Ad-hoc start channel
+		[o]: 0 - Bandwidth 20Mhz
+		     1 - HT Bandwidth 40Mhz above
+		     3 - HT Bandwidth 40Mhz below
+			 4 - VHT Bandwidth 80Mhz
+	Examples:
+		mlanutl mlan0 bandcfg            : Get infra/ad-hoc band and ad-hoc
+		                                  start channel configurations
+		mlanutl mlan0 bandcfg 1          : Set infra band to B only
+		mlanutl mlan0 bandcfg 3 2 6      : Set infra band to B/G, ad-hoc start band
+		                                  to G and ad-hoc start channel to 6
+		mlanutl mlan0 bandcfg 7 11 6 1   : Set infra band to B/G/A, ad-hoc start band
+		                                  to B/G/GN, ad-hoc start channel to 6 and
+		                                  secondary channel to above
+
+bcninterval
+	This command is used to set/get the beacon interval in ad-hoc mode.
+	The valid beacon interval is between 20 - 1000, default beacon
+	interval is 100.
+
+	Where <n>
+		Beacon interval in TU (Time Unit: 1024 us).
+
+	Examples:
+		mlanutl mlan0 bcninterval 200    : Set ad-hoc beacon interval to 200
+		mlanutl mlan0 bcninterval        : Get ad-hoc beacon interval
+
+bssrole
+	This command is used to set/get the BSS role.
+
+	Where
+	[l] is <bss_role>
+	<bss_role> - This parameter specifies the BSS role to set.
+		0       : STA
+		1       : uAP
+
+	Examples:
+		mlanutl wfd0 bssrole                 : Get the current BSS role
+		mlanutl wfd0 bssrole 1               : Set the current BSS role to uAP
+
+cfgdata
+	This command is used to set/get the configuration data to/from firmware.
+
+	Usage:
+		mlanutl mlanX cfgdata <type> [<.conf file name>]
+
+	Where the parameters are:
+		type :
+		        2 -- CAL data download and <.conf file name> is cal_data.conf
+		.conf file name : The configuration file used to set/get the configuration data.
+
+	Examples:
+		mlanutl mlan0 cfgdata 2
+			: This command is used to get and display the CAL data from firmware.
+
+cfpcode
+	This command is used to set/get the Channel-Frequency-Power table codes.
+	The region table can be selected through region code.
+	The current configuration is returned if no parameter provided.
+
+	where the parameters are,
+		[m]: code of the CFP table for 2.4GHz (0: unchanged)
+		[n]: code of the CFP table for 5GHz (0 or not provided: unchanged)
+
+	Examples:
+		mlanutl mlan0 cfpcode            : Get current configuration
+		mlanutl mlan0 cfpcode 0x30       : Set 2.4GHz CFP table code 0x30 (EU),
+		                                  keep 5GHz table unchanged
+		mlanutl mlan0 cfpcode 0x10 5     : Set 2.4GHz CFP table code 0x10 (USA)
+		                                  and 5GHz table code 5
+
+changraph
+	Displays 2-dimensional graph, plotting channel number along x-axis and
+	anpi or channel-load along y-axis, depending on whether it is an anpi graph
+	or a channel load graph.
+
+	Usage:
+		mlanutl mlanX changraph [<load | anpi | anpiload> <loops>]
+		where:
+			load:       Only channel vs channel-load graph is displayed
+			anpi:       Only channel vs Average Noise Power Indicator(ANPI)
+						graph is displayed
+			anpiload:   Both the graphs for anpi and for the load are displayed
+			loops:      This is used to calculate the number of times
+						the graph [load or anpi or both] will be printed
+
+coex_rx_winsize
+	This command is used to set/get control to coex RX window size
+
+	where value of m is:
+		0       -- Disable COEX RX winsize (default)
+		1       -- Enable COEX RX winsize
+
+	Examples:
+		mlanutl mlan0 coex_rx_winsize             : Get COEX RX winsize
+		mlanutl mlan0 coex_rx_winsize 1           : Enable COEX RX winsize
+
+countrycode
+	This command is used to set and get the country code.
+
+	Where
+	[l] is Country code
+
+	Examples:
+		mlanutl mlan0 countrycode            : Get current countrycode
+		mlanutl mlan0 countrycode CN         : Set countrycode as China (CN)
+
+cfpinfo
+	This command is used to get region, country, environment codes,
+	channel and power table information from the FW.
+
+	Examples:
+		mlanutl mlan0 cfpinfo		     : Display cfp tables
+		mlanutl uap0 cfpinfo
+
+acs
+	This command is used to issue acs scan, then FW will
+	report the best channel and channel statistics.
+	User could specify channels or not. If channel is not
+	specified, acs scan will be on all supported channels.
+
+	Examples:
+		mlanutl mlan0 acs		     : ACS scan on all supported channels
+		mlanutl uap0 acs		     : ACS scan on all supported channels
+		mlanutl mlan0 acs 5 6 7 8	     : ACS scan on 5 6 7 8 channels
+		mlanutl uap0 acs 1 2 3		     : ACS scan on 1 2 3 channels
+
+customie
+	This command is used to set or get custom IEs for management frames.
+
+	Usage:
+		mlanutl mlanX customie [[[<index>] <mask>] <IEBuffer>]
+
+	Where the parameter is:
+		empty - Get all IE settings
+		<index> :   0 - Get/Set IE index 0 setting
+		            1 - Get/Set IE index 1 setting
+		            2 - Get/Set IE index 2 setting
+		           MAX IE Index depends on device memory.
+		           -1 - Append/Delete IE automatically
+		                Delete will delete the IE from the matching IE buffer
+		                Append will append the IE to the buffer with the same mask
+		<mask>      :  Management subtype mask value as per bit definitions
+		            :  Bit 0 - Association request
+		            :  Bit 1 - Association response
+		            :  Bit 2 - Reassociation request
+		            :  Bit 3 - Reassociation response
+		            :  Bit 4 - Probe request
+		            :  Bit 5 - Probe response
+		            :  Bit 8 - Beacon
+		<mask>      :  mask = 0 to clear the mask and the IE buffer
+		<IEBuffer>  :  IE Buffer in hex (max 256 bytes)
+		               The Buffer should not be space separated.
+
+	Examples:
+		mlanutl mlan0 customie
+			: Get IE buffer, subtype mask settings for all indices.
+
+		mlanutl mlan0 customie 1
+			: Get IE buffer and subtype mask for the Index = 1.
+
+		mlanutl mlan0 customie 2 0
+			: Clear IE buffer and mask value for Index = 2.
+
+		mlanutl mlan0 customie 3 0x101 0xdd051234567890
+			: Set IE buffer and mask value for Index = 3.
+
+		mlanutl mlan0 customie -1 0x101 0xdd051234567890
+			: Append the specified IEBuffer at index with mask value of 0x101.
+
+		mlanutl mlan0 customie -1 0 0xdd051234567890
+			: Delete the specified IEBuffer from all the IEs.
+
+		mlanutl mlan0 customie 2 0 0xdd051234567890
+			: Delete the specified IEBuffer from the IEs at index 2.
+
+deauth
+	This command is used to send a de-authentication to an arbitrary AP.
+	If [l] is omitted, the driver will deauth the associated AP.
+	If in ad-hoc mode this command is used to stop beacon transmission
+	from the station and go into idle state.
+
+	When <l> is supplied as a MAC address, the driver will deauth the
+	  specified AP.  If the AP address matches the driver's associated AP,
+	  the driver will disconnect. Otherwise, the driver remains connected.
+
+	When this command is executed on AP interface, it is used to send
+	a de-authentication to associated station.
+
+deepsleep
+	This command is used to set/get auto deep sleep mode.
+
+	Usage:
+		mlanutl mlanX deepsleep [l] [m]
+
+	where the parameters are:
+		[l]: Enable/disable auto deep sleep mode (1/0)
+		[m]: Idle time in milliseconds after which firmware will put the device
+		     in deep sleep mode. Default value is 100 ms.
+
+	Examples:
+		mlanutl mlan0 deepsleep          : Display auto deep sleep mode
+		mlanutl mlan0 deepsleep 1        : Enable auto deep sleep mode, idle time unchanged
+		mlanutl mlan0 deepsleep 0        : Disable auto deep sleep mode
+		mlanutl mlan0 deepsleep 1 500    : Enable auto deep sleep mode with idle time 500 ms
+        Note:
+            Deepsleep must be disabled before changing idle time.
+
+delba
+	This command is used to delete either all Tx BA or all Rx BA or a specific BA stream
+	based on direction, TID and peer address.
+
+	where <l> [<m> <n>]
+		<l> - This is the direction of BA stream, Tx (bit 0), Rx (bit 1).
+		<m> - This is the TID (0-7, 0xff for all) of BA stream.
+		<n> - This is the peer MAC addres of BA stream.
+
+	eg:
+	mlanutl mlanX delba 2 - This command will delete all the Rx BA streams.
+	mlanutl mlanX delba 3 - This command will delete all the Tx and Rx BA streams.
+	mlanutl mlanX delba 1 0 - This command will delete all the Tx streams with TID 0.
+	mlanutl mlanX delba 2 0xff "00:11:22:33:44:55" - This command will delete all the Rx BA streams
+		with specified peer MAC address
+	mlanutl mlanX delba 1 3 "00:11:22:33:44:55" - This command will delete the Tx BA stream with
+		TID 3 and specified peer MAC address.
+
+delts
+	Send a DELTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in a DELTS request to the associated AP.
+
+	Return the execution status of the command.  There is no response to a
+	  DELTS from the AP.
+
+	Usage:
+		mlanutl mlanX delts <filename.conf> <section# of tspec>
+
+dfstesting
+	This command is used to set/get settings for DFS testing.
+
+	Usage:
+	    mlanutl mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+
+	where <user_cac_pd> is user-configured Channel Availability Check in msec
+                        0 = disable, use default period (60000)
+                        1-65535 = enable with that period
+	where <user_nop_pd> is user-configured Non-Occupancy Period in sec
+                        0 = disable, use default period (1800)
+                        1-65535 = enable with that period
+	where <no_chan_change> is enable/disable no channel change on radar
+                           0 = disable, 1 = enable (overrides below)
+	where <fixed_chan_num> is user-configured channel to change to on radar
+                           0 = disable, 1-255 = enable with that channel
+                           (channel validity for region, etc. is not checked)
+                           (only takes effect if no_chan_change = 0)
+
+	Examples:
+		mlanutl mlan0 dfstesting             : Get current dfstesting settings
+		mlanutl mlan0 dfstesting 2000 0 0 0  : user_cac=2sec, others disabled/default
+		mlanutl mlan0 dfstesting 0 0 1 0     : only no_chan_change enabled
+		mlanutl mlan0 dfstesting 0 120 0 64  : user_nop=2min, force chan 64 on radar
+
+dfs_repeater
+	This command is used to get/set DFS Repeater mode.
+
+	Usage:
+		mlanutl mlan0 dfs_repeater <n>
+
+	where the parameter is <n> :
+		null:	to get current setting
+		1:	to enable dfs_repeater mode
+		0:	to disable dfs_repeater mode
+
+	eg.,
+		mlanutl mlan0 dfs_repeater        :get current setting
+		mlanutl mlan0 dfs_repeater 1	  :enable dfs repeater mode
+		mlanutl mlan0 dfs_repeater 0	  :disable dfs repeater mode
+
+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
+
+esuppmode
+	This command is used to set/get the e-supplicant mode configurations/status.
+
+	Note: The configurations can be set only before association.
+	      For get, the configurations will be returned before association
+	      and the current status will be returned after association.
+
+	Where
+	[l] is <rsn_mode>
+	<rsn_mode> - This parameter specifies the RSN mode configuration
+		Bit 0    : No RSN
+		Bit 1-2  : RFU
+		Bit 3    : WPA
+		Bit 4    : WPA-NONE
+		Bit 5    : WPA2
+		Bit 6-15 : RFU
+	[m] is <pairwise_cipher>
+	<pairwise_cipher> - This parameter specifies the pairwise cipher
+		Bit 0    : RFU
+		Bit 1    : RFU
+		Bit 2    : TKIP
+		Bit 3    : AES
+		Bit 4-7  : RFU
+	[n] is <group_cipher>
+	<group_cipher> - This parameter specifies the group cipher
+		Bit 0    : RFU
+		Bit 1    : RFU
+		Bit 2    : TKIP
+		Bit 3    : AES
+		Bit 4-7  : RFU
+	Note that: the RFU bits cannot be SET.
+
+	Examples:
+		mlanutl mlan0 esuppmode          : Get RSN mode and pairwise/group cipher
+		mlanutl mlan0 esuppmode 8 4 4    : Set RSN mode yo WPA, active pairwise and
+		                                   group ciphers to TKIP
+
+extcapcfg
+	This command is used to set/get extended capabilities.
+
+	Usage:
+		mlanutl mlanX extcapcfg [<ext_cap>]
+
+	where <ext_cap> :  Extended capabilities in hex (max 9 bytes)
+		               The Buffer should not be space separated.
+
+	Examples:
+		mlanutl mlan0 extcapcfg 0x0000008020	: Set TDLS support and Interworking bits.
+
+fwmacaddr
+	This command is used to set/get FW side MAC address but host side address will remain as earlier.
+
+	Usage:
+		mlanutl mlanX fwmacaddr [mac_addr]
+
+	where <mac_addr> is desired MAC address
+
+	Examples:
+		mlanutl mlan0 fwmacaddr                        : Get current FW MAC address
+		mlanutl mlan0 fwmacaddr 00:50:43:20:bc:44      : Set FW side MAC address
+
+getdatarate
+	This command is used to get the data rate being used in last Tx
+	packet and last Rx packet.
+
+getkey
+	This command is used to get PTK/GTK
+
+	mlanutl mlanX getkey
+
+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
+
+getscantable
+	Display the current contents of the driver scan table
+
+	Usage:
+		mlanutl mlanX getscantable
+		mlanutl mlanX getscantable [#]
+		mlanutl mlanX getscantable tsf
+		mlanutl mlanX getscantable ch
+		mlanutl mlanX getscantable help
+
+	1) Without argument, the entire scantable is displayed in terms of channel (ch), signal strength (ss), BSS id (bssid), capability (cap), and SSID,
+		where each column in the capability is described as follows:
+		column 1 indicates the IBSS capability: A (Adhoc), I (Infra)
+		column 2 indicates the encryption capability: P (WEP), W (WPA), 2 (WPA2)
+		column 3 indicates the 11D capability: D (11D)
+		column 4 indicates the WMM capability: W (WMM), C (CAC)
+		column 5 indicates the 11K capability: K (11K)
+		column 6 indicates the 11R capability: R (11R)
+		column 7 indicates the WPS capability: S (WPS)
+		column 8 indicates the 11N/11AC capability: N (11N), A (11AC)
+
+	2) Specifying a # will display detailed information about a specific scan
+	   table entry.  '0' displays driver cached information regarding the
+	   current association (if any).
+	3) The tsf argument will display the entire scan table with the recorded
+	   TSF timestamp for the entry.
+	4) The ch argument will display the entire scan table sorted by channel
+	   number in the ascending order. If this argument is not specified,
+           scan table is sorted by signal strength in the descending order.
+	6) The help argument will display the legend for the capability field.
+
+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
+
+getstalist
+    This command is used to get list of associated stations to the AP.
+
+    Example:
+        mlanutl uap0 getstalist
+
+channel_switch <switch mode> <oper class> <new channel> <switch count> <bandwidth>
+    This command is used to do channel switch according to spec.
+
+    Where the paramters are:
+        switch mode : 0 -- no need to block traffic, 1 -- need block traffic
+        oper class  : operating class according to IEEE std802.11 spec, when 0 is used, only CSA IE will be used
+        new channel : the channel will switch to
+        switch count: channel switch time to send ECSA ie
+        bandwidth   : channel width switch to(optional),only for 5G channels.
+                      Support value 1 -- 40M above, 3 -- 40M below, 4 -- 80M, 5 -- 160M
+
+    Example:
+        mlanutl uap0 channel_switch 1 115 36 10      :switch to channel 36, oper class 115
+        mlanutl uap0 channel_switch 1 81 6 10        :switch to channel 6, oper class 81
+        mlanutl uap0 channel_switch 1 0 6 10         :switch to channel 6
+        mlanutl uap0 channel_switch 1 0 36 10 1      :switch to channel 36, bandwidth 40MHz above
+
+hostcmd 2040coex
+	This command is used to send the 11n 20/40 Coex command to firmware.
+	Firmware will send 11n 20/40 Coex management action frame to AP.
+
+	Usage:
+		mlanutl mlanX hostcmd config/11n_2040coex.conf 2040coex
+
+hostcmd auto_tx_get
+hostcmd auto_tx_unreg
+	This command is used to configures the Frame Auto Transmission parameters.
+	auto_tx_get: get auto_tx parameters
+	auto_tx_unreg: unregister to firmware auto_tx
+
+	Usage:
+		mlanutl mlanX hostcmd config/auto_tx.conf auto_tx_get
+		mlanutl mlanX hostcmd config/auto_tx.conf auto_tx_unreg
+
+hostcmd bgscfg
+	This command is used to configure the various parameters for PPS/UAPSD
+	or normal background scan.
+
+	Usage:
+		mlanutl mlanX hostcmd config/bg_scan.conf bgscfg
+
+hostcmd <pkt_coalescing.conf> coalesce_cfg
+	This command is used to set/clear rules to filter and buffer
+	broadcast/multicast packet which reduce unwanted patcket or interrupt to
+	host.
+
+	Usage:
+		mlanutl mlanX hostcmd <pkt_coalescing.conf> coalesce_cfg
+
+hostcmd <ed_mac_ctrl.conf> ed_mac_ctrl
+	This command is used to control ED MAC.
+
+	Usage:
+		mlanutl mlanX hostcmd <ed_mac_ctrl.conf> ed_mac_ctrl
+
+hostcmd crypto_test
+	This command is used to test the encryption/decryption API of the firmware.
+
+	Usage:
+		mlanutl mlanX hostcmd config/crypto_test.conf crypto_test
+
+hostcmd nat_keep_alive
+	This command is used to configures the Frame Auto Transmission parameters.
+	nat_keep_alive: register to firmware for sending NAT Keep Alive packet
+
+	Usage:
+		mlanutl mlanX hostcmd config/auto_tx.conf nat_keep_alive
+
+hostcmd pad_cfg_get
+hostcmd pad_cfg_set
+	This command is used to set/get the configuration data for PAD OR.
+
+	Usage:
+		mlanutl mlanX hostcmd config/pad_cfg.conf pad_cfg_get
+		mlanutl mlanX hostcmd config/pad_cfg.conf pad_cfg_set
+
+hostcmd requesttpc
+	This command is used to request 802.11H TPC info.
+
+	Usage:
+		mlanutl mlanX hostcmd config/requesttpc.conf requesttpc
+
+hostcmd mode_get
+hostcmd mode_timeshare
+hostcmd mode_spatial
+hostcmd mode_none
+	This command is used to get/set Robust BT Coex.
+	mode_get:       get the current mode
+	mode_timeshare: set Robust BT Coex to timeshare mode  (default on 1x1_1Antenna chips)
+	mode_spatial:   set Robust BT Coex to spatial mode    (default on 2x2 chips)
+	mode_none:      set Robust BT Coex to mode none       (default on chips with dedicated BT Antenna. Example: 2x2_3Antenna, 1x1_2Antenna chips)
+
+	Usage:
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_get
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_timeshare
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_spatial
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_none
+
+hostcmd gpio_cfg
+	This command is used to enable/disable GPIO cfg.
+	gpio_cfg:       enable/disable GPIO cfg for external bt request  (default is enable with High Polarity)
+
+	Usage:
+		mlanutl mlanX hostcmd config/robust_btc.conf gpio_cfg
+
+hostcmd generictime
+hostcmd a2dptime
+hostcmd inquirytime
+hostcmd ap_generictime
+hostcmd ap_a2dptime
+hostcmd ap_inquirytime
+        This command is used to configure the time slice of COEX (only works in timeshare mode)
+        generictime:       configure the Bttime and Wlantime in Station Generic case
+        a2dptime:          configure the Bttime and Wlantime in Station A2DP case
+        inquirytime:       configure the Bttime and Wlantime in Station Inquiry case
+        ap_generictime:    configure the Bttime and Wlantime in Ap Generic case
+        ap_a2dptime:       configure the Bttime and Wlantime in Ap A2DP case
+        ap_inquirytime:    configure the Bttime and Wlantime in Ap Inquiry case
+
+    Usage:
+                mlanutl mlanX hostcmd config/robust_btc.conf generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf inquirytim
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime
+
+hostcmd sdio_pulldown_get
+hostcmd sdio_pulldown_set
+hostcmd sdio_pulldown_disable
+	This command is used to set/get the settings of pulling up and
+	pulling down of SDIO lines.
+
+	Usage:
+		mlanutl mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_get
+		mlanutl mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_set
+		mlanutl mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_disable
+
+hostcmd subevent_get
+hostcmd subevent_set
+	This command is used to get/set the configurations for event descriptor
+	interface command.
+	subsvent_get: get subscribed event parameters
+	subsvent_set: set subscribed event parameters
+
+	Usage:
+		mlanutl mlanX hostcmd config/subevent.conf subevent_get
+		mlanutl mlanX hostcmd config/subevent.conf subevent_set
+
+hostcmd txpwrlimit_2g_cfg_set
+hostcmd txpwrlimit_5g_cfg_set
+hostcmd txpwrlimit_cfg_get
+	This command is used to set/get the configuration data of Tx power limitation.
+	Note: The configuration set should be issued when STA is disconnected.
+
+	Usage:
+		mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get
+		mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set
+		mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set
+
+hostcmd txrate_cfg_get
+hostcmd txrate_cfg_set_bg
+hostcmd txrate_cfg_set_bgn
+	This command is used to set/get the transmit data rate.
+
+	Usage:
+		mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_get
+		mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bg
+		mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bgn
+
+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>
+
+hostcmd fwdump
+	This command is used to trigger firmware dump
+
+	Usage:
+		mlanutl mlanX hostcmd <fwdump.conf> fwdump
+
+hotspotcfg
+	This command is used to get/set the HotSpot configuration.
+
+	Usage:
+		mlanutl mlanX hotspotcfg [<bitmap>]
+
+	Where the parameter is:
+		<bitmap> : configuration bitset
+			 : Bit 31-10 - Reserved set to 0
+			 : Bit 9 - TDLS support indication enable/disable
+			 : Bit 8 - Interworking indication enable/disable
+			 : Bit 7-1 - Reserved set to 0
+			 : Bit 0 - HotSpot feature enable/disable
+
+	Examples:
+		mlanutl mlan0 hotspotcfg        : Get present remote address mode
+		mlanutl mlan0 hotspotcfg 0x301  : Turn on HotSpot2.0 and enable TDLS support and interworking indication
+		mlanutl mlan0 hotspotcfg 0      : Turn off HotSpot2.0 and disable TDLS support and interworking indication
+
+hscfg
+	This command is used to configure the host sleep parameters.
+
+	Usage:
+		mlanutl mlanX hscfg [condition [[GPIO# [gap]]]] (optional)[type ind_GPIO# [level]] (optional)[type event_force_ignore event_use_ext_gap ext_gap [gpio_wave]]
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap). If more than three parameters, it can set different or multiple features indicating by type(this is optional):
+
+	If type=1, it will set indication gpio and its level. And the parameter format will be (condition, GPIO#,gap and type,ind_GPIO#) or
+	(condition, GPIO#, gap, type, ind_GPIO# and level).
+
+	If type=2, it will set extend hscfg wakup method. And the parameter format will be (condition, GPIO#, gap, type, force_ignore,
+	use_ext_gap, ext_gap [gpio_wave]). gpio_wave parameter is optional and default value is 0(falling edge). Each bit of
+	event_force_ignore and event_use_ext_gap will be defined to one same event, and set one same event(same bit) in those two
+	parameters is not allowed. Set bit(s) in event_force_ignore means the event(s) will be forced ignore in firmware silently.
+	Set bit(s) in event_use_ext_gap mean the event(s) will use extend gap to inform host. Not set means not handle.
+
+	If type=3, it will set hs_wakeup_interval.
+
+        If no parameter provided, get is performed.
+
+	The usages of parameters for "hscfg" are the same as that for "hssetpara" command.
+
+hssetpara
+	This command is used to set host sleep parameters.
+
+	Usage:
+		mlanutl mlanX hssetpara condition [GPIO# [gap]] (optional)[type ind_GPIO# [level]] (optional)[type event_force_ignore event_use_ext_gap ext_gap [gpio_wave]] (optional)[type hs_wakeup_interval]
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap).If more than three parameters, it can set different or multiple features indicating by type and
+        the detailed usage is the same as hscfg above.
+
+	where Condition is:
+		bit 0 = 1   -- broadcast data
+		bit 1 = 1   -- unicast data
+		bit 2 = 1   -- mac event
+		bit 3 = 1   -- multicast data
+		bit 6 = 1  --  Wakeup when mgmt frame received.
+		Bit 31 = 1  --  Don't wakeup when IPV6 packet received.
+
+	The host sleep mode will be canceled if condition is set to -1. The default is 0x7.
+
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+	GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead).
+	The default is 0xff.
+
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff
+	for special setting (host acknowledge required) when GPIO is used to wakeup host.
+	The default is 200.
+
+	The host sleep set except for cancellation will be blocked if host sleep is
+	already activated.
+
+	where ind_GPIO# is the pin number of GPIO used to indicate wakeup source. The level on
+	this GPIO will indicate normal wakeup source or abnormal wakeup source.
+
+	where level is used to set level(0/1) on ind_GPIO# pin for indication normal wakeup source.
+	The opposite level will indicate abnormal wakeup source. The default value is 0.
+
+	where event_force_ignore is a bitmap,each bit represent one wakeup reason event. Set the bit means this
+	wakeup reason should be force ignored in firmware. Reset the bit means do not handle this reason.
+
+	where event_use_ext_gap is a bitmap, each bit represent one wakeup reason event. Set the bit means this
+	wakeup reason should use ext_gap to indicate host. Reset the bit means do not handle this reason.
+
+	where event_force_ignore and event_use_ext_gap have the same wakeup reason event definition of each bit:
+		bit 0  = 1     --Disconnect
+		bit 1  = 1     --GTK/iGTK rekey failure
+		bit 2  = 1     --Eapol
+		other bits     --Reserved
+	They should not set both for one same wakeup reason.
+
+	where ext_gap is the extend gap based on third parameter Gap. Only valid when use_ext_gap is used.
+	The total gap is (Gap + (x+1)*ext_gap). x means the bit number(start from 0) of this reason in use_ext_gap.
+
+	where gpio_wave is used to set GPIO wave level for hscfg extend. 0 means falling edge, 1 means rising edge.
+	This parameter is optional and default value is 0.
+
+	where hs_wakeup_interval is used to set host sleep wakeup interval and the type must set to 3 to indicate
+	this feature. And the value will round to the nearest multiple dtim*beacon_interval in fw. The unit is milliseconds.
+
+	Examples:
+		mlanutl mlan0 hssetpara -1           : Cancel host sleep mode
+		mlanutl mlan0 hssetpara 3            : Broadcast and unicast data
+		                                       Use GPIO and gap set previously
+		mlanutl mlan0 hssetpara 2 3          : Unicast data
+		                                       Use GPIO 3 and gap set previously
+		mlanutl mlan0 hssetpara 2 1 0xa0     : Unicast data
+		                                       Use GPIO 1 and gap 160 ms
+		mlanutl mlan0 hssetpara 2 0xff       : Unicast data
+		                                       Use interface (e.g. SDIO)
+		                                       Use gap set previously
+		mlanutl mlan0 hssetpara 4 3 0xff     : MAC event
+		                                       Use GPIO 3
+		                                       Special host sleep mode
+		mlanutl mlan0 hssetpara 1 0xff 0xff  : Broadcast data
+
+		mlanutl mlan0 hssetpara 2 1 0xa0 1 5 1 : Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=1 to set indication GPIO feature
+                                                       Use GPIO 5 to indicate wakeup source
+                                                       High level on GPIO 5 means this is a normal wakeup
+		mlanutl mlan0 hssetpara 2 1 0xa0 1 5   : Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=1 to set indication GPIO feature
+                                                       Use GPIO 5 to indicate wakeup source
+                                                       Use level set previously.
+
+		mlanutl mlan0 hssetpara 2 1 0xa0 2 0 0x1 10 1: Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=2 to set extend hscfg feature
+                                                       Force_ignore not used
+                                                       Disconnect will use extend gap to indicate host
+                                                       Use gap 170.
+                                                       Rising edge
+		mlanutl mlan0 hssetpara 2 1 0xa0 2 0x1 0 0 0: Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=2 to set extend hscfg feature
+                                                       Falling edge
+                                                       Force ignore Disconnect
+                                                       Extend gap not used
+                                                       Not used.
+                                                       Falling edge
+		mlanutl mlan0 hssetpara 2 1 0xa0 3 400:  Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=3 to set hs_wakeup_interval feature
+                                                       hs_wakeup_interval set to 400ms
+
+	Note: The parameters will be saved in the driver and be used when host suspends.
+              The ind_GPIO# and level parameters only work with specific board and firmware.
+
+mgmtfilter
+        This command is used to set management frame to wake up host when host suspend.
+
+        Usage:
+                mlanutl mlanX mgmtfilter <mgmtfilter.conf>
+
+        where <mgmtfilter.conf>
+                This conf file will set management frame catagory, action and frame mask.
+
+        Examples:
+                mlanutl mlan0 mgmtfilter mgmtfilter.conf
+
+auto_arp
+        This command is used to enable/disable auto arp response in host sleep mode.
+        No argument is used to get.
+
+        where value of n is:
+                0   -- Disable
+                1   -- Enable
+
+        Examples:
+                mlanutl mlan0 auto_arp 0           : Disable auto arp response from FW
+                mlanutl mlan0 auto_arp             : Get auto arp configuration status
+
+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).
+
+htstreamcfg
+	This command is used to set/get HT stream configuration.
+	The setting only takes effect in next association.
+
+	Usage:
+		mlanutl mlanX htstreamcfg [n]
+
+	where <n>
+		0x11: HT stream 1x1 mode
+		0x22: HT stream 2x2 mode
+
+	Examples:
+		mlanutl mlan0 htstreamcfg        : Get current setting
+		mlanutl mlan0 htstreamcfg 0x11   : Set HT stream 1x1 mode
+		mlanutl mlan0 htstreamcfg 0x22   : Set HT stream 2x2 mode
+
+httxbfcap
+	This command is used to set/get the TX beamforming capabilities.
+
+	Usage:
+		mlanutl mlanX httxbfcap [cap]
+
+	where the parameters are,
+		cap: TX beamforming capabilities
+			 Bit 0    : Implicit TX BF receiving capable
+			 Bit 1    : RX staggered sounding capable
+			 Bit 2    : TX staggered sounding capable
+			 Bit 3    : RX NDP capable
+			 Bit 4    : TX NDP capable
+			 Bit 5    : Implicit TX BF capable
+			 Bit 6-7  : Calibration
+			         0: - not supported
+			         1: - STA can respond to a calibration request using
+			              the CSI Report, but cannot initiate calibration
+			         2: - reserved
+			         3: - STA can both initiate and respond to a calibration request
+			 Bit 8    : Explicit CSI TX BF capable
+			 Bit 9    : Explicit non-compressed steering capable
+			 Bit 10   : Explicit compressed steering capable
+			 Bit 11-12: Explicit TX BF CSI feedback
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 13-14: Explicit non-compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 15-16: Explicit compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 17-18: Minimal grouping
+			         0: - no grouping (STA supports groups of 1)
+			         1: - groups of 1, 2
+			         2: - groups of 1, 4
+			         3: - groups of 1, 2, 4
+			 Bit 19-20: CSI number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 21-22: Non-compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 23-24: Compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 25-26: CSI max number of rows beamformer supported
+			         0: - single row of CSI
+			         1: - 2 rows of CSI
+			         2: - 3 rows of CSI
+			         3: - 4 rows of CSI
+			 Bit 27-28: Channel estimation capability
+			         0: - 1 space time stream
+			         1: - 2 space time streams
+			         2: - 3 space time streams
+			         3: - 4 space time streams
+			 Bit 29-31: Reserved
+
+	Examples:
+		mlanutl mlan0 httxbfcap             : Get the current TX BF capabilities
+		mlanutl mlan0 httxbfcap 0x0000001F  : Set the TX BF capabilities of the
+		                                     Implicit TX BF receiving capable,
+		                                     RX staggered sounding capable,
+		                                     TX staggered sounding capable,
+		                                     RX NDP capable and TX NDP capable
+
+httxbfcfg
+	This command is used to configure the TX beamforming options.
+	Note: Any new subcommand should be inserted in the second
+		argument and each argument of the sub command should be
+		separated by semicolon. For global configuration, the
+		arguments should be separated by space.
+
+	Usage:
+		mlanutl mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData/txSounding]"
+
+	where the parameters are,
+		action: TX beamforming action
+			0: Control global parameters for beamforming
+		        1: Performs NDP Sounding for PEER
+		        2: TX BF interval in milliseconds
+		        3: Enable/Disable beamforming/sounding for a particular peer
+		        4: TX BF SNR Threshold for peer
+		        .. <for new subcommand>
+		GlobalData: Global parameter arguments.
+		    It contains beamforming enable, sounding enable, FB type, snr_threshold
+		    sounding interval, Beamformig mode values seperated by space.
+		    Syntax:
+			mlanutl mlanX httxbfcfg <action>;<beamforming enable> <sounding enable> <FB type>
+			                       <snr_threshold>  <sounding interval> <Beamforming mode>
+		tsData: Trigger sounding for PEER specific arguments,
+		        it contains PEER MAC and status
+		interval: TX BF interval in milliseconds
+		txPeerData: Enable/Disable beamforming/sounding for the indicated peer,
+		          it contains PEER MAC, sounding, beamfoming options and FB type;
+		snrData: TX BF SNR Threshold for peer, it contains PEER MAC and SNR
+
+	Examples:
+		mlanutl mlan0 httxbfcfg "0"                          : Get current global configuration parameter
+		mlanutl mlan0 httxbfcfg "2;00:50:43:20:BF:64"        : Get the TX BF periodicity for a given peer
+		mlanutl mlan0 httxbfcfg "3"                          : Get the list of MAC addresses that have
+		                                                      beamforming and/or sounding enabled
+		mlanutl mlan0 httxbfcfg "4"                          : Get the list of PEER MAC, SNR tuples
+		                                                      programmed into the firmware.
+		mlanutl mlan0 httxbfcfg "0;0 0 3 10 500 5"           : Disable beamforming, sounding, set FB type
+		                                                      to 3, snr threshold to 10, sounding interval
+		                                                      to 500 ms and beamforming mode to 5
+		mlanutl mlan0 httxbfcfg "1;00:50:43:20:BF:64"        : Perform NDP Trigger sounding to peer
+		                                                      00:50:43:20:BF:64
+		mlanutl mlan0 httxbfcfg "2;00:50:43:20:BF:64;500"    : Set TX BF periodicity for peer 00:50:43:20:BF:64
+		                                                      to 500 milliseconds
+		mlanutl mlan0 httxbfcfg "3;00:50:43:20:BF:43;1;0;3"  : Enable beamforming, disable sounding and set
+		                                                      FB type to 3 for peer 00:50:43:20:BF:43
+		mlanutl mlan0 httxbfcfg "4;00:50:43:20:BF:24;43"     : Set TX BF SNR threshold to peer
+		                                                      00:50:43:20:BF:24 with SNR 43
+
+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-10: Reserved set to 0
+        Bit 9-8: Rx STBC set to 0x01
+        BIT9 BIT8  Description
+         0    0     No spatial streams
+         0    1     One spatial streams supported
+         1    0     Reserved
+         1    1     Reserved
+		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.
+
+inactivityto
+	This command is used to set/get the inactivity timeout value, which specifies
+	when WLAN device is put to sleep.
+
+	Usage:
+		mlanutl mlanX inactivityto <n> <m> <l> [k]
+
+	where the parameter are:
+		<n>: timeout unit in microseconds.
+		<m>: Inactivity timeout for unicast data.
+		<l>: Inactivity timeout for multicast data.
+		[k]: Inactivity timeout for new Rx traffic after PS notification to AP.
+
+	Examples:
+		mlanutl mlan0 inactivityto           : Get the timeout value
+		mlanutl mlan0 inactivityto 1000 2 3  : Set timeout unit to 1000 us (1 ms),
+		                                      inactivity timeout for unicast data is 2 ms,
+		                                      inactivity timeout for multicast data is 3 ms
+
+ipaddr
+	This command is used to set/get IP address.
+
+	Usage:
+		mlanutl mlanX ipaddr ["<op>;<ipaddr>"]
+
+	where <op>
+		0: Remove the IP address
+		bit 0: Set IP address for broadcast ARP filter, which will be auto enabled
+		       in next host sleep configuration
+		bit 1: Set IP address for auto broadcast ARP response
+
+	Examples:
+		mlanutl mlan0 ipaddr                 : Get current settings
+		mlanutl mlan0 ipaddr "0"             : Remove IP address
+		mlanutl mlan0 ipaddr "1;192.168.0.5" : Set IP address for ARP filter
+		mlanutl mlan0 ipaddr "3;192.168.0.6" : Set IP address for ARP filter
+		                                     : and auto ARP response
+
+linkstats
+	This command is used to get the link statistics from the firmware.
+
+	Usage:
+		mlanutl mlanX linkstats
+
+listeninterval
+	This command is used to set/get listen interval in assoc request.
+
+	Usage:
+		mlanutl mlanX listeninterval [l]
+
+	where the parameter:
+		[l]: Value of listen interval [Default 10]
+
+	Examples:
+		mlanutl mlan0 listeninterval     : Display Listen interval
+		mlanutl mlan0 listeninterval 1   : Set Listen interval to 1.
+
+macctrl
+	This command is used to set/get MAC control.
+	It's recommended to read the current setting first to avoid override issue.
+
+	Usage:
+		mlanutl mlanX macctrl [n]
+
+	where <n>
+		bit 0:  Rx enabled
+		bit 1:  Directed Filter enabled
+		bit 2:  LoopBack enabled
+		bit 3:  WEP enabled
+		bit 4:  EthernetII enabled
+		bit 5:  MultiCast enabled
+		bit 6:  BroadCast enabled
+		bit 7:  Promiscuous enabled
+		bit 8:  All MultiCast enabled
+		bit 9:  RTS/CTS enabled (0: CTS to self)
+		bit 10: Enforce Protection enabled
+		bit 11: Force 11N Protection enabled
+		bit 12: Rx 802.11 Packets enabled
+		bit 13: Ad-hoc g Protection enabled
+		bit 14: Reserved
+		bit 15: WEP Type
+		bit 16: BandWidth Indication in RTS enabled
+		bit 17: Dynamic BandWidth Indication Mode in RTS enabled
+		bit 18-31: Reserved
+
+	Examples:
+		mlanutl mlan0 macctrl           : Get current MAC control
+		mlanutl mlan0 macctrl 0x13      : Set Rx enabled and Directed Filter enabled and EthernetII enabled
+		mlanutl mlan0 macctrl 0x813     : Set Rx enabled and Directed Filter enabled and EthernetII enabled
+		                                  Force 11N Protection enabled
+
+mefcfg
+	This command is used to set MEF settings.
+
+	Usage:
+		mlanutl mlanX mefcfg <mef.conf>
+
+	Where the parameter is:
+		mef.conf : The configuration file specifying the MEF settings.
+
+	Example:
+		mlanutl mlan0 mefcfg config/mef.conf
+
+memrdwr
+	This command is used to read/write the adapter memory.
+
+	Usage:
+		mlanutl mlanX memrdwr <address> [value]
+
+	where the parameters are,
+		<address>:  memory address
+		[value]:    value to be written
+
+	Examples:
+		mlanutl mlan0 memrdwr 0x4cf70    : Read memory address 0x4cf70
+		mlanutl mlan0 memrdwr 0x80000000 0xffffffff
+		                                 : Write 0xffffffff to memory address 0x80000000
+
+miracastcfg
+	This command is used to set/get the miracast configuration.
+
+	Usage:
+	mlanutl mlanX miracastcfg [l] [m] [n]
+
+	where the parameters are,
+		[l]:    miracast mode
+				0: Disable
+				1: Source
+				2: Sink
+		[m]:    scan time per channel, in ms
+		[n]:    gap during two scans, in ms
+
+	Examples:
+		mlanutl mlan0 miracastcfg           : Get miracast configuration
+		mlanutl mlan0 miracastcfg 0         : Disable miracast configuration
+		mlanutl mlan0 miracastcfg 1 20 40   : Set miracast mode as source, with scan time
+	                                          20ms per channel and gap during two scans 40ms
+
+mgmtframectrl
+	This command is used to set/get registered frame type to passthrough.
+
+	Usage:
+		mlanutl mlanX mgmtframectrl [<mask>]
+		mlanutl uapX mgmtframectrl [<mask>]
+
+	Where the parameter is:
+		<mask>  : the bit mask of management frame reception.
+			: Bit 0 - Association Request
+			: Bit 1 - Association Response
+			: Bit 2 - Re-Association Request
+			: Bit 3 - Re-Association Response
+			: Bit 4 - Probe Request
+			: Bit 5 - Probe Response
+			: Bit 8 - Beacon Frames
+
+	Examples:
+		mlanutl mlan0 mgmtframectrl        : Get present mask
+		mlanutl mlan0 mgmtframectrl 0x0020 : Bit 5 is set, Forward probe response frames to application layer
+
+mgmtframetx
+	This command is used to send management frame.
+
+	Usage:
+		mlanutl mlanX mgmtframetx <mgmt_frame.conf>
+
+	Where the parameter is:
+		mgmt_frame.conf : The configuration file contains the management frame.
+
+	Examples:
+		mlanutl mlan0 mgmtframetx config/mgmt_frame.conf
+
+mpactrl
+	This command is used to set/get the Tx, Rx SDIO aggregation parameters.
+	Note: The parameters can be set only in disconnected state.
+
+	Usage:
+		mlanutl mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+
+	where the parameter are:
+		[tx_ena]: Enable/disable (1/0) Tx MP-A
+		[rx_ena]: Enable/disable (1/0) Rx MP-A
+		[tx_size]: Size of Tx MP-A buffer
+		[rx_size]: Size of Rx MP-A buffer
+		[tx_ports]: Max ports (1-16) for Tx MP-A
+		[rx_ports]: Max ports (1-16) for Rx MP-A
+	default values are 1 1 16384 32768 16 16
+	The MP-A may be disabled by default at build time if the MMC driver byte mode patch
+	is not available in kernel.
+
+	Examples:
+		mlanutl mlan0 mpactrl       : Get MP aggregation parameters
+		mlanutl mlan0 mpactrl 0 0
+		                           : Disable MP aggregation for Tx, Rx respectively
+		mlanutl mlan0 mpactrl 1 1 8192 8192 8 8
+		                           : Enable MP aggregation for Tx, Rx
+		                           : Set Tx, Rx buffer size to 8192 bytes
+		                           : Set maximum Tx, Rx ports to 8
+
+offchannel
+	This command is used to set/cancel the offchannel configuration.
+	Note: This command only can be used when cfg80211 is enabled during load time.
+
+	Usage:
+		mlanutl mlanX offchannel [<l> <m> <n>]
+
+	where
+		<l>
+			0 : Cancel the offchannel configuration
+			1 : Set the offchannel configuration
+		<m>
+			The channel to configure
+		<n>
+			The duration for which to configure
+
+	Examples:
+		mlanutl mlan0 offchannel           : Get current offchannel status.
+		mlanutl mlan0 offchannel 0         : Cancel the offchannel configuration.
+		mlanutl mlan0 offchannel 1 3 5     : Configure channel 3 for 5 milliseconds.
+		mlanutl mlan0 offchannel 1 36 5000 : Configure channel 36 for 5000 milliseconds.
+
+otpuserdata
+	This command is used to get the OTP user data.
+
+	Where
+	<l> is <user_data_length>
+	<user_data_length> - This parameter specifies the length of OTP user data to be read
+
+	Examples:
+		mlanutl mlan0 otpuserdata 10         : Get the 10-byte OTP user data
+
+passphrase
+	This command is used to set/get passphrase for WPA-PSK/WPA2-PSK mode.
+
+	Where <l>
+		ASCII string for ssid/passphrase/psk.
+
+	1) "0;<ssid=valid ssid>" - This will get the passphrase, AKMP
+	   for specified ssid, if none specified then it will get all.
+
+	Example:
+		mlanutl mlan0 passphrase "0;ssid=marvell"
+
+	2) "1;<psk=64 byte hexpsk>;<passphrase=1-63 byte passphare>
+	   <ssid=valid ssid>" - Passphrase and psk cannot be provided for the same SSID.
+	   This command takes only one SSID at a time, If ssid= is present 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 ';' or '/' has to be used in an SSID then a '/' should be preceded
+	   to ';' or '/' as a escape.
+
+	Examples:
+		mlanutl mlan0 passphrase "1;ssid=mrvlAP;passphrase=abcdefgd"
+		mlanutl mlan0 passphrase "1;ssid=mrvl AP;psk=<64 bytes hexpsk>"
+
+		If user wants to input the ssid as "mrvl; AP" then command has to be
+		mlanutl mlan0 passphrase "1;ssid=mrvl/; AP;passphrase=abcdefgh"
+
+		If user wants to input the ssid as "//;" then command has to be
+		mlanutl mlan0 passphrase "1;ssid=/////;;passphrase=abcdefgh"
+
+	3) "2;<ssid=valid ssid>" - This will clear the passphrase
+	   for specified ssid, if none specified then it will clear all.
+
+	Examples:
+		mlanutl mlan0 passphrase "2;ssid=marvell"
+		mlanutl mlan0 passphrase "2"     : Clear all profiles and disable embedded supplicant
+
+pb_bypass
+	This command is used to get the By-passed TX packet from upper layer.
+
+	Usage:
+
+	mlanutl mlanX pb_bypass [data_1, data_2, ... data_n]
+
+	where value of data_1, data_2, ... data_n isBypass TX Data
+
+pmfcfg
+	This command is used to set/get management frame protection parameters.
+
+	Usage:
+		mlanutl mlanX pmfcfg <m> <n>
+
+	where
+		<m>: Management Frame Protection Capable (MFPC)
+			1: Management Frame Protection Capable
+			0: Management Frame Protection not Capable
+		<n>: Management Frame Protection Required (MFPR)
+			1: Management Frame Protection Required
+			0: Management Frame Protection Optional
+		Default setting is PMF not capable.
+		m = 0, n = 1 is an invalid combination
+
+        Examples:
+                mlanutl mlan0 pmfcfg            : Get PMF parameters
+                mlanutl mlan0 pmfcfg 1 0        : Set MFPC and make MFPR optional
+
+port_ctrl
+	This command is used to Set/Get Port Control mode. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 port_ctrl 1           : Enable Port Control mode
+		mlanutl mlan0 port_ctrl             : Get Port Control mode status
+
+powercons
+	This command is used to set the local transmit power constraint.
+	Value is in dbm unit. This command is only used for ad-hoc start.
+
+	Usage:
+		mlanutl mlanX powercons [n]
+
+	Examples:
+		mlanutl mlanX powercons          : get the current setting
+		mlanutl mlanX powercons 12       : set local power constraint to 12 dbm
+
+pscfg
+	This command is used to set/get PS configuration parameters.
+
+	Usage:
+		mlanutl mlanX pscfg [k] [d] [l] ...
+
+	Where the parameters:
+		[k]: Keep alive null packet interval (0: Unchanged, -1: Disable, n: Interval in seconds)
+		[d]: DTIM interval (    0: Unchanged,
+		                      1-5: Value,
+		                    65534: DTIM will be ignored, listen interval will be used,
+		                    65533: Closest DTIM to the listen interval period will be used )
+		[l]: Local listen interval (     0: Unchanged,
+		                                -1: Disable,
+		                              1-49: Value in beacon intervals,
+		                             >= 50: Value in TUs )
+		[b]: Beacon miss timeout (0: Unchanged, 1-50: Value in milliseconds, 65535: Disable)
+		[p]: Delay to PS (0-65535: Value in milliseconds, default 1000ms)
+		[m]: PS mode (0: Unchanged, 1: Auto mode, 2: PS-Poll mode, 3: PS Null mode)
+	No change if parameters are not provided.
+
+	Examples:
+		mlanutl mlan0 pscfg              : Get all the current PS configuration settings
+		mlanutl mlan0 pscfg 3 4          : Set PS keep alive null packet interval to 3 seconds
+		                                   and DTIM interval to 4, all the other configurations
+		                                   are unchanged
+		mlanutl mlan0 pscfg 0 0 0 0 50 2 : Set delay to PS to 50 ms and PS mode to PS-Poll mode,
+		                                   keep the others unchanged
+
+bcntimeoutcfg
+	This command is used to set Beacon timeout parameters.
+
+	Usage:
+		mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p]
+
+	Where the parameters:
+		[l]: Beacon miss timeout period Rx window (in ms)
+		[m]: Beacon miss timeout period (unit in beacon interval)
+		[o]: Beacon reacquire timeout period Rx window (unit in beacon interval)
+		[p]: Beacon reacquire timeout period (unit in beacon interval)
+		Please note that it would be better [m]+[p] not exceed 64.
+	Examples:
+		mlanutl mlan0 bcntimeoutcfg 10 30 2 30    : Set beacon timeout configure to
+		                                            Beacon miss timeout period Rx window      : 10 (ms)
+		                                            Beacon miss timeout period                : 30 (Beacon Interval)
+		                                            Beacon reacquire timeout period Rx window : 2  (Beacon Interval)
+		                                            Beacon reacquire timeout period           : 30 (Beacon Interval)
+
+psmode
+	This command is used to set/get the IEEE PS mode configuration.
+
+	Usage:
+		mlanutl mlanX psmode [l]
+
+	where the parameter:
+		[l]
+			0 : Disable IEEE PS mode
+			1 : Enable IEEE PS mode
+			<none>: Get IEEE PS mode
+
+	Examples:
+		mlanutl mlan0 psmode   : Get IEEE PS mode.
+		mlanutl mlan0 psmode 1 : Enable IEEE PS mode.
+
+qconfig
+	Send a WMM AC Queue configuration command to get/set/default params
+
+	Configure or get the parameters of a WMM AC queue. The command takes
+	an optional Queue Id as a last parameter.  Without the queue id, all
+	queues will be acted upon.
+
+	Usage:
+		mlanutl mlanX qconfig def [Queue Id: 0-3]
+		mlanutl mlanX qconfig get [Queue Id: 0-3]
+		mlanutl mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+
+qoscfg
+	This command sets WMM IE QOS info when an argument is given, and gets current WMM
+	IE QOS info when no argument is given.
+
+	Examples:
+		mlanutl mlanX qoscfg 0x0f        : Set WMM IE QOS info to 0x0f
+		mlanutl mlanX qoscfg             : Get WMM IE QOS info
+
+qstatus
+	This command retrieves the current status of the WMM queues. If WMM
+	  is enabled then it displays the information for each AC in a table.
+
+	Usage:
+		mlanutl mlanX qstatus
+
+radioctrl
+	This command is used to turn on/off the radio.
+	Note: The radio can be disabled only in disconnected state.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 radioctrl 1        : Turn the radio on
+		mlanutl mlan0 radioctrl          : Get radio status
+
+rdeeprom
+	This command is used to read the EEPROM contents of the card.
+
+	Usage:
+		mlanutl mlanX rdeeprom <offset> <length>
+
+	where the parameters are,
+		<offset>:   multiples of 4
+		<length>:   4-20, multiples of 4
+
+	Example:
+		mlanutl mlan0 rdeeprom 0 20      : Read 20 bytes of EEPROM data from offset 0
+
+reassoctrl
+	This command is used to turn on/off re-association in driver.
+
+	Usage:
+		mlanutl mlanX reassoctrl [n]
+
+	Where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 reassoctrl         : Get re-association status
+		mlanutl mlan0 reassoctrl 1       : Turn re-association on
+
+regioncode
+	This command is used to set/get the region code in the station.
+	Note: This command should be issued at beginning before band/channel selection
+	and association.
+
+	where value is 'region code' for various regions like
+	USA FCC, Canada IC, Europe ETSI, Japan ...
+	The special code (0xff) is used for Japan to support channel 1-14 in B/G/N mode.
+
+	Examples:
+		mlanutl mlan0 regioncode         : Get region code
+		mlanutl mlan0 regioncode 0x10    : Set region code to USA (0x10)
+	Note : in some case regioncode will be 0 after updated countycode or 80211d
+		i.e. mlanutl mlanX countrycode  (CA, JP, CN, DE, ES AT, BR, RU)
+		or uaputl.exe sys_cfg_80211d state 1 country (CA, JP, CN, DE, ES AT, BR, RU)
+		Please use cfp instead of it.
+
+regrdwr
+	This command is used to read/write the adapter register.
+
+	Usage:
+		mlanutl mlanX regrdwr <type> <offset> [value]
+
+	where the parameters are,
+		<type>:     1:MAC/SOC, 2:BBP, 3:RF, 5:CAU, 6:PSU
+		<offset>:   offset of register
+		[value]:    value to be written
+		Note:
+		BBP reg (type 2) 0xXZZZ:
+		X: 0=BBUD, 8=BBUA.
+		ZZZ: offset (0-0xFFF).
+		RF reg (type 3) 0xXYZZ:
+                 X   = Path ID (0-1)
+           	 Y   = Page Number (0-6) in selected Path
+           	 ZZ  = Register offset in selected path/page
+
+	Examples:
+		mlanutl mlan0 regrdwr 1 0xa060   : Read the MAC register
+		mlanutl mlan0 regrdwr 1 0xa794 0x80000000
+		                                 : Write 0x80000000 to MAC register
+
+rejectaddbareq
+	This command is used to set/get the conditions of rejecting addba request.
+
+	Usage:
+		mlanutl mlanX rejectaddbareq [conditions]
+		mlanutl uapX rejectaddbareq [conditions]
+
+	Where conditions are:
+		bit 0 = 1   -- reject the addba request when host sleep activated
+		others      -- reserved
+
+	Examples:
+		mlanutl mlan0 rejectaddbareq      : Get the reject addba request conditions
+		mlanutl mlan0 rejectaddbareq 0x1  : Reject the addba request
+		                                    when host sleep activated
+		mlanutl uap0 rejectaddbareq 0x1   : Reject the addba request
+		                                    when host sleep activated
+
+scancfg
+	This command is used to set/get scan configuration parameters.
+
+	Usage:
+		mlanutl mlanX scancfg [t] [m] [p] [s] [a] [b] [c] [ext]
+
+	where the parameters:
+		[t]: Scan Type (0: Unchanged, 1: Active, 2: Passive, default Active)
+		[m]: Scan Mode (0: Unchanged, 1: BSS, 2: IBSS, 3: Any, default Any)
+		[p]: Scan Probes (0: Unchanged, 1-4: Number of probes per channel, default 4)
+		[s]: Specific Scan Time (0: Unchanged, n: Value in ms, default 110 ms, max 500 ms)
+		[a]: Active Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 500 ms)
+		[b]: Passive Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 2000 ms)
+		[c]: Passive to Active Scan (0: Unchanged, 1: Enable, 2: Disable, default Enable)
+		[ext]: Extended scan (0: Unchanged, 1: Legacy scan, 2: Extended scan)
+	No change if the parameter is 0 or the parameter is not provided.
+
+	Examples:
+		mlanutl mlan0 scancfg            : Get all the current scan configuration settings
+		mlanutl mlan0 scancfg 1 3        : Set scan type to active and scan mode to any,
+		                                   all the other scan configurations are unchanged
+		mlanutl mlan0 scancfg 0 1 2 200  : Set scan mode to BSS, number of probes to 2 and
+		                                   specific scan time to 200 ms, all the other scan
+		                                   configurations are unchanged
+		mlanutl mlan0 scancfg 0 0 0 0 0 0 1  : Set Passive to Active Scan to enable, all the
+ 		                                       other scan configurations are unchanged
+		mlanutl mlan0 scancfg 2 0 0 0 0 0 2  : Set scan type to passive, Passive to Active
+  		                                       Scan to disable, all the other scan configurations
+  		                                       are unchanged
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanutl mlanX sdcmd52rw <function number> <register address> [value]
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+	Examples:
+		mlanutl mlan0 sdcmd52rw 1 3      : Read SDIO function 1 register 3
+		mlanutl mlan0 sdcmd52rw 1 1 0x3f : Write 0x3f to SDIO function 1 register 1
+
+sdcmd53rw
+	This command is used to issue a CMD53 read/write data in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanutl mlanX sdcmd53rw <func> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+
+	where the parameters are,
+		<func>:     function number (0/1/2/..)
+		<address>:  data address
+		<mode>:     byte mode/block mode (0/1)
+		<blksize>:  block size (32/64/../512, NA for byte mode)
+		<blknum>:   block number or byte number
+		<data1> ... <dataN>:  data for write
+
+	Note: The total data length is block size * block number for block mode
+	or byte number for byte mode. The max data length is 2000-byte.
+	For write the data pattern will be duplicated to data buffer.
+
+	Examples:
+		mlanutl mlan0 sdcmd53rw 0 0x8000 1 0x40 2
+		mlanutl mlan0 sdcmd53rw 1 0x10000 0 1 5 0x0a 0x0b 0x0c 0x0d 0x0e
+
+sdioclock
+	Turn On(1) or Off(0) the SDIO clock.
+
+	Usage:
+		mlanutl mlanX sdioclock 1 (on)
+		mlanutl mlanX sdioclock 0 (off)
+		mlanutl mlanX sdioclock (get the current clock state)
+
+setuserscan
+	Initiate a customized scan and retrieve the results
+
+	Usage:
+		mlanutl mlanX setuserscan [ARGS]
+
+	Where [ARGS]:
+	  ssid="[SSID]"            specify a SSID filter for the scan
+	  chan=[chan#][band][mode] where band is [a,b,g,n] and mode is
+	                           blank for unchange, or 'c' for active or 'p' for passive
+	  bssid=xx:xx:xx:xx:xx:xx  specify a BSSID filter for the scan
+	  wc="[WILDCARD SSID]"     specify a UNIX pattern matching filter (using *
+	                           and ?) for SSIDs found in a broadcast probe
+	  keep=[0 or 1]            keep the previous scan results (1), discard (0)
+	  dur=[scan time]          time to scan for each channel in milliseconds
+	  gap=[gap time]           Time gap between two scans in milliseconds
+	  probes=[#]               number of probe requests to send on each chan
+	                           for each broadcast probe required and each SSID
+	                           specific probe required (1-4)
+	  bss_type=[1,2,3]         BSS type: 1 (Infra), 2(Adhoc), 3(Any)
+          sort_by_ch               Sort by channel number in ascending order.
+                                   Default mode: Sort by Signal Strength in descending order.
+
+	Any combination of the above arguments can be supplied on the command line.
+	If the chan token is absent, a full channel scan will be completed by driver.
+	If the dur or probes tokens are absent, the driver default setting will be
+	used. The bssid and ssid fields, if blank, will produce an unfiltered scan.
+	It's allowed to input multiple ssid/wc entries, the max entry number is 10.
+	The type field will default to 3 (Any) and the keep field will default to 0
+	(Discard).
+
+	Examples:
+	1) Perform an active scan on channels 1, 6, and 11 in the 'g' band:
+		setuserscan chan=1g,6g,11g
+
+	2) Perform a passive scan on channel 11 for 20 ms:
+		setuserscan chan=11gp dur=20
+
+	3) Perform an active scan on channels 1, 6, and 11; and a passive scan on
+	   channel 36 in the 'a' band:
+		setuserscan chan=1g,6g,11g,36ap
+
+	4) Perform an active scan on channel 6 and 36 for specific SSID:
+		setuserscan chan=6g,36a ssid=TestAP1 ssid=TestAP2
+
+	5) Scan all available channels (B/G/N, A bands) for a specific BSSID, keep
+	   the current scan table intact, update existing or append new scan data:
+		setuserscan bssid=00:50:43:20:12:82 keep=1
+
+	6) Scan channel 6, for all infrastructure networks, sending two probe
+	   requests.  Keep the previous scan table intact. Update any duplicate
+	   BSSID/SSID matches with the new scan data:
+		setuserscan chan=6g bss_type=1 probes=2 keep=1
+
+	7) Scan channel 1 and 6, for all networks matching the Mrvl*AP
+	   or AP*Mrvl? patterns and for MrvlTst SSID.  Generate 3 broadcast
+	   probes for the patterns and 3 SSID specific probes for MrvlTst on
+	   both channel 1 and channel 6.
+		setuserscan chan=1g,6g probes=3 wc="Mrvl*AP" wc="AP*Mrvl?" ssid="MrvlTst"
+
+	8) Scan all the channels for specified band.
+		setuserscan chan=0g
+
+	9) Scan channel 1 and 6, send 3 probe requests, scan each channel for 40 ms
+	   with time gap of 50ms between 2 scans
+		setuserscan chan=1g,6g probes=3 dur=40 gap=50
+
+	All entries in the scan table (not just the new scan data when keep=1)
+	will be displayed upon completion by use of the getscantable ioctl.
+cancelscan
+	This command is used to cancel scan
+	Usage:
+		mlanutl mlanX cancelscan
+sleepparams
+	This command is used to set the sleepclock configurations
+
+	Usage:
+		mlanutl mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+
+	where:
+		p1 is Sleep clock error in ppm (0-65535)
+		p2 is Wakeup offset in usec (0-65535)
+		p3 is Clock stabilization time in usec (0-65535)
+		p4 is Control periodic calibration (0-2)
+		p5 is Control the use of external sleep clock (0-2)
+		p6 is reserved for debug (0-65535)
+
+	Examples:
+		mlanutl mlan0 sleepparams                      : Get current sleepclock configuration
+		mlanutl mlan0 sleepparams 10 1000 2000 1 0 128 : Set sleepclock configuration
+
+sleeppd
+	This command is used to configure the sleep period of the WLAN device.
+
+	Usage:
+		mlanutl mlanX sleeppd [<period>]
+
+	Where the parameter is:
+		period: sleep period in milliseconds. Range 10~60. 0 for disable.
+
+	Examples:
+		mlanutl mlan0 sleeppd            : Get sleep period configuration
+		mlanutl mlan0 sleeppd 10         : Set sleep period to 10 ms
+
+sysclock
+	This command is used to set/get system clocks in MHz.
+	The current system clock, configurable system clocks and all of the
+	supported system clocks will be returned if no parameter provided.
+
+	Examples:
+		mlanutl mlan0 sysclock           : Get system clocks
+		80 80 128 128 128 5 11 16 20 22 32 40 44 64 80 106 128 160 ...
+		(The current system clock is 80 MHz.
+		 The configurable system clocks of non-security, security, non-security
+		 A-MPDU and security A-MPDU are 80 MHz, 128 MHz, 128 MHz and 128 MHz.
+		 The supported system clocks are 5 MHz, 11 MHz, ..., 160 MHz, 182 MHz,
+		 213 MHz, 256 MHz, 320 Mhz, 366 MHz , ... . the Max system clocks is different
+		 for different chips, you could use this command to get the supported system clock)
+
+		mlanutl mlanX sysclock 80        : Set system clock in non-security mode
+		                                  to 80 MHz, no change for others
+		mlanutl mlanX sysclock 0 0 128   : Set system clock in non-security A-MPDU
+		                                  mode to 128 MHz, no changes for others
+
+host_tdls_config
+	This command is used to support channel switch and uapsd for host based tdls
+
+	Usage:
+		mlanutl mlanX host_tdls_config <host_tdls.conf>
+
+
+	Where the parameter is:
+		host_tdls.conf: The configuration file specifying to enable/disable uapsd/cs and related parameters.
+
+	Examples:
+		mlanutl mlan0 host_tdls_config config/host_tdls.conf
+			: enable or disable uapsd/cs, config the channel related ie, based on the configuration file.
+tdls_channel_switch
+	This command is used to send TDLS channel switch request.
+
+	Usage:
+		mlanutl mlanX tdls_channel_switch <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending TDLS channel switch command.
+
+	Examples:
+		mlanutl mlan0 tdls_channel_switch config/tdls.conf
+			: Send TDLS channel switch command, based on the configuration file.
+
+tdls_config
+	This command is used to enable/disable TDLS on device.
+
+	Usage:
+		mlanutl mlanX tdls_config <0/1>
+
+	Where the parameter is:
+		0: Enable TDLS.
+		1: Disable TDLS.
+
+	Examples:
+		mlanutl mlan0 tdls_config 0      : Disable TDLS
+		mlanutl mlan0 tdls_config 1      : Enable TDLS
+
+tdls_cs_params
+	This command is used to set TDLS channel switch params
+
+	Usage:
+		mlanutl mlanX tdls_cs_params <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file specifying the TDLS channel switch params.
+
+	Examples:
+		mlanutl mlan0 tdls_cs_params config/tdls.conf
+			: Set TDLS channel switch params, based on the configuration file.
+
+tdls_debug
+	This command is used for FW debug functionality and tests.
+
+tdls_disable_cs
+	This command is used to disable TDLS channel switch
+
+	Usage:
+		mlanutl mlanX tdls_disable_cs <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file to disable TDLS channel switch.
+
+	Examples:
+		mlanutl mlan0 tdls_disable_cs config/tdls.conf
+			: Disable TDLS channel switch, based on the configuration file.
+
+tdls_discovery
+	This command is used to request TDLS discovery.
+
+	Usage:
+		mlanutl mlanX tdls_discovery <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file to request TDLS discovery.
+
+	Examples:
+		mlanutl mlan0 tdls_discovery config/tdls.conf
+			: Request TDLS discovery based on the configuration file.
+
+tdls_link_status [peer_mac_address]
+	This command is used to get link information about TDLS links or
+    a TDLS link correponding to peer mac address.
+
+	Usage:
+		mlanutl mlanX tdls_link_status <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file to send TDLS command to get current link status.
+
+	Examples:
+		mlanutl mlan0 tdls_link_status config/tdls.conf
+			: Send TDLS command to get current link status based on the configuration file.
+
+tdls_powermode
+	This command is used to send TDLS powermode request.
+
+	Usage:
+		mlanutl mlanX tdls_powermode <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending TDLS powermode command.
+
+	Examples:
+		mlanutl mlan0 tdls_powermode config/tdls.conf
+			: Send TDLS powermode (either 0:Active, 1:PowerSave) command, based on the configuration file.
+
+tdls_setinfo
+	This command is used for setting the capabilities of the TDLS station.
+
+	Usage:
+		mlanutl mlanX tdls_setinfo <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file specifying the capabilities of the TDLS station.
+
+	Examples:
+		mlanutl mlan0 tdls_setinfo config/tdls.conf
+			: Set capabilities of the TDLS station, based on the configuration file.
+
+tdls_setup
+	This command is used to send TDLS setup request.
+
+	Usage:
+		mlanutl mlanX tdls_setup <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending TDLS setup request.
+
+	Examples:
+		mlanutl mlan0 tdls_setup config/tdls.conf
+			: Send TDLS setup request, based on the configuration file.
+
+tdls_stop_channel_switch
+	This command is used to send stop TDLS channel switch request.
+
+	Usage:
+		mlanutl mlanX tdls_stop_channel_switch <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending stop TDLS channel switch command.
+
+	Examples:
+		mlanutl mlan0 tdls_stop_channel_switch config/tdls.conf
+			: Send stop TDLS channel switch command, based on the configuration file.
+
+tdls_teardown
+	This command is used to send TDLS teardown request.
+
+	Usage:
+		mlanutl mlanX tdls_teardown <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for requesting teardown of TDLS link.
+
+	Examples:
+		mlanutl mlan0 tdls_teardown config/tdls.conf
+			: Request teardown of TDLS link, based on the configuration file.
+
+thermal
+	This command is used to get the current thermal reading.
+
+	Examples:
+		mlanutl mlan0 thermal            : Get thermal reading
+
+ts_status
+	This command queries the FW for the status of TSIDs 0 through 7
+	  configured via call admission control and displays the results in a
+	  table.
+
+	Usage:
+		mlanutl mlanX ts_status
+
+tsf
+	Get the TSF timer value for the station. Station maintains a TSF timer with
+	modulus 2^64 counting in increments of microseconds.
+
+	Usage:
+		mlanutl mlanX tsf
+
+txaggrctrl
+	This command is used to enable/disable TX AMPDU on infra link when TDLS link is established
+
+	Usage:
+		mlanutl mlanX txaggrctrl [m]
+
+	Where:
+		[m]: 1 to enable TX AMPDU on infra link; 0 to disable TX AMPDU on infra link
+
+	Examples:
+		mlanutl mlan0 txaggrctrl	: Get current TX AMPDU status on infra link
+		mlanutl mlan0 txaggrctrl 0	: Disable TX AMPDU on infra link
+		mlanutl mlan0 txaggrctrl 1	: Enable TX AMPDU on infra link
+
+	Note:
+		The set command only works when TDLS link is established.
+
+txbufcfg
+	This command can be used to get current buffer size.
+
+	eg:
+	mlanutl mlanX txbufcfg 	  - This will display the current buffer size.
+
+	Note:- The actual tx buf size will depends on AP's capability and max transmit buffer size.
+
+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.
+
+	Where
+	[l] is <format>
+	<format> - This parameter specifies the data rate format used in this command
+		0:    LG
+		1:    HT
+		2:    VHT
+		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
+	[n] is <nss>
+	<nss> - This parameter specifies the NSS. It is valid only for VHT
+	If <format> is 2 (VHT),
+		1	NSS1
+		2	NSS2
+
+	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 0xff     : Disable fixed rate and uses auto rate
+
+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.
+
+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.
+
+opermodecfg
+	This command is used to set and get 11ac Operating Mode Notification configuration.
+
+	where <m> is <bw>
+	<bw> - This is the channel width setting for the opermodecfg
+		1: 20MHz
+		2: 40MHz
+		3: 80MHz
+		4: 160MHz or 80+80MHz
+
+	where <n> is <nss>
+	<nss> - This parameter specifies the nss that the STA can receive.
+		1: NSS1
+		2: NSS2
+		3: NSS3
+		4: NSS4
+		5: NSS5
+		6: NSS6
+		7: NSS7
+		8: NSS8
+
+wakeupreason
+	This command is used to get the host sleep wakeup reason.
+
+	Usage:
+		mlanutl mlanX wakeupreason
+		mlanutl uapX wakeupreason
+	Examples:
+		mlanutl mlan0 wakeupreason        : Get the host sleep wakeup reason
+		mlanutl uap0 wakeupreason         : Get the host sleep wakeup reason
+		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
+		8:  Control frame matched
+		9:  Management frame matched
+		Others: reserved. (0)
+
+warmreset
+	This command is used for warm reset of the interface.
+
+	Usage:
+		mlanutl mlanX warmreset
+
+wpssession
+	This command is used to control wps session. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 wpssession 1           : Enable wpssession
+		mlanutl mlan0 wpssession             : Get wpssession status
+
+wmmcfg
+	This command is used to control WMM. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 wmmcfg 1           : Enable WMM
+		mlanutl mlan0 wmmcfg             : Get WMM status
+
+wmmparamcfg
+	This command is used to configure WMM paramameters.
+
+	Usage:
+		mlanutl mlanX wmmparamcfg [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+                                          [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+                                          [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+                                          [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+
+	The supported option are:
+           AC_BE: 0
+           AC_BK: 1
+           AC_VI: 2
+           AC_V0: 3
+           AIFSN: AIFSN value
+           ECW_MAX: ECW max
+           ECW_MIN: ECW min
+           TX_OP: TXOP Limit
+           empty - Get current WMM parameters
+
+        Example:
+        mlanutl mlanX wmmparamcfg 0 3 10 4 0
+           Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        mlanutl mlanX wmmparamcfg 1 7 10 4 0
+           Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        mlanutl mlanX wmmparamcfg 2 2 4 3 94
+           Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+
+        mlanutl mlanX wmmparamcfg 3 2 3 2 47
+           Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        mlanutl mlanX wmmparamcfg
+            Get current WMM parameters
+
+        mlanutl mlanX wmmparamcfg 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+wwscfg
+	This command is used to set/get the WWS (World Wide Safe) mode.
+
+	where value of m is:
+		0       -- Disable WWS mode (default)
+		1       -- Enable WWS mode
+
+	Examples:
+		mlanutl mlan0 wwscfg             : Get WWS mode
+		mlanutl mlan0 wwscfg 1           : Enable WWS mode
+		mlanutl mlan0 wwscfg 0           : Disable WWS mode
+
+mc_cfg
+	This command is used to set/get the channel time.
+
+	Usage:
+		mlanutl mlanX mc_cfg [n]
+
+	where <n> :  Channel time in microseconds.
+
+	Examples:
+		mlanutl mlanX mc_cfg			: Get Channel time and buffer weight.
+		mlanutl mlanX mc_cfg 10000		: Set Channel time to 10000us.
+
+mc_policy
+        This command is used to set/get the multi-channel policy.
+	Note: This is a device specific command. Hence, setting on one interface is
+		reflected on all other interfaces.
+
+        Usage:
+                mlanutl mlanX mc_policy [n]
+
+        where <n> :  Multi-channel policy
+
+        Examples:
+                mlanutl mlanX mc_policy			: Get multi-channel policy setting.
+                mlanutl mlanX mc_policy 1		: Set multi-channel policy to 1.
+                mlanutl mlanX mc_policy 0		: Disable multi-channel policy
+
+mc_cfg_ext
+    This command is used to set/get the drcs parameters.
+
+    Usage:
+        mlanutl mlanX mc_cfg_ext [c] [s] [u] [m] <a> <b> <d> <e>
+
+    where:
+    channel index0:
+        [c] :  chantime(in TU)
+        [s] :  switchtime(in TU)
+        [u] :  undozetime(in TU)
+        [m] :  mode :0x0 --- PM1(default)
+                     0x1 --- Null2Self
+    channel index1:
+        <a> :  chantime(in TU)
+        <b> :  switchtime(in TU)
+        <d> :  undozetime(in TU)
+        <e> :  mode :0x0 --- PM1(default)
+                     0x1 --- Null2Self
+    Note:
+        channel index0: the first channel
+        channel index1: the second channel
+        undozetime should be less than other channel's switchtime
+        If want to set two channels the same parameters, just ignore the last four parameters and
+        use [c] [s] [u] [m] to set.
+    Examples:
+        mlanutl mlanX mc_cfg_ext                        : Get the drcs parameters for two channels.
+        mlanutl mlanX mc_cfg_ext 15 10 5 0              : Set two channels:channeltime 15TU, switchtime 10TU, undozetime 5TU, mode PM1
+        mlanutl mlanX mc_cfg_ext 15 10 5 0 25 15 9 0    : Set channel index0: channeltime 17TU, switchtime 10TU, undozetime 5TU, mode PM1;
+                                                        set channel index1: channeltime 25TU, switchtime 15TU, undozetime 9TU, mode PM1.
+
+cfg_noa
+	This is used to get/set P2P NoA (Notice of Absence) parameters only for P2P GO.
+
+	Usage:
+		mlanutl p2pX cfg_noa [h] [i] [j] [k] [l]
+
+	where:
+		[h] : noa_enable : 1/0 Set to 1 to enable NoA, 0 to disable NoA.
+		[i] : index      : 0 - 255 Identifies an instance of NoA timing.
+		[j] : count      : 1 - 255 Indicates the number of absence intervals.
+				   255 means a continuous schedule.
+		[k] : duration   : Indicates the maximum duration in units of microseconds
+				   that P2P GO can remain absent following the start of
+				   a NoA interval.
+		[l] : interval   : Indicates the length of the NoA interval in units of
+				   microseconds.
+
+        Examples:
+                mlanutl p2pX cfg_noa						: Get noa configuration.
+                mlanutl p2pX cfg_noa 1 1 255 50 100			: Set noa configuration.
+
+cfg_opp_ps
+	This is used to get/set P2P OPP-PS parameters only for P2P GO.
+
+	Usage:
+		mlanutl p2pX cfg_opp_ps [m] [n]
+
+	where:
+		[m] : ps_enable  : 1/0 Set to 1 to indicate P2P GO is using opportunistic
+				   power save. Set to 0 if opportunistic power save is disabled.
+		[n] : ct_window  : A period of time in TU after a TBTT during which P2P GO
+				   is present. 0 indicates that there shall be no
+				   CTWindow (Client Traffic Window).
+
+        Examples:
+                mlanutl p2pX cfg_opp_ps					: Get noa configuration.
+                mlanutl p2pX cfg_opp_ps 1 7				: Set noa configuration.
+
+rxpktcoal_cfg
+	This is used to get/set RX packet coalescing paramters
+	Usage:
+		mlanutl mlanX rxpktcoal_cfg [m] [n]
+
+	where:
+        [m]: pkt_threshold: count after which packets would be sent to host. Valid values 1-7
+        [n]: delay: timeout in ms after which packets would be sent to host. Valid values 1-4
+        Coalescing is disabled if both or either of packet_thershold and delay is zero
+
+        RX packet coalescing parameters can be changed only when device is in
+        idle state i.e. all interfaces are disconnected.
+
+robustcoex
+    This command is used to set robust coex.
+
+    Usage :
+            mlanutl <interface> robustcoex <gpiocfg> [Enable/Disable] [gpionum] [gpiopolarity]
+            Enable/Disable : 0 -- Disable ; 1 -- Enable
+            gpionum : Number of gpio
+            gpiopolarity : polarity of gpio
+
+    Example :
+            mlanutl mlan0 robustcoex gpiocfg 1 4 1 : Enable robustcoex gpio, set gpionum to 4 and gpiopolarity to 1
+            mlanutl mlan0 robustcoex gpiocfg 0     : Disable robustcoex gpio
+
+ctrldeauth
+    This command is used to set/get firmware ctrldeauth setting
+    Usage :
+            mlanutl uapX ctrldeauth <n>
+
+    Where value of n is :
+            0 -- Firmware will use default behavior
+            1 -- Firmware will not send deauth packet when uap move to another channel.
+
+    Example :
+            mlanutl uap0 ctrldeauth   : Get current setting
+            mlanutl uap0 ctrldeauth   : Firmware will not send deauth packet when uap move to different channel.
+
+bootsleep
+    This command is used to set and get boot sleep configure.
+
+    Usage :
+            mlanutl mlanX/uapX bootsleep <enable>
+            <enable> :  enable boot sleep
+                     :  0 - disable boot sleep
+                     :  1 - enable boot sleep
+
+    Example :
+            mlanutl mlan0/uap0 bootsleep 1       : Enable boot sleep
+            mlanutl mlan0/uap0 bootsleep         : Get boot sleep configure
+
+
+===============================================================================
diff --git a/wlan_sd8987/README_OPENWRT b/wlan_sd8987/README_OPENWRT
new file mode 100644
index 0000000..90a6722
--- /dev/null
+++ b/wlan_sd8987/README_OPENWRT
@@ -0,0 +1,356 @@
+=================================================================================
+        U S E R  M A N U A L  F O R  OpenWrt
+
+This section describes detailed steps to add Marvell Wireless NIC (sdio/usb/pcie)
+driver to OpenWrt build system.
+
+Add marvell driver (sdio/usb/pcie) to OpenWrt build system.
+
+1. Go to the openwrt source code folder
+2. make menuconfig
+	choose x86 platform
+	other general openwrt configurations please refer to:
+	https://wiki.openwrt.org/doc/howto/build
+3. After make menuconfig
+	make sure that following configurations are set in .config
+	CONFIG_PACKAGE_hostapd=y
+	CONFIG_PACKAGE_hostapd-common=y
+	CONFIG_PACKAGE_kmod-cfg80211=y
+4. Go to the openwrt source code folder and Compile openwrt BSP
+	make V=s [-j[number]]
+5. After the first time compiling, openwrt/dl folder will be created
+   , related packages will be downloaded during compiling, so you need
+   network access as long as you need to compile openwrt BSP.
+6. Go to the openwrt source code folder: openwrt/dl/
+7. Find compat-wireless-xxxx-xx-xx.tar.bz2, and uncompress the package
+8. Go to compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/
+9. Modify compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/Kconfig
+
+	source "drivers/net/wireless/marvell/libertas/Kconfig"
+	source "drivers/net/wireless/marvell/libertas_tf/Kconfig"
+	source "drivers/net/wireless/marvell/mwifiex/Kconfig"
+	+source "drivers/net/wireless/marvell/mrvl-pcie/Kconfig"
+	+source "drivers/net/wireless/marvell/mrvl-sd8xxx/Kconfig"
+	+source "drivers/net/wireless/marvell/mrvl-usb/Kconfig"
+
+10. Modify compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/Makefile
+
+	obj-$(CPTCFG_LIBERTAS_THINFIRM)	+= libertas_tf/
+	obj-$(CPTCFG_MWIFIEX)	+= mwifiex/
+	+obj-$(CPTCFG_MRVL_PCIE)  += mrvl-pcie/
+	+obj-$(CPTCFG_MRVL_SD8XXX) += mrvl-sd8xxx/
+	+obj-$(CPTCFG_MRVL_USB) += mrvl-usb/
+
+11. Go to compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/
+12. mkdir (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)
+13. copy (pcie/sdio/usb)/wlan_src/* to (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)
+14. Go to mrvl-pcie/mrvl-sd8xxx/mrvl-usb
+15. Add new Kconfig:
+	mrvl-pcie/Kconfig
+
+	+config MRVL_PCIE
+	+	tristate "Marvell Wireless Driver for PCIE 8997"
+	+	depends on m
+	+	depends on PCI
+	+	depends on CFG80211
+	+	depends on WIRELESS_EXT
+	+	---help---
+	+	  This adds support for wireless adapters based on Marvell
+	+	  pcie 8997 chipsets with PCIe interface.
+	+
+	+	  If you choose to build it as a module, it will be called
+	+	  pcie8xxx.
+
+	mrvl-sd8xxx/Kconfig
+
+	+config MRVL_SD8XXX
+	+	tristate "Marvell sdio 802.11n/802.11ac Wireless cards"
+	+	depends on m
+	+	depends on MMC
+	+	depends on CFG80211
+	+	depends on WIRELESS_EXT
+	+	---help---
+	+	  A driver for Marvell sdio 802.11n/802.11ac Wireless cards.
+
+	mrvl-usb/Kconfig
+
+	+config MRVL_USB
+	+	tristate "Marvell sdio 802.11n/802.11ac Wireless cards"
+	+	depends on m
+	+	depends on USB
+	+	depends on CFG80211
+	+	depends on WIRELESS_EXT
+	+	---help---
+	+	A driver for Marvell sdio 802.11n/802.11ac Wireless cards.
+
+16. Open moal_main.h under (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlinux/
+
+	find #define COMPAT_VERSION_CODE KERNEL_VERSION_CODE(x, x, x)
+	modify (x, x, x) to the kernel version code of backports/compat-wireless package
+
+	backported kernel version code could be found in
+	compat-wireless-xxxx-xx-xx/version as following
+
+	'BACKPORTED_KERNEL_VERSION="v4.4-rc5-1913-gc8fdf68"'
+	v4.4 means KERNEL_VERSION(4, 4, 0)
+
+17. Modify (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/Makefile
+
+	# OpenWrt support
+	-CONFIG_OPENWRT_SUPPORT=n
+	+CONFIG_OPENWRT_SUPPORT=y
+
+	...
+
+	#############################################################################
+	# Select Platform Tools
+	#############################################################################
+
+	MODEXT = ko
+	-ccflags-y += -I$(M)/mlan
+	+ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan
+	ccflags-y += -DLINUX
+
+
+	ifeq ($(CONFIG_EMBEDDED_SUPP_AUTH), y)
+	-ccflags-y += -I$(M)/mlan/esa
+	-ccflags-y += -I$(M)/mlan/esa/common
+	+ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan/esa
+	+ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan/esa/common
+	endif
+
+18. compress compat-wireless-xxxx-xx-xx to its original .tar.bz2 format
+19. Go to the openwrt source code folder: openwrt/package/kernel/mac80211/
+20. Modify openwrt/package/kernel/mac80211/Makefile.
+
+	PKG_DRIVERS = \
+		adm8211 \
+		ath ath5k ath9k ath9k-common ath9k-htc ath10k \
+		b43 b43legacy \
+		carl9170 \
+		hermes hermes-pci hermes-pcmcia hermes-plx\
+		iwl-legacy iwl3945 iwl4965 iwlwifi \
+		lib80211 \
+		libipw ipw2100 ipw2200 \
+		libertas-sdio libertas-usb libertas-spi \
+		mac80211-hwsim \
+		mt7601u \
+		mwl8k mwifiex-pcie \
+		+mrvl-pcie \
+		+mrvl-sd8xxx \
+		+mrvl-usb \
+		p54-common p54-pci p54-spi p54-usb \
+		rt2x00-lib rt2x00-pci rt2x00-usb \
+		rt2400-pci rt2500-pci rt2500-usb \
+
+	...
+
+	+define KernelPackage/mrvl-pcie
+	+  $(call KernelPackage/mac80211/Default)
+	+  TITLE:=Marvell pcie wireless driver
+	+  URL:=http://wireless.kernel.org/en/users/Drivers/mwifiex
+	+  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT
+	+  FILES:= \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/mlan.ko \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/pcie8xxx.ko
+	+  AUTOLOAD:=$(call AutoProbe,mrvl-pcie)
+	+endef
+
+	+define KernelPackage/mrvl-pcie/description
+	+ Kernel modules for Marvell pcie 802.11n/802.11ac PCIe Wireless cards
+	+endef
+
+	+define KernelPackage/mrvl-sd8xxx
+	+  $(call KernelPackage/mac80211/Default)
+	+  DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT
+	+  TITLE:=Marvell sdio Wireless Driver
+	+  FILES:= \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/mlan.ko \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/sd8xxx.ko
+	+  AUTOLOAD:=$(call AutoProbe, mrvl-sd8xxx)
+	+endef
+
+	+define KernelPackage/mrvl-sd8xxx/description
+	+ Kernel modules for Marvell sdio 802.11n/802.11ac Wireless cards
+	+endef
+
+	+define KernelPackage/mrvl-usb
+	+  $(call KernelPackage/mac80211/Default)
+	+  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
+	+  TITLE:=Marvell usb Wireless Driver
+	+  FILES:= \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/mlan.ko \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/usb8xxx.ko
+	+  AUTOLOAD:=$(call AutoProbe, mrvl-usb)
+	+endef
+
+	+define KernelPackage/mrvl-usb/description
+	+ Kernel modules for Marvell usb 802.11n/802.11ac Wireless cards
+	+endef
+
+	...
+
+	config-$(call config_package,mwl8k) += MWL8K
+	config-$(call config_package,mwifiex-pcie) += MWIFIEX MWIFIEX_PCIE
+	+config-$(call config_package,mrvl-pcie) += MRVL_PCIE
+	+config-$(call config_package,mrvl-sd8xxx) += MRVL_SD8XXX
+	+config-$(call config_package,mrvl-usb) += MRVL_USB
+	config-$(call config_package,rtl8180) += RTL8180
+	config-$(call config_package,rtl8187) += RTL8187
+
+	...
+
+	$(eval $(call KernelPackage,mwl8k))
+	$(eval $(call KernelPackage,mwifiex-pcie))
+	+$(eval $(call KernelPackage,mrvl-pcie))
+	+$(eval $(call KernelPackage,mrvl-sd8xxx))
+	+$(eval $(call KernelPackage,mrvl-usb))
+	$(eval $(call KernelPackage,p54-common))
+
+OpenWrt configuration
+21. Go to OpenWrt srouce code folder
+22. Make menuconfig
+
+   select one of the newly added marvell driver
+	│-> Kernel modules
+	│	-> Wireless Drivers
+	|		->mrvl-pcie
+	|		->mrvl-sd8xxx
+	|		->mrvl-usb
+
+23. Other general configurations, please refer to the https://wiki.openwrt.org/doc/howto/build
+24. after menucofig make soure that following configurations are seletect
+
+	CONFIG_PACKAGE_hostapd=y
+	CONFIG_PACKAGE_hostapd-common=y
+	CONFIG_PACKAGE_kmod-cfg80211=y
+
+	Go to openwrt folder and re-build openwrt BSP
+	make V=s [-j[number]]
+
+	After openwrt BSP is successfully build, kernel modules could be found
+	both in the build folder and the running OS once openwrt is boot up.
+	kernel modules will be written to u-disk while openwrt img is burned to u-disk.
+
+	kernel modules in openwrt build dir:
+	openwrt/build_dir/target-x86_64_uClibc-0.9.33.2/linux-x86_64/compat-wireless-2016-01-10/
+	ipkg-x86_64/kmod-mrvl-(usb/sd8xxx/pcie)/lib/modules/3.18.45/
+
+	kernel modules in openwrt running OS:
+	/lib/modules/xx.xx.xx/
+
+25. To support SDIO card in OpenWrt x86 platforma
+	Add following kernel configurations for OpenWrt
+	Go to OpenWrt source code foler
+
+	make kernel_menuconfig
+
+	Device Drivers---->
+		--- MMC/SD/SDIO card support
+                  [ ]   MMC debugging
+                  [ ]   MMC host clock gating
+                  *** MMC/SD/SDIO Card Drivers ***
+                  < >   MMC block device driver
+                  < >   SDIO UART/GPS class support
+                  < >   MMC host test driver
+                  *** MMC/SD/SDIO Host Controller Drivers ***
+                  <*>   Secure Digital Host Controller Interface support
+                  <*>   SDHCI support on PCI bus
+                  [ ]     Ricoh MMC Controller Disabler
+                  < >   SDHCI platform and OF driver helper
+                  < >   Winbond W83L51xD SD/MMC Card Interface support
+                  < >   TI Flash Media MMC/SD Interface support
+                  < >   ENE CB710 MMC/SD Interface support
+                  < >   VIA SD/MMC Card Reader Driver
+                  < >   Renesas USDHI6ROL0 SD/SDIO Host Controller support
+
+	Compile OpenWrt using Make V=s, then write openwrt img to u-disk and boot up
+
+26. Bring up marvell wireless NIC on OpenWrt system
+
+	copy pcie/sdio/usb firmware to /lib/firmware/mrvl folder
+	On OpenWrt running OS
+	scp usrname@<target_pc ip address>:/path/firmware.bin /lib/firmware/mrvl
+
+	Another way is to add firmware binary to OpenWrt source code
+
+27. load marvell pcie/sdio/usb driver modules
+
+    End with Marvell Wirelss NIC card bring up on OpenWrt
+
+=======================================================================================================
+If firmware is copied to OpenWrt via scp, following steps could be ignored.
+28. Add firmware binary in OpenWrt
+	Copy pcie/usb/sdio firmware to folder:
+	openwrt/build_dir/target-x86_64_uClibc-0.9.33.2/linux-firmware-52442afee9907bc32a058f22bb3295d040677c26/mrvl/
+29. Go to penwrt/package/firmware/linux-firmware
+	Modify marvell.mk as following
+
+	+Package/mrvl-pcie-firmware = $(call Package/firmware-default,Marvell PCIE8997 firmware)
+	+define Package/mrvl-pcie-firmware/install
+	+	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+	+	$(INSTALL_DATA) \
+	+		$(PKG_BUILD_DIR)/mrvl/pcieusb8997_combo_v4.bin \
+	+		$(1)/lib/firmware/mrvl/
+	+endef
+	+$(eval $(call BuildPackage,mrvl-pcie-firmware))
+
+	+Package/mrvl-sd8xxx-firmware = $(call Package/firmware-default,Marvell SDIO8997 firmware)
+	+define Package/mrvl-sd8xxx-firmware/install
+	+	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+	+	$(INSTALL_DATA) \
+	+		$(PKG_BUILD_DIR)/mrvl/sdsd8997_combo_v4.bin \
+	+		$(1)/lib/firmware/mrvl/
+	+endef
+	+$(eval $(call BuildPackage,mrvl-sd8xxx-firmware))
+
+	+Package/mrvl-usb-firmware = $(call Package/firmware-default,Marvell SDIO8997 firmware)
+	+define Package/mrvl-usb-firmware/install
+	+	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+	+	$(INSTALL_DATA) \
+	+		$(PKG_BUILD_DIR)/mrvl/usbusb8997_combo_v4.bin \
+	+		$(1)/lib/firmware/mrvl/
+	+endef
+	+$(eval $(call BuildPackage,mrvl-usb-firmware))
+
+30. re-modify openwrt/package/kernel/mac80211/Makefile
+
+	for PCIE
+	+  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT +mrvl-pcie-firmware
+	for SDIO
+	+  DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT +mrvl-sd8xxx-firmware
+	for USB
+	+  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT +mrvl-usb-firmware
+31. Go to step 25.
+=======================================================================================================
+To support SDIO, USB and PCIE in one OpenWrt BSP
+if no need to support multi bus types in one BSP, ignore the following steps
+32. Re-modify Modify openwrt/package/kernel/mac80211/Makefile.
+	for PCIE
+        +       $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/mlan-pcie.ko \
+	for SDIO
+	+       $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/mlan-sdio.ko \
+	for USB
+	+       $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/mlan-usb.ko \
+33. Re-modify (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/Makefile
+	for PCIE
+
+	-obj-m := mlan.o
+	-mlan-objs := $(MLANOBJS)
+	+obj-m := mlan-pcie.o
+	+mlan-pcie-objs := $(MLANOBJS)
+
+	for SDIO
+
+	-obj-m := mlan.o
+	-mlan-objs := $(MLANOBJS)
+	+obj-m := mlan-sdio.o
+	+mlan-sdio-objs := $(MLANOBJS)
+
+	for USB
+
+	-obj-m := mlan.o
+	-mlan-objs := $(MLANOBJS)
+	+obj-m := mlan-usb.o
+	+mlan-usb-objs := $(MLANOBJS)
+34. Go to step 25.
diff --git a/wlan_sd8987/README_RBC b/wlan_sd8987/README_RBC
new file mode 100644
index 0000000..c849287
--- /dev/null
+++ b/wlan_sd8987/README_RBC
@@ -0,0 +1,103 @@
+===============================================================================
+            U S E R  M A N U A L for Robust BT-WLAN coex (RBC)
+
+ Copyright (C) 2014-2018, Marvell International Ltd.
+ All Rights Reserved
+===============================================================================
+
+###############################
+
+# Abbreviations and acronyms
+
+###############################
+RBC - Robust BT-WLAN co-existence
+TMD - Time Distribute
+SMPS - Spatial Multiplexing Power Save
+
+###############################
+
+# Default RBC modes:
+
+###############################
+1.  For systems where BT and WLAN have seperate antennas, RBC mode is
+    automatically disabled in FW after detecting this from FEM cal data. e.g.
+    For 1x1 Dual-Ant system and 2x2 3-Ant system RBC mode is disabled.
+2.  For systems where BT and WLAN share an antenna, RBC mode is automatically
+    enabled in FW after detecting this from FEM cal data.
+    Default modes:
+    1x1 single antenna system: TMD RBC
+    2x2 2-antenna system: 1x1 SMPS RBC
+
+
+#################################
+
+# 2x2 2-antenna system RBC modes
+
+#################################
+There are three mutually exclusive RBC modes for a 2x2 system.
+The default RBC mode is 1x1 SMPS RBC. The required RBC mode must be
+configured before starting uAP or associating in-STA. The mode cannot be
+changed dynamically when any of these connections is active. The modes are
+described below:
+1.  1x1 SMPS RBC mode: WLAN switches to 1x1 FEM when BT is turned on. Also,
+    in-STA goes to SMPS mode w.r.t. ext-AP. When BT is turned off, WLAN
+    switches back to 2x2 FEM setting and in-STA moves out of SMPS.
+    uAP starts bss with only 1-stream even BT is off because it cannot
+    dynamically move between 1-stream and 2-stream rates like in-STA. To start
+    uAP with 2-stream, RBC mode has to be disabled.
+2.  1x2 SMPS RBC mode: Similar as 1x1 SMPS RBC mode. WLAN switches to 1x2 FEM
+    when BT is turned on. In this mode, it is expected that when BT is not
+    actively transmitting, WLAN can receive on both the antennas to enhance
+    the range. Note that 1-stream rates are used for receive and transmit.
+3.  2x2 TMD RBC mode: WLAN uses 2x2 antenna setting and timeshares the antenna
+    with BT.
+
+###############################
+
+# RBC mode select:
+
+###############################
+
+User can use robust_btc.conf and hostcmd to select different RBC mode:
+
+hostcmd mode_get
+hostcmd mode_timeshare
+hostcmd mode_spatial
+    This command is used to get/set Robust BT Coex.
+    mode_get:       get the current mode
+    mode_timeshare: set Robust BT Coex to timeshare mode  (default on 1x1 chips)
+    mode_spatial:   set Robust BT Coex to spatial mode    (only for, and default on 2x2 chips)
+
+    Usage:
+        mlanconfig mlanX hostcmd config/robust_btc.conf mode_get
+        mlanconfig mlanX hostcmd config/robust_btc.conf mode_timeshare
+        mlanconfig mlanX hostcmd config/robust_btc.conf mode_spatial
+
+hostcmd gpio_cfg
+    This command is used to enable/disable GPIO cfg.
+    gpio_cfg: enable/disable GPIO cfg for external bt request  (default is enable with High Polarity)
+
+    Usage:
+        mlanconfig mlanX hostcmd config/robust_btc.conf gpio_cfg
+
+hostcmd generictime
+hostcmd a2dptime
+hostcmd inquirytime
+hostcmd ap_generictime
+hostcmd ap_a2dptime
+hostcmd ap_inquirytime
+        This command is used to configure the time slice of COEX (only works in timeshare mode)
+        generictime:       configure the Bttime and Wlantime in Station Generic case
+        a2dptime:          configure the Bttime and Wlantime in Station A2DP case
+        inquirytime:       configure the Bttime and Wlantime in Station Inquiry case
+        ap_generictime:    configure the Bttime and Wlantime in Ap Generic case
+        ap_a2dptime:       configure the Bttime and Wlantime in Ap A2DP case
+        ap_inquirytime:    configure the Bttime and Wlantime in Ap Inquiry case
+
+    Usage:
+                mlanutl mlanX hostcmd config/robust_btc.conf generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf inquirytim
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime
diff --git a/wlan_sd8987/README_UAP b/wlan_sd8987/README_UAP
new file mode 100644
index 0000000..c3234ee
--- /dev/null
+++ b/wlan_sd8987/README_UAP
@@ -0,0 +1,2724 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2009-2018, Marvell International Ltd.
+ All Rights Reserved
+
+1) FOR DRIVER BUILD
+
+	Goto source code directory wlan_src.
+		make [clean] build
+	The driver binaries can be found in ../bin_xxxx directory.
+	The driver code supports Linux kernel up to 4.18.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy sd8786_uapsta.bin | sd8787_uapsta.bin | ... to /lib/firmware/mrvl/ directory,
+	   create the directory if it doesn't exist.
+	b) Install uAP 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
+		The default drv_mode is 7.
+
+		max_uap_bss: Maximum number of uAP BSS (default 1, max 2)
+		uap_name: Name of the uAP interface (default: "uap")
+	   For example, to install SD8787 driver,
+	   To load driver in uAP only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=2 [fw_name=mrvl/sd8787_uapsta.bin]
+	   To switch mode between STA only, uAP only and uAPSTA in run time,
+		echo drv_mode=1 > /proc/mwlan/config		// STA mode
+		echo drv_mode=2 > /proc/mwlan/config		// uAP mode
+		echo drv_mode=3 > /proc/mwlan/config		// uAPSTA mode
+	c) Uninstall uAP driver,
+		ifconfig uapX down
+		rmmod sd8xxx
+		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)>
+	  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>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf
+	  sdio_rx_aggr=1|2 <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
+	  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>
+	  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
+
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sd8xxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+	The following info are provided in /proc/mwlan/uapX/info.
+
+	driver_name = "uap"
+	driver_version = <driver version>
+	InterfaceName= "uapX"
+	State= "Disconnected" | "Connected"
+	MACAddress= <6-byte adapter MAC address>
+	MCCount= <multicast address count>
+	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>
+	num_tx_timeout =  <number of tx timeout>
+	carrier "on" | "off"
+	tx queue "stopped" | "started"
+
+	The following debug info are provided in /proc/mwlan/uapX/debug.
+
+	drvdbg = <bit masks of driver debug message control>
+		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,...)
+	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>
+	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>
+	num_bridge_pkts = <number of bridged packets>
+	num_drop_pkts = <number of dropped packets>
+	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>
+	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>
+	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>
+	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>
+	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>
+
+	Example:
+		echo "drvdbg=0x7" > /proc/mwlan/uapX/debug	#enable MMSG,MFATAL,MERROR messages
+
+	Use dmesg or cat /var/log/debug to check driver debug messages.
+
+	To log driver debug messages to file,
+	a) Edit /etc/rsyslog.conf, add one line "*.debug		/var/log/debug"
+	b) touch /var/log/debug (if the file doesn't exist)
+	c) service rsyslog restart
+
+4) SOFT_RESET command
+   This command is used to perform a "soft reset" on the module.
+   The FW code will disable hardware and jump to boot code.
+   Host software will then need to re-download firmware if required.
+
+   Usage:
+	echo "soft_reset=1" > /proc/mwlan/config
+
+===============================================================================
+
+		U S E R  M A N U A L  F O R  UAPUTL
+
+NAME
+uaputl.exe [options] <command> [command parameters]]
+
+Options:
+	--help 	Display help
+	-v    	Display version
+	-i <interface>
+	-d <debug_level=0|1|2>
+
+Example:
+	./uaputl.exe --help
+		"display help for uaputl"
+
+	./uaputl.exe sys_config --help
+		"display help for sys_config command"
+
+This tool can be used to set/get uAP's settings. To change AP settings, you might
+need to issue "bss_stop" command to stop AP before making change and issue "bss_start"
+command to restart the AP after making change.
+
+------------------
+Supported Commands
+------------------
+version
+debug_level
+sys_config [CONFIG_FILE_NAME]
+bss_config [CONFIG_FILE_NAME]
+sys_info
+sys_reset
+bss_start
+bss_stop
+sta_list
+sta_deauth <STA_MAC_ADDRESS>
+sta_deauth_ext <STA_MAC_ADDRESS> <REASON_CODE>
+radioctrl [0|1]
+txratecfg [l] [m] [n]
+antcfg [m] [n]
+pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE]
+mic_err <STA_MAC_ADDRESS>
+key_material <MAC_ADDRESS> <KEY> [KEY_ID]
+sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]
+coex_config [CONFIG_FILE_NAME]
+hscfg [condition [[GPIO# [gap]]]]
+hssetpara condition [[GPIO# [gap]]]
+sys_cfg_wmm  [qosinfo=<qosinfo>]
+             [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+             [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+             [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+             [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+sys_cfg_ap_wmm [0]
+               [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+               [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+               [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+               [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_MAP]
+addbapara [timeout txwinsize rxwinsize txamsdu rxamsdu]
+aggrpriotbl <m0> <n0> <m1> <n1> ... <m7> <n7>
+addbareject <m0> <m1> ... <m7>
+httxbfcfg <ACTION> [ACT_DATA]
+httxcfg [<m>]
+htstreamcfg [n]
+deepsleep [MODE] [IDLE_TIME]
+sdcmd52rw <FN no.> <address> [data]
+hostcmd <txpwrlimit_cfg.conf> txpwrlimit_cfg_get
+hostcmd <txpwrlimit_cfg.conf> txpwrlimit_2g_cfg_set
+hostcmd <txpwrlimit_cfg.conf> txpwrlimit_5g_cfg_set
+tx_data_pause [ENABLE][TX_BUF_CNT]
+vhtcfg <j> <k> [l] [m] [n] [o]
+dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+cscount [<channel_switch_count>]
+mgmtframectrl [MASK]
+
+-------------------------------------------------------------------
+The following commands can be issued individually for debug purpose
+-------------------------------------------------------------------
+sys_cfg_ap_mac_address [AP_MAC_ADDRESS]
+sys_cfg_ssid [SSID]
+sys_cfg_beacon_period [BEACON_PERIOD]
+sys_cfg_dtim_period [DTIM_PERIOD]
+sys_cfg_channel [CHANNEL] [MODE]
+sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]
+sys_cfg_scan_channels [CHANNEL[.BAND]]
+sys_cfg_rates [RATES]
+sys_cfg_rates_ext [rates RATES] [mbrate RATE]
+sys_cfg_tx_power [TX_POWER]
+sys_cfg_bcast_ssid_ctl [0|1|2]
+sys_cfg_preamble_ctl
+sys_cfg_bss_status
+sys_cfg_rts_threshold [RTS_THRESHOLD]
+sys_cfg_frag_threshold [FRAG_THRESHOLD]
+sys_cfg_rsn_replay_prot [1|0]
+sys_cfg_tx_beacon_rate [TX_BEACON_RATE]
+sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]
+sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]
+sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]
+sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]
+sys_cfg_auth [AUTH_MODE]
+sys_cfg_protocol [PROTOCOL] [AKM_SUITE]
+sys_cfg_pmf [MFPC] [MFPR]
+sys_cfg_wep_key [INDEX ISDEFAULT KEY]
+sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]
+sys_cfg_pwk_cipher [<PROTOCOL>] [PAIRWISE_CIPHER]
+sys_cfg_gwk_cipher [GROUP_CIPHER]
+sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]
+sys_cfg_wpa_passphrase [PASSPHRASE]
+sys_cfg_max_sta_num [STA_NUM]
+sys_cfg_retry_limit [RETRY_LIMIT]
+sys_cfg_sticky_tim_config [ENABLE] [<DURATION> <STICKY_BIT_MASK>]
+sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]
+sys_cfg_2040_coex [ENABLE]
+sys_cfg_eapol_pwk_hsk [<TIMEOUT> <RETRIES>]
+sys_cfg_eapol_gwk_hsk [<TIMEOUT> <RETRIES>]
+sta_filter_table <FILTERMODE> <MACADDRESS_LIST>
+regrdwr <TYPE> <OFFSET> [value]
+memaccess <ADDR> [value]
+rdeeprom <offset> <byteCount>
+cfg_data <type> [*.conf]
+sys_cfg_80211d [state STATE] [country COUNTRY]
+uap_stats
+sys_cfg_tdls_ext_cap [CONFIG_FILE]
+sys_cfg_restrict_client_mode [<ENABLE> [MODE_CONFIG]]
+skip_cac [<MODE>]
+
+-------------------
+Details of Commands
+-------------------
+
+version
+-------
+    "./uaputl.exe -v"
+
+    This command prints the uAP utility version information.
+
+debug_level
+-----------
+    "./uaputl.exe -d <debug_level>"
+
+    The supported debug_level are:
+        0     - no debug
+        1     - enable MSG_DEBUG
+        2     - enable all the debug
+    This command use to control the debug level of uaputl.exe.
+
+    Example:
+	./uaputl.exe -d 2 sys_config
+		Enable all the debug in uaputl.exe
+
+sys_config
+----------
+    "./uaputl.exe sys_config [CONFIG_FILE]"
+    This command is used to set or get the current settings of the Micro AP.
+
+    The supported options are:
+        CONFIG_FILE is file contain all the Micro AP settings.
+        empty - Get current Micro AP settings
+
+    Example:
+	./uaputl.exe sys_config
+		Get current settings of the Micro AP.
+
+	./uaputl.exe sys_config config/uaputl.conf
+		Load Micro AP's settings from uaputl.conf file and set.
+
+bss_config
+----------
+    "./uaputl.exe bss_config [CONFIG_FILE]"
+    This command is used to set or get the current settings of the BSS.
+
+    The supported options are:
+        CONFIG_FILE is file contain all the BSS settings.
+        empty - Get current BSS settings
+
+    Example:
+	./uaputl.exe bss_config
+		Get current settings of the BSS.
+
+	./uaputl.exe bss_config config/uaputl.conf
+		Load BSS settings from uaputl.conf file and set.
+
+sys_info
+--------
+    "./uaputl.exe sys_info"
+
+    This command returns system information such as firmware version number
+    and HW information.
+
+sys_reset
+---------
+    "./uaputl.exe sys_reset"
+
+    This command is used to reset the Micro AP back to its initial state.
+    For example, this can be used to recover from a serious error, or before
+    creating a new BSS.
+
+    This command has the following effects:
+        1. The WLAN hardware MAC is reset.
+        2. All MIB variables are initialized to their respective default
+           values.
+        3. The firmware internal variables are reset to their respective
+           default values.
+        4. The firmware state machines are reset to their respective initial
+           states.
+
+bss_start
+---------
+    "./uaputl.exe bss_start"
+
+    This command starts the BSS.
+    There is no error for redundant bss_start command.
+
+bss_stop
+--------
+    "./uaputl.exe bss_stop"
+
+    This command stops the BSS. The command causes the firmware to:
+        1. Deauthenticate all associated client stations.
+        2. Turn off the radio (hence stopping beaconing).
+    There is no error for redundant bss_stop command.
+
+sta_list
+--------
+    "./uaputl.exe sta_list"
+
+    This command returns the list of client stations that are currently
+    associated with the AP.
+
+    The output is formatted as shown below, for each STA:
+    "STA <STA_NUM> information:
+     ==========================
+     MAC Address: <STA MAC address>
+     Power mfg status: active|power save
+     Rssi:  <RSSI_VALUE>"
+
+sta_deauth
+----------
+    "./uaputl.exe sta_deauth <STA_MAC_ADDRESS>"
+
+    This command is used to de-authentciate a client station for any reason.
+
+radioctrl
+----------
+    "./uaputl.exe radioctrl [0|1]"
+
+    This command is used to set or get the radio settings.
+    The supported options are:
+        1     - Turn radio on
+        0     - Turn radio off
+        empty - Get current radio setting
+
+txratecfg
+----------
+    "./uaputl.exe txratecfg [l] [m] [n]"
+
+    This command is used to set/get the transmit data rate.
+
+    Where
+        [l] is <format>
+        <format> - This parameter specifies the data rate format used in this command
+            0:    LG
+            1:    HT
+            2:    VHT
+            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
+            32   MCS32
+        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
+        [n] is <nss>
+        <nss> - This parameter specifies the NSS. It is valid only for VHT
+        If <format> is 2 (VHT),
+            1    NSS1
+            2    NSS2
+
+    Examples:
+        ./uaputl.exe txratecfg 0 3        : Set fixed Tx rate to 11 Mbps
+        ./uaputl.exe txratecfg 0 11       : Set fixed Tx rate to 54 Mbps
+        ./uaputl.exe txratecfg 1 3        : Set fixed Tx rate to MCS3
+        ./uaputl.exe txratecfg 2 3 2    : Set fixed Tx rate to MCS3 for NSS2
+        ./uaputl.exe txratecfg 0xff     : Disable fixed rate and uses auto rate
+        ./uaputl.exe txratecfg          : Read the current data rate setting
+
+antcfg
+----------
+    "./uaputl.exe antcfg [m] [n]"
+
+    This command is used to set/get the transmit and receive antenna.
+    where value of m is:
+        Bit 0   -- Tx Path A
+        Bit 1   -- Tx Path B
+        Bit 0-1 -- Tx Path A+B
+
+    where value of n is:
+        Bit 0   -- Rx Path A
+        Bit 1   -- Rx Path B
+        Bit 0-1 -- Rx Path A+B
+    The Tx path setting (m) is used if Rx path (n) is not provided.
+
+    Examples:
+        ./uaputl.exe antcfg             : Get Tx and Rx path
+        ./uaputl.exe antcfg 3           : Set Tx and Rx path to A+B
+        ./uaputl.exe antcfg 2 3         : Set Tx path to B and Rx path to A+B
+
+sys_cfg_ap_mac_address
+----------------------
+    "./uaputl.exe sys_cfg_ap_mac_address [AP_MAC_ADDRESS]"
+
+    This command is used to set or get the AP MAC address.
+
+    If no arguments are given, this command returns the current AP MAC
+    address.
+    Otherwise, this MAC address becomes the BSSID of the infrastructure
+    network created by the AP.
+
+    Example:
+	./uaputl.exe sys_cfg_ap_mac_address 00:50:43:20:aa:bb
+		Set AP MAC address to 00:50:43:20:aa:bb
+
+	./uaputl.exe sys_cfg_ap_mac_address
+		Get AP MAC address"
+
+sys_cfg_ssid
+------------
+    "./uaputl.exe sys_cfg_ssid [SSID]"
+
+    This command is used to set or get the AP SSID.
+
+    If no arguments are given, this command returns the current AP SSID.
+    While setting, the maximum length of the SSID can be 32 characters.
+
+    Example:
+	./uaputl.exe sys_cfg_ssid microap
+		Set AP ssid to "microap"
+
+	./uaputl.exe sys_cfg_ssid
+		Get AP ssid
+
+sys_cfg_beacon_period
+---------------------
+    "./uaputl.exe sys_cfg_beacon_period [BEACON_PERIOD]"
+
+    This command is used to set or get the AP beacon period.
+
+    If no arguments are given, this command returns the current AP beacon
+    period.
+
+    Beacon period is represented in milliseconds.
+
+    Example:
+	./uaputl.exe sys_cfg_beacon_period 100
+		Set AP beacon period to 100 TU
+
+	./uaputl.exe sys_cfg_beacon_period
+		Get AP beacon period
+
+sys_cfg_dtim_period
+-------------------
+    "./uaputl.exe sys_cfg_dtim_period [DTIM_PERIOD]
+
+    This command is used to set or get the AP DTIM period.
+
+    If no arguments are given, this command returns the current AP DTIM
+    period.
+
+    Example:
+	./uaputl.exe sys_cfg_dtim_period 3
+		Set AP DTIM period to 3
+
+	./uaputl.exe sys_cfg_dtim_period
+		Get AP DTIM period
+
+sys_cfg_scan_channels
+---------------------
+    "./uaputl.exe sys_cfg_scan_channels [CHANNEL[.BAND]]"
+
+    This command is used to set or get the AP's scan channel list.
+
+    If no arguments are given, this command returns the scan channel list.
+    If BAND is 0, channel is set in 2.4 GHz band and if BAND is 1, channel is set to 5GHz.
+    Channels from only one of the bands should be specified.
+    Each CHANNEL.BAND pair must be separated by a space. BAND parameter is optional.
+
+    Example:
+	./uaputl.exe sys_cfg_scan_channels 1 11 6
+		Set AP scan channel list to 1 11 6
+
+	./uaputl.exe sys_cfg_scan_channels 11.0 6.0
+		Set AP scan channel list to 11 6
+
+	./uaputl.exe sys_cfg_scan_channels
+		Get AP scan channel list
+
+        ./uaputl.exe sys_cfg_scan_channels 8.1 16.1 34
+                Set AP scan channel list to 8 16 and 34 in 5GHz band.
+
+sys_cfg_channel
+---------------
+    "./uaputl.exe sys_cfg_channel [CHANNEL] [MODE]"
+
+    This command is used to set or get the AP radio channel.
+
+    If no arguments are given, this command returns the current AP radio
+    channel.
+
+    MODE: band config mode.
+          Bit 0:  automatic channel selection (ACS) enable/disable
+          Bit 1:  secondary channel is above primary channel enable/disable(only allow for channel 1-7)
+          Bit 2:  secondary channel is below primary channel enable/disable(only allow for channel 5-11)
+          For 'a' band channel:
+          Bit 1:  secondary channel is above primary channel enable/disable
+          Bit 2:  secondary channel is below primary channel enable/disable
+          Only following pairs of channels are valid for secondary channel setting in 5GHz band.
+          36, 40
+          44, 48
+          52, 56
+          60, 64
+          100, 104
+          108, 112
+          116, 120
+          124, 128
+          132, 136
+          149, 153
+          157, 161
+
+    Example:
+        ./uaputl.exe sys_cfg_channel 6
+                Set AP radio channel to 6, and no secondary channel.
+
+        ./uaputl.exe sys_cfg_channel 11 0
+                Set AP radio channel to 11 with Manual Channel Select.
+
+        ./uaputl.exe sys_cfg_channel 0 1
+                Set AP to ACS.
+
+        ./uaputl.exe sys_cfg_channel
+                Get AP radio channel
+
+        ./uaputl.exe sys_cfg_channel 6 2
+                Set AP primary radio channel to 6, and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel 6 4
+                Set AP primary radio channel to 6, and secondary channel is below
+        ./uaputl.exe sys_cfg_channel 0 3
+                Set AP to ACS mode, and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel 0 5
+                Set AP to ACS mode, and secondary channel is below.
+        ./uaputl.exe sys_cfg_channel 36 2
+                Set AP primary radio channel to 36, and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel 40 4
+                Set AP primary radio channel to 40, and secondary channel is below.
+
+sys_cfg_channel_ext
+---------------
+    "./uaputl.exe sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]"
+
+    This command is used to set or get the AP radio channel.
+
+    If no arguments are given, this command returns the current AP radio
+    channel.
+
+    BAND: 0 : 2.4GHz operation
+          1 : 5GHz operation
+    MODE: band config mode.
+          Bit 0:  automatic channel selection (ACS) enable/disable
+          Bit 1:  secondary channel is above primary channel enable/disable(only allow for channel 1-7)
+          Bit 2:  secondary channel is below primary channel enable/disable(only allow for channel 5-11)
+          For 'a' band channel:
+          Bit 1:  secondary channel is above primary channel enable/disable
+          Bit 2:  secondary channel is below primary channel enable/disable
+          Only following pairs of channels are valid for secondary channel setting in 5GHz band.
+          36, 40
+          44, 48
+          52, 56
+          60, 64
+          100, 104
+          108, 112
+          116, 120
+          124, 128
+          132, 136
+          149, 153
+          157, 161
+
+    Example:
+        ./uaputl.exe sys_cfg_channel_ext 6
+Set AP radio channel to 6, and no secondary channel.
+
+        ./uaputl.exe sys_cfg_channel_ext 11 0 0
+                Set AP radio channel to 11 in 2.4GHz band with Manual Channel Select.
+
+        ./uaputl.exe sys_cfg_channel_ext 0 0 1
+                Set AP to ACS mode and 2.4GHz band.
+
+        ./uaputl.exe sys_cfg_channel_ext 8 0
+                Set AP to channel 8 and 2.4GHz band.
+
+        ./uaputl.exe sys_cfg_channel_ext 8 1
+                Set AP to channel 8 and 5GHz band.
+
+        ./uaputl.exe sys_cfg_channel_ext 36 1
+                Set AP to channel 36 and 5GHZ band.
+
+        ./uaputl.exe sys_cfg_channel_ext
+                Get AP radio channel, band and mode.
+
+        ./uaputl.exe sys_cfg_channel_ext 6 0 2
+                Set AP primary radio channel to 6, band to 2.4GHz and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel_ext 6 0 4
+                Set AP primary radio channel to 6, band to 2.4GHz and secondary channel is below
+        ./uaputl.exe sys_cfg_channel_ext 0 0 3
+                Set AP to ACS mode, band to 2.4GHz and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel_ext 0 0 5
+                Set AP to ACS mode, band to 2.4GHz and secondary channel is below.
+        ./uaputl.exe sys_cfg_channel_ext 36 1 2
+                Set AP primary radio channel to 36, band to 5GHz and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel_ext 40 1 4
+                Set AP primary radio channel to 40, band to 5GHz and secondary channel is below.
+
+sys_cfg_rates
+-------------
+    "./uaputl.exe sys_cfg_rates [RATES]"
+
+    If 'Rate' provided, a 'set' is performed else a 'get' is performed
+    RATES is provided as a set of data rates, in unit of 500 kilobits
+    A rate with MSB bit is basic rate, i.e 0x82 is basic rate.
+
+    'set' will not allowed after bss start.
+
+    Valid rates: 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
+    Non-Basic rates: 0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+    Basic rates: 0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc
+
+    Each rate must be separated by a space.
+
+    Example:
+    ./uaputl.exe sys_cfg_rates 0x82 0x84 0x96 0x0c 0x12 0x18
+    ./uaputl.exe sys_cfg_rates
+
+sys_cfg_rates_ext
+-----------------
+    "./uaputl.exe sys_cfg_rates_ext [rates RATES] [mbrate RATE]"
+
+    If 'Rate' provided, a 'set' is performed else a 'get' is performed.
+    RATES is provided as a set of data rates, in unit of 500 kilobits
+    A rate with MSB bit is basic rate, i.e 0x82 is basic rate.
+    If only operational rates is provided, MCBC rate and unicast rate will be set to auto.
+
+    Valid rates: 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
+    Non-Basic rates: 0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+    Basic rates: 0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc
+    Rates 2, 4, 11 and 22 (in units of 500 Kbps) must be present in either of
+    basic or non-basic rates. If OFDM rates are enabled then 12, 24 and 48 (in
+    units of 500 Kbps) must be present in either basic or non-basic rates.
+
+    Each rate must be separated by a space.
+
+    rates followed by RATES for setting operational rates.
+    mbrate followed by RATE for setting multicast and broadcast rate.
+
+    operational rates only allow to set before bss start.
+
+    Example:
+    ./uaputl.exe sys_cfg_rates_ext rates 0x82 0x04 11 0x96 12 24 48 mbrate 0x16
+        Set AP operation rates to 0x82,0x04,11,0x96,12,24,48, multicast rate to 0x16
+    ./uaputl.exe sys_cfg_rates_ext rates 0x82 0x04 11 0x96 12 24 48
+		Set AP operation rates to 0x82,0x04,11,0x96,12,24,48.
+
+sys_cfg_tx_power
+----------------
+    "./uaputl.exe sys_cfg_tx_power [TX_POWER]"
+
+    This command is used to set or get the AP Tx power.
+
+    If no arguments are given, this command returns the current AP Tx power.
+
+    Tx power level is represented in dBm.
+
+    Example:
+	./uaputl.exe sys_cfg_tx_power 13
+		Set AP Tx power to 13 dBm
+
+	./uaputl.exe sys_cfg_tx_power
+		Get AP Tx power
+
+sys_cfg_bcast_ssid_ctl
+----------------------
+    "./uaputl.exe sys_cfg_bcast_ssid_ctl [0|1|2]"
+
+    This command is used to set or get the SSID broadcast feature setting.
+
+    The supported options are:
+        0     - Disable SSID broadcast, send empty SSID (length=0) in beacon.
+        1     - Enable SSID broadcast
+        2     - Disable SSID broadcast, clear SSID (ACSII 0) in beacon, but keep the original length
+        empty - Get current SSID broadcast setting
+
+    When broadcast SSID is enabled, the AP responds to probe requests from
+    client stations that contain null SSID.
+
+    When broadcast SSID is disabled (sys_cfg_bcast_ssid_ctl = 0/2), the AP:
+        1. Does not respond to probe requests that contain null SSID.
+        2. when sys_cfg_bcast_ssid_ctl = 0, generates beacons that contain null SSID (length=0).
+        3. when sys_cfg_bcast_ssid_ctl = 2, clear SSID (ACSII 0) in beacon and keep the original length
+
+   Example:
+        ./uaputl.exe sys_cfg_bcast_ssid_ctl 0
+                Disable SSID broadcast, send empty SSID (length=0) in beacon.
+
+	./uaputl.exe sys_cfg_bcast_ssid_ctl 1
+		Enable SSID broadcast
+
+        ./uaputl.exe sys_cfg_bcast_ssid_ctl 2
+                Disable SSID broadcast, clear SSID (ACSII 0) in beacon, but keep the original length
+
+	./uaputl.exe sys_cfg_bcast_ssid_ctl
+		Get SSID broadcast setting
+
+sys_cfg_preamble_ctl
+--------------------
+    "./uaputl.exe sys_cfg_preamble_ctl"
+
+    This command is used to get type of preamble.
+
+    Example:
+	./uaputl.exe sys_cfg_preamble_ctl
+		Get AP preamble setting
+
+sys_cfg_bss_status
+--------------------
+    "./uaputl.exe sys_cfg_bss_status"
+
+    This command is used to get current BSS status.
+
+    Example:
+	./uaputl.exe sys_cfg_bss_status
+		Get current BSS status
+
+sys_cfg_rts_threshold
+---------------------
+    "./uaputl.exe sys_cfg_rts_threshold [RTS_THRESHOLD]"
+
+    This command is used to set or get the RTS threshold value.
+
+    If no arguments are given, this command returns the current RTS threshold
+    value.
+
+    Example:
+	./uaputl.exe sys_cfg_rts_threshold 2347
+		Set AP RTS threshold to 2347
+
+	./uaputl.exe sys_cfg_rts_threshold
+		Get AP RTS threshold
+
+sys_cfg_frag_threshold
+----------------------
+    "./uaputl.exe sys_cfg_frag_threshold [FRAG_THRESHOLD]"
+
+    This command is used to set or get the Fragmentation threshold value.
+
+    If no arguments are given, this command returns the current Fragmentation threshold
+    value.
+
+    Example:
+	./uaputl.exe sys_cfg_frag_threshold 2346
+		Set AP Fragmentation threshold to 2346
+
+	./uaputl.exe sys_cfg_frag_threshold
+		Get AP Fragmentation threshold
+
+    Note: Please use aggrpriotbl command to disable the AMPDU/AMSDU aggregation when frag_threshold is set.
+
+sys_cfg_rsn_replay_prot
+-----------------------
+    "./uaputl.exe sys_cfg_rsn_replay_prot [1|0]"
+
+    This command is used to enable or disable RSN replay protection.
+
+    The supported options are:
+        0     - Disable RSN replay protection
+        1     - Enable RSN replay protection
+        empty - Get current RSN replay protection setting
+
+   Example:
+	./uaputl.exe sys_cfg_rsn_replay_prot 1
+		Enable RSN replay protection
+
+	./uaputl.exe sys_cfg_rsn_replay_prot
+		Get RSN replay protection setting
+
+sys_cfg_tx_beacon_rate
+--------------------
+    "./uaputl.exe sys_cfg_tx_beacon_rate [TX_BEACON_RATE]"
+
+    This command is used to set or get the Tx beacon rate settings.
+
+    The supported options are:
+        0     - Auto rate
+        >0    - Set specified beacon rate
+        empty - Get current beacon rate
+
+    Tx beacon rate is represented in units of 500 kbps. While setting Tx beacon
+    rates, only zero or rates currently configured are allowed.
+
+	Following is the list of supported rates in units of 500 Kbps:
+	    2,    4,    11,   22,   12,   18,   24,   36,   48,   72,   96,   108
+	    0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+
+    Example:
+	./uaputl.exe sys_cfg_tx_beacon_rate 0x04
+		Set AP Tx beacon rate to 2 M
+
+   	./uaputl.exe sys_cfg_tx_beacon_rate 4
+		Set AP Tx data beacon to 2 M
+
+	./uaputl.exe sys_cfg_tx_beacon_rate
+		Get AP Tx beacon rate
+
+sys_cfg_mcbc_data_rate
+----------------------
+    "./uaputl.exe sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]"
+
+    This command is used to set or get the MCBC data rate to use for multicast
+    or broadcast packet transmission.
+
+    The supported options are:
+        0     - Auto rate
+        >0    - Set specified MCBC data rate
+        empty - Get current MCBC data rate
+
+    MCBC data rate is represented in units of 500 kbps. While setting MCBC data
+    rates, only zero or one of rates currently configured as basic rates are allowed.
+
+    For example:  If current basic rates is "0x82 0x84 0x8b 0x96", then the allowed
+                  values for MCBC data rate will be "0x2 0x4 0xb 0x16".
+
+    Example:
+	./uaputl.exe sys_cfg_mcbc_data_rate 22
+		Set AP MCBC data rate to 11 M
+
+   	./uaputl.exe sys_cfg_mcbc_data_rate 0
+		Set AP MCBC data rate to auto
+
+	./uaputl.exe sys_cfg_mcbc_data_rate
+		Get AP MCBC data rate
+
+sys_cfg_pkt_fwd_ctl
+-------------------
+    "./uaputl.exe sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]"
+
+    This command is used to set or get the packet forwarding control
+    settings.
+
+    where PKT_FWD_CTRL is:
+        bit 0 -- Packet forwarding handled by Host (0) or Firmware (1)
+        bit 1 -- Intra-BSS broadcast packets are allowed (0) or denied (1)
+        bit 2 -- Intra-BSS unicast packets are allowed (0) or denied (1)
+        bit 3 -- Inter-BSS unicast packets are allowed (0) or denied (1)
+        empty - Get current packet forwarding setting
+
+    Example:
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 1
+		Set AP packet forwarding control in firmware to allow all packets
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 6
+		Set AP packet forwarding control in Host, only allow Inter-BSS unicast packets forwarding.
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 8
+		Set AP packet forwarding control in Host, only allow Intra-BSS packets forwarding.
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 0
+		Set AP packet forwarding control in Host, allow Intra-BSS packets and
+	            Inter-BSS unicast packets forwarding.
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl
+		Get AP packet forwarding control
+
+sys_cfg_sta_ageout_timer
+------------------------
+    "./uaputl.exe sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]"
+
+    This command is used to set or get the STA ageout value.
+
+    Value of 0 will mean that stations will never be aged out.
+
+    Minimum value for this is 100. Maximum allowed setting should be 864000.
+
+    If no arguments are given, this command returns the current STA ageout
+    value.
+
+    Ageout timer value is represented in units of 100 ms.
+
+    Example:
+	./uaputl.exe sys_cfg_sta_ageout_timer 1800
+		Set AP STA ageout time to 180000 ms
+
+	./uaputl.exe sys_cfg_sta_ageout_timer
+		Get AP STA ageout time
+
+sys_cfg_ps_sta_ageout_timer
+---------------------------
+	"./uaputl.exe sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]"
+
+	This command is used to set or get the PS STA ageout value.
+
+	Value of 0 will mean that stations will never be aged out.
+
+	Minimum value for this is 100. Maximum allowed setting should be 864000.
+
+	If no arguments are given, this command returns the current	PS STA ageout
+	value.
+
+	Ageout timer value is represented in units of 100 ms.
+
+	Example:
+	./uaputl.exe sys_cfg_ps_sta_ageout_timer 1800
+		Set AP PS STA ageout time to 180000 ms
+
+	./uaputl.exe sys_cfg_ps_sta_ageout_timer
+		Get AP PS STA ageout time
+
+sys_cfg_auth
+------------
+    "./uaputl.exe sys_cfg_auth [AUTHMODE]"
+
+    This command is used to set or get the AP authentication mode.
+
+    The supported options are:
+        AUTHMODE :     0 - Open authentication
+                       1 - Shared key authentication
+                       3 - WPA3 SAE
+                       255 - Auto (Open and Shared key) authentication
+    empty - Get current authentication mode
+
+    Example:
+	./uaputl.exe sys_cfg_auth 0
+		Set AP authentication mode to Open.
+
+	./uaputl.exe sys_cfg_auth
+		Get AP authentication mode.
+
+sys_cfg_protocol
+----------------
+    "./uaputl.exe sys_cfg_protocol [PROTOCOL] [AKM_SUITE]"
+
+    This command is used to set or get the encryption protocol.
+
+    The supported options are:
+	PROTOCOL:
+			1		 No RSN
+			2		WEP Static
+			8		  WPA
+			32		  WPA2
+			40		 WPA, WPA2 Mixed Mode
+			64		 WPA3 SAE
+    empty - Get current encryption protocol
+
+    AKM_SUITE:
+            bit 0   KEY_MGMT_EAP
+            bit 1   KEY_MGMT_PSK
+            bit 2   KEY_MGMT_NONE
+            bit 8   KEY_MGMT_PSK_SHA256
+
+    Example:
+	./uaputl.exe sys_cfg_protocol 2
+		Set AP encryption protocol to static WEP.
+
+	./uaputl.exe sys_cfg_protocol
+		Get AP encryption protocol.
+
+    ./uaputl.exe sys_cfg_protocol 32 0x102
+        Set AP encryption protocol to WPA2 and AKM SUITE to PSK and PSK SHA256
+
+    ./uaputl.exe sys_cfg_protocol 40 0x100
+        Set AP encryption protocol to WPA+WPA2 and AKM SUITE to PSK SHA256
+
+sys_cfg_pmf
+-----------
+    "./uaputl.exe sys_cfg_pmf [MFPC] [MFPR]"
+
+    This command is used to set or get the PMF settings.
+
+    The supported options are:
+        MFPC:       0 - Mgmt frame protection not capable
+                    1 - Mgmt frame protection capable
+
+        MFPR:       0 - Mgmt frame protection not required
+                    1 - Mgmt frame protection required
+                    x - don't care if MFPC = 0
+
+    Example:
+    ./uaputl.exe sys_cfg_pmf 1 1
+        Set AP's PMF params to Mgmt frames protection capable and required.
+
+    ./uaputl.exe sys_cfg_pmf
+        Get AP's PMF params settings.
+
+sys_cfg_wep_key
+---------------
+    "./uaputl.exe sys_cfg_wep_key [INDEX ISDEFAULT Key_0]
+                                  [INDEX ISDEFAULT Key_1]
+                                  [INDEX ISDEFAULT Key_2]
+                                  [INDEX ISDEFAULT Key_3]
+                                  [INDEX]"
+
+    This command is used to set or get the WEP key settings.
+
+    The supported options are:
+        INDEX:       0 - KeyIndex is 0
+                     1 - KeyIndex is 1
+                     2 - KeyIndex is 2
+                     3 - KeyIndex is 3
+	ISDEFAULT:   0: KeyIndex is not the default
+		     1: KeyIndex is the default transmit key
+
+        KEY_* :      Key value.
+        empty - Get current WEP key settings for all the keys
+        INDEX - Only INDEX will get the key setting for the particular
+                KeyIndex.
+
+    Example:
+	./uaputl.exe sys_cfg_wep_key 0 1 55555
+		Set AP's default transmit key to "55555", key index is 0.
+
+    ./uaputl.exe sys_cfg_wep_key 0 1 12345678901234567890123456
+        Set AP's default transmit key to "12345678901234567890123456", key index is 0.
+
+	./uaputl.exe sys_cfg_wep_key
+		Get AP all the WEP keys settings.
+
+	./uaputl.exe sys_cfg_wep_key 1
+		Get WEP key setting for the KeyIndex = 1.
+
+sys_cfg_cipher
+--------------
+    "./uaputl.exe sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]"
+
+    This command is used to set or get the key types for the pairwise and group key.
+
+    The supported options are:
+	PAIRWISE_CIPHER:
+			0		  None
+			4		  TKIP
+			8		 AES CCMP
+			12		 AES CCMP + TKIP
+        GROUP_CIPHER:
+			0		  None
+			4		  TKIP
+			8		 AES CCMP
+    	empty - Get current key types
+
+	Valid combinations of [PAIRWISE_CIPHER GROUP_CIPHER] are:
+		[0 0], [4 4], [8 8], [12 4].
+
+    Example:
+	./uaputl.exe sys_cfg_cipher 4 4
+		Set AP's pairwise and group key's type to TKIP.
+
+	./uaputl.exe sys_cfg_cipher
+		Get AP's key types for the pairwise and group key.
+
+sys_cfg_pwk_cipher
+------------------
+    "./uaputl.exe sys_cfg_pwk_cipher [<PROTOCOL>] [PAIRWISE_CIPHER]"
+
+    This command is used to set or get protocol and corresponding pairwise cipher settings.
+
+    The supported options are:
+        PROTOCOL:
+                        0                None
+                        8                 WPA
+                        32                WPA2
+        PAIRWISE_CIPHER:
+                        0                 None
+                        4                 TKIP
+                        8                AES CCMP
+                        12               AES CCMP + TKIP
+        WPA/TKIP cipher cannot be used when uAP operates in 802.11n mode.
+        If only PROTOCOL is provided, pairwise cipher for that protocol is displayed.
+        empty - Get protocol and corresponding pairwise cipher settings.
+
+    Example:
+        ./uaputl.exe sys_cfg_pwk_cipher 8 4
+                Set AP's pairwise cipher to TKIP for WPA protocol.
+
+        ./uaputl.exe sys_cfg_pwk_cipher 32
+                Get AP's pairwise cipher for WPA2 protocol.
+
+        ./uaputl.exe sys_cfg_pwk_cipher
+                Get AP's protocol and corresponding pairwise cipher settings.
+
+sys_cfg_gwk_cipher
+------------------
+    "./uaputl.exe sys_cfg_gwk_cipher [GROUP_CIPHER]"
+
+    This command is used to set or get group cipher.
+
+    The supported options are:
+        GROUP_CIPHER:
+                        0                 None
+                        4                 TKIP
+                        8                AES CCMP
+        empty - Get group cipher settings.
+
+    Example:
+        ./uaputl.exe sys_cfg_gwk_cipher 8
+                Set AP's group cipher to AES CCMP.
+
+        ./uaputl.exe sys_cfg_gwk_cipher
+                Get AP's group cipher settings.
+
+sys_cfg_group_rekey_timer
+-------------------------
+    "./uaputl.exe sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]"
+
+    This command is used to set or get the AP group re-key time interval, in seconds.
+
+    The supported options are:
+        GROUP_REKEY_TIMER is represented in seconds. This is only applicable
+        		 if the protocol is WPA or WPA2. Value of 0 will disable group re-key.
+
+        empty - Get current group rekey timer
+
+    Example:
+	./uaputl.exe sys_cfg_group_rekey_timer 1800
+		Set AP's group re-key time interval to 1800 s
+
+	./uaputl.exe sys_cfg_group_rekey_timer
+		Get AP's group re-key time interval.
+
+sys_cfg_wpa_passphrase
+----------------------
+    "./uaputl.exe sys_cfg_wpa_passphrase [PASSPHRASE]"
+
+    This command is used to set or get the WPA or WPA2 passphrase.
+
+    If no arguments are given, this command returns the current WPA or WPA2
+    passphrase.
+    While setting, the maximum length of the passphrase can be 64 characters.
+
+    Example:
+	./uaputl.exe sys_cfg_wpa_passphrase 1234567890
+		Set AP's WPA or WPA2 passphrase to "1234567890"
+
+	./uaputl.exe sys_cfg_wpa_passphrase
+		Get AP's WPA or WPA2 passphrase.
+
+sys_cfg_max_sta_num
+-------------------
+    "./uaputl.exe sys_cfg_max_sta_num [STA_NUM]"
+
+    This command is used to set or get the maximum number of stations allowed to connect to uAP.
+
+    If no arguments are given, this command returns the configured maximum number of stations
+		allowed to connect to uAP and maximum number of stations supported.
+
+    Example:
+	./uaputl.exe sys_cfg_max_sta_num 2
+		Set AP's maximum station number to 2
+
+	./uaputl.exe sys_cfg_max_sta_num
+		Get AP's maximum station number configured and maximum station number supported.
+
+sys_cfg_retry_limit
+-------------------
+    "./uaputl.exe sys_cfg_retry_limit [RETRY_LIMIT]"
+
+    This command is used to set or get the retry limit to use for packet transmissions.
+
+    The maximum retry_limit allowed is 14.
+
+    If no arguments are given, this command returns the current retry limit value.
+
+    Example:
+	./uaputl.exe sys_cfg_retry_limit 2
+		Set AP's retry limit value to 2
+
+	./uaputl.exe sys_cfg_retry_limit
+		Get AP's retry limit value
+
+sys_cfg_sticky_tim_config
+-------------------------
+    "./uaputl.exe sys_cfg_sticky_tim_config [ENABLE] [<DURATION> <STICKY_BIT_MASK>]"
+
+    This command is used to set or get sticky TIM configuration.
+
+    ENABLE is used to enable or disable sticky TIM feature.
+    Following are the valid values of ENABLE
+    0- disable SticktyTIM
+    1- enable StickyTIM  (Both DURATION in beacons and STICKY_BIT_MASK must be provided)
+    2- enable StickyTIM  (enable sticky TIM without changing previous values of
+       DURATION and STICKY_BIT_MASK)
+
+    When bit 0 of STICKY_BIT_MASK is set, TIM bit is made sticky and when
+    cleared, normal TIM bit updates resume.
+    When bit 1 of STICKY_BIT_MASK is set, MoreData bit is made sticky and when
+    cleared, normal MoreData bit updates resume.
+    STICKY_BIT_MASK = 0 is NOT a valid configuration value.
+
+    If no argument is given, this command returns current sticky TIM configuration.
+
+    Example:
+    ./uaputl.exe sys_cfg_sticky_tim_config
+                Get sticky TIM configuration.
+
+    ./uaputl.exe sys_cfg_sticky_tim_config 0
+                Disable sticky TIM feature.
+
+    ./uaputl.exe sys_cfg_sticky_tim_config 1 30 1
+                Enable sticky TIM feature with DURATION of 30 beacons and
+                STICKY_BIT_MASK set to 1.
+
+sys_cfg_sticky_tim_sta_mac_addr
+-------------------------------
+    "./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]"
+
+    This command is used to set or get sticky TIM control parameter for associated station.
+
+    CONTROL when set to 1, sticky TIM bit for that station is activated.
+    When set to 0, sticky TIM bit for that station is deactivated.
+
+    If no argument is given, it returns sticky TIM configuration for all associated stations.
+    If only STA_MAC_ADDRESS is provided, it returns sticky TIM configartion for that station.
+
+    Example:
+    ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr
+            Get sticky TIM configuration for all associated stations.
+
+    ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr 00:50:43:20:11:22
+            Get control parameter for station 00:50:43:20:11:22.
+
+    ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr 1 00:50:43:20:11:22
+            Set control parameter for station with MAC address 00:50:43:20:11:22 to 1.
+
+    Note:TIM bit for an associated STA is made sticky only if both below mentioned
+         conditions are satisfied
+         1.Enable = 1 or 2 in most recently received sys_cfg_sticky_tim_config command, and
+         2.Control = 1 in most recently received sys_cfg_sticky_tim_sta_mac_addr
+           with this station MAC address.
+
+sys_cfg_2040_coex
+-------------------------------
+    "./uaputl.exe sys_cfg_2040_coex [ENABLE]"
+
+    This command is used to set or get 20/40 BSS coexistence configuration.
+
+    ENABLE when set to 0, disables 20/40 coex.
+    When set to 1, enables 20/40 coex.
+
+    If no argument is given, it returns 20/40 BSS coex configuration.
+
+    Example:
+    ./uaputl.exe sys_cfg_2040_coex
+            Get 20/40 BSS coexistence configuration.
+
+    ./uaputl.exe sys_cfg_2040_coex 0
+            Disable 20/40 BSS coexistence.
+
+    ./uaputl.exe sys_cfg_2040_coex 1
+            Enable 20/40 BSS coexistence.
+
+    Note:20/40 BSS coex configuration can be set only before starting BSS.
+
+sys_cfg_eapol_pwk_hsk
+---------------------
+    "./uaputl.exe sys_cfg_eapol_pwk_hsk [<TIMEOUT> <RETRIES>]"
+
+	This command is used to set or get pairwise handshake update timeout and
+	number of retries.
+
+	Both TIMEOUT and number of RETRIES should be provided for a 'set'.
+
+	If no arguments are given, this command returns timeout value and number
+	of
+	retries for pairwise key.
+
+	Example:
+	./uaputl.exe sys_cfg_eapol_pwk_hsk 50 2
+		Set AP's pairwise key timeout to 50ms and number of retries to 2.
+
+	./uaputl.exe sys_cfg_eapol_pwk_hsk
+		Get AP's pairwise key timeout and number of retries.
+
+sys_cfg_eapol_gwk_hsk
+---------------------
+	"./uaputl.exe sys_cfg_eapol_gwk_hsk [<TIMEOUT> <RETRIES>]"
+
+	This command is used to set or get groupwise handshake update timeout and
+	number of retries.
+
+	Both TIMEOUT and number of RETRIES should be provided for a	'set'.
+
+	If no arguments are given, this command returns timeout	value and number
+	of retries for groupwise key.
+
+	Example:
+	./uaputl.exe sys_cfg_eapol_gwk_hsk 50 2
+	Set AP's groupwise key timeout to 50ms and number of retries to 2.
+
+	./uaputl.exe sys_cfg_eapol_gwk_hsk
+	Get AP's groupwise key timeout and number of retries.
+
+sta_filter_table
+----------------
+    "./uaputl.exe sta_filter_table <FILTERMODE> [<MACADDRESS_LIST>]"
+
+    This command is used to get or set the client station MAC address
+    filter table.
+
+    The supported options are:
+    FILTERMODE : 0 - Disable filter table
+                 1 - Allow mac address specified in the allowed list
+                 2 - Block MAC addresses specified in the  banned list
+    MACADDRESS_LIST is the list of MAC addresses to be acted upon. Each
+    MAC address must be separated with a space. Maximum of 16 MAC addresses
+    are supported.
+
+    empty - Get current client station MAC address filter table.
+
+    Example:
+	./uaputl.exe sta_filter_table 0
+		Disable filter table
+
+	./uaputl.exe sta_filter_table 1 00:50:43:20:aa:bb
+		Set AP's filter mode to allow, only MAC address "00:50:43:ab:bb" will be allowed.
+
+	./uaputl.exe sta_filter_table
+		Get AP's filter table settings.
+
+regrdwr
+-------
+     "./uaputl.exe regrdwr <TYPE> <OFFSET> [value]"
+
+     These commands are used to read the MAC, BBP and RF registers from the card.
+     TYPE can take 3 values, 1 - read/write MAC register
+                             2 - read/write BBP register
+                             3 - read/write RF  register
+
+     OFFSET specifies the offset location that is to be read.
+     This parameter can be specified either in decimal or in hexadecimal (by preceding the number with a "0x").
+
+     value if specified, then that value will be written to that offset in the specified register. Value should be
+     specified in hexadecimal.
+
+     Example:
+	./uaputl.exe regrdwr 1 0xa123
+		read MAC register 0xa123
+
+	./uaputl.exe regrdwr 1 0xa123 0xaa
+		write 0xaa to MAC register 0xa123
+
+        ./uaputl.exe regrdwr 2 0x0123
+		read BBP register 0x0123
+
+	./uaputl.exe regrdwr 2 0x0123 0xaa
+		write 0xaa to BBP register 0x0123
+
+        ./uaputl.exe regrdwr 3 0x0123
+		read RF register 0x0123
+
+	./uaputl.exe regrdwr 3 0x0123 0xaa
+		write 0xaa to RF register 0x0123
+
+memaccess
+---------
+ 	"./uaputl.exe memaccess <ADDR> [value]"
+	This commands is used to read/write to a memory address
+
+	ADDR specifies the address of the location that is to be read/write
+	This parameter can be specified either in decimal or in hexadecimal (by preceding the number with a "0x").
+
+	value if specified, then that value will be written to that address in the specified register.
+
+	Example:
+		./uaputl.exe memaccess 0xc00153e4
+			read contents of memory location 0xc00153e4
+
+
+		./uaputl.exe memaccess 0xc00153e4 0xaabbccdd
+			write value 0xaabbccdd to  memory location 0xc00153e4
+
+rdeeprom
+--------
+    "./uaputl.exe rdeeprom <offset> <bytecount>"
+
+    This command is used to read bytes from offset location on
+    EEPROM
+
+    offset: 0,4,8,..., multiple of 4
+    bytecount: 4-20, multiple of 4
+
+   	Example:
+    ./uaputl.exe rdeeprom 200 12
+        read 12 bytes from offset 200 ON EEPROM
+
+cfg_data
+--------
+ 	"./uaputl.exe cfg_data <type> [*.conf]"
+
+    This command is used to set/get the configuration data to/from the firmware.
+
+    type: 2 -- cal data
+
+   	Example:
+        ./uaputl.exe cfg_data 2 cal_data.conf
+            read cal_data from cal_data.conf and download to firmware.
+        ./uaputl.exe cfg_data 2
+            read cal_data from firmware
+
+sys_cfg_80211d
+--------------
+    "./uaputl.exe sys_cfg_80211d [state STATE] [country COUNTRY]"
+    This command is used to set/get 802.11D specific parameters.
+    If no parameters are provided, this command returns state, country and
+    domain information.
+
+    Allowed values for state are 0 for disable and 1 for enable.
+    COUNTRY is a two letter string input (derived from ISO 3166 code;
+    http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
+    )
+
+    Countries are mapped with specific domain in file "80211d_domain.conf". In
+    order to set customize band setting, user can modify 80211d_domain.conf
+    file.
+
+    Example:
+    ./uaputl.exe sys_cfg_80211d state 0
+        To-disable
+
+    ./uaputl.exe sys_cfg_80211d state 1
+        To-enable
+
+    ./uaputl.exe sys_cfg_80211d country IN
+        for using country as INDIA
+
+    ./uaputl.exe sys_cfg_80211d state 1 country US
+        for enabling and setting country in single command.
+
+uap_stats
+---------
+    "./uaputl.exe uap_stats"
+    This command is used to get uAP statistics.
+
+    Example:
+    ./uaputl.exe uap_stats
+
+pscfg
+---------
+    "./uaputl.exe pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE]
+
+    This command is used to set or get the AP's power mode and power save params.
+
+    The supported options are:
+        MODE :     0 - disable power mode
+                   2 - enable inactivity based power save mode
+
+        PS PARAMS:
+            CTRL:  0 - disable protection frame Tx before PS
+                   1 - enable protection frame Tx before PS
+            INACTTO: Inactivity timeout in microseconds, default value is 200000 us
+            MIN_SLEEP: Minimum sleep duration in microseconds, default value 17000 us
+            MAX_SLEEP: Maximum sleep duration in microseconds, default value 17000 us
+			The value of MIN_SLEEP should be >= 5000 us.
+			The value of MAX_SLEEP should be <= beacon interval(when ctrl: 0).
+			The value of MAX_SLEEP should be <= 32000 us(when ctrl: 1).
+
+            MIN_AWAKE: Minimum awake duration in microseconds, default value is 2000 us
+            MAX_AWAKE: Maximum awake duration in microseconds, default value is 2000 us
+			The value of MIN_AWAKE should be >= 2000 us.
+            MIN_AWAKE,MAX_AWAKE only valid when MODE is set to inactivity based power save mode.
+
+
+	empty - Get current power mode and power save params.
+
+    Example:
+	./uaputl.exe pscfg 0
+		Disable AP's power mode.
+
+   	./uaputl.exe pscfg 2
+		Enable inactivity based power save mode.
+
+   	./uaputl.exe pscfg 2 1 400000 20000 20000 10000 10000
+		Enable inactivity based power save mode, enable protection, set inactivity timeout 400000 us
+        set minimum sleep duration to 20000 us, maximum sleep duration to 20000 us
+        and set minimum awake duration to 10000us, maximum awake duration to 10000 us
+
+	./uaputl.exe pscfg
+		Get current AP's power mode and power save params.
+
+hscfg
+-----
+    ./uaputl.exe hscfg [condition [[GPIO# [gap]]]]
+	This command is used to configure the host sleep parameters.
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap) parameters for set. If no parameter provided,
+	get is performed.
+
+	where Condition is:
+		bit 0 = 1   -- broadcast data
+		bit 1 = 1   -- unicast data
+		bit 2 = 1   -- mac event
+		bit 3 = 1   -- multicast data
+		bit 6 = 1  --  Wakeup when mgmt frame received.
+
+	The host sleep mode will be cancelled if condition is set to 0xffff.
+	The default is 0x7.
+
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+	GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead).
+	The default is 0xff.
+
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff
+	for special setting (host acknowledge required) when GPIO is used to wakeup host.
+	The default is 200.
+
+	Examples:
+		./uaputl.exe hscfg              : Get current host sleep mode
+		./uaputl.exe hscfg 0xffff       : Cancel host sleep mode
+		./uaputl.exe hscfg 3            : Broadcast and unicast data
+		                                  Use GPIO and gap set previously
+		./uaputl.exe hscfg 2 3          : Unicast data
+		                                  Use GPIO 3 and gap set previously
+		./uaputl.exe hscfg 2 1 0xa0     : Unicast data
+		                                  Use GPIO 1 and gap 160 ms
+		./uaputl.exe hscfg 2 0xff       : Unicast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap set previously
+		./uaputl.exe hscfg 4 3 0xff     : MAC event
+		                                  Use GPIO 3
+		                                  Special host sleep mode
+		./uaputl.exe hscfg 1 0xff 0xff  : Broadcast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap 255ms
+
+hssetpara
+---------
+    ./uaputl.exe hssetpara condition [[GPIO# [gap]]]
+    This command is used to configure the host sleep parameters.
+
+    Note:
+    1) The usages of parameters are the same as "hscfg" command.
+    2) The parameters will be saved in the driver and be used when host suspends.
+
+sta_deauth_ext
+--------------
+    "./uaputl.exe sta_deauth_ext <STA_MAC_ADDRESS><REASON_CODE>"
+
+    This command is used to de-authenticate a client station with specific reason code.
+
+    Example:
+        ./uaputl.exe sta_deauth_ext 00:50:43:20:34:58  4
+            deauth station 00:50:43:20:34:58 with IEEE reason code 4 (Disassociated due to inactivity)
+
+mic_err
+-------
+    "./uaputl.exe mic_err <STA_MAC_ADDRESS>"
+
+    This command is used to report station mic error.
+
+    Example:
+        ./uaputl.exe mic_err 00:50:43:20:34:58
+            report mic err for station 00:50:43:20:34:58
+
+key_material
+------------
+    "./uaputl.exe key_material <MAC_ADDRESS> <KEY> [KEY_ID]"
+
+    This command is used to set key. Get operation is not supported.
+
+        MAC_ADDRESS: station mac address while setting station unicast key
+                     ff:ff:ff:ff:ff:ff while setting multicast key
+
+        KEY: hex string, allowed length should be 32 or 64.
+        KEY_ID: default value is 0.
+
+    Example:
+        ./uaputl.exe key_material ff:ff:ff:ff:ff:ff 12345678901234567890123456789012 1
+            set group key, key value is "12345678901234567890123456789012", key id is 1
+
+        ./uaputl.exe key_material 00:50:43:20:34:58 1234567890123456789012345678901234567890123456789012345678901234
+            set station 00:50:43:20:34:58 unicast key,
+            key value is "1234567890123456789012345678901234567890123456789012345678901234"
+
+sys_cfg_custom_ie
+-----------------
+    "./uaputl.exe sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]"
+
+    This command is used to set or get custom IEs for management frames.
+
+    The supported options are:
+        INDEX:       0 - IE Index is 0
+                     1 - IE Index is 1
+                     2 - IE Index is 2
+                     MAX IE Index depends on device memory.
+
+               	    -1 - Append/Delete IE automatically
+                         Delete will delete the IE from the matching IE buffer
+                         Append will append the IE to the buffer with the same mask
+        MASK :       Management subtype mask value as per bit definitions
+	                   :  Bit 0 - Association request.
+	                   :  Bit 1 - Association response.
+	                   :  Bit 2 - Reassociation request.
+	                   :  Bit 3 - Reassociation response.
+	                   :  Bit 4 - Probe request.
+	                   :  Bit 5 - Probe response.
+	                   :  Bit 8 - Beacon.
+        MASK :       MASK = 0 to clear the mask and the IE buffer
+
+        IEBuffer:    IE buffer to set in hexadecimal bytes.
+	                  The Buffer should not be space separated.
+	                  ( Maximum length = 256 bytes )
+        empty - Get IE buffer, subtype mask settings for all the indices [0-3].
+        INDEX - Only INDEX will get the IE buffer configured for the particular
+                Index.
+
+    Example:
+	./uaputl.exe sys_cfg_custom_ie
+		Get IE buffer, subtype mask settings for all indices.
+
+	./uaputl.exe sys_cfg_custom_ie 1
+		Get IE buffer and subtype mask WEP key setting for the Index = 1.
+
+	./uaputl.exe sys_cfg_custom_ie 2 0
+		Clear IE buffer and mask value for Index = 2.
+
+	./uaputl.exe sys_cfg_custom_ie 3 0x101 0xdd051234567890
+		Set IE buffer and mask value for Index = 3.
+
+	./uaputl.exe sys_cfg_custom_ie -1 0x101 0xdd051234567890
+		Append the specified IEBuffer at index with mask value of 0x101
+
+	./uaputl.exe sys_cfg_custom_ie -1 0 0xdd051234567890
+		Delete the specified IEBuffer from all the IEs.
+
+	./uaputl.exe sys_cfg_custom_ie 2 0 0xdd051234567890
+		Delete the specified IEBuffer from the IEs at index 2.
+
+coex_config
+-----------
+    "./uaputl.exe coex_config [CONFIG_FILE]"
+    This command is used to set or get the BT coex configuration settings.
+
+    The supported options are:
+        CONFIG_FILE is file contain all the BT coex settings.
+        empty - Get current BT coex settings
+
+    Example:
+	./uaputl.exe coex_config
+		Get current BT coex settings.
+
+	./uaputl.exe coex_config uapcoex.conf
+		Load BT coex configuration settings from uapcoex.conf file and set.
+
+sys_cfg_wmm
+-----------
+    "./uaputl.exe sys_cfg_wmm [qosinfo=<qosinfo>]
+                              [0]
+                              [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+                              [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+                              [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+                              [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]"
+
+    This command can be used set/get beacon WMM parameters
+
+    The supported option are:
+        qosinfo: qos information. User can set only MSB. Valid values are 0x80 and 0x00.
+        Lower 4 bits are managed by FW. Hence, value read for qosinfo may have
+        lower 4 bits non-zero.
+
+        AC_BE: 0
+        AC_BK: 1
+        AC_VI: 2
+        AC_V0: 3
+        AIFSN: AIFSN value
+        ECW_MAX: ECW max
+        ECW_MIN: ECW min
+        TX_OP: TXOP Limit
+        empty - Get current WMM parameters
+        When all the parameter are 0, wmm will be disabled.
+
+        Example:
+        ./uaputl.exe sys_cfg_wmm 0 3 10 4 0
+           Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_wmm 1 7 10 4 0
+           Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_wmm 2 2 4 3 94
+           Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+
+        ./uaputl.exe sys_cfg_wmm 3 2 3 2 47
+           Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_wmm
+            Get current wmm parameters
+
+        ./uaputl.exe sys_cfg_wmm 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_wmm qosinfo=0x80 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Enable wmm PS mode.
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_wmm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        ./uaputl.exe sys_cfg_wmm 0
+            Disable wmm
+
+sys_cfg_ap_wmm
+-----------
+    "./uaputl.exe sys_cfg_ap wmm [0]
+                                 [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+                                 [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+                                 [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+                                 [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]"
+
+    This command can be used set/get AP WMM parameters
+
+    The supported option are:
+        AC_BE: 0
+        AC_BK: 1
+        AC_VI: 2
+        AC_V0: 3
+        AIFSN: AIFSN value
+        ECW_MAX: ECW max
+        ECW_MIN: ECW min
+        TX_OP: TXOP Limit
+        empty - Get current AP WMM parameters
+        When all the parameter are 0, AP wmm will be disabled.
+
+        Example:
+        ./uaputl.exe sys_cfg_ap_wmm 0 3 10 4 0
+           Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_ap_wmm 1 7 10 4 0
+           Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_ap_wmm 2 2 4 3 94
+           Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+
+        ./uaputl.exe sys_cfg_ap_wmm 3 2 3 2 47
+           Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_ap_wmm
+            Get current AP wmm parameters
+
+        ./uaputl.exe sys_cfg_ap_wmm 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_ap_wmm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        ./uaputl.exe sys_cfg_ap_wmm 0
+            Disable AP wmm
+
+addbapara
+---------
+    "./uaputl.exe addbapara [timeout txwinsize rxwinsize txamsdu rxamsdu]"
+	This command can be used to update the default ADDBA parameters.
+
+	The supported options are:
+	    timeout - This is the block ack timeout for ADDBA request.
+		    0 : Disable (recommended for throughput test)
+		    1 - 65535 : Block Ack Timeout in TU
+	    txwinsize - Buffer size for ADDBA request. (32 is default value)
+	    rxwinsize - Buffer size for ADDBA response. (16 is default value)
+	    txamsdu - amsdu support for ADDBA request. (1 is default value)
+		    0 : Disable amsdu in ADDBA request.
+		    1 - Enable amsdu in ADDBA request.
+	    rxamsdu - amsdu support for ADDBA response. (1 is default value)
+		    0 : Disable amsdu in ADDBA response.
+		    1 - Enable amsdu in ADDBA response.
+        empty - Get current ADDBA parameters.
+
+	Current window size limit for Tx as well as Rx is 1023.
+
+	Example:
+	./uaputl.exe addbapara
+        Get the current addba params
+	./uaputl.exe addbaparam 1000 64 8 0 0
+        This will change the ADDBA timeout to (1000 * 1024) us,	txwinsize to 64 and rxwinsize to 8
+        and disable AMSDU in ADDBA request/response.
+
+	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 txamdsdu/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.
+
+sys_cfg_11n
+-----------
+    "./uaputl.exe sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_CAP]"
+    This command can be used set/get 802.11n parameters.
+
+    The supported option are:
+        ENABLE: 0 - disable 802.11n in uap
+                1 - enable 802.11n in uap
+		Note: If 802.11n is disabled, 802.11ac MUST be disabled at the same time
+        HTCAP: HT Capabilities info (default value is 0x111c)
+               Bit 15-13: Reserved set to 0
+               Bit 12: DSS/CCK mode in 40MHz enable/disable
+               Bit 11-10: Reserved set to 0
+               Bit 9-8: Reserved set to 0x01
+               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
+        AMPDU: A-MPDU Parameter (default value is 0x03)
+               Bit 7-5: Reserved set to 0
+               Bit 4-2: Minimum MPDU Start spacing
+                        Set to 0 for no restriction
+                        Set to 1 for 1/4 us
+                        Set to 2 for 1/2 us
+                        Set to 3 for 1 us
+                        Set to 4 for 2 us
+                        Set to 5 for 4 us
+                        Set to 6 for 8 us
+                        Set to 7 for 16 us
+               Bit 1-0: Max A-MPDU length
+        TXBFCAP: TX Beamforming capabilities
+               Bit 0    : Implicit TX BF receiving capable
+               Bit 1    : RX staggered sounding capable
+               Bit 2    : TX staggered sounding capable
+               Bit 3    : RX NDP capable
+               Bit 4    : TX NDP capable
+               Bit 5    : Implicit TX BF capable
+               Bit 6-7  : Calibration
+                       0: - not supported
+                       1: - STA can respond to a calibration request using
+                            the CSI Report, but cannot initiate calibration
+                       2: - reserved
+                       3: - STA can both initiate and respond to a calibration request
+               Bit 8    : Explicit CSI TX BF capable
+               Bit 9    : Explicit non-compressed steering capable
+               Bit 10   : Explicit compressed steering capable
+               Bit 11-12: Explicit TX BF CSI feedback
+                       0: - not supported
+                       1: - delayed feedback
+                       2: - immediate feedback
+                       3: - delayed and immediate feedback
+               Bit 13-14: Explicit non-compressed BF feedback capable
+                       0: - not supported
+                       1: - delayed feedback
+                       2: - immediate feedback
+                       3: - delayed and immediate feedback
+               Bit 15-16: Explicit compressed BF feedback capable
+                       0: - not supported
+                       1: - delayed feedback
+                       2: - immediate feedback
+                       3: - delayed and immediate feedback
+               Bit 17-18: Minimal grouping
+                       0: - no grouping (STA supports groups of 1)
+                       1: - groups of 1, 2
+                       2: - groups of 1, 4
+                       3: - groups of 1, 2, 4
+               Bit 19-20: CSI number of beamformer antennas supported
+                       0: - single TX antenna sounding
+                       1: - 2 TX antenna sounding
+                       2: - 3 TX antenna sounding
+                       3: - 4 TX antenna sounding
+               Bit 21-22: Non-compressed steering number of beamformer antennas supported
+                       0: - single TX antenna sounding
+                       1: - 2 TX antenna sounding
+                       2: - 3 TX antenna sounding
+                       3: - 4 TX antenna sounding
+               Bit 23-24: Compressed steering number of beamformer antennas supported
+                       0: - single TX antenna sounding
+                       1: - 2 TX antenna sounding
+                       2: - 3 TX antenna sounding
+                       3: - 4 TX antenna sounding
+               Bit 25-26: CSI max number of rows beamformer supported
+                       0: - single row of CSI
+                       1: - 2 rows of CSI
+                       2: - 3 rows of CSI
+                       3: - 4 rows of CSI
+               Bit 27-28: Channel estimation capability
+                       0: - 1 space time stream
+                       1: - 2 space time streams
+                       2: - 3 space time streams
+                       3: - 4 space time streams
+               Bit 29-31: Reserved
+        HT_MCS_MAP: MCS rate bitmap
+               Bit 0-7   : MCS_SET_0
+               Bit 15-8  : MCS_SET_1
+        empty - Get current 802.11n parameters.
+
+        Example:
+        ./uaputl.exe sys_cfg_11n 1 0x117e 3
+            enable 802.11n, and set HT Capabilities info to 0x117e, and A-MPDU Parameter to 0x03
+        ./uaputl.exe sys_cfg_11n 1 0x117e 3 0xFFFFFFFF
+            enable 802.11n, and set HT Capabilities info to 0x117e, A-MPDU
+            Parameter to 0x03 and TX Beamforming capabilities to 0xFFFFFFFF
+        ./uaputl.exe sys_cfg_11n 1 0x117e 3 0xFFFFFFFF 0x00100023
+            enable 802.11n, and set HT Capabilities info to 0x117e, A-MPDU
+            Parameter to 0x03, TX Beamforming capabilities to 0xFFFFFFFF and
+            MCS rate bitmap to 0x00100023.
+        ./uaputl.exe sys_cfg_11n 0
+            disable 802.11n in uap
+        ./uaputl.exe sys_cfg_11n
+            Get current 802.11n parameters
+
+aggrpriotbl
+-----------
+        "./uaputl.exe aggrpriotbl <m0> <n0> <m1> <n1> ... <m7> <n7>"
+        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)
+
+        The supported option are:
+            <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.
+
+        empty - Get current priority table for AMPDU/AMSDU traffic.
+
+        Example:
+        ./uaputl.exe 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
+
+	    ./uaputl.exe 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.
+
+	    ./uaputl.exe 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 issued in disconnected state.
+
+addbareject
+-----------
+        "./uaputl.exe addbareject <m0> <m1> ... <m7>"
+        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.
+
+        The supported option are:
+            <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.
+        empty - Get current addbareject table for all the TIDs.
+
+        Example:
+        ./uaputl.exe addbareject
+            This command will get the current table.
+	        [0 0 0 0 0 0 1 1]. ADDBA would be accepted for all TIDs except for TID [6,7].
+	        This is the default state.
+
+        ./uaputl.exe 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]
+
+	    ./uaputl.exe 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 issued in disconnected state.
+
+sys_cfg_tdls_ext_cap
+--------------------
+
+    "./uaputl.exe sys_cfg_tdls_ext_cap [CONFIG_FILE]"
+
+    This command is used to set/get TDLS extended capability settings.
+
+    If CONFIG_FILE is provided, a SET is performed , else a GET is performed.
+
+    Examples:
+        ./uaputl.exe sys_cfg_tdls_ext_cap config/tdls_ext_cap.conf
+        Set TDLS extended capability parameters in the config file.
+        ./uaputl.exe sys_cfg_tdls_ext_cap
+        Get TDLS extended capability parameters.
+
+    "./uaputl.exe skip_cac [<MODE>]"
+
+    This command is used to set/get SKIP_CAC feature. If enabled then next BSS
+    start would skip the channel availability check (CAC). The mode will be
+    disabled automatically once BSS_START is performed.
+
+    MODE : 0 - Disable skip CAC mode
+	   1 - Enable skip CAC mode
+
+    eg.,
+	./uaputl.exe skip_cac ==> GET current configured mode
+	./uaputl.exe skip_cac 1 ==> enables skip_cac mode
+	./uaputl.exe skip_cac 0 ==> disable skip_cac mode
+
+httxbfcfg
+---------
+	"./uaputl.exe httxbfcfg <ACTION> [ACT_DATA]"
+
+	This command is used to configure the TX beamforming options.
+
+	The supported options are:
+		ACTION: 0 - Control global parameters for beamforming
+                1 - Performs NDP Sounding for PEER
+		        2 - TX BF interval in milliseconds
+		        3 - Enable/Disable beamforming/sounding for the indicated peer.
+		        4 - TX BF SNR Threshold for peer
+		ACT_DATA: Specific data for the above actions
+                  For ACTION 0 - Beamforming enable/disable, sounding enable/disable,
+                                 FB type, snr_threshold, sounding interval, Beamformig mode
+		          For ACTION 1 - PEER MAC and status
+		          For ACTION 2 - TX BF interval
+		          For ACTION 3 - PEER MAC
+		          For ACTION 4 - PEER MAC and SNR
+		          empty - Get action specific settings
+
+	Examples:
+		./uaputl.exe httxbfcfg 0                          : Get current global configuration parameter
+		./uaputl.exe httxbfcfg 2 00:50:43:20:BF:64        : Get the TX BF periodicity for a given peer
+		./uaputl.exe httxbfcfg 3                          : Get the list of MAC addresses that have
+		                                                      beamforming and/or sounding enabled
+		./uaputl.exe httxbfcfg 4                          : Get the list of PEER MAC, SNR tuples
+		                                                      programmed into the firmware.
+		./uaputl.exe httxbfcfg 0 0 0 3 10 500 5           : Disable beamforming, sounding, set FB type
+		                                                      to 3, snr threshold to 10, sounding interval
+		                                                      to 500 ms and beamforming mode to 5
+		./uaputl.exe httxbfcfg 1 00:50:43:20:BF:64        : Perform NDP Trigger sounding to peer
+		                                                      00:50:43:20:BF:64
+		./uaputl.exe httxbfcfg 2 00:50:43:20:BF:64 500    : Set TX BF periodicity for peer 00:50:43:20:BF:64
+		                                                      to 500 milliseconds
+		./uaputl.exe httxbfcfg 3 00:50:43:20:BF:43 1 0 3  : Enable beamforming, disable sounding and set
+		                                                      FB type to 3 for peer 00:50:43:20:BF:43
+		./uaputl.exe httxbfcfg 4 00:50:43:20:BF:24 43     : Set TX BF SNR threshold to peer
+
+
+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-10: Reserved set to 0
+        Bit 9-8: Rx STBC set to 0x01
+        BIT9 BIT8  Description
+        0    0     No spatial streams
+        0    1     One spatial streams supported
+        1    0     Reserved
+        1    1     Reserved
+		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.
+
+	Example:
+		./uaputl.exe -i uapX httxcfg
+		This will display HT Tx configuration.
+
+		./uaputl.exe -i uapX httxcfg 0x62
+		This will enable 20/40 and Short GI but will disable Green field.
+
+		./uaputl.exe -i uapX httxcfg 0x30
+		This will enable Short GI 20 Mhz and Green field.
+
+	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.
+
+htstreamcfg
+	This command is used to set/get HT stream configuration.
+	The setting only takes effect in next association.
+
+	Usage:
+		./uaputl.exe -i uapX htstreamcfg [n]
+
+	where <n>
+		0x11: HT stream 1x1 mode
+		0x22: HT stream 2x2 mode
+
+	Examples:
+		./uaputl.exe -i uapX htstreamcfg        : Get current setting
+		./uaputl.exe -i uapX htstreamcfg 0x11   : Set HT stream 1x1 mode
+		./uaputl.exe -i uapX htstreamcfg 0x22   : Set HT stream 2x2 mode
+
+deepsleep
+---------
+    "./uaputl.exe deepsleep [MODE] [IDLE_TIME]"
+    This command is used to set/get auto deep sleep mode.
+
+    The supported option are:
+        [MODE]: Enable/disable auto deep sleep mode (1/0)
+        [IDLE_TIME]: Idle time in milliseconds after which firmware will put the device
+                    in deep sleep mode. Default value is 100 ms.
+        empty - Get current deep sleep mode.
+
+    Example:
+    ./uaputl.exe deepsleep          : Display auto deep sleep mode
+    ./uaputl.exe deepsleep 1        : Enable auto deep sleep mode, idle time unchanged
+    ./uaputl.exe deepsleep 0        : Disable auto deep sleep mode
+    ./uaputl.exe deepsleep 1 500    : Enable auto deep sleep mode with idle time 500 ms
+
+    Note:
+            Deepsleep must be disabled before changing idle time.
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+    "./uaputl.exe sdcmd52rw <function number> <register address> [value]"
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+	Examples:
+    ./uaputl.exe sdcmd52rw 1 3          : Issue cmd52 to read function 1, register 3.
+    ./uaputl.exe sdcmd52rw 1 1 0x3f     : Issue cmd52 to write function 1, register 1
+                                          with value 0x3f.
+
+txpwrlimit_cfg_get
+txpwrlimit_2g_cfg_set
+txpwrlimit_5g_cfg_set
+------------------
+    This command is used to set/get the configuration data of Tx power limitation.
+    Note: The configuration set should be issued when no STA is connected.
+
+    Examples:
+        ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get
+        ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set
+        ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set
+
+rxpktcoal_cfg
+-------------
+   "./uaputl.exe rxpktcoal_cfg [PKT-THRESHOLD] [TIMEOUT]"
+
+	This is used to get/set RX packet coalescing paramters
+
+    The supported option are:
+        [PKT-THRESHOLD]: count after which packets would be sent to host. Valid values 1-7
+        [TIMEOUT]: timeout in ms after which packets would be sent to host. Valid values 1-4
+        Coalescing is disabled if both or either of packet_thershold and delay is zero
+
+        RX packet coalescing parameters can be changed only when device is in
+        idle state i.e. all interfaces are disconnected.
+
+    Example:
+    ./uaputl.exe rxpktcoal_cfg      : Display RX packet coalescing settings
+    ./uaputl.exe rxpktcoal_cfg 5 1  : Enable RX packet coalescing: packet count 5, delay 1.
+    ./uaputl.exe rxpktcoal_cfg 0 0  : Disable RX packet coalescing.
+
+tx_data_pause
+-------------
+  "./uaputl.exe tx_data_pause [ENABLE][TX_BUF_CNT]"
+
+    This command is used to set/get tx data pause settings.
+
+    The supported option are:
+        [ENABLE]: Enable/disable pause tx events from firmware to host.
+        [TX_BUF_CNT]: Max number of TX buffers allowed for all PS clients
+        empty - Get current tx data pause settings
+
+    Example:
+    ./uaputl.exe tx_data_pause      : Display tx data pause settings
+    ./uaputl.exe tx_data_pause 1    : Enable pause tx event, max tx buffer number unchanged.
+    ./uaputl.exe tx_data_pause 0    : Disable pasue tx event, max tx buffer number unchanged.
+    ./uaputl.exe tx_data_pause 1 15 : Enable pause tx event, with max tx buffer number 15.
+
+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
+		3: configuration of VHT capabilities (uAP only)
+	Note: For the UAP, only 3 is supported for txrx.
+
+	where [l] is <bwcfg>
+	<bwcfg> - This parameter specifies the bandwidth (BW) configuration
+		  applied to the vhtcfg.
+	If <txrx> is 3 (For uAP),
+		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.
+
+	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.
+
+	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:
+		./uaputl.exe -i uapX vhtcfg 2 3            : Get current VHT configuration in 5GHz for the uAP.
+		./uaputl.exe -i uapX 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.
+		./uaputl.exe -i uapX 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.
+
+dfstesting
+----------
+  "./uaputl.exe dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]"
+
+    This command is used to set/get DFS testing settings.
+
+    The supported option are:
+        <user_cac_pd>: user-configured Channel Availability Check in msec
+                       0 = disable, use default period (60000)
+                       1-65535 = enable with that period
+        <user_nop_pd>: user-configured Non-Occupancy Period in sec
+                       0 = disable, use default period (1800)
+                       1-65535 = enable with that period
+        <no_chan_change>: enable/disable no channel change on radar
+                          0 = disable, 1 = enable (overrides below)
+        <fixed_chan_num>: user-configured channel to change to on radar
+                          0 = disable, 1-255 = enable with that channel
+                          (channel validity for region, etc. is not checked)
+                          (only takes effect if no_chan_change = 0)
+
+    Example:
+    ./uaputl.exe dfstesting             : Get current dfstesting settings
+    ./uaputl.exe dfstesting 2000 0 0 0  : user_cac=2sec, others disabled/default
+    ./uaputl.exe dfstesting 0 0 1 0     : only no_chan_change enabled
+    ./uaputl.exe dfstesting 0 120 0 64  : user_nop=2min, force chan 64 on radar
+
+cscount
+---------------
+
+  "./uaputl.exe cscount [<channel_switch_count>]"
+
+    This command is used to configure the number of beacons AP sends with channel switch IE, before channel change due to
+    radar detection. If not configured, <channel_switch_count> is set to 5 by default.
+
+    The supported options are:
+        <channel_switch_count>: user configured channel switch count
+                                5-20 = configure with that value
+
+   Example:
+   ./uaputl.exe cscount         : Get user configured channel switch count value
+   ./uaputl.exe cscount 10      : Set channel switch count to 10
+
+
+mgmtframectrl
+-------------
+  "./uaputl.exe mgmtframectrl [MASK]"
+
+    This command is used to set/get management frame control mask.
+
+    where the parameter [MASK] is the bit mask of management frame reception.
+        Following are the bit definitions.
+        Bit 0 : Association Request
+        Bit 1 : Association Response
+        Bit 2 : Re-Association Request
+        Bit 3 : Re-Association Response
+        Bit 4 : Probe Request
+        Bit 5 : Probe Response
+        Bit 8 : Beacon Frames
+
+    Example:
+    ./uaputl.exe mgmtframectrl 0x101
+    Set management frame control mask to 0x101.
+
+restrict_client_mode
+--------------------
+	"./uaputl.exe restrict_client_mode [<ENABLE> [MODE_CONFIG]]"
+
+	This command is used to set/get the mode in which the ex-Stations can connect to the uAP.
+	If no arguments are given, this command returns the current configuration.
+	By default this feature will be disabled.
+	[ENABLE]:
+		1: Enable the feature.
+		0: Disable the feature.
+	[MODE_CONFIG]: config mode.
+		Bit 0:	B only Mode.
+		Bit 1:	A only Mode.
+		Bit 2:	G only Mode.
+		Bit 3:	N only Mode.
+		Bit 4:	AC only Mode.
+
+	Example:
+	./uaputl.exe restrict_client_mode 1 0x8.
+	Only N mode clients will be able to connect. Association will fail for other clients.
+
+	./uaputl.exe restrict_client_mode 0.
+	This feature is disabled.
+
+	Note:
+	The set operation should be performed before bss is started.
+	User should make sure that the mode advertized by uAP in beacons
+	(i.e. combination of supported/extended rates IE and capability IEs)
+	is superset of the mode allowed for ex-STA associations using this TLV.
+
+uap_oper_ctrl
+-------------
+	"./uaputl.exe uap_oper_ctrl [control] [chanopt] [bandcfg] [channel]"
+
+	This command is used to set/get uAP operation control when in-STA disconnected with ext-AP.
+	If no arguments are given, this command returns the current configuration.
+
+	The supported options are:
+		<control> : 0  default, do nothing
+				   2  uAP stops and restart automatically
+		<chanopt> Specify which channel should be used when uap restarts automatically
+				   1: uap restarts on default 2.4G/channel 6
+				   2: uap restart on band/channel configured by driver previously
+				   3: uap restart on band/channel configured by parameter bandcfg/channel
+		<bandcfg> This parameter specifies the bandwidth when chanopt is 3
+				   0: 20Mhz
+				   2: 40Mhz
+				   3: 80Mhz
+		<channel> This parameter specifies the channel will be used when chanopt is 3
+
+		Example:
+		./uaputl.exe uap_oper_ctrl  2 1
+		uap stops and restart automatically when in-STA disconnects with ext-AP,
+		and restart on default 2.4G/channel 6.
+
+		./uaputl.exe uap_oper_ctrl  2 2
+		uap stops and restart automatically when in-STA disconnects with ext-AP,
+		and restart on band/channel configured by driver previously.
+
+		./uaputl.exe uap_oper_ctrl  2 3 2 36
+		uap stops and restart automatically when in-STA disconnects with ext-AP,
+		and restart on channel 36, bandwidth 40.
+
+		./uaputl.exe uap_oper_ctrl  0
+		when in-STA disconnects with ext-AP, uap will stay on current operation channel.
+
+		./uaputl.exe uap_oper_ctrl
+		Get current uap operation control setting.
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANEVENT
+
+NAME
+mlanevent.exe
+
+This tool can be used to listen for and obtain events from the uAP driver
+through the netlink layer.
+
+----------------
+Supported events
+----------------
+STA_DEAUTH
+STA_ASSOC
+BSS_START
+BSS_IDLE
+BSS_ACTIVE
+
+-----------------
+Details of events
+-----------------
+
+STA_DEAUTH
+----------
+    For this event, the following information is shown:
+        + Deauthenticated STA MAC address.
+        + Reason for deauthentication.
+
+STA_ASSOC
+---------
+    For this event, the following information is shown:
+        + STA MAC address.
+
+BSS_START
+---------
+    For this event, the following information is shown:
+        + AP MAC address.
+
+BSS_IDLE
+--------
+    For this event, there is no associated information.
+
+BSS_ACTIVE
+----------
+    For this event, there is no associated information.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  IWPRIV
+
+NAME
+	This manual describes the usage of private commands used in Marvell MLAN
+	Linux UAP Driver.
+
+	To use parameters as hex format, a '0x' must precede it for the parameters to
+	be parsed properly.
+
+SYNOPSIS
+	iwpriv <uapX> <command> [sub-command] ...
+
+	iwpriv uapX version
+	iwpriv uapX verext
+	iwpriv uapX start
+	iwpriv uapX stop
+	iwpriv uapX bssstart
+	iwpriv uapX bssstop
+	iwpriv uapX fwreload <path>
+	iwpriv uapX apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,[SEC,][KEY,]
+	                   [CHANNEL,][PREAMBLE,][MAX_SCB,][END]"
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell MLAN
+	card via the Linux device driver.
+
+	The uapX parameter specifies the network device that is to be used to
+	perform this command on. It could be uap0, uap1 etc.
+
+version
+	This is used to get the current version of the driver and the firmware.
+
+verext
+	Retrieve and display an extended version string from the firmware
+
+	Usage:
+		iwpriv uapX verext [#]
+
+	where [#] is an optional argument to retrieve a specific version string,
+	omission of the argument retrieves the 0 indexed string.
+
+start
+	Start the uAP driver.
+
+	Usage:
+		iwpriv uapX start
+
+stop
+	Stop the uAP driver.
+
+	Usage:
+		iwpriv uapX stop
+
+bssstart
+	Start the AP mode, so that uAP will start transmitting beacon.
+
+	Usage:
+		iwpriv uapX bssstart
+
+bssstop
+	Stop the AP mode and disconnect all stations. uAP will stop
+	transmitting beacon as well.
+
+	Usage:
+		iwpriv uapX bssstop
+
+fwreload
+	Reload the firmware. Here string "FW_PATH=" in the path
+	argument is mandatory part.
+
+	Usage:
+		iwpriv uapX fwreload <path>
+
+apcfg
+	This command is used to set the AP configurations. Here string
+	"ASCII_CMD=AP_CFG" is minimum requirement in the ASCII string.
+	Note: BSS will be stopped then restarted if BSS is already started
+	when the command is received.
+
+	Usage:
+		iwpriv uapX apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,[SEC=sec,]
+			[KEY=key,][CHANNEL=channel,][MAX_SCB=max_scb,][END]"
+
+	Where the parameters are:
+		SSID:       Set SSID to be used in beacon and probe response
+		[SEC]:      Security modes - open, wep128, wpa-psk or wpa2-psk
+		            11n will be auto disabled in wep128 and wpa-psk mode
+		[KEY]:      Encrypted key for wep128, wpa-psk or wpa2-psk, minimum 8 chars
+		[CHANNEL]:  Channel to be selected
+		[MAX_SCB]:  Maximum STA number
+		[END]:      Optional termination in ASCII string
+
+	Examples:
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP"
+                                        : Set AP SSID to "TEST_uAP"
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,SEC=open"
+                                        : Set AP SSID to "TEST_uAP" and
+                                          security mode is disabled
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,SEC=WPA2-PSK,KEY=ecbe5facdbfe234a"
+                                        : Set AP SSID to "TEST_uAP" and security mode
+                                          to WPA2-SPK and encrypted key ecbe5facdbfe234a
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,CHANNEL=8"
+                                        : Set AP SSID to "TEST_uAP" and
+                                          set the AP channel to 8
+
+===============================================================================
diff --git a/wlan_sd8987/README_WIFIDIRECT b/wlan_sd8987/README_WIFIDIRECT
new file mode 100644
index 0000000..b56602a
--- /dev/null
+++ b/wlan_sd8987/README_WIFIDIRECT
@@ -0,0 +1,448 @@
+
+===============================================================================
+
+        S E T U P  I N S T R U C T I O N S F O R  *WifiDirect*
+
+Driver,FW release:
+
+1. Make sure, bg_scan.conf,uaputl.conf has SSID starting with "DIRECT-"
+2. Download uAP configuration and BG scan configuration.
+3. This version of wifidirectutl breaks the backward compatibility and will work
+with following releases -
+    8797 >= 14.xx.16.p15
+         >= 14.xx.11.p138
+    8766 >= 14.xx.11.p138
+    8787 >= 14.xx.9.p89
+
+    However, In case one needs to run the utility in backward compatibility mode
+    he can do so by running following command before running the utility -
+
+    # export WIFIDIR_USE_FIXED_IE_INDICES=1
+
+    To disable backward comaptibility mode run following command -
+
+    # export WIFIDIR_USE_FIXED_IE_INDICES=0
+
+WPSWIFIDIRECT release:
+
+1. Modify the wifidirect.conf file to specify the correct HW addresses of
+   devices. The DUT mac address and peer mac address needs to be correctly
+   entered.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  WIFIDIRECTUTL
+
+NAME
+	wifidirectutl
+
+This tool can be used to configure WifiDirect parameters.
+
+------------------
+Supported Commands
+------------------
+wifidirect_mode [MODE]
+wifidirect_config [*.conf]
+wifidirect_params_config [*.conf]
+wifidirect_action_frame <*.conf> | [<PeerAddr> <Category> <OuiSubtype> <DialogToken>]
+wifidirect_discovery_request <*.conf>
+wifidirect_discovery_response <*.conf>
+
+wifidirect_cfg_discovery_period [<MinDiscPeriod> <MaxDiscPeriod>]
+wifidirect_cfg_intent [IntentValue]
+wifidirect_cfg_capability [<DeviceCapability> <GroupCapability>]
+wifidirect_cfg_noa <enable|disable> <index> [<counttype> <duration> <interval>]
+wifidirect_cfg_opp_ps <enable|disable> [<CTWindow>]
+wifidirect_cfg_invitation_list [mac_addr]
+wifidirect_cfg_listen_channel [ListenChannel]
+wifidirect_cfg_op_channel [OperatingChannel]
+wifidirect_cfg_persistent_group_record [index] [role]
+           [<groupbss> <deviceId> <ssid> <psk>] [peermac1] [peermac2]
+wifidirect_cfg_persistent_group_invoke [index] | <cancel>
+wifidirect_cfg_presence_req_params [<type> <duration> <interval>]
+wifidirect_cfg_ext_listen_time [<duration> <interval>]
+wifidirect_cfg_provisioning_params [<action> <configMethods> <devicePassword>]
+wifidirect_cfg_wps_params [<action>]
+
+wifidirect_mode [mode]
+----------
+    "./wifidirectutl <iface> wifidirect_mode [mode]"
+
+    This command is used to setup various modes for wifidirect device.
+    The mode 2 can be used only when wifidirect is started using mode 1.
+    The mode 3 should not be used for uAP.
+
+    The supported options are:
+        mode :     0 - stop wifidirect mode
+                   1 - start wifidirect mode
+                   2 - start wifidirect group owner mode
+                   3 - start wifidirect client mode
+                   4 - start wifidirect find phase
+                   5 - stop wifidirect find phase
+        empty - Get current wifidirect mode
+
+    Example:
+        ./wifidirectutl <iface> wifidirect_mode 0
+                Stop wifidirect mode.
+
+        ./wifidirectutl <iface> wifidirect_mode 1
+                Start wifidirect mode.
+
+        ./wifidirectutl <iface> wifidirect_mode
+                Get current WIFIDIRECT start/stop mode.
+
+wifidirect_config
+----------
+    "./wifidirectutl <iface> wifidirect_config [*.conf]"
+
+    This command is used to set/get the wifidirect configuration.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_config wifidirect.conf
+            Read configuration from wifidirect.conf and apply it.
+        ./wifidirectutl <iface> wifidirect_config
+            Read existing wifidirect configuration and display it.
+
+wifidirect_params_config
+----------
+    "./wifidirectutl <iface> wifidirect_params_config [*.conf]"
+
+    This command is used to set/get the wifidirect parameters configuration.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_params_config wifidirect.conf
+            Read parameter configuration from wifidirect.conf and apply it.
+        ./wifidirectutl <iface> wifidirect_params_config
+            Read existing wifidirect parameters's configuration and display it.
+
+wifidirect_action_frame
+----------
+    "./wifidirectutl <iface> wifidirect_action_frame <*.conf> | <PeerAddr> <Category> <OUISubtype> <DialogToken>"
+
+    This command is used to send action frames as specified in config file or on command line.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_action_frame wifidirect.conf
+            Read action_frame from wifidirect.conf and send to peer.
+        ./wifidirectutl <iface> wifidirect_action_frame <PeerAddr> <Category> <OUISubtype> <DialogToken>
+            Read action frame parameters from command line and send to peer.
+
+wifidirect_discovery_request
+----------
+    "./wifidirectutl <iface> wifidirect_discovery_request <*.conf>"
+
+    This command is used to send wifidirect discovery request packet.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_discovery_request wifidirect.conf
+            Read discovery packet from wifidirect.conf and send to peer.
+
+wifidirect_discovery_response
+----------
+    "./wifidirectutl <iface> wifidirect_discovery_response <*.conf>"
+
+    This command is used to send wifidirect discovery response packet.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_discovery_response wifidirect.conf
+            Read discovery packet from wifidirect.conf and send to peer.
+
+wifidirect_cfg_discovery_period
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_discovery_period [<MinDiscPeriod> <MaxDiscPeriod>]"
+
+	This command is used to set or get minimum and maximum discovery period.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_discovery_period 10 20
+		Set minimum discovery interval to 10 and maximum discovery
+		interval to	20.
+
+		./wifidirectutl <iface> wifidirect_cfg_discovery_period
+		Get minimum and maximum discovery interval.
+
+wifidirect_cfg_intent
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_intent [IntentValue]"
+
+	This command is used to set or get intent value.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_intent 12
+		Set intent value to 12.
+
+		./wifidirectutl <iface> wifidirect_cfg_intent
+		Get Group Owner Intent.
+
+wifidirect_cfg_capability
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_capability [<DeviceCapability> <GroupCapability>]"
+
+	This command is used to set or get device capability and group capability.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_capability 10 20
+		Set Device capability to 10 and group capability to 20
+
+		./wifidirectutl <iface> wifidirect_cfg_capability
+		Get Device capability and group capability.
+
+wifidirect_cfg_noa
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_noa <enable|disable> <index> [<counttype> <duration> <interval>]"
+
+	This command is used to set or get NoA parameters like count_type, duration and
+	interval in ms when NoA is enabled. Valid value of index is [0, 1].
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_noa enable 0 10 50 100
+		Enable NoA and set count to 10, duration to 50ms and interval to 100 ms
+            for index 0.
+
+		./wifidirectutl <iface> wifidirect_cfg_noa disable 1
+		Disable NoA at index 1.
+
+		./wifidirectutl <iface> wifidirect_cfg_noa
+		Get NoA settings.
+
+wifidirect_cfg_opp_ps
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_opp_ps <enable|disable> [<CTWindow>]"
+
+	This command is used to set or get Opportunistic power save and CT window.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_opp_ps enable 50
+		Set OppPS and CTwindow value to 50.
+
+		./wifidirectutl <iface> wifidirect_cfg_opp_ps disable
+		Disable OppPS.
+
+		./wifidirectutl <iface> wifidirect_cfg_opp_ps
+		Get OppPS and CT window.
+
+wifidirect_cfg_invitation_list
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_invitation_list [mac_addr]"
+
+	This command is used to set or get invitation list of peers.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_invitation_list 00:50:43:20:23:34
+		Set 00:50:43:20:23:34 in invitation list of peers.
+
+		./wifidirectutl <iface> wifidirect_cfg_invitation_list
+		Get Invitation list of peers.
+
+wifidirect_cfg_listen_channel
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_listen_channel [ListenChannel]"
+
+	This command is used to set or get Listen channel.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_listen_channel 11
+		Set Listen channel to 11.
+
+		./wifidirectutl <iface> wifidirect_cfg_listen_channel
+		Get Listen channel.
+
+wifidirect_cfg_op_channel
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_op_channel [OperatingChannel]"
+
+		This command is used to set or get Operating channel.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_op_channel 11
+		Set Operating channel to 11.
+
+		./wifidirectutl <iface> wifidirect_cfg_op_channel
+		Get Operating channel.
+
+wifidirect_cfg_persistent_group_record
+----------
+		"./wifidirectutl <iface> [index] [role]
+                 [<groupbss> <deviceId> <ssid> <psk>] [peermac1] [peermac2]"
+
+		This command is used to set or get the persistent group record
+        maintained in the device. Valid index is from 0 to 3. The role should be
+        0 for client, 1 for group-owner.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record 0 1
+        00:50:43:12:24:36 00:50:43:13:26:39 "DIRECT-" "1234567890"
+        00:50:43:20:c2:d0
+		Set persistent group record with index 0, role as group owner, bssId and
+        device Id, ssid="DIRECT-", passphrase="1234567890", and peer mac address.
+        The passphrase get converted to PSK.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record 1 1
+        00:50:43:12:24:36 00:50:43:13:26:39 "DIRECT-" "1234567890"
+        0x1234567890123456789012345678901234567890123456789012345678901234
+		Set persistent group record with index 1, role as group owner, bssId and
+        device Id, ssid="DIRECT-", passphrase="1234567890", and peer mac address.
+        The passphrase get converted to PSK.
+        PSK is specified with "0x" prefix and 32 bytes (64 characters).
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record 1
+		Get persistent group record with index 1.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record
+		Get persistent group record for all indices.
+
+wifidirect_cfg_persistent_group_invoke
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_persistent_group_invoke [index] | <cancel>"
+
+		This command is used to invoke a particular persistent group record
+        from the list. Valid index is from 0 to 3.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_invoke 2
+		Invoke persistent group record with index 1.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_invoke cancel
+		Cancel invokation of persistent groups.
+
+wifidirect_cfg_presence_req_params
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_presence_req_params [<type> <duration> <interval>]"
+
+		This command is used to set/get presence request parameters. Type should
+        be 1 for preferred values and 2 for acceptable values.
+
+		./wifidirectutl <iface> wifidirect_cfg_presence_req_params 1 50 100
+		Set duration to 50ms and interval to 100ms.
+
+		./wifidirectutl <iface> wifidirect_cfg_presence_req_params
+		Get presence request parameters.
+
+wifidirect_cfg_ext_listen_time
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_ext_listen_time [<duration> <interval>]"
+
+		This command is used to set/get extended listen timing parameters.
+
+		./wifidirectutl <iface> wifidirect_cfg_ext_listen_time 1200 1300
+		Set availability period to 1200ms and availability interval to 1300 ms.
+
+		./wifidirectutl <iface> wifidirect_cfg_ext_listen_time
+		Get extended listen timing parameters.
+
+wifidirect_cfg_provisioning_params
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_provisioning_params [<action> <configMethod> <devicePassword>]"
+
+		This command is used to set/get provisioning protocol parameters. Action should
+        be 1 for request parameters and 2 for response parameters.
+
+		./wifidirectutl <iface> wifidirect_cfg_provisioning_params 1 0x80 0x04
+		Set config method to 0x86 and device password to 0x04.
+
+		./wifidirectutl <iface> wifidirect_cfg_provisioning_params
+		Get Provision protocol parameters.
+
+wifidirect_cfg_wps_params
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_wps_params [<action>]"
+
+		This command is used to set WPS action. action can be "pin" (pin entered),
+        "pbc"(button pressed) or "none".
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_wps_params pin
+		Indicates pin operation
+
+		./wifidirectutl <iface> wifidirect_cfg_wps_params none
+		Indicates no operation
+
+===============================================================================
+        U S E R  M A N U A L  F O R  WIFIDISPLAY
+
+wifidisplay_mode
+-----------
+            "./wifidirectutl <iface> wifidisplay_mode [<action>]"
+            This command is used to enable or disable wifi-display. The possible values are either 1 or 0.
+		Example:
+		./wifidirectutl <iface> wifidisplay_mode 1
+		Indicates enable wifi_display
+
+		./wifidirectutl <iface> wifidisplay_mode 0
+		Indicates disable wifi_display
+
+wifidisplay_config
+-----------
+            "./wifidirectutl <iface> wifidisplay_config [*.conf]"
+
+            This command is used to set/get the wifidisplay configuration.
+
+             Example:
+             ./wifidirectutl <iface> wifidisplay_config wifidisplay.conf
+             Read configuration from wifidisplay.conf and apply it.
+             ./wifidirectutl <iface> wifidisplay_config
+             Read existing wifidisplay configuration and display it.
+
+wifidisplay_update_devinfo
+----------
+            "./wifidirectutl <iface> wifidisplay_update_devinfo [value]"
+
+            This command is used to set the device information of wifidisplay device information subelement.
+            This command will overwrite the new device information with user defined value.
+
+             Example:
+             ./wifidirectutl <iface> wifidisplay_update_devinfo 10
+             Update device information programmed with new value 10 by overwritting existing value.
+
+wifidisplay_discovery_request
+----------
+            "./wifidirectutl <iface> wifidisplay_discovery_request [*.config]"
+
+            This command is used to send wifi display service discovery request.
+
+            Example:
+            ./wifidirectutl <iface> wifidisplay_discovery_request wifidisplay.conf
+            Read discovery packet from wifidisplay.conf and send to peer.
+
+wifidisplay_discovery_response
+----------
+           "./wifidirectutl <iface> wifidisplay_discovery_response <*.conf>"
+
+           This command is used to send wifidisplay discovery response packet.
+
+           Example:
+           ./wifidirectutl <iface> wifidisplay_discovery_response wifidisplay.conf
+           Read discovery packet from wifidisplay.conf and send to peer.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANEVENT
+
+NAME
+mlanevent.exe
+
+This tool can be used to listen for and obtain events from the driver
+through the netlink layer. This is only used for display/debugging purpose.
+
+----------------
+Supported events
+----------------
+WIFIDIRECT_GENERIC_EVENT
+WIFIDIRECT_SERVICE_DISCOVERY
+
+-----------------
+Details of events
+-----------------
+
+WIFIDIRECT_GENERIC_EVENT
+-----------------
+    For this event, the following information is shown:
+        + Event length.
+        + Event Type indicating Negociation, Invitation, Discoverability,
+		Provision discovery related Request or Response.
+        + Event SubType indicating Client or Group owner role.
+        + Peer MAC address.
+        + Associated WIFIDIRECT IE elements.
+
+WIFIDIRECT_SERVICE_DISCOVERY
+---------------------
+    For this event, the following information is shown:
+        + Peer MAC address.
+        + Service discovery packet details.
diff --git a/wlan_sd8987/gpl-2.0.txt b/wlan_sd8987/gpl-2.0.txt
new file mode 100644
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 100644
index 0000000..f8b25c6
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan.h
@@ -0,0 +1,35 @@
+/** @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 (C) 2008-2019, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+/******************************************************
+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 100644
index 0000000..fdc2d01
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11ac.c
@@ -0,0 +1,1383 @@
+/** @file mlan_11ac.c
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *  Copyright (C) 2011-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+
+#define NO_NSS_SUPPORT 0x3
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+t_u16 wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u8 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(IN mlan_private *pmpriv,
+			 IN t_u8 band, IN t_u32 pri_chan, IN 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;
+			}
+		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;
+			}
+		case 100:
+		case 104:
+		case 108:
+		case 112:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 106;
+				break;
+			}
+		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;
+			}
+		case 132:
+		case 136:
+		case 140:
+		case 144:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 138;
+				break;
+			}
+		case 149:
+		case 153:
+		case 157:
+		case 161:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 155;
+				break;
+			}
+		case 165:
+		case 169:
+		case 173:
+		case 177:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 171;
+				break;
+			}
+		case 184:
+		case 188:
+		case 192:
+		case 196:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 190;
+				break;
+			}
+
+		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 number of nss which supports VHT mcs
+ *
+ *  @param mcs_map_set  VHT mcs map
+ *
+ *  @return             Number of supported nss
+ */
+static t_u8
+wlan_get_nss_num_vht_mcs(t_u16 mcs_map_set)
+{
+	t_u8 nss, nss_num = 0;
+	for (nss = 1; nss <= 8; nss++) {
+		if (GET_VHTNSSMCS(mcs_map_set, nss) != NO_NSS_SUPPORT)
+			nss_num++;
+	}
+	PRINTM(MCMND, "Supported nss:%d\n", nss_num);
+	return nss_num;
+}
+
+/**
+ *  @brief This function fills the cap info
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_fill_cap_info(mlan_private *priv, VHT_capa_t *vht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11ac_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_bg;
+
+	vht_cap->vht_cap_info = usr_dot_11ac_dev_cap;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Set/get 11ac configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_11ac_ioctl_vhtcfg(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_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;
+
+	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) {
+			/* 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 ((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 ((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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+				  IN 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(pmadapter, cfg->param.supported_mcs_set, mcs_set, NUM_MCS_SUPP);
+
+#endif
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function prints the 802.11ac device capability
+ *
+ *  @param pmadapter     A pointer to mlan_adapter structure
+ *  @param cap           Capability value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_dot11acdevcap(pmlan_adapter pmadapter, t_u32 cap)
+{
+	ENTER();
+
+	switch (GET_VHTCAP_MAXMPDULEN(cap)) {
+	case 0x0:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MSDU length = 3895 octets\n");
+		break;
+	case 0x1:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MSDU length = 7991 octets\n");
+		break;
+	case 0x2:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MSDU length = 11454 octets\n");
+		break;
+	default:
+		PRINTM(MINFO, "Unsupport value\n");
+		break;
+	}
+
+	PRINTM(MINFO, "GET_HW_SPEC: HTC-VHT %s\n",
+	       (ISSUPP_11ACVHTHTCVHT(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: VHT TXOP PS %s\n",
+	       (ISSUPP_11ACVHTTXOPPS(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: MU RX beamformee %s\n",
+	       (ISSUPP_11ACMURXBEAMFORMEE(cap) ? "supported" :
+		"not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: MU TX beamformee %s\n",
+	       (ISSUPP_11ACMUTXBEAMFORMEE(cap) ? "supported" :
+		"not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: SU RX Beamformee %s\n",
+	       (ISSUPP_11ACSUBEAMFORMEE(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: SU TX Beamformer %s\n",
+	       (ISSUPP_11ACSUBEAMFORMER(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n",
+	       (ISSUPP_11ACRXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n",
+	       (ISSUPP_11ACTXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 160MHz BW\n",
+	       (ISSUPP_11ACSGI160(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 80MHz BW\n",
+	       (ISSUPP_11ACSGI80(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: LDPC coding %s\n",
+	       (ISSUPP_11ACLDPC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160/80+80 MHz %s\n",
+	       (ISSUPP_11ACBW8080(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160 MHz %s\n",
+	       (ISSUPP_11ACBW160(cap) ? "supported" : "not supported"));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function prints the 802.11ac device MCS
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param support   Support value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_dot11acmcssupport(pmlan_adapter pmadapter, t_u32 support)
+{
+	ENTER();
+
+	PRINTM(MINFO, "GET_HW_SPEC: MCSs for %2dx%2d MIMO\n",
+	       GET_DEVRXMCSMAP(support), GET_DEVTXMCSMAP(support));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function converts the 2-bit MCS map to the highest long GI
+ *  VHT PPDU data rate
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param bands        Supported bands
+ *  @param mcs_map      2-bit MCS map
+ *
+ *  @return             the max data rate for long GI
+ */
+t_u16
+wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u8 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
+ *  @return             N/A
+ */
+void
+wlan_fill_vht_cap_tlv(mlan_private *priv,
+		      MrvlIETypes_VHTCap_t *pvht_cap, t_u8 bands, t_u8 flag)
+{
+	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;
+
+	ENTER();
+
+	/* Fill VHT cap info */
+	wlan_fill_cap_info(priv, &pvht_cap->vht_cap, bands);
+	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);
+	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));
+	}
+	/* 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 ((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_u8 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 append the 802_11AC 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;
+	MrvlIETypes_VHTOprat_t *pvht_op;
+	t_u8 supp_chwd_set;
+	t_u32 usr_vht_cap_info;
+	int ret_len = 0;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (pbss_desc->bss_band & BAND_A)
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_bg;
+
+	/* 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(pmadapter,
+		       (t_u8 *)pvht_cap + sizeof(MrvlIEtypesHeader_t),
+		       (t_u8 *)pbss_desc->pvht_cap + sizeof(IEEEtypes_Header_t),
+		       pvht_cap->header.len);
+
+		wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pbss_desc->bss_band,
+				      MTRUE);
+
+		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;
+	}
+
+	/* VHT Operation IE */
+	if (pbss_desc->pvht_oprat) {
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+			pvht_op = (MrvlIETypes_VHTOprat_t *)*ppbuffer;
+			memset(pmadapter, pvht_op, 0,
+			       sizeof(MrvlIETypes_VHTOprat_t));
+			pvht_op->header.type = wlan_cpu_to_le16(VHT_OPERATION);
+			pvht_op->header.len = sizeof(MrvlIETypes_VHTOprat_t) -
+				sizeof(MrvlIEtypesHeader_t);
+			memcpy(pmadapter,
+			       (t_u8 *)pvht_op + sizeof(MrvlIEtypesHeader_t),
+			       (t_u8 *)pbss_desc->pvht_oprat +
+			       sizeof(IEEEtypes_Header_t), pvht_op->header.len);
+
+			/* negotiate the channel width and central freq */
+			/* and keep the central freq as the peer suggests */
+			supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
+			if (supp_chwd_set == VHT_CAP_CHWD_80MHZ)
+				pvht_op->chan_width = MIN(VHT_OPER_CHWD_80MHZ,
+							  pbss_desc->
+							  pvht_oprat->
+							  chan_width);
+			else if (supp_chwd_set == VHT_CAP_CHWD_160MHZ)
+				pvht_op->chan_width = MIN(VHT_OPER_CHWD_160MHZ,
+							  pbss_desc->
+							  pvht_oprat->
+							  chan_width);
+			else if (supp_chwd_set == VHT_CAP_CHWD_80_80MHZ)
+				pvht_op->chan_width =
+					MIN(VHT_OPER_CHWD_80_80MHZ,
+					    pbss_desc->pvht_oprat->chan_width);
+			else
+				pvht_op->chan_width = VHT_OPER_CHWD_20_40MHZ;
+	    /** current region don't allow bandwidth 80 */
+			if (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_80MHZ)
+				pvht_op->chan_width = VHT_OPER_CHWD_20_40MHZ;
+			HEXDUMP("VHT_OPERATION IE", (t_u8 *)pvht_op,
+				sizeof(MrvlIETypes_VHTOprat_t));
+			*ppbuffer += sizeof(MrvlIETypes_VHTOprat_t);
+			ret_len += sizeof(MrvlIETypes_VHTOprat_t);
+			pvht_op->header.len =
+				wlan_cpu_to_le16(pvht_op->header.len);
+		}
+	}
+	/* 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);
+
+		mcs_map_user =
+			GET_DEVRXMCSMAP(pmpriv->usr_dot_11ac_mcs_support);
+		nss = wlan_get_nss_num_vht_mcs(mcs_map_user);
+		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(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *cmd,
+		  IN t_u16 cmd_action, IN 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;
+	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(pmadapter, &vhtcfg->vht_supp_mcs_set[0],
+	       &vht_cfg->vht_rx_mcs, sizeof(t_u32));
+	vht_cfg->vht_tx_mcs = wlan_cpu_to_le32(vht_cfg->vht_tx_mcs);
+	memcpy(pmadapter, &vhtcfg->vht_supp_mcs_set[4],
+	       &vht_cfg->vht_tx_mcs, sizeof(t_u32));
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of 11ac 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_11ac_cfg(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *resp, IN 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(pmadapter, &cfg->param.vht_cfg.vht_rx_mcs,
+		       &vhtcfg->vht_supp_mcs_set[0], sizeof(t_u32));
+		cfg->param.vht_cfg.vht_rx_mcs =
+			wlan_le32_to_cpu(cfg->param.vht_cfg.vht_rx_mcs);
+		memcpy(pmadapter, &cfg->param.vht_cfg.vht_tx_mcs,
+		       &vhtcfg->vht_supp_mcs_set[4], 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_u8 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 100644
index 0000000..291e109
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11ac.h
@@ -0,0 +1,55 @@
+/** @file mlan_11ac.h
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *  Copyright (C) 2011-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+#ifndef _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_u8 bands,
+				     t_u16 mcs_map);
+void wlan_fill_vht_cap_tlv(mlan_private *priv, MrvlIETypes_VHTCap_t *pvht_cap,
+			   t_u8 bands, t_u8 flag);
+void wlan_fill_vht_cap_ie(mlan_private *priv, IEEEtypes_VHTCap_t *pvht_cap,
+			  t_u8 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_u8 bss_band);
+
+mlan_status wlan_cmd_11ac_cfg(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_11ac_cfg(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN mlan_ioctl_req *pioctl_buf);
+
+#endif /* _MLAN_11AC_H_ */
diff --git a/wlan_sd8987/mlan/mlan_11d.c b/wlan_sd8987/mlan/mlan_11d.c
new file mode 100644
index 0000000..cc944fe
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11d.c
@@ -0,0 +1,1640 @@
+/** @file mlan_11d.c
+ *
+ *  @brief This file contains functions for 802.11D.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+/********************************************************
+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[] = {
+	{"WW ", 0x00},		/* World       */
+	{"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 */
+};
+
+/** Universal region code */
+#define UNIVERSAL_REGION_CODE   0xff
+#endif
+
+/** Default Tx power */
+#define TX_PWR_DEFAULT  10
+
+/* Following two structures define the supported channels */
+/** Channels for 802.11b/g */
+static chan_freq_power_t channel_freq_power_UN_BG[] = {
+	{1, 2412, TX_PWR_DEFAULT},
+	{2, 2417, TX_PWR_DEFAULT},
+	{3, 2422, TX_PWR_DEFAULT},
+	{4, 2427, TX_PWR_DEFAULT},
+	{5, 2432, TX_PWR_DEFAULT},
+	{6, 2437, TX_PWR_DEFAULT},
+	{7, 2442, TX_PWR_DEFAULT},
+	{8, 2447, TX_PWR_DEFAULT},
+	{9, 2452, TX_PWR_DEFAULT},
+	{10, 2457, TX_PWR_DEFAULT},
+	{11, 2462, TX_PWR_DEFAULT},
+	{12, 2467, TX_PWR_DEFAULT},
+	{13, 2472, TX_PWR_DEFAULT},
+	{14, 2484, TX_PWR_DEFAULT}
+};
+
+/** Channels for 802.11a/j */
+static chan_freq_power_t channel_freq_power_UN_AJ[] = {
+	{8, 5040, TX_PWR_DEFAULT},
+	{12, 5060, TX_PWR_DEFAULT},
+	{16, 5080, TX_PWR_DEFAULT},
+	{34, 5170, TX_PWR_DEFAULT},
+	{38, 5190, TX_PWR_DEFAULT},
+	{42, 5210, TX_PWR_DEFAULT},
+	{46, 5230, TX_PWR_DEFAULT},
+	{36, 5180, TX_PWR_DEFAULT},
+	{40, 5200, TX_PWR_DEFAULT},
+	{44, 5220, TX_PWR_DEFAULT},
+	{48, 5240, TX_PWR_DEFAULT},
+	{52, 5260, TX_PWR_DEFAULT},
+	{56, 5280, TX_PWR_DEFAULT},
+	{60, 5300, TX_PWR_DEFAULT},
+	{64, 5320, TX_PWR_DEFAULT},
+	{100, 5500, TX_PWR_DEFAULT},
+	{104, 5520, TX_PWR_DEFAULT},
+	{108, 5540, TX_PWR_DEFAULT},
+	{112, 5560, TX_PWR_DEFAULT},
+	{116, 5580, TX_PWR_DEFAULT},
+	{120, 5600, TX_PWR_DEFAULT},
+	{124, 5620, TX_PWR_DEFAULT},
+	{128, 5640, TX_PWR_DEFAULT},
+	{132, 5660, TX_PWR_DEFAULT},
+	{136, 5680, TX_PWR_DEFAULT},
+	{140, 5700, TX_PWR_DEFAULT},
+	{149, 5745, TX_PWR_DEFAULT},
+	{153, 5765, TX_PWR_DEFAULT},
+	{157, 5785, TX_PWR_DEFAULT},
+	{161, 5805, TX_PWR_DEFAULT},
+	{165, 5825, TX_PWR_DEFAULT},
+/*  {240, 4920, TX_PWR_DEFAULT},
+    {244, 4940, TX_PWR_DEFAULT},
+    {248, 4960, TX_PWR_DEFAULT},
+    {252, 4980, TX_PWR_DEFAULT},
+channels for 11J JP 10M channel gap */
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function converts integer code to region string
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param code         Region code
+ *
+ *  @return             Region string
+ */
+static t_u8 *
+wlan_11d_code_2_region(pmlan_adapter pmadapter, t_u8 code)
+{
+	t_u8 i;
+
+	ENTER();
+
+	/* Look for code in mapping table */
+	for (i = 0; i < NELEMENTS(region_code_mapping); i++) {
+		if (region_code_mapping[i].code == code) {
+			LEAVE();
+			return region_code_mapping[i].region;
+		}
+	}
+
+	LEAVE();
+	/* Default is US */
+	return region_code_mapping[0].region;
+}
+
+/**
+ *  @brief This function Checks if channel txpwr is learned from AP/IBSS
+ *
+ *  @param pmadapter            A pointer to mlan_adapter structure
+ *  @param band                 Band number
+ *  @param chan                 Channel number
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     MTRUE or MFALSE
+ */
+static t_u8
+wlan_11d_channel_known(pmlan_adapter pmadapter,
+		       t_u8 band,
+		       t_u8 chan, parsed_region_chan_11d_t *parsed_region_chan)
+{
+	chan_power_11d_t *pchan_pwr = parsed_region_chan->chan_pwr;
+	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+	t_u8 i = 0;
+	t_u8 ret = MFALSE;
+	mlan_private *pmpriv;
+
+	ENTER();
+
+	HEXDUMP("11D: parsed_region_chan", (t_u8 *)pchan_pwr,
+		sizeof(chan_power_11d_t) * no_of_chan);
+
+	/* Search channel */
+	for (i = 0; i < no_of_chan; i++) {
+		if (chan == pchan_pwr[i].chan && band == pchan_pwr[i].band) {
+			PRINTM(MINFO, "11D: Found channel:%d (band:%d)\n", chan,
+			       band);
+			ret = MTRUE;
+
+			if (band & BAND_A) {
+				/* If chan is a DFS channel, we need to see an AP on it */
+				pmpriv = wlan_get_priv(pmadapter,
+						       MLAN_BSS_ROLE_STA);
+				if (pmpriv &&
+				    wlan_11h_radar_detect_required(pmpriv,
+								   chan)) {
+					PRINTM(MINFO,
+					       "11H: DFS channel %d, and ap_seen=%d\n",
+					       chan, pchan_pwr[i].ap_seen);
+					ret = pchan_pwr[i].ap_seen;
+				}
+			}
+
+			LEAVE();
+			return ret;
+		}
+	}
+
+	PRINTM(MINFO, "11D: Could not find channel:%d (band:%d)\n", chan, band);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function generates parsed_region_chan from Domain Info
+ *           learned from AP/IBSS
+ *
+ *  @param pmadapter            Pointer to mlan_adapter structure
+ *  @param region_chan          Pointer to region_chan_t
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     N/A
+ */
+static t_void
+wlan_11d_generate_parsed_region_chan(pmlan_adapter pmadapter,
+				     region_chan_t *region_chan,
+				     parsed_region_chan_11d_t
+				     *parsed_region_chan)
+{
+	chan_freq_power_t *cfp;
+	t_u8 i;
+
+	ENTER();
+
+	/* Region channel must be provided */
+	if (!region_chan) {
+		PRINTM(MWARN, "11D: region_chan is MNULL\n");
+		LEAVE();
+		return;
+	}
+
+	/* Get channel-frequency-power trio */
+	cfp = region_chan->pcfp;
+	if (!cfp) {
+		PRINTM(MWARN, "11D: cfp equal MNULL\n");
+		LEAVE();
+		return;
+	}
+
+	/* Set channel, band and power */
+	for (i = 0; i < region_chan->num_cfp; i++, cfp++) {
+		parsed_region_chan->chan_pwr[i].chan = (t_u8)cfp->channel;
+		parsed_region_chan->chan_pwr[i].band = region_chan->band;
+		parsed_region_chan->chan_pwr[i].pwr = (t_u8)cfp->max_tx_power;
+		PRINTM(MINFO, "11D: Chan[%d] Band[%d] Pwr[%d]\n",
+		       parsed_region_chan->chan_pwr[i].chan,
+		       parsed_region_chan->chan_pwr[i].band,
+		       parsed_region_chan->chan_pwr[i].pwr);
+	}
+	parsed_region_chan->no_of_chan = region_chan->num_cfp;
+
+	PRINTM(MINFO, "11D: no_of_chan[%d]\n", parsed_region_chan->no_of_chan);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function generates domain_info from parsed_region_chan
+ *
+ *  @param pmadapter            Pointer to mlan_adapter structure
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11d_generate_domain_info(pmlan_adapter pmadapter,
+			      parsed_region_chan_11d_t *parsed_region_chan)
+{
+	t_u8 no_of_sub_band = 0;
+	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+	t_u8 no_of_parsed_chan = 0;
+	t_u8 first_chan = 0, next_chan = 0, max_pwr = 0;
+	t_u8 i, flag = MFALSE;
+	wlan_802_11d_domain_reg_t *domain_info = &pmadapter->domain_reg;
+
+	ENTER();
+
+	/* Should be only place that clear domain_reg (besides init) */
+	memset(pmadapter, domain_info, 0, sizeof(wlan_802_11d_domain_reg_t));
+
+	/* Set country code */
+	memcpy(pmadapter, domain_info->country_code,
+	       wlan_11d_code_2_region(pmadapter, (t_u8)pmadapter->region_code),
+	       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(pmadapter, parsed_region_chan,
+		       &region_chan, 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(pmadapter, pdomain->country_code, country_code,
+	       COUNTRY_CODE_LEN);
+	pdomain->band = band;
+	pdomain->no_of_sub_band = num_sub_band;
+	memcpy(pmadapter, pdomain->sub_band, sub_band_list,
+	       MIN(MRVDRV_MAX_SUBBAND_802_11D,
+		   num_sub_band) * 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(pmadapter, domain->country_code,
+	       pmadapter->domain_reg.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(pmadapter, domain->sub_band,
+		       pmadapter->domain_reg.sub_band,
+		       MIN(MRVDRV_MAX_SUBBAND_802_11D,
+			   no_of_sub_band) * 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(pmadapter, &region_chan,
+		       &pmadapter->parsed_region_chan,
+		       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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(pmadapter, pmadapter->country_code, domain_info->country_code,
+	       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(pmadapter, pmadapter->country_code, pdomain_tlv->country_code,
+	       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 100644
index 0000000..4d83661
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11h.c
@@ -0,0 +1,4272 @@
+/** @file mlan_11h.c
+ *
+ *  @brief This file contains functions for 802.11H.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+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 = 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 Marvell
+ *         proprietary format
+ *
+ *  @param pmadapter Pointer to mlan_adapter
+ *  @param pout_buf Output parameter: Buffer to output Marvell formatted IE
+ *  @param pin_ie   Pointer to IEEE IE to be converted to Marvell 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 Marvell 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(pmadapter, ptmp_buf, &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(pmadapter, ptmp_buf, pin_ie + 2, 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(adapter, pdfs->dfs_owner, priv->curr_addr,
+	       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;
+		}
+	}
+
+	/*
+	 * 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(priv->adapter, &pcmd_ptr->params.tpc_req, pinfo_buf,
+	       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(priv->adapter, &pcmd_ptr->params.chan_sw_ann, pch_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)
+{
+	const 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;
+
+	/*
+	 * 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;
+
+	ENTER();
+	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(priv->adapter, &pcmd_ptr->params.chan_rpt_req, pchan_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);
+	}
+
+	/* 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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, &sup_chan_ie, 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(adapter, dfs_elem.dfs_owner,
+		       p11h_bss_info->ibss_dfs.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, OUT 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(IN 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(IN mlan_adapter *pmadapter,
+				  OUT mlan_ioctl_req **ppioctl_req,
+				  IN t_bool is_adding_ie)
+{
+	mlan_ioctl_req *pioctl_req = MNULL;
+	mlan_ds_misc_cfg *pds_misc_cfg = MNULL;
+	custom_ie *pcust_chansw_ie = MNULL;
+	IEEEtypes_ChanSwitchAnn_t *pchansw_ie = MNULL;
+	mlan_status ret;
+	IEEEtypes_Header_t *pChanSwWrap_ie = MNULL;
+	IEEEtypes_WideBWChanSwitch_t *pbwchansw_ie = MNULL;
+	IEEEtypes_VhtTpcEnvelope_t *pvhttpcEnv_ie = MNULL;
+	t_u8 index;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	if (pmadapter == MNULL || ppioctl_req == MNULL) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* allocate buffer for mlan_ioctl_req and mlan_ds_misc_cfg */
+	/* FYI - will be freed as part of cmd_response handler */
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(mlan_ioctl_req) +
+					       sizeof(mlan_ds_misc_cfg),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pioctl_req);
+	if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+		PRINTM(MERROR, "%s(): Could not allocate ioctl req\n",
+		       __func__);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pds_misc_cfg = (mlan_ds_misc_cfg *)((t_u8 *)pioctl_req +
+					    sizeof(mlan_ioctl_req));
+
+	/* prepare mlan_ioctl_req */
+	memset(pmadapter, pioctl_req, 0x00, sizeof(mlan_ioctl_req));
+	pioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	pioctl_req->action = MLAN_ACT_SET;
+	pioctl_req->pbuf = (t_u8 *)pds_misc_cfg;
+	pioctl_req->buf_len = sizeof(mlan_ds_misc_cfg);
+
+	/* prepare mlan_ds_misc_cfg */
+	memset(pmadapter, pds_misc_cfg, 0x00, sizeof(mlan_ds_misc_cfg));
+	pds_misc_cfg->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	pds_misc_cfg->param.cust_ie.type = TLV_TYPE_MGMT_IE;
+	pds_misc_cfg->param.cust_ie.len = (sizeof(custom_ie) - MAX_IE_SIZE);
+
+	/* configure custom_ie api settings */
+	pcust_chansw_ie =
+		(custom_ie *)&pds_misc_cfg->param.cust_ie.ie_data_list[0];
+	pcust_chansw_ie->ie_index = 0xffff;	/* Auto index */
+	pcust_chansw_ie->ie_length = sizeof(IEEEtypes_ChanSwitchAnn_t);
+	pcust_chansw_ie->mgmt_subtype_mask = (is_adding_ie)
+		? MBIT(8) | MBIT(5)	/* add IE for BEACON | PROBE_RSP */
+		: 0;		/* remove IE */
+
+	/* prepare CHAN_SW IE inside ioctl */
+	pchansw_ie = (IEEEtypes_ChanSwitchAnn_t *)pcust_chansw_ie->ie_buffer;
+	pchansw_ie->element_id = CHANNEL_SWITCH_ANN;
+	pchansw_ie->len =
+		sizeof(IEEEtypes_ChanSwitchAnn_t) - sizeof(IEEEtypes_Header_t);
+	pchansw_ie->chan_switch_mode = 1;	/* STA should not transmit */
+	pchansw_ie->new_channel_num = pmadapter->state_rdh.new_channel;
+
+	pchansw_ie->chan_switch_count = pmadapter->dfs_cs_count;
+	PRINTM(MCMD_D, "New Channel = %d Channel switch count = %d\n",
+	       pmadapter->state_rdh.new_channel, pchansw_ie->chan_switch_count);
+
+	for (index = 0; index < pmadapter->state_rdh.priv_list_count; index++) {
+		pmpriv = pmadapter->state_rdh.priv_list[index];
+		/*find the first AP interface */
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+			if (pmpriv->is_11ac_enabled) {
+
+				pChanSwWrap_ie =
+					(IEEEtypes_Header_t *)((t_u8 *)
+							       pchansw_ie +
+							       sizeof
+							       (IEEEtypes_ChanSwitchAnn_t));
+				pChanSwWrap_ie->element_id = EXT_POWER_CONSTR;
+				/*will have multiple sub IEs */
+				pChanSwWrap_ie->len = 0;
+
+				/* prepare the Wide Bandwidth Channel Switch IE
+				 * Channel Switch IE */
+				pbwchansw_ie =
+					(IEEEtypes_WideBWChanSwitch_t
+					 *)((t_u8 *)pChanSwWrap_ie +
+					    sizeof(IEEEtypes_Header_t));
+				pbwchansw_ie->ieee_hdr.element_id =
+					BW_CHANNEL_SWITCH;
+				pbwchansw_ie->ieee_hdr.len =
+					sizeof(IEEEtypes_WideBWChanSwitch_t) -
+					sizeof(IEEEtypes_Header_t);
+				/*fix 80MHZ now */
+				pbwchansw_ie->new_channel_width =
+					VHT_OPER_CHWD_80MHZ;
+				pbwchansw_ie->new_channel_center_freq0 =
+					wlan_11h_get_channel_freq_idx
+					(pmadapter->state_rdh.new_channel);
+				pbwchansw_ie->new_channel_center_freq1 =
+					wlan_11h_get_channel_freq_idx
+					(pmadapter->state_rdh.new_channel);
+				pChanSwWrap_ie->len +=
+					sizeof(IEEEtypes_WideBWChanSwitch_t);
+
+				/*prepare the VHT Transmit Power Envelope IE */
+				pvhttpcEnv_ie =
+					(IEEEtypes_VhtTpcEnvelope_t *)((t_u8 *)
+								       pChanSwWrap_ie
+								       +
+								       sizeof
+								       (IEEEtypes_Header_t)
+								       +
+								       sizeof
+								       (IEEEtypes_WideBWChanSwitch_t));
+				pvhttpcEnv_ie->ieee_hdr.element_id =
+					VHT_TX_POWER_ENV;
+				pvhttpcEnv_ie->ieee_hdr.len =
+					sizeof(IEEEtypes_VhtTpcEnvelope_t) -
+					sizeof(IEEEtypes_Header_t);
+				/* Local Max TX Power Count= 3,
+				 * Local TX Power Unit Inter=EIP(0) */
+				pvhttpcEnv_ie->tpc_info = 3;
+				pvhttpcEnv_ie->local_max_tp_20mhz = 0xff;
+				pvhttpcEnv_ie->local_max_tp_40mhz = 0xff;
+				pvhttpcEnv_ie->local_max_tp_80mhz = 0xff;
+				pChanSwWrap_ie->len +=
+					sizeof(IEEEtypes_VhtTpcEnvelope_t);
+
+				pcust_chansw_ie->ie_length +=
+					sizeof(IEEEtypes_WideBWChanSwitch_t)
+					+ sizeof(IEEEtypes_VhtTpcEnvelope_t)
+					+ sizeof(IEEEtypes_Header_t);
+
+				PRINTM(MINFO,
+				       "Append Wide Bandwidth Channel Switch IE\n");
+				break;
+			}
+		}
+	}
+
+	pds_misc_cfg->param.cust_ie.len += pcust_chansw_ie->ie_length;
+	DBG_HEXDUMP(MCMD_D, "11h: custom_ie containing CHAN_SW IE",
+		    (t_u8 *)pcust_chansw_ie, pds_misc_cfg->param.cust_ie.len);
+
+	/* assign output pointer before returning */
+	*ppioctl_req = pioctl_req;
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Check if start channel 165 is allowed to operate in
+ *  previous uAP channel's band config
+ *
+ *  @param pcfp          a pointer to chan_freq_power_t structure
+ *  @param 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_chan_band_valid(chan_freq_power_t *pcfp, Band_Config_t bandcfg)
+{
+	t_u8 start_ch = pcfp->channel;
+	t_bool ret = MTRUE;
+
+	if (pcfp->dynamic.flags & MARVELL_CHANNEL_DISABLED)
+		return MFALSE;
+
+	/* if band width is not 20MHZ (either 40 or 80MHz)
+	 * return MFALSE, 165 is not allowed in bands other than 20MHZ
+	 */
+	if (start_ch == 165 && (bandcfg.chanWidth != CHAN_BW_20MHZ))
+		return MFALSE;
+
+	switch (bandcfg.chanWidth) {
+	case CHAN_BW_80MHZ:
+		if (pcfp->dynamic.flags & MARVELL_CHANNEL_NOHT80)
+			ret = MFALSE;
+		break;
+	case CHAN_BW_40MHZ:
+		if (pcfp->dynamic.flags & MARVELL_CHANNEL_NOHT40)
+			ret = MFALSE;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+#ifdef UAP_SUPPORT
+/** Bits 2,3 of band config define the band width */
+#define UAP_BAND_WIDTH_MASK 0x0C
+
+/**
+ *  @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 ((!wlan_11h_is_chan_band_valid
+						(&chn_tbl->pcfp[rand_entry],
+						 uap_band_cfg) ||
+						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 <
+						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;
+#ifdef DFS_TESTING_SUPPORT
+	wlan_dfs_testing_settings_t *pdfs_test = &adapter->dfs_test_params;
+#endif
+
+	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;
+
+#ifdef DFS_TESTING_SUPPORT
+	/* 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;
+#endif
+
+	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)
+	    || (adapter->adhoc_start_band & BAND_AN)
+		) {
+		/*
+		 * 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 (((chn_tbl->pcfp[rand_entry].
+						   dynamic.
+						   flags &
+						   MARVELL_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)))
+						 && (++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;
+}
+
+/**
+ *  @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;
+			}
+		}
+#ifdef DFS_TESTING_SUPPORT
+		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;
+		}
+#endif
+
+		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)
+		|| (adapter->adhoc_start_band & BAND_AN)
+	    )
+		) {
+		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(priv->adapter, priv->adapter->curr_cmd->pdata_buf,
+		       &resp->params.tpc_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_cancel_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(pmadapter, &p11h_bss_info->power_constraint, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->power_capability, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->tpc_report, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->chan_switch_ann, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->quiet, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->ibss_dfs, pelement,
+		       MIN((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;
+#if defined(UAP_SUPPORT)
+	mlan_adapter *pmadapter = priv->adapter;
+	int i;
+	t_u8 radar_detected = MFALSE;
+	mlan_private *pmpriv = MNULL;
+#endif
+
+	ENTER();
+
+#if defined(UAP_SUPPORT)
+    /** No need handle AP if mc_policy is disabled, FW will move the AP to client's new channel */
+	if (pmadapter->mc_policy &&
+	    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 {
+#ifdef DFS_TESTING_SUPPORT
+				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 {
+#endif
+					pmpriv->intf_state_11h.tx_disabled =
+						MTRUE;
+					wlan_recv_event(pmpriv,
+							MLAN_EVENT_ID_FW_RADAR_DETECTED,
+							MNULL);
+
+#ifdef DFS_TESTING_SUPPORT
+				}
+#endif
+			}
+		}
+	}
+	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(priv->adapter, deauth_param.mac_addr,
+	       &priv->curr_bss_params.bss_descriptor.mac_address,
+	       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;
+}
+
+#ifdef DFS_TESTING_SUPPORT
+/**
+ *  @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;
+	} 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;
+	}
+
+	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;
+	Band_Config_t bandcfg;
+
+	ENTER();
+
+	if (pioctl_req) {
+		ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+		ch_nop_info = &ds_11hcfg->param.ch_nop_info;
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+		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);
+			memset(pmadapter, &bandcfg, 0, sizeof(Band_Config_t));
+			bandcfg.chanWidth = ch_nop_info->chan_width;
+			if (ch_nop_info->chan_under_nop) {
+				wlan_11h_switch_non_dfs_chan(pmpriv, bandcfg,
+							     &ch_nop_info->
+							     new_chan.channel);
+				if (ch_nop_info->chan_width == CHAN_BW_80MHZ ||
+				    ch_nop_info->chan_width == CHAN_BW_40MHZ)
+					wlan_11h_update_bandcfg(&ch_nop_info->
+								new_chan.
+								bandcfg,
+								ch_nop_info->
+								new_chan.
+								channel);
+				if (ch_nop_info->chan_width == CHAN_BW_80MHZ)
+					ch_nop_info->new_chan.center_chan =
+						wlan_get_center_freq_idx(pmpriv,
+									 BAND_AAC,
+									 ch_nop_info->
+									 new_chan.
+									 channel,
+									 ch_nop_info->
+									 chan_width);
+			}
+		}
+		ret = MLAN_STATUS_SUCCESS;
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif /* DFS_TESTING_SUPPORT */
+
+/**
+ *  @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 cancel 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_cancel_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);
+#ifdef DFS_TESTING_SUPPORT
+		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
+#endif
+		{
+			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)
+{
+	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;
+
+	ENTER();
+	pchan_rpt_rsp = (HostCmd_DS_CHAN_RPT_RSP *)&pevent->event_buf;
+	DBG_HEXDUMP(MCMD_D, "11h: Event ChanRptReady (HostCmd_DS_CHAN_RPT_RSP)",
+		    (t_u8 *)pchan_rpt_rsp, pevent->event_len);
+
+	if (wlan_le32_to_cpu(pchan_rpt_rsp->cmd_result) ==
+	    MLAN_CMD_RESULT_SUCCESS) {
+		pbuffer = (t_u8 *)&pchan_rpt_rsp->tlv_buffer;
+		evt_len = pevent->event_len;
+		evt_len -=
+			sizeof(HostCmd_DS_CHAN_RPT_RSP) -
+			sizeof(pchan_rpt_rsp->tlv_buffer);
+
+		while (evt_len >= sizeof(MrvlIEtypesHeader_t)) {
+			ptlv = (MrvlIEtypes_Data_t *)pbuffer;
+			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+
+			switch (wlan_le16_to_cpu(ptlv->header.type)) {
+			case TLV_TYPE_CHANRPT_11H_BASIC:
+				pmeas_rpt_basic =
+					(MeasRptBasicMap_t *)&ptlv->data;
+				if (pmeas_rpt_basic->radar) {
+					pstate_dfs->dfs_radar_found = MTRUE;
+					PRINTM(MMSG,
+					       "RADAR Detected on channel %d!\n",
+					       pstate_dfs->dfs_check_channel);
+					/* add channel to NOP list */
+					wlan_11h_add_dfs_timestamp(priv->
+								   adapter,
+								   DFS_TS_REPR_NOP_START,
+								   pstate_dfs->
+								   dfs_check_channel);
+				}
+				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;
+	}
+
+	/* Update DFS structure. */
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &sec,
+						      &usec);
+	pstate_dfs->dfs_report_time_sec = sec;
+	pstate_dfs->dfs_check_pending = MFALSE;
+	pstate_dfs->dfs_check_priv = MNULL;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 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;
+}
+
+/**
+ *  @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);
+		}
+	}
+}
+
+/**
+ *  @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(IN Band_Config_t *uap_band_cfg, IN t_u8 new_channel)
+{
+	t_u8 chan_offset;
+	ENTER();
+
+	/* Update the channel offset for 20MHz, 40MHz and 80MHz
+	 * Clear the channel bandwidth for 20MHz
+	 * since channel switch could be happening from 40/80MHz to 20MHz
+	 */
+	chan_offset = wlan_get_second_channel_offset(new_channel);
+	uap_band_cfg->chan2Offset = chan_offset;
+
+	if (!chan_offset) {	/* 40MHz/80MHz */
+		PRINTM(MCMD_D, "20MHz channel, clear channel bandwidth\n");
+		uap_band_cfg->chanWidth = CHAN_BW_20MHZ;
+	}
+	LEAVE();
+}
+
+/**
+ * @brief Get priv current index -- this is used to enter correct rdh_state during radar handling
+ *
+ * @param pmpriv           Pointer to mlan_private
+ * @param pstate_rdh       Pointer to radar detected state handler
+ *
+ * @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_get_priv_curr_idx(mlan_private *pmpriv,
+			   wlan_radar_det_hndlg_state_t *pstate_rdh)
+{
+	t_bool found = MFALSE;
+	ENTER();
+
+	PRINTM(MINFO, "%s:pmpriv =%p\n", __func__, pmpriv);
+	while ((++pstate_rdh->priv_curr_idx) < pstate_rdh->priv_list_count) {
+		if (pmpriv == pstate_rdh->priv_list[pstate_rdh->priv_curr_idx]) {
+			PRINTM(MINFO, "found matching priv: priv_idx=%d\n",
+			       pstate_rdh->priv_curr_idx);
+			found = MTRUE;
+			break;
+		}
+	}
+	return (found == MTRUE) ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Driver handling for remove customeie
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *  @param pmpriv       Pointer to mlan_private
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_11h_remove_custom_ie(mlan_adapter *pmadapter, mlan_private *pmpriv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	wlan_radar_det_hndlg_state_t *pstate_rdh = &pmadapter->state_rdh;
+	mlan_ioctl_req *pioctl_req = MNULL;
+
+	ENTER();
+	if (pstate_rdh->stage == RDH_SET_CUSTOM_IE) {
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		PRINTM(MMSG, "Removing CHAN_SW IE from interfaces.\n");
+		while ((++pstate_rdh->priv_curr_idx) <
+		       pstate_rdh->priv_list_count) {
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+			if (!wlan_11h_is_dfs_master(pmpriv))
+				continue;
+			ret = wlan_11h_prepare_custom_ie_chansw(pmadapter,
+								&pioctl_req,
+								MFALSE);
+			if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+				PRINTM(MERROR,
+				       "%s(): Error in preparing CHAN_SW IE.\n",
+				       __func__);
+				goto done;
+			}
+
+			pioctl_req->bss_index = pmpriv->bss_index;
+			ret = wlan_misc_ioctl_custom_ie_list(pmadapter,
+							     pioctl_req,
+							     MFALSE);
+			if (ret != MLAN_STATUS_SUCCESS &&
+			    ret != MLAN_STATUS_PENDING) {
+				PRINTM(MERROR,
+				       "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
+				       __func__, pmpriv, pmpriv->bss_index);
+				/* TODO: hiow to handle this error case??  ignore & continue? */
+			}
+			/* free ioctl buffer memory before we leave */
+			pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+							(t_u8 *)pioctl_req);
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Driver handling for RADAR_DETECTED event
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *  @param pmpriv       Pointer to mlan_private
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_11h_radar_detected_handling(mlan_adapter *pmadapter, mlan_private *pmpriv)
+{
+#ifdef DEBUG_LEVEL1
+	const char *rdh_stage_str[] = {
+		"RDH_OFF",
+		"RDH_CHK_INTFS",
+		"RDH_STOP_TRAFFIC",
+		"RDH_GET_INFO_CHANNEL",
+		"RDH_GET_INFO_BEACON_DTIM",
+		"RDH_SET_CUSTOM_IE",
+		"RDH_REM_CUSTOM_IE",
+		"RDH_STOP_INTFS",
+		"RDH_SET_NEW_CHANNEL",
+		"RDH_RESTART_INTFS",
+		"RDH_RESTART_TRAFFIC"
+	};
+#endif
+
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 i;
+	wlan_radar_det_hndlg_state_t *pstate_rdh = &pmadapter->state_rdh;
+
+	ENTER();
+
+	if (!pmpriv) {
+		PRINTM(MERROR, "Invalid radar priv -- Exit radar handling\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	switch (pstate_rdh->stage) {
+	case RDH_CHK_INTFS:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s\n",
+		       __func__, pstate_rdh->stage,
+		       rdh_stage_str[pstate_rdh->stage]);
+
+		/* get active interfaces */
+		memset(pmadapter, pstate_rdh->priv_list, 0x00,
+		       sizeof(pstate_rdh->priv_list));
+		pstate_rdh->priv_list_count = wlan_get_privs_by_cond(pmadapter,
+								     wlan_is_intf_active,
+								     pstate_rdh->
+								     priv_list);
+		PRINTM(MCMD_D, "%s():  priv_list_count = %d\n", __func__,
+		       pstate_rdh->priv_list_count);
+		for (i = 0; i < pstate_rdh->priv_list_count; i++)
+			PRINTM(MINFO, "%s():  priv_list[%d] = %p\n",
+			       __func__, i, pstate_rdh->priv_list[i]);
+
+		if (pstate_rdh->priv_list_count == 0) {
+			/* no interfaces active... nothing to do */
+			PRINTM(MMSG, "11h: Radar Detected - no active priv's,"
+			       " skip event handling.\n");
+			pstate_rdh->stage = RDH_OFF;
+			PRINTM(MCMD_D, "%s(): finished - stage(%d)=%s\n",
+			       __func__, pstate_rdh->stage,
+			       rdh_stage_str[pstate_rdh->stage]);
+			break;	/* EXIT CASE */
+		}
+
+		/* else: start handling */
+		pstate_rdh->curr_channel = 0;
+		pstate_rdh->new_channel = 0;
+		memset(pmadapter, &(pstate_rdh->uap_band_cfg), 0,
+		       sizeof(pstate_rdh->uap_band_cfg));
+		pstate_rdh->max_bcn_dtim_ms = 0;
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_STOP_TRAFFIC;
+		/* FALL THROUGH TO NEXT STAGE */
+
+	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 TO NEXT STAGE */
+
+	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
+		}
+#ifdef DFS_TESTING_SUPPORT
+		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;
+		}
+#endif
+		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 TO NEXT STAGE */
+
+	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 TO NEXT STAGE */
+
+	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 TO NEXT STAGE */
+
+	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 TO NEXT STAGE */
+
+	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;
+
+#ifdef DFS_TESTING_SUPPORT
+		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 */
+		}
+#endif
+		/* FALL THROUGH TO NEXT STAGE */
+
+	case RDH_SET_NEW_CHANNEL:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n",
+		       __func__, pstate_rdh->stage,
+		       rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+		/* only set new channel for UAP intfs */
+		while ((++pstate_rdh->priv_curr_idx) <
+		       pstate_rdh->priv_list_count) {
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+
+				pmpriv->uap_state_chan_cb.pioctl_req_curr =
+					MNULL;
+				pmpriv->uap_state_chan_cb.get_chan_callback =
+					wlan_11h_radar_detected_callback;
+
+				/* DFS only in 5GHz */
+				wlan_11h_update_bandcfg(&pstate_rdh->
+							uap_band_cfg,
+							pstate_rdh->
+							new_channel);
+				PRINTM(MCMD_D,
+				       "RDH_SET_NEW_CHANNEL: uAP band config = 0x%x channel=%d\n",
+				       pstate_rdh->uap_band_cfg,
+				       pstate_rdh->new_channel);
+
+				ret = wlan_uap_set_channel(pmpriv,
+							   pstate_rdh->
+							   uap_band_cfg,
+							   pstate_rdh->
+							   new_channel);
+				break;	/* leads to exit case */
+			}
+#endif
+		}
+
+		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
+		    ret == MLAN_STATUS_FAILURE)
+			break;	/* EXIT CASE (for UAP) */
+		/* else */
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_RESTART_INTFS;
+		/* FALL THROUGH TO NEXT STAGE */
+
+	case RDH_RESTART_INTFS:
+#ifdef DFS_TESTING_SUPPORT
+rdh_restart_intfs:
+#endif
+		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 TO NEXT STAGE */
+
+	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;
+
+			/* After RDH_SET_CUSTOM_IE, priv_curr_idx value wasn't reset. Reset priv_curr_idx
+			 * and remove custome ie. The remove needs to be done after every set custom ie
+			 * to avoid the case of adding of duplicate ie */
+			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];
+
+	ENTER();
+	switch (pmadapter->event_cause & EVENT_ID_MASK) {
+	case EVENT_RADAR_DETECTED:
+		/* find active intf:  prefer dfs_master over dfs_slave */
+		if (wlan_get_privs_by_two_cond(pmadapter,
+					       wlan_11h_is_master_active_on_dfs_chan,
+					       wlan_11h_is_dfs_master,
+					       MTRUE, priv_list)) {
+			pmpriv = priv_list[0];
+			PRINTM(MINFO, "%s: found dfs_master priv=%p\n",
+			       __func__, pmpriv);
+		} else if (wlan_get_privs_by_two_cond(pmadapter,
+						      wlan_11h_is_slave_active_on_dfs_chan,
+						      wlan_11h_is_dfs_slave,
+						      MTRUE, priv_list)) {
+			pmpriv = priv_list[0];
+			PRINTM(MINFO, "%s: found dfs_slave priv=%p\n",
+			       __func__, pmpriv);
+		} else if (pmadapter->state_dfs.dfs_check_pending) {
+			pmpriv = (mlan_private *)(pmadapter->state_dfs.
+						  dfs_check_priv);
+			PRINTM(MINFO, "%s: found dfs priv=%p\n", __func__,
+			       pmpriv);
+		}
+
+		/* update event_cause if we found an appropriate priv */
+		if (pmpriv) {
+			pmlan_buffer pmevbuf = pmadapter->pmlan_buffer_event;
+			t_u32 new_event_cause =
+				pmadapter->event_cause & EVENT_ID_MASK;
+			new_event_cause |=
+				((GET_BSS_NUM(pmpriv) & 0xff) << 16) |
+				((pmpriv->bss_type & 0xff) << 24);
+			PRINTM(MINFO, "%s: priv - bss_num=%d, bss_type=%d\n",
+			       __func__, GET_BSS_NUM(pmpriv), pmpriv->bss_type);
+			memcpy(pmadapter, pmevbuf->pbuf + pmevbuf->data_offset,
+			       &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,
+			     Band_Config_t bandcfg, 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();
+
+#ifdef DFS_TESTING_SUPPORT
+	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;
+	}
+#endif
+
+	/*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) ||
+		  !(wlan_11h_is_chan_band_valid
+		    (&chn_tbl->pcfp[rand_entry], bandcfg)) ||
+		  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;
+}
diff --git a/wlan_sd8987/mlan/mlan_11h.h b/wlan_sd8987/mlan/mlan_11h.h
new file mode 100644
index 0000000..0f3eec9
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11h.h
@@ -0,0 +1,195 @@
+/** @file mlan_11h.h
+ *
+ *  @brief This header file contains data structures and
+ *  function declarations of 802.11h
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+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);
+
+#ifdef DFS_TESTING_SUPPORT
+/** 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);
+#endif
+
+extern mlan_status
+
+wlan_11h_ioctl_dfs_cancel_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);
+
+/** 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);
+
+/** 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);
+
+/** 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,
+						Band_Config_t bandcfg,
+						t_u8 *chan);
+
+extern void wlan_11h_update_bandcfg(IN Band_Config_t *uap_band_cfg,
+				    IN 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 100644
index 0000000..cc2123c
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n.c
@@ -0,0 +1,3272 @@
+/** @file mlan_11n.c
+ *
+ *  @brief This file contains functions for 11n handling.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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(IN pmlan_adapter pmadapter,
+			       IN 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_SET) {
+		if (cfg->param.tx_buf_size == 0xffff) {
+			PRINTM(MIOCTL, "Send reconfigure tx buf to FW\n");
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_RECONFIGURE_TX_BUFF,
+					       HostCmd_ACT_GEN_SET, 0,
+					       (t_void *)pioctl_req,
+					       &cfg->param.tx_buf_size);
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = MLAN_STATUS_PENDING;
+			LEAVE();
+			return ret;
+		}
+	}
+	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(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_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(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_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(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_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(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_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(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_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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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(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_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(IN pmlan_adapter pmadapter,
+			    IN 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(pmadapter, cfg->param.addba_reject, pmpriv->addba_reject,
+		       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(IN pmlan_adapter pmadapter,
+				IN 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 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(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_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(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_11n_cfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_REJECT_ADDBA_REQ,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &cfg->param.reject_addba_req);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will send DELBA to entries in the priv's
+ *          Tx BA stream table
+ *
+ *  @param priv                 A pointer to mlan_private
+ *  @param tid                  TID
+ *
+ *  @return		 N/A
+ */
+static void
+wlan_send_delba_txbastream_tbl(pmlan_private priv, t_u8 tid)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	TxBAStreamTbl *tx_ba_stream_tbl_ptr;
+
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	tx_ba_stream_tbl_ptr =
+		(TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+						&priv->tx_ba_stream_tbl_ptr,
+						MNULL, MNULL);
+	if (!tx_ba_stream_tbl_ptr) {
+		wlan_release_ralist_lock(priv);
+		LEAVE();
+		return;
+	}
+
+	while (tx_ba_stream_tbl_ptr !=
+	       (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (tx_ba_stream_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) {
+			if (tid == tx_ba_stream_tbl_ptr->tid) {
+				PRINTM(MIOCTL,
+				       "Tx:Send delba to tid=%d, " MACSTR "\n",
+				       tid, MAC2STR(tx_ba_stream_tbl_ptr->ra));
+				wlan_release_ralist_lock(priv);
+				wlan_send_delba(priv, MNULL,
+						tx_ba_stream_tbl_ptr->tid,
+						tx_ba_stream_tbl_ptr->ra, 1);
+				LEAVE();
+				return;
+			}
+		}
+		tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext;
+	}
+	wlan_release_ralist_lock(priv);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief update station list for the new aggr_prio_tbl setting
+ *
+ *  @param priv 	A pointer to mlan_private structure
+ *
+ *
+ *  @return		N/A
+ */
+void
+wlan_update_all_stations_ampdu(mlan_private *priv)
+{
+	sta_node *sta_ptr;
+	mlan_adapter *pmadapter = priv->adapter;
+	int i = 0;
+
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	sta_ptr = (sta_node *)util_peek_list(pmadapter->pmoal_handle,
+					     &priv->sta_list, MNULL, MNULL);
+	if (!sta_ptr) {
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		LEAVE();
+		return;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			if (sta_ptr->is_11n_enabled)
+				sta_ptr->ampdu_sta[i] =
+					priv->aggr_prio_tbl[i].ampdu_user;
+		}
+		sta_ptr = sta_ptr->pnext;
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Set/get aggr_prio_tbl
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_aggr_prio_tbl(IN pmlan_adapter pmadapter,
+			     IN 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(IN pmlan_adapter pmadapter,
+				 IN 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(pmadapter, cfg->param.supported_mcs_set, mcs_set, 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 */
+	if (priv->adapter->psdio_device->v15_fw_api) {
+		RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+	} else {
+		if (GET_DELAYEDBACK(priv->adapter->hw_dot_11n_dev_cap))
+			SETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+		else
+			RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+	}
+
+	/* Need change to support 8k AMSDU receive */
+	RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+	/* SM power save */
+	if (ISSUPP_MIMOPS(priv->adapter->hw_dot_11n_dev_cap))
+		RESETHT_SM_POWERSAVE(ht_cap->ht_cap_info);	/* Enable HT SMPS */
+	else
+		SETHT_STATIC_SMPS(ht_cap->ht_cap_info);	/* Disable HT SMPS */
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function clear the bit in cap info which we don't support
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_reset_cap_info(mlan_private *priv, HTCap_t *ht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11n_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+	if (!ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
+		RESETHT_GREENFIELD(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
+		RESETHT_SHORTGI20(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+	if (!ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
+		RESETHT_RXSTBC(ht_cap->ht_cap_info);
+
+	if (!ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+
+	/** if current channel only allow 20Mhz, we should cler 40Mhz support */
+	if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	    priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+	}
+	/* No user config for LDPC coding capability yet */
+	if (!ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
+		RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+
+	/* No user config for TX STBC yet */
+	if (!ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
+		RESETHT_TXSTBC(ht_cap->ht_cap_info);
+
+	/* No user config for Delayed BACK yet */
+	if (priv->adapter->psdio_device->v15_fw_api) {
+		RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+	} else {
+		if (!GET_DELAYEDBACK(priv->adapter->hw_dot_11n_dev_cap))
+			RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+	}
+
+	/* Need change to support 8k AMSDU receive */
+	RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+	/* SM power save */
+	if (!ISSUPP_MIMOPS(priv->adapter->hw_dot_11n_dev_cap))
+		SETHT_STATIC_SMPS(ht_cap->ht_cap_info);	/* Disable HT SMPS */
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function fills the HT cap tlv
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *  @param fill         A flag for fill the htcap info
+ *
+ *  @return             N/A
+ */
+void
+wlan_fill_ht_cap_tlv(mlan_private *priv,
+		     MrvlIETypes_HTCap_t *pht_cap, t_u8 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);
+	/* 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_u8 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);
+	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"));
+
+	if (pmadapter->psdio_device->v15_fw_api) {
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Number of Tx BA streams supported = %d\n",
+		       ISSUPP_GETTXBASTREAM(cap));
+	} else {
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Number of Delayed Block Ack streams = %d\n",
+		       GET_DELAYEDBACK(cap));
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Number of Immediate Block Ack streams = %d\n",
+		       GET_IMMEDIATEBACK(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 (priv->bss_mode == MLAN_BSS_MODE_IBSS)
+				disable_station_ampdu(priv, tid,
+						      padd_ba_rsp->
+						      peer_mac_addr);
+			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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *cmd,
+		 IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *cmd,
+		   IN t_u16 cmd_action, IN 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(pmadapter, txbfcfg->body.bf_periodicity.peer_mac,
+		       txbf->body.bf_periodicity[0].peer_mac,
+		       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(pmadapter, txbfcfg->body.bf_sound_args.peer_mac,
+			       txbf->body.bf_sound[0].peer_mac,
+			       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(pmadapter, txbfcfg->body.tx_bf_peer.peer_mac,
+			       txbf->body.tx_bf_peer[0].peer_mac,
+			       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(pmadapter, txbfcfg->body.bf_snr.peer_mac,
+			       txbf->body.bf_snr[0].peer_mac,
+			       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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *resp, IN 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(pmadapter, txbf->body.bf_sound[0].peer_mac,
+			       txbfcfg->body.bf_sound_args.peer_mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			txbf->body.bf_sound[0].status =
+				txbfcfg->body.bf_sound_args.status;
+			break;
+		case SET_GET_BF_PERIODICITY:
+			memcpy(pmadapter, txbf->body.bf_periodicity->peer_mac,
+			       txbfcfg->body.bf_periodicity.peer_mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			txbf->body.bf_periodicity->interval =
+				wlan_le16_to_cpu(txbfcfg->body.bf_periodicity.
+						 interval);
+			break;
+		case TX_BF_FOR_PEER_ENBL:
+			txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+			tx_bf_peer =
+				(bf_peer_args *)((t_u8 *)&txbfcfg->body +
+						 sizeof(t_u8));
+			for (i = 0; i < txbf->no_of_peers; i++) {
+				memcpy(pmadapter,
+				       txbf->body.tx_bf_peer[i].peer_mac,
+				       (t_u8 *)tx_bf_peer->peer_mac,
+				       MLAN_MAC_ADDR_LENGTH);
+				txbf->body.tx_bf_peer[i].bf_enbl =
+					tx_bf_peer->bf_enbl;
+				txbf->body.tx_bf_peer[i].sounding_enbl =
+					tx_bf_peer->sounding_enbl;
+				txbf->body.tx_bf_peer[i].fb_type =
+					tx_bf_peer->fb_type;
+				tx_bf_peer++;
+			}
+			break;
+		case SET_SNR_THR_PEER:
+			txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+			bf_snr = (bf_snr_thr_t *)((t_u8 *)&txbfcfg->body +
+						  sizeof(t_u8));
+			for (i = 0; i < txbf->no_of_peers; i++) {
+				memcpy(pmadapter, txbf->body.bf_snr[i].peer_mac,
+				       (t_u8 *)bf_snr->peer_mac,
+				       MLAN_MAC_ADDR_LENGTH);
+				txbf->body.bf_snr[i].snr = bf_snr->snr;
+				bf_snr++;
+			}
+			break;
+		default:
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get second channel offset
+ *
+ * @param chan            channel num
+ * @return                second channel offset
+ */
+t_u8
+wlan_get_second_channel_offset(int chan)
+{
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+
+	switch (chan) {
+	case 36:
+	case 44:
+	case 52:
+	case 60:
+	case 100:
+	case 108:
+	case 116:
+	case 124:
+	case 132:
+	case 140:
+	case 149:
+	case 157:
+		chan2Offset = SEC_CHAN_ABOVE;
+		break;
+	case 40:
+	case 48:
+	case 56:
+	case 64:
+	case 104:
+	case 112:
+	case 120:
+	case 128:
+	case 136:
+	case 144:
+	case 153:
+	case 161:
+		chan2Offset = SEC_CHAN_BELOW;
+		break;
+	case 165:
+		/* Special Case: 20Mhz-only Channel */
+		chan2Offset = SEC_CHAN_NONE;
+		break;
+	}
+	return chan2Offset;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief validate the channel offset for Infra/Ad-hoc band configuration
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param band         band
+ *  @param chan         primary channel
+ *  @param chan_bw      channel bandwidth
+ *
+ *  @return             channel offset (NO_SEC_CHANNEL, SEC_CHANNEL_ABOVE,
+ *                                      SEC_CHANNEL_BELOW)
+ */
+t_u8
+wlan_validate_chan_offset(IN mlan_private *pmpriv,
+			  IN t_u8 band, IN t_u32 chan, IN t_u8 chan_bw)
+{
+	t_u8 chan_offset;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+
+	if (chan_bw == CHANNEL_BW_40MHZ_ABOVE)
+		chan_offset = SEC_CHAN_ABOVE;
+	else if (chan_bw == CHANNEL_BW_40MHZ_BELOW)
+		chan_offset = SEC_CHAN_BELOW;
+	else
+		chan_offset = SEC_CHAN_NONE;
+
+	/* validation */
+	if (chan_offset != SEC_CHAN_NONE) {
+		if (band & BAND_GN) {
+			if ((chan == 1) || (chan == 2) || (chan == 3) ||
+			    (chan == 4))
+				chan_offset = SEC_CHAN_ABOVE;
+			else if ((chan == 10) || (chan == 11) ||
+				 (chan == 12) || (chan == 13))
+				chan_offset = SEC_CHAN_BELOW;
+
+			/* check if channel 12 is supported in the region */
+			if (!wlan_find_cfp_by_band_and_channel
+			    (pmadapter, band, 12))
+				if ((chan == 8) || (chan == 9))
+					chan_offset = SEC_CHAN_BELOW;
+		} else if (band & BAND_AN)
+			chan_offset = wlan_get_second_channel_offset(chan);
+	}
+	return chan_offset;
+}
+
+/**
+ *  @brief This function check if ht40 is allowed in current region
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc    A pointer to BSSDescriptor_t structure
+ *
+ *  @return MTRUE/MFALSE
+ */
+static int
+wlan_check_chan_width_ht40_by_region(IN mlan_private *pmpriv,
+				     IN 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 && 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(IN mlan_private *pmpriv,
+			IN BSSDescriptor_t *pbss_desc, OUT t_u8 **ppbuffer)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	MrvlIETypes_HTCap_t *pht_cap;
+	MrvlIETypes_HTInfo_t *pht_info;
+	MrvlIEtypes_ChanListParamSet_t *pchan_list;
+	MrvlIETypes_2040BSSCo_t *p2040_bss_co;
+	MrvlIETypes_ExtCap_t *pext_cap;
+	t_u32 usr_dot_11n_dev_cap, orig_usr_dot_11n_dev_cap = 0;
+	t_u32 usr_vht_cap_info;
+	t_u8 usr_dot_11ac_bw;
+	int ret_len = 0;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+
+	if (pbss_desc->bss_band & BAND_A)
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
+
+	if (pbss_desc->bss_band & BAND_A)
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_bg;
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+		usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
+	else
+		usr_dot_11ac_bw = pmpriv->usr_dot_11ac_bw;
+	if ((pbss_desc->bss_band & (BAND_B | BAND_G
+				    | BAND_A)) &&
+	    ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+	    !wlan_check_chan_width_ht40_by_region(pmpriv, pbss_desc)) {
+		orig_usr_dot_11n_dev_cap = usr_dot_11n_dev_cap;
+		RESETSUPP_CHANWIDTH40(usr_dot_11n_dev_cap);
+		RESET_40MHZ_INTOLARENT(usr_dot_11n_dev_cap);
+		RESETSUPP_SHORTGI40(usr_dot_11n_dev_cap);
+		pmpriv->usr_dot_11n_dev_cap_bg = usr_dot_11n_dev_cap;
+		pbss_desc->curr_bandwidth = BW_20MHZ;
+	}
+	if (pbss_desc->pht_cap) {
+		pht_cap = (MrvlIETypes_HTCap_t *)*ppbuffer;
+		memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
+		pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
+		pht_cap->header.len = sizeof(HTCap_t);
+		memcpy(pmadapter, (t_u8 *)pht_cap + sizeof(MrvlIEtypesHeader_t),
+		       (t_u8 *)pbss_desc->pht_cap + sizeof(IEEEtypes_Header_t),
+		       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);
+
+		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) {
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+			pht_info = (MrvlIETypes_HTInfo_t *)*ppbuffer;
+			memset(pmadapter, pht_info, 0,
+			       sizeof(MrvlIETypes_HTInfo_t));
+			pht_info->header.type = wlan_cpu_to_le16(HT_OPERATION);
+			pht_info->header.len = sizeof(HTInfo_t);
+
+			memcpy(pmadapter,
+			       (t_u8 *)pht_info + sizeof(MrvlIEtypesHeader_t),
+			       (t_u8 *)pbss_desc->pht_info +
+			       sizeof(IEEEtypes_Header_t),
+			       pht_info->header.len);
+
+			if (!ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+				RESET_CHANWIDTH40(pht_info->ht_info.field2);
+
+			*ppbuffer += sizeof(MrvlIETypes_HTInfo_t);
+			ret_len += sizeof(MrvlIETypes_HTInfo_t);
+			pht_info->header.len =
+				wlan_cpu_to_le16(pht_info->header.len);
+		}
+
+		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;
+			if (pmpriv->adapter->psdio_device->v15_update)
+				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(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);
+
+		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(pmadapter,
+		       (t_u8 *)pext_cap + sizeof(MrvlIEtypesHeader_t),
+		       (t_u8 *)&pmpriv->ext_cap, sizeof(ExtCap_t));
+		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, 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(IN pmlan_adapter pmadapter, IN 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;
+	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(pmadapter, new_node->ra, ra, 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(priv->adapter, &add_ba_req.peer_mac_addr, peer_mac,
+	       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(priv->adapter, &delba.peer_mac_addr, peer_mac,
+	       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(priv->adapter, ptbl->ta, rx_reorder_tbl_ptr->ta,
+		       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;
+	}
+	if (priv->adapter->psdio_device->v15_fw_api) {
+		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(priv->adapter, ptbl->ra, ptxtbl->ra,
+		       MLAN_MAC_ADDR_LENGTH);
+		ptbl->amsdu = ptxtbl->amsdu;
+		ptxtbl = ptxtbl->pnext;
+		ptbl++;
+		count++;
+		if ((priv->adapter->psdio_device->v15_fw_api &&
+		     (count >= bastream_max)) ||
+		    (!priv->adapter->psdio_device->v15_fw_api &&
+		     (count >= MLAN_MAX_TX_BASTREAM_SUPPORTED_NOV15)))
+			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 100644
index 0000000..16b9481
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n.h
@@ -0,0 +1,438 @@
+/** @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 (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf);
+/** Prepare 11ncfg command */
+mlan_status wlan_cmd_11n_cfg(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action,
+			     IN t_void *pdata_buf);
+/** Prepare reject addba requst command */
+mlan_status wlan_cmd_reject_addba_req(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_u16 cmd_action,
+				      IN t_void *pdata_buf);
+/** Handle the command response of rejecting addba request */
+mlan_status wlan_ret_reject_addba_req(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+/** Prepare TX BF configuration command */
+mlan_status wlan_cmd_tx_bf_cfg(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action, IN t_void *pdata_buf);
+/** Handle the command response TX BF configuration */
+mlan_status wlan_ret_tx_bf_cfg(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *resp,
+			       IN 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(IN mlan_private *pmpriv,
+			    IN BSSDescriptor_t *pbss_desc, OUT t_u8 **ppbuffer);
+/** wlan fill HT cap tlv */
+void wlan_fill_ht_cap_tlv(mlan_private *priv, MrvlIETypes_HTCap_t *pht_cap,
+			  t_u8 band, t_u8 fill);
+/** wlan fill HT cap IE */
+void wlan_fill_ht_cap_ie(mlan_private *priv, IEEEtypes_HTCap_t *pht_cap,
+			 t_u8 bands);
+#endif /* STA_SUPPORT */
+/** Miscellaneous configuration handler */
+mlan_status wlan_11n_cfg_ioctl(IN pmlan_adapter pmadapter,
+			       IN 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(IN mlan_private *pmpriv,
+			       IN t_u8 band, IN t_u32 chan, IN t_u8 chan_bw);
+/** get channel offset */
+t_u8 wlan_get_second_channel_offset(int chan);
+
+void wlan_update_11n_cap(mlan_private *pmpriv);
+
+/** clean up txbastream_tbl */
+void wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra);
+/**
+ *  @brief This function checks whether a station has 11N enabled or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param mac      station mac address
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+is_station_11n_enabled(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		return (sta_ptr->is_11n_enabled) ? MTRUE : MFALSE;
+	return MFALSE;
+}
+
+/**
+ *  @brief This function get station max amsdu size
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param mac      station mac address
+ *  @return         max amsdu size statio supported
+ */
+static INLINE t_u16
+get_station_max_amsdu_size(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		return sta_ptr->max_amsdu;
+	return 0;
+}
+
+/**
+ *  @brief This function checks whether a station allows AMPDU or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ptr      A pointer to RA list table
+ *  @param tid      TID value for ptr
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+is_station_ampdu_allowed(mlan_private *priv, raListTbl *ptr, int tid)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+	if (sta_ptr) {
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			if (priv->sec_info.wapi_enabled &&
+			    !sta_ptr->wapi_key_on)
+				return MFALSE;
+		}
+		return (sta_ptr->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED)
+			? MTRUE : MFALSE;
+	}
+	return MFALSE;
+}
+
+/**
+ *  @brief This function disable station ampdu for specific tid
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param tid     tid index
+ *  @param ra      station mac address
+ *  @return        N/A
+ */
+static INLINE void
+disable_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ra);
+	if (sta_ptr)
+		sta_ptr->ampdu_sta[tid] = BA_STREAM_NOT_ALLOWED;
+	return;
+}
+
+/**
+ *  @brief This function reset station ampdu for specific id to user setting.
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param tid     tid index
+ *  @param ra      station mac address
+ *  @return        N/A
+ */
+static INLINE void
+reset_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ra);
+	if (sta_ptr)
+		sta_ptr->ampdu_sta[tid] = priv->aggr_prio_tbl[tid].ampdu_user;
+	return;
+}
+
+#define IS_BG_RATE (priv->bitmap_rates[0] || priv->bitmap_rates[1])
+/**
+ *  @brief This function checks whether AMPDU is allowed or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ptr      A pointer to RA list table
+ *  @param tid      TID value for ptr
+ *
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+wlan_is_ampdu_allowed(mlan_private *priv, raListTbl *ptr, int tid)
+{
+	if (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;
+	if (priv->bss_mode == MLAN_BSS_MODE_IBSS)
+		return is_station_ampdu_allowed(priv, ptr, tid);
+	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_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+		return wlan_update_station_del_ba_count(priv, ptr);
+#endif /* UAP_SUPPORT */
+	if (ptr->is_tdls_link)
+		return wlan_update_station_del_ba_count(priv, ptr);
+	if (priv->bss_mode == MLAN_BSS_MODE_IBSS)
+		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;
+	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);
+	}
+	if (priv->adapter->psdio_device->v15_fw_api) {
+		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;
+	} else {
+		return (bastream_num <
+			MLAN_MAX_TX_BASTREAM_SUPPORTED_NOV15) ? 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(priv->adapter, ra, ptx_tbl->ra,
+			       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 */
+#ifdef STA_SUPPORT
+	if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
+		if ((!(ra[0] & 0x01)) && (priv->adapter->adhoc_11n_enabled))
+			ret = is_station_11n_enabled(priv, ra);
+	}
+#endif
+	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 100644
index 0000000..1d6d5fe
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n_aggr.c
@@ -0,0 +1,595 @@
+/** @file mlan_11n_aggr.c
+ *
+ *  @brief This file contains functions for 11n Aggregation.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.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(pmadapter, amsdu_buf, data, (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(pmadapter, amsdu_buf + amsdu_buf_offset, &snap, LLC_SNAP_LEN);
+	amsdu_buf_offset += LLC_SNAP_LEN;
+
+	memcpy(pmadapter, amsdu_buf + amsdu_buf_offset, data + 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 };
+
+	ENTER();
+
+	data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+	total_pkt_len = pmbuf->data_len;
+
+	/* Sanity test */
+	if (total_pkt_len > max_rx_data_size) {
+		PRINTM(MERROR, "Total packet length greater than tx buffer"
+		       " size %d\n", total_pkt_len);
+		goto done;
+	}
+
+	pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len);
+
+	while (total_pkt_len >= hdr_len) {
+		prx_pkt = (RxPacketHdr_t *)data;
+		/* Length will be in network format, change it to host */
+		pkt_len = mlan_ntohs((*(t_u16 *)(data + (2 *
+							 MLAN_MAC_ADDR_LENGTH))));
+		if (pkt_len > total_pkt_len) {
+			PRINTM(MERROR,
+			       "Error in packet length: total_pkt_len = %d, pkt_len = %d\n",
+			       total_pkt_len, pkt_len);
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+
+		pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
+			(4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;
+
+		total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);
+
+		if (memcmp(pmadapter, &prx_pkt->rfc1042_hdr,
+			   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
+			memmove(pmadapter, data + LLC_SNAP_LEN, data, (2 *
+								       MLAN_MAC_ADDR_LENGTH));
+			data += LLC_SNAP_LEN;
+			pkt_len += sizeof(Eth803Hdr_t) - LLC_SNAP_LEN;
+		} else {
+			*(t_u16 *)(data + (2 * MLAN_MAC_ADDR_LENGTH))
+				= (t_u16)0;
+			pkt_len += sizeof(Eth803Hdr_t);
+		}
+		daggr_mbuf =
+			wlan_alloc_mlan_buffer(pmadapter,
+					       pkt_len + MLAN_NET_IP_ALIGN, 0,
+					       MOAL_ALLOC_MLAN_BUFFER);
+		if (daggr_mbuf == MNULL) {
+			PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		daggr_mbuf->data_offset += MLAN_NET_IP_ALIGN;
+		daggr_mbuf->bss_index = pmbuf->bss_index;
+		daggr_mbuf->buf_type = pmbuf->buf_type;
+		daggr_mbuf->data_len = pkt_len;
+		daggr_mbuf->in_ts_sec = pmbuf->in_ts_sec;
+		daggr_mbuf->in_ts_usec = pmbuf->in_ts_usec;
+		daggr_mbuf->pparent = pmbuf;
+		daggr_mbuf->priority = pmbuf->priority;
+		memcpy(pmadapter, daggr_mbuf->pbuf + daggr_mbuf->data_offset,
+		       data, pkt_len);
+
+#ifdef UAP_SUPPORT
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			ret = wlan_uap_recv_packet(priv, daggr_mbuf);
+		} else {
+#endif /* UAP_SUPPORT */
+		/** send EAPOL from AMSDU pkt to firmware */
+			if (priv->sec_info.ewpa_enabled &&
+			    (!memcmp
+			     (pmadapter,
+			      daggr_mbuf->pbuf + daggr_mbuf->data_offset +
+			      MLAN_ETHER_PKT_TYPE_OFFSET, eapol_type,
+			      sizeof(eapol_type)))) {
+				ret = wlan_prepare_cmd(priv,
+						       HostCmd_CMD_802_11_EAPOL_PKT,
+						       0, 0, MNULL, daggr_mbuf);
+				if (ret == MLAN_STATUS_SUCCESS)
+					wlan_recv_event(priv,
+							MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+							MNULL);
+				wlan_free_mlan_buffer(pmadapter, daggr_mbuf);
+				data += pkt_len + pad;
+				continue;
+			}
+	/**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;
+		case MLAN_STATUS_SUCCESS:
+			wlan_recv_packet_complete(pmadapter, daggr_mbuf, ret);
+			break;
+		default:
+			break;
+		}
+
+		data += pkt_len + pad;
+	}
+
+done:
+	priv->msdu_in_rx_amsdu_cnt += pmbuf->use_count;
+	priv->amsdu_rx_cnt++;
+    /** we should free the aggr buffer after deaggr */
+	wlan_free_mlan_buffer(pmadapter, pmbuf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Aggregate multiple packets into one single AMSDU packet
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param pra_list Pointer to the RA List table containing the pointers
+ *                  to packets.
+ *  @param headroom Any interface specific headroom that may be need. TxPD
+ *                  will be formed leaving this headroom.
+ *  @param ptrindex Pointer index
+ *
+ *  @return     Final packet size or MLAN_STATUS_FAILURE
+ */
+int
+wlan_11n_aggregate_pkt(mlan_private *priv, raListTbl *pra_list,
+		       int headroom, int ptrindex)
+{
+	int pkt_size = 0;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_buffer *pmbuf_aggr, *pmbuf_src;
+	t_u8 *data;
+	int pad = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	mlan_tx_param tx_param;
+#ifdef STA_SUPPORT
+	TxPD *ptx_pd = MNULL;
+#endif
+	t_u32 max_amsdu_size = MIN(pra_list->max_amsdu, pmadapter->tx_buf_size);
+	ENTER();
+
+	PRINTM(MDAT_D, "Handling Aggr packet\n");
+
+	pmbuf_src =
+		(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+					     &pra_list->buf_head, MNULL, MNULL);
+	if (pmbuf_src) {
+		pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter,
+						    pmadapter->tx_buf_size, 0,
+						    MOAL_MALLOC_BUFFER);
+		if (!pmbuf_aggr) {
+			PRINTM(MERROR, "Error allocating mlan_buffer\n");
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		data = pmbuf_aggr->pbuf + headroom;
+		pmbuf_aggr->bss_index = pmbuf_src->bss_index;
+		pmbuf_aggr->buf_type = pmbuf_src->buf_type;
+		pmbuf_aggr->priority = pmbuf_src->priority;
+		pmbuf_aggr->pbuf = data;
+		pmbuf_aggr->data_offset = 0;
+		pmbuf_aggr->in_ts_sec = pmbuf_src->in_ts_sec;
+		pmbuf_aggr->in_ts_usec = pmbuf_src->in_ts_usec;
+		if (pmbuf_src->flags & MLAN_BUF_FLAG_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);
+
+		pra_list->total_pkts--;
+
+		/* decrement for every PDU taken from the list */
+		priv->wmm.pkts_queued[ptrindex]--;
+		util_scalar_decrement(pmadapter->pmoal_handle,
+				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+
+		if (pmbuf_src) {
+			pkt_size += wlan_11n_form_amsdu_pkt(pmadapter,
+							    (data + pkt_size),
+							    pmbuf_src->pbuf +
+							    pmbuf_src->
+							    data_offset,
+							    pmbuf_src->data_len,
+							    &pad);
+
+			DBG_HEXDUMP(MDAT_D, "pmbuf_src", pmbuf_src,
+				    sizeof(mlan_buffer));
+			wlan_write_data_complete(pmadapter, pmbuf_src,
+						 MLAN_STATUS_SUCCESS);
+		}
+		pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+						    priv->wmm.ra_list_spinlock);
+
+		if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		pmbuf_src =
+			(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &pra_list->buf_head, MNULL,
+						     MNULL);
+		priv->msdu_in_tx_amsdu_cnt++;
+	}
+
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+
+	/* Last AMSDU packet does not need padding */
+	pkt_size -= pad;
+	pmbuf_aggr->data_len = pkt_size;
+	wlan_11n_update_pktlen_amsdu_txpd(priv, pmbuf_aggr);
+	pmbuf_aggr->data_len += headroom;
+	pmbuf_aggr->pbuf = data - headroom;
+	tx_param.next_pkt_len = ((pmbuf_src) ?
+				 pmbuf_src->data_len + sizeof(TxPD) : 0);
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA,
+				     pmbuf_aggr, &tx_param);
+	switch (ret) {
+	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;
+			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:
+		pmadapter->data_sent = MFALSE;
+		PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
+		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 100644
index 0000000..6ad87a3
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n_aggr.h
@@ -0,0 +1,37 @@
+/** @file mlan_11n_aggr.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of 11n aggregation functionalities
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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 100644
index 0000000..a7902ae
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n_rxreorder.c
@@ -0,0 +1,1659 @@
+/** @file mlan_11n_rxreorder.c
+ *
+ *  @brief This file contains the handling of RxReordering in wlan
+ *  driver.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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;
+	pmlan_adapter pmadapter = ((pmlan_private)priv)->adapter;
+
+	ENTER();
+	if (payload == (t_void *)RX_PKT_DROPPED_IN_FW) {
+		LEAVE();
+		return ret;
+	}
+	if (ISSUPP_RSN_REPLAY_DETECTION(pmadapter->fw_cap_info) &&
+	    rx_reor_tbl_ptr &&
+	    wlan_is_rsn_replay_attack((mlan_private *)priv, payload,
+				      rx_reor_tbl_ptr)) {
+		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);
+	if (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));
+	else
+		PRINTM(MMSG, "rx_reor_tbl_ptr: %p timer is NULL\n", rx_reor_tbl_ptr);
+	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(t_void *) * 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(pmadapter, new_node->ta, ta, 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];
+		}
+		if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
+			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;
+
+	new_node->hi_curr_rx_count32 = 0xffffffff;
+	new_node->lo_curr_rx_count16 = 0;
+
+	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(priv->adapter, padd_ba_req, pdata_buf,
+	       sizeof(HostCmd_DS_11N_ADDBA_REQ));
+	padd_ba_req->block_ack_param_set =
+		wlan_cpu_to_le16(padd_ba_req->block_ack_param_set);
+	padd_ba_req->block_ack_tmo =
+		wlan_cpu_to_le16(padd_ba_req->block_ack_tmo);
+	padd_ba_req->ssn = wlan_cpu_to_le16(padd_ba_req->ssn);
+	padd_ba_req->add_req_result = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+  *  @brief This function check if AMPDU Rx allowed
+  *
+  *  @param priv        A pointer to mlan_private structure
+  *  @param tid         TID
+  *
+  *  @return            MTRUE/MFALSE
+  */
+t_u8
+wlan_is_addba_reject(mlan_private *priv, t_u8 tid)
+{
+#ifdef STA_SUPPORT
+	if (priv->bss_mode == MLAN_BSS_MODE_IBSS)
+		return priv->ibss_addba_reject[tid];
+#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(priv->adapter, padd_ba_rsp->peer_mac_addr,
+	       pevt_addba_req->peer_mac_addr, 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
+	    || ((priv->bss_mode == MLAN_BSS_MODE_IBSS)
+		&& !wlan_is_11n_enabled(priv, pevt_addba_req->peer_mac_addr))
+	    || ((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(priv->adapter, pdel_ba, pdata_buf, 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 is to reset PN value when ptk rekey
+  *  @param pmpriv                pointer to mlan_private
+  *  @param key               pointer to mlan_ds_encrypt_key
+  *
+  *  @return                     N/A
+  */
+t_void wlan_reset_pn_value(mlan_private *pmpriv, mlan_ds_encrypt_key *key)
+{
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+
+	t_u8 tid = 0;
+	ENTER();
+	if (key->key_flags & KEY_FLAG_REMOVE_KEY
+	    || key->key_flags & KEY_FLAG_GROUP_KEY)
+		goto done;
+
+	for (tid = 0; tid < 7; tid++) {
+		rx_reor_tbl_ptr =
+			wlan_11n_get_rxreorder_tbl(pmpriv, tid, key->mac_addr);
+		if (rx_reor_tbl_ptr) {
+			rx_reor_tbl_ptr->hi_curr_rx_count32 = 0xffffffff;
+			rx_reor_tbl_ptr->lo_curr_rx_count16 = 0;
+		}
+	}
+
+done:
+	LEAVE();
+	return ;
+}
+
+
+
+
+/**
+ *  @brief This function check PN numbers to detect replay counter attack
+ *  @param pmpriv                pointer to mlan_private
+ *  @param payload               pointer to mlan_buffer
+ *  @param rx_reor_tbl_ptr       pointer to RxReorderTbl
+ *
+ *  @return                      MTRUE/MFALSE
+ */
+t_u8
+wlan_is_rsn_replay_attack(mlan_private *pmpriv, t_void *payload,
+			  RxReorderTbl *rx_reor_tbl_ptr)
+{
+	RxPD *prx_pd = MNULL;
+	pmlan_buffer pmbuf = MNULL;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	pmbuf = (pmlan_buffer)payload;
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+
+	if (!(prx_pd->flags & RXPD_FLAG_PN_CHECK_SUPPORT)) {
+		LEAVE();
+		return MFALSE;
+	}
+
+	if ((prx_pd->hi_rx_count32 == rx_reor_tbl_ptr->hi_curr_rx_count32 &&
+	     prx_pd->lo_rx_count16 <= rx_reor_tbl_ptr->lo_curr_rx_count16)
+	    || (rx_reor_tbl_ptr->hi_curr_rx_count32 != 0xffffffff &&
+		prx_pd->hi_rx_count32 < rx_reor_tbl_ptr->hi_curr_rx_count32)) {
+		PRINTM(MERROR,
+		       "Drop packet because of invalid PN value. Last PN:0x%x 0x%x,New PN:0x%x 0x%x\n",
+		       rx_reor_tbl_ptr->hi_curr_rx_count32,
+		       rx_reor_tbl_ptr->lo_curr_rx_count16,
+		       prx_pd->hi_rx_count32, prx_pd->lo_rx_count16);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		LEAVE();
+		return MTRUE;
+	}
+
+	rx_reor_tbl_ptr->lo_curr_rx_count16 = prx_pd->lo_rx_count16;
+	rx_reor_tbl_ptr->hi_curr_rx_count32 = prx_pd->hi_rx_count32;
+
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @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(priv->adapter, delba.peer_mac_addr, event->peer_mac_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	delba.del_ba_param_set |= (t_u16)event->tid << DELBA_TID_POS;
+	delba.del_ba_param_set |=
+		(t_u16)event->origninator << DELBA_INITIATOR_POS;
+	delba.reason_code = REASON_CODE_STA_TIMEOUT;
+	wlan_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, MNULL, &delba);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function cleans up reorder tbl
+ *
+ *  @param priv     A pointer to mlan_private
+ *
+ *  @return         N/A
+ */
+void
+wlan_11n_cleanup_reorder_tbl(mlan_private *priv)
+{
+	RxReorderTbl *del_tbl_ptr;
+
+	ENTER();
+
+	while ((del_tbl_ptr = (RxReorderTbl *)
+		util_peek_list(priv->adapter->pmoal_handle,
+			       &priv->rx_reorder_tbl_ptr,
+			       priv->adapter->callbacks.moal_spin_lock,
+			       priv->adapter->callbacks.moal_spin_unlock))) {
+		wlan_11n_delete_rxreorder_tbl_entry(priv, del_tbl_ptr);
+	}
+
+	util_init_list((pmlan_linked_list)&priv->rx_reorder_tbl_ptr);
+
+	memset(priv->adapter, priv->rx_seq, 0xff, sizeof(priv->rx_seq));
+	LEAVE();
+}
+
+/**
+ *  @brief This function handle the rxba_sync event
+ *
+ *  @param priv       A pointer to mlan_private
+ *  @param event_buf  A pointer to event buf
+ *  @param len        event_buf length
+ *  @return           N/A
+ */
+void
+wlan_11n_rxba_sync_event(mlan_private *priv, t_u8 *event_buf, t_u16 len)
+{
+	MrvlIEtypes_RxBaSync_t *tlv_rxba = (MrvlIEtypes_RxBaSync_t *)event_buf;
+	t_u16 tlv_type, tlv_len;
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+	t_u8 i, j;
+	t_u16 seq_num = 0;
+	int tlv_buf_left = len;
+	ENTER();
+
+	DBG_HEXDUMP(MEVT_D, "RXBA_SYNC_EVT", event_buf, len);
+	while (tlv_buf_left >= sizeof(MrvlIEtypes_RxBaSync_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv_rxba->header.type);
+		tlv_len = wlan_le16_to_cpu(tlv_rxba->header.len);
+		if (tlv_type != TLV_TYPE_RXBA_SYNC) {
+			PRINTM(MERROR, "Wrong TLV id=0x%x\n", tlv_type);
+			goto done;
+		}
+		tlv_rxba->seq_num = wlan_le16_to_cpu(tlv_rxba->seq_num);
+		tlv_rxba->bitmap_len = wlan_le16_to_cpu(tlv_rxba->bitmap_len);
+		PRINTM(MEVENT, MACSTR " tid=%d seq_num=%d bitmap_len=%d\n",
+		       MAC2STR(tlv_rxba->mac), tlv_rxba->tid, tlv_rxba->seq_num,
+		       tlv_rxba->bitmap_len);
+		rx_reor_tbl_ptr =
+			wlan_11n_get_rxreorder_tbl(priv, tlv_rxba->tid,
+						   tlv_rxba->mac);
+		if (!rx_reor_tbl_ptr) {
+			PRINTM(MEVENT, "Can not find rx_reorder_tbl\n");
+			goto done;
+		}
+		if (rx_reor_tbl_ptr->force_no_drop) {
+			PRINTM(MEVENT, "Ignore RXBA_SYNC_EVT in resume\n");
+			goto done;
+		}
+		for (i = 0; i < tlv_rxba->bitmap_len; i++) {
+			for (j = 0; j < 8; j++) {
+				if (tlv_rxba->bitmap[i] & (1 << j)) {
+					seq_num =
+						(tlv_rxba->seq_num + i * 8 +
+						 j) & (MAX_TID_VALUE - 1);
+					PRINTM(MEVENT,
+					       "Fw dropped packet, seq=%d start_win=%d, win_size=%d\n",
+					       seq_num,
+					       rx_reor_tbl_ptr->start_win,
+					       rx_reor_tbl_ptr->win_size);
+					if (MLAN_STATUS_SUCCESS !=
+					    mlan_11n_rxreorder_pkt(priv,
+								   seq_num,
+								   tlv_rxba->
+								   tid,
+								   tlv_rxba->
+								   mac, 0,
+								   (t_void *)
+								   RX_PKT_DROPPED_IN_FW))
+					{
+						PRINTM(MERROR,
+						       "Fail to handle dropped packet, seq=%d\n",
+						       seq_num);
+					}
+				}
+			}
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv_rxba =
+			(MrvlIEtypes_RxBaSync_t *)((t_u8 *)tlv_rxba + tlv_len +
+						   sizeof(MrvlIEtypesHeader_t));
+	}
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function cleans up reorder tbl for specific station
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ta       ta to find in reordering table
+ *  @return         N/A
+ */
+void
+wlan_cleanup_reorder_tbl(mlan_private *priv, t_u8 *ta)
+{
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+	t_u8 i;
+	ENTER();
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, i, ta);
+		if (rx_reor_tbl_ptr)
+			wlan_11n_delete_rxreorder_tbl_entry(priv,
+							    rx_reor_tbl_ptr);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function will set force_no_drop flag in rxreorder_tbl.
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param flag    MTRUE/MFALSE
+ *
+ *  @return        N/A
+ */
+void
+wlan_set_rxreorder_tbl_no_drop_flag(mlan_private *priv, t_u8 flag)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		rx_reor_tbl_ptr->force_no_drop = flag;
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param flag         MTRUE/MFALSE
+ *  @return             N/A
+ */
+void
+wlan_update_rxreorder_tbl(pmlan_adapter pmadapter, t_u8 flag)
+{
+	t_u8 i;
+	pmlan_private priv = MNULL;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			wlan_set_rxreorder_tbl_no_drop_flag(priv, flag);
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief This function will flush the data  in rxreorder_tbl.
+ *  	   which has flush_data flag on.
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return        N/A
+ */
+void
+wlan_flush_priv_rxreorder_tbl(mlan_private *priv)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		if (rx_reor_tbl_ptr->flush_data) {
+			rx_reor_tbl_ptr->flush_data = MFALSE;
+			wlan_start_flush_data(priv, rx_reor_tbl_ptr);
+		}
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @return             N/A
+ */
+void
+wlan_flush_rxreorder_tbl(pmlan_adapter pmadapter)
+{
+	t_u8 i;
+	pmlan_private priv = MNULL;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			wlan_flush_priv_rxreorder_tbl(priv);
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_win_size based on coex flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param coex_flag    coex flag
+ *
+ *  @return             N/A
+ */
+void
+wlan_update_ampdu_rxwinsize(pmlan_adapter pmadapter, t_u8 coex_flag)
+{
+	t_u8 i;
+	t_u32 rx_win_size = 0;
+	pmlan_private priv = MNULL;
+
+	ENTER();
+	if (!pmadapter->coex_rx_winsize) {
+		LEAVE();
+		return;
+	}
+	PRINTM(MEVENT, "Update rxwinsize %d\n", coex_flag);
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			rx_win_size = priv->add_ba_param.rx_win_size;
+			if (coex_flag == MTRUE) {
+#ifdef STA_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_STA)
+					priv->add_ba_param.rx_win_size =
+						MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+					priv->add_ba_param.rx_win_size =
+						MLAN_WFD_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+#ifdef UAP_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_UAP)
+					priv->add_ba_param.rx_win_size =
+						MLAN_UAP_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+
+			} else {
+				priv->add_ba_param.rx_win_size =
+					priv->user_rxwinsize;
+			}
+			if (pmadapter->coex_win_size &&
+			    pmadapter->coex_rx_win_size)
+				priv->add_ba_param.rx_win_size =
+					pmadapter->coex_rx_win_size;
+			if (rx_win_size != priv->add_ba_param.rx_win_size) {
+				if (priv->media_connected == MTRUE) {
+					for (i = 0; i < MAX_NUM_TID; i++)
+						wlan_11n_delba(priv, i);
+					wlan_recv_event(priv,
+							MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+							MNULL);
+				}
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function updates ampdu rx_win_size
+ *
+ *  @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 100644
index 0000000..7f09dbe
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n_rxreorder.h
@@ -0,0 +1,105 @@
+/** @file mlan_11n_rxreorder.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of 11n RxReordering functionalities
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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
+
+t_void wlan_reset_pn_value(mlan_private *pmpriv, mlan_ds_encrypt_key *key);
+t_u8 wlan_is_rsn_replay_attack(mlan_private *pmpriv, t_void *payload,
+			       RxReorderTbl *rx_reor_tbl_ptr);
+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 100644
index 0000000..1a0fec6
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_cfp.c
@@ -0,0 +1,2866 @@
+/**
+ * @file mlan_cfp.c
+ *
+ *  @brief This file contains WLAN client mode channel, frequency and power
+ *  related code
+ *
+ *  Copyright (C) 2009-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+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"
+#include "mlan_sdio.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/** 100mW */
+#define WLAN_TX_PWR_DEFAULT     20
+/** 100mW */
+#define WLAN_TX_PWR_00_DEFAULT      20
+/** 100mW */
+#define WLAN_TX_PWR_US_DEFAULT      20
+/** 100mW */
+#define WLAN_TX_PWR_JP_BG_DEFAULT   20
+/** 200mW */
+#define WLAN_TX_PWR_JP_A_DEFAULT    23
+/** 100mW */
+#define WLAN_TX_PWR_FR_100MW        20
+/** 10mW */
+#define WLAN_TX_PWR_FR_10MW         10
+/** 100mW */
+#define WLAN_TX_PWR_EMEA_DEFAULT    20
+/** 2000mW */
+#define WLAN_TX_PWR_CN_2000MW       33
+/** 200mW */
+#define WLAN_TX_PWR_200MW   23
+/** 1000mW */
+#define WLAN_TX_PWR_1000MW   30
+/** 30mW */
+#define WLAN_TX_PWR_SP_30MW   14
+/** 60mW */
+#define WLAN_TX_PWR_SP_60MW   17
+/** 25mW */
+#define WLAN_TX_PWR_25MW   14
+/** 250mW */
+#define WLAN_TX_PWR_250MW   24
+
+/** Region code mapping */
+typedef struct _country_code_mapping {
+    /** Region */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+    /** Code for B/G CFP table */
+	t_u8 cfp_code_bg;
+    /** Code for A CFP table */
+	t_u8 cfp_code_a;
+} country_code_mapping_t;
+
+#define EU_CFP_CODE_BG  0x30
+#define EU_CFP_CODE_A   0x30
+
+/** Region code mapping table */
+static country_code_mapping_t country_code_mapping[] = {
+	{"WW", 0x00, 0x00},	/* World       */
+	{"US", 0x10, 0x10},	/* US FCC      */
+	{"CA", 0x10, 0x20},	/* IC Canada   */
+	{"SG", 0x10, 0x10},	/* Singapore   */
+	{"EU", 0x30, 0x30},	/* ETSI        */
+	{"AU", 0x30, 0x30},	/* Australia   */
+	{"KR", 0x30, 0x30},	/* Republic Of Korea */
+	{"JP", 0xFF, 0x40},	/* Japan       */
+	{"CN", 0x30, 0x50},	/* China       */
+	{"BR", 0x01, 0x09},	/* Brazil      */
+	{"RU", 0x30, 0x0f},	/* Russia      */
+	{"IN", 0x10, 0x06},	/* India       */
+	{"MY", 0x30, 0x06},	/* Malaysia    */
+};
+
+/** 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"
+};
+
+/**
+ * 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 FCC/Canada IC */
+static chan_freq_power_t channel_freq_power_00_BG[] = {
+	{1, 2412, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_00_DEFAULT, MFALSE}
+};
+
+/* Format { Channel, Frequency (MHz), MaxTxPower } */
+/** Band: 'B/G', Region: USA FCC/Canada IC */
+static chan_freq_power_t channel_freq_power_US_BG[] = {
+	{1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Europe ETSI/China */
+static chan_freq_power_t channel_freq_power_EU_BG[] = {
+	{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
+	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPNFE_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE}
+};
+
+/** Band : 'B/G', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR_BG[] = {
+	{1, 2412, WLAN_TX_PWR_1000MW, MFALSE},
+	{2, 2417, WLAN_TX_PWR_1000MW, MFALSE},
+	{3, 2422, WLAN_TX_PWR_1000MW, MFALSE},
+	{4, 2427, WLAN_TX_PWR_1000MW, MFALSE},
+	{5, 2432, WLAN_TX_PWR_1000MW, MFALSE},
+	{6, 2437, WLAN_TX_PWR_1000MW, MFALSE},
+	{7, 2442, WLAN_TX_PWR_1000MW, MFALSE},
+	{8, 2447, WLAN_TX_PWR_1000MW, MFALSE},
+	{9, 2452, WLAN_TX_PWR_1000MW, MFALSE},
+	{10, 2457, WLAN_TX_PWR_1000MW, MFALSE},
+	{11, 2462, WLAN_TX_PWR_1000MW, MFALSE},
+	{12, 2467, WLAN_TX_PWR_1000MW, MFALSE},
+	{13, 2472, WLAN_TX_PWR_1000MW, MFALSE},
+};
+
+/** Band : 'B/G', Region: Special */
+static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
+};
+
+/**
+ * The 2.4GHz CFP tables
+ */
+static cfp_table_t cfp_table_BG[] = {
+	{
+	 0x01,			/* Brazil */
+	 channel_freq_power_BR_BG,
+	 NELEMENTS(channel_freq_power_BR_BG),
+	 },
+	{0x00,			/* World FCC */
+	 channel_freq_power_00_BG,
+	 NELEMENTS(channel_freq_power_00_BG),
+	 },
+	{0x10,			/* US FCC */
+	 channel_freq_power_US_BG,
+	 NELEMENTS(channel_freq_power_US_BG),
+	 },
+	{0x20,			/* CANADA IC */
+	 channel_freq_power_US_BG,
+	 NELEMENTS(channel_freq_power_US_BG),
+	 },
+	{0x30,			/* EU */
+	 channel_freq_power_EU_BG,
+	 NELEMENTS(channel_freq_power_EU_BG),
+	 },
+	{0x40,			/* JAPAN */
+	 channel_freq_power_JPN40_BG,
+	 NELEMENTS(channel_freq_power_JPN40_BG),
+	 },
+	{0x41,			/* JAPAN */
+	 channel_freq_power_JPN41_BG,
+	 NELEMENTS(channel_freq_power_JPN41_BG),
+	 },
+	{0x50,			/* China */
+	 channel_freq_power_EU_BG,
+	 NELEMENTS(channel_freq_power_EU_BG),
+	 },
+	{
+	 0xfe,			/* JAPAN */
+	 channel_freq_power_JPNFE_BG,
+	 NELEMENTS(channel_freq_power_JPNFE_BG),
+	 },
+	{0xff,			/* Special */
+	 channel_freq_power_SPECIAL_BG,
+	 NELEMENTS(channel_freq_power_SPECIAL_BG),
+	 },
+/* Add new region here */
+};
+
+/** Number of the CFP tables for 2.4GHz */
+#define MLAN_CFP_TABLE_SIZE_BG  (NELEMENTS(cfp_table_BG))
+
+/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
+/** Band: 'A', Region: World FCC */
+static chan_freq_power_t channel_freq_power_00_A[] = {
+	{36, 5180, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{144, 5720, WLAN_TX_PWR_00_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_00_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_00_DEFAULT, MFALSE}
+};
+
+/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
+/** Band: 'A', Region: USA FCC */
+static chan_freq_power_t channel_freq_power_A[] = {
+	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Region: Canada IC */
+static chan_freq_power_t channel_freq_power_CAN_A[] = {
+	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Region: Europe ETSI */
+static chan_freq_power_t channel_freq_power_EU_A[] = {
+	{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN_A[] = {
+	{36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE}
+};
+
+/** Band: 'A', Region: China */
+static chan_freq_power_t channel_freq_power_CN_A[] = {
+	{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
+	{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
+	{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
+	{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
+	{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
+	{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
+	{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
+	{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
+	{149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE}
+};
+
+/** Band: 'A', NULL */
+static chan_freq_power_t channel_freq_power_NULL_A[] = {
+};
+
+/** Band: 'A', Region: Spain/Austria/Brazil */
+static chan_freq_power_t channel_freq_power_SPN2_A[] = {
+	{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
+	{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
+	{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
+	{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
+	{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
+	{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
+	{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
+	{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR1_A[] = {
+	{100, 5500, WLAN_TX_PWR_250MW, MTRUE},
+	{104, 5520, WLAN_TX_PWR_250MW, MTRUE},
+	{108, 5540, WLAN_TX_PWR_250MW, MTRUE},
+	{112, 5560, WLAN_TX_PWR_250MW, MTRUE},
+	{116, 5580, WLAN_TX_PWR_250MW, MTRUE},
+	{120, 5600, WLAN_TX_PWR_250MW, MTRUE},
+	{124, 5620, WLAN_TX_PWR_250MW, MTRUE},
+	{128, 5640, WLAN_TX_PWR_250MW, MTRUE},
+	{132, 5660, WLAN_TX_PWR_250MW, MTRUE},
+	{136, 5680, WLAN_TX_PWR_250MW, MTRUE},
+	{140, 5700, WLAN_TX_PWR_250MW, MTRUE},
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR2_A[] = {
+	{149, 5745, WLAN_TX_PWR_1000MW, MFALSE},
+	{153, 5765, WLAN_TX_PWR_1000MW, MFALSE},
+	{157, 5785, WLAN_TX_PWR_1000MW, MFALSE},
+	{161, 5805, WLAN_TX_PWR_1000MW, MFALSE},
+	{165, 5825, WLAN_TX_PWR_1000MW, MFALSE}
+};
+
+/** Band: 'A', Region: Russia */
+static chan_freq_power_t channel_freq_power_RU_A[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{132, 5660, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{136, 5680, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{140, 5700, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+};
+
+/** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+};
+
+/** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
+static chan_freq_power_t channel_freq_power_lower_middle_band[] = {
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE},
+};
+
+/** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
+static chan_freq_power_t channel_freq_power_upper_middle_band[] = {
+	{100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE},
+};
+
+/** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_high_band[] = {
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
+ * High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_high_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Code: 6, Low band (5150-5250 MHz) and
+ * mid low (5260-5320) and High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_middle_high_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
+};
+
+/**
+ * The 5GHz CFP tables
+ */
+static cfp_table_t cfp_table_A[] = {
+	{0x1,			/* Low band (5150-5250 MHz) channels */
+	 channel_freq_power_low_band,
+	 NELEMENTS(channel_freq_power_low_band)
+	 },
+	{0x2,			/* Lower middle band (5250-5350 MHz) channels */
+	 channel_freq_power_lower_middle_band,
+	 NELEMENTS(channel_freq_power_lower_middle_band)
+	 },
+	{0x3,			/* Upper middle band (5470-5725 MHz) channels */
+	 channel_freq_power_upper_middle_band,
+	 NELEMENTS(channel_freq_power_upper_middle_band)
+	 },
+	{0x4,			/* High band (5725-5850 MHz) channels */
+	 channel_freq_power_high_band,
+	 NELEMENTS(channel_freq_power_high_band)
+	 },
+	{0x5,			/* Low band (5150-5250 MHz) and
+				   High band (5725-5850 MHz) channels */
+	 channel_freq_power_low_high_band,
+	 NELEMENTS(channel_freq_power_low_high_band)
+	 },
+	{0x6,			/* Low band (5150-5250 MHz)
+				   Mid band (5260-5320) and
+				   High band (5725-5850 MHz) channels */
+	 channel_freq_power_low_middle_high_band,
+	 NELEMENTS(channel_freq_power_low_middle_high_band)
+	 },
+	{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))
+
+/********************************************************
+			Global Variables
+********************************************************/
+/**
+ * The table to keep region code
+ */
+
+t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = {
+	0x00, 0x10, 0x20, 0x30, 0x40, 0x41, 0x50, 0xfe, 0xff
+};
+
+/** The table to keep CFP code for BG */
+t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG] = { };
+
+/** The table to keep CFP code for A */
+t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = { 0x1, 0x2, 0x3, 0x4, 0x5 };
+
+/**
+ * The rates supported for ad-hoc B mode
+ */
+t_u8 AdhocRates_B[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
+
+/**
+ * The rates supported for ad-hoc G mode
+ */
+t_u8 AdhocRates_G[G_SUPPORTED_RATES] = {
+	0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported for ad-hoc BG mode
+ */
+t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = {
+	0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
+	0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in A mode for ad-hoc
+ */
+t_u8 AdhocRates_A[A_SUPPORTED_RATES] = {
+	0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in A mode (used for BAND_A)
+ */
+t_u8 SupportedRates_A[A_SUPPORTED_RATES] = {
+	0x0c, 0x12, 0x18, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported by the card
+ */
+t_u16 WlanDataRates[WLAN_SUPPORTED_RATES_EXT] = {
+	0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
+	0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,
+	0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75,
+	0x82, 0x0C, 0x1B, 0x36, 0x51, 0x6C, 0xA2,
+	0xD8, 0xF3, 0x10E, 0x00
+};
+
+/**
+ * The rates supported in B mode
+ */
+t_u8 SupportedRates_B[B_SUPPORTED_RATES] = {
+	0x02, 0x04, 0x0b, 0x16, 0x00
+};
+
+/**
+ * The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_G[G_SUPPORTED_RATES] = {
+	0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = {
+	0x02, 0x04, 0x0b, 0x0c, 0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
+	0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in N mode
+ */
+t_u8 SupportedRates_N[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
+
+/********************************************************
+			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();
+
+	/* first clear dest dynamic blacklisted entries */
+	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();
+
+	/* Look for code in mapping table */
+	for (i = 0; i < NELEMENTS(country_code_mapping); i++) {
+		if (!memcmp(pmadapter, country_code_mapping[i].country_code,
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			*cfp_bg = country_code_mapping[i].cfp_code_bg;
+			*cfp_a = country_code_mapping[i].cfp_code_a;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	/* If still not found, look for code in EU country code table */
+	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+		if (!memcmp(pmadapter, eu_country_code_table[i],
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			*cfp_bg = EU_CFP_CODE_BG;
+			*cfp_a = EU_CFP_CODE_A;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function finds if given country code is in EU table
+ *
+ *  @param pmadapter        A pointer to mlan_adapter structure
+ *  @param country_code     Country string
+ *
+ *  @return                 MTRUE or MFALSE
+ */
+t_bool
+wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
+{
+
+	t_u8 i;
+
+	ENTER();
+
+	/* Look for code in EU country code table */
+	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+		if (!memcmp(pmadapter, eu_country_code_table[i],
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			LEAVE();
+			return MTRUE;
+		}
+	}
+
+	LEAVE();
+	return MFALSE;
+}
+
+#define BAND_MASK_5G        0x03
+#define ANTENNA_OFFSET      2
+/**
+ *   @brief This function adjust the antenna index
+ *
+ *   V16_FW_API: Bit0: ant A, Bit 1:ant B, Bit0 & Bit 1: A+B
+ *   8887: case1: 0 - 2.4G ant A,  1- 2.4G antB, 2-- 5G ant C
+ *   case2: 0 - 2.4G ant A,  1- 2.4G antB, 0x80- 5G antA, 0x81-5G ant B
+ *   @param priv 	 A pointer to mlan_private structure
+ *   @param prx_pd   A pointer to the RxPD structure
+ *
+ *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+t_u8
+wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd)
+{
+	t_u8 antenna = prx_pd->antenna;
+	t_u32 rx_channel = (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+	if (prx_pd->antenna == 0xff)
+		return 0;
+	if (priv->adapter->psdio_device->v16_fw_api &&
+	    (IS_STREAM_2X2(priv->adapter->feature_control))) {
+		if ((antenna & MBIT(0)) && (antenna & MBIT(1)))
+			antenna = 2;
+		else if (antenna & MBIT(1))
+			antenna = 1;
+		else if (antenna & MBIT(0))
+			antenna = 0;
+	}
+
+	if (IS_SD8887(priv->adapter->card_type) ||
+	    IS_SD8987(priv->adapter->card_type)) {
+		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;
+
+		}
+	}
+
+	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_u8
+wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info)
+{
+	t_u8 rate_index = 0;
+	t_u8 bw = 0;
+	t_u8 nss = 0;
+	t_bool sgi_enable = 0;
+
+#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);
+	}
+	return rate_index;
+}
+
+#ifdef STA_SUPPORT
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief convert ht_info to rate_info
+ *
+ *  @param ht_info      ht info
+ *
+ *  @return             rate info
+ */
+t_u8
+wlan_convert_v14_rate_ht_info(t_u8 ht_info)
+{
+	t_u8 rate_info = 0;
+	rate_info = ht_info & 0x01;
+	/* band */
+	rate_info |= (ht_info & MBIT(1)) << 1;
+	/* short GI */
+	rate_info |= (ht_info & MBIT(2)) << 2;
+	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
+ *
+ *  @return                 Data rate or 0
+ */
+t_u32
+wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 tx_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 bw = 0;
+	t_u8 gi = 0;
+	ENTER();
+
+	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_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_u8 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:
+			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:
+			case BAND_B:	/* Matching BAND_B/G */
+			case BAND_G:
+			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, "wlan_get_cfp_by_band_and_channel(): cannot find "
+		       "cfp by band %d & channel %d\n", 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:
+			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:
+			case BAND_B:
+			case BAND_G:
+			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,
+		       "wlan_find_cfp_by_band_and_freq(): cannot find cfp by "
+		       "band %d & freq %d\n", 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_u8 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:
+			PRINTM(MINFO, "Infra band=%d SupportedRates_G\n",
+			       config_bands);
+			k = wlan_copy_rates(rates, k, SupportedRates_G,
+					    sizeof(SupportedRates_G));
+			break;
+		case BAND_B | BAND_G:
+		case BAND_A | BAND_B | BAND_G:
+		case BAND_A | BAND_B:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC | BAND_GAC:
+		case BAND_B | BAND_G | BAND_GN:
+		case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+			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:
+			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:
+			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:
+		case BAND_G | BAND_GN:
+		case BAND_G | BAND_GN | BAND_GAC:
+			PRINTM(MINFO, "Band: Adhoc G only\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_G,
+					    sizeof(AdhocRates_G));
+			break;
+		case BAND_B | BAND_G:
+		case BAND_B | BAND_G | BAND_GN:
+		case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+			PRINTM(MINFO, "Band: Adhoc BG\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_BG,
+					    sizeof(AdhocRates_BG));
+			break;
+		case BAND_A:
+		case BAND_AN:
+		case BAND_A | BAND_AN:
+		case BAND_A | BAND_AN | BAND_AAC:
+			PRINTM(MINFO, "Band: Adhoc A\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_A,
+					    sizeof(AdhocRates_A));
+			break;
+		}
+	}
+
+	LEAVE();
+	return k;
+}
+
+#define COUNTRY_ID_US 0
+#define COUNTRY_ID_JP 1
+#define COUNTRY_ID_CN 2
+#define COUNTRY_ID_EU 3
+typedef struct _oper_bw_chan {
+	/*non-global operating class */
+	t_u8 oper_class;
+	/*global operating class */
+	t_u8 global_oper_class;
+	/*bandwidth 0-20M 1-40M 2-80M 3-160M */
+	t_u8 bandwidth;
+	/*channel list */
+	t_u8 channel_list[13];
+} oper_bw_chan;
+
+/** oper class table for US*/
+static oper_bw_chan oper_bw_chan_us[] = {
+    /** non-Global oper class, global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 124, 0, {149, 153, 157, 161}},
+	{4, 121, 0,
+	 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144}},
+	{5, 125, 0, {149, 153, 157, 161, 165}},
+	{12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
+	{22, 116, 1, {36, 44}},
+	{23, 119, 1, {52, 60}},
+	{24, 122, 1, {100, 108, 116, 124, 132, 140}},
+	{25, 126, 1, {149, 157}},
+	{26, 126, 1, {149, 157}},
+	{27, 117, 1, {40, 48}},
+	{28, 120, 1, {56, 64}},
+	{29, 123, 1, {104, 112, 120, 128, 136, 144}},
+	{30, 127, 1, {153, 161}},
+	{31, 127, 1, {153, 161}},
+	{32, 83, 1, {1, 2, 3, 4, 5, 6, 7}},
+	{33, 84, 1, {5, 6, 7, 8, 9, 10, 11}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for EU*/
+static oper_bw_chan oper_bw_chan_eu[] = {
+    /** non-global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{5, 116, 1, {36, 44}},
+	{6, 119, 1, {52, 60}},
+	{7, 122, 1, {100, 108, 116, 124, 132}},
+	{8, 117, 1, {40, 48}},
+	{9, 120, 1, {56, 64}},
+	{10, 123, 1, {104, 112, 120, 128, 136}},
+	{11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{17, 125, 0, {149, 153, 157, 161, 165, 169}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for Japan*/
+static oper_bw_chan oper_bw_chan_jp[] = {
+    /** non-Global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48}},
+	{30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{31, 82, 0, {14}},
+	{32, 118, 0, {52, 56, 60, 64}},
+	{33, 118, 0, {52, 56, 60, 64}},
+	{34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{36, 116, 1, {36, 44}},
+	{37, 119, 1, {52, 60}},
+	{38, 119, 1, {52, 60}},
+	{39, 122, 1, {100, 108, 116, 124, 132}},
+	{40, 122, 1, {100, 108, 116, 124, 132}},
+	{41, 117, 1, {40, 48}},
+	{42, 120, 1, {56, 64}},
+	{43, 120, 1, {56, 64}},
+	{44, 123, 1, {104, 112, 120, 128, 136}},
+	{45, 123, 1, {104, 112, 120, 128, 136}},
+	{56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for China*/
+static oper_bw_chan oper_bw_chan_cn[] = {
+    /** non-Global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 125, 0, {149, 153, 157, 161, 165}},
+	{4, 116, 1, {36, 44}},
+	{5, 119, 1, {52, 60}},
+	{6, 126, 1, {149, 157}},
+	{7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/**
+ *  @brief Get non-global operaing class table according to country
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param arraysize          A pointer to table size
+ *
+ *  @return                   A pointer to oper_bw_chan
+ */
+oper_bw_chan *
+wlan_get_nonglobal_operclass_table(mlan_private *pmpriv, int *arraysize)
+{
+	t_u8 country_code[][COUNTRY_CODE_LEN] = { "US", "JP", "CN" };
+	int country_id = 0;
+	oper_bw_chan *poper_bw_chan = MNULL;
+
+	ENTER();
+
+	for (country_id = 0; country_id < 3; country_id++)
+		if (!memcmp
+		    (pmpriv->adapter, pmpriv->adapter->country_code,
+		     country_code[country_id], COUNTRY_CODE_LEN - 1))
+			break;
+	if (country_id >= 3)
+		country_id = COUNTRY_ID_US;	/*Set default to US */
+	if (wlan_is_etsi_country
+	    (pmpriv->adapter, pmpriv->adapter->country_code))
+		country_id = COUNTRY_ID_EU;
+				    /** Country in EU */
+
+	switch (country_id) {
+	case COUNTRY_ID_US:
+		poper_bw_chan = oper_bw_chan_us;
+		*arraysize = sizeof(oper_bw_chan_us);
+		break;
+	case COUNTRY_ID_JP:
+		poper_bw_chan = oper_bw_chan_jp;
+		*arraysize = sizeof(oper_bw_chan_jp);
+		break;
+	case COUNTRY_ID_CN:
+		poper_bw_chan = oper_bw_chan_cn;
+		*arraysize = sizeof(oper_bw_chan_cn);
+		break;
+	case COUNTRY_ID_EU:
+		poper_bw_chan = oper_bw_chan_eu;
+		*arraysize = sizeof(oper_bw_chan_eu);
+		break;
+	default:
+		PRINTM(MERROR, "Country not support!\n");
+		break;
+	}
+
+	LEAVE();
+	return poper_bw_chan;
+}
+
+/**
+ *  @brief Check validation of given channel and oper class
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param channel            Channel number
+ *  @param oper_class         operating class
+ *
+ *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
+				t_u8 oper_class)
+{
+	int arraysize = 0, i = 0, channum = 0;
+	oper_bw_chan *poper_bw_chan = MNULL;
+	t_u8 center_freq_idx = 0;
+	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
+
+	ENTER();
+
+	for (i = 0; i < sizeof(center_freqs); i++) {
+		if (channel == center_freqs[i]) {
+			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	if (oper_class <= 0 || oper_class > 130) {
+		PRINTM(MERROR, "Invalid operating class!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (oper_class >= 128) {
+		center_freq_idx =
+			wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
+						 CHANNEL_BW_80MHZ);
+		channel = center_freq_idx;
+	}
+	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+	if (!poper_bw_chan) {
+		PRINTM(MCMND, "Operating class table do not find!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
+		if (poper_bw_chan[i].oper_class == oper_class ||
+		    poper_bw_chan[i].global_oper_class == oper_class) {
+			for (channum = 0;
+			     channum < sizeof(poper_bw_chan[i].channel_list);
+			     channum++) {
+				if (poper_bw_chan[i].channel_list[channum] &&
+				    poper_bw_chan[i].channel_list[channum] ==
+				    channel) {
+					LEAVE();
+					return MLAN_STATUS_SUCCESS;
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMND, "Operating class %d do not match channel %d!\n",
+	       oper_class, channel);
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Get current operating class from channel and bandwidth
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param channel            Channel number
+ *  @param bw                 Bandwidth
+ *  @param oper_class         A pointer to current operating class
+ *
+ *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel, t_u8 bw,
+			 t_u8 *oper_class)
+{
+	oper_bw_chan *poper_bw_chan = MNULL;
+	t_u8 center_freq_idx = 0;
+	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
+	int i = 0, arraysize = 0, channum = 0;
+
+	ENTER();
+
+	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+	if (!poper_bw_chan) {
+		PRINTM(MCMND, "Operating class table do not find!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	for (i = 0; i < sizeof(center_freqs); i++) {
+		if (channel == center_freqs[i]) {
+			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	if (bw == BW_80MHZ) {
+		center_freq_idx =
+			wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
+						 CHANNEL_BW_80MHZ);
+		channel = center_freq_idx;
+	}
+
+	for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
+		if (poper_bw_chan[i].bandwidth == bw) {
+			for (channum = 0;
+			     channum < sizeof(poper_bw_chan[i].channel_list);
+			     channum++) {
+				if (poper_bw_chan[i].channel_list[channum] &&
+				    poper_bw_chan[i].channel_list[channum] ==
+				    channel) {
+					*oper_class =
+						poper_bw_chan[i].oper_class;
+					return MLAN_STATUS_SUCCESS;
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMND, "Operating class not find!\n");
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Add Supported operating classes IE
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param pptlv_out          A pointer to TLV to fill in
+ *  @param curr_oper_class    Current operating class
+ *
+ *  @return                   Length
+ */
+int
+wlan_add_supported_oper_class_ie(IN mlan_private *pmpriv, OUT 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(pmpriv->adapter, &poper_class->oper_class, oper_class_us,
+		       sizeof(oper_class_us));
+	} else if (country_id == COUNTRY_ID_JP) {
+		poper_class->header.len = sizeof(oper_class_jp);
+		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_jp,
+		       sizeof(oper_class_jp));
+	} else if (country_id == COUNTRY_ID_CN) {
+		poper_class->header.len = sizeof(oper_class_cn);
+		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_cn,
+		       sizeof(oper_class_cn));
+	} else if (country_id == COUNTRY_ID_EU) {
+		poper_class->header.len = sizeof(oper_class_eu);
+		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_eu,
+		       sizeof(oper_class_eu));
+	}
+	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(pmadapter, region_chan_old, pmadapter->region_channel,
+	       sizeof(pmadapter->region_channel));
+	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, "wlan_set_regiontable 2.4G 0x%x\n", 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)
+			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
+					      region_chan_old[j].pcfp,
+					      region_chan_old[j].num_cfp);
+		else
+			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, "wlan_set_regiontable 5G 0x%x\n", 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
+			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 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 & MARVELL_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	Update CFP tables and power tables from FW
+ *
+ *  @param priv		Private driver information structure
+ *  @param buf		Pointer to the buffer holding TLV data
+ *					from 0x242 command response.
+ *  @param buf_left	bufsize
+ *
+ *  @return
+ *    None
+ */
+void
+wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	MrvlIEtypesHeader_t *head;
+	t_u16 tlv;
+	t_u16 tlv_buf_len;
+	t_u16 tlv_buf_left;
+	t_u16 i;
+	int k = 0, rows, cols;
+	t_u16 max_tx_pwr_bg = WLAN_TX_PWR_DEFAULT;
+	t_u16 max_tx_pwr_a = WLAN_TX_PWR_DEFAULT;
+	t_u8 *tlv_buf;
+	t_u8 *data;
+	t_u8 *tmp;
+	mlan_status ret;
+
+	ENTER();
+
+	if (!buf) {
+		PRINTM(MERROR, "CFP table update failed!\n");
+		goto out;
+	}
+	if (pmadapter->otp_region)
+		wlan_free_fw_cfp_tables(pmadapter);
+	pmadapter->tx_power_table_bg_rows = FW_CFP_TABLE_MAX_ROWS_BG;
+	pmadapter->tx_power_table_bg_cols = FW_CFP_TABLE_MAX_COLS_BG;
+	pmadapter->tx_power_table_a_rows = FW_CFP_TABLE_MAX_ROWS_A;
+	pmadapter->tx_power_table_a_cols = FW_CFP_TABLE_MAX_COLS_A;
+	tlv_buf = (t_u8 *)buf;
+	tlv_buf_left = buf_left;
+
+	while (tlv_buf_left >= sizeof(*head)) {
+		head = (MrvlIEtypesHeader_t *)tlv_buf;
+		tlv = wlan_le16_to_cpu(head->type);
+		tlv_buf_len = wlan_le16_to_cpu(head->len);
+
+		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
+			break;
+		data = (t_u8 *)head + sizeof(*head);
+
+		switch (tlv) {
+		case TLV_TYPE_REGION_INFO:
+			/* Skip adding fw region info if it already exists or
+			 * if this TLV has no set data
+			 */
+			if (*data == 0)
+				break;
+			if (pmadapter->otp_region)
+				break;
+
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(otp_region_info_t),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->otp_region);
+			if (ret != MLAN_STATUS_SUCCESS ||
+			    !pmadapter->otp_region) {
+				PRINTM(MERROR,
+				       "Memory allocation for the otp region"
+				       " info struct failed!\n");
+				break;
+			}
+			/* Save region info values from OTP in the otp_region
+			 * structure
+			 */
+			memcpy(pmadapter, pmadapter->otp_region, data,
+			       sizeof(otp_region_info_t));
+			data += sizeof(otp_region_info_t);
+			/* Get pre-defined cfp tables corresponding to the region code
+			 * in OTP
+			 */
+			for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
+				if (cfp_table_BG[i].code ==
+				    pmadapter->otp_region->region_code) {
+					max_tx_pwr_bg =
+						(cfp_table_BG[i].cfp)->
+						max_tx_power;
+					break;
+				}
+			}
+			for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
+				if (cfp_table_A[i].code ==
+				    pmadapter->otp_region->region_code) {
+					max_tx_pwr_a =
+						(cfp_table_A[i].cfp)->
+						max_tx_power;
+					break;
+				}
+			}
+			/* Update the region code and the country code in pmadapter */
+			pmadapter->region_code =
+				pmadapter->otp_region->region_code;
+			pmadapter->country_code[0] =
+				pmadapter->otp_region->country_code[0];
+			pmadapter->country_code[1] =
+				pmadapter->otp_region->country_code[1];
+			pmadapter->country_code[2] = '\0';
+			pmadapter->domain_reg.country_code[0] =
+				pmadapter->otp_region->country_code[0];
+			pmadapter->domain_reg.country_code[1] =
+				pmadapter->otp_region->country_code[1];
+			pmadapter->domain_reg.country_code[2] = '\0';
+			pmadapter->cfp_code_bg =
+				pmadapter->otp_region->region_code;
+			pmadapter->cfp_code_a =
+				pmadapter->otp_region->region_code;
+			break;
+		case TLV_TYPE_CHAN_ATTR_CFG:
+			/* Skip adding fw cfp tables if they already exist or
+			 * if this TLV has no set data
+			 */
+			if (*data == 0)
+				break;
+			if (pmadapter->cfp_otp_bg || pmadapter->cfp_otp_a) {
+				break;
+			}
+
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       pmadapter->
+					       tx_power_table_bg_rows *
+					       sizeof(chan_freq_power_t),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->cfp_otp_bg);
+			if (ret != MLAN_STATUS_SUCCESS ||
+			    !pmadapter->cfp_otp_bg) {
+				PRINTM(MERROR,
+				       "Memory allocation for storing otp bg"
+				       " table data failed!\n");
+				break;
+			}
+			/* Save channel usability flags from OTP data in the fw cfp bg
+			 * table and set frequency and max_tx_power values
+			 */
+			for (i = 0; i < pmadapter->tx_power_table_bg_rows; i++) {
+				(pmadapter->cfp_otp_bg + i)->channel = *data;
+				if (*data == 14)
+					(pmadapter->cfp_otp_bg + i)->freq =
+						2484;
+				else
+					(pmadapter->cfp_otp_bg + i)->freq =
+						2412 + 5 * (*data - 1);
+				(pmadapter->cfp_otp_bg + i)->max_tx_power =
+					max_tx_pwr_bg;
+				data++;
+				(pmadapter->cfp_otp_bg + i)->dynamic.flags =
+					*data;
+				if (*data & MARVELL_CHANNEL_DFS)
+					(pmadapter->cfp_otp_bg +
+					 i)->passive_scan_or_radar_detect =
+			MTRUE;
+				data++;
+			}
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       pmadapter->
+					       tx_power_table_a_rows *
+					       sizeof(chan_freq_power_t),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->cfp_otp_a);
+			if (ret != MLAN_STATUS_SUCCESS || !pmadapter->cfp_otp_a) {
+				PRINTM(MERROR,
+				       "Memory allocation for storing otp a"
+				       " table data failed!\n");
+				break;
+			}
+			/* Save channel usability flags from OTP data in the fw cfp a
+			 * table and set frequency and max_tx_power values
+			 */
+			for (i = 0; i < pmadapter->tx_power_table_a_rows; i++) {
+				(pmadapter->cfp_otp_a + i)->channel = *data;
+				if (*data < 183)
+					/* 5GHz channels */
+					(pmadapter->cfp_otp_a + i)->freq =
+						5035 + 5 * (*data - 7);
+				else
+					/* 4GHz channels */
+					(pmadapter->cfp_otp_a + i)->freq =
+						4915 + 5 * (*data - 183);
+				(pmadapter->cfp_otp_a + i)->max_tx_power =
+					max_tx_pwr_a;
+				data++;
+				(pmadapter->cfp_otp_a + i)->dynamic.flags =
+					*data;
+				if (*data & MARVELL_CHANNEL_DFS)
+					(pmadapter->cfp_otp_a +
+					 i)->passive_scan_or_radar_detect =
+			 MTRUE;
+				data++;
+			}
+			break;
+		case TLV_TYPE_POWER_TABLE:
+			/* Skip adding fw power tables if this TLV has no data or
+			 * if they already exists but force reg rule is set in the otp
+			 */
+			if (*data == 0)
+				break;
+			if (pmadapter->otp_region &&
+			    pmadapter->otp_region->force_reg &&
+			    pmadapter->tx_power_table_bg)
+				break;
+
+			/* Save the tlv data in power tables for band BG and A */
+			tmp = data;
+			i = 0;
+			while ((i < pmadapter->tx_power_table_bg_rows *
+				pmadapter->tx_power_table_bg_cols)
+			       && (i < tlv_buf_len) && (*tmp != 36)) {
+				i++;
+				tmp++;
+			}
+			if (!pmadapter->tx_power_table_bg) {
+				ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+						       i, MLAN_MEM_DEF,
+						       (t_u8 **)&pmadapter->
+						       tx_power_table_bg);
+				if (ret != MLAN_STATUS_SUCCESS ||
+				    !pmadapter->tx_power_table_bg) {
+					PRINTM(MERROR,
+					       "Memory allocation for the BG-band"
+					       " power table falied!\n");
+					break;
+				}
+			}
+			memcpy(pmadapter, pmadapter->tx_power_table_bg, data,
+			       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(pmadapter, pmadapter->tx_power_table_a, data, i);
+			pmadapter->tx_power_table_a_size = i;
+			break;
+		case TLV_TYPE_POWER_TABLE_ATTR:
+			pmadapter->tx_power_table_bg_rows =
+				((power_table_attr_t *) data)->rows_2g;
+			pmadapter->tx_power_table_bg_cols =
+				((power_table_attr_t *) data)->cols_2g;
+			pmadapter->tx_power_table_a_rows =
+				((power_table_attr_t *) data)->rows_5g;
+			pmadapter->tx_power_table_a_cols =
+				((power_table_attr_t *) data)->cols_5g;
+			break;
+		default:
+			break;
+		}
+		tlv_buf += (sizeof(*head) + tlv_buf_len);
+		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
+	}
+	if (!pmadapter->cfp_otp_bg || !pmadapter->tx_power_table_bg)
+		goto out;
+	/* Set remaining flags for BG */
+	rows = pmadapter->tx_power_table_bg_rows;
+	cols = pmadapter->tx_power_table_bg_cols;
+
+	for (i = 0; i < rows; i++) {
+		k = (i * cols) + 1;
+		if ((pmadapter->cfp_otp_bg + i)->dynamic.flags &
+		    MARVELL_CHANNEL_DISABLED)
+			continue;
+
+		if (pmadapter->tx_power_table_bg[k + MOD_CCK] == 0)
+			(pmadapter->cfp_otp_bg + i)->dynamic.flags |=
+				MARVELL_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 |=
+				MARVELL_CHANNEL_NO_OFDM;
+		}
+	}
+out:
+	LEAVE();
+}
+
+/**
+ *  @brief	This function deallocates otp cfp and power tables memory.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ */
+void
+wlan_free_fw_cfp_tables(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+	if (pmadapter->otp_region)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->otp_region);
+	if (pmadapter->cfp_otp_bg)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->cfp_otp_bg);
+	if (pmadapter->tx_power_table_bg)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->tx_power_table_bg);
+	pmadapter->otp_region = MNULL;
+	pmadapter->cfp_otp_bg = MNULL;
+	pmadapter->tx_power_table_bg = MNULL;
+	pmadapter->tx_power_table_bg_size = 0;
+	if (pmadapter->cfp_otp_a)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->cfp_otp_a);
+	if (pmadapter->tx_power_table_a)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->tx_power_table_a);
+	pmadapter->cfp_otp_a = MNULL;
+	pmadapter->tx_power_table_a = MNULL;
+	pmadapter->tx_power_table_a_size = 0;
+	LEAVE();
+}
+
+/**
+ *  @brief	Get 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(IN pmlan_adapter pmadapter, IN 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_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);
+
+	/* Get cfp table and its size corresponding to the region code */
+	cfp_bg = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
+					   BAND_G | BAND_B, &cfp_no_bg);
+	size += cfp_no_bg * sizeof(chan_freq_power_t);
+	cfp_a = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
+					  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(pmadapter, req_buf, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, &pmadapter->region_code,
+	       sizeof(pmadapter->region_code));
+	len += sizeof(pmadapter->region_code);
+	memcpy(pmadapter, req_buf + len, &pmadapter->country_code,
+	       sizeof(pmadapter->country_code));
+	len += sizeof(pmadapter->country_code);
+	if (pmadapter->otp_region) {
+		memcpy(pmadapter, req_buf + len,
+		       &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(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, cfp_bg, size);
+	len += size;
+	if (!cfp_a)
+		goto out;
+	size = cfp_no_a * sizeof(chan_freq_power_t);
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, cfp_a, 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(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+
+	/* No. of rows */
+	size = pmadapter->tx_power_table_bg_rows;
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+
+	/* No. of cols */
+	size = pmadapter->tx_power_table_bg_size /
+		pmadapter->tx_power_table_bg_rows;
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, pmadapter->tx_power_table_bg,
+	       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(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+
+	/* No. of rows */
+	size = pmadapter->tx_power_table_a_rows;
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+
+	/* No. of cols */
+	size = pmadapter->tx_power_table_a_size /
+		pmadapter->tx_power_table_a_rows;
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, pmadapter->tx_power_table_a,
+	       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 100644
index 0000000..785c2cd
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_cmdevt.c
@@ -0,0 +1,6188 @@
+/**
+ * @file mlan_cmdevt.c
+ *
+ *  @brief This file contains the handling of CMD/EVENT in MLAN
+ *
+ *  Copyright (C) 2009-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+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_11h.h"
+#include "mlan_sdio.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(IN mlan_private *pmpriv, IN cmd_ctrl_node *pcmd_node)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (pcmd_node == MNULL)
+		goto done;
+	pcmd_node->cmd_flag |= CMD_F_SCAN;
+
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &pmadapter->scan_pending_q,
+			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief Internal function used to flush the scan pending queue
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+void
+wlan_check_scan_queue(IN 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
+/**
+ *  @brief This function dump debug info
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param reason        Reason code
+ *
+ *  @return     N/A
+ */
+t_void
+wlan_dump_info(mlan_adapter *pmadapter, t_u8 reason)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	t_u8 i;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	t_u8 j;
+	t_u8 mp_aggr_pkt_limit = pmadapter->psdio_device->mp_aggr_pkt_limit;
+#endif
+	t_u16 cmd_id, cmd_act;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	PRINTM(MERROR, "------------Dump info-----------\n", reason);
+	switch (reason) {
+	case REASON_CODE_NO_CMD_NODE:
+		pmadapter->dbg.num_no_cmd_node++;
+		PRINTM(MERROR, "No Free command node\n");
+		break;
+	case REASON_CODE_CMD_TIMEOUT:
+		PRINTM(MERROR, "Commmand Timeout\n");
+		break;
+	case REASON_CODE_CMD_TO_CARD_FAILURE:
+		PRINTM(MERROR, "Command to card failure\n");
+		break;
+	default:
+		break;
+	}
+	if ((reason == REASON_CODE_NO_CMD_NODE) &&
+	    (pmadapter->dbg.num_no_cmd_node > 1)) {
+		if (pmadapter->dbg.num_no_cmd_node >= 5)
+			wlan_recv_event(wlan_get_priv
+					(pmadapter, MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+		LEAVE();
+		return;
+	}
+	wlan_dump_pending_commands(pmadapter);
+	if (reason != REASON_CODE_CMD_TIMEOUT) {
+		if (!pmadapter->curr_cmd) {
+			PRINTM(MERROR, "CurCmd Empty\n");
+		} else {
+			pcmd_node = pmadapter->curr_cmd;
+			cmd_id = pmadapter->dbg.last_cmd_id[pmadapter->dbg.
+							    last_cmd_index];
+			cmd_act =
+				pmadapter->dbg.last_cmd_act[pmadapter->dbg.
+							    last_cmd_index];
+			PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
+			PRINTM(MERROR,
+			       "Current cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n",
+			       sec, usec, cmd_id, cmd_act);
+			if (pcmd_node->cmdbuf) {
+				t_u8 *pcmd_buf;
+				pcmd_buf =
+					pcmd_node->cmdbuf->pbuf +
+					pcmd_node->cmdbuf->data_offset +
+					INTF_HEADER_LEN;
+				for (i = 0; i < 16; i++)
+					PRINTM(MERROR, "%02x ", *pcmd_buf++);
+				PRINTM(MERROR, "\n");
+			}
+			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, "dbg.num_cmd_timeout = %d\n",
+	       pmadapter->dbg.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);
+	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);
+	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_cmd_assoc_failure = %d\n",
+	       pmadapter->dbg.num_cons_cmd_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\n",
+	       pmadapter->pm_wakeup_card_req, pmadapter->pm_wakeup_fw_try);
+	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, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
+	       pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port);
+	PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
+	       pmadapter->mp_wr_bitmap, pmadapter->curr_wr_port);
+	PRINTM(MERROR, "mp_invalid_update=%d\n", pmadapter->mp_invalid_update);
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n",
+	       pmadapter->last_recv_wr_bitmap, pmadapter->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->last_mp_wr_bitmap[i],
+		       pmadapter->last_mp_wr_ports[i],
+		       pmadapter->last_mp_wr_len[i],
+		       pmadapter->last_curr_wr_port[i]);
+		for (j = 0; j < mp_aggr_pkt_limit; j++) {
+			PRINTM(MERROR, "0x%02x ",
+			       pmadapter->last_mp_wr_info[i *
+							  mp_aggr_pkt_limit +
+							  j]);
+		}
+		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)
+			) {
+			if (pmpriv)
+				wlan_recv_event(pmpriv,
+						MLAN_EVENT_ID_DRV_DBG_DUMP,
+						MNULL);
+			else
+				wlan_recv_event(wlan_get_priv
+						(pmadapter, MLAN_BSS_ROLE_ANY),
+						MLAN_EVENT_ID_DRV_DBG_DUMP,
+						MNULL);
+		}
+	}
+	PRINTM(MERROR, "-------- Dump info End---------\n", reason);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function convert a given character to hex
+ *
+ *  @param chr        Character to be converted
+ *
+ *  @return           The converted hex if chr is a valid hex, else 0
+ */
+static t_u32
+wlan_hexval(t_u8 chr)
+{
+	if (chr >= '0' && chr <= '9')
+		return chr - '0';
+	if (chr >= 'A' && chr <= 'F')
+		return chr - 'A' + 10;
+	if (chr >= 'a' && chr <= 'f')
+		return chr - 'a' + 10;
+
+	return 0;
+}
+
+/**
+ *  @brief This function convert a given string to hex
+ *
+ *  @param a            A pointer to string to be converted
+ *
+ *  @return             The converted hex value if param a is a valid hex, else 0
+ */
+int
+wlan_atox(t_u8 *a)
+{
+	int i = 0;
+
+	ENTER();
+
+	while (wlan_isxdigit(*a))
+		i = i * 16 + wlan_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief This function parse cal data from ASCII to hex
+ *
+ *  @param src          A pointer to source data
+ *  @param len          Source data length
+ *  @param dst          A pointer to a buf to store the parsed data
+ *
+ *  @return             The parsed hex data length
+ */
+static t_u32
+wlan_parse_cal_cfg(t_u8 *src, t_size len, t_u8 *dst)
+{
+	t_u8 *ptr;
+	t_u8 *dptr;
+
+	ENTER();
+	ptr = src;
+	dptr = dst;
+
+	while (ptr - src < len) {
+		if (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) {
+			ptr++;
+			continue;
+		}
+
+		if (wlan_isxdigit(*ptr)) {
+			*dptr++ = wlan_atox(ptr);
+			ptr += 2;
+		} else {
+			ptr++;
+		}
+	}
+	LEAVE();
+	return dptr - dst;
+}
+
+/**
+ *  @brief This function finds first occurrence of a char in a string
+ *
+ *  @param s            A pointer to the string to be searched
+ *  @param c            The character to search for
+ *
+ *  @return             Location of the first occurrence of the char
+ *                      if found, else NULL
+ */
+t_u8 *
+wlan_strchr(t_u8 *s, int c)
+{
+	t_u8 *pos = s;
+	while (*pos != '\0') {
+		if (*pos == (t_u8)c)
+			return pos;
+		pos++;
+	}
+	return MNULL;
+}
+
+#define CFG_TYPE_HOSTCMD        0
+#define CFG_TYPE_DPDFILE          1
+
+/**
+ *    @brief WOAL parse ASCII format raw data to hex format
+ *
+ *    @param pmpriv       MOAL handle
+ *    @param cfg_type     Conf file type
+ *    @param data         Source data
+ *    @param size         data length
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+wlan_process_hostcmd_cfg(IN pmlan_private pmpriv, IN t_u16 cfg_type,
+			 IN t_u8 *data, IN 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_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             N/A
+ */
+static void
+wlan_init_cmd_node(IN pmlan_private pmpriv,
+		   IN cmd_ctrl_node *pcmd_node,
+		   IN t_u32 cmd_oid,
+		   IN t_void *pioctl_buf, IN t_void *pdata_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (pcmd_node == MNULL) {
+		LEAVE();
+		return;
+	}
+	pcmd_node->priv = pmpriv;
+	pcmd_node->cmd_oid = cmd_oid;
+	pcmd_node->pioctl_buf = pioctl_buf;
+	pcmd_node->pdata_buf = pdata_buf;
+
+	pcmd_node->cmdbuf = pcmd_node->pmbuf;
+
+	/* 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;
+	pcmd_node->cmdbuf->data_offset += INTF_HEADER_LEN;
+
+	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_oid = 0;
+	pcmd_node->cmd_flag = 0;
+	pcmd_node->pioctl_buf = MNULL;
+	pcmd_node->pdata_buf = MNULL;
+
+	if (pcmd_node->respbuf) {
+		wlan_free_mlan_buffer(pmadapter, pcmd_node->respbuf);
+		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(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *resp, IN 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(pmpriv->adapter, misc->param.hostcmd.cmd, (void *)resp,
+		       size);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function sends host command to firmware.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_host_cmd(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_cmd *pcmd_ptr = (mlan_ds_misc_cmd *)pdata_buf;
+
+	ENTER();
+
+	/* Copy the HOST command to command buffer */
+	memcpy(pmpriv->adapter, (void *)cmd, pcmd_ptr->cmd,
+	       MIN(MRVDRV_SIZE_OF_CMD_BUFFER, pcmd_ptr->len));
+	PRINTM(MINFO, "Host command size = %d\n", pcmd_ptr->len);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN mlan_private *pmpriv, IN 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 DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+
+	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);
+	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);
+
+	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\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));
+	DBG_HEXDUMP(MCMD_D, "DNLD_CMD", (t_u8 *)pcmd, cmd_size);
+
+	/* Send the command to lower layer */
+
+	pcmd_node->cmdbuf->data_offset -= INTF_HEADER_LEN;
+	pcmd_node->cmdbuf->data_len += INTF_HEADER_LEN;
+	/* Extra header for SDIO is added here */
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_CMD,
+				     pcmd_node->cmdbuf, MNULL);
+
+	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,
+			      MRVDRV_TIMER_10S * 2);
+
+	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;
+	t_u16 cmd_len = 0;
+	opt_sleep_confirm_buffer *sleep_cfm_buf =
+		(opt_sleep_confirm_buffer *)(pmadapter->psleep_cfm->pbuf +
+					     pmadapter->psleep_cfm->
+					     data_offset);
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	if (!pmpriv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	cmd_len = sizeof(OPT_Confirm_Sleep);
+	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 */
+
+	pmadapter->psleep_cfm->data_len = cmd_len + INTF_HEADER_LEN;
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_CMD,
+				     pmadapter->psleep_cfm, MNULL);
+
+	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 */
+
+#define NUM_SC_PER_LINE         16
+		if (++i % NUM_SC_PER_LINE == 0)
+			PRINTM(MEVENT, "+\n");
+		else
+			PRINTM(MEVENT, "+");
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Event handler
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param event_id Event ID
+ *  @param pmevent  Event buffer
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_recv_event(pmlan_private priv, mlan_event_id event_id, t_void *pmevent)
+{
+	pmlan_callbacks pcb = MNULL;
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pcb = &priv->adapter->callbacks;
+
+	if (pmevent)
+		/* The caller has provided the event. */
+		pcb->moal_recv_event(priv->adapter->pmoal_handle,
+				     (pmlan_event)pmevent);
+	else {
+		mlan_event mevent;
+
+		memset(priv->adapter, &mevent, 0, sizeof(mlan_event));
+		mevent.bss_index = priv->bss_index;
+		mevent.event_id = event_id;
+		mevent.event_len = 0;
+
+		pcb->moal_recv_event(priv->adapter->pmoal_handle, &mevent);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function allocates the command buffer and links
+ *          it to command free queue.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_alloc_cmd_buffer(IN 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);
+
+	/* 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;
+		}
+	}
+	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(IN 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++) {
+		if (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;
+		}
+		if (pcmd_array[i].respbuf) {
+			wlan_free_mlan_buffer(pmadapter, pcmd_array[i].respbuf);
+			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(pmadapter, (t_u8 *)&eventcause,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       sizeof(eventcause));
+		} else {
+			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(pmadapter,
+		       pmbuf->pbuf + pmbuf->data_offset,
+		       (t_u8 *)&eventcause, sizeof(eventcause));
+	}
+
+	if (MTRUE
+	    && (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE)
+		) {
+		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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	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(IN 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(IN 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(IN mlan_private *pmpriv,
+		 IN t_u16 cmd_no,
+		 IN t_u16 cmd_action,
+		 IN t_u32 cmd_oid, IN t_void *pioctl_buf, IN 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)
+			) {
+			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_oid, pioctl_buf, pdata_buf);
+
+	if (pcmd_node->cmdbuf == MNULL) {
+		PRINTM(MERROR, "PREP_CMD: No free cmd buf\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_ptr =
+		(HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+				       pcmd_node->cmdbuf->data_offset);
+	cmd_ptr->command = cmd_no;
+	cmd_ptr->result = 0;
+
+	/* Prepare command */
+	if (cmd_no)
+		ret = pmpriv->ops.prepare_cmd(pmpriv, cmd_no, cmd_action,
+					      cmd_oid, pioctl_buf, pdata_buf,
+					      cmd_ptr);
+	else {
+		ret = wlan_cmd_host_cmd(pmpriv, cmd_ptr, pdata_buf);
+		pcmd_node->cmd_flag |= CMD_F_HOSTCMD;
+	}
+
+	/* Return error, since the command preparation failed */
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "PREP_CMD: Command 0x%x preparation failed\n",
+		       cmd_no);
+		pcmd_node->pioctl_buf = MNULL;
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+		wlan_request_cmd_lock(pmadapter);
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+		wlan_release_cmd_lock(pmadapter);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	/* Send command */
+#ifdef STA_SUPPORT
+	if (cmd_no == HostCmd_CMD_802_11_SCAN
+	    || cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
+		wlan_queue_scan_cmd(pmpriv, pcmd_node);
+	} else {
+#endif
+		if ((cmd_no == HostCmd_CMD_802_11_HS_CFG_ENH) &&
+		    (cmd_action == HostCmd_ACT_GEN_SET) &&
+		    (pmadapter->hs_cfg.conditions == HOST_SLEEP_CFG_CANCEL))
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MFALSE);
+		else
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MTRUE);
+#ifdef STA_SUPPORT
+	}
+#endif
+	wlan_release_cmd_lock(pmadapter);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function inserts command node to cmd_free_q
+ *              after cleaning it.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_insert_cmd_to_free_q(IN mlan_adapter *pmadapter,
+			  IN 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(IN mlan_adapter *pmadapter,
+			     IN cmd_ctrl_node *pcmd_node, IN 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();
+
+	/* 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;
+	}
+
+	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;
+	}
+
+	pmadapter->num_cmd_timeout = 0;
+
+	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);
+	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);
+	}
+	orig_cmdresp_no = wlan_le16_to_cpu(resp->command);
+	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) {
+#if defined(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;
+		}
+	}
+
+	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) {
+
+#if defined(STA_SUPPORT)
+			if (pmadapter->pwarm_reset_ioctl_req) {
+				/* warm reset complete */
+				pmadapter->hw_status = WlanHardwareStatusReady;
+				pcb->moal_ioctl_complete(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 pwarm_reset_ioctl_req,
+							 MLAN_STATUS_SUCCESS);
+				pmadapter->pwarm_reset_ioctl_req = MNULL;
+				goto done;
+			}
+#endif
+			pmadapter->hw_status = WlanHardwareStatusInitdone;
+		} else {
+			/* Issue init commands for the next interface */
+			ret = pmpriv_next->ops.init_cmd(pmpriv_next, MFALSE);
+		}
+	} else if ((pmadapter->hw_status == WlanHardwareStatusGetHwSpec) &&
+		   (HostCmd_CMD_GET_HW_SPEC == cmdresp_no)) {
+		pmadapter->hw_status = WlanHardwareStatusGetHwSpecdone;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the timeout of command sending.
+ *          It will re-send the same command again.
+ *
+ *  @param function_context   A pointer to function_context
+ *  @return                   N/A
+ */
+t_void
+wlan_cmd_timeout_func(t_void *function_context)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)function_context;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	t_u8 i;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	pmadapter->cmd_timer_is_set = MFALSE;
+	if (!pmadapter->curr_cmd) {
+		PRINTM(MWARN, "CurCmd Empty\n");
+		goto exit;
+	}
+	pmadapter->num_cmd_timeout++;
+	pmadapter->dbg.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 (pcmd_node->cmdbuf) {
+		t_u8 *pcmd_buf;
+		pcmd_buf =
+			pcmd_node->cmdbuf->pbuf +
+			pcmd_node->cmdbuf->data_offset + INTF_HEADER_LEN;
+		for (i = 0; i < 16; i++)
+			PRINTM(MERROR, "%02x ", *pcmd_buf++);
+		PRINTM(MERROR, "\n");
+	}
+
+	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(IN pmlan_adapter pmadapter)
+{
+
+	cmd_ctrl_node *pcmd_node = MNULL;
+
+	ENTER();
+
+	wlan_request_cmd_lock(pmadapter);
+	while ((pcmd_node =
+		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						&pmadapter->scan_pending_q,
+						MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->scan_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		pcmd_node->pioctl_buf = MNULL;
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+
+	pmadapter->scan_processing = MFALSE;
+	wlan_release_cmd_lock(pmadapter);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Cancel pending SCAN ioctl cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param pioctl_req   A pointer to pmlan_ioctl_req
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	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;
+		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);
+	/* 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
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	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;
+		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;
+		pmadapter->curr_cmd = 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);
+	}
+
+	/* Cancel all pending command */
+	while ((pcmd_node =
+		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						&pmadapter->cmd_pending_q,
+						MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		if (pcmd_node->pioctl_buf) {
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+			pcmd_node->pioctl_buf = MNULL;
+		}
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+	wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	/* Cancel all pending scan command */
+	wlan_flush_scan_queue(pmadapter);
+#endif
+	LEAVE();
+}
+
+/**
+ *  @brief Cancel specific bss's pending ioctl cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param bss_index    BSS index
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+	t_u8 flash_scan = MFALSE;
+#endif
+	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;
+		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) {
+		/* 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;
+
+	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) {
+		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) {
+		/* 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 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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(pmpriv->adapter, info->param.ver_ext.version_str,
+		       ver_ext->version_str, sizeof(char) * 128);
+	}
+	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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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 && !IS_CARD_RX_RCVD(pmadapter)) {
+		wlan_dnld_sleep_confirm_cmd(pmadapter);
+	} else {
+		PRINTM(MCMND, "Delay Sleep Confirm (%s%s%s)\n",
+		       (pmadapter->cmd_sent) ? "D" : "",
+		       (pmadapter->curr_cmd) ? "C" : "",
+		       (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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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();
+
+	if (wlan_le16_to_cpu(phs_cfg->action) == HS_ACTIVATE) {
+		/* 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);
+		wlan_host_sleep_activated_event(pmpriv, MTRUE);
+		goto done;
+	} else {
+		phs_cfg->params.hs_config.conditions =
+			wlan_le32_to_cpu(phs_cfg->params.hs_config.conditions);
+		PRINTM(MCMND,
+		       "CMD_RESP: HS_CFG cmd reply result=%#x,"
+		       " conditions=0x%x gpio=0x%x gap=0x%x\n", resp->result,
+		       phs_cfg->params.hs_config.conditions,
+		       phs_cfg->params.hs_config.gpio,
+		       phs_cfg->params.hs_config.gap);
+	}
+	if (phs_cfg->params.hs_config.conditions != HOST_SLEEP_CFG_CANCEL) {
+		pmadapter->is_hs_configured = 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) {
+		wlan_pm_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;
+
+	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);
+
+	/* 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 (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(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,
+			IN HostCmd_DS_COMMAND *cmd,
+			IN t_u16 cmd_action,
+			IN t_u16 ps_bitmap, IN 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(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *resp,
+			IN 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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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->psdio_device->v15_fw_api)
+		pmpriv->tx_rate_info =
+			wlan_convert_v14_rate_ht_info(pmpriv->tx_rate_info);
+
+	if (!pmpriv->is_data_rate_auto) {
+		pmpriv->data_rate = wlan_index_to_data_rate(pmadapter,
+							    pmpriv->tx_rate,
+							    pmpriv->
+							    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)
+					/* 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);
+			}
+		} else if (rate->sub_command == MLAN_OID_GET_DATA_RATE) {
+			/* Tx rate info */
+			if ((pmpriv->tx_rate_info & 0x3) ==
+			    MLAN_RATE_FORMAT_VHT) {
+				/* VHT rate */
+				rate->param.data_rate.tx_rate_format =
+					MLAN_RATE_FORMAT_VHT;
+				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_nss =
+					(pmpriv->tx_rate) >> 4;
+				rate->param.data_rate.tx_mcs_index =
+					(pmpriv->tx_rate) & 0xF;
+				rate->param.data_rate.tx_data_rate =
+					wlan_index_to_data_rate(pmadapter,
+								pmpriv->tx_rate,
+								pmpriv->
+								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);
+			} 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) {
+				/* VHT rate */
+				rate->param.data_rate.rx_rate_format =
+					MLAN_RATE_FORMAT_VHT;
+				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_nss =
+					(pmpriv->rxpd_rate) >> 4;
+				rate->param.data_rate.rx_mcs_index =
+					(pmpriv->rxpd_rate) & 0xF;
+				rate->param.data_rate.rx_data_rate =
+					wlan_index_to_data_rate(pmadapter,
+								pmpriv->
+								rxpd_rate,
+								pmpriv->
+								rxpd_rate_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);
+			} 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN 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 *) ((t_u8 *)rbstcx +
+							sizeof
+							(HostCmd_DS_802_11_ROBUSTCOEX));
+
+	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;
+}
+
+/**
+ *  @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
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN t_void *pdata_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;
+	t_u16 *pbitmap_rates = (t_u16 *)pdata_buf;
+
+	t_u32 i;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
+
+	rate_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	rate_scope = (MrvlRateScope_t *)((t_u8 *)rate_cfg +
+					 sizeof(HostCmd_DS_TX_RATE_CFG));
+	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]);
+	} 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]);
+	}
+
+	rate_drop = (MrvlRateDropPattern_t *)((t_u8 *)rate_scope +
+					      sizeof(MrvlRateScope_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) +
+				     sizeof(MrvlRateScope_t) +
+				     sizeof(MrvlRateDropPattern_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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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;
+
+	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 *)((t_u8 *)prate_cfg) + sizeof(HostCmd_DS_TX_RATE_CFG);
+	if (tlv_buf) {
+		tlv_buf_len = *(t_u16 *)(tlv_buf + sizeof(t_u16));
+		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]);
+			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;
+	}
+
+	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;
+			}
+			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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	/*
+	 * This should be issued in the very first to config
+	 *   SDIO_GPIO interrupt mode.
+	 */
+	if (wlan_set_sdio_gpio_int(priv) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	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;
+	}
+    /** 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;
+	}
+	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;
+		}
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
+				       HostCmd_ACT_GEN_GET, OID_TYPE_DPD_OTHER,
+				       MNULL, MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	/* Get FW region and cfp tables */
+	if (pmadapter->init_para.fw_region) {
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
+				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	/*
+	 * Get HW spec
+	 */
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function issues adapter specific commands
+ *          to initialize firmware
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_adapter_init_cmd(IN 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
+
+	/* Reconfigure tx buf size */
+	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
+
+#if defined(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->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;
+		}
+	}
+	if (pmadapter->init_para.drcs_chantime_mode) {
+		mlan_ds_drcs_cfg drcs_init_cfg[2];
+		drcs_init_cfg[0].chan_idx = 0x1;
+		drcs_init_cfg[0].chantime =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 8);
+		/* switchtime use default value in fw */
+		drcs_init_cfg[0].switchtime = 10;
+		drcs_init_cfg[0].undozetime = 5;
+		drcs_init_cfg[0].mode =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode);
+		drcs_init_cfg[1].chan_idx = 0x2;
+		drcs_init_cfg[1].chantime =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 24);
+		/* switchtime use default value in fw */
+		drcs_init_cfg[1].switchtime = 10;
+		drcs_init_cfg[1].undozetime = 5;
+		drcs_init_cfg[1].mode =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 16);
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DRCS_CONFIG,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       (t_void *)drcs_init_cfg);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef RX_PACKET_COALESCE
+/**
+ *  @brief This function prepares command of rx_pkt_coalesce_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_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			     const IN HostCmd_DS_COMMAND *resp,
+			     OUT 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 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_handle_event_multi_chan_info(IN pmlan_private pmpriv, pmlan_buffer pevent)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	t_u32 interfaces = 0;
+	MrvlIEtypes_multi_chan_info_t *pmulti_chan_info = MNULL;
+	MrvlIEtypes_multi_chan_group_info_t *pmulti_chan_grp_info = MNULL;
+	int tlv_buf_left = pevent->data_len - sizeof(mlan_event_id);
+	t_u16 tlv_type, tlv_len;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private intf_priv = MNULL;
+	int num_intf = 0, bss_type = 0, bss_num = 0;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+
+	ENTER();
+
+	PRINTM(MEVENT, "multi channel event\n");
+	pmulti_chan_info =
+		(MrvlIEtypes_multi_chan_info_t *)(pevent->pbuf +
+						  pevent->data_offset +
+						  sizeof(mlan_event_id));
+	if (tlv_buf_left < sizeof(MrvlIEtypes_multi_chan_info_t) ||
+	    wlan_le16_to_cpu(pmulti_chan_info->header.type) !=
+	    TLV_TYPE_MULTI_CHAN_INFO) {
+		PRINTM(MERROR, "Invalid multi channel event\n");
+		goto done;
+	}
+
+	pmadapter->mc_status = wlan_le16_to_cpu(pmulti_chan_info->status);
+	PRINTM(MEVENT, "mc_status=%d\n", pmadapter->mc_status);
+	tlv_buf_left -= sizeof(MrvlIEtypes_multi_chan_info_t);
+	tlv = (MrvlIEtypesHeader_t *)pmulti_chan_info->tlv_buffer;
+
+	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_MULTI_CHAN_GROUP_INFO_TLV_ID) {
+			PRINTM(MERROR, "wrong tlv type:0x%x\n", tlv_type);
+			break;
+		}
+		pmulti_chan_grp_info =
+			(MrvlIEtypes_multi_chan_group_info_t *)tlv;
+		PRINTM(MEVENT, "mc_info: groupid=%d chan=%d, numintf=%d\n",
+		       pmulti_chan_grp_info->chan_group_id,
+		       pmulti_chan_grp_info->chan_band_info.chan_num,
+		       pmulti_chan_grp_info->num_intf);
+		num_intf = pmulti_chan_grp_info->num_intf;
+		for (interfaces = 0; interfaces < num_intf; interfaces++) {
+			bss_type =
+				pmulti_chan_grp_info->
+				bss_type_numlist[interfaces] >> 4;
+			bss_num =
+				pmulti_chan_grp_info->
+				bss_type_numlist[interfaces] & BSS_NUM_MASK;
+			PRINTM(MEVENT, "intf%d: bss_type=%d bss_num=%d\n",
+			       interfaces, bss_type, bss_num);
+			intf_priv =
+				wlan_get_priv_by_id(pmadapter, bss_num,
+						    bss_type);
+			if (intf_priv) {
+			} else {
+				PRINTM(MERROR,
+				       "Invalid bss_type, bss_num in multi_channel event\n");
+			}
+		}
+
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares the command MULTI_CHAN_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          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_multi_chan_cfg(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *cmd,
+			IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_multi_chan_cfg *multi_chan_cfg =
+		(mlan_ds_multi_chan_cfg *)pdata_buf;
+	HostCmd_DS_MULTI_CHAN_CFG *pmchan_cfg =
+		(HostCmd_DS_MULTI_CHAN_CFG *)&cmd->params.multi_chan_cfg;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_CONFIG);
+	pmchan_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		pmchan_cfg->buffer_weight = multi_chan_cfg->buffer_weight;
+		pmchan_cfg->channel_time =
+			wlan_cpu_to_le32(multi_chan_cfg->channel_time);
+		PRINTM(MCMND,
+		       "Set multi-channel: buffer_weight=%d channel_time=%d\n",
+		       multi_chan_cfg->buffer_weight,
+		       multi_chan_cfg->channel_time);
+		cmd->size =
+			wlan_cpu_to_le16(S_DS_GEN +
+					 sizeof(HostCmd_DS_MULTI_CHAN_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 MULTI_CHAN_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_multi_chan_cfg(IN pmlan_private pmpriv,
+			const IN HostCmd_DS_COMMAND *resp,
+			OUT mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_MULTI_CHAN_CFG *presp_cfg =
+		&resp->params.multi_chan_cfg;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		pcfg->param.multi_chan_cfg.channel_time =
+			wlan_le32_to_cpu(presp_cfg->channel_time);
+		pcfg->param.multi_chan_cfg.buffer_weight =
+			presp_cfg->buffer_weight;
+		pcfg->param.multi_chan_cfg.tlv_len =
+			resp->size - (sizeof(HostCmd_DS_GEN) +
+				      sizeof(HostCmd_DS_MULTI_CHAN_CFG));
+		PRINTM(MCMND,
+		       "Get multi-channel: buffer_weight=%d channel_time=%d tlv_len=%d\n",
+		       pcfg->param.multi_chan_cfg.buffer_weight,
+		       pcfg->param.multi_chan_cfg.channel_time,
+		       pcfg->param.multi_chan_cfg.tlv_len);
+		memcpy(pmpriv->adapter, pcfg->param.multi_chan_cfg.tlv_buf,
+		       presp_cfg->tlv_buf, pcfg->param.multi_chan_cfg.tlv_len);
+		pioctl_buf->buf_len =
+			sizeof(mlan_ds_multi_chan_cfg) +
+			pcfg->param.multi_chan_cfg.tlv_len;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command MULTI_CHAN_POLICY
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          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_multi_chan_policy(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	t_u16 policy = 0;
+	HostCmd_DS_MULTI_CHAN_POLICY *pmulti_chan_policy =
+		(HostCmd_DS_MULTI_CHAN_POLICY *)&cmd->params.multi_chan_policy;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_POLICY);
+	pmulti_chan_policy->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size =
+		wlan_cpu_to_le16(S_DS_GEN +
+				 sizeof(HostCmd_DS_MULTI_CHAN_POLICY));
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		policy = *((t_u16 *)pdata_buf);
+		pmulti_chan_policy->policy = wlan_cpu_to_le16(policy);
+		PRINTM(MCMND, "Set multi-channel policy: %d\n", policy);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of MULTI_CHAN_POLICY
+ *
+ *  @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_multi_chan_policy(IN pmlan_private pmpriv,
+			   const IN HostCmd_DS_COMMAND *resp,
+			   OUT mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_MULTI_CHAN_POLICY *presp_cfg =
+		&resp->params.multi_chan_policy;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		pcfg->param.multi_chan_policy =
+			wlan_le16_to_cpu(presp_cfg->policy);
+
+		if (pioctl_buf->action == HostCmd_ACT_GEN_SET) {
+			if (pcfg->param.multi_chan_policy)
+				pmpriv->adapter->mc_policy = MTRUE;
+			else
+				pmpriv->adapter->mc_policy = MFALSE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command DRCD_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          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_drcs_cfg(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *cmd,
+		  IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_drcs_cfg *drcs_cfg = (mlan_ds_drcs_cfg *) pdata_buf;
+	HostCmd_DS_DRCS_CFG *pdrcs_cfg =
+		(HostCmd_DS_DRCS_CFG *) & cmd->params.drcs_cfg;
+	MrvlTypes_DrcsTimeSlice_t *channel_time_slicing =
+		&pdrcs_cfg->time_slicing;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DRCS_CONFIG);
+	pdrcs_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		channel_time_slicing->header.type =
+			wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
+		channel_time_slicing->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlTypes_DrcsTimeSlice_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		channel_time_slicing->chan_idx =
+			wlan_cpu_to_le16(drcs_cfg->chan_idx);
+		channel_time_slicing->chantime = drcs_cfg->chantime;
+		channel_time_slicing->switchtime = drcs_cfg->switchtime;
+		channel_time_slicing->undozetime = drcs_cfg->undozetime;
+		channel_time_slicing->mode = drcs_cfg->mode;
+		PRINTM(MCMND,
+		       "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+		       channel_time_slicing->chan_idx,
+		       channel_time_slicing->chantime,
+		       channel_time_slicing->switchtime,
+		       channel_time_slicing->undozetime,
+		       channel_time_slicing->mode);
+		cmd->size =
+			wlan_cpu_to_le16(S_DS_GEN +
+					 sizeof(HostCmd_DS_DRCS_CFG));
+		/* Set two channels different parameters */
+		if (0x3 != channel_time_slicing->chan_idx) {
+			drcs_cfg++;
+			channel_time_slicing = pdrcs_cfg->drcs_buf;
+			channel_time_slicing->header.type =
+				wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
+			channel_time_slicing->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlTypes_DrcsTimeSlice_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			channel_time_slicing->chan_idx =
+				wlan_cpu_to_le16(drcs_cfg->chan_idx);
+			channel_time_slicing->chantime = drcs_cfg->chantime;
+			channel_time_slicing->switchtime = drcs_cfg->switchtime;
+			channel_time_slicing->undozetime = drcs_cfg->undozetime;
+			channel_time_slicing->mode = drcs_cfg->mode;
+			PRINTM(MCMND,
+			       "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+			       channel_time_slicing->chan_idx,
+			       channel_time_slicing->chantime,
+			       channel_time_slicing->switchtime,
+			       channel_time_slicing->undozetime,
+			       channel_time_slicing->mode);
+			cmd->size +=
+				wlan_cpu_to_le16(sizeof
+						 (MrvlTypes_DrcsTimeSlice_t));
+		}
+	} 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 DRCS_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_drcs_cfg(IN pmlan_private pmpriv,
+		  const IN HostCmd_DS_COMMAND *resp,
+		  OUT mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_DRCS_CFG *presp_cfg = &resp->params.drcs_cfg;
+	const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing =
+		&presp_cfg->time_slicing;
+	const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing1 = MNULL;
+	mlan_ds_drcs_cfg *drcs_cfg1 = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		if (wlan_le16_to_cpu(channel_time_slicing->header.type) !=
+		    MRVL_DRCS_TIME_SLICE_TLV_ID ||
+		    wlan_le16_to_cpu(channel_time_slicing->header.len) !=
+		    sizeof(MrvlTypes_DrcsTimeSlice_t) -
+		    sizeof(MrvlIEtypesHeader_t)) {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pcfg->param.drcs_cfg[0].chan_idx =
+			wlan_le16_to_cpu(channel_time_slicing->chan_idx);
+		pcfg->param.drcs_cfg[0].chantime =
+			channel_time_slicing->chantime;
+		pcfg->param.drcs_cfg[0].switchtime =
+			channel_time_slicing->switchtime;
+		pcfg->param.drcs_cfg[0].undozetime =
+			channel_time_slicing->undozetime;
+		pcfg->param.drcs_cfg[0].mode = channel_time_slicing->mode;
+		PRINTM(MCMND,
+		       "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+		       pcfg->param.drcs_cfg[0].chan_idx,
+		       channel_time_slicing->chantime,
+		       channel_time_slicing->switchtime,
+		       channel_time_slicing->undozetime,
+		       channel_time_slicing->mode);
+		pioctl_buf->buf_len = sizeof(mlan_ds_drcs_cfg);
+		/*Channel for chan_idx 1 and 2 have different parameters */
+		if (0x3 != pcfg->param.drcs_cfg[0].chan_idx) {
+			channel_time_slicing1 = presp_cfg->drcs_buf;
+			if (wlan_le16_to_cpu(channel_time_slicing1->header.type)
+			    != MRVL_DRCS_TIME_SLICE_TLV_ID ||
+			    wlan_le16_to_cpu(channel_time_slicing1->header.
+					     len) !=
+			    sizeof(MrvlTypes_DrcsTimeSlice_t) -
+			    sizeof(MrvlIEtypesHeader_t)) {
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+			drcs_cfg1 =
+				(mlan_ds_drcs_cfg *) & pcfg->param.drcs_cfg[1];
+			drcs_cfg1->chan_idx =
+				wlan_le16_to_cpu(channel_time_slicing1->
+						 chan_idx);
+			drcs_cfg1->chantime = channel_time_slicing1->chantime;
+			drcs_cfg1->switchtime =
+				channel_time_slicing1->switchtime;
+			drcs_cfg1->undozetime =
+				channel_time_slicing1->undozetime;
+			drcs_cfg1->mode = channel_time_slicing1->mode;
+			PRINTM(MCMND,
+			       "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+			       drcs_cfg1->chan_idx, drcs_cfg1->chantime,
+			       drcs_cfg1->switchtime, drcs_cfg1->undozetime,
+			       drcs_cfg1->mode);
+			pioctl_buf->buf_len += sizeof(mlan_ds_drcs_cfg);
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv, IN 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(pmpriv->adapter, hw_spec->permanent_addr, pmpriv->curr_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN HostCmd_DS_COMMAND *pcmd,
+			  IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &resp->params.sdio_rx_aggr;
+
+	pmadapter->sdio_rx_aggr_enable = cfg->enable;
+	pmadapter->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->sdio_rx_block_size);
+	if (!pmadapter->sdio_rx_block_size)
+		pmadapter->sdio_rx_aggr_enable = MFALSE;
+	if (pmadapter->sdio_rx_aggr_enable) {
+		pmadapter->max_sp_rx_size = SDIO_CMD53_MAX_SIZE;
+		wlan_re_alloc_sdio_rx_mpa_buffer(pmadapter);
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *pcmd,
+		  IN t_u16 cmd_action, IN t_u32 cmd_oid, IN 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 (!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 || type == OID_TYPE_DPD_OTHER)) {
+			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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *pcmd,
+		     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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;
+
+	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;
+			}
+		}
+		if ((pmadapter->fw_bands & BAND_AN)
+			) {
+			pmadapter->adhoc_start_band = BAND_A | BAND_AN;
+			pmadapter->adhoc_11n_enabled = MTRUE;
+		} else
+			pmadapter->adhoc_start_band = BAND_A;
+		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
+	} else if ((pmadapter->fw_bands & BAND_GN)
+		) {
+		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+		pmadapter->adhoc_11n_enabled = MTRUE;
+	} 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 */
+
+	PRINTM(MCMND, "fw_band=0x%x, config_band=0x%x adhoc_band=0x%x\n",
+	       pmadapter->fw_bands, pmadapter->config_bands,
+	       pmadapter->adhoc_start_band);
+	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 (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 =
+					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);
+	pmadapter->mp_end_port = wlan_le16_to_cpu(hw_spec->mp_end_port);
+
+	for (i = 1; i <= (unsigned)(MAX_PORT - pmadapter->mp_end_port); i++)
+		pmadapter->mp_data_port_mask &= ~(1 << (MAX_PORT - i));
+
+	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 & SDIO_SP_RX_AGGR_ENABLE) &&
+	    pmadapter->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->sdio_rx_aggr_enable = MFALSE;
+		PRINTM(MCMND, "FW: SDIO rx aggr disabled 0x%x\n",
+		       pmadapter->fw_cap_info);
+	}
+
+	if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+				 pmadapter->fw_bands)) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#ifdef STA_SUPPORT
+	if (wlan_11d_set_universaltable(pmpriv, pmadapter->fw_bands)) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#endif /* STA_SUPPORT */
+	if (pmadapter->fw_cap_info & FW_CAPINFO_ECSA) {
+		t_u8 ecsa_enable = MTRUE;
+		pmadapter->ecsa_enable = MTRUE;
+		PRINTM(MCMND, "pmadapter->ecsa_enable=%d\n",
+		       pmadapter->ecsa_enable);
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET, ECSAEnable_i, MNULL,
+				       &ecsa_enable);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (pmadapter->fw_cap_info & FW_CAPINFO_GET_LOG) {
+		pmadapter->getlog_enable = MTRUE;
+		PRINTM(MCMND, "pmadapter->getlog_enable=%d\n",
+		       pmadapter->getlog_enable);
+	}
+
+	left_len = resp->size - sizeof(HostCmd_DS_GET_HW_SPEC) - S_DS_GEN;
+	tlv = (MrvlIEtypesHeader_t *)((t_u8 *)hw_spec +
+				      sizeof(HostCmd_DS_GET_HW_SPEC));
+	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		switch (tlv_type) {
+		case TLV_TYPE_FW_VER_INFO:
+			api_rev = (MrvlIEtypes_fw_ver_info_t *) tlv;
+			api_id = wlan_le16_to_cpu(api_rev->api_id);
+			switch (api_id) {
+			case FW_API_VER_ID:
+				pmadapter->fw_ver = api_rev->major_ver;
+				pmadapter->fw_min_ver = api_rev->minor_ver;
+				PRINTM(MCMND, "fw ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			case UAP_FW_API_VER_ID:
+				pmadapter->uap_fw_ver = api_rev->major_ver;
+				PRINTM(MCMND, "uap fw ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			case CHANRPT_API_VER_ID:
+				pmadapter->chanrpt_param_bandcfg =
+					api_rev->minor_ver;
+				PRINTM(MCMND, "chanrpt api ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			default:
+				break;
+			}
+			break;
+		case TLV_TYPE_MAX_CONN:
+			tlv_max_conn = (MrvlIEtypes_Max_Conn_t *) tlv;
+			PRINTM(MMSG, "max_p2p_conn = %d, max_sta_conn = %d\n",
+			       tlv_max_conn->max_p2p_conn,
+			       tlv_max_conn->max_sta_conn);
+			if (tlv_max_conn->max_p2p_conn &&
+			    tlv_max_conn->max_sta_conn)
+				pmadapter->max_sta_conn =
+					MIN(tlv_max_conn->max_sta_conn,
+					    tlv_max_conn->max_p2p_conn);
+			else if (tlv_max_conn->max_sta_conn)
+				pmadapter->max_sta_conn =
+					tlv_max_conn->max_sta_conn;
+			else if (tlv_max_conn->max_p2p_conn)
+				pmadapter->max_sta_conn =
+					tlv_max_conn->max_p2p_conn;
+			else
+				pmadapter->max_sta_conn = 0;
+			break;
+		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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN 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(pmpriv->adapter, &radio_ctl, pdata_buf, sizeof(t_u32));
+	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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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 +
+			sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG);
+		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 +
+			sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG);
+		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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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 *)((t_u8 *)p2p_config +
+						      sizeof
+						      (HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG));
+			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 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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);
+	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(MINFO, "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);
+	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 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(IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_reg_rw *reg_rw;
+
+	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);
+			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;
+			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;
+			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;
+		}
+	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,
+		    IN HostCmd_DS_COMMAND *resp, IN 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(pmadapter, &eeprom->value,
+					       &cmd_eeprom->value,
+					       MIN(MAX_EEPROM_DATA,
+						   eeprom->byte_count));
+					HEXDUMP("EEPROM",
+						(char *)&eeprom->value,
+						MIN(MAX_EEPROM_DATA,
+						    eeprom->byte_count));
+				}
+				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(IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_ds_mem_rw *mem_rw = MNULL;
+	HostCmd_DS_MEM_ACCESS *mem = (HostCmd_DS_MEM_ACCESS *)&resp->params.mem;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
+		mem_rw = &reg_mem->param.mem_rw;
+
+		mem_rw->addr = wlan_le32_to_cpu(mem->addr);
+		mem_rw->value = wlan_le32_to_cpu(mem->value);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+*
+*  @brief This function handles coex events generated by firmware
+*
+*  @param priv A pointer to mlan_private structure
+*  @param pevent   A pointer to event buf
+*
+*  @return     N/A
+*/
+void
+wlan_bt_coex_wlan_param_update_event(pmlan_private priv, pmlan_buffer pevent)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	MrvlIETypes_BtCoexAggrWinSize_t *pCoexWinsize = MNULL;
+	MrvlIEtypes_BtCoexScanTime_t *pScantlv = MNULL;
+	t_s32 len = pevent->data_len - sizeof(t_u32);
+	t_u8 *pCurrent_ptr = pevent->pbuf + pevent->data_offset + sizeof(t_u32);
+	t_u16 tlv_type, tlv_len;
+
+	ENTER();
+
+	while (len >= sizeof(MrvlIEtypesHeader_t)) {
+		tlv = (MrvlIEtypesHeader_t *)pCurrent_ptr;
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		if ((tlv_len + sizeof(MrvlIEtypesHeader_t)) > len)
+			break;
+		switch (tlv_type) {
+		case TLV_BTCOEX_WL_AGGR_WINSIZE:
+			pCoexWinsize = (MrvlIETypes_BtCoexAggrWinSize_t *) tlv;
+			pmadapter->coex_win_size = pCoexWinsize->coex_win_size;
+			pmadapter->coex_tx_win_size = pCoexWinsize->tx_win_size;
+			pmadapter->coex_rx_win_size = pCoexWinsize->rx_win_size;
+			wlan_coex_ampdu_rxwinsize(pmadapter);
+			wlan_update_ampdu_txwinsize(pmadapter);
+			break;
+		case TLV_BTCOEX_WL_SCANTIME:
+			pScantlv = (MrvlIEtypes_BtCoexScanTime_t *) tlv;
+			pmadapter->coex_scan = pScantlv->coex_scan;
+			pmadapter->coex_min_scan_time =
+				wlan_le16_to_cpu(pScantlv->min_scan_time);
+			pmadapter->coex_max_scan_time =
+				wlan_le16_to_cpu(pScantlv->max_scan_time);
+			break;
+		default:
+			break;
+		}
+		len -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		pCurrent_ptr += tlv_len + sizeof(MrvlIEtypesHeader_t);
+	}
+	PRINTM(MEVENT,
+	       "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
+	       pmadapter->coex_scan, pmadapter->coex_min_scan_time,
+	       pmadapter->coex_win_size, pmadapter->coex_tx_win_size,
+	       pmadapter->coex_rx_win_size);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares command of supplicant pmk
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_802_11_supplicant_pmk(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+	MrvlIEtypes_Passphrase_t *ppassphrase_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;
+
+	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=marvell
+	 *  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=mrvl/: 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=marvell
+	 */
+
+	/* -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(pmpriv->adapter, pbssid_tlv->bssid, (t_u8 *)&psk->bssid,
+		       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(pmpriv->adapter, ppmk_tlv->pmk, psk->psk.pmk.pmk,
+		       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 && 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(pmpriv->adapter, (t_u8 *)pssid_tlv->ssid,
+		       (t_u8 *)psk->ssid.ssid, MIN(MLAN_MAX_SSID_LENGTH,
+						   psk->ssid.ssid_len));
+		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->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(pmpriv->adapter, ppassphrase_tlv->passphrase,
+		       psk->psk.passphrase.passphrase,
+		       MIN(MLAN_MAX_PASSPHRASE_LENGTH,
+			   psk->psk.passphrase.passphrase_len));
+		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 ((cmd_action == HostCmd_ACT_GEN_SET) &&
+	    ((ssid_flag || bssid_flag) && (!pmk_flag && !passphrase_flag))) {
+		PRINTM(MERROR,
+		       "Invalid case,ssid/bssid present without pmk or passphrase\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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *resp,
+			       IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_SUPPLICANT_PMK *supplicant_pmk_resp =
+		&resp->params.esupplicant_psk;
+	mlan_ds_sec_cfg sec_buf;
+	mlan_ds_sec_cfg *sec = MNULL;
+	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+	MrvlIEtypes_Passphrase_t *passphrase_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)
+			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))
+					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(pmpriv->adapter,
+					       sec->param.passphrase.ssid.ssid,
+					       pssid_tlv->ssid,
+					       MIN(MLAN_MAX_SSID_LENGTH,
+						   pssid_tlv->header.len));
+					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(pmpriv->adapter,
+					       &sec->param.passphrase.bssid,
+					       pbssid_tlv->bssid,
+					       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(pmpriv->adapter,
+					       sec->param.passphrase.psk.
+					       passphrase.passphrase,
+					       passphrase_tlv->passphrase,
+					       MIN(MLAN_MAX_PASSPHRASE_LENGTH,
+						   passphrase_tlv->header.len));
+					tlv_buf +=
+						passphrase_tlv->header.len +
+						sizeof(MrvlIEtypesHeader_t);
+					tlv_buf_len -=
+						(passphrase_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(pmpriv->adapter,
+					       sec->param.passphrase.psk.pmk.
+					       pmk, ppmk_tlv->pmk,
+					       MIN(MLAN_MAX_KEY_LENGTH,
+						   ppmk_tlv->header.len));
+					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;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action, IN 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,
+		 IN HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u16 action;
+	HostCmd_DS_CHAN_REGION_CFG *reg = MNULL;
+	t_u8 *tlv_buf = MNULL;
+	t_u16 tlv_buf_left;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	mlan_ds_misc_chnrgpwr_cfg *cfg = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	reg = (HostCmd_DS_CHAN_REGION_CFG *) & resp->params.reg_cfg;
+	if (!reg) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	action = wlan_le16_to_cpu(reg->action);
+	if (action != HostCmd_ACT_GEN_GET) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	tlv_buf = (t_u8 *)reg + sizeof(*reg);
+	tlv_buf_left = wlan_le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
+
+	/* Add FW cfp tables and region info */
+	wlan_add_fw_cfp_tables(pmpriv, tlv_buf, tlv_buf_left);
+
+	if (!pioctl_buf)
+		goto done;
+
+	if (!pioctl_buf->pbuf) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+	if (misc_cfg->sub_command == MLAN_OID_MISC_GET_REGIONPWR_CFG) {
+		cfg = (mlan_ds_misc_chnrgpwr_cfg *) & (misc_cfg->param.
+						       rgchnpwr_cfg);
+		cfg->length = wlan_le16_to_cpu(resp->size);
+		memcpy(pmpriv->adapter, cfg->chnrgpwr_buf, (t_u8 *)resp,
+		       cfg->length);
+	} else {
+		memset(pmpriv->adapter, &misc_cfg->param.custom_reg_domain, 0,
+		       sizeof(mlan_ds_custom_reg_domain));
+		if (pmadapter->otp_region)
+			memcpy(pmpriv->adapter,
+			       &misc_cfg->param.custom_reg_domain.region,
+			       pmadapter->otp_region,
+			       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(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));
+		}
+		if (pmadapter->cfp_otp_a) {
+			misc_cfg->param.custom_reg_domain.num_a_chan =
+				pmadapter->tx_power_table_a_rows;
+			memcpy(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));
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends fw dump event command to firmware.
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param cmd            HostCmd_DS_COMMAND structure
+ *  @param cmd_action     the action: GET or SET
+ *  @param pdata_buf      A void pointer to information buffer
+ *  @return               N/A
+ */
+mlan_status
+wlan_cmd_fw_dump_event(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *resp, IN 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;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN 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 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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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(pmadapter, cfg->trpc_buf, (t_u8 *)resp, cfg->length);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/wlan_sd8987/mlan/mlan_decl.h b/wlan_sd8987/mlan/mlan_decl.h
new file mode 100644
index 0000000..a308809
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_decl.h
@@ -0,0 +1,1478 @@
+/** @file mlan_decl.h
+ *
+ *  @brief This file declares the generic data structures and APIs.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    11/07/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_DECL_H_
+#define _MLAN_DECL_H_
+
+/** MLAN release version */
+#define MLAN_RELEASE_VERSION		 "C637.P9"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef signed char t_s8;
+/** Unsigned char (1-byte) */
+typedef unsigned char t_u8;
+/** Signed short (2-bytes) */
+typedef short t_s16;
+/** Unsigned short (2-bytes) */
+typedef unsigned short t_u16;
+/** Signed long (4-bytes) */
+typedef int t_s32;
+/** Unsigned long (4-bytes) */
+typedef unsigned int t_u32;
+/** Signed long long 8-bytes) */
+typedef long long t_s64;
+/** Unsigned long long 8-bytes) */
+typedef unsigned long long t_u64;
+/** Void pointer (4-bytes) */
+typedef void t_void;
+/** 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)
+
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM         (16)
+
+/** NET IP alignment */
+#define MLAN_NET_IP_ALIGN        2
+
+/** DMA alignment */
+/* SDIO3.0 Inrevium Adapter require 32 bit DMA alignment */
+#define DMA_ALIGNMENT            32
+
+/** max size of TxPD */
+#define MAX_TXPD_SIZE            32
+
+/** Minimum data header length */
+#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT+MAX_TXPD_SIZE)
+
+/** rx data header length */
+#define MLAN_RX_HEADER_LEN       MLAN_MIN_DATA_HEADER_LEN
+
+/** This is current limit on Maximum Tx AMPDU allowed */
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED          16
+#define MLAN_MAX_TX_BASTREAM_DEFAULT            2
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED_NOV15    2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED     16
+
+/** station ampdu tx win size */
+#define MLAN_STA_AMPDU_DEF_TXWINSIZE_NOV15      32
+/** uap ampdu tx win size */
+#define MLAN_UAP_AMPDU_DEF_TXWINSIZE_NOV15      32
+/** uap ampdu rx win size */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE_NOV15      32
+#ifdef WIFI_DIRECT_SUPPORT
+/** wfd ampdu tx/rx win size */
+#define MLAN_WFD_AMPDU_DEF_TXRXWINSIZE_NOV15    32
+#endif
+
+#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       48
+/** Default Win size attached during ADDBA response */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE       32
+/** 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 7 */
+#define MLAN_RATE_INDEX_MCS7    7
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9    9
+/** 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 command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (4 * 1024)
+/** Upload size */
+#define WLAN_UPLD_SIZE            MRVDRV_SIZE_OF_CMD_BUFFER
+/** Size of rx data buffer 4096+256 */
+#define MLAN_RX_DATA_BUF_SIZE     4352
+/** Size of rx command buffer */
+#define MLAN_RX_CMD_BUF_SIZE      MRVDRV_SIZE_OF_CMD_BUFFER
+
+#define MLAN_USB_RX_DATA_BUF_SIZE       MLAN_RX_DATA_BUF_SIZE
+
+/** 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
+
+/** 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)
+/** SDIO MP aggr pkt limit 16*/
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_16	 (16)
+/** max SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX	 (16)
+
+/** SDIO IO Port mask */
+#define MLAN_SDIO_IO_PORT_MASK		0xfffff
+/** SDIO Block/Byte mode mask */
+#define MLAN_SDIO_BYTE_MODE_MASK	0x80000000
+
+/** Max retry number of IO write */
+#define MAX_WRITE_IOMEM_RETRY		2
+
+/** 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)
+
+/** 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)
+
+#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 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,
+	MLAN_STATUS_COMPLETE,
+} 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,
+	MLAN_BUF_TYPE_SPA_DATA,
+} mlan_buf_type;
+
+/** 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 bit mask */
+#define BSS_ROLE_BIT_MASK    MBIT(0)
+
+/** Get BSS role */
+#define GET_BSS_ROLE(priv)   ((priv)->bss_role & BSS_ROLE_BIT_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,
+	/* 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_STORE_HOST_CMD_RESP = 0x80000029,
+} mlan_event_id;
+
+/** Data Structures */
+/** mlan_image data structure */
+typedef struct _mlan_fw_image {
+    /** Helper image buffer pointer */
+	t_u8 *phelper_buf;
+    /** Helper image length */
+	t_u32 helper_len;
+    /** 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;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Data_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Data */
+	t_u8 data[1];
+} MLAN_PACK_END MrvlIEtypes_Data_t;
+
+#define OID_TYPE_CAL    0x2
+/** DPD PM-PM data type*/
+#define OID_TYPE_DPD              0xa
+/** DPD AM-AM AM-PM and APPD data */
+#define OID_TYPE_DPD_OTHER        0xb
+/** Unknow DPD length, Flag to trigger FW DPD training */
+#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,
+};
+
+/** 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 MARVELL_CHANNEL_NO_OFDM         MBIT(9)
+#define MARVELL_CHANNEL_NO_CCK          MBIT(8)
+#define MARVELL_CHANNEL_DISABLED		MBIT(7)
+/* BIT 5/6 resevered for FW */
+#define MARVELL_CHANNEL_NOHT160			MBIT(4)
+#define MARVELL_CHANNEL_NOHT80			MBIT(3)
+#define MARVELL_CHANNEL_NOHT40			MBIT(2)
+#define MARVELL_CHANNEL_DFS				MBIT(1)
+#define MARVELL_CHANNEL_PASSIVE			MBIT(0)
+
+/** CFP dynamic (non-const) elements */
+typedef struct _cfp_dyn_t {
+	/** extra flags to specify channel usability
+	 *  bit 9 : if set, channel is non-OFDM
+	 *  bit 8 : if set, channel is non-CCK
+	 *  bit 7 : if set, channel is disabled
+	 *  bit  5/6 resevered for FW
+	 *  bit 4 : if set, 160MHz on channel is disabled
+	 *  bit 3 : if set, 80MHz on channel is disabled
+	 *  bit 2 : if set, 40MHz on channel is disabled
+	 *  bit 1 : if set, channel is DFS channel
+	 *  bit 0 : if set, channel is passive
+	 */
+	t_u16 flags;
+    /** TRUE: Channel is blacklisted (do not use) */
+	t_bool blacklist;
+} cfp_dyn_t;
+
+/** Chan-Freq-TxPower mapping table*/
+typedef struct _chan_freq_power_t {
+    /** Channel Number */
+	t_u16 channel;
+    /** Frequency of this Channel */
+	t_u32 freq;
+    /** Max allowed Tx power level */
+	t_u16 max_tx_power;
+    /** TRUE:radar detect required for BAND A or passive scan for BAND B/G;
+      * FALSE:radar detect not required for BAND A or active scan for BAND B/G*/
+	t_bool passive_scan_or_radar_detect;
+    /** Elements associated to cfp that change at run-time */
+	cfp_dyn_t dynamic;
+} chan_freq_power_t;
+
+/** mlan_event data structure */
+typedef struct _mlan_event {
+    /** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+    /** Event ID */
+	mlan_event_id event_id;
+    /** Event length */
+	t_u32 event_len;
+    /** Event buffer */
+	t_u8 event_buf[0];
+} 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;
+
+/** 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;
+    /** Offset to data */
+	t_u32 data_offset;
+    /** Data length */
+	t_u32 data_len;
+    /** Buffer type: data, cmd, event etc. */
+	mlan_buf_type buf_type;
+
+    /** Fields below are valid for data packet only */
+    /** QoS priority */
+	t_u32 priority;
+    /** Time stamp when packet is received (seconds) */
+	t_u32 in_ts_sec;
+    /** Time stamp when packet is received (micro seconds) */
+	t_u32 in_ts_usec;
+    /** Time stamp when packet is processed (seconds) */
+	t_u32 out_ts_sec;
+    /** Time stamp when packet is processed (micro seconds) */
+	t_u32 out_ts_usec;
+    /** tx_seq_num */
+	t_u32 tx_seq_num;
+
+    /** Fields below are valid for MLAN module only */
+    /** Pointer to parent mlan_buffer */
+	struct _mlan_buffer *pparent;
+    /** Use count for this buffer */
+	t_u32 use_count;
+} mlan_buffer, *pmlan_buffer;
+
+/** mlan_fw_info data structure */
+typedef struct _mlan_hw_info {
+    /** Firmware capabilities */
+	t_u32 fw_cap;
+} mlan_hw_info, *pmlan_hw_info;
+
+/** mlan_bss_attr data structure */
+typedef struct _mlan_bss_attr {
+    /** BSS type */
+	t_u32 bss_type;
+    /** Data frame type: Ethernet II, 802.11, etc. */
+	t_u32 frame_type;
+    /** The BSS is active (non-0) or not (0). */
+	t_u32 active;
+    /** BSS Priority */
+	t_u32 bss_priority;
+    /** BSS number */
+	t_u32 bss_num;
+    /** The BSS is virtual */
+	t_u32 bss_virtual;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+/** bss tbl data structure */
+typedef struct _mlan_bss_tbl {
+    /** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+} mlan_bss_tbl, *pmlan_bss_tbl;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** Type enumeration for the command result */
+typedef MLAN_PACK_START enum _mlan_cmd_result_e {
+	MLAN_CMD_RESULT_SUCCESS = 0,
+	MLAN_CMD_RESULT_FAILURE = 1,
+	MLAN_CMD_RESULT_TIMEOUT = 2,
+	MLAN_CMD_RESULT_INVALID_DATA = 3
+} MLAN_PACK_END mlan_cmd_result_e;
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} MLAN_PACK_END mlan_wmm_ac_e;
+
+/** Type enumeration for the action field in the Queue Config command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e {
+	MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_config_action_e;
+
+/** Type enumeration for the action field in the queue stats command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e {
+	MLAN_WMM_STATS_ACTION_START = 0,
+	MLAN_WMM_STATS_ACTION_STOP = 1,
+	MLAN_WMM_STATS_ACTION_GET_CLR = 2,
+	MLAN_WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_stats_action_e;
+
+/**
+ *  @brief IOCTL structure for a Traffic stream status.
+ *
+ */
+typedef MLAN_PACK_START struct {
+    /** TSID: Range: 0->7 */
+	t_u8 tid;
+    /** TSID specified is valid */
+	t_u8 valid;
+    /** AC TSID is active on */
+	t_u8 access_category;
+    /** UP specified for the TSID */
+	t_u8 user_priority;
+    /** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 psb;
+    /** Upstream(0), Downlink(1), Bidirectional(3) */
+	t_u8 flow_dir;
+    /** Medium time granted for the TSID */
+	t_u16 medium_time;
+} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t,
+/** Type definition of mlan_ds_wmm_ts_status for MLAN_OID_WMM_CFG_TS_STATUS */
+mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status;
+
+/** Max Ie length */
+#define MAX_IE_SIZE             256
+
+/** custom IE */
+typedef MLAN_PACK_START struct _custom_ie {
+    /** IE Index */
+	t_u16 ie_index;
+    /** Mgmt Subtype Mask */
+	t_u16 mgmt_subtype_mask;
+    /** IE Length */
+	t_u16 ie_length;
+    /** IE buffer */
+	t_u8 ie_buffer[MAX_IE_SIZE];
+} MLAN_PACK_END custom_ie;
+
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW         4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX               26
+
+/** custom IE info */
+typedef MLAN_PACK_START struct _custom_ie_info {
+    /** size of buffer */
+	t_u16 buf_size;
+    /** no of buffers of buf_size */
+	t_u16 buf_count;
+} MLAN_PACK_END custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** No of tuples */
+	t_u16 count;
+    /** custom IE info tuples */
+	custom_ie_info info[MAX_MGMT_IE_INDEX];
+} MLAN_PACK_END tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef MLAN_PACK_START struct _tlvbuf_custom_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** IE data */
+	custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW];
+    /** Max mgmt IE TLV */
+	tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+/** 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[0];
+} 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[0];
+		} 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[0];
+		} 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[0];
+		} 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;
+
+/** 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) (IN t_void *pmoal_handle,
+					 IN t_u32 offset,
+					 IN t_u32 len, OUT t_u8 *pbuf);
+    /** moal_get_hw_spec_complete */
+	mlan_status (*moal_get_hw_spec_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status,
+						  IN mlan_hw_info * phw,
+						  IN pmlan_bss_tbl ptbl);
+    /** moal_init_fw_complete */
+	mlan_status (*moal_init_fw_complete) (IN t_void *pmoal_handle,
+					      IN mlan_status status);
+    /** moal_shutdown_fw_complete */
+	mlan_status (*moal_shutdown_fw_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status);
+    /** moal_send_packet_complete */
+	mlan_status (*moal_send_packet_complete) (IN t_void *pmoal_handle,
+						  IN pmlan_buffer pmbuf,
+						  IN mlan_status status);
+    /** moal_recv_complete */
+	mlan_status (*moal_recv_complete) (IN t_void *pmoal_handle,
+					   IN pmlan_buffer pmbuf,
+					   IN t_u32 port,
+					   IN mlan_status status);
+    /** moal_recv_packet */
+	mlan_status (*moal_recv_packet) (IN t_void *pmoal_handle,
+					 IN pmlan_buffer pmbuf);
+    /** moal_recv_event */
+	mlan_status (*moal_recv_event) (IN t_void *pmoal_handle,
+					IN pmlan_event pmevent);
+    /** moal_ioctl_complete */
+	mlan_status (*moal_ioctl_complete) (IN t_void *pmoal_handle,
+					    IN pmlan_ioctl_req pioctl_req,
+					    IN mlan_status status);
+
+    /** moal_alloc_mlan_buffer */
+	mlan_status (*moal_alloc_mlan_buffer) (IN t_void *pmoal_handle,
+					       IN t_u32 size,
+					       OUT pmlan_buffer *pmbuf);
+    /** moal_free_mlan_buffer */
+	mlan_status (*moal_free_mlan_buffer) (IN t_void *pmoal_handle,
+					      IN pmlan_buffer pmbuf);
+
+    /** moal_write_reg */
+	mlan_status (*moal_write_reg) (IN t_void *pmoal_handle,
+				       IN t_u32 reg, IN t_u32 data);
+    /** moal_read_reg */
+	mlan_status (*moal_read_reg) (IN t_void *pmoal_handle,
+				      IN t_u32 reg, OUT t_u32 *data);
+    /** moal_write_data_sync */
+	mlan_status (*moal_write_data_sync) (IN t_void *pmoal_handle,
+					     IN pmlan_buffer pmbuf,
+					     IN t_u32 port, IN t_u32 timeout);
+    /** moal_read_data_sync */
+	mlan_status (*moal_read_data_sync) (IN t_void *pmoal_handle,
+					    IN OUT pmlan_buffer pmbuf,
+					    IN t_u32 port, IN t_u32 timeout);
+    /** moal_malloc */
+	mlan_status (*moal_malloc) (IN t_void *pmoal_handle,
+				    IN t_u32 size,
+				    IN t_u32 flag, OUT t_u8 **ppbuf);
+    /** moal_mfree */
+	mlan_status (*moal_mfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_vmalloc */
+	mlan_status (*moal_vmalloc) (IN t_void *pmoal_handle,
+				     IN t_u32 size, OUT t_u8 **ppbuf);
+    /** moal_vfree */
+	mlan_status (*moal_vfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_memset */
+	t_void *(*moal_memset) (IN t_void *pmoal_handle,
+				IN t_void *pmem, IN t_u8 byte, IN t_u32 num);
+    /** moal_memcpy */
+	t_void *(*moal_memcpy) (IN t_void *pmoal_handle,
+				IN t_void *pdest,
+				IN const t_void *psrc, IN t_u32 num);
+    /** moal_memmove */
+	t_void *(*moal_memmove) (IN t_void *pmoal_handle,
+				 IN t_void *pdest,
+				 IN const t_void *psrc, IN t_u32 num);
+    /** moal_memcmp */
+	t_s32 (*moal_memcmp) (IN t_void *pmoal_handle,
+			      IN const t_void *pmem1,
+			      IN const t_void *pmem2, IN t_u32 num);
+    /** moal_udelay */
+	t_void (*moal_udelay) (IN t_void *pmoal_handle, IN t_u32 udelay);
+    /** moal_get_boot_ktime */
+	mlan_status (*moal_get_boot_ktime) (IN t_void *pmoal_handle,
+					    OUT t_u64 *pnsec);
+    /** moal_get_system_time */
+	mlan_status (*moal_get_system_time) (IN t_void *pmoal_handle,
+					     OUT t_u32 *psec, OUT t_u32 *pusec);
+    /** moal_usleep */
+	mlan_status (*moal_usleep) (IN t_void *pmoal_handle,
+				    IN t_u64 min, IN t_u64 max);
+
+    /** moal_init_timer*/
+	mlan_status (*moal_init_timer) (IN t_void *pmoal_handle,
+					OUT t_void **pptimer,
+					IN t_void (*callback) (t_void
+							       *pcontext),
+					IN t_void *pcontext);
+    /** moal_free_timer */
+	mlan_status (*moal_free_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_start_timer*/
+	mlan_status (*moal_start_timer) (IN t_void *pmoal_handle,
+					 IN t_void *ptimer,
+					 IN t_u8 periodic, IN t_u32 msec);
+    /** moal_stop_timer*/
+	mlan_status (*moal_stop_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_init_lock */
+	mlan_status (*moal_init_lock) (IN t_void *pmoal_handle,
+				       OUT t_void **pplock);
+    /** moal_free_lock */
+	mlan_status (*moal_free_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_lock */
+	mlan_status (*moal_spin_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_unlock */
+	mlan_status (*moal_spin_unlock) (IN t_void *pmoal_handle,
+					 IN t_void *plock);
+    /** moal_print */
+	t_void (*moal_print) (IN t_void *pmoal_handle,
+			      IN t_u32 level, IN char *pformat, IN ...
+		);
+    /** moal_print_netintf */
+	t_void (*moal_print_netintf) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index, IN t_u32 level);
+    /** moal_assert */
+	t_void (*moal_assert) (IN t_void *pmoal_handle, IN t_u32 cond);
+    /** moal_hist_data_add */
+	t_void (*moal_hist_data_add) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index,
+				      IN t_u8 rx_rate,
+				      IN t_s8 snr,
+				      IN t_s8 nflr, IN t_u8 antenna);
+	t_void (*moal_updata_peer_signal) (IN t_void *pmoal_handle,
+					   IN t_u32 bss_index,
+					   IN t_u8 *peer_addr,
+					   IN t_s8 snr, IN t_s8 nflr);
+} 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
+
+/** 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
+
+/** 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(6)
+/** Control bit for DFS support */
+#define FEATURE_CTRL_DFS_SUPPORT    MBIT(7)
+
+/** Default feature control */
+#define FEATURE_CTRL_DEFAULT        0xffffffff
+
+/** 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
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#ifdef DEBUG_LEVEL1
+    /** Driver debug bit masks */
+	t_u32 drvdbg;
+#endif
+    /** allocate fixed buffer size for scan beacon buffer*/
+	t_u32 fixed_beacon_buffer;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** SDIO MPA Rx */
+	t_u32 mpa_rx_cfg;
+#endif
+	/** SDIO Single port rx aggr */
+	t_u8 sdio_rx_aggr_enable;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/* 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
+    /** FW download CRC check flag */
+	t_u32 fw_crc_check;
+    /** Feature control bitmask */
+	t_u32 feature_control;
+    /** enable/disable rx work */
+	t_u8 rx_work;
+    /** dev cap mask */
+	t_u32 dev_cap_mask;
+    /** dtim interval */
+	t_u16 multi_dtim;
+    /** IEEE ps inactivity timeout value */
+	t_u16 inact_tmo;
+	/** card type */
+	t_u16 card_type;
+    /** Host sleep wakeup interval */
+	t_u32 hs_wake_interval;
+    /** GPIO to indicate wakeup source */
+	t_u8 indication_gpio;
+    /** channel time and mode for DRCS*/
+	t_u32 drcs_chantime_mode;
+	t_bool fw_region;
+} mlan_device, *pmlan_device;
+
+/** MLAN API function prototype */
+#define MLAN_API
+
+/** oops dump */
+MLAN_API void mlan_dump_adapter(IN t_void *pmlan_adapter);
+
+/** Registration */
+MLAN_API mlan_status mlan_register(IN pmlan_device pmdevice,
+				   OUT t_void **ppmlan_adapter);
+
+/** Un-registration */
+MLAN_API mlan_status mlan_unregister(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Downloading */
+MLAN_API mlan_status mlan_dnld_fw(IN t_void *pmlan_adapter,
+				  IN pmlan_fw_image pmfw);
+
+/** Custom data pass API */
+MLAN_API mlan_status mlan_set_init_param(IN t_void *pmlan_adapter,
+					 IN pmlan_init_param pparam);
+
+/** Firmware Initialization */
+MLAN_API mlan_status mlan_init_fw(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Shutdown */
+MLAN_API mlan_status mlan_shutdown_fw(IN t_void *pmlan_adapter
+	);
+
+/** Main Process */
+MLAN_API mlan_status mlan_main_process(IN t_void *pmlan_adapter
+	);
+
+/** Rx process */
+mlan_status mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts);
+
+/** Packet Transmission */
+MLAN_API mlan_status mlan_send_packet(IN t_void *pmlan_adapter,
+				      IN pmlan_buffer pmbuf);
+
+/** Packet Reception complete callback */
+MLAN_API mlan_status mlan_recv_packet_complete(IN t_void *pmlan_adapter,
+					       IN pmlan_buffer pmbuf,
+					       IN mlan_status status);
+
+/** interrupt handler */
+MLAN_API mlan_status mlan_interrupt(IN t_void *pmlan_adapter);
+
+#if defined(SYSKT)
+/** GPIO IRQ callback function */
+MLAN_API t_void mlan_hs_callback(IN t_void *pctx);
+#endif /* SYSKT_MULTI || SYSKT */
+
+MLAN_API t_void mlan_pm_wakeup_card(IN t_void *pmlan_adapter);
+
+MLAN_API t_u8 mlan_is_main_process_running(IN t_void *adapter);
+
+/** mlan ioctl */
+MLAN_API mlan_status mlan_ioctl(IN t_void *pmlan_adapter,
+				IN pmlan_ioctl_req pioctl_req);
+/** mlan select wmm queue */
+MLAN_API t_u8 mlan_select_wmm_queue(IN t_void *pmlan_adapter,
+				    IN t_u8 bss_num, IN t_u8 tid);
+#endif /* !_MLAN_DECL_H_ */
diff --git a/wlan_sd8987/mlan/mlan_fw.h b/wlan_sd8987/mlan/mlan_fw.h
new file mode 100644
index 0000000..593df63
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_fw.h
@@ -0,0 +1,6398 @@
+/** @file mlan_fw.h
+ *
+ *  @brief This file contains firmware specific defines.
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    10/27/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_FW_H_
+#define _MLAN_FW_H_
+
+/** Interface header length */
+#define INTF_HEADER_LEN     4
+
+#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_ID_GCMP = 5,
+    /** Key type : GCMP */
+	KEY_TYPE_ID_GCMP_256 = 6,
+    /** Key type : GCMP_256 */
+	KEY_TYPE_ID_CCMP_256 = 7,
+	/** Key type : CCMP_256 */
+	
+} KEY_TYPE_ID;
+
+/** Key Info flag for multicast key */
+#define KEY_INFO_MCAST_KEY      0x01
+/** Key Info flag for unicast key */
+#define KEY_INFO_UCAST_KEY      0x02
+
+/** KEY_INFO_WEP*/
+typedef enum _KEY_INFO_WEP {
+	KEY_INFO_WEP_MCAST = 0x01,
+	KEY_INFO_WEP_UNICAST = 0x02,
+	KEY_INFO_WEP_ENABLED = 0x04
+} KEY_INFO_WEP;
+
+/** KEY_INFO_TKIP */
+typedef enum _KEY_INFO_TKIP {
+	KEY_INFO_TKIP_MCAST = 0x01,
+	KEY_INFO_TKIP_UNICAST = 0x02,
+	KEY_INFO_TKIP_ENABLED = 0x04
+} KEY_INFO_TKIP;
+
+/** KEY_INFO_AES*/
+typedef enum _KEY_INFO_AES {
+	KEY_INFO_AES_MCAST = 0x01,
+	KEY_INFO_AES_UNICAST = 0x02,
+	KEY_INFO_AES_ENABLED = 0x04,
+	KEY_INFO_AES_MCAST_IGTK = 0x400,
+} KEY_INFO_AES;
+
+/** WPA AES key length */
+#define WPA_AES_KEY_LEN                 16
+/** WPA TKIP key length */
+#define WPA_TKIP_KEY_LEN                32
+/** WPA AES IGTK key length */
+#define CMAC_AES_KEY_LEN                16
+/** IGTK key length */
+#define WPA_IGTK_KEY_LEN                16
+
+/** WAPI key length */
+#define WAPI_KEY_LEN            50
+/** KEY_INFO_WAPI*/
+typedef enum _KEY_INFO_WAPI {
+	KEY_INFO_WAPI_MCAST = 0x01,
+	KEY_INFO_WAPI_UNICAST = 0x02,
+	KEY_INFO_WAPI_ENABLED = 0x04
+} KEY_INFO_WAPI;
+
+/** Maximum ethernet frame length sans FCS */
+#define MV_ETH_FRAME_LEN   1514
+
+/** 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)
+
+/* Macros in interface module */
+/** Firmware ready */
+#define FIRMWARE_READY          0xfedc
+
+/** Number of firmware blocks to transfer */
+#define FIRMWARE_TRANSFER_NBLOCK	2
+
+/** 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
+
+/** TLV  type ID definition */
+#define PROPRIETARY_TLV_BASE_ID                 0x0100
+
+/** 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
+/**TLV type : Host MLME Flag*/
+#define TLV_TYPE_HOST_MLME                      (PROPRIETARY_TLV_BASE_ID + 307)
+
+/** TLV type : Vendor Specific IE */
+#define TLV_TYPE_VENDOR_SPECIFIC_IE             0x00dd
+
+/** TLV type : Key material */
+#define TLV_TYPE_KEY_MATERIAL       (PROPRIETARY_TLV_BASE_ID + 0x00)	/* 0x0100 */
+/** TLV type : Channel list */
+#define TLV_TYPE_CHANLIST           (PROPRIETARY_TLV_BASE_ID + 0x01)	/* 0x0101 */
+/** TLV type : Number of probes */
+#define TLV_TYPE_NUMPROBES          (PROPRIETARY_TLV_BASE_ID + 0x02)	/* 0x0102 */
+/** TLV type : Beacon RSSI low */
+#define TLV_TYPE_RSSI_LOW           (PROPRIETARY_TLV_BASE_ID + 0x04)	/* 0x0104 */
+/** TLV type : Beacon SNR low */
+#define TLV_TYPE_SNR_LOW            (PROPRIETARY_TLV_BASE_ID + 0x05)	/* 0x0105 */
+/** TLV type : Fail count */
+#define TLV_TYPE_FAILCOUNT          (PROPRIETARY_TLV_BASE_ID + 0x06)	/* 0x0106 */
+/** TLV type : BCN miss */
+#define TLV_TYPE_BCNMISS            (PROPRIETARY_TLV_BASE_ID + 0x07)	/* 0x0107 */
+/** TLV type : LED behavior */
+#define TLV_TYPE_LEDBEHAVIOR        (PROPRIETARY_TLV_BASE_ID + 0x09)	/* 0x0109 */
+/** TLV type : Passthrough */
+#define TLV_TYPE_PASSTHROUGH        (PROPRIETARY_TLV_BASE_ID + 0x0a)	/* 0x010a */
+/** TLV type : Power TBL 2.4 Ghz */
+#define TLV_TYPE_POWER_TBL_2_4GHZ   (PROPRIETARY_TLV_BASE_ID + 0x0c)	/* 0x010c */
+/** TLV type : Power TBL 5 GHz */
+#define TLV_TYPE_POWER_TBL_5GHZ     (PROPRIETARY_TLV_BASE_ID + 0x0d)	/* 0x010d */
+/** TLV type : WMM queue status */
+#define TLV_TYPE_WMMQSTATUS         (PROPRIETARY_TLV_BASE_ID + 0x10)	/* 0x0110 */
+/** TLV type : Wildcard SSID */
+#define TLV_TYPE_WILDCARDSSID       (PROPRIETARY_TLV_BASE_ID + 0x12)	/* 0x0112 */
+/** TLV type : TSF timestamp */
+#define TLV_TYPE_TSFTIMESTAMP       (PROPRIETARY_TLV_BASE_ID + 0x13)	/* 0x0113 */
+/** TLV type : 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 : Passphrase */
+#define TLV_TYPE_PASSPHRASE         (PROPRIETARY_TLV_BASE_ID + 0x3c)	/* 0x013c */
+
+/** 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: robustcoex mode */
+#define TLV_TYPE_ROBUSTCOEX           (PROPRIETARY_TLV_BASE_ID + 0x11B)	/* 0x021B */
+
+/** 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 : 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)
+
+/** 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
+/** Test if adhoc 11n is enabled */
+#define IS_11N_ADHOC_ENABLED(priv) ((priv->bss_mode == MLAN_BSS_MODE_IBSS) && pmadapter->adhoc_11n_enabled)
+#endif
+
+/** Test if 11n is enabled by checking the HTCap IE */
+#define IS_11N_ENABLED(priv) ((priv->config_bands & BAND_GN || priv->config_bands & BAND_AN) \
+	 && priv->curr_bss_params.bss_descriptor.pht_cap && !priv->curr_bss_params.bss_descriptor.disable_11n)
+/** Find out if we are the initiator or not */
+#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) & \
+			MBIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS)
+
+/** 4K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_4K        4096
+/** 8K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_8K        8192
+/** 12K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_12K        12288
+/** Max Rx AMPDU Size */
+#define MAX_RX_AMPDU_SIZE_64K   0x03
+/** Non green field station */
+#define NON_GREENFIELD_STAS     0x04
+
+/** Greenfield support */
+#define HWSPEC_GREENFIELD_SUPP   MBIT(29)
+/** RX STBC support */
+#define HWSPEC_RXSTBC_SUPP   MBIT(26)
+/** ShortGI @ 40Mhz support */
+#define HWSPEC_SHORTGI40_SUPP    MBIT(24)
+/** ShortGI @ 20Mhz support */
+#define HWSPEC_SHORTGI20_SUPP    MBIT(23)
+/** RX LDPC support */
+#define HWSPEC_LDPC_SUPP         MBIT(22)
+/** Channel width 40Mhz support */
+#define HWSPEC_CHANBW40_SUPP     MBIT(17)
+/** 40Mhz intolarent enable */
+#define CAPINFO_40MHZ_INTOLARENT MBIT(8)
+
+/** Default 11n capability mask for 2.4GHz */
+#define DEFAULT_11N_CAP_MASK_BG (HWSPEC_SHORTGI20_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+/** Default 11n capability mask for 5GHz */
+#define DEFAULT_11N_CAP_MASK_A  (HWSPEC_CHANBW40_SUPP | HWSPEC_SHORTGI20_SUPP | \
+		HWSPEC_SHORTGI40_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+
+/** Default 11n TX BF capability **/
+#define DEFAULT_11N_TX_BF_CAP   0x19E74608
+
+/** Bits to ignore in hw_dev_cap as these bits are set in get_hw_spec */
+#define IGN_HW_DEV_CAP      (CAPINFO_40MHZ_INTOLARENT)
+
+/** HW_SPEC FwCapInfo : 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 : Delayed ACK */
+#define GET_DELAYEDBACK(Dot11nDevCap) (((Dot11nDevCap >> 20) & 0x03))
+/** HW_SPEC Dot11nDevCap : Immediate ACK */
+#define GET_IMMEDIATEBACK(Dot11nDevCap) (((Dot11nDevCap >> 18) & 0x03))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 40Mhz  support */
+#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 20Mhz  support */
+#define ISSUPP_CHANWIDTH20(Dot11nDevCap) (Dot11nDevCap & MBIT(16))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 10Mhz  support */
+#define ISSUPP_CHANWIDTH10(Dot11nDevCap) (Dot11nDevCap & MBIT(15))
+/** Dot11nUsrCap : 40Mhz intolarance enabled */
+#define ISENABLED_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap & MBIT(8))
+/** Dot11nUsrCap : Reset 40Mhz intolarance enabled */
+#define RESET_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(8))
+/** HW_SPEC Dot11nDevCap : Rx AntennaD support */
+#define ISSUPP_RXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(7))
+/** HW_SPEC Dot11nDevCap : Rx AntennaC support */
+#define ISSUPP_RXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(6))
+/** HW_SPEC Dot11nDevCap : Rx AntennaB support */
+#define ISSUPP_RXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(5))
+/** HW_SPEC Dot11nDevCap : Rx AntennaA support */
+#define ISSUPP_RXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(4))
+/** HW_SPEC Dot11nDevCap : Tx AntennaD support */
+#define ISSUPP_TXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(3))
+/** HW_SPEC Dot11nDevCap : Tx AntennaC support */
+#define ISSUPP_TXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(2))
+/** HW_SPEC Dot11nDevCap : Tx AntennaB support */
+#define ISSUPP_TXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(1))
+/** HW_SPEC Dot11nDevCap : Tx AntennaA support */
+#define ISSUPP_TXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(0))
+
+/** HW_SPEC Dot11nDevCap : Set support of channel bw @ 40Mhz */
+#define SETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap |= MBIT(17))
+/** HW_SPEC Dot11nDevCap : Reset support of channel bw @ 40Mhz */
+#define RESETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(17))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_TXMCSSUPP(DevMCSSupported) (DevMCSSupported >> 4)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
+
+/** GET HTCapInfo : Supported Channel BW */
+#define GETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo & MBIT(1))
+/** GET HTCapInfo : Support for Greenfield */
+#define GETHT_GREENFIELD(HTCapInfo) (HTCapInfo & MBIT(4))
+/** GET HTCapInfo : Support for Short GI @ 20Mhz */
+#define GETHT_SHORTGI20(HTCapInfo) (HTCapInfo & MBIT(5))
+/** GET HTCapInfo : Support for Short GI @ 40Mhz */
+#define GETHT_SHORTGI40(HTCapInfo) (HTCapInfo & MBIT(6))
+/** GET HTCapInfo : Support for Tx STBC */
+#define GETHT_TXSTBC(HTCapInfo) (HTCapInfo & MBIT(7))
+
+/** GET HTCapInfo : Support for Rx STBC */
+#define GETHT_RXSTBC(HTCapInfo) ((HTCapInfo >> 8) & 0x03)
+/** GET HTCapInfo : Support for Delayed ACK */
+#define GETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo & MBIT(10))
+/** GET HTCapInfo : Support for Max AMSDU */
+#define GETHT_MAXAMSDU(HTCapInfo) (HTCapInfo & MBIT(11))
+
+/** SET HTCapInfo : Set support for LDPC coding capability */
+#define SETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo |= MBIT(0))
+/** SET HTCapInfo : Set support for Channel BW */
+#define SETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo |= MBIT(1))
+/** SET HTCapInfo : Set support for Greenfield */
+#define SETHT_GREENFIELD(HTCapInfo) (HTCapInfo |= MBIT(4))
+/** SET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define SETHT_SHORTGI20(HTCapInfo) (HTCapInfo |= MBIT(5))
+/** SET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define SETHT_SHORTGI40(HTCapInfo) (HTCapInfo |= MBIT(6))
+/** SET HTCapInfo : Set support for Tx STBC */
+#define SETHT_TXSTBC(HTCapInfo) (HTCapInfo |= MBIT(7))
+/** SET HTCapInfo : Set support for Rx STBC */
+#define SETHT_RXSTBC(HTCapInfo, value) (HTCapInfo |= (value << 8))
+/** SET HTCapInfo : Set support for delayed block ack */
+#define SETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo |= MBIT(10))
+/** SET HTCapInfo : Set support for Max size AMSDU */
+#define SETHT_MAXAMSDU(HTCapInfo) (HTCapInfo |= MBIT(11))
+/** SET HTCapInfo : Set support for DSSS/CCK Rates @ 40Mhz */
+#define SETHT_DSSSCCK40(HTCapInfo) (HTCapInfo |= MBIT(12))
+/** SET HTCapInfo : Enable 40Mhz Intolarence */
+#define SETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo |= MBIT(14))
+/** SET HTCapInfo : Disable Static SM power save */
+#define SETHT_STATIC_SMPS(HTCapInfo) ((HTCapInfo) |= (MBIT(2) | MBIT(3)))
+
+/** RESET HTCapInfo : Set support for LDPC coding capability */
+#define RESETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo &= ~MBIT(0))
+/** RESET HTCapInfo : Set support for Channel BW */
+#define RESETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo &= ~MBIT(1))
+/** RESET HTCapInfo : Set support for Greenfield */
+#define RESETHT_GREENFIELD(HTCapInfo) (HTCapInfo &= ~MBIT(4))
+/** RESET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define RESETHT_SHORTGI20(HTCapInfo) (HTCapInfo &= ~MBIT(5))
+/** RESET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define RESETHT_SHORTGI40(HTCapInfo) (HTCapInfo &= ~MBIT(6))
+/** RESET HTCapInfo : Set support for Tx STBC */
+#define RESETHT_TXSTBC(HTCapInfo) (HTCapInfo &= ~MBIT(7))
+/** RESET HTCapInfo : Set support for Rx STBC */
+#define RESETHT_RXSTBC(HTCapInfo) (HTCapInfo &= ~(0x03 << 8))
+/** RESET HTCapInfo : Set support for delayed block ack */
+#define RESETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo &= ~MBIT(10))
+/** RESET HTCapInfo : Set support for Max size AMSDU */
+#define RESETHT_MAXAMSDU(HTCapInfo) (HTCapInfo &= ~MBIT(11))
+/** RESET HTCapInfo : Disable 40Mhz Intolarence */
+#define RESETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo &= ~MBIT(14))
+/** RESET HTCapInfo: Enable SM power save */
+#define RESETHT_SM_POWERSAVE(HTCapInfo) ((HTCapInfo) &= ~(MBIT(2) | MBIT(3)))
+/** RESET HTExtCap : Clear RD Responder bit */
+#define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~MBIT(11))
+/** SET MCS32 */
+#define SETHT_MCS32(x) (x[4] |= 1)
+/** Set mcs set defined bit */
+#define SETHT_MCS_SET_DEFINED(x) (x[12] |= 1)
+/** Set the highest Rx data rate */
+#define SETHT_RX_HIGHEST_DT_SUPP(x, y) ((*(t_u16 *) (x + 10)) = y)
+/** AMPDU factor size */
+#define AMPDU_FACTOR_64K	0x03
+/** Set AMPDU size in A-MPDU paramter field */
+#define SETAMPDU_SIZE(x, y) do { \
+	x = x & ~0x03; \
+	x |= y & 0x03; \
+} while (0) \
+/** Set AMPDU spacing in A-MPDU paramter field */
+#define SETAMPDU_SPACING(x, y) do { \
+	x = x & ~0x1c; \
+	x |= (y & 0x07) << 2; \
+} while (0) \
+
+/** RadioType : Support for Band A */
+#define ISSUPP_BANDA(FwCapInfo) (FwCapInfo & MBIT(10))
+/** RadioType : Support for 40Mhz channel BW */
+#define ISALLOWED_CHANWIDTH40(Field2) (Field2 & MBIT(2))
+/** RadioType : Set support 40Mhz channel */
+#define SET_CHANWIDTH40(Field2) (Field2 |= MBIT(2))
+/** RadioType : Reset support 40Mhz channel */
+#define RESET_CHANWIDTH40(Field2) (Field2 &= ~(MBIT(0) | MBIT(1) | MBIT(2)))
+/** RadioType : Get secondary channel */
+#define GET_SECONDARYCHAN(Field2) (Field2 & (MBIT(0) | MBIT(1)))
+
+/** ExtCap : Support for FILS */
+#define ISSUPP_EXTCAP_FILS(ext_cap) (ext_cap.FILS)
+/** ExtCap : Set support FILS */
+#define SET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 1)
+/** ExtCap : Reset support FILS */
+#define RESET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 0)
+
+/** ExtCap : Support for TDLS */
+#define ISSUPP_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport)
+/** ExtCap : Set support TDLS */
+#define SET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 1)
+/** ExtCap : Reset support TDLS */
+#define RESET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 0)
+/** ExtCap : Support for TDLS UAPSD */
+#define ISSUPP_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport)
+/** ExtCap : Set support TDLS UAPSD */
+#define SET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 1)
+/** ExtCap : Reset support TDLS UAPSD */
+#define RESET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 0)
+/** ExtCap : Support for TDLS CHANNEL SWITCH */
+#define ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching)
+/** ExtCap : Set support TDLS CHANNEL SWITCH */
+#define SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching = 1)
+/** ExtCap : Reset support TDLS CHANNEL SWITCH */
+#define RESET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching = 0)
+
+/** ExtCap : 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)
+
+/** LLC/SNAP header len   */
+#define LLC_SNAP_LEN    8
+
+/** bandwidth following HTCAP */
+#define BW_FOLLOW_HTCAP             0
+/** bandwidth following VHTCAP */
+#define BW_FOLLOW_VHTCAP            1
+
+/** HW_SPEC FwCapInfo */
+#define HWSPEC_11ACSGI80_SUPP       MBIT(5)
+#define HWSPEC_11ACRXSTBC_SUPP      MBIT(8)
+
+#define ISSUPP_11ACENABLED(FwCapInfo) (FwCapInfo & (MBIT(12)|MBIT(13)))
+
+#define ISSUPP_11AC2GENABLED(FwCapInfo) (FwCapInfo & MBIT(12))
+#define ISSUPP_11AC5GENABLED(FwCapInfo) (FwCapInfo & MBIT(13))
+
+/** HW_SPEC Dot11acDevCap : HTC-VHT supported */
+#define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & MBIT(22))
+/** HW_SPEC Dot11acDevCap : VHT TXOP PS support */
+#define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & MBIT(21))
+/** HW_SPEC Dot11acDevCap : MU RX beamformee support */
+#define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(20))
+/** HW_SPEC Dot11acDevCap : MU TX beamformee support */
+#define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(19))
+/** HW_SPEC Dot11acDevCap : SU Beamformee support */
+#define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(12))
+/** HW_SPEC Dot11acDevCap : SU Beamformer support */
+#define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & MBIT(11))
+/** HW_SPEC Dot11acDevCap : Rx STBC support */
+#define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(8))
+/** HW_SPEC Dot11acDevCap : Tx STBC support */
+#define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(7))
+/** HW_SPEC Dot11acDevCap : Short GI support for 160MHz BW */
+#define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & MBIT(6))
+/** HW_SPEC Dot11acDevCap : Short GI support for 80MHz BW */
+#define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & MBIT(5))
+/** HW_SPEC Dot11acDevCap : LDPC coding support */
+#define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & MBIT(4))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160/80+80 MHz support */
+#define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & MBIT(3))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160 MHz support */
+#define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & MBIT(2))
+
+/** Set VHT Cap Info: Max MPDU length */
+#define SET_VHTCAP_MAXMPDULEN(VHTCapInfo, value) (VHTCapInfo |= (value & 0x03))
+/** SET VHT CapInfo:  Supported Channel Width SET (2 bits)*/
+#define SET_VHTCAP_CHWDSET(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x3) << 2))
+/** SET VHT CapInfo:  Rx STBC (3 bits) */
+#define SET_VHTCAP_RXSTBC(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 8))
+/** SET VHT CapInfo:  Commpressed Steering Num of BFer Ant Supported (3 bits) */
+#define SET_VHTCAP_SNBFERANT(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 13))
+/** SET VHT CapInfo:  Num of Sounding Dimensions (3 bits) */
+#define SET_VHTCAP_NUMSNDDM(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 16))
+/** SET VHT CapInfo:  Max AMPDU Length Exponent (3 bits) */
+#define SET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 23))
+/** SET VHT CapInfo:  VHT Link Adaptation Capable (2 bits) */
+#define SET_VHTCAP_LINKADPCAP(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x3) << 26))
+
+/** HW_SPEC Dot11acDevCap : ReSet VHT Link Adapation Capable */
+#define RESET_11ACVHTLINKCAPA(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x03))
+/** HW_SPEC Dot11acDevCap : ReSet Maximum AMPDU Length Exponent */
+#define RESET_11ACAMPDULENEXP(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x07))
+/** HW_SPEC Dot11acDevCap : ReSet support of HTC-VHT */
+#define RESET_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(22))
+/** HW_SPEC Dot11acDevCap : ReSet support of VHT TXOP PS */
+#define RESET_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(21))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU RX beamformee */
+#define RESET_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(20))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU TX beamformee */
+#define RESET_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(19))
+/** HW_SPEC Dot11acDevCap : ReSet Number of Sounding Dimensions */
+#define RESET_11ACSOUNDINGNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 16))
+/** HW_SPEC Dot11acDevCap : ReSet Compressed Steering Number
+  * of Beamformer Antenna */
+#define RESET_11ACBFANTNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 13))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformee */
+#define RESET_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(12))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformer */
+#define RESET_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(11))
+/** HW_SPEC Dot11acDevCap : ReSet support of Rx STBC */
+#define RESET_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 8))
+/** HW_SPEC Dot11acDevCap : ReSet support of Tx STBC */
+#define RESET_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(7))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 160MHz BW */
+#define RESET_11ACSGI160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(6))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 80MHz BW */
+#define RESET_11ACSGI80(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(5))
+/** HW_SPEC Dot11acDevCap : ReSet support of LDPC coding */
+#define RESET_11ACLDPC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(4))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+  * Channel BW 20/40/80/160/80+80 MHz */
+#define RESET_11ACBW8080(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(3))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+  * Channel BW 20/40/80/160 MHz */
+#define RESET_11ACBW160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(2))
+/** HW_SPEC Dot11acDevCap : ReSet Max MPDU length */
+#define RESET_11ACMAXMPDULEN(Dot11acDevCap) (Dot11acDevCap &= ~(0x03))
+
+/** Default 11ac capability mask for 2.4GHz */
+#define DEFAULT_11AC_CAP_MASK_BG (HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** Default 11ac capability mask for 5GHz */
+#define DEFAULT_11AC_CAP_MASK_A  (HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** GET VHT CapInfo : MAX MPDU Length */
+#define GET_VHTCAP_MAXMPDULEN(VHTCapInfo) (VHTCapInfo & 0x3)
+/** GET VHT CapInfo:  Supported Channel Width SET (2 bits)*/
+#define GET_VHTCAP_CHWDSET(VHTCapInfo)    ((VHTCapInfo >> 2) & 0x3)
+/** GET VHT CapInfo:  Rx STBC (3 bits) */
+#define GET_VHTCAP_RXSTBC(VHTCapInfo)     ((VHTCapInfo >> 8) & 0x7)
+/** GET VHT CapInfo:  Compressed Steering Num of BFer Ant Supported (3 bits) */
+#define GET_VHTCAP_SNBFERANT(VHTCapInfo)  ((VHTCapInfo >> 13) & 0x7)
+/** GET VHT CapInfo:  Num of Sounding Dimensions (3 bits) */
+#define GET_VHTCAP_NUMSNDDM(VHTCapInfo)   ((VHTCapInfo >> 16) & 0x7)
+/** GET VHT CapInfo:  Max AMPDU Length Exponent (3 bits) */
+#define GET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo)   ((VHTCapInfo >> 23) & 0x7)
+/** GET VHT CapInfo:  VHT Link Adaptation Capable (2 bits) */
+#define GET_VHTCAP_LINKADPCAP(VHTCapInfo)  ((VHTCapInfo >> 26) & 0x3)
+/**SET OPERATING MODE:Channel Width:80M*/
+#define SET_OPER_MODE_80M(oper_mode)  (oper_mode = (oper_mode & ~MBIT(0))| MBIT(1))
+/**SET OPERATING MODE:Channel Width:40M*/
+#define SET_OPER_MODE_40M(oper_mode)  (oper_mode = (oper_mode & ~MBIT(1))| MBIT(0))
+/**SET OPERATING MODE:Channel Width:20M*/
+#define SET_OPER_MODE_20M(oper_mode)  (oper_mode &= ~(0x03))
+#define IS_OPER_MODE_20M(oper_mode) (((oper_mode) & (MBIT(0) | MBIT(1))) == 0)
+/**SET OPERATING MODE:Rx NSS:2*/
+#define SET_OPER_MODE_2NSS(oper_mode)  (oper_mode = (oper_mode &~(MBIT(5)|MBIT(6)))| MBIT(4))
+/**SET OPERATING MODE:Rx NSS:1*/
+#define SET_OPER_MODE_1NSS(oper_mode)  (oper_mode &= ~(MBIT(4)|MBIT(5)|MBIT(6)))
+
+#define GET_VHTMCS(MCSMapSet)         (MCSMapSet & 0xFFFF)
+#define GET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2*(nss-1)))&0x3)
+#define RET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2*(nss-1)))&0x3)
+#define SET_VHTNSSMCS(MCSMapSet, nss, value) \
+            (MCSMapSet |= (value & 0x3) << (2 * (nss - 1)))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_DEVTXMCSMAP(DevMCSMap)      (DevMCSMap >> 16)
+#define GET_DEVNSSTXMCS(DevMCSMap, nss) ((DevMCSMap >> (2*(nss-1)+16))&0x3)
+#define SET_DEVNSSTXMCS(DevMCSMap, nss, value) \
+            (DevMCSMap |= (value & 0x3) << (2 * (nss - 1) + 16))
+#define RESET_DEVTXMCSMAP(DevMCSMap)    (DevMCSMap &= 0xFFFF)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_DEVRXMCSMAP(DevMCSMap)      (DevMCSMap & 0xFFFF)
+#define GET_DEVNSSRXMCS(DevMCSMap, nss) ((DevMCSMap >> (2*(nss-1)))&0x3)
+#define SET_DEVNSSRXMCS(DevMCSMap, nss, value) \
+            (DevMCSMap |= (value & 0x3) << (2 * (nss - 1)))
+#define RESET_DEVRXMCSMAP(DevMCSMap)    (DevMCSMap &= 0xFFFF0000)
+
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_DROP_PATTERN  (PROPRIETARY_TLV_BASE_ID + 0x51)	/* 0x0151 */
+/** TLV type : Rate drop pattern */
+#define TLV_TYPE_RATE_DROP_CONTROL  (PROPRIETARY_TLV_BASE_ID + 0x52)	/* 0x0152 */
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_SCOPE         (PROPRIETARY_TLV_BASE_ID + 0x53)	/* 0x0153 */
+
+/** TLV type : Power group */
+#define TLV_TYPE_POWER_GROUP        (PROPRIETARY_TLV_BASE_ID + 0x54)	/* 0x0154 */
+
+/** Modulation class for DSSS Rates */
+#define MOD_CLASS_HR_DSSS       0x03
+/** Modulation class for OFDM Rates */
+#define MOD_CLASS_OFDM          0x07
+/** Modulation class for HT Rates */
+#define MOD_CLASS_HT            0x08
+/** Modulation class for VHT Rates */
+#define MOD_CLASS_VHT           0x09
+/** HT bandwidth 20 MHz */
+#define HT_BW_20    0
+/** HT bandwidth 40 MHz */
+#define HT_BW_40    1
+/** HT bandwidth 80 MHz */
+#define HT_BW_80    2
+
+/** TLV type : 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 : 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 : 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 : 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 : 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
+
+/** Host Command ID : SDIO GPIO interrupt configuration */
+#define HostCmd_CMD_SDIO_GPIO_INT_CONFIG      0x0088
+
+#ifdef MFG_CMD_SUPPORT
+/** Host Command ID : Mfg command */
+#define HostCmd_CMD_MFG_COMMAND               0x0089
+#endif
+/** 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 : 802.11 RSSI INFO EXT*/
+#define HostCmd_CMD_RSSI_INFO_EXT             0x0237
+
+/** Host Command ID: Multi chan config */
+#define HostCmd_CMD_MULTI_CHAN_CONFIG                0x011e
+/** Host Command ID: Multi chan policy */
+#define HostCmd_CMD_MULTI_CHAN_POLICY                0x0121
+/** TLV ID for multi chan info */
+#define TLV_TYPE_MULTI_CHAN_INFO             (PROPRIETARY_TLV_BASE_ID + 0xb7)
+/** TLV ID for multi chan group info */
+#define TLV_TYPE_MULTI_CHAN_GROUP_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0xb8)
+/** TLV ID for DRCS TimeSlice */
+#define MRVL_DRCS_TIME_SLICE_TLV_ID  (PROPRIETARY_TLV_BASE_ID + 263)
+/** Host Command ID: DRCS config */
+#define HostCmd_CMD_DRCS_CONFIG                     0x024a
+
+#ifdef RX_PACKET_COALESCE
+/** TLV ID for RX pkt coalesce config */
+#define TLV_TYPE_RX_PKT_COAL_CONFIG           (PROPRIETARY_TLV_BASE_ID + 0xC9)
+#endif
+
+/** Host Command ID : Channel report request */
+#define HostCmd_CMD_CHAN_REPORT_REQUEST              0x00dd
+
+/** Host Command ID: SUPPLICANT_PMK */
+#define HostCmd_CMD_SUPPLICANT_PMK            0x00c4
+/** Host Command ID: SUPPLICANT_PROFILE */
+#define HostCmd_CMD_SUPPLICANT_PROFILE        0x00c5
+
+/** Host Command ID : Add Block Ack Request */
+#define HostCmd_CMD_11N_ADDBA_REQ             0x00ce
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_CFG                   0x00cd
+/** Host Command ID : Add Block Ack Response */
+#define HostCmd_CMD_11N_ADDBA_RSP             0x00cf
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_DELBA                 0x00d0
+/** Host Command ID: Configure Tx Buf size */
+#define HostCmd_CMD_RECONFIGURE_TX_BUFF       0x00d9
+/** Host Command ID: AMSDU Aggr Ctrl */
+#define HostCmd_CMD_AMSDU_AGGR_CTRL           0x00df
+/** Host Command ID: 11AC config */
+#define HostCmd_CMD_11AC_CFG                   0x0112
+/** Host Command ID: Configure TX Beamforming capability */
+#define HostCmd_CMD_TX_BF_CFG                 0x0104
+
+/** Host Command ID : 802.11 TX power configuration */
+#define HostCmd_CMD_TXPWR_CFG                 0x00d1
+
+/** Host Command ID : Soft Reset */
+#define  HostCmd_CMD_SOFT_RESET               0x00d5
+
+/** Host Command ID : 802.11 b/g/n rate configration */
+#define HostCmd_CMD_TX_RATE_CFG               0x00d6
+
+/** Host Command ID : Enhanced PS mode */
+#define HostCmd_CMD_802_11_PS_MODE_ENH        0x00e4
+
+/** Host command action : Host sleep configuration */
+#define HostCmd_CMD_802_11_HS_CFG_ENH         0x00e5
+
+/** Host Command ID : CAU register access */
+#define HostCmd_CMD_CAU_REG_ACCESS            0x00ed
+
+/** Host Command ID : mgmt IE list */
+#define  HostCmd_CMD_MGMT_IE_LIST             0x00f2
+
+/** Host Command ID : TDLS configuration */
+#define  HostCmd_CMD_TDLS_CONFIG              0x0100
+/** Host Command ID : TDLS operation */
+#define HostCmd_CMD_TDLS_OPERATION          0x0122
+
+/** 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)
+
+/* 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)
+
+#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
+
+/** Host Command ID : Set BSS_MODE */
+#define HostCmd_CMD_SET_BSS_MODE               0x00f7
+
+#ifdef UAP_SUPPORT
+/**  Host Command id: SYS_INFO */
+#define HOST_CMD_APCMD_SYS_INFO                0x00ae
+/** Host Command id: sys_reset */
+#define HOST_CMD_APCMD_SYS_RESET               0x00af
+/** Host Command id: SYS_CONFIGURE  */
+#define HOST_CMD_APCMD_SYS_CONFIGURE           0x00b0
+/** Host Command id: BSS_START */
+#define HOST_CMD_APCMD_BSS_START               0x00b1
+/** Host Command id: BSS_STOP  */
+#define HOST_CMD_APCMD_BSS_STOP                0x00b2
+/** Host Command id: sta_list */
+#define HOST_CMD_APCMD_STA_LIST                0x00b3
+/** Host Command id: STA_DEAUTH */
+#define HOST_CMD_APCMD_STA_DEAUTH              0x00b5
+
+/** Host Command id: REPORT_MIC */
+#define HOST_CMD_APCMD_REPORT_MIC              0x00ee
+/** Host Command id: UAP_OPER_CTRL */
+#define HOST_CMD_APCMD_OPER_CTRL              0x0233
+#endif /* UAP_SUPPORT */
+
+/** Host Command id: PMIC CONFIGURE*/
+#define HOST_CMD_PMIC_CONFIGURE                0x23E
+
+/** Host Command ID: Tx data pause */
+#define HostCmd_CMD_CFG_TX_DATA_PAUSE           0x0103
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** Host Command ID: P2P PARAMS CONFIG */
+#define HOST_CMD_P2P_PARAMS_CONFIG              0x00ea
+/** Host Command ID: WIFI_DIRECT_MODE_CONFIG */
+#define HOST_CMD_WIFI_DIRECT_MODE_CONFIG    0x00eb
+#endif
+
+/** Host Command ID: Remain On Channel */
+#define HostCmd_CMD_802_11_REMAIN_ON_CHANNEL     0x010d
+
+#define HostCmd_CMD_COALESCE_CFG                 0x010a
+
+/** Host Command ID : 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: DFS repeater mode */
+#define HostCmd_DFS_REPEATER_MODE	0x012b
+
+/** Host Command ID: ACS scan */
+#define HostCMD_APCMD_ACS_SCAN     0x0224
+
+/** Host Command ID : Configure ADHOC_OVER_IP parameters */
+#define HostCmd_CMD_WMM_PARAM_CONFIG                0x023a
+
+#ifdef STA_SUPPORT
+/** Host Command ID :  set/get sta configure */
+#define HostCmd_CMD_STA_CONFIGURE            0x023f
+#endif
+
+/** Host Command ID : GPIO independent reset configure */
+
+#define HostCmd_CMD_CHAN_REGION_CFG			0x0242
+/* mod_grp */
+typedef enum _mod_grp {
+	MOD_CCK,		//0
+	MOD_OFDM_PSK,		//1
+	MOD_OFDM_QAM16,		//2
+	MOD_OFDM_QAM64,		//3
+	MOD_HT_20_PSK,		//4
+	MOD_HT_20_QAM16,	//5
+	MOD_HT_20_QAM64,	//6
+	MOD_HT_40_PSK,		//7
+	MOD_HT_40_QAM16,	//8
+	MOD_HT_40_QAM64,	//9
+#ifdef STREAM_2x2
+	MOD_HT2_20_PSK,		//10
+	MOD_HT2_20_QAM16,	//11
+	MOD_HT2_20_QAM64,	//12
+	MOD_HT2_40_PSK,		//13
+	MOD_HT2_40_QAM16,	//14
+	MOD_HT2_40_QAM64,	//15
+#endif
+
+	MOD_VHT_20_QAM256,	//16
+	MOD_VHT_40_QAM256,	//17
+	MOD_VHT_80_PSK,		//18
+	MOD_VHT_80_QAM16,	//19
+	MOD_VHT_80_QAM64,	//20
+	MOD_VHT_80_QAM256,	//21
+#ifdef STREAM_2x2
+	MOD_VHT2_20_QAM256,	//22
+	MOD_VHT2_40_QAM256,	//23
+	MOD_VHT2_80_PSK,	//24
+	MOD_VHT2_80_QAM16,	//25
+	MOD_VHT2_80_QAM64,	//26
+	MOD_VHT2_80_QAM256,	//27
+#endif
+} mod_grp;
+
+typedef MLAN_PACK_START struct _power_table_attr {
+	t_u8 rows_2g;
+	t_u8 cols_2g;
+	t_u8 rows_5g;
+	t_u8 cols_5g;
+} MLAN_PACK_END power_table_attr_t;
+
+#define FW_CFP_TABLE_MAX_ROWS_BG		14
+#define FW_CFP_TABLE_MAX_COLS_BG		17
+
+#define FW_CFP_TABLE_MAX_ROWS_A		39
+#define FW_CFP_TABLE_MAX_COLS_A		29
+
+#define HostCmd_CMD_DYN_BW                  0x0252
+
+#define HostCmd_CMD_BOOT_SLEEP              0x0258
+
+#define HostCmd_CMD_ACS     0x025a
+
+/** 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 : 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        30
+
+/** 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
+
+/** 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
+
+/** 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
+
+/** 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: Multi Chan Info*/
+#define EVENT_MULTI_CHAN_INFO               0x0000006a
+
+/** Event ID: Tx status */
+#define EVENT_TX_STATUS_REPORT               0x00000074
+
+#define EVENT_BT_COEX_WLAN_PARA_CHANGE	 0x00000076
+
+#define EVENT_EXCEED_MAX_P2P_CONN     0x00000089
+
+#define EVENT_FW_HANG_REPORT     0x0000008F
+
+#define EVENT_FW_DUMP_INFO      0x00000073
+/** Event ID mask */
+#define EVENT_ID_MASK                   0xffff
+
+/** BSS number mask */
+#define BSS_NUM_MASK                    0xf
+
+/** Get BSS number from event cause (bit 23:16) */
+#define EVENT_GET_BSS_NUM(event_cause)          \
+	(((event_cause) >> 16) & BSS_NUM_MASK)
+
+/** Get BSS type from event cause (bit 31:24) */
+#define EVENT_GET_BSS_TYPE(event_cause)         \
+	(((event_cause) >> 24) & 0x00ff)
+
+/** event 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             1
+/** 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;
+
+/** tdls ie data structure */
+typedef MLAN_PACK_START struct _ie_data {
+    /** IE Length */
+	t_u16 ie_length;
+    /** IE pointer */
+	t_u8 ie_ptr[0];
+} 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;
+
+#define RXPD_FLAG_PN_CHECK_SUPPORT             (1 << 2)
+
+/** 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] Reserved */
+	t_u8 rate_info;
+   /** Reserved */
+	t_u8 reserved[3];
+    /** TDLS flags, bit 0: 0=InfraLink, 1=DirectLink,
+      *  bit 1: extra info for radio tap,
+      *  bit 2: PN check support*/
+	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;
+    /** PN number high 32 bits*/
+	t_u32 hi_rx_count32;
+    /** PN number low 16 bits*/
+	t_u16 lo_rx_count16;
+    /** Reserved */
+	t_u8 reserved3[2];
+} MLAN_PACK_END RxPD, *PRxPD;
+
+/** IEEEtypes_FrameCtl_t*/
+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;
+
+/** 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[0]; */
+} 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
+/** TxPD descriptor */
+typedef MLAN_PACK_START struct _UapTxPD {
+	/** 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 UapTxPD, *PUapTxPD;
+
+/** RxPD Descriptor */
+typedef MLAN_PACK_START struct _UapRxPD {
+    /** BSS Type */
+	t_u8 bss_type;
+    /** BSS number*/
+	t_u8 bss_num;
+    /** Rx packet length */
+	t_u16 rx_pkt_length;
+    /** Rx packet offset */
+	t_u16 rx_pkt_offset;
+    /** Rx packet type */
+	t_u16 rx_pkt_type;
+    /** Sequence nunmber */
+	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] Reserved */
+	t_u8 rate_info;
+    /** Reserved */
+	t_u8 reserved1[3];
+    /** TDLS flags, bit 0: 0=InfraLink, 1=DirectLink */
+	t_u8 flags;
+    /** For SD8887 ntenna 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;
+    /** PN number high 32 bits*/
+	t_u32 hi_rx_count32;
+    /** PN number low 16 bits*/
+	t_u16 lo_rx_count16;
+    /** Reserved */
+	t_u8 reserved3[2];
+} MLAN_PACK_END UapRxPD, *PUapRxPD;
+
+/** 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[0]; */
+} 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[0]; */
+} 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 tlv */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ChannelStats_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** channel statictics */
+	ChanStatistics_t chanStat[0];
+} MLAN_PACK_END MrvlIEtypes_ChannelStats_t;
+
+/** MrvlIETypes_ActionFrame_t */
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header;
+				  /**< Header */
+
+    /** Source Address */
+	t_u8 srcAddr[MLAN_MAC_ADDR_LENGTH];
+    /** Destination Address */
+	t_u8 dstAddr[MLAN_MAC_ADDR_LENGTH];
+
+    /** IEEEtypes Action frame structure */
+	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[0];
+} MLAN_PACK_END MrvlIEtypes_RsnParamSet_t;
+
+/** Key Info flag for multicast key */
+#define KEY_INFO_MCAST_KEY      0x01
+/** Key Info flag for unicast key */
+#define KEY_INFO_UCAST_KEY      0x02
+/** Key Info flag for enable key */
+#define KEY_INFO_ENABLE_KEY     0x04
+/** Key Info flag for default key */
+#define KEY_INFO_DEFAULT_KEY    0x08
+/** Key Info flag for TX key */
+#define KEY_INFO_TX_KEY         0x10
+/** Key Info flag for RX key */
+#define KEY_INFO_RX_KEY         0x20
+#define KEY_INFO_CMAC_AES_KEY   0x400
+/** PN size for WPA/WPA2 */
+#define WPA_PN_SIZE             8
+/** PN size for PMF IGTK */
+#define IGTK_PN_SIZE            8
+/** WAPI KEY size */
+#define WAPI_KEY_SIZE           32
+/** key params fix size */
+#define KEY_PARAMS_FIXED_LEN    10
+/** key index mask */
+#define KEY_INDEX_MASK          0xf
+
+/** wep_param */
+typedef MLAN_PACK_START struct _wep_param_t {
+    /** key_len */
+	t_u16 key_len;
+    /** wep key */
+	t_u8 key[MAX_WEP_KEY_SIZE];
+} MLAN_PACK_END wep_param_t;
+
+/** tkip_param */
+typedef MLAN_PACK_START struct _tkip_param {
+    /** Rx packet num */
+	t_u8 pn[WPA_PN_SIZE];
+    /** key_len */
+	t_u16 key_len;
+    /** tkip key */
+	t_u8 key[WPA_TKIP_KEY_LEN];
+} MLAN_PACK_END tkip_param;
+
+/** aes_param */
+typedef MLAN_PACK_START struct _aes_param {
+    /** Rx packet num */
+	t_u8 pn[WPA_PN_SIZE];
+    /** key_len */
+	t_u16 key_len;
+    /** aes key */
+	t_u8 key[WPA_AES_KEY_LEN];
+} MLAN_PACK_END aes_param;
+
+/** wapi_param */
+typedef MLAN_PACK_START struct _wapi_param {
+    /** Rx packet num */
+	t_u8 pn[PN_SIZE];
+    /** key_len */
+	t_u16 key_len;
+    /** wapi key */
+	t_u8 key[WAPI_KEY_SIZE];
+} MLAN_PACK_END wapi_param;
+
+/** cmac_aes_param */
+typedef MLAN_PACK_START struct _cmac_aes_param {
+    /** IGTK pn */
+	t_u8 ipn[IGTK_PN_SIZE];
+    /** key_len */
+	t_u16 key_len;
+    /** aes key */
+	t_u8 key[CMAC_AES_KEY_LEN];
+} MLAN_PACK_END cmac_aes_param;
+
+/** gmac_param */
+typedef MLAN_PACK_START struct _gcmp_param {
+    /** GCMP pn */
+	t_u8 pn[WPA_PN_SIZE];
+    /** key_len */
+	t_u16 key_len;
+    /** aes key */
+	t_u8 key[WPA_GCMP_KEY_LEN];
+} MLAN_PACK_END gcmp_param;
+
+/** ccmp256_param */
+typedef MLAN_PACK_START struct _ccmp256_param {
+    /** ccmp256 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_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;
+
+/** 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;
+	mod_group_setting mod_group[0];
+} 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[0];
+} 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;
+
+/* 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 new power save command */
+typedef MLAN_PACK_START struct _HostCmd_DS_PS_MODE_ENH {
+    /** Action */
+	t_u16 action;
+    /** Data speciifc to action */
+	/* For IEEE power save data will be as
+	 * UINT16 mode (0x01 - firmware to automatically choose PS_POLL or NULL mode, 0x02 - PS_POLL, 0x03 - NULL mode )
+	 * UINT16 NullpacketInterval
+	 * UINT16 NumDtims
+	 * UINT16 BeaconMissInterval
+	 * UINT16 locallisteninterval
+	 * UINT16 adhocawakeperiod */
+
+	/* For auto deep sleep */
+	/* UINT16 Deep sleep inactivity timeout */
+
+	/* For PS sleep confirm
+	 * UINT16 responeCtrl - 0x00 - reponse from fw not needed, 0x01 - response from fw is needed */
+
+	union {
+    /** PS param definition */
+		ps_param opt_ps;
+    /** Auto ds param definition */
+		auto_ds_param auto_ds;
+    /** Sleep comfirm param definition */
+		sleep_confirm_param sleep_cfm;
+    /** bitmap for get PS info and Disable PS mode */
+		t_u16 ps_bitmap;
+    /** auto ps param */
+		auto_ps_param auto_ps;
+	} params;
+} MLAN_PACK_END HostCmd_DS_802_11_PS_MODE_ENH;
+
+/** FW VERSION tlv */
+#define TLV_TYPE_FW_VER_INFO        (PROPRIETARY_TLV_BASE_ID + 0xC7)	/* 0x1C7 */
+
+/** MrvlIEtypes_fw_ver_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_ver_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** API id */
+	t_u16 api_id;
+    /** major version */
+	t_u8 major_ver;
+    /** minor version */
+	t_u8 minor_ver;
+} MLAN_PACK_END MrvlIEtypes_fw_ver_info_t;
+
+/** API ID */
+enum API_VER_ID {
+	KEY_API_VER_ID = 1,
+	FW_API_VER_ID = 2,
+	UAP_FW_API_VER_ID = 3,
+	CHANRPT_API_VER_ID = 4,
+};
+
+/** FW AP V15 */
+#define HOST_API_VERSION_V15  15
+/** FW minor version 1 */
+#define FW_MINOR_VERSION_1    1
+
+/** UAP FW version 2 */
+#define UAP_FW_VERSION_2	 0x2
+
+/** HostCMD_DS_APCMD_ACS_SCAN */
+typedef MLAN_PACK_START struct _HostCMD_DS_APCMD_ACS_SCAN {
+	/** band */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 chan;
+} MLAN_PACK_END HostCMD_DS_APCMD_ACS_SCAN;
+
+/** HostCmd_DS_GET_HW_SPEC */
+typedef MLAN_PACK_START struct _HostCmd_DS_GET_HW_SPEC {
+    /** HW Interface version number */
+	t_u16 hw_if_version;
+    /** HW version number */
+	t_u16 version;
+    /** Reserved field */
+	t_u16 reserved;
+    /** Max no of Multicast address  */
+	t_u16 num_of_mcast_adr;
+    /** MAC address */
+	t_u8 permanent_addr[MLAN_MAC_ADDR_LENGTH];
+    /** Region Code */
+	t_u16 region_code;
+    /** Number of antenna used */
+	t_u16 number_of_antenna;
+    /** FW release number, example 0x1234=1.2.3.4 */
+	t_u32 fw_release_number;
+    /** Reserved field */
+	t_u32 reserved_1;
+    /** Reserved field */
+	t_u32 reserved_2;
+    /** Reserved field */
+	t_u32 reserved_3;
+    /** FW/HW Capability */
+	t_u32 fw_cap_info;
+    /** 802.11n Device Capabilities */
+	t_u32 dot_11n_dev_cap;
+    /** MIMO abstraction of MCSs supported by device */
+	t_u8 dev_mcs_support;
+	/** Valid end port at init */
+	t_u16 mp_end_port;
+	/** mgmt IE buffer count */
+	t_u16 mgmt_buf_count;
+    /** Reserved */
+	t_u32 reserved_8;
+    /** Reserved */
+	t_u32 reserved_9;
+    /** 802.11ac Device Capabilities */
+	t_u32 Dot11acDevCap;
+    /** MCSs supported by 802.11ac device */
+	t_u32 Dot11acMcsSupport;
+} MLAN_PACK_END HostCmd_DS_GET_HW_SPEC;
+
+/* HostCmd_DS_SDIO_SP_RX_AGGR_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SDIO_SP_RX_AGGR_CFG {
+    /** Action */
+	t_u8 action;
+    /** Enable */
+	t_u8 enable;
+    /** Sdio block size */
+	t_u16 sdio_block_size;
+} MLAN_PACK_END HostCmd_DS_SDIO_SP_RX_AGGR_CFG;
+
+/**  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[0];
+} 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;
+
+/** 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;
+
+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;
+} MLAN_PACK_END HostCmd_DS_802_11_GET_LOG;
+
+/**_HostCmd_TX_RATE_QUERY */
+typedef MLAN_PACK_START struct _HostCmd_TX_RATE_QUERY {
+    /** Tx rate */
+	t_u8 tx_rate;
+    /** Tx Rate Info:
+     * [Bit 0-1] tx rate formate: LG = 0, HT = 1, VHT = 2
+     * [Bit 2-3] HT/VHT Bandwidth: BW20 = 0, BW40 = 1, BW80 = 2, BW160 = 3
+     * [Bit 4]   HT/VHT Guard Interval: LGI = 0, SGI = 1 */
+	t_u8 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;
+} MLAN_PACK_END HostCmd_DS_802_11_ROBUSTCOEX;
+
+/** 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
+
+/**  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];
+    /** VHT MCS rate bitmap */
+	t_u16 vht_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[0]; */
+} MLAN_PACK_END MrvlRateDropPattern_t;
+
+/** HostCmd_DS_TX_RATE_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TX_RATE_CFG {
+    /** Action */
+	t_u16 action;
+    /** Reserved */
+	t_u16 reserved_1;
+	/* MrvlRateScope_t RateScope;
+	 * MrvlRateDropPattern_t RateDrop; */
+} 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[0] */
+} 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;
+
+#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
+     */
+} MLAN_PACK_END HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG;
+#endif
+
+/** Coalesce filter field parameter */
+MLAN_PACK_START struct coalesce_filt_field_param {
+    /** Operation */
+	t_u8 operation;
+    /** Operation length */
+	t_u8 operand_len;
+    /** Offset */
+	t_u16 offset;
+    /** Operand byte stream */
+	t_u8 operand_byte_stream[4];
+} MLAN_PACK_END;
+
+/** Coalesce receive filter rule */
+MLAN_PACK_START struct coalesce_receive_filt_rule {
+    /** header */
+	MrvlIEtypesHeader_t header;
+    /** Number of fields */
+	t_u8 num_of_fields;
+    /** packet type */
+	t_u8 pkt_type;
+    /** maximum coalescing delay */
+	t_u16 max_coalescing_delay;
+	struct coalesce_filt_field_param params[0];
+} MLAN_PACK_END;
+
+/** HostCmd_DS_COALESCE_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_COALESCE_CONFIG {
+    /** Action 0-GET, 1-SET */
+	t_u16 action;
+    /** Number of rules */
+	t_u16 num_of_rules;
+	struct coalesce_receive_filt_rule rule[0];
+} 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;
+
+/*
+ * 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_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 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;
+
+/** 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 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;
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_VHTOprat_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+
+    /** Channel width */
+	t_u8 chan_width;
+    /** Channel center frequency 1 */
+	t_u8 chan_center_freq_1;
+    /** Channel center frequency 2 */
+	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;
+
+    /** Maximum tx power */
+	t_u8 max_tx_power;
+    /** Channel center frequency */
+	t_u8 chan_center_freq;
+    /** Channel width */
+	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;
+
+    /** MIMO Capability count */
+	t_u8 MU_MIMO_capa_count;
+    /** Stream under utilization */
+	t_u8 stream_underutilization;
+    /** VHT40 util */
+	t_u8 VHT40_util;
+    /** VHT80 util */
+	t_u8 VHT80_util;
+    /** VHT160 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;
+
+    /** AP quiet mode */
+	t_u8 AP_quiet_mode;
+    /** Quiet count */
+	t_u8 quiet_count;
+    /** Quiet period */
+	t_u8 quiet_period;
+    /** Quiet duration */
+	t_u16 quiet_dur;
+    /** Quiet offset */
+	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;
+
+    /** New Channel width */
+	t_u8 new_chan_width;
+    /** New Channel center frequency 1 */
+	t_u8 new_chan_center_freq_1;
+    /** New channel center frequency 2 */
+	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;
+
+/* 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_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_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;
+
+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_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;
+
+/** HostCmd_DS_ACS */
+typedef MLAN_PACK_START struct _HostCmd_DS_ACS {
+    /** Best channel */
+	t_u8 best_ch;
+    /** TLV buffer */
+    /** MrvlIEtypes_ChanListParamSet_t TLV (0x0101) in cmd */
+    /** MrvlIEtypes_ScanChanGap_t TLV (0x01c5) in cmd */
+    /** MrvlIEtypes_ChannelStats_t TLV (0x01c6) in cmd resp */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END HostCmd_DS_ACS;
+
+/** TLV type : STA Mac address */
+#define TLV_TYPE_STA_MAC_ADDRESS      (PROPRIETARY_TLV_BASE_ID + 0x20)	/* 0x0120 */
+
+/** 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 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_sta_ageout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sta_ageout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** station age out timer */
+	t_u32 sta_ageout_timer;
+} MLAN_PACK_END MrvlIEtypes_sta_ageout_t;
+
+/** MrvlIEtypes_rts_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rts_threshold_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** rts threshold */
+	t_u16 rts_threshold;
+} MLAN_PACK_END MrvlIEtypes_rts_threshold_t;
+
+/** MrvlIEtypes_frag_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_frag_threshold_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** frag threshold */
+	t_u16 frag_threshold;
+} MLAN_PACK_END MrvlIEtypes_frag_threshold_t;
+
+/** MrvlIEtypes_retry_limit_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_retry_limit_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** retry limit */
+	t_u8 retry_limit;
+} MLAN_PACK_END MrvlIEtypes_retry_limit_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_timeout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** pairwise update timeout in milliseconds */
+	t_u32 pairwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_retries_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** pairwise handshake retries */
+	t_u32 pwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_retries_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_timeout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** groupwise update timeout in milliseconds */
+	t_u32 groupwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_retries_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** groupwise handshake retries */
+	t_u32 gwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_retries_t;
+
+/** MrvlIEtypes_mgmt_ie_passthru_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mgmt_ie_passthru_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** mgmt IE mask value */
+	t_u32 mgmt_ie_mask;
+} MLAN_PACK_END MrvlIEtypes_mgmt_ie_passthru_t;
+
+/** MrvlIEtypes_mac_filter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mac_filter_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Filter mode */
+	t_u8 filter_mode;
+    /** Number of STA MACs */
+	t_u8 count;
+    /** STA MAC addresses buffer */
+	t_u8 mac_address[1];
+} MLAN_PACK_END MrvlIEtypes_mac_filter_t;
+
+/** MrvlIEtypes_auth_type_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_auth_type_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Authentication type */
+	t_u8 auth_type;
+} MLAN_PACK_END MrvlIEtypes_auth_type_t;
+
+/** MrvlIEtypes_encrypt_protocol_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_encrypt_protocol_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** encryption protocol */
+	t_u16 protocol;
+} MLAN_PACK_END MrvlIEtypes_encrypt_protocol_t;
+
+/** MrvlIEtypes_pwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_pwk_cipher_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** protocol */
+	t_u16 protocol;
+    /** pairwise cipher */
+	t_u8 pairwise_cipher;
+    /** reserved */
+	t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_pwk_cipher_t;
+
+/** MrvlIEtypes_gwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_gwk_cipher_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** group cipher */
+	t_u8 group_cipher;
+    /** reserved */
+	t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_gwk_cipher_t;
+
+/** MrvlIEtypes_akmp_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_akmp_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** key management */
+	t_u16 key_mgmt;
+    /** key management operation */
+	t_u16 key_mgmt_operation;
+} MLAN_PACK_END MrvlIEtypes_akmp_t;
+
+/** MrvlIEtypes_passphrase_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_passphrase_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** passphrase */
+	t_u8 passphrase[1];
+} MLAN_PACK_END MrvlIEtypes_passphrase_t;
+
+/** MrvlIEtypes_rsn_replay_prot_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rsn_replay_prot_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** rsn replay proection */
+	t_u8 rsn_replay_prot;
+} MLAN_PACK_END MrvlIEtypes_rsn_replay_prot_t;
+
+/** MrvlIEtypes_group_rekey_time_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_group_rekey_time_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** group key rekey time */
+	t_u32 gk_rekey_time;
+} MLAN_PACK_END MrvlIEtypes_group_rekey_time_t;
+
+/** MrvlIEtypes_wep_key_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wep_key_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** key index */
+	t_u8 key_index;
+    /** is default */
+	t_u8 is_default;
+    /** key data */
+	t_u8 key[1];
+} MLAN_PACK_END MrvlIEtypes_wep_key_t;
+
+/** MrvlIEtypes_bss_status_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_bss_status_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** BSS status, READ only */
+	t_u16 bss_status;
+} MLAN_PACK_END MrvlIEtypes_bss_status_t;
+
+/** MrvlIEtypes_preamble_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_preamble_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** preamble type, READ only */
+	t_u8 preamble_type;
+} MLAN_PACK_END MrvlIEtypes_preamble_t;
+
+/** MrvlIEtypes_wmm_parameter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wmm_parameter_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** WMM parameter */
+	WmmParameter_t wmm_para;
+} MLAN_PACK_END MrvlIEtypes_wmm_parameter_t;
+
+/** SNMP_MIB_UAP_INDEX */
+typedef enum _SNMP_MIB_UAP_INDEX {
+	tkip_mic_failures = 0x0b,
+	ccmp_decrypt_errors = 0x0c,
+	wep_undecryptable_count = 0x0d,
+	wep_icv_error_count = 0x0e,
+	decrypt_failure_count = 0xf,
+	dot11_failed_count = 0x12,
+	dot11_retry_count = 0x13,
+	dot11_multi_retry_count = 0x14,
+	dot11_frame_dup_count = 0x15,
+	dot11_rts_success_count = 0x16,
+	dot11_rts_failure_count = 0x17,
+	dot11_ack_failure_count = 0x18,
+	dot11_rx_fragment_count = 0x19,
+	dot11_mcast_rx_frame_count = 0x1a,
+	dot11_fcs_error_count = 0x1b,
+	dot11_tx_frame_count = 0x1c,
+	dot11_rsna_tkip_cm_invoked = 0x1d,
+	dot11_rsna_4way_hshk_failures = 0x1e,
+	dot11_mcast_tx_count = 0x1f,
+} SNMP_MIB_UAP_INDEX;
+
+/** MrvlIEtypes_snmp_oid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_snmp_oid_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** data */
+	t_u32 data;
+} MLAN_PACK_END MrvlIEtypes_snmp_oid_t;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_CONFIG {
+	/** CMD Action GET/SET*/
+	t_u16 action;
+	/** Tlv buffer */
+	t_u8 tlv_buffer[1];
+} MLAN_PACK_END HostCmd_DS_SYS_CONFIG;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_INFO {
+    /** sys info */
+	t_u8 sys_info[64];
+} MLAN_PACK_END HostCmd_DS_SYS_INFO;
+
+/** HostCmd_DS_STA_DEAUTH */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_DEAUTH {
+    /** mac address */
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+    /** reason code */
+	t_u16 reason;
+} MLAN_PACK_END HostCmd_DS_STA_DEAUTH;
+
+/** HostCmd_DS_REPORT_MIC */
+typedef MLAN_PACK_START struct _HostCmd_DS_REPORT_MIC {
+    /** mac address */
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END HostCmd_DS_REPORT_MIC;
+
+/** HostCmd_UAP_OPER_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_UAP_OPER_CTRL {
+    /** CMD Action GET/SET*/
+	t_u16 action;
+    /** control*/
+	t_u16 ctrl;
+    /**channel operation*/
+	t_u16 chan_opt;
+    /**channel band tlv*/
+	MrvlIEtypes_channel_band_t channel_band;
+} MLAN_PACK_END HostCmd_DS_UAP_OPER_CTRL;
+
+/** Host Command id: POWER_MGMT  */
+#define HOST_CMD_POWER_MGMT_EXT                   0x00ef
+/** TLV type: AP Sleep param */
+#define TLV_TYPE_AP_SLEEP_PARAM\
+		(PROPRIETARY_TLV_BASE_ID + 0x6a)	/* 0x016a */
+/** TLV type: AP Inactivity Sleep param */
+#define TLV_TYPE_AP_INACT_SLEEP_PARAM\
+		(PROPRIETARY_TLV_BASE_ID + 0x6b)	/* 0x016b */
+
+/** MrvlIEtypes_sleep_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sleep_param_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** control bitmap */
+	t_u32 ctrl_bitmap;
+    /** min_sleep */
+	t_u32 min_sleep;
+    /** max_sleep */
+	t_u32 max_sleep;
+} MLAN_PACK_END MrvlIEtypes_sleep_param_t;
+
+/** MrvlIEtypes_inact_sleep_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_inact_sleep_param_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** inactivity timeout */
+	t_u32 inactivity_to;
+
+    /** min_awake */
+	t_u32 min_awake;
+    /** max_awake */
+	t_u32 max_awake;
+} MLAN_PACK_END MrvlIEtypes_inact_sleep_param_t;
+
+/** HostCmd_DS_POWER_MGMT */
+typedef MLAN_PACK_START struct _HostCmd_DS_POWER_MGMT_EXT {
+    /** CMD Action Get/Set*/
+	t_u16 action;
+    /** power mode */
+	t_u16 power_mode;
+} MLAN_PACK_END HostCmd_DS_POWER_MGMT_EXT;
+
+/** MrvlIEtypes_ps_sta_ageout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ps_sta_ageout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** station age out timer */
+	t_u32 ps_sta_ageout_timer;
+} MLAN_PACK_END MrvlIEtypes_ps_sta_ageout_t;
+
+/** MrvlIEtypes_sta_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sta_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+} 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[0]; */
+} 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 */
+
+/** 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;
+
+/** 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;
+
+/**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[0];
+} 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;
+
+#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
+
+typedef MLAN_PACK_START struct _MrvlTypes_DrcsTimeSlice_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Channel Index*/
+	t_u16 chan_idx;
+	/** Channel time (in TU) for chan_idx*/
+	t_u8 chantime;
+	/** Channel swith time (in TU) for chan_idx*/
+	t_u8 switchtime;
+	/** Undoze time (in TU) for chan_idx*/
+	t_u8 undozetime;
+	/** Rx traffic control scheme when channel switch*/
+	/** only valid for GC/STA interface*/
+	t_u8 mode;
+} MLAN_PACK_END MrvlTypes_DrcsTimeSlice_t;
+typedef MLAN_PACK_START struct _HostCmd_DS_MULTI_CHAN_CFG {
+	/** Action */
+	t_u16 action;
+	/** Channel time */
+	t_u32 channel_time;
+	/** Buffer weight */
+	t_u8 buffer_weight;
+	/** TLV buffer */
+	t_u8 tlv_buf[0];
+	/* t_u8 *tlv_buf; */
+} MLAN_PACK_END HostCmd_DS_MULTI_CHAN_CFG;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_DRCS_CFG {
+	/** Action */
+	t_u16 action;
+	/** TLV buffer */
+	MrvlTypes_DrcsTimeSlice_t time_slicing;
+	/** TLV buffer */
+	MrvlTypes_DrcsTimeSlice_t drcs_buf[0];
+	/* t_u8 *tlv_buf; */
+} MLAN_PACK_END HostCmd_DS_DRCS_CFG;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_MULTI_CHAN_POLICY {
+	/** Action */
+	t_u16 action;
+	/** Multi-channel Policy */
+	t_u16 policy;
+} MLAN_PACK_END HostCmd_DS_MULTI_CHAN_POLICY;
+
+/** Channel band info */
+typedef MLAN_PACK_START struct _ChannelBandInfo {
+	/* band config */
+	Band_Config_t bandcfg;
+    /** channel num for specificed band */
+	t_u8 chan_num;
+} MLAN_PACK_END ChannelBandInfo;
+
+/** MrvlIETypes_mutli_chan_group_info_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_mutli_chan_group_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** channel group id */
+	t_u8 chan_group_id;
+    /** buffer weight for this channel group */
+	t_u8 chan_buff_weight;
+    /** channel number and band information */
+	ChannelBandInfo chan_band_info;
+    /** Max channel time (us) */
+	t_u32 channel_time;
+    /** Reserved */
+	t_u32 reserved;
+	MLAN_PACK_START union {
+		t_u8 sdio_func_num;
+		t_u8 usb_epnum;
+	} MLAN_PACK_END hid_num;
+    /** interface number in this group */
+	t_u8 num_intf;
+    /** bss_type list */
+	t_u8 bss_type_numlist[0];
+} MLAN_PACK_END MrvlIEtypes_multi_chan_group_info_t;
+
+/** MrvlIEtypes_multi_chan_info_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_mutli_chan_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** multi channel operation status */
+	t_u16 status;
+    /** Tlv buffer */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END MrvlIEtypes_multi_chan_info_t;
+
+/** 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;
+
+/** 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*/
+
+/* DFS Repeater Mode */
+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 Marvell extended TLV
+ */
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header;
+				/**< Marvell 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;
+
+/**
+ * @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;
+
+/** Marvell channel descriptor */
+typedef MLAN_PACK_START struct {
+	t_u16 startFreq;		/**< Start Frequency */
+	Band_Config_t bandcfg;		/**< bandcfg */
+	t_u8 chanNum;			/**< channel no */
+
+} MLAN_PACK_END MrvlChannelDesc_t;
+
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t Header;  /**< Header */
+
+	MeasRptBasicMap_t map;	     /**< IEEE 802.11h basic meas report */
+} MLAN_PACK_END MrvlIEtypes_ChanRpt11hBasic_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 STA_SUPPORT
+/** HostCmd_DS_STA_CONFIGURE structure */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_CONFIGURE {
+    /** Action Set or get */
+	t_u16 action;
+    /** Tlv buffer */
+	t_u8 tlv_buffer[0];
+    /**MrvlIEtypes_channel_band_t band_channel; */
+} MLAN_PACK_END HostCmd_DS_STA_CONFIGURE;
+#endif
+
+/** 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;
+
+#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[0];
+} 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
+
+/** 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;
+		HostCmd_DS_SDIO_SP_RX_AGGR_CFG sdio_rx_aggr;
+	/** 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;
+		/** 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;
+	/** 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;
+
+	/** 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;
+	/** 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;
+
+	/** 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 */
+
+       /** Sleep period command */
+		HostCmd_DS_802_11_SLEEP_PERIOD sleep_pd;
+       /** Sleep params command */
+		HostCmd_DS_802_11_SLEEP_PARAMS sleep_param;
+
+       /** SDIO GPIO interrupt config command */
+		HostCmd_DS_SDIO_GPIO_INT_CONFIG sdio_gpio_int;
+		HostCmd_DS_SDIO_PULL_CTRL sdio_pull_ctl;
+		HostCmd_DS_SET_BSS_MODE bss_mode;
+		HostCmd_DS_CMD_TX_DATA_PAUSE tx_data_pause;
+		HostCmd_DS_REMAIN_ON_CHANNEL remain_on_chan;
+#ifdef WIFI_DIRECT_SUPPORT
+		HostCmd_DS_WIFI_DIRECT_MODE wifi_direct_mode;
+		HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG p2p_params_config;
+#endif
+		HostCmd_DS_COALESCE_CONFIG coalesce_config;
+		HostCmd_DS_HS_WAKEUP_REASON hs_wakeup_reason;
+		HostCmd_DS_MULTI_CHAN_CFG multi_chan_cfg;
+		HostCmd_DS_MULTI_CHAN_POLICY multi_chan_policy;
+		HostCmd_DS_DRCS_CFG drcs_cfg;
+		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_APCMD_ACS_SCAN acs_scan;
+#ifdef STA_SUPPORT
+		HostCmd_DS_STA_CONFIGURE sta_cfg;
+#endif
+		HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT ps_inact_tmo;
+		HostCmd_DS_ACS acs;
+		HostCmd_DS_CHAN_REGION_CFG reg_cfg;
+		HostCmd_DS_DYN_BW dyn_bw;
+		HostCmd_DS_802_11_ROBUSTCOEX robustcoexparams;
+    /** boot sleep configure */
+		HostCmd_DS_BOOT_SLEEP boot_sleep;
+#ifdef UAP_SUPPORT
+    /** Add station cmd */
+		HostCmd_DS_ADD_STATION sta_info;
+#endif
+    /** trpc_config */
+		HostCmd_DS_CHANNEL_TRPC_CONFIG ch_trpc_config;
+	} params;
+} MLAN_PACK_END HostCmd_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_u8 hdr[4];
+#ifdef SPI_SUPPORT
+    /** Header for interface */
+	t_u16 hdr;
+#endif
+    /** 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;
+
+#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 100644
index 0000000..9cf442c
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_ieee.h
@@ -0,0 +1,2016 @@
+/** @file mlan_ieee.h
+ *
+ *  @brief This file contains IEEE information element related
+ *  definitions used in MLAN and MOAL module.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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
+
+/** 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,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	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_IE = VENDOR_SPECIFIC_221,
+	RSN_IE = 48,
+	VS_IE = VENDOR_SPECIFIC_221,
+	WAPI_IE = 68,
+	FRAGMENT = 242,
+	EXTENSION = 255
+} MLAN_PACK_END IEEEtypes_ElementId_e;
+
+/** IEEE IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_Header_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+} MLAN_PACK_END IEEEtypes_Header_t, *pIEEEtypes_Header_t;
+
+/** Vendor specific IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorHeader_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI type */
+	t_u8 oui_type;
+    /** OUI subtype */
+	t_u8 oui_subtype;
+    /** Version */
+	t_u8 version;
+} MLAN_PACK_END IEEEtypes_VendorHeader_t, *pIEEEtypes_VendorHeader_t;
+
+/** Vendor specific IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorSpecific_t {
+    /** Vendor specific IE header */
+	IEEEtypes_VendorHeader_t vend_hdr;
+    /** IE Max - size of previous fields */
+	t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_VendorHeader_t)];
+} MLAN_PACK_END IEEEtypes_VendorSpecific_t, *pIEEEtypes_VendorSpecific_t;
+
+/** IEEE IE */
+typedef MLAN_PACK_START struct _IEEEtypes_Generic_t {
+    /** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+    /** IE Max - size of previous fields */
+	t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_Header_t)];
+} MLAN_PACK_END IEEEtypes_Generic_t, *pIEEEtypes_Generic_t;
+
+/**ft capability policy*/
+typedef MLAN_PACK_START struct _IEEEtypes_FtCapPolicy_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Reserved */
+	t_u8 reserved:6;
+    /** RIC support */
+	t_u8 ric:1;
+    /** FT over the DS capable */
+	t_u8 ft_over_ds:1;
+#else
+    /** FT over the DS capable */
+	t_u8 ft_over_ds:1;
+    /** RIC support */
+	t_u8 ric:1;
+    /** Reserved */
+	t_u8 reserved:6;
+#endif
+} MLAN_PACK_END IEEEtypes_FtCapPolicy_t;
+
+/** Mobility domain IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MobilityDomain_t {
+    /** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+    /** Mobility Domain ID */
+	t_u16 mdid;
+    /** FT Capability policy */
+	t_u8 ft_cap;
+} MLAN_PACK_END IEEEtypes_MobilityDomain_t;
+
+/**FT MIC Control*/
+typedef MLAN_PACK_START struct _IEEEtypes_FT_MICControl_t {
+	/** reserved */
+	t_u8 reserved;
+	/** element count */
+	t_u8 element_count;
+} MLAN_PACK_END IEEEtypes_FT_MICControl_t;
+
+/** FTIE MIC LEN */
+#define FTIE_MIC_LEN  16
+
+/**FT IE*/
+typedef MLAN_PACK_START struct _IEEEtypes_FastBssTransElement_t {
+    /** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** mic control */
+	IEEEtypes_FT_MICControl_t mic_control;
+	/** mic */
+	t_u8 mic[FTIE_MIC_LEN];
+	/** ANonce */
+	t_u8 a_nonce[32];
+	/** SNonce */
+	t_u8 s_nonce[32];
+	/** sub element */
+	t_u8 sub_element[1];
+} MLAN_PACK_END IEEEtypes_FastBssTransElement_t;
+
+/*Category for FT*/
+#define FT_CATEGORY 6
+/** FT ACTION request */
+#define FT_ACTION_REQUEST 1
+/** FT ACTION response */
+#define FT_ACTION_RESPONSE 2
+
+/*FT response and FT ack*/
+typedef MLAN_PACK_START struct {
+    /** category */
+	t_u8 category;
+    /** action */
+	t_u8 action;
+    /** sta address */
+	t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+    /** target ap address */
+	t_u8 target_ap_addr[MLAN_MAC_ADDR_LENGTH];
+    /** status code */
+	t_u16 status_code;
+    /** varible */
+	t_u8 variable[0];
+} 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[0];
+} 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[0];
+} 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[0];
+} 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_CfParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_CfParamSet_t {
+    /** CF peremeter : Element ID */
+	t_u8 element_id;
+    /** CF peremeter : Length */
+	t_u8 len;
+    /** CF peremeter : Count */
+	t_u8 cfp_cnt;
+    /** CF peremeter : Period */
+	t_u8 cfp_period;
+    /** CF peremeter : Maximum duration */
+	t_u16 cfp_max_duration;
+    /** CF peremeter : Remaining duration */
+	t_u16 cfp_duration_remaining;
+} MLAN_PACK_END IEEEtypes_CfParamSet_t, *pIEEEtypes_CfParamSet_t;
+
+/** IEEEtypes_IbssParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_IbssParamSet_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+    /** ATIM window value in milliseconds */
+	t_u16 atim_window;
+} MLAN_PACK_END IEEEtypes_IbssParamSet_t, *pIEEEtypes_IbssParamSet_t;
+
+/** IEEEtypes_SsParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_SsParamSet_t {
+    /** SS parameter : CF parameter set */
+	IEEEtypes_CfParamSet_t cf_param_set;
+    /** SS parameter : IBSS parameter set */
+	IEEEtypes_IbssParamSet_t ibss_param_set;
+} MLAN_PACK_END IEEEtypes_SsParamSet_t, *pIEEEtypes_SsParamSet_t;
+
+/** IEEEtypes_FhParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_FhParamSet_t {
+    /** FH parameter : Element ID */
+	t_u8 element_id;
+    /** FH parameter : Length */
+	t_u8 len;
+    /** FH parameter : Dwell time in milliseconds */
+	t_u16 dwell_time;
+    /** FH parameter : Hop set */
+	t_u8 hop_set;
+    /** FH parameter : Hop pattern */
+	t_u8 hop_pattern;
+    /** FH parameter : Hop index */
+	t_u8 hop_index;
+} MLAN_PACK_END IEEEtypes_FhParamSet_t, *pIEEEtypes_FhParamSet_t;
+
+/** IEEEtypes_DsParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_DsParamSet_t {
+    /** DS parameter : Element ID */
+	t_u8 element_id;
+    /** DS parameter : Length */
+	t_u8 len;
+    /** DS parameter : Current channel */
+	t_u8 current_chan;
+} MLAN_PACK_END IEEEtypes_DsParamSet_t, *pIEEEtypes_DsParamSet_t;
+
+/** IEEEtypes_PhyParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_PhyParamSet_t {
+    /** FH parameter set */
+	IEEEtypes_FhParamSet_t fh_param_set;
+    /** DS parameter set */
+	IEEEtypes_DsParamSet_t ds_param_set;
+} MLAN_PACK_END IEEEtypes_PhyParamSet_t, *pIEEEtypes_PhyParamSet_t;
+
+/** IEEEtypes_ERPInfo_t */
+typedef MLAN_PACK_START struct _IEEEtypes_ERPInfo_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+    /** ERP flags */
+	t_u8 erp_flags;
+} MLAN_PACK_END IEEEtypes_ERPInfo_t, *pIEEEtypes_ERPInfo_t;
+
+/** IEEEtypes_AId_t */
+typedef t_u16 IEEEtypes_AId_t;
+
+/** IEEEtypes_StatusCode_t */
+typedef t_u16 IEEEtypes_StatusCode_t;
+
+/** Fixed size in assoc_resp */
+#define ASSOC_RESP_FIXED_SIZE      6
+
+/** IEEEtypes_SeqCtl_t */
+typedef MLAN_PACK_START struct _IEEEtypes_SeqCtl_t {
+/** Fragment Number */
+	t_u16 FragNum:4;
+/** Sequence Number */
+	t_u16 SeqNum:12;
+} MLAN_PACK_END IEEEtypes_SeqCtl_t;
+
+/** IEEEtypes_MgmtHdr_t */
+typedef MLAN_PACK_START struct _IEEEtypes_MgmtHdr_t {
+/** FrmCtl*/
+	t_u16 FrmCtl;
+/** Duration*/
+	t_u16 Duration;
+/** Destination Addr*/
+	t_u8 DestAddr[6];
+/** Source Addr*/
+	t_u8 SrcAddr[6];
+/** BSSID */
+	t_u8 BssId[6];
+/** IEEEtypes_SeqCtl_t */
+	IEEEtypes_SeqCtl_t SeqCtl;
+} MLAN_PACK_END IEEEtypes_MgmtHdr_t;
+
+/** IEEEtypes_AssocRsp_t */
+typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t {
+    /** Capability information */
+	IEEEtypes_CapInfo_t capability;
+    /** Association response status code */
+	IEEEtypes_StatusCode_t status_code;
+    /** Association ID */
+	IEEEtypes_AId_t a_id;
+    /** IE data buffer */
+	t_u8 ie_buffer[1];
+} MLAN_PACK_END IEEEtypes_AssocRsp_t, *pIEEEtypes_AssocRsp_t;
+
+/** 802.11 supported rates */
+typedef t_u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES];
+
+/** cipher TKIP */
+#define WPA_CIPHER_TKIP		2
+/** cipher AES */
+#define WPA_CIPHER_AES_CCM	4
+/** AKM: 8021x */
+#define RSN_AKM_8021X		1
+/** AKM: PSK */
+#define RSN_AKM_PSK         2
+/** AKM: PSK SHA256 */
+#define RSN_AKM_PSK_SHA256	6
+
+/** AKM: PSK SHA256 */
+#define RSN_AKM_SAE	8
+/** AKM: PSK SHA256 */
+#define RSN_AKM_OWE	18
+
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN    4
+/** AKM Suite length */
+#define AKM_SUITE_LEN    4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT    7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT    6
+/** PMF ORing mask */
+#define PMF_MASK    0x00c0
+#endif
+
+/** wpa_suite_t */
+typedef MLAN_PACK_START struct _wpa_suite_t {
+    /** OUI */
+	t_u8 oui[3];
+    /** tyep */
+	t_u8 type;
+} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t;
+
+/** wpa_suite_ucast_t */
+typedef MLAN_PACK_START struct {
+	/* count */
+	t_u16 count;
+    /** wpa_suite list */
+	wpa_suite list[1];
+} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+
+/** IEEEtypes_Rsn_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t {
+    /** Rsn : Element ID */
+	t_u8 element_id;
+    /** Rsn : Length */
+	t_u8 len;
+    /** Rsn : version */
+	t_u16 version;
+    /** Rsn : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Rsn : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t;
+
+/** IEEEtypes_Wpa_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t {
+    /** Wpa : Element ID */
+	t_u8 element_id;
+    /** Wpa : Length */
+	t_u8 len;
+    /** Wpa : oui */
+	t_u8 oui[4];
+    /** version */
+	t_u16 version;
+    /** Wpa : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Wpa : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Reserved */
+	t_u8 reserved:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aifsn */
+	t_u8 aifsn:4;
+#else
+    /** Aifsn */
+	t_u8 aifsn:4;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn;   /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;		    /**< Ecw */
+	t_u16 tx_op_limit;		      /**< Tx op limit */
+} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t {
+
+    /**
+     * WMM Info IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [7]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [0]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+
+} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t {
+    /**
+     * WMM Parameter IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [24]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [1]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+    /** Reserved */
+	t_u8 reserved;
+
+    /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/** Enumerator for TSPEC direction */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e {
+
+	TSPEC_DIR_UPLINK = 0,
+	TSPEC_DIR_DOWNLINK = 1,
+	/* 2 is a reserved value */
+	TSPEC_DIR_BIDIRECT = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e;
+
+/** Enumerator for TSPEC PSB */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e {
+
+	TSPEC_PSB_LEGACY = 0,
+	TSPEC_PSB_TRIG = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e;
+
+/** Enumerator for TSPEC Ack Policy */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e {
+
+	TSPEC_ACKPOLICY_NORMAL = 0,
+	TSPEC_ACKPOLICY_NOACK = 1,
+	/* 2 is reserved */
+	TSPEC_ACKPOLICY_BLOCKACK = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e;
+
+/** Enumerator for TSPEC Trafffice type */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e {
+
+	TSPEC_TRAFFIC_APERIODIC = 0,
+	TSPEC_TRAFFIC_PERIODIC = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e;
+
+/** Data structure of WMM TSPEC information */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+	t_u8 Schedule:1;
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 AccessPolicy1:1;	/* ! */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+#else
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 AccessPolicy1:1;	/* ! */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 Schedule:1;
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t;
+
+/** Data structure of WMM TSPEC Nominal Size */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+	t_u16 Size:15;		/* ! Nominal size in octets */
+#else
+	t_u16 Size:15;		/* ! Nominal size in octets */
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t;
+
+/** Data structure of WMM TSPEC SBWA */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Whole:3;		/* ! Whole portion */
+	t_u16 Fractional:13;	/* ! Fractional portion */
+#else
+	t_u16 Fractional:13;	/* ! Fractional portion */
+	t_u16 Whole:3;		/* ! Whole portion */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA;
+
+/** Data structure of WMM TSPEC Body */
+typedef MLAN_PACK_START struct {
+
+    /** TS Information */
+	IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo;
+    /** NomMSDU size */
+	IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize;
+    /** MAximum MSDU size */
+	t_u16 MaximumMSDUSize;
+    /** Minimum Service Interval */
+	t_u32 MinServiceInterval;
+    /** Maximum Service Interval */
+	t_u32 MaxServiceInterval;
+    /** Inactivity Interval */
+	t_u32 InactivityInterval;
+    /** Suspension Interval */
+	t_u32 SuspensionInterval;
+    /** Service Start Time */
+	t_u32 ServiceStartTime;
+    /** Minimum Data Rate */
+	t_u32 MinimumDataRate;
+    /** Mean Data Rate */
+	t_u32 MeanDataRate;
+    /** Peak Data Rate */
+	t_u32 PeakDataRate;
+    /** Maximum Burst Size */
+	t_u32 MaxBurstSize;
+    /** Delay Bound */
+	t_u32 DelayBound;
+    /** Minimum Phy Rate */
+	t_u32 MinPHYRate;
+    /** Surplus BA Allowance */
+	IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance;
+    /** Medium Time */
+	t_u16 MediumTime;
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t;
+
+/** Data structure of WMM TSPEC all elements */
+typedef MLAN_PACK_START struct {
+    /** Element ID */
+	t_u8 ElementId;
+    /** Length */
+	t_u8 Len;
+    /** Oui Type */
+	t_u8 OuiType[4];	/* 00:50:f2:02 */
+    /** Ouisubtype */
+	t_u8 OuiSubType;	/* 01 */
+    /** Version */
+	t_u8 Version;
+
+    /** TspecBody */
+	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 {
+
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+    /** Action */
+	IEEEtypes_WMM_Tspec_Action_e action;
+    /** Dialog Token */
+	t_u8 dialogToken;
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t;
+
+/** WMM TSPEC AddTS request structure */
+typedef MLAN_PACK_START struct {
+
+    /** Tspec action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Status Code */
+	t_u8 statusCode;
+    /** tspecIE */
+	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 {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Reason Code */
+	t_u8 reasonCode;
+    /** tspecIE */
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t;
+
+/** union of WMM TSPEC structures */
+typedef MLAN_PACK_START union {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+
+    /** add TS request */
+	IEEEtypes_Action_WMM_AddTsReq_t addTsReq;
+    /** add TS response */
+	IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp;
+    /** Delete TS */
+	IEEEtypes_Action_WMM_DelTs_t delTs;
+
+} MLAN_PACK_END IEEEtypes_Action_WMMAC_t;
+
+/** union of WMM TSPEC & Action category */
+typedef MLAN_PACK_START union {
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+
+    /** wmmAc */
+	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;
+
+/** 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;
+    /** Channel width */
+	t_u8 chan_width;
+    /** Channel center frequency 1 */
+	t_u8 chan_center_freq_1;
+    /** Channel center frequency 2 */
+	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;
+    /** maximum tx power */
+	t_u8 max_tx_power;
+    /** channel center frequency */
+	t_u8 chan_center_freq;
+    /** channel width */
+	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;
+    /** MIMO capability count */
+	t_u8 MU_MIMO_capa_count;
+    /** stream under utilization */
+	t_u8 stream_underutilization;
+    /** VHT 40 util */
+	t_u8 VHT40_util;
+    /** VHT 80 util */
+	t_u8 VHT80_util;
+    /** VHT 160 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;
+    /** AP quiet mode */
+	t_u8 AP_quiet_mode;
+    /** Quiet count */
+	t_u8 quiet_count;
+    /** Quiet period */
+	t_u8 quiet_period;
+    /** Quiet duration */
+	t_u16 quiet_dur;
+    /** Quiet offset */
+	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;
+    /** New channel width */
+	t_u8 new_chan_width;
+    /** New channel center frequency 1 */
+	t_u8 new_chan_center_freq_1;
+    /** New channel center frequency 2 */
+	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;
+
+/** default channel switch count */
+#define DEF_CHAN_SWITCH_COUNT       5
+
+/*  IEEE Channel Switch Announcement Element (7.3.2.20) */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a chan switch element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;	/**< IEEE Element ID = 37 */
+	t_u8 len;		/**< Element length after id and len */
+	t_u8 chan_switch_mode;	/**< STA should not transmit any frames if 1 */
+	t_u8 new_channel_num;	/**< Channel # that AP/IBSS is moving to */
+	t_u8 chan_switch_count;	/**< # of TBTTs before channel switch */
+
+} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t;
+
+/** data structure for extended channel switch */
+typedef MLAN_PACK_START struct {
+   /** IEEE element ID = 60 */
+	t_u8 element_id;
+    /** Element length after id and len, set to 4 */
+	t_u8 len;
+    /** STA should not transmit any frames if 1 */
+	t_u8 chan_switch_mode;
+    /** Operate class # that AP/IBSS is moving to */
+	t_u8 new_oper_class;
+    /** Channel # that AP/IBSS is moving to */
+	t_u8 new_channel_num;
+    /** of TBTTs before channel switch */
+	t_u8 chan_switch_count;
+} MLAN_PACK_END IEEEtypes_ExtChanSwitchAnn_t;
+
+/*  IEEE Wide Bandwidth Channel Switch Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a wide bandwidth chan
+ *    switch element.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 194*/
+	IEEEtypes_Header_t ieee_hdr;
+    /** New channel width */
+	t_u8 new_channel_width;
+    /** New channel center frequency 0*/
+	t_u8 new_channel_center_freq0;
+    /** New channel center frequency 1*/
+	t_u8 new_channel_center_freq1;
+} MLAN_PACK_END IEEEtypes_WideBWChanSwitch_t;
+
+/*  IEEE VHT Transmit Power Envelope Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise the max
+ *    TX power in sepeate bandwidth and as a sub element of Channel Switch
+ *    Wrapper IE.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 195*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 tpc_info;		/**< Transmit Power Information>*/
+	t_u8 local_max_tp_20mhz;/**< Local Maximum Transmit Power for 20 MHZ>*/
+	t_u8 local_max_tp_40mhz;/**< Local Maximum Transmit Power for 40 MHZ>*/
+	t_u8 local_max_tp_80mhz;/**< Local Maximum Transmit Power for 80 MHZ>*/
+} MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t;
+
+/** 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 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
+
+/** 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;
+
+/**
+ *  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;
+    /** flag to filer only probe response */
+	t_u8 proberesp_only;
+} 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];
+} MLAN_PACK_END wlan_bgscan_cfg;
+#endif /* STA_SUPPORT */
+
+/** 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;
+} MLAN_PACK_END ChanStatistics_t;
+
+#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 */
+	t_u32 channel;
+
+    /** Freq */
+	t_u32 freq;
+
+    /** Beacon period */
+	t_u16 beacon_period;
+
+    /** ATIM window */
+	t_u32 atim_window;
+
+    /** ERP flags */
+	t_u8 erp_flags;
+
+    /** Type of network in use */
+	WLAN_802_11_NETWORK_TYPE network_type_use;
+
+    /** Network infrastructure mode */
+	t_u32 bss_mode;
+
+    /** Network supported rates */
+	WLAN_802_11_RATES supported_rates;
+
+    /** Supported data rates */
+	t_u8 data_rates[WLAN_SUPPORTED_RATES];
+
+    /** Current channel bandwidth
+     *  0 : 20MHZ
+     *  1 : 40MHZ
+     *  2 : 80MHZ
+     *  3 : 160MHZ
+     */
+	t_u8 curr_bandwidth;
+
+    /** Network band.
+     * BAND_B(0x01): 'b' band
+     * BAND_G(0x02): 'g' band
+     * BAND_A(0X04): 'a' band
+     */
+	t_u16 bss_band;
+
+    /** TSF timestamp from the current firmware TSF */
+	t_u64 network_tsf;
+
+    /** TSF value included in the beacon/probe response */
+	t_u8 time_stamp[8];
+
+    /** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+
+    /** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+
+    /** Capability information */
+	IEEEtypes_CapInfo_t cap_info;
+
+    /** WMM IE */
+	IEEEtypes_WmmParameter_t wmm_ie;
+
+    /** 802.11h BSS information */
+	wlan_11h_bss_info_t wlan_11h_bss_info;
+
+    /** Indicate disabling 11n when associate with AP */
+	t_u8 disable_11n;
+    /** 802.11n BSS information */
+    /** HT Capabilities IE */
+	IEEEtypes_HTCap_t *pht_cap;
+    /** HT Capabilities Offset */
+	t_u16 ht_cap_offset;
+    /** HT Information IE */
+	IEEEtypes_HTInfo_t *pht_info;
+    /** HT Information Offset */
+	t_u16 ht_info_offset;
+    /** 20/40 BSS Coexistence IE */
+	IEEEtypes_2040BSSCo_t *pbss_co_2040;
+    /** 20/40 BSS Coexistence Offset */
+	t_u16 bss_co_2040_offset;
+    /** Extended Capabilities IE */
+	IEEEtypes_ExtCap_t *pext_cap;
+    /** Extended Capabilities Offset */
+	t_u16 ext_cap_offset;
+    /** Overlapping BSS Scan Parameters IE */
+	IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param;
+    /** Overlapping BSS Scan Parameters Offset */
+	t_u16 overlap_bss_offset;
+
+    /** VHT Capabilities IE */
+	IEEEtypes_VHTCap_t *pvht_cap;
+    /** VHT Capabilities IE offset */
+	t_u16 vht_cap_offset;
+    /** VHT Operations IE */
+	IEEEtypes_VHTOprat_t *pvht_oprat;
+    /** VHT Operations IE offset */
+	t_u16 vht_oprat_offset;
+    /** VHT Transmit Power Envelope IE */
+	IEEEtypes_VHTtxpower_t *pvht_txpower;
+    /** VHT Transmit Power Envelope IE offset */
+	t_u16 vht_txpower_offset;
+    /** Extended Power Constraint IE */
+	IEEEtypes_ExtPwerCons_t *pext_pwer;
+    /** Extended Power Constraint IE offset */
+	t_u16 ext_pwer_offset;
+    /** Extended BSS Load IE  */
+	IEEEtypes_ExtBSSload_t *pext_bssload;
+    /** Extended BSS Load IE offset */
+	t_u16 ext_bssload_offset;
+    /** Quiet Channel IE */
+	IEEEtypes_QuietChan_t *pquiet_chan;
+    /** Quiet Channel IE offset */
+	t_u16 quiet_chan_offset;
+    /** Operating Mode Notification IE */
+	IEEEtypes_OperModeNtf_t *poper_mode;
+    /** Operating Mode Notification IE offset */
+	t_u16 oper_mode_offset;
+
+#ifdef STA_SUPPORT
+    /** Country information set */
+	IEEEtypes_CountryInfoFullSet_t country_info;
+#endif				/* STA_SUPPORT */
+
+    /** WPA IE */
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+    /** WPA IE offset in the beacon buffer */
+	t_u16 wpa_offset;
+    /** RSN IE */
+	IEEEtypes_Generic_t *prsn_ie;
+    /** RSN IE offset in the beacon buffer */
+	t_u16 rsn_offset;
+#ifdef STA_SUPPORT
+    /** WAPI IE */
+	IEEEtypes_Generic_t *pwapi_ie;
+    /** WAPI IE offset in the beacon buffer */
+	t_u16 wapi_offset;
+#endif
+	/* Hotspot 2.0 OSEN AKM  IE */
+	IEEEtypes_Generic_t *posen_ie;
+    /** osen IE offset in the beacon buffer */
+	t_u16 osen_offset;
+	/* Mobility domain IE */
+	IEEEtypes_MobilityDomain_t *pmd_ie;
+	/** Mobility domain IE offset in the beacon buffer */
+	t_u16 md_offset;
+
+    /** Pointer to the returned scan response */
+	t_u8 *pbeacon_buf;
+    /** Length of the stored scan response */
+	t_u32 beacon_buf_size;
+    /** Max allocated size for updated scan response */
+	t_u32 beacon_buf_size_max;
+
+} BSSDescriptor_t, *pBSSDescriptor_t;
+
+/**
+ *  Type definitions for TCLAS element
+ */
+#define TCLAS_CLASSIFIER_TYPE_4      4
+
+/**
+ *  IEEE TCLAS Classifier Type 4
+ *
+ *  Type definition for Classifier Type 4 in TCLAS element
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_IPv4_t {
+    /** Version */
+	t_u8 version;
+    /** Source IP address */
+	t_u8 source_ip_addr[4];
+    /** Dest IP address */
+	t_u8 dest_ip_addr[4];
+    /** Source port */
+	t_u8 source_port[2];
+    /** Dest port */
+	t_u8 dest_port[2];
+    /** DSCP value */
+	t_u8 dscp;
+    /** Protocol value */
+	t_u8 protocol;
+    /** Reserved */
+	t_u8 reserved;
+} MLAN_PACK_END IEEEtypes_TCLAS_IPv4_t;
+
+/**
+ *  IEEE TCLAS base
+ *
+ *  Type definition for common parameters for every
+ *    classifier type
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_Base_t {
+    /** Element id */
+	t_u8 element_id;
+    /** Element len */
+	t_u8 element_len;
+    /** User priority */
+	t_u8 user_priority;
+    /** Classifier type */
+	t_u8 classifier_type;
+    /** Classifier mask */
+	t_u8 classifier_mask;
+} MLAN_PACK_END IEEEtypes_TCLAS_Base_t;
+
+/**
+ *  IEEE TCLAS element
+ *
+ *  Type definition for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_t {
+    /** Base structure for TCLAS */
+	IEEEtypes_TCLAS_Base_t tclas_base;
+
+	union MLAN_PACK_START {
+	/** Classifier type 4 */
+		IEEEtypes_TCLAS_IPv4_t ipv4;
+	} MLAN_PACK_END classifier;
+} MLAN_PACK_END IEEEtypes_TCLAS_t;
+
+/**
+ *  TCLAS element TLV
+ *
+ *  Structure that defines TLV for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _tclasElemen_tlv {
+    /** Type */
+	t_u16 type;
+    /** Length of TLV */
+	t_u16 len;
+    /** Tclas Ie */
+	IEEEtypes_TCLAS_t tclas_ie;
+} MLAN_PACK_END tclas_element_tlv_t;
+
+#endif /* !_MLAN_IEEE_H_ */
diff --git a/wlan_sd8987/mlan/mlan_init.c b/wlan_sd8987/mlan/mlan_init.c
new file mode 100644
index 0000000..33160c9
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_init.c
@@ -0,0 +1,1677 @@
+/** @file mlan_init.c
+ *
+ *  @brief This file contains the initialization for FW
+ *  and HW.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.h"
+
+/********************************************************
+			Global Variables
+********************************************************/
+extern mlan_operations *mlan_ops[];
+/*******************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief This function adds a BSS priority table
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_add_bsspriotbl(pmlan_private priv)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_bssprio_node *pbssprio = MNULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	status = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						  sizeof(mlan_bssprio_node),
+						  MLAN_MEM_DEF,
+						  (t_u8 **)&pbssprio);
+	if (status) {
+		PRINTM(MERROR, "Failed to allocate bsspriotbl\n");
+		LEAVE();
+		return status;
+	}
+
+	pbssprio->priv = priv;
+
+	util_init_list((pmlan_linked_list)pbssprio);
+
+	if (!pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur)
+		pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur
+			= pbssprio;
+
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &pmadapter->bssprio_tbl[priv->bss_priority].
+			       bssprio_head, (pmlan_linked_list)pbssprio,
+			       pmadapter->callbacks.moal_spin_lock,
+			       pmadapter->callbacks.moal_spin_unlock);
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function deletes the BSS priority table
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         N/A
+ */
+static t_void
+wlan_delete_bsspriotbl(pmlan_private priv)
+{
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_bssprio_node *pbssprio_node = MNULL, *ptmp_node = MNULL, **ppcur =
+		MNULL;
+	pmlan_list_head phead;
+
+	ENTER();
+
+	for (i = 0; i < pmadapter->priv_num; ++i) {
+		phead = &pmadapter->bssprio_tbl[i].bssprio_head;
+		ppcur = &pmadapter->bssprio_tbl[i].bssprio_cur;
+		PRINTM(MINFO,
+		       "Delete BSS priority table, index = %d, i = %d, phead = %p, pcur = %p\n",
+		       priv->bss_index, i, phead, *ppcur);
+		if (*ppcur) {
+			pbssprio_node =
+				(mlan_bssprio_node *)util_peek_list(pmadapter->
+								    pmoal_handle,
+								    phead,
+								    pmadapter->
+								    callbacks.
+								    moal_spin_lock,
+								    pmadapter->
+								    callbacks.
+								    moal_spin_unlock);
+			while (pbssprio_node &&
+			       ((pmlan_list_head)pbssprio_node != phead)) {
+				ptmp_node = pbssprio_node->pnext;
+				if (pbssprio_node->priv == priv) {
+					PRINTM(MINFO,
+					       "Delete node, pnode = %p, pnext = %p\n",
+					       pbssprio_node, ptmp_node);
+					util_unlink_list(pmadapter->
+							 pmoal_handle, phead,
+							 (pmlan_linked_list)
+							 pbssprio_node,
+							 pmadapter->callbacks.
+							 moal_spin_lock,
+							 pmadapter->callbacks.
+							 moal_spin_unlock);
+					pmadapter->callbacks.
+						moal_mfree(pmadapter->
+							   pmoal_handle,
+							   (t_u8 *)
+							   pbssprio_node);
+				}
+				pbssprio_node = ptmp_node;
+			}
+			*ppcur = (mlan_bssprio_node *)phead;
+		}
+	}
+
+	LEAVE();
+}
+
+/********************************************************
+			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
+	t_u32 max_mp_regs = pmadapter->psdio_device->reg->max_mp_regs;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	t_u32 mp_tx_aggr_buf_size =
+		pmadapter->psdio_device->mp_tx_aggr_buf_size;
+	t_u32 mp_rx_aggr_buf_size =
+		pmadapter->psdio_device->mp_rx_aggr_buf_size;
+#endif
+
+	ENTER();
+
+#ifdef STA_SUPPORT
+	/* Allocate buffer to store the BSSID list */
+	buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST;
+	if (pmadapter->callbacks.moal_vmalloc &&
+	    pmadapter->callbacks.moal_vfree)
+		ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle,
+							buf_size,
+							(t_u8 **)
+							&ptemp_scan_table);
+	else
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       buf_size, MLAN_MEM_DEF,
+						       (t_u8 **)
+						       &ptemp_scan_table);
+	if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) {
+		PRINTM(MERROR, "Failed to allocate scan table\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->pscan_table = ptemp_scan_table;
+
+	if (pmadapter->fixed_beacon_buffer)
+		beacon_buffer_size = MAX_SCAN_BEACON_BUFFER;
+	else
+		beacon_buffer_size = DEFAULT_SCAN_BEACON_BUFFER;
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       beacon_buffer_size, MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->bcn_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->bcn_buf) {
+		PRINTM(MERROR, "Failed to allocate bcn buf\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->bcn_buf_size = beacon_buffer_size;
+
+	pmadapter->num_in_chan_stats = sizeof(chan_2g);
+	pmadapter->num_in_chan_stats += sizeof(chan_5g);
+	buf_size = sizeof(ChanStatistics_t) * pmadapter->num_in_chan_stats;
+	if (pmadapter->callbacks.moal_vmalloc &&
+	    pmadapter->callbacks.moal_vfree)
+		ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle,
+							buf_size,
+							(t_u8 **)&pmadapter->
+							pchan_stats);
+	else
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       buf_size, MLAN_MEM_DEF,
+						       (t_u8 **)&pmadapter->
+						       pchan_stats);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pchan_stats) {
+		PRINTM(MERROR, "Failed to allocate channel statistics\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+#endif
+
+	/* Allocate command buffer */
+	ret = wlan_alloc_cmd_buffer(pmadapter);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to allocate command buffer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       max_mp_regs + DMA_ALIGNMENT,
+					       MLAN_MEM_DEF | MLAN_MEM_DMA,
+					       (t_u8 **)&pmadapter->
+					       mp_regs_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mp_regs_buf) {
+		PRINTM(MERROR, "Failed to allocate mp_regs_buf\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->mp_regs =
+		(t_u8 *)ALIGN_ADDR(pmadapter->mp_regs_buf, DMA_ALIGNMENT);
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       SDIO_CMD53_MAX_SIZE +
+					       DMA_ALIGNMENT,
+					       MLAN_MEM_DEF | MLAN_MEM_DMA,
+					       (t_u8 **)&pmadapter->rx_buffer);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->rx_buffer) {
+		PRINTM(MERROR, "Failed to allocate receive buffer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->rx_buf =
+		(t_u8 *)ALIGN_ADDR(pmadapter->rx_buffer, DMA_ALIGNMENT);
+#endif
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	pmadapter->max_sp_tx_size = MAX_SUPPORT_AMSDU_SIZE;
+	pmadapter->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->mpa_buf_size =
+			SDIO_MP_DBG_NUM *
+			pmadapter->psdio_device->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->
+								mpa_buf_size,
+								(t_u8 **)
+								&pmadapter->
+								mpa_buf);
+		else
+			ret = pmadapter->callbacks.moal_malloc(pmadapter->
+							       pmoal_handle,
+							       pmadapter->
+							       mpa_buf_size,
+							       MLAN_MEM_DEF,
+							       (t_u8 **)
+							       &pmadapter->
+							       mpa_buf);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->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);
+
+	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;
+
+	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->curr_bss_params, 0,
+	       sizeof(priv->curr_bss_params));
+	priv->listen_interval = MLAN_DEFAULT_LISTEN_INTERVAL;
+
+	memset(pmadapter, &priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf));
+	priv->assoc_rsp_size = 0;
+
+	wlan_11d_priv_init(priv);
+	wlan_11h_priv_init(priv);
+
+#ifdef UAP_SUPPORT
+	priv->uap_bss_started = MFALSE;
+	priv->uap_host_based = MFALSE;
+	memset(pmadapter, &priv->uap_state_chan_cb, 0,
+	       sizeof(priv->uap_state_chan_cb));
+#endif
+#if defined(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;
+	/* refer to V15 CMD_TX_RATE_QUERY */
+	priv->rxpd_vhtinfo = 0;
+	priv->rxpd_rate = 0;
+	priv->rate_bitmap = 0;
+	priv->data_rssi_last = 0;
+	priv->data_rssi_avg = 0;
+	priv->data_nf_avg = 0;
+	priv->data_nf_last = 0;
+	priv->bcn_rssi_last = 0;
+	priv->bcn_rssi_avg = 0;
+	priv->bcn_nf_avg = 0;
+	priv->bcn_nf_last = 0;
+
+	priv->sec_info.ewpa_enabled = MFALSE;
+	priv->sec_info.wpa_enabled = MFALSE;
+	priv->sec_info.wpa2_enabled = MFALSE;
+	memset(pmadapter, &priv->wpa_ie, 0, sizeof(priv->wpa_ie));
+	memset(pmadapter, &priv->aes_key, 0, sizeof(priv->aes_key));
+	priv->wpa_ie_len = 0;
+	priv->wpa_is_gtk_set = MFALSE;
+#if defined(STA_SUPPORT)
+	priv->pmfcfg.mfpc = 0;
+	priv->pmfcfg.mfpr = 0;
+#endif
+	priv->sec_info.wapi_enabled = MFALSE;
+	priv->wapi_ie_len = 0;
+	priv->sec_info.wapi_key_on = MFALSE;
+
+	memset(pmadapter, &priv->wps, 0, sizeof(priv->wps));
+	memset(pmadapter, &priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
+	priv->gen_ie_buf_len = 0;
+#endif /* STA_SUPPORT */
+	priv->wmm_required = MTRUE;
+	priv->wmm_enabled = MFALSE;
+	priv->wmm_qosinfo = 0;
+	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;
+	priv->tdls_idle_time = TDLS_IDLE_TIMEOUT;
+	priv->txaggrctrl = MTRUE;
+#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(priv->adapter, &priv->def_ext_cap, &priv->ext_cap,
+	       sizeof(priv->ext_cap));
+#endif /* STA_SUPPORT */
+
+	for (i = 0; i < MAX_NUM_TID; i++)
+		priv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+	priv->addba_reject[6] = ADDBA_RSP_STATUS_REJECT;
+	priv->addba_reject[7] = ADDBA_RSP_STATUS_REJECT;
+	memcpy(priv->adapter, priv->ibss_addba_reject, priv->addba_reject,
+	       sizeof(priv->addba_reject));
+	priv->max_amsdu = 0;
+#ifdef STA_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+		priv->add_ba_param.tx_win_size =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_sta_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 =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_wfd_txrxwinsize;
+		priv->add_ba_param.rx_win_size =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_wfd_txrxwinsize;
+	}
+#endif
+#ifdef UAP_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		priv->add_ba_param.tx_win_size =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_uap_txwinsize;
+		priv->add_ba_param.rx_win_size =
+			pmadapter->psdio_device->ampdu_info->
+			ampdu_uap_rxwinsize;
+		priv->aggr_prio_tbl[6].ampdu_user =
+			priv->aggr_prio_tbl[7].ampdu_user =
+			BA_STREAM_NOT_ALLOWED;
+	}
+#endif
+	priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
+
+	priv->port_ctrl_mode = MTRUE;
+
+	priv->port_open = MFALSE;
+
+	priv->intf_hr_len = INTF_HEADER_LEN;
+	ret = wlan_add_bsspriotbl(priv);
+
+	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;
+
+	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
+
+	pmadapter->int_mode = pmadapter->init_para.int_mode;
+	pmadapter->gpio_pin = pmadapter->init_para.gpio_pin;
+
+#if defined(STA_SUPPORT)
+	pmadapter->pwarm_reset_ioctl_req = MNULL;
+#endif
+	pmadapter->cmd_sent = MFALSE;
+	pmadapter->data_sent = MTRUE;
+	pmadapter->mp_rd_bitmap = 0;
+	pmadapter->mp_wr_bitmap = 0;
+	if (pmadapter->psdio_device->supports_sdio_new_mode) {
+		pmadapter->curr_rd_port = 0;
+		pmadapter->curr_wr_port = 0;
+	} else {
+		pmadapter->curr_rd_port = 1;
+		pmadapter->curr_wr_port = 1;
+	}
+	pmadapter->mp_data_port_mask =
+		pmadapter->psdio_device->reg->data_port_mask;
+	pmadapter->mp_invalid_update = 0;
+	memset(pmadapter, pmadapter->mp_update, 0,
+	       sizeof(pmadapter->mp_update));
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	pmadapter->mpa_tx.buf_len = 0;
+	pmadapter->mpa_tx.pkt_cnt = 0;
+	pmadapter->mpa_tx.start_port = 0;
+
+	if (!pmadapter->init_para.mpa_tx_cfg)
+		pmadapter->mpa_tx.enabled = MFALSE;
+	else if (pmadapter->init_para.mpa_tx_cfg == MLAN_INIT_PARA_DISABLED)
+		pmadapter->mpa_tx.enabled = MFALSE;
+	else
+		pmadapter->mpa_tx.enabled = MTRUE;
+	pmadapter->mpa_tx.pkt_aggr_limit =
+		pmadapter->psdio_device->mp_aggr_pkt_limit;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	pmadapter->mpa_rx.buf_len = 0;
+	pmadapter->mpa_rx.pkt_cnt = 0;
+	pmadapter->mpa_rx.start_port = 0;
+
+	if (!pmadapter->init_para.mpa_rx_cfg)
+		pmadapter->mpa_rx.enabled = MFALSE;
+	else if (pmadapter->init_para.mpa_rx_cfg == MLAN_INIT_PARA_DISABLED)
+		pmadapter->mpa_rx.enabled = MFALSE;
+	else
+		pmadapter->mpa_rx.enabled = MTRUE;
+	pmadapter->mpa_rx.pkt_aggr_limit =
+		pmadapter->psdio_device->mp_aggr_pkt_limit;
+
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+	pmadapter->rx_pkts_queued = 0;
+	pmadapter->cmd_resp_received = MFALSE;
+	pmadapter->event_received = MFALSE;
+	pmadapter->data_received = MFALSE;
+
+	pmadapter->cmd_timer_is_set = MFALSE;
+
+	/* PnP and power profile */
+	pmadapter->surprise_removed = MFALSE;
+	/* FW hang report */
+	pmadapter->fw_hang_report = MFALSE;
+
+	if (!pmadapter->init_para.ps_mode) {
+		pmadapter->ps_mode = DEFAULT_PS_MODE;
+	} else if (pmadapter->init_para.ps_mode == MLAN_INIT_PARA_DISABLED)
+		pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+	else
+		pmadapter->ps_mode = Wlan802_11PowerModePSP;
+	pmadapter->ps_state = PS_STATE_AWAKE;
+	pmadapter->need_to_wakeup = MFALSE;
+
+#ifdef STA_SUPPORT
+	pmadapter->scan_block = MFALSE;
+	/* Scan type */
+	pmadapter->scan_type = MLAN_SCAN_TYPE_ACTIVE;
+	/* Scan mode */
+	pmadapter->scan_mode = HostCmd_BSS_MODE_ANY;
+	/* Scan time */
+	pmadapter->specific_scan_time = MRVDRV_SPECIFIC_SCAN_CHAN_TIME;
+	pmadapter->active_scan_time = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
+	pmadapter->passive_scan_time = MRVDRV_PASSIVE_SCAN_CHAN_TIME;
+
+	pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_EN;
+
+	pmadapter->num_in_scan_table = 0;
+	memset(pmadapter, pmadapter->pscan_table, 0,
+	       (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
+	pmadapter->ext_scan = pmadapter->psdio_device->ext_scan;
+	pmadapter->scan_probes = DEFAULT_PROBES;
+
+	memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size);
+	pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+
+	pmadapter->radio_on = RADIO_ON;
+	if (!pmadapter->multiple_dtim)
+		pmadapter->multiple_dtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
+
+	pmadapter->local_listen_interval = 0;	/* default value in firmware will be used */
+#endif /* STA_SUPPORT */
+
+	pmadapter->is_deep_sleep = MFALSE;
+	pmadapter->idle_time = DEEP_SLEEP_IDLE_TIME;
+	if (!pmadapter->init_para.auto_ds)
+		pmadapter->init_auto_ds = DEFAULT_AUTO_DS_MODE;
+	else if (pmadapter->init_para.auto_ds == MLAN_INIT_PARA_DISABLED)
+		pmadapter->init_auto_ds = MFALSE;
+	else
+		pmadapter->init_auto_ds = MTRUE;
+
+	pmadapter->delay_null_pkt = MFALSE;
+	pmadapter->delay_to_ps = DELAY_TO_PS_DEFAULT;
+	pmadapter->enhanced_ps_mode = PS_MODE_AUTO;
+
+	pmadapter->gen_null_pkt = MFALSE;	/* Disable NULL Pkt generation-default */
+	pmadapter->pps_uapsd_mode = MFALSE;	/* Disable pps/uapsd mode -default */
+
+	pmadapter->pm_wakeup_card_req = MFALSE;
+
+	pmadapter->pm_wakeup_fw_try = MFALSE;
+
+	if (!pmadapter->init_para.max_tx_buf)
+		pmadapter->max_tx_buf_size =
+			pmadapter->psdio_device->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;
+
+	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->adhoc_11n_enabled = MFALSE;
+	pmadapter->tdls_status = TDLS_NOT_SETUP;
+#endif /* STA_SUPPORT */
+
+	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);
+	}
+	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->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(pmadapter, pmadapter->country_code, MRVDRV_DEFAULT_COUNTRY_CODE,
+	       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 */
+
+	pmadapter->mc_status = MFALSE;
+
+	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(IN 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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pmlan_lock)
+	    != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pint_lock)
+	    != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	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;
+	}
+
+	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(IN 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 (pmadapter->pint_lock)
+		pcb->moal_free_lock(pmadapter->pmoal_handle,
+				    pmadapter->pint_lock);
+	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);
+
+	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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	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 (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(IN pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	if (pmadapter->pmlan_cmd_timer)
+		pcb->moal_free_timer(pmadapter->pmoal_handle,
+				     pmadapter->pmlan_cmd_timer);
+
+	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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	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
+	}
+#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;
+	}
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode == MTRUE) {
+		pmadapter->hw_status = WlanHardwareStatusInitializing;
+		ret = wlan_get_hw_spec_complete(pmadapter);
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function udpate hw spec info to each interface
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+void
+wlan_update_hw_spec(IN 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;
+			}
+		}
+		if ((pmadapter->fw_bands & BAND_AN)
+			) {
+			pmadapter->adhoc_start_band = BAND_A | BAND_AN;
+			pmadapter->adhoc_11n_enabled = MTRUE;
+		} else
+			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_GN)
+		) {
+		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i])
+				pmadapter->priv[i]->adhoc_channel =
+					DEFAULT_AD_HOC_CHANNEL;
+		}
+		pmadapter->adhoc_11n_enabled = MTRUE;
+	} 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 =
+					DEFAULT_11N_TX_BF_CAP;
+		}
+	}
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i])
+			wlan_update_11ac_cap(pmadapter->priv[i]);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief  This function initializes firmware for interface
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_init_priv_fw(IN 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;
+	} 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;
+	ENTER();
+
+	if (!pmadapter) {
+		PRINTM(MERROR, "The adapter is NULL\n");
+		LEAVE();
+		return;
+	}
+
+	wlan_cancel_all_pending_cmd(pmadapter);
+	/* 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 (pmadapter->wakeup_fw_timer_is_set) {
+		/* Cancel wakeup card timer */
+		pcb->moal_stop_timer(pmadapter->pmoal_handle,
+				     pmadapter->pwakeup_fw_timer);
+		pmadapter->wakeup_fw_timer_is_set = MFALSE;
+	}
+	wlan_free_fw_cfp_tables(pmadapter);
+#ifdef STA_SUPPORT
+	PRINTM(MINFO, "Free ScanTable\n");
+	if (pmadapter->pscan_table) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pscan_table);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pscan_table);
+		pmadapter->pscan_table = MNULL;
+	}
+	if (pmadapter->pchan_stats) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pchan_stats);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pchan_stats);
+		pmadapter->pchan_stats = MNULL;
+	}
+	if (pmadapter->bcn_buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->bcn_buf);
+		pmadapter->bcn_buf = MNULL;
+	}
+#endif
+
+	wlan_11h_cleanup(pmadapter);
+
+	if (pmadapter->mp_regs_buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mp_regs_buf);
+		pmadapter->mp_regs_buf = MNULL;
+		pmadapter->mp_regs = MNULL;
+	}
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+	if (pmadapter->rx_buffer) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->rx_buffer);
+		pmadapter->rx_buffer = MNULL;
+		pmadapter->rx_buf = MNULL;
+	}
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	wlan_free_sdio_mpa_buffers(pmadapter);
+#ifdef DEBUG_LEVEL1
+	if (pmadapter->mpa_buf) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->mpa_buf);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->mpa_buf);
+		pmadapter->mpa_buf = MNULL;
+		pmadapter->mpa_buf_size = 0;
+	}
+#endif
+#endif
+	wlan_free_mlan_buffer(pmadapter, pmadapter->psleep_cfm);
+	pmadapter->psleep_cfm = MNULL;
+
+	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 */
+
+	wlan_delete_station_list(pmpriv);
+	LEAVE();
+}
+
+/**
+ *  @brief This function init interface based on pmadapter's bss_attr table
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+mlan_status
+wlan_init_interface(IN 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(pmadapter,
+					       &pmadapter->priv[i]->ops,
+					       mlan_ops[j],
+					       sizeof(mlan_operations));
+				}
+			}
+		}
+	}
+	/*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(IN pmlan_adapter pmadapter)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_hw_info info;
+	mlan_bss_tbl bss_tbl;
+
+	ENTER();
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode != MTRUE) {
+#endif
+		/* Check if hardware is ready */
+		if (pmadapter->hw_status != WlanHardwareStatusInitializing)
+			status = MLAN_STATUS_FAILURE;
+		else {
+			memset(pmadapter, &info, 0, sizeof(info));
+			info.fw_cap = pmadapter->fw_cap_info;
+			memset(pmadapter, &bss_tbl, 0, sizeof(bss_tbl));
+			memcpy(pmadapter, bss_tbl.bss_attr, pmadapter->bss_attr,
+			       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(pmadapter, pmadapter->bss_attr, bss_tbl.bss_attr,
+			       sizeof(mlan_bss_tbl));
+#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(IN pmlan_adapter pmadapter)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	/* Check if hardware is ready */
+	if (pmadapter->hw_status != WlanHardwareStatusReady)
+		status = MLAN_STATUS_FAILURE;
+
+	/* Reconfigure wmm parameter */
+	if (status == MLAN_STATUS_SUCCESS) {
+		wlan_prepare_cmd(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA),
+				 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(IN 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 100644
index 0000000..816801e
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_init.h
@@ -0,0 +1,90 @@
+/** @file mlan_init.h
+ *
+ *  @brief This file defines the FW initialization data
+ *  structures.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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 CMD7 */
+#define FW_CMD_7                0x00000007
+
+/** 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;
+} MLAN_PACK_END FWSyncHeader;
+
+#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); \
+	}
+#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 100644
index 0000000..8e30e80
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_ioctl.h
@@ -0,0 +1,4393 @@
+/** @file mlan_ioctl.h
+ *
+ *  @brief This file declares the IOCTL data structures and APIs.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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
+
+	/* 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,
+
+	/* 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_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,
+
+	/* 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,
+
+	/* 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,
+#if defined(DFS_TESTING_SUPPORT)
+	MLAN_OID_11H_DFS_TESTING = 0x00110003,
+#endif
+	MLAN_OID_11H_CHAN_REPORT_REQUEST = 0x00110004,
+	MLAN_OID_11H_CHAN_SWITCH_COUNT = 0x00110005,
+#ifdef DFS_TESTING_SUPPORT
+	MLAN_OID_11H_CHAN_NOP_INFO = 0x00110006,
+#endif
+
+	/* 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,
+
+	/* 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,
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	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,
+	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
+	MLAN_OID_MISC_MULTI_CHAN_CFG = 0x00200023,
+	MLAN_OID_MISC_MULTI_CHAN_POLICY = 0x00200024,
+#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_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_OPER_CLASS = 0x00200038,
+	MLAN_OID_MISC_PMIC_CFG = 0x00200039,
+	MLAN_OID_MISC_GET_TSF = 0x00200045,
+	MLAN_OID_MISC_GET_CHAN_REGION_CFG = 0x00200046,
+	MLAN_OID_MISC_OPER_CLASS_CHECK = 0x00200049,
+	MLAN_OID_MISC_DRCS_CFG = 0x00200050,
+
+	MLAN_OID_MISC_CWMODE_CTRL = 0x00200051,
+	MLAN_OID_MISC_DYN_BW = 0x00200053,
+	MLAN_OID_MISC_FW_DUMP_EVENT = 0x00200054,
+	MLAN_OID_MISC_ROBUSTCOEX = 0x00200056,
+	MLAN_OID_MISC_CFP_INFO = 0x00200060,
+	MLAN_OID_MISC_BOOT_SLEEP = 0x00200061,
+	MLAN_OID_MISC_ACS = 0x00200063,
+	MLAN_OID_MISC_GET_CHAN_TRPC_CFG = 0x00200070,
+	MLAN_OID_MISC_GET_REGIONPWR_CFG = 0x00200071,
+};
+
+/** 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
+};
+
+/** 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
+
+/** 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
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES      4
+
+/** Default number of probes to send on each channel */
+#define DEFAULT_PROBES  4
+
+/** MAX BG channel */
+#define MAX_BG_CHANNEL 14
+
+/**
+ *  @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;
+    /** 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;
+
+/** tx status event structure */
+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[0]; */
+} 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;
+
+/** 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;
+} 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;
+
+/** mlan_ssid_bssid  data structure for
+ *  MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS
+ */
+typedef struct _mlan_ssid_bssid {
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+    /** index in BSSID list, start from 1 */
+	t_u32 idx;
+    /** Receive signal strength in dBm */
+	t_s32 rssi;
+    /**channel*/
+	t_u16 channel;
+    /**mobility domain value*/
+	t_u16 ft_md;
+    /**ft capability*/
+	t_u8 ft_cap;
+    /**band*/
+	t_u16 bss_band;
+    /** channel flag */
+	t_u32 channel_flags;
+    /** host mlme flag*/
+	t_u8 host_mlme;
+    /** assoicate resp frame/ie from firmware */
+	mlan_ds_misc_assoc_rsp assoc_rsp;
+} mlan_ssid_bssid;
+
+/** 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   10
+/** 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           16
+
+/* 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
+
+/** 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;
+
+/** 5G band */
+#define BAND_CONFIG_5G        0x01
+/** 2.4 G band */
+#define BAND_CONFIG_2G        0x00
+/** 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;
+
+} mlan_uap_bss_param;
+
+/** mlan_uap_scan_channels */
+typedef struct _mlan_uap_scan_channels {
+    /** flag for remove nop channel*/
+	t_u8 remove_nop_channel;
+	/** num of removed channel */
+	t_u8 num_remvoed_channel;
+    /** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+    /** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+} mlan_uap_scan_channels;
+
+/** mlan_uap_oper_ctrl */
+typedef struct _mlan_uap_oper_ctrl {
+    /** control value
+      *  0: do nothing,
+      *  2: uap stops and restarts automaticaly
+     */
+	t_u16 ctrl_value;
+    /** channel opt
+      *  1: uap restart on default 2.4G/channel 6
+      *  2: uap restart on the band/channel configured by driver previously
+      *  3: uap restart on the band/channel specified by band_cfg and channel
+	*/
+	t_u16 chan_opt;
+    /** band cfg   0
+      *  0: 20Mhz  2: 40 Mhz  3: 80Mhz
+     */
+	t_u8 band_cfg;
+    /** channel */
+	t_u8 channel;
+} mlan_uap_oper_ctrl;
+
+/** mlan_uap_acs_scan */
+typedef struct _mlan_uap_acs_scan {
+	/** band */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 chan;
+} mlan_uap_acs_scan;
+
+/** station is authorized (802.1X) */
+#define STA_FLAG_AUTHORIZED     MBIT(1)
+/** Station is capable of receiving frames with short barker preamble */
+#define STA_FLAG_SHORT_PREAMBLE MBIT(2)
+/** station is WME/QoS capable */
+#define STA_FLAG_WME            MBIT(3)
+/** station uses management frame protection */
+#define STA_FLAG_MFP            MBIT(4)
+/** station is authenticated */
+#define STA_FLAG_AUTHENTICATED  MBIT(5)
+/** station is a TDLS peer */
+#define STA_FLAG_TDLS_PEER      MBIT(6)
+/** station is associated */
+#define STA_FLAG_ASSOCIATED     MBIT(7)
+/** mlan_ds_sta_info */
+typedef struct _mlan_ds_sta_info {
+    /** aid */
+	t_u16 aid;
+    /** peer_mac */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+    /** Listen Interval */
+	int listen_interval;
+    /** Capability Info */
+	t_u16 cap_info;
+    /** station flag */
+	t_u32 sta_flags;
+	/** tlv len */
+	t_u16 tlv_len;
+    /** tlv start */
+	t_u8 tlv[0];
+} 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 uap flag for MLAN_OID_BSS_START */
+		t_u8 host_based;
+	/** BSS param for AP mode for MLAN_OID_UAP_BSS_CONFIG */
+		mlan_uap_bss_param bss_config;
+	/** AP Wmm parameters for MLAN_OID_UAP_CFG_WMM_PARAM */
+		wmm_parameter_t ap_wmm_para;
+	/** ap scan channels for MLAN_OID_UAP_SCAN_CHANNELS*/
+		mlan_uap_scan_channels ap_scan_channels;
+	/** ap channel for MLAN_OID_UAP_CHANNEL*/
+		chan_band_info ap_channel;
+	/** ap operation control for MLAN_OID_UAP_OPER_CTRL*/
+		mlan_uap_oper_ctrl ap_oper_ctrl;
+	/** AP acs scan 	    MLAN_OID_UAP_ACS_SCAN */
+		mlan_uap_acs_scan ap_acs_scan;
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	/** BSS role for MLAN_OID_BSS_ROLE */
+		t_u8 bss_role;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	/** wifi direct mode for MLAN_OID_WIFI_DIRECT_MODE */
+		t_u16 wfd_mode;
+#endif
+#ifdef STA_SUPPORT
+	/** Listen interval for MLAN_OID_BSS_LISTEN_INTERVAL */
+		t_u16 listen_interval;
+	/** STA channel info for MLAN_OID_BSS_CHAN_INFO */
+		chan_band_info sta_channel;
+#endif
+#ifdef UAP_SUPPORT
+		/** STA info for MLAN_OID_UAP_ADD_STATION */
+		mlan_ds_sta_info sta_info;
+#endif
+	} param;
+} mlan_ds_bss, *pmlan_ds_bss;
+
+/* OTP Region info */
+typedef MLAN_PACK_START struct _otp_region_info {
+	t_u8 country_code[2];
+	t_u8 region_code;
+	t_u8 environment;
+	t_u16 force_reg:1;
+	t_u16 reserved:15;
+} MLAN_PACK_END otp_region_info_t;
+
+/** Type definition of mlan_ds_custom_reg_domain */
+typedef struct _mlan_ds_custom_reg_domain {
+	otp_region_info_t region;
+    /** num of 2g channels in custom_reg_domain */
+	t_u8 num_bg_chan;
+    /** num of 5g channels in custom_reg_domain */
+	t_u8 num_a_chan;
+    /** cfp table */
+	chan_freq_power_t cfp_tbl[0];
+} 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,
+};
+
+/** 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;
+    /** Ad-hoc channel bandwidth */
+	t_u32 adhoc_chan_bandwidth;
+    /** 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_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 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
+
+/** filt field param structure */
+struct filt_field_param {
+	/** Operation */
+	t_u8 operation;
+	/** Operand len */
+	t_u8 operand_len;
+	/** offset */
+	t_u16 offset;
+	/** Operand byte stream */
+	t_u8 operand_byte_stream[COALESCE_MAX_BYTESEQ];
+};
+
+/** coalesce rule structure */
+struct coalesce_rule {
+	/** max coalescing delay */
+	t_u16 max_coalescing_delay;
+	/** number of fields */
+	t_u8 num_of_fields;
+	/** packet type */
+	t_u8 pkt_type;
+	struct filt_field_param params[COALESCE_MAX_FILTERS];
+};
+
+/** coalesce configuration structure */
+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
+};
+
+/** Get stats org structure */
+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;
+} mlan_ds_get_stats, *pmlan_ds_get_stats;
+
+/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_uap_stats {
+    /** tkip mic failures */
+	t_u32 tkip_mic_failures;
+    /** ccmp decrypt errors */
+	t_u32 ccmp_decrypt_errors;
+    /** wep undecryptable count */
+	t_u32 wep_undecryptable_count;
+    /** wep icv error count */
+	t_u32 wep_icv_error_count;
+    /** decrypt failure count */
+	t_u32 decrypt_failure_count;
+    /** dot11 multicast tx count */
+	t_u32 mcast_tx_count;
+    /** dot11 failed count */
+	t_u32 failed_count;
+    /** dot11 retry count */
+	t_u32 retry_count;
+    /** dot11 multi retry count */
+	t_u32 multi_retry_count;
+    /** dot11 frame duplicate count */
+	t_u32 frame_dup_count;
+    /** dot11 rts success count */
+	t_u32 rts_success_count;
+    /** dot11 rts failure count */
+	t_u32 rts_failure_count;
+    /** dot11 ack failure count */
+	t_u32 ack_failure_count;
+    /** dot11 rx ragment count */
+	t_u32 rx_fragment_count;
+    /** dot11 mcast rx frame count */
+	t_u32 mcast_rx_frame_count;
+    /** dot11 fcs error count */
+	t_u32 fcs_error_count;
+    /** dot11 tx frame count */
+	t_u32 tx_frame_count;
+    /** dot11 rsna tkip cm invoked */
+	t_u32 rsna_tkip_cm_invoked;
+    /** dot11 rsna 4way handshake failures */
+	t_u32 rsna_4way_hshk_failures;
+} mlan_ds_uap_stats, *pmlan_ds_uap_stats;
+
+/** Mask of last beacon RSSI */
+#define BCN_RSSI_LAST_MASK              0x00000001
+/** Mask of average beacon RSSI */
+#define BCN_RSSI_AVG_MASK               0x00000002
+/** Mask of last data RSSI */
+#define DATA_RSSI_LAST_MASK             0x00000004
+/** Mask of average data RSSI */
+#define DATA_RSSI_AVG_MASK              0x00000008
+/** Mask of last beacon SNR */
+#define BCN_SNR_LAST_MASK               0x00000010
+/** Mask of average beacon SNR */
+#define BCN_SNR_AVG_MASK                0x00000020
+/** Mask of last data SNR */
+#define DATA_SNR_LAST_MASK              0x00000040
+/** Mask of average data SNR */
+#define DATA_SNR_AVG_MASK               0x00000080
+/** Mask of last beacon NF */
+#define BCN_NF_LAST_MASK                0x00000100
+/** Mask of average beacon NF */
+#define BCN_NF_AVG_MASK                 0x00000200
+/** Mask of last data NF */
+#define DATA_NF_LAST_MASK               0x00000400
+/** Mask of average data NF */
+#define DATA_NF_AVG_MASK                0x00000800
+/** Mask of all RSSI_INFO */
+#define ALL_RSSI_INFO_MASK              0x00000fff
+#define MAX_PATH_NUM                    3
+/** path A */
+#define PATH_A							0x01
+/** path B */
+#define PATH_B							0x02
+/** path AB */
+#define PATH_AB							0x03
+/** ALL the path */
+#define PATH_ALL						0
+/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */
+typedef struct _mlan_ds_get_signal {
+    /** Selector of get operation */
+	/*
+	 * Bit0:  Last Beacon RSSI,  Bit1:  Average Beacon RSSI,
+	 * Bit2:  Last Data RSSI,    Bit3:  Average Data RSSI,
+	 * Bit4:  Last Beacon SNR,   Bit5:  Average Beacon SNR,
+	 * Bit6:  Last Data SNR,     Bit7:  Average Data SNR,
+	 * Bit8:  Last Beacon NF,    Bit9:  Average Beacon NF,
+	 * Bit10: Last Data NF,      Bit11: Average Data NF
+	 *
+	 * Bit0: PATH A
+	 * Bit1: PATH B
+	 */
+	t_u16 selector;
+
+    /** RSSI */
+    /** RSSI of last beacon */
+	t_s16 bcn_rssi_last;
+    /** RSSI of beacon average */
+	t_s16 bcn_rssi_avg;
+    /** RSSI of last data packet */
+	t_s16 data_rssi_last;
+    /** RSSI of data packet average */
+	t_s16 data_rssi_avg;
+
+    /** SNR */
+    /** SNR of last beacon */
+	t_s16 bcn_snr_last;
+    /** SNR of beacon average */
+	t_s16 bcn_snr_avg;
+    /** SNR of last data packet */
+	t_s16 data_snr_last;
+    /** SNR of data packet average */
+	t_s16 data_snr_avg;
+
+    /** NF */
+    /** NF of last beacon */
+	t_s16 bcn_nf_last;
+    /** NF of beacon average */
+	t_s16 bcn_nf_avg;
+    /** NF of last data packet */
+	t_s16 data_nf_last;
+    /** NF of data packet average */
+	t_s16 data_nf_avg;
+} mlan_ds_get_signal, *pmlan_ds_get_signal;
+
+/** bit for 2.4 G antenna diversity */
+#define ANT_DIVERSITY_2G   MBIT(3)
+/** bit for 5 G antenna diversity */
+#define ANT_DIVERSITY_5G   MBIT(7)
+
+/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */
+typedef struct _mlan_fw_info {
+    /** Firmware version */
+	t_u32 fw_ver;
+    /** MAC address */
+	mlan_802_11_mac_addr mac_addr;
+    /** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+    /** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+    /** user's MCS setting */
+	t_u8 usr_dev_mcs_support;
+    /** 802.11ac device capabilities */
+	t_u32 hw_dot_11ac_dev_cap;
+    /** 802.11ac device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11ac_dev_cap_bg;
+    /** 802.11ac device Capabilities for 5GHz */
+	t_u32 usr_dot_11ac_dev_cap_a;
+    /** 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_u8 fw_bands;
+	/** region code */
+	t_u16 region_code;
+    /** 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;
+} mlan_fw_info, *pmlan_fw_info;
+
+/** Version string buffer length */
+#define MLAN_MAX_VER_STR_LEN    128
+
+/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */
+typedef struct _mlan_ver_ext {
+    /** Selected version string */
+	t_u32 version_str_sel;
+    /** Version string */
+	char version_str[MLAN_MAX_VER_STR_LEN];
+} mlan_ver_ext, *pmlan_ver_ext;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+    /** Extended Capabilities value */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit77: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 MaxAMSDU:2;	/* bit 63-bit 64 */
+	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 MaxAMSDU:2;	/* bit 63-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 rsvdBit77:1;	/* bit 77 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#endif
+
+/** ExtCap : TDLS prohibited */
+#define IS_EXTCAP_TDLS_PROHIBITED(ext_cap) (ext_cap.TDLSProhibited)
+/** ExtCap : TDLS channel switch prohibited */
+#define IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ext_cap) (ext_cap.TDLSChlSwitchProhib)
+
+/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */
+typedef struct _mlan_bss_info {
+    /** BSS mode */
+	t_u32 bss_mode;
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** Table index */
+	t_u32 scan_table_idx;
+    /** Channel */
+	t_u32 bss_chan;
+    /** Band */
+	t_u8 bss_band;
+    /** Region code */
+	t_u32 region_code;
+    /** Connection status */
+	t_u32 media_connected;
+    /** Radio on */
+	t_u32 radio_on;
+    /** Max power level in dBm */
+	t_s32 max_power_level;
+    /** Min power level in dBm */
+	t_s32 min_power_level;
+    /** Adhoc state */
+	t_u32 adhoc_state;
+    /** NF of last beacon */
+	t_s32 bcn_nf_last;
+    /** wep status */
+	t_u32 wep_status;
+    /** scan block status */
+	t_u8 scan_block;
+     /** Host Sleep configured flag */
+	t_u32 is_hs_configured;
+    /** Deep Sleep flag */
+	t_u32 is_deep_sleep;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+#ifdef STA_SUPPORT
+    /** Capability Info */
+	t_u16 capability_info;
+    /** Beacon Interval */
+	t_u16 beacon_interval;
+    /** Listen Interval */
+	t_u16 listen_interval;
+    /** Association Id  */
+	t_u16 assoc_id;
+    /** AP/Peer supported rates */
+	t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES];
+    /** extend capability for AP */
+	ExtCap_t ext_cap;
+#endif				/* STA_SUPPORT */
+    /** Mobility Domain ID */
+	t_u16 mdid;
+    /** FT Capability policy */
+	t_u8 ft_cap;
+    /** 11h active */
+	t_bool is_11h_active;
+    /** dfs check channel */
+	t_u8 dfs_check_channel;
+} mlan_bss_info, *pmlan_bss_info;
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID     8
+
+/** Max RX Win size */
+#define MAX_RX_WINSIZE  64
+
+/** rx_reorder_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** TA */
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+    /** Start window */
+	t_u32 start_win;
+    /** Window size */
+	t_u32 win_size;
+    /** amsdu flag */
+	t_u8 amsdu;
+    /** buffer status */
+	t_u32 buffer[MAX_RX_WINSIZE];
+} rx_reorder_tbl;
+
+/** tx_ba_stream_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** RA */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+    /** amsdu flag */
+	t_u8 amsdu;
+} tx_ba_stream_tbl;
+
+/** Debug command number */
+#define DBG_CMD_NUM	10
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** 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;
+
+/** 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;
+    /** Corresponds to is_hs_configured member of mlan_adapter */
+	t_u8 is_hs_configured;
+    /** Corresponds to hs_activated member of mlan_adapter */
+	t_u8 hs_activated;
+    /** Corresponds to pps_uapsd_mode member of mlan_adapter */
+	t_u16 pps_uapsd_mode;
+    /** Corresponds to sleep_period.period member of mlan_adapter */
+	t_u16 sleep_pd;
+    /** Corresponds to wmm_qosinfo member of mlan_private */
+	t_u8 qos_cfg;
+    /** Corresponds to tx_lock_flag member of mlan_adapter */
+	t_u8 tx_lock_flag;
+    /** Corresponds to port_open member of mlan_private */
+	t_u8 port_open;
+    /** bypass pkt count */
+	t_u16 bypass_pkt_count;
+    /** Corresponds to scan_processing member of mlan_adapter */
+	t_u32 scan_processing;
+    /** Corresponds to mlan_processing member of mlan_adapter */
+	t_u32 mlan_processing;
+    /** Corresponds to main_lock_flag member of mlan_adapter */
+	t_u32 main_lock_flag;
+    /** Corresponds to main_process_cnt member of mlan_adapter */
+	t_u32 main_process_cnt;
+	/** Corresponds to delay_task_flag member of mlan_adapter */
+	t_u32 delay_task_flag;
+    /** mlan_rx_processing */
+	t_u32 mlan_rx_processing;
+    /** rx pkts queued */
+	t_u32 rx_pkts_queued;
+    /** Number of host to card command failures */
+	t_u32 num_cmd_host_to_card_failure;
+    /** Number of host to card sleep confirm failures */
+	t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+    /** Number of host to card Tx failures */
+	t_u32 num_tx_host_to_card_failure;
+    /** Number of allocate buffer failure */
+	t_u32 num_alloc_buffer_failure;
+	/** Number of pkt dropped */
+	t_u32 num_pkt_dropped;
+    /** 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;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** Number of packets tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+    /** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+	/** last recv wr_bitmap */
+	t_u32 last_recv_wr_bitmap;
+    /** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+    /** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+	/** last len for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+    /** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+    /** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** last mp_index */
+	t_u8 last_mp_index;
+    /** buffer for mp debug */
+	t_u8 *mpa_buf;
+    /** length info for mp buf size */
+	t_u32 mpa_buf_size;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** Number of packets rx aggr */
+	t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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 command failures */
+	t_u32 num_cons_cmd_assoc_failure;
+    /** Number of Tx timeouts */
+	t_u32 num_tx_timeout;
+    /** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+    /** Number of command timeouts */
+	t_u32 dbg_num_cmd_timeout;
+    /** Timeout command ID */
+	t_u16 timeout_cmd_id;
+    /** Timeout command action */
+	t_u16 timeout_cmd_act;
+    /** List of last command IDs */
+	t_u16 last_cmd_id[DBG_CMD_NUM];
+    /** List of last command actions */
+	t_u16 last_cmd_act[DBG_CMD_NUM];
+    /** Last command index */
+	t_u16 last_cmd_index;
+    /** List of last command response IDs */
+	t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+    /** Last command response index */
+	t_u16 last_cmd_resp_index;
+    /** List of last events */
+	t_u16 last_event[DBG_CMD_NUM];
+    /** Last event index */
+	t_u16 last_event_index;
+    /** Number of no free command node */
+	t_u16 num_no_cmd_node;
+    /** pending command id */
+	t_u16 pending_cmd;
+    /** time stamp for dnld last cmd */
+	t_u32 dnld_cmd_in_secs;
+    /** Corresponds to data_sent member of mlan_adapter */
+	t_u8 data_sent;
+    /** Corresponds to cmd_sent member of mlan_adapter */
+	t_u8 cmd_sent;
+    /** SDIO multiple port read bitmap */
+	t_u32 mp_rd_bitmap;
+    /** SDIO multiple port write bitmap */
+	t_u32 mp_wr_bitmap;
+    /** Current available port for read */
+	t_u8 curr_rd_port;
+    /** Current available port for write */
+	t_u8 curr_wr_port;
+    /** Corresponds to cmdresp_received member of mlan_adapter */
+	t_u8 cmd_resp_received;
+    /** Corresponds to event_received member of mlan_adapter */
+	t_u8 event_received;
+    /**  pendig tx pkts */
+	t_u32 tx_pkts_queued;
+#ifdef UAP_SUPPORT
+    /**  pending bridge pkts */
+	t_u16 num_bridge_pkts;
+    /**  dropped pkts */
+	t_u32 num_drop_pkts;
+#endif
+    /** FW hang report */
+	t_u8 fw_hang_report;
+    /** mlan_adapter pointer */
+	t_void *mlan_adapter;
+    /** mlan_adapter_size */
+	t_u32 mlan_adapter_size;
+    /** mlan_priv vector */
+	t_void *mlan_priv[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_size */
+	t_u32 mlan_priv_size[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_num */
+	t_u8 mlan_priv_num;
+} mlan_debug_info, *pmlan_debug_info;
+
+#ifdef UAP_SUPPORT
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS         MAX_STA_COUNT
+
+/** station info */
+typedef struct _sta_info {
+    /** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+    /** station bandmode */
+	t_u8 bandmode;
+    /** station stats */
+	sta_stats stats;
+} sta_info;
+
+/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */
+typedef struct _mlan_ds_sta_list {
+    /** station count */
+	t_u16 sta_count;
+    /** station list */
+	sta_info info[MAX_NUM_CLIENTS];
+} mlan_ds_sta_list, *pmlan_ds_sta_list;
+#endif
+
+/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */
+typedef struct _mlan_ds_get_info {
+    /** Sub-command */
+	t_u32 sub_command;
+
+    /** Status information parameter */
+	union {
+	/** Signal information for MLAN_OID_GET_SIGNAL */
+		mlan_ds_get_signal signal;
+		/** Signal path id for MLAN_OID_GET_SIGNAL_EXT */
+		t_u16 path_id;
+	/** Signal information for MLAN_OID_GET_SIGNAL_EXT */
+		mlan_ds_get_signal signal_ext[MAX_PATH_NUM];
+	/** Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_get_stats stats;
+	/** 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_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_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,
+};
+
+/** 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
+/** PMK length */
+#define MLAN_PMK_HEXSTR_LENGTH        64
+/* A few details needed for WEP (Wireless Equivalent Privacy) */
+/** 104 bits */
+#define MAX_WEP_KEY_SIZE	13
+/** 40 bits RC4 - WEP */
+#define MIN_WEP_KEY_SIZE	5
+/** packet number size */
+#define PN_SIZE			16
+/** max seq size of wpa/wpa2 key */
+#define SEQ_MAX_SIZE        8
+
+/** key flag for tx_seq */
+#define KEY_FLAG_TX_SEQ_VALID	0x00000001
+/** key flag for rx_seq */
+#define KEY_FLAG_RX_SEQ_VALID	0x00000002
+/** key flag for group key */
+#define KEY_FLAG_GROUP_KEY      0x00000004
+/** key flag for tx */
+#define KEY_FLAG_SET_TX_KEY     0x00000008
+/** key flag for mcast IGTK */
+#define KEY_FLAG_AES_MCAST_IGTK 0x00000010
+/** key flag for remove key */
+#define KEY_FLAG_REMOVE_KEY     0x80000000
+/** key flag for GCMP */
+#define KEY_FLAG_GCMP           0x00000020
+/** key flag for GCMP_256 */
+#define KEY_FLAG_GCMP_256           0x00000040
+/** key flag for CCMP_256 */
+#define KEY_FLAG_CCMP_256           0x00000080
+/** Type definition of mlan_ds_encrypt_key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */
+typedef struct _mlan_ds_encrypt_key {
+    /** Key disabled, all other fields will be
+     *  ignore when this flag set to MTRUE
+     */
+	t_u32 key_disable;
+    /** key removed flag, when this flag is set
+     *  to MTRUE, only key_index will be check
+     */
+	t_u32 key_remove;
+    /** Key index, used as current tx key index
+     *  when is_current_wep_key is set to MTRUE
+     */
+	t_u32 key_index;
+    /** Current Tx key flag */
+	t_u32 is_current_wep_key;
+    /** Key length */
+	t_u32 key_len;
+    /** Key */
+	t_u8 key_material[MLAN_MAX_KEY_LENGTH];
+    /** mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+    /** wapi key flag */
+	t_u32 is_wapi_key;
+    /** Initial packet number */
+	t_u8 pn[PN_SIZE];
+    /** key flags */
+	t_u32 key_flags;
+} mlan_ds_encrypt_key, *pmlan_ds_encrypt_key;
+
+/** Type definition of mlan_passphrase_t */
+typedef struct _mlan_passphrase_t {
+    /** Length of passphrase */
+	t_u32 passphrase_len;
+    /** Passphrase */
+	t_u8 passphrase[MLAN_MAX_PASSPHRASE_LENGTH];
+} mlan_passphrase_t;
+
+/** Type 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;
+	/** 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;
+
+/*-----------------------------------------------------------------*/
+/** 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_AUTO = 0xFF,
+};
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE   18
+
+/** 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;
+} 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;
+	} param;
+} mlan_ds_power_cfg, *pmlan_ds_power_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;
+	} 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;
+
+/** 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,
+};
+
+/** 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 */
+/*-----------------------------------------------------------------*/
+#if defined(DFS_TESTING_SUPPORT)
+/** 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;
+} 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;
+#endif
+
+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;
+
+/** 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;
+#if defined(DFS_TESTING_SUPPORT)
+	/** 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;
+#endif
+		mlan_ds_11h_chan_rep_req chan_rpt_req;
+		t_s8 cs_count;
+	} param;
+} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Miscellaneous Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** 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;
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** 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;
+
+/** 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;
+
+/* 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_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;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** flag for NOA */
+#define WIFI_DIRECT_NOA         1
+/** flag for OPP_PS */
+#define WIFI_DIRECT_OPP_PS      2
+/** Type definition of mlan_ds_wifi_direct_config
+ *  for MLAN_OID_MISC_WIFI_DIRECT_CONFIG
+ */
+typedef struct _mlan_ds_wifi_direct_config {
+    /** flags for NOA/OPP_PS */
+	t_u8 flags;
+     /** NoA enable/disable */
+	t_u8 noa_enable;
+    /** index */
+	t_u16 index;
+    /** NoA count */
+	t_u8 noa_count;
+    /** NoA duration */
+	t_u32 noa_duration;
+    /** NoA interval */
+	t_u32 noa_interval;
+    /** opp ps enable/disable */
+	t_u8 opp_ps_enable;
+    /** CT window value */
+	t_u8 ct_window;
+} mlan_ds_wifi_direct_config;
+#endif
+
+#if defined(STA_SUPPORT)
+/** mlan_ds_misc_pmfcfg structure */
+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
+
+/** mlan_ds_multi_chan_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_multi_chan_cfg {
+    /** Channel Time */
+	t_u32 channel_time;
+    /** Buffer Weight */
+	t_u8 buffer_weight;
+    /** tlv len */
+	t_u16 tlv_len;
+    /** TLV buffer */
+	t_u8 tlv_buf[0];
+} MLAN_PACK_END mlan_ds_multi_chan_cfg;
+
+/** mlan_ds_drcs_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_drcs_cfg {
+    /** Channel Index*/
+	t_u16 chan_idx;
+    /** Channel time (in TU) for chan_idx */
+	t_u8 chantime;
+    /** Channel swith time (in TU) for chan_idx */
+	t_u8 switchtime;
+    /** Undoze time (in TU) for chan_idx */
+	t_u8 undozetime;
+    /** Rx traffic control scheme when channel switch*/
+    /** only valid for GC/STA interface*/
+	t_u8 mode;
+} MLAN_PACK_END mlan_ds_drcs_cfg;
+
+/**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
+
+/** mlan_ds_misc_dfs_repeater structure */
+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
+
+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;
+
+/** 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;
+
+/** channel statictics */
+typedef struct _ChStat_t {
+    /** channle number */
+	t_u8 chan_num;
+    /** total network */
+	t_u16 total_networks;
+    /** busy duration */
+	t_u16 cca_busy_duration;
+} ChStat_t, *pChStat_t;
+
+#define MAX_CH_STATS    MAX_BG_CHANNEL
+/** Type definition of mlan_acs_scan */
+typedef struct _mlan_ds_misc_acs {
+    /** Best Channel Number */
+	t_u8 best_ch;
+    /** Scan channel gap */
+	t_u16 scan_chan_gap;
+    /** Channel Statistics Number */
+	t_u8 ch_stats_num;
+    /** Channel Statistics */
+	ChStat_t ch_stats[MAX_CH_STATS];
+} mlan_ds_misc_acs, *pmlan_ds_misc_acs;
+
+/** 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;
+
+typedef struct _mlan_ds_misc_chnrgpwr_cfg {
+    /** length */
+	t_u16 length;
+    /** chnrgpwr buf */
+	t_u8 chnrgpwr_buf[2048];
+} mlan_ds_misc_chnrgpwr_cfg;
+
+/** 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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;
+	/** 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;
+	/** Tx control */
+		t_u32 tx_control;
+#if defined(STA_SUPPORT)
+		mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+	/** Multi-channel config for MLAN_OID_MISC_MULTI_CHAN_CFG */
+		mlan_ds_multi_chan_cfg multi_chan_cfg;
+	/** Multi-channel policy for MLAN_OID_MISC_MULTI_CHAN_POLICY */
+		t_u16 multi_chan_policy;
+	/** channel drcs time slicing config for MLAN_OID_MISC_DRCS_CFG */
+		mlan_ds_drcs_cfg drcs_cfg[2];
+#ifdef WIFI_DIRECT_SUPPORT
+		mlan_ds_wifi_direct_config p2p_config;
+#endif
+		mlan_ds_coalesce_cfg coalesce_cfg;
+		t_u8 low_pwr_mode;
+		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;
+	/** Bandwidth Channel operation */
+		mlan_ds_bw_chan_oper bw_chan_oper;
+    /** misc tsf */
+		t_u64 misc_tsf;
+    /** Custom regulatory domain */
+		mlan_ds_custom_reg_domain custom_reg_domain;
+		mlan_ds_misc_robustcoex_params robustcoexparams;
+    /** boot sleep enable or disable */
+		t_u16 boot_sleep;
+    /** ACS */
+		mlan_ds_misc_acs acs;
+		mlan_ds_misc_chan_trpc_cfg trpc_cfg;
+		mlan_ds_misc_chnrgpwr_cfg rgchnpwr_cfg;
+	} 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 100644
index 0000000..f93a7b5
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_join.c
@@ -0,0 +1,2618 @@
+/** @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 (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_11h.h"
+/********************************************************
+			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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, priv->gen_ie_buf,
+		       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(MrvlIEtypesHeader_t));
+		memcpy(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, ie,
+		       ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_t));
+
+		/* Increment the return size and the return buffer pointer param */
+		*ppbuffer += ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_t);
+		ret_len += ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_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(pmriv->adapter, *ppbuffer, &tsf_tlv, 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(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val));
+	*ppbuffer += sizeof(tsf_val);
+
+	memcpy(pmriv->adapter, &tsf_val, pbss_desc->time_stamp,
+	       sizeof(tsf_val));
+
+	PRINTM(MINFO, "ASSOC: TSF offset calc: %016llx - %016llx\n",
+	       tsf_val, pbss_desc->network_tsf);
+
+	memcpy(pmriv->adapter, *ppbuffer, &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(IN mlan_private *pmpriv,
+		      IN t_u8 *rate1,
+		      IN t_u32 rate1_size, IN t_u8 *rate2, IN 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(pmpriv->adapter, tmp, rate1, 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(IN mlan_private *pmpriv,
+			      IN BSSDescriptor_t *pbss_desc,
+			      OUT t_u8 *pout_rates, OUT t_u32 *pout_rates_size)
+{
+	t_u8 card_rates[WLAN_SUPPORTED_RATES];
+	t_u32 card_rates_size = 0;
+	ENTER();
+	/* Copy AP supported rates */
+	memcpy(pmpriv->adapter, pout_rates, pbss_desc->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(IN mlan_private *pmpriv,
+			   IN 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(pmpriv->adapter, &new_tsf_base, 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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, priv->wapi_ie,
+		       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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, &priv->osen_ie[2],
+		       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;
+}
+
+/********************************************************
+				Global Functions
+********************************************************/
+/**
+ *  @brief This function updates RSN IE in the association request.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @param ptlv_rsn_ie       A pointer to rsn_ie TLV
+ */
+int
+wlan_update_rsn_ie(mlan_private *pmpriv, MrvlIEtypes_RsnParamSet_t *ptlv_rsn_ie)
+{
+	t_u16 *prsn_cap;
+	t_u16 *ptr;
+	t_u16 *akm_suite_count_ptr;
+	t_u16 pmf_mask = 0x00;
+	t_u8 *temp;
+	t_u16 pairwise_cipher_count = 0;
+	t_u16 akm_suite_count = 0;
+	t_u16 temp_akm_suite_count = 0;
+	int found = 0;
+	t_u8 sha_256_oui[4] = { 0x00, 0x0f, 0xac, 0x06 };
+	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 (!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(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)),
+			       sha_256_oui, AKM_SUITE_LEN);
+			/* Shift remaining bytes of RSN IE after this */
+			memmove(pmadapter,
+				ptlv_rsn_ie->rsn_ie + (sizeof(t_u16) +
+						       4 * sizeof(t_u8)
+						       + sizeof(t_u16) +
+						       pairwise_cipher_count *
+						       PAIRWISE_CIPHER_SUITE_LEN
+						       + sizeof(t_u16) +
+						       AKM_SUITE_LEN),
+				ptlv_rsn_ie->rsn_ie + (sizeof(t_u16) +
+						       4 * sizeof(t_u8) +
+						       sizeof(t_u16) +
+						       pairwise_cipher_count *
+						       PAIRWISE_CIPHER_SUITE_LEN
+						       + sizeof(t_u16) +
+						       akm_suite_count *
+						       AKM_SUITE_LEN),
+				ptlv_rsn_ie->header.len - (sizeof(t_u16) +
+							   4 * sizeof(t_u8) +
+							   sizeof(t_u16) +
+							   pairwise_cipher_count
+							   *
+							   PAIRWISE_CIPHER_SUITE_LEN
+							   + sizeof(t_u16) +
+							   akm_suite_count *
+							   AKM_SUITE_LEN));
+			ptlv_rsn_ie->header.len =
+				ptlv_rsn_ie->header.len - (akm_suite_count -
+							   1) * AKM_SUITE_LEN;
+			/* Update akm suite count */
+			akm_suite_count = 1;
+			*akm_suite_count_ptr = akm_suite_count;
+		}
+	}
+	ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8)
+			+ sizeof(t_u16) +
+			pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
+			sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN);
+	prsn_cap = ptr;
+
+	ap_mfpc = ((*prsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
+	ap_mfpr = ((*prsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
+
+	if ((!ap_mfpc && !ap_mfpr && pmpriv->pmfcfg.mfpr)
+	    || ((!ap_mfpc) && ap_mfpr)
+	    || (ap_mfpc && ap_mfpr && (!pmpriv->pmfcfg.mfpc))
+		) {
+		PRINTM(MERROR,
+		       "Mismatch in PMF config of STA and AP, can't associate to AP\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if ((pmpriv->pmfcfg.mfpr && pmpriv->pmfcfg.mfpc) || pmpriv->pmfcfg.mfpc) {
+		*prsn_cap |= PMF_MASK;
+		*prsn_cap &= pmf_mask;
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief This function is to find FT AKM in RSN.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @param rsn_ie       A pointer to rsn_ie
+ *
+ */
+t_u8
+wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie)
+{
+	t_u8 *temp;
+	t_u16 count;
+	t_u16 pairwise_cipher_count = 0;
+	t_u16 akm_suite_count = 0;
+	t_u8 found = 0;
+	t_u8 rsn_ft_1x_oui[4] = { 0x00, 0x0f, 0xac, 0x03 };
+	t_u8 rsn_ft_psk_oui[4] = { 0x00, 0x0f, 0xac, 0x04 };
+	t_u8 rsn_ft_sae_oui[4] = { 0x00, 0x0f, 0xac, 0x09 };
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (!rsn_ie)
+		goto done;
+
+	if (rsn_ie[0] != RSN_IE)
+		goto done;
+
+	/*  2 bytes header + 2 bytes version + 4 bytes group_cipher_suite +
+	 *  2 bytes pairwise_cipher_count + pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN (4) +
+	 *  2 bytes akm_suite_count + akm_suite_count * AKM_SUITE_LEN (4)
+	 */
+	count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8));
+	pairwise_cipher_count = wlan_le16_to_cpu(count);
+	count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8)
+			   + sizeof(t_u16) + pairwise_cipher_count * 4);
+	akm_suite_count = wlan_le16_to_cpu(count);
+	temp = (t_u8 *)(rsn_ie + 2 + sizeof(t_u16) + 4 * sizeof(t_u8)
+			+ sizeof(t_u16) + pairwise_cipher_count
+			* 4 + sizeof(t_u16));
+
+	while (akm_suite_count) {
+		if (!memcmp
+		    (pmadapter, temp, rsn_ft_1x_oui, sizeof(rsn_ft_1x_oui)) ||
+		    !memcmp(pmadapter, temp, rsn_ft_psk_oui,
+			    sizeof(rsn_ft_psk_oui)) ||
+		    !memcmp(pmadapter, temp, rsn_ft_sae_oui,
+			    sizeof(rsn_ft_sae_oui))) {
+			found = 1;
+			break;
+		}
+		temp += 4;
+		akm_suite_count--;
+	}
+
+done:
+	LEAVE();
+	return found;
+}
+
+/**
+ *  @brief This function is to find specific IE.
+ *
+ *  @param ie           A pointer to ie buffer
+ *  @param ie_len    Length of ie buffer
+ *  @param ie_type  Type of ie that wants to be found in ie buffer
+ *
+ *  @return     MFALSE if not found; MTURE if found
+ */
+t_u8
+wlan_find_ie(t_u8 *ie, t_u8 ie_len, t_u8 ie_type)
+{
+	IEEEtypes_Header_t *pheader = MNULL;
+	t_u8 *pos = MNULL;
+	t_s8 ret_len;
+	t_u8 ret = MFALSE;
+
+	ENTER();
+
+	pos = (t_u8 *)ie;
+	ret_len = ie_len;
+	while (ret_len >= 2) {
+		pheader = (IEEEtypes_Header_t *)pos;
+		if (pheader->len + sizeof(IEEEtypes_Header_t) > ret_len) {
+			PRINTM(MMSG, "invalid IE length = %d left len %d\n",
+			       pheader->len, ret_len);
+			break;
+		}
+		if (pheader->element_id == ie_type) {
+			ret = MTRUE;
+			break;
+		}
+		ret_len -= pheader->len + sizeof(IEEEtypes_Header_t);
+		pos += pheader->len + sizeof(IEEEtypes_Header_t);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of association.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer cast of BSSDescriptor_t from the
+ *                        scan table to assoc
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_802_11_associate(IN mlan_private *pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_ASSOCIATE *passo = &cmd->params.associate;
+	BSSDescriptor_t *pbss_desc;
+	MrvlIEtypes_SsIdParamSet_t *pssid_tlv;
+	MrvlIEtypes_PhyParamSet_t *pphy_tlv;
+	MrvlIEtypes_SsParamSet_t *pss_tlv;
+	MrvlIEtypes_RatesParamSet_t *prates_tlv;
+	MrvlIEtypes_AuthType_t *pauth_tlv;
+	MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
+	WLAN_802_11_RATES rates;
+	t_u32 rates_size;
+	t_u16 tmp_cap;
+	t_u8 *pos;
+	t_u8 ft_akm = 0;
+	t_u8 oper_class;
+	t_u8 oper_class_flag = MFALSE;
+	MrvlIEtypes_HostMlme_t *host_mlme_tlv = MNULL;
+
+	ENTER();
+
+	pbss_desc = (BSSDescriptor_t *)pdata_buf;
+	pos = (t_u8 *)passo;
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
+
+	/* Save so we know which BSS Desc to use in the response handler */
+	pmpriv->pattempted_bss_desc = pbss_desc;
+
+	/* clear assoc_rsp_size */
+	pmpriv->assoc_rsp_size = 0;
+
+	memcpy(pmadapter, passo->peer_sta_addr,
+	       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(pmadapter, pssid_tlv->ssid, pbss_desc->ssid.ssid,
+	       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(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));
+	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(pmadapter, &pmpriv->curr_bss_params.data_rates, rates,
+	       rates_size);
+
+	/* 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(pmadapter, prates_tlv->rates, rates, 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
+			pauth_tlv->auth_type =
+				wlan_cpu_to_le16(MLAN_AUTH_MODE_OPEN);
+		pos += sizeof(pauth_tlv->header) + pauth_tlv->header.len;
+		pauth_tlv->header.len = wlan_cpu_to_le16(pauth_tlv->header.len);
+	}
+
+	if (IS_SUPPORT_MULTI_BANDS(pmadapter)
+	    && (pbss_desc->bss_band & pmpriv->config_bands)
+	    && !(ISSUPP_11NENABLED(pmadapter->fw_cap_info)
+		 && (!pbss_desc->disable_11n)
+		 && (pmpriv->config_bands & BAND_GN
+		     || pmpriv->config_bands & BAND_AN)
+		 && (pbss_desc->pht_cap)
+	    )
+		) {
+		/* Append a channel TLV for the channel the attempted AP was found on */
+		pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
+		pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		pchan_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
+
+		memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
+		       sizeof(ChanScanParamSet_t));
+		pchan_tlv->chan_scan_param[0].chan_number =
+			(pbss_desc->phy_param_set.ds_param_set.current_chan);
+		PRINTM(MINFO, "Assoc: TLV Chan = %d\n",
+		       pchan_tlv->chan_scan_param[0].chan_number);
+
+		pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
+			wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
+
+		PRINTM(MINFO, "Assoc: TLV Bandcfg = %x\n",
+		       pchan_tlv->chan_scan_param[0].bandcfg);
+		pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+	}
+	if (!pmpriv->wps.session_enable) {
+		if ((pmpriv->sec_info.wpa_enabled
+		     || pmpriv->sec_info.wpa2_enabled)) {
+			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+			/* WPA_IE or RSN_IE */
+			prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
+			prsn_ie_tlv->header.type =
+				prsn_ie_tlv->header.type & 0x00FF;
+			prsn_ie_tlv->header.type =
+				wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+			prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
+			prsn_ie_tlv->header.len =
+				prsn_ie_tlv->header.len & 0x00FF;
+			if (prsn_ie_tlv->header.len <=
+			    (sizeof(pmpriv->wpa_ie) - 2))
+				memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
+				       &pmpriv->wpa_ie[2],
+				       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);
+		} 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(pmadapter, prsn_ie_tlv->rsn_ie,
+					       &((*(pbss_desc->pwpa_ie)).
+						 vend_hdr.oui[0]),
+					       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(pmadapter, prsn_ie_tlv->rsn_ie,
+					       &((*(pbss_desc->prsn_ie)).
+						 data[0])
+					       , 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, &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);
+
+	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 (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(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+	       sizeof(passo->cap_info));
+
+	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(pmadapter, &passo->cap_info, &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(IN mlan_private *pmpriv,
+			  IN HostCmd_DS_COMMAND *resp, IN 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_ds_bss *bss;
+	ENTER();
+
+	if (pmpriv->curr_bss_params.host_mlme)
+		passoc_rsp =
+			(IEEEtypes_AssocRsp_t *)((t_u8 *)(&resp->params) +
+						 sizeof(IEEEtypes_MgmtHdr_t));
+	else
+		passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params;
+	passoc_rsp->status_code = wlan_le16_to_cpu(passoc_rsp->status_code);
+	if (pmpriv->media_connected == MTRUE)
+		memcpy(pmpriv->adapter, cur_mac,
+		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		       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(pmpriv->adapter, pmpriv->assoc_rsp_buf, &resp->params,
+	       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(pmpriv->adapter,
+		       bss->param.ssid_bssid.assoc_rsp.assoc_resp_buf,
+		       pmpriv->assoc_rsp_buf, pmpriv->assoc_rsp_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 (pmpriv->port_open)
+				pmpriv->adapter->dbg.num_cons_cmd_assoc_failure = 0;
+			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_cmd_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));
+
+		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(pmpriv->adapter, &pmpriv->ext_cap, &pmpriv->def_ext_cap,
+	       sizeof(pmpriv->ext_cap));
+	/* Make a copy of current BSSID descriptor */
+	memcpy(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+	       pbss_desc, 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->amsdu_rx_cnt = 0;
+	pmpriv->amsdu_tx_cnt = 0;
+	pmpriv->msdu_in_rx_amsdu_cnt = 0;
+	pmpriv->msdu_in_tx_amsdu_cnt = 0;
+	pmpriv->rxpd_rate = 0;
+	pmpriv->rxpd_rate_info = 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++;
+
+	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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+	       (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	/* 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) {
+		/* We are in Open/WEP mode, open port immediately */
+		if (pmpriv->port_ctrl_mode == MTRUE) {
+			pmpriv->port_open = MTRUE;
+			pmpriv->adapter->dbg.num_cons_cmd_assoc_failure = 0;
+			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)
+		pmpriv->adapter->scan_block = MTRUE;
+
+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(IN mlan_private *pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd, IN 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;
+	MrvlIETypes_HTCap_t *pht_cap;
+	MrvlIETypes_HTInfo_t *pht_info;
+	t_u32 rx_mcs_supp = 0;
+	MrvlIETypes_VHTCap_t *pvht_cap = MNULL;
+	MrvlIETypes_VHTOprat_t *pvht_op = MNULL;
+	t_u16 mcs_map_user = 0;
+	/* 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(pmadapter, padhoc_start->ssid,
+	       ((mlan_802_11_ssid *)pdata_buf)->ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len));
+
+	PRINTM(MINFO, "ADHOC_S_CMD: SSID = %s\n", padhoc_start->ssid);
+
+	memset(pmadapter, pbss_desc->ssid.ssid, 0, MLAN_MAX_SSID_LENGTH);
+	memcpy(pmadapter, pbss_desc->ssid.ssid,
+	       ((mlan_802_11_ssid *)pdata_buf)->ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len));
+
+	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(pmadapter, &pbss_desc->phy_param_set,
+	       &padhoc_start->phy_param_set, 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(pmadapter, &pbss_desc->ss_param_set,
+	       &padhoc_start->ss_param_set, 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(pmadapter, &pmpriv->curr_bss_params.data_rates,
+	       &padhoc_start->DataRate, pmpriv->curr_bss_params.num_of_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);
+		if (pmadapter->adhoc_start_band & BAND_GN
+		    || pmadapter->adhoc_start_band & BAND_AN
+		    || pmadapter->adhoc_start_band & BAND_GAC
+		    || pmadapter->adhoc_start_band & BAND_AAC) {
+			if (pmadapter->chan_bandwidth == CHANNEL_BW_40MHZ_ABOVE) {
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chan2Offset = SEC_CHAN_ABOVE;
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chanWidth = CHAN_BW_40MHZ;
+			} else if (pmadapter->chan_bandwidth ==
+				   CHANNEL_BW_40MHZ_BELOW) {
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chan2Offset = SEC_CHAN_BELOW;
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chanWidth = CHAN_BW_40MHZ;
+			} else if (pmadapter->chan_bandwidth ==
+				   CHANNEL_BW_80MHZ) {
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chanWidth = CHAN_BW_80MHZ;
+			}
+		}
+		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(pmadapter, pmpriv->wpa_ie, wpa_ie, sizeof(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(pmadapter, prsn_ie_tlv->rsn_ie,
+			       &pmpriv->wpa_ie[2], 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);
+	}
+
+	if (pmadapter->adhoc_11n_enabled == MTRUE) {
+		{
+			pht_cap = (MrvlIETypes_HTCap_t *)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);
+			rx_mcs_supp =
+				GET_RXMCSSUPP(pmpriv->usr_dev_mcs_support);
+			/* Set MCS for 1x1/2x2 */
+			memset(pmadapter,
+			       (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
+			       rx_mcs_supp);
+			wlan_fill_ht_cap_tlv(pmpriv, pht_cap,
+					     pmpriv->curr_bss_params.band,
+					     MTRUE);
+			HEXDUMP("ADHOC_START: HT_CAPABILITIES IE",
+				(t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
+			pos += sizeof(MrvlIETypes_HTCap_t);
+			cmd_append_size += sizeof(MrvlIETypes_HTCap_t);
+			pht_cap->header.len =
+				wlan_cpu_to_le16(pht_cap->header.len);
+		}
+		{
+			pht_info = (MrvlIETypes_HTInfo_t *)pos;
+			memset(pmadapter, pht_info, 0,
+			       sizeof(MrvlIETypes_HTInfo_t));
+			pht_info->header.type = wlan_cpu_to_le16(HT_OPERATION);
+			pht_info->header.len = sizeof(HTInfo_t);
+			pht_info->ht_info.pri_chan =
+				(t_u8)pmpriv->curr_bss_params.bss_descriptor.
+				channel;
+			if ((pmadapter->chan_bandwidth ==
+			     CHANNEL_BW_40MHZ_ABOVE) ||
+			    (pmadapter->chan_bandwidth ==
+			     CHANNEL_BW_40MHZ_BELOW)) {
+				pht_info->ht_info.field2 =
+					pmadapter->chan_bandwidth;
+				SET_CHANWIDTH40(pht_info->ht_info.field2);
+			}
+			if (pmadapter->chan_bandwidth == CHANNEL_BW_80MHZ) {
+				pht_info->ht_info.field2 =
+					wlan_get_second_channel_offset
+					(pht_info->ht_info.pri_chan);
+				pht_info->ht_info.field2 |= MBIT(2);
+			}
+			pht_info->ht_info.field3 =
+				wlan_cpu_to_le16(NON_GREENFIELD_STAS);
+			pht_info->ht_info.basic_mcs_set[0] = 0xff;
+			HEXDUMP("ADHOC_START: HT_INFORMATION IE",
+				(t_u8 *)pht_info, sizeof(MrvlIETypes_HTInfo_t));
+			pos += sizeof(MrvlIETypes_HTInfo_t);
+			cmd_append_size += sizeof(MrvlIETypes_HTInfo_t);
+			pht_info->header.len =
+				wlan_cpu_to_le16(pht_info->header.len);
+		}
+		if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info)
+		    && (pmadapter->adhoc_start_band & BAND_GAC
+			|| pmadapter->adhoc_start_band & BAND_AAC)) {
+			/* VHT Capabilities IE */
+			pvht_cap = (MrvlIETypes_VHTCap_t *)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);
+			/* rx MCS Map */
+			mcs_map_user =
+				GET_DEVRXMCSMAP(pmpriv->
+						usr_dot_11ac_mcs_support);
+			pvht_cap->vht_cap.mcs_sets.rx_mcs_map =
+				wlan_cpu_to_le16(mcs_map_user);
+			/* rx highest rate */
+			pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+				wlan_convert_mcsmap_to_maxrate(pmpriv,
+							       pmadapter->
+							       adhoc_start_band,
+							       mcs_map_user);
+			pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+				wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.
+						 rx_max_rate);
+			/* tx MCS map */
+			mcs_map_user =
+				GET_DEVTXMCSMAP(pmpriv->
+						usr_dot_11ac_mcs_support);
+			pvht_cap->vht_cap.mcs_sets.tx_mcs_map =
+				wlan_cpu_to_le16(mcs_map_user);
+			/* tx highest rate */
+			pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+				wlan_convert_mcsmap_to_maxrate(pmpriv,
+							       pmadapter->
+							       adhoc_start_band,
+							       mcs_map_user);
+			pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+				wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.
+						 tx_max_rate);
+
+			wlan_fill_vht_cap_tlv(pmpriv, pvht_cap,
+					      pmadapter->adhoc_start_band,
+					      MTRUE);
+			HEXDUMP("VHT_CAPABILITIES IE", (t_u8 *)pvht_cap,
+				sizeof(MrvlIETypes_VHTCap_t));
+			pos += sizeof(MrvlIETypes_VHTCap_t);
+			cmd_append_size += sizeof(MrvlIETypes_VHTCap_t);
+			pvht_cap->header.len =
+				wlan_cpu_to_le16(pvht_cap->header.len);
+			/* VHT Operation IE */
+			pvht_op = (MrvlIETypes_VHTOprat_t *)pos;
+			memset(pmadapter, pvht_op, 0,
+			       sizeof(MrvlIETypes_VHTOprat_t));
+			pvht_op->header.type = wlan_cpu_to_le16(VHT_OPERATION);
+			pvht_op->header.len = sizeof(MrvlIETypes_VHTOprat_t) -
+				sizeof(MrvlIEtypesHeader_t);
+			if (pmadapter->chan_bandwidth == CHANNEL_BW_80MHZ) {
+				pvht_op->chan_width = VHT_OPER_CHWD_80MHZ;
+				/* central frequency */
+				pvht_op->chan_center_freq_1 =
+					wlan_get_center_freq_idx(pmpriv,
+								 pmadapter->
+								 adhoc_start_band,
+								 pmpriv->
+								 adhoc_channel,
+								 pmadapter->
+								 chan_bandwidth);
+			}
+			/* basic MCS (rx MCS Map) */
+			pvht_op->basic_MCS_map =
+				GET_DEVRXMCSMAP(pmpriv->
+						usr_dot_11ac_mcs_support);
+			pvht_op->basic_MCS_map =
+				wlan_cpu_to_le16(pvht_op->basic_MCS_map);
+
+			HEXDUMP("VHT_OPERATION IE", (t_u8 *)pvht_op,
+				sizeof(MrvlIETypes_VHTOprat_t));
+			pos += sizeof(MrvlIETypes_VHTOprat_t);
+			cmd_append_size += sizeof(MrvlIETypes_VHTOprat_t);
+			pvht_op->header.len =
+				wlan_cpu_to_le16(pvht_op->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(pmadapter, &tmp_cap, &padhoc_start->cap, sizeof(t_u16));
+
+	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(pmadapter, &padhoc_start->cap, &tmp_cap, sizeof(t_u16));
+
+	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(IN mlan_private *pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd, IN 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(pmadapter, &padhoc_join->bss_descriptor.bssid,
+	       &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH);
+
+	memcpy(pmadapter, &padhoc_join->bss_descriptor.ssid,
+	       &pbss_desc->ssid.ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH, pbss_desc->ssid.ssid_len));
+
+	memcpy(pmadapter, &padhoc_join->bss_descriptor.phy_param_set,
+	       &pbss_desc->phy_param_set, 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(pmadapter, &padhoc_join->bss_descriptor.ss_param_set,
+	       &pbss_desc->ss_param_set, 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(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+	       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(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
+	       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(pmadapter, padhoc_join->bss_descriptor.data_rates,
+	       pbss_desc->supported_rates, rates_size);
+
+	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(pmadapter, &pmpriv->curr_bss_params.data_rates,
+	       pbss_desc->supported_rates, rates_size);
+
+	/* 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(pmadapter, prsn_ie_tlv->rsn_ie,
+			       &pmpriv->wpa_ie[2], 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(pmadapter, prsn_ie_tlv->rsn_ie,
+				       &((*(pbss_desc->pwpa_ie)).vend_hdr.
+					 oui[0]), 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(pmadapter, prsn_ie_tlv->rsn_ie,
+				       &((*(pbss_desc->prsn_ie)).data[0])
+				       , 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 (ISSUPP_11NENABLED(pmadapter->fw_cap_info)
+	    && wlan_11n_bandconfig_allowed(pmpriv, pbss_desc->bss_band)
+		)
+		cmd_append_size +=
+			wlan_cmd_append_11n_tlv(pmpriv, pbss_desc, &pos);
+	if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info)
+	    && wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
+		cmd_append_size +=
+			wlan_cmd_append_11ac_tlv(pmpriv, pbss_desc, &pos);
+
+	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(pmadapter, &tmp_cap, &padhoc_join->bss_descriptor.cap,
+	       sizeof(IEEEtypes_CapInfo_t));
+	tmp_cap = wlan_cpu_to_le16(tmp_cap);
+
+	memcpy(pmadapter, &padhoc_join->bss_descriptor.cap,
+	       &tmp_cap, 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(IN mlan_private *pmpriv,
+		       IN HostCmd_DS_COMMAND *resp, IN 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(pmpriv->adapter, pbss_desc->mac_address,
+		       padhoc_start_result->bssid, 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(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+		       pbss_desc, sizeof(BSSDescriptor_t));
+
+		pmpriv->adhoc_state = ADHOC_JOINED;
+	}
+
+    /** process wmm ie */
+	if (ie_len >= sizeof(IEEEtypes_VendorHeader_t)) {
+		if ((pwmm_param_ie->vend_hdr.element_id == VENDOR_SPECIFIC_221)
+		    && !memcmp(pmadapter, pwmm_param_ie->vend_hdr.oui, wmm_oui,
+			       sizeof(wmm_oui)) &&
+		    (pwmm_param_ie->vend_hdr.len + 2 == ie_len)) {
+			DBG_HEXDUMP(MCMD_D, "WMM Param", (t_u8 *)pwmm_param_ie,
+				    ie_len);
+			memcpy(pmpriv->adapter,
+			       (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.
+			       wmm_ie, pwmm_param_ie,
+			       MIN(sizeof(IEEEtypes_WmmParameter_t),
+				   (pwmm_param_ie->vend_hdr.len + 2)));
+			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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+	       (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+	       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(IN mlan_private *pmpriv,
+	       IN t_void *pioctl_buf, IN 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(pmpriv->adapter, &current_bssid,
+	       &pmpriv->curr_bss_params.bss_descriptor.mac_address,
+	       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(IN mlan_private *pmpriv,
+		 IN t_void *pioctl_buf, IN 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(pmpriv->adapter, &pmpriv->adhoc_last_start_ssid,
+		       padhoc_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(IN mlan_private *pmpriv,
+		IN t_void *pioctl_buf, IN 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(IN mlan_private *pmpriv,
+		IN mlan_ioctl_req *pioctl_req,
+		IN 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(pmpriv->adapter, &local_param, deauth_param,
+		       sizeof(*deauth_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(pmpriv->adapter, local_param.mac_addr,
+				       (t_u8 *)&pmpriv->curr_bss_params.
+				       bss_descriptor.mac_address,
+				       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(IN 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 100644
index 0000000..4798c73
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_join.h
@@ -0,0 +1,40 @@
+/** @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 (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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 100644
index 0000000..1529107
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_main.h
@@ -0,0 +1,3701 @@
+/** @file mlan_main.h
+ *
+ *  @brief This file defines the private and adapter data
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    10/13/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_MAIN_H_
+#define _MLAN_MAIN_H_
+
+#ifdef DEBUG_LEVEL1
+extern t_void (*print_callback) (IN t_void *pmoal_handle,
+				 IN t_u32 level, IN char *pformat, IN ...
+	);
+
+extern mlan_status (*get_sys_time_callback) (IN t_void *pmoal_handle,
+					     OUT t_u32 *psec, OUT 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))
+
+#ifdef memcmp
+#undef memcmp
+#endif
+/** Memcmp routine */
+#define memcmp(adapter, s1, s2, len) \
+	(adapter->callbacks.moal_memcmp(adapter->pmoal_handle, s1, s2, len))
+
+/** Find number of elements */
+#ifndef NELEMENTS
+#define NELEMENTS(x)    (sizeof(x)/sizeof(x[0]))
+#endif
+
+/** SWAP: swap t_u8 */
+#define SWAP_U8(a, b)	{t_u8 t; t = a; a = b; b = t; }
+
+/** SWAP: swap t_u8 */
+#define SWAP_U16(a, b)	{t_u16 t; t = a; a = b; b = t; }
+
+/** MLAN MNULL pointer */
+#define MNULL                           (0)
+
+/** 16 bits byte swap */
+#define swap_byte_16(x) \
+((t_u16)((((t_u16)(x) & 0x00ffU) << 8) | \
+		 (((t_u16)(x) & 0xff00U) >> 8)))
+
+/** 32 bits byte swap */
+#define swap_byte_32(x) \
+((t_u32)((((t_u32)(x) & 0x000000ffUL) << 24) | \
+	 (((t_u32)(x) & 0x0000ff00UL) <<  8) | \
+	 (((t_u32)(x) & 0x00ff0000UL) >>  8) | \
+	 (((t_u32)(x) & 0xff000000UL) >> 24)))
+
+/** 64 bits byte swap */
+#define swap_byte_64(x) \
+((t_u64)((t_u64)(((t_u64)(x) & 0x00000000000000ffULL) << 56) | \
+	     (t_u64)(((t_u64)(x) & 0x000000000000ff00ULL) << 40) | \
+	     (t_u64)(((t_u64)(x) & 0x0000000000ff0000ULL) << 24) | \
+	     (t_u64)(((t_u64)(x) & 0x00000000ff000000ULL) <<  8) | \
+	     (t_u64)(((t_u64)(x) & 0x000000ff00000000ULL) >>  8) | \
+	     (t_u64)(((t_u64)(x) & 0x0000ff0000000000ULL) >> 24) | \
+	     (t_u64)(((t_u64)(x) & 0x00ff000000000000ULL) >> 40) | \
+	     (t_u64)(((t_u64)(x) & 0xff00000000000000ULL) >> 56)))
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert ulong n/w to host */
+#define mlan_ntohl(x) x
+/** Convert host ulong to n/w */
+#define mlan_htonl(x) x
+/** Convert n/w to host */
+#define mlan_ntohs(x)  x
+/** Convert host to n/w */
+#define mlan_htons(x)  x
+/** Convert from 16 bit little endian format to CPU format */
+#define wlan_le16_to_cpu(x) swap_byte_16(x)
+/** Convert from 32 bit little endian format to CPU format */
+#define wlan_le32_to_cpu(x) swap_byte_32(x)
+/** Convert from 64 bit little endian format to CPU format */
+#define wlan_le64_to_cpu(x) swap_byte_64(x)
+/** Convert to 16 bit little endian format from CPU format */
+#define wlan_cpu_to_le16(x) swap_byte_16(x)
+/** Convert to 32 bit little endian format from CPU format */
+#define wlan_cpu_to_le32(x) swap_byte_32(x)
+/** Convert to 64 bit little endian format from CPU format */
+#define wlan_cpu_to_le64(x) swap_byte_64(x)
+
+/** Convert TxPD to little endian format from CPU format */
+#define endian_convert_TxPD(x)                                          \
+	{                                                                   \
+	    (x)->tx_pkt_length = wlan_cpu_to_le16((x)->tx_pkt_length);      \
+	    (x)->tx_pkt_offset = wlan_cpu_to_le16((x)->tx_pkt_offset);      \
+	    (x)->tx_pkt_type   = wlan_cpu_to_le16((x)->tx_pkt_type);        \
+	    (x)->tx_control    = wlan_cpu_to_le32((x)->tx_control);         \
+        (x)->tx_control_1  = wlan_cpu_to_le32((x)->tx_control_1);         \
+	}
+/** Convert RxPD from little endian format to CPU format */
+#define endian_convert_RxPD(x)                                          \
+	{                                                                   \
+	    (x)->rx_pkt_length = wlan_le16_to_cpu((x)->rx_pkt_length);      \
+	    (x)->rx_pkt_offset = wlan_le16_to_cpu((x)->rx_pkt_offset);      \
+	    (x)->rx_pkt_type   = wlan_le16_to_cpu((x)->rx_pkt_type);        \
+	    (x)->seq_num       = wlan_le16_to_cpu((x)->seq_num);            \
+        (x)->rx_info       = wlan_le32_to_cpu((x)->rx_info);            \
+	    (x)->hi_rx_count32 = wlan_le32_to_cpu((x)->hi_rx_count32);      \
+	    (x)->lo_rx_count16 = wlan_le16_to_cpu((x)->lo_rx_count16);      \
+	}
+#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) (IN t_void *pmoal_handle, IN 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                  2048
+
+#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         100
+/** low rx pending packets */
+#define LOW_RX_PENDING          80
+
+/** Default region code */
+#define MRVDRV_DEFAULT_REGION_CODE      0x10
+
+/** Default country code */
+#define MRVDRV_DEFAULT_COUNTRY_CODE      "US"
+
+/** Japan country code */
+#define COUNTRY_CODE_JP_40	        0x40
+/** Japan special country code */
+#define COUNTRY_CODE_JP_FF	        0xFF
+
+/** Default factor for calculating beacon average */
+#define DEFAULT_BCN_AVG_FACTOR          8
+/** Default factor for calculating data average */
+#define DEFAULT_DATA_AVG_FACTOR         8
+
+/** The first valid channel for use */
+#define FIRST_VALID_CHANNEL          0xff
+/** Default Ad-Hoc channel */
+#define DEFAULT_AD_HOC_CHANNEL       6
+/** Default Ad-Hoc channel A */
+#define DEFAULT_AD_HOC_CHANNEL_A     36
+
+/** Number of WEP keys */
+#define MRVL_NUM_WEP_KEY                (4)
+
+/** Default multiple DTIM */
+#define MRVDRV_DEFAULT_MULTIPLE_DTIM        1
+
+/** Default beacon missing timeout */
+#define DEFAULT_BCN_MISS_TIMEOUT            10
+
+/** Maximum buffer space for beacons retrieved from scan responses */
+#define MAX_SCAN_BEACON_BUFFER          49152
+/** Default buffer space for beacons retrieved from scan responses */
+#define DEFAULT_SCAN_BEACON_BUFFER      4096
+
+/**
+ * @brief Buffer pad space for newly allocated beacons/probe responses
+ *
+ * Beacons are typically 6 bytes longer than an equivalent probe response.
+ *  For each scan response stored, allocate an extra byte pad at the end to
+ *  allow easy expansion to store a beacon in the same memory a probe response
+ *  previously contained
+ */
+#define SCAN_BEACON_ENTRY_PAD          6
+
+/** Scan time specified in the channel TLV
+ *  for each channel for passive scans
+ */
+#define MRVDRV_PASSIVE_SCAN_CHAN_TIME       200
+
+/** Scan time specified in the channel TLV
+ *  for each channel for active scans
+ */
+#define MRVDRV_ACTIVE_SCAN_CHAN_TIME        200
+
+/** Scan time specified in the channel TLV
+ *  for each channel for specific scans
+ */
+#define MRVDRV_SPECIFIC_SCAN_CHAN_TIME      110
+
+/**
+ * Max total scan time in milliseconds
+ * The total scan time should be less than scan command timeout value (20s)
+ */
+#define MRVDRV_MAX_TOTAL_SCAN_TIME     (MRVDRV_TIMER_10S * 2 - MRVDRV_TIMER_1S)
+
+/** Offset for GTK as it has version to skip past for GTK */
+#define RSN_GTK_OUI_OFFSET 2
+
+/** If OUI is not found */
+#define MLAN_OUI_NOT_PRESENT 0
+/** If OUI is found */
+#define MLAN_OUI_PRESENT 1
+
+/** Is cmd_resp, event or data packet received? */
+#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \
+	adapter->event_received || \
+	adapter->data_received)
+/** Type command */
+#define MLAN_TYPE_CMD			1
+/** Type data */
+#define MLAN_TYPE_DATA			0
+/** Type event */
+#define MLAN_TYPE_EVENT			3
+
+/** 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 */
+/* upto 0xB7 */
+#define MAX_MP_REGS			184
+/** Maximum port */
+#define MAX_PORT			32
+
+/** max MP REGS */
+#define MAX_MP_REGS_MAX	    (196)
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** Multi port TX aggregation buffer size */
+#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE        (65280)	/* 64K - 256 */
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+/** Multi port RX aggregation buffer size */
+#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE        (65280)	/* 64K - 256 */
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+/** High threshold at which to start drop packets */
+#define  RX_HIGH_THRESHOLD           1024
+/** Low threshold to allow Rx BA */
+#define  RX_LOW_THRESHOLD            128
+
+/** 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_cmd_assoc_failure;
+    /** Number of Tx timeouts */
+	t_u32 num_tx_timeout;
+    /** 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;
+} 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;
+
+/** 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;
+} 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) (IN t_void *priv, IN t_u8 first_bss);
+    /** ioctl handler */
+	mlan_status (*ioctl) (t_void *adapter, pmlan_ioctl_req pioctl_req);
+    /** cmd handler */
+	mlan_status (*prepare_cmd) (IN t_void *priv,
+				    IN t_u16 cmd_no,
+				    IN t_u16 cmd_action,
+				    IN t_u32 cmd_oid,
+				    IN t_void *pioctl_buf,
+				    IN t_void *pdata_buf, IN t_void *pcmd_buf);
+    /** cmdresp handler */
+	mlan_status (*process_cmdresp) (IN t_void *priv,
+					IN t_u16 cmdresp_no,
+					IN t_void *pcmd_buf, IN t_void *pioctl);
+    /** rx handler */
+	mlan_status (*process_rx_packet) (IN t_void *adapter,
+					  IN pmlan_buffer pmbuf);
+    /** event handler */
+	mlan_status (*process_event) (IN t_void *priv);
+    /** txpd handler */
+	t_void *(*process_txpd) (IN t_void *priv, IN pmlan_buffer pmbuf);
+    /** BSS role */
+	mlan_bss_role bss_role;
+} mlan_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;
+    /** rxpd_htinfo */
+	t_u8 rxpd_rate_info;
+    /** max amsdu size */
+	t_u16 max_amsdu;
+    /** 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;
+    /** 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;
+    /**  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;
+    /** Rate bitmap */
+	t_u16 rate_bitmap;
+    /** 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;
+
+    /** Current SSID/BSSID related parameters*/
+	current_bss_params_t curr_bss_params;
+    /** current channel flags */
+	t_u32 curr_chan_flags;
+    /** User selected bands */
+	t_u8 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;
+	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;
+    /** Current Beacon buffer */
+	t_u8 *pcurr_bcn_buf;
+    /** Current Beacon size */
+	t_u32 curr_bcn_size;
+    /** Current Beacon buffer lock */
+	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];
+    /** Hotspot configuration */
+	t_u32 hotspot_cfg;
+#ifdef STA_SUPPORT
+    /** Extended capabilities */
+	ExtCap_t ext_cap;
+    /** Default extended capabilities */
+	ExtCap_t def_ext_cap;
+#endif
+    /** interface header len */
+	t_u8 intf_hr_len;
+    /** Control TX AMPDU on infra link */
+	t_u8 txaggrctrl;
+    /** 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;
+
+/** 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;
+    /** PN number high 32 bits*/
+	t_u32 hi_curr_rx_count32;
+    /** PN number low 16 bits*/
+	t_u16 lo_curr_rx_count16;
+};
+
+/** 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 OID for sub-command use */
+	t_u32 cmd_oid;
+    /** 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;
+    /** pre_allocated mlan_buffer for cmd */
+	mlan_buffer *pmbuf;
+};
+
+/** 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;
+
+/** 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;
+    /** 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_u8 bandmode;
+	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;
+
+#ifdef DFS_TESTING_SUPPORT
+/** 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;
+} wlan_dfs_testing_settings_t;
+#endif /* DFS_SUPPORT_TESTING */
+
+/**
+ * @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;
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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++;
+}
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** 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;
+#endif
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+/** 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 /* SDIO_MULTI_PORT_RX_AGGR */
+
+/** mlan_init_para structure */
+typedef struct _mlan_init_para {
+#ifdef MFG_CMD_SUPPORT
+    /** MFG mode */
+	t_u32 mfg_mode;
+#endif
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** 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;
+    /** FW download CRC check flag */
+	t_u32 fw_crc_check;
+    /** dev cap mask */
+	t_u32 dev_cap_mask;
+	t_u32 drcs_chantime_mode;
+	t_bool fw_region;
+} mlan_init_para, *pmlan_init_para;
+/** mlan sdio card register structure */
+typedef struct _mlan_sdio_card_reg {
+    /** start read port */
+	t_u8 start_rd_port;
+    /** start write port */
+	t_u8 start_wr_port;
+    /** base 0 register */
+	t_u8 base_0_reg;
+    /** base 1 register */
+	t_u8 base_1_reg;
+    /** poll register */
+	t_u8 poll_reg;
+    /** host interrupt enable */
+	t_u8 host_int_enable;
+    /** host interrupt status */
+	t_u8 host_int_status;
+    /** status register 0 */
+	t_u8 status_reg_0;
+    /** status register 1 */
+	t_u8 status_reg_1;
+    /** sdio interrupt mask */
+	t_u8 sdio_int_mask;
+    /** data port mask */
+	t_u32 data_port_mask;
+    /** maximum mp register */
+	t_u8 max_mp_regs;
+    /** read bitmap lower byte */
+	t_u8 rd_bitmap_l;
+    /** read bitmap upper byte */
+	t_u8 rd_bitmap_u;
+    /** read bitmap_1 lower byte */
+	t_u8 rd_bitmap_1l;
+    /** read bitmap_1 upper byte */
+	t_u8 rd_bitmap_1u;
+    /** write bitmap lower byte */
+	t_u8 wr_bitmap_l;
+     /** write bitmap upper byte */
+	t_u8 wr_bitmap_u;
+    /** write bitmap_1 lower byte */
+	t_u8 wr_bitmap_1l;
+    /** write bitmap_1 upper byte */
+	t_u8 wr_bitmap_1u;
+    /** read port0 length lower byte */
+	t_u8 rd_len_p0_l;
+    /** read port0 length upper byte */
+	t_u8 rd_len_p0_u;
+    /** card misc configuration register */
+	t_u8 card_misc_cfg_reg;
+    /** scratch reg used for reset */
+	t_u8 reset_reg;
+    /** reset value */
+	t_u8 reset_val;
+} mlan_sdio_card_reg, *pmlan_sdio_card_reg;
+
+/** ampdu info */
+typedef struct _ampdu_info {
+    /** staion tx win_size */
+	t_u32 ampdu_sta_txwinsize;
+#ifdef UAP_SUPPORT
+    /** uap tx win_size */
+	t_u32 ampdu_uap_txwinsize;
+    /** uap rx win_size */
+	t_u32 ampdu_uap_rxwinsize;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+    /** wfd tx/rx winsize */
+	t_u32 ampdu_wfd_txrxwinsize;
+#endif
+} ampdu_info;
+/** mlan sdio device structure */
+typedef struct _mlan_sdio_device {
+    /** reg */
+	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;
+    /** control mask */
+	t_bool has_control_mask;
+    /** more option */
+	t_u8 card_config_2_1_reg;	//8897:0xCD, 8887:0xD9
+	t_u8 cmd_config_0;	//CMD_CONFIG_0 8897:0xB8 8887:0xC4
+	t_u8 cmd_config_1;	//CMD_CONFIG_1 8897:0xB9, 8887:0xC5
+	t_u8 cmd_rd_len_0;	//CMD_RD_LEN_0 8897:0xB4, 8887:0xC0
+	t_u8 cmd_rd_len_1;	//CMD_RD_LEN_1   8897:0xB5, 8887:0xC1
+	t_u8 io_port_0_reg;	//IO_PORT_0_REG
+	t_u8 io_port_1_reg;	//IO_PORT_1_REG
+	t_u8 io_port_2_reg;	//IO_PORT_2_REG
+	t_u8 host_int_rsr_reg;	//HOST_INT_RSR_REG
+	t_u8 card_rx_len_reg;	//CARD_RX_LEN_REG
+	t_u8 card_rx_unit_reg;	//CARD_RX_UNIT_REG
+	t_u8 host_int_mask_reg;	//HOST_INT_MASK_REG
+	t_u8 host_int_status_reg;	//HOST_INT_STATUS_REG
+	t_u32 mp_tx_aggr_buf_size;
+	t_u32 mp_rx_aggr_buf_size;
+    /** Max Tx buffer size */
+	t_u32 max_tx_buf_size;
+    /** support V15_UPDATE */
+	t_u8 v15_update;
+    /** support V15_FW_API */
+	t_u8 v15_fw_api;
+    /** support V16_FW_API */
+	t_u8 v16_fw_api;
+    /** support ext_scan */
+	t_u8 ext_scan;
+    /** support fw reload */
+	t_u8 fw_reload;
+	/** ampdu info*/
+	ampdu_info *ampdu_info;
+} mlan_sdio_device, *pmlan_sdio_device;
+
+/** 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;
+    /** more_rx_task_flag */
+	t_u32 more_rx_task_flag;
+    /** rx_proc_lock for main_rx_process */
+	t_void *prx_proc_lock;
+    /** 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 */
+	t_u8 flush_data;
+    /** IO port */
+	t_u32 ioport;
+
+    /** STATUS variables */
+	WLAN_HARDWARE_STATUS hw_status;
+    /** PnP SUPPORT */
+	t_u8 surprise_removed;
+    /** FW hang report */
+	t_u8 fw_hang_report;
+
+    /** ECSA support */
+	t_u8 ecsa_enable;
+
+    /** Get log support */
+	t_u8 getlog_enable;
+
+    /** Radio on flag */
+	t_u16 radio_on;
+
+    /** Firmware release number */
+	t_u32 fw_release_number;
+    /** firmware version */
+	t_u8 fw_ver;
+    /** firmware minor version */
+	t_u8 fw_min_ver;
+    /** uap firmware version */
+	t_u8 uap_fw_ver;
+    /** mac address retrun from get_hw_spec */
+	t_u8 permanent_addr[MLAN_MAC_ADDR_LENGTH];
+    /** Number of antenna used */
+	t_u16 number_of_antenna;
+    /** antenna info */
+	t_u8 antinfo;
+    /** Firmware capability information */
+	t_u32 fw_cap_info;
+    /** pint_lock for interrupt handling */
+	t_void *pint_lock;
+	const mlan_sdio_device *psdio_device;
+	t_u16 card_type;
+    /** Interrupt status */
+	t_u8 sdio_ireg;
+    /** 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/* see blk_queue_max_segment_size */
+	t_u32 max_seg_size;
+	/* see blk_queue_max_segments */
+	t_u16 max_segs;
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	/** data structure for SDIO MPA TX */
+	sdio_mpa_tx mpa_tx;
+    /** packet number for tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+    /** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+    /** last wr_bitmap from FW */
+	t_u32 last_recv_wr_bitmap;
+    /** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+    /** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+    /** last length for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+    /** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+
+    /** buffer for mp debug */
+	t_u8 *mpa_buf;
+    /** length info for mp buf size */
+	t_u32 mpa_buf_size;
+
+    /** last mp_index */
+	t_u8 last_mp_index;
+#endif				/* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	/** 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];
+#endif				/* SDIO_MULTI_PORT_RX_AGGR */
+
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+
+    /** Event cause */
+	t_u32 event_cause;
+    /** Event buffer */
+	pmlan_buffer pmlan_buffer_event;
+    /** Upload length */
+	t_u32 upld_len;
+    /** Upload buffer*/
+	t_u8 upld_buf[WLAN_UPLD_SIZE];
+    /** Data sent:
+     *       TRUE - Data is sent to fw, no Tx Done received
+     *       FALSE - Tx done received for previous Tx
+     */
+	t_u8 data_sent;
+    /** CMD sent:
+     *       TRUE - CMD is sent to fw, no CMD Done received
+     *       FALSE - CMD done received for previous CMD
+     */
+	t_u8 cmd_sent;
+    /** CMD Response received:
+     *       TRUE - CMD is response is received from fw, and yet to process
+     *       FALSE - No cmd response to process
+     */
+	t_u8 cmd_resp_received;
+    /** Event received:
+     *       TRUE - Event received from fw, and yet to process
+     *       FALSE - No events to process
+     */
+	t_u8 event_received;
+
+    /** Data received:
+     *       TRUE - Data received from fw
+     *       FALSE - No Data received
+     */
+	t_u8 data_received;
+
+    /** Command-related variables */
+    /** Command sequence number */
+	t_u16 seq_num;
+    /** Command controller nodes */
+	cmd_ctrl_node *cmd_pool;
+    /** Current Command */
+	cmd_ctrl_node *curr_cmd;
+    /** mlan_lock for command */
+	t_void *pmlan_cmd_lock;
+    /** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+    /** Last init fw command id */
+	t_u16 last_init_cmd;
+    /** Command timer */
+	t_void *pmlan_cmd_timer;
+    /** Command timer set flag */
+	t_u8 cmd_timer_is_set;
+    /** time stamp for command dnld */
+	t_u32 dnld_cmd_in_secs;
+
+    /** Command Queues */
+    /** Free command buffers */
+	mlan_list_head cmd_free_q;
+    /** Pending command buffers */
+	mlan_list_head cmd_pending_q;
+    /** Command queue for scanning */
+	mlan_list_head scan_pending_q;
+    /** ioctl pending queue */
+	mlan_list_head ioctl_pending_q;
+    /** pending_ioctl flag */
+	t_u8 pending_ioctl;
+    /** pending_disconnect_priv structure */
+	pmlan_private pending_disconnect_priv;
+    /** mlan_processing */
+	t_u32 scan_processing;
+    /** 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 */
+	wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+#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;
+#ifdef DFS_TESTING_SUPPORT
+    /** User configured settings for DFS testing */
+	wlan_dfs_testing_settings_t dfs_test_params;
+#endif
+    /** 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;
+    /** 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 block flag */
+	t_u8 scan_block;
+    /** Extended scan or legacy scan */
+	t_u8 ext_scan;
+	t_u16 bcn_buf_size;
+    /** Beacon buffer */
+	t_u8 *bcn_buf;
+    /** Pointer to valid beacon buffer end */
+	t_u8 *pbcn_buf_end;
+    /** allocate fixed scan beacon buffer size*/
+	t_u32 fixed_beacon_buffer;
+
+    /** F/W supported bands */
+	t_u8 fw_bands;
+    /** User selected band to start adhoc network */
+	t_u8 adhoc_start_band;
+    /** User selected bands */
+	t_u8 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;
+	/** Multi channel status */
+	t_u8 mc_status;
+
+    /** 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;
+
+    /** 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;
+
+    /** 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;
+    /** 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
+    /** Enable 11n support for adhoc start */
+	t_u8 adhoc_11n_enabled;
+    /** 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;
+
+    /** 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;
+    /** management frame wakeup filter config */
+	mlan_mgmt_frame_wakeup mgmt_filter[MAX_MGMT_FRAME_FILTER];
+
+    /** Bypass TX queue pkt count  */
+	t_u16 bypass_pkt_count;
+#if defined(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;
+    /** DFS repeater */
+	t_bool dfs_repeater;
+    /** DFSr channel */
+	t_u32 dfsr_channel;
+    /** multi channel policy */
+	t_bool mc_policy;
+	/** flag for sdio rx aggr */
+	t_bool sdio_rx_aggr_enable;
+	/** fw rx block size */
+	t_u16 sdio_rx_block_size;
+    /**channel param band config */
+	t_u8 chanrpt_param_bandcfg;
+    /** maximum station 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, *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)
+
+/** Ethernet packet type for EAPOL */
+#define MLAN_ETHER_PKT_TYPE_EAPOL	(0x888E)
+/** 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(IN pmlan_adapter pmadapter);
+mlan_status wlan_init_priv_lock_list(IN pmlan_adapter pmadapter,
+				     t_u8 start_index);
+t_void wlan_free_lock_list(IN pmlan_adapter pmadapter);
+mlan_status wlan_init_timer(IN pmlan_adapter pmadapter);
+t_void wlan_free_timer(IN pmlan_adapter pmadapter);
+
+/* Function prototype */
+/** Download firmware */
+mlan_status wlan_dnld_fw(IN pmlan_adapter pmadapter, IN pmlan_fw_image pmfw);
+
+/** Initialize firmware */
+mlan_status wlan_init_fw(IN pmlan_adapter pmadapter);
+
+/** get hw spec complete */
+mlan_status wlan_get_hw_spec_complete(IN pmlan_adapter pmadapter);
+
+/** Initialize firmware complete */
+mlan_status wlan_init_fw_complete(IN pmlan_adapter pmadapter);
+
+/** Shutdown firmware complete */
+mlan_status wlan_shutdown_fw_complete(IN 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(IN pmlan_adapter pmadapter);
+
+/** Initialize mlan_private structure */
+mlan_status wlan_init_priv(IN pmlan_private priv);
+
+/** Process event */
+mlan_status wlan_process_event(pmlan_adapter pmadapter);
+
+/** Prepare command */
+mlan_status wlan_prepare_cmd(IN pmlan_private priv,
+			     IN t_u16 cmd_no,
+			     IN t_u16 cmd_action,
+			     IN t_u32 cmd_oid,
+			     IN t_void *pioctl_buf, IN t_void *pdata_buf);
+
+/** cmd timeout handler */
+t_void wlan_cmd_timeout_func(t_void *function_context);
+/** process host cmd */
+mlan_status wlan_misc_ioctl_host_cmd(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req);
+/** process init/shutdown cmd*/
+mlan_status wlan_misc_ioctl_init_shutdown(IN pmlan_adapter pmadapter,
+					  IN pmlan_ioctl_req pioctl_req);
+/** process debug info */
+mlan_status wlan_get_info_debug_info(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req);
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/** Set/Get BSS role */
+mlan_status wlan_bss_ioctl_bss_role(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_set_ewpa_mode(mlan_private *priv, mlan_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(IN mlan_adapter *pmadapter);
+/** Free command buffer */
+mlan_status wlan_free_cmd_buffer(IN mlan_adapter *pmadapter);
+/** Request command lock */
+t_void wlan_request_cmd_lock(mlan_adapter *pmadapter);
+/** Release command lock */
+t_void wlan_release_cmd_lock(mlan_adapter *pmadapter);
+#ifdef STA_SUPPORT
+/** Flush the scan pending queue */
+t_void wlan_flush_scan_queue(pmlan_adapter pmadapter);
+mlan_status wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+					 pmlan_ioctl_req pioctl_req);
+#endif
+/**Cancel pending command */
+t_void wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter);
+/**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(IN mlan_adapter *pmadapter,
+				 IN cmd_ctrl_node *pcmd_node);
+
+/** Insert command to pending queue */
+t_void wlan_insert_cmd_to_pending_q(IN mlan_adapter *pmadapter,
+				    IN cmd_ctrl_node *pcmd_node,
+				    IN 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);
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+mlan_status wlan_alloc_sdio_mpa_buffers(IN mlan_adapter *pmadapter,
+					t_u32 mpa_tx_buf_size,
+					t_u32 mpa_rx_buf_size);
+
+mlan_status wlan_free_sdio_mpa_buffers(IN mlan_adapter *pmadapter);
+#endif
+
+/** Process write data complete */
+mlan_status wlan_write_data_complete(pmlan_adapter pmlan_adapter,
+				     pmlan_buffer pmbuf, mlan_status status);
+/** 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)
+
+/** 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,
+				    IN HostCmd_DS_COMMAND *cmd,
+				    IN t_u16 cmd_action,
+				    IN t_u16 ps_bitmap, IN t_void *pdata_buf);
+/** handle command resp for enhanced power save mode */
+mlan_status wlan_ret_enh_power_mode(IN pmlan_private pmpriv,
+				    IN HostCmd_DS_COMMAND *resp,
+				    IN mlan_ioctl_req *pioctl_buf);
+
+/** handle commnand for cfg data */
+mlan_status wlan_cmd_cfg_data(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *pcmd,
+			      IN t_u16 cmd_action,
+			      IN t_u32 cmd_oid, IN t_void *pdata_buf);
+/** handle command resp for cfg data */
+mlan_status wlan_ret_cfg_data(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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);
+
+mlan_status wlan_pm_reset_card(pmlan_adapter adapter);
+mlan_status wlan_pm_wakeup_card(pmlan_adapter pmadapter, t_u8 timeout);
+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);
+
+#ifdef WIFI_DIRECT_SUPPORT
+mlan_status wlan_bss_ioctl_wifi_direct_mode(IN pmlan_adapter pmadapter,
+					    IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_wifi_direct_mode(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_u16 cmd_action,
+				      IN t_void *pdata_buf);
+mlan_status wlan_ret_wifi_direct_mode(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_p2p_params_config(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+mlan_status wlan_ret_p2p_params_config(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *resp,
+				       IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_p2p_config(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req);
+#endif
+/** get ralist info */
+int wlan_get_ralist_info(mlan_private *priv, ralist_info *buf);
+/** dump ralist */
+void wlan_dump_ralist(mlan_private *priv);
+
+/** get pm info */
+mlan_status wlan_get_pm_info(IN pmlan_adapter pmadapter,
+			     IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_bss_ioctl_bss_remove(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_config_mgmt_filter(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_get_hs_wakeup_reason(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_hs_wakeup_reason(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_void *pdata_buf);
+
+mlan_status wlan_ret_hs_wakeup_reason(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_radio_ioctl_radio_ctl(IN pmlan_adapter pmadapter,
+				       IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_radio_ioctl_remain_chan_cfg(IN pmlan_adapter pmadapter,
+					     IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_remain_on_channel(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+mlan_status wlan_ret_remain_on_channel(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *resp,
+				       IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_radio_ioctl_ant_cfg(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *cmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_cfg(IN pmlan_adapter pmadapter,
+				IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_get_data_rate(IN pmlan_adapter pmadapter,
+					  IN 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(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN 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(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_u16 *pdata_buf);
+/** Set Robustcoex gpiocfg */
+mlan_status wlan_misc_robustcoex(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req);
+
+/** send get hw spec command to firmware */
+mlan_status wlan_adapter_get_hw_spec(IN pmlan_adapter pmadapter);
+/** send adapter specific init cmd to firmware */
+mlan_status wlan_adapter_init_cmd(IN pmlan_adapter pmadapter);
+/** get/set bandcfg */
+mlan_status wlan_radio_ioctl_band_cfg(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status wlan_cmd_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
+					 IN HostCmd_DS_COMMAND *cmd,
+					 IN t_u16 cmd_action,
+					 IN t_void *pdata_buf);
+mlan_status wlan_ret_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
+					 const IN HostCmd_DS_COMMAND *resp,
+					 OUT mlan_ioctl_req *pioctl_buf);
+#endif
+mlan_status wlan_handle_event_multi_chan_info(IN pmlan_private pmpriv,
+					      pmlan_buffer pevent);
+
+#ifdef STA_SUPPORT
+/** warm reset */
+mlan_status wlan_misc_ioctl_warm_reset(IN pmlan_adapter pmadapter,
+				       IN 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(IN t_void *priv,
+				     IN t_u16 cmd_no,
+				     IN t_u16 cmd_action,
+				     IN t_u32 cmd_oid,
+				     IN t_void *pioctl_buf,
+				     IN t_void *pdata_buf, IN t_void *pcmd_buf);
+
+/** cmdresp handler for station mode */
+mlan_status wlan_ops_sta_process_cmdresp(IN t_void *priv,
+					 IN t_u16 cmdresp_no,
+					 IN t_void *pcmd_buf,
+					 IN t_void *pioctl);
+
+/** rx handler for station mode */
+mlan_status wlan_ops_sta_process_rx_packet(IN t_void *adapter,
+					   IN pmlan_buffer pmbuf);
+
+/** event handler for station mode */
+mlan_status wlan_ops_sta_process_event(IN t_void *priv);
+
+/** fill txpd for station mode */
+t_void *wlan_ops_sta_process_txpd(IN t_void *priv, IN pmlan_buffer pmbuf);
+
+/** send init cmd to firmware for station mode */
+mlan_status wlan_ops_sta_init_cmd(IN t_void *priv, IN t_u8 first_bss);
+
+/** Flush the scan table */
+mlan_status wlan_flush_scan_table(IN pmlan_adapter pmadapter);
+
+/** Scan for networks */
+mlan_status wlan_scan_networks(IN mlan_private *pmpriv,
+			       IN t_void *pioctl_buf,
+			       IN wlan_user_scan_cfg *puser_scan_in);
+
+/** Scan for specific SSID */
+mlan_status wlan_scan_specific_ssid(IN mlan_private *pmpriv,
+				    IN t_void *pioctl_buf,
+				    IN mlan_802_11_ssid *preq_ssid);
+
+/** Scan command handler */
+mlan_status wlan_cmd_802_11_scan(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *pcmd,
+				 IN t_void *pdata_buf);
+
+/** Handler for scan command response */
+mlan_status wlan_ret_802_11_scan(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN t_void *pioctl_buf);
+
+/** Extended scan command handler */
+mlan_status wlan_cmd_802_11_scan_ext(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *pcmd,
+				     IN t_void *pdata_buf);
+/** Handler for extended scan command response */
+mlan_status wlan_ret_802_11_scan_ext(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *resp,
+				     IN t_void *pioctl_buf);
+/** Handler event for extended scan report */
+mlan_status wlan_handle_event_ext_scan_report(IN mlan_private *pmpriv,
+					      IN mlan_buffer *pmbuf);
+
+/** check network compatibility */
+t_s32 wlan_is_network_compatible(IN mlan_private *pmpriv,
+				 IN t_u32 index, IN t_u32 mode);
+
+/** Find an SSID in a list */
+t_s32 wlan_find_ssid_in_list(IN pmlan_private pmpriv,
+			     IN mlan_802_11_ssid *ssid,
+			     IN t_u8 *bssid, IN t_u32 mode);
+
+/** Find a BSSID in a list */
+t_s32 wlan_find_bssid_in_list(IN mlan_private *pmpriv,
+			      IN t_u8 *bssid, IN t_u32 mode);
+
+/** Find best network */
+mlan_status wlan_find_best_network(IN mlan_private *pmpriv,
+				   OUT mlan_ssid_bssid *preq_ssid_bssid);
+
+/** Compare two SSIDs */
+t_s32 wlan_ssid_cmp(IN pmlan_adapter pmadapter,
+		    IN mlan_802_11_ssid *ssid1, IN mlan_802_11_ssid *ssid2);
+
+/** Associate */
+mlan_status wlan_associate(IN mlan_private *pmpriv,
+			   IN t_void *pioctl_buf, IN BSSDescriptor_t *pBSSDesc);
+
+/** Associate command handler */
+mlan_status wlan_cmd_802_11_associate(IN mlan_private *pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_void *pdata_buf);
+
+/** Handler for association command response */
+mlan_status wlan_ret_802_11_associate(IN mlan_private *pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN t_void *pioctl_buf);
+
+/** Reset connected state */
+t_void wlan_reset_connect_state(IN pmlan_private priv, IN 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(IN t_u8 band);
+/** convert radio_type to band */
+t_u8 radio_type_to_band(t_u8 chanBand);
+
+/** Disconnect */
+mlan_status wlan_disconnect(IN mlan_private *pmpriv,
+			    IN mlan_ioctl_req *pioctl_req,
+			    IN mlan_deauth_param *deauth_param);
+
+/** Ad-Hoc start */
+mlan_status wlan_adhoc_start(IN mlan_private *pmpriv,
+			     IN t_void *pioctl_buf,
+			     IN mlan_802_11_ssid *padhoc_ssid);
+
+/** Ad-Hoc join */
+mlan_status wlan_adhoc_join(IN mlan_private *pmpriv,
+			    IN t_void *pioctl_buf,
+			    IN BSSDescriptor_t *pBSSDesc);
+
+/** Ad-Hoc start command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_start(IN mlan_private *pmpriv,
+					 IN HostCmd_DS_COMMAND *cmd,
+					 IN t_void *pdata_buf);
+
+/** Ad-Hoc command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_join(IN mlan_private *pmpriv,
+					IN HostCmd_DS_COMMAND *cmd,
+					IN t_void *pdata_buf);
+
+/** Handler for Ad-Hoc commands */
+mlan_status wlan_ret_802_11_ad_hoc(IN mlan_private *pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN t_void *pioctl_buf);
+
+/** Handler for bgscan query commands */
+mlan_status wlan_cmd_802_11_bg_scan_query(IN mlan_private *pmpriv,
+					  IN HostCmd_DS_COMMAND *pcmd,
+					  IN t_void *pdata_buf);
+/** Handler for bgscan config command */
+mlan_status wlan_cmd_bgscan_config(IN mlan_private *pmpriv,
+				   IN HostCmd_DS_COMMAND *pcmd,
+				   IN t_void *pdata_buf);
+/** Hander for bgscan config command response */
+mlan_status wlan_ret_bgscan_config(IN mlan_private *pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_802_11_bgscan_query(IN mlan_private *pmpriv,
+					 IN HostCmd_DS_COMMAND *resp,
+					 IN 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(IN mlan_private *pmpriv);
+/*  Free a beacon buffer of the current bss descriptor */
+t_void wlan_free_curr_bcn(IN mlan_private *pmpriv);
+
+#endif /* STA_SUPPORT */
+
+/* Rate related functions */
+t_u8 wlan_convert_v14_rate_ht_info(t_u8 ht_info);
+/** Convert index into data rate */
+t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index,
+			      t_u8 rate_info);
+/** Get active data rates */
+t_u32 wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
+				 t_u8 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_u8 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);
+
+/* 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 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(IN pmlan_adapter pmadapter,
+				     IN mlan_ioctl_req *pioctl_req);
+
+/** This function converts region string to CFP table code */
+mlan_status wlan_misc_country_2_cfp_table_code(IN pmlan_adapter pmadapter,
+					       IN t_u8 *country_code,
+					       OUT t_u8 *cfp_bg,
+					       OUT 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 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(IN mlan_private *priv,
+				       IN 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(IN mlan_private *priv, IN pmlan_buffer pmbuf);
+#endif /* UAP_SUPPORT */
+
+mlan_status wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req,
+					   IN t_bool send_ioctl);
+
+mlan_status wlan_cmd_get_hw_spec(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *pcmd);
+mlan_status wlan_ret_get_hw_spec(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN t_void *pioctl_buf);
+mlan_status wlan_cmd_sdio_rx_aggr_cfg(IN HostCmd_DS_COMMAND *pcmd,
+				      IN t_u16 cmd_action,
+				      IN t_void *pdata_buf);
+mlan_status wlan_ret_sdio_rx_aggr_cfg(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp);
+
+mlan_status wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_mac_control(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *pcmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_mac_control(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_radio_control(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *cmd,
+					  IN t_u16 cmd_action,
+					  IN t_void *pdata_buf);
+mlan_status wlan_ret_802_11_radio_control(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_rf_antenna(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+mlan_status wlan_ret_802_11_rf_antenna(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *resp,
+				       IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_ret_reg_access(mlan_adapter *pmadapter,
+				t_u16 type,
+				IN HostCmd_DS_COMMAND *resp,
+				IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_mem_access(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *resp,
+				IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_reg_mem_ioctl_reg_rw(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_read_eeprom(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_mem_rw(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_reg_access(IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_cmd_mem_access(IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_void *pdata_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(IN pmlan_adapter pmadapter,
+					IN 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(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status
+
+wlan_misc_ioctl_tdls_get_ies(IN pmlan_adapter pmadapter,
+			     IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_tdls_idle_time(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req);
+
+t_void wlan_tdls_config(IN pmlan_private pmpriv, IN t_u8 enable);
+mlan_status wlan_misc_ioctl_tdls_cs_channel(IN pmlan_adapter pmadapter,
+					    IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_get_info_ver_ext(IN pmlan_adapter pmadapter,
+				  IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_reg_rx_mgmt_ind(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req);
+
+#ifdef DEBUG_LEVEL1
+mlan_status wlan_set_drvdbg(IN pmlan_adapter pmadapter,
+			    IN pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_hotspot_cfg(IN pmlan_adapter pmadapter,
+				  IN pmlan_ioctl_req pioctl_req);
+#ifdef STA_SUPPORT
+mlan_status wlan_misc_ext_capa_cfg(IN pmlan_adapter pmadapter,
+				   IN pmlan_ioctl_req pioctl_req);
+
+t_u32 wlan_is_ext_capa_support(IN mlan_private *pmpriv);
+#endif
+
+#ifdef STA_SUPPORT
+void wlan_add_ext_capa_info_ie(IN mlan_private *pmpriv, OUT t_u8 **pptlv_out);
+#endif
+
+mlan_status wlan_cmd_boot_sleep(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_boot_sleep(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *resp,
+				IN mlan_ioctl_req *pioctl_buf);
+
+#define BW_20MHZ  0
+#define BW_40MHZ  1
+#define BW_80MHZ  2
+#define BW_160MHZ 3
+int wlan_add_supported_oper_class_ie(IN mlan_private *pmpriv,
+				     OUT 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(IN pmlan_adapter pmadapter,
+						 IN mlan_ioctl_req *pioctl_req);
+mlan_status wlan_misc_ioctl_oper_class(IN pmlan_adapter pmadapter,
+				       IN mlan_ioctl_req *pioctl_req);
+
+t_u8 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(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_txcontrol(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_region(IN pmlan_adapter pmadapter,
+				   IN pmlan_ioctl_req pioctl_req);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status
+
+wlan_misc_ioctl_rx_pkt_coalesce_config(IN pmlan_adapter pmadapter,
+				       IN pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_ioctl_multi_chan_config(IN pmlan_adapter pmadapter,
+					      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_multi_chan_cfg(IN pmlan_private pmpriv,
+				    IN HostCmd_DS_COMMAND *cmd,
+				    IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_multi_chan_cfg(IN pmlan_private pmpriv,
+				    const IN HostCmd_DS_COMMAND *resp,
+				    OUT mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_multi_chan_policy(IN pmlan_adapter pmadapter,
+					      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_multi_chan_policy(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+
+mlan_status wlan_ret_multi_chan_policy(IN pmlan_private pmpriv,
+				       const IN HostCmd_DS_COMMAND *resp,
+				       OUT mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_drcs_config(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_drcs_cfg(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_drcs_cfg(IN pmlan_private pmpriv,
+			      const IN HostCmd_DS_COMMAND *resp,
+			      OUT mlan_ioctl_req *pioctl_buf);
+
+void wlan_bt_coex_wlan_param_update_event(pmlan_private priv,
+					  pmlan_buffer pevent);
+
+mlan_status wlan_misc_ioctl_dfs_repeater_cfg(IN pmlan_adapter pmadapter,
+					     IN pmlan_ioctl_req pioctl_req);
+
+t_bool wlan_check_interface_active(mlan_adapter *pmadapter);
+
+mlan_status wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,
+					 IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_low_pwr_mode(IN pmlan_adapter pmadapter,
+					 IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_pmic_configure(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_802_11_supplicant_pmk(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *cmd,
+					   IN t_u16 cmd_action,
+					   IN t_void *pdata_buf);
+
+mlan_status wlan_ret_802_11_supplicant_pmk(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *resp,
+					   IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_sec_ioctl_passphrase(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_get_tsf(IN pmlan_adapter pmadapter,
+				    IN 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(IN pmlan_adapter pmadapter,
+				   IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_get_cfpinfo(IN pmlan_adapter pmadapter,
+			     IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_acs(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_acs(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_acs(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_get_tsf(pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action);
+mlan_status wlan_ret_get_tsf(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN 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(IN pmlan_adapter pmadapter,
+				  IN mlan_ioctl_req *pioctl_req);
+
+mlan_status wlan_get_chan_trpc_cfg(IN pmlan_adapter pmadapter,
+				   IN mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_get_chan_trpc_config(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *cmd,
+					  IN t_u16 cmd_action,
+					  IN t_void *pdata_buf);
+mlan_status wlan_ret_get_chan_trpc_config(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_ps_inactivity_timeout(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *cmd,
+					   IN t_u16 cmd_action,
+					   IN t_void *pdata_buf);
+
+t_u8 wlan_get_center_freq_idx(IN mlan_private *pmpriv,
+			      IN t_u8 band, IN t_u32 pri_chan, IN t_u8 chan_bw);
+
+mlan_status wlan_ret_chan_region_cfg(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *resp,
+				     IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_fw_dump_event(IN pmlan_adapter pmadapter,
+					  IN mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_fw_dump_event(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *cmd,
+				   IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_misc_bootsleep(IN pmlan_adapter pmadapter,
+				IN pmlan_ioctl_req pioctl_req);
+
+/**
+ *  @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) (IN pmlan_private pmpriv),
+		     t_bool (*check_cond) (IN 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) (IN pmlan_private pmpriv),
+		      t_bool (*check_cond) (IN 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) (IN 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) (IN pmlan_private pmpriv),
+			   t_bool (*check_cond_2) (IN 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 100644
index 0000000..6a8cab3
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_meas.c
@@ -0,0 +1,463 @@
+/**
+ * @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 (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+Change Log:
+    03/24/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_ioctl.h"
+#include "mlan_meas.h"
+
+/** Default measurement duration when not provided by the application */
+#define WLAN_MEAS_DEFAULT_MEAS_DURATION    1000U	/* TUs */
+
+#ifdef DEBUG_LEVEL2
+/** String descriptions of the different measurement enums.  Debug display */
+static const char *meas_type_str[WLAN_MEAS_NUM_TYPES] = {
+	"basic",
+};
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief Retrieve the measurement string representation of a meas_type enum
+ *  Used for debug display only
+ *
+ *  @param meas_type Measurement type enumeration input for string lookup
+ *
+ *  @return         Constant string representing measurement type
+ */
+static const char *
+wlan_meas_get_meas_type_str(MeasType_t meas_type)
+{
+	if (meas_type <= WLAN_MEAS_11H_MAX_TYPE)
+		return meas_type_str[meas_type];
+
+	return "Invld";
+}
+#endif
+
+/**
+ *  @brief Debug print display of the input measurement request
+ *
+ *  @param pmeas_req  Pointer to the measurement request to display
+ *
+ *  @return          N/A
+ */
+static
+	void
+wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req)
+{
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+
+	PRINTM(MINFO, "Meas: Req: mac_addr: " MACSTR "\n",
+	       MAC2STR(pmeas_req->mac_addr));
+
+	PRINTM(MINFO, "Meas: Req:  dlgTkn: %d\n", pmeas_req->dialog_token);
+	PRINTM(MINFO, "Meas: Req:    mode: dm[%c] rpt[%c] req[%c]\n",
+	       pmeas_req->req_mode.duration_mandatory ? 'X' : ' ',
+	       pmeas_req->req_mode.report ? 'X' : ' ',
+	       pmeas_req->req_mode.request ? 'X' : ' ');
+	PRINTM(MINFO, "Meas: Req:        : en[%c] par[%c]\n",
+	       pmeas_req->req_mode.enable ? 'X' : ' ',
+	       pmeas_req->req_mode.parallel ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+	PRINTM(MINFO, "Meas: Req: measTyp: %s\n",
+	       wlan_meas_get_meas_type_str(pmeas_req->meas_type));
+#endif
+
+	switch (pmeas_req->meas_type) {
+	case WLAN_MEAS_BASIC:
+		/* Lazy cheat, fields of bas, cca, rpi union match on the request */
+		PRINTM(MINFO, "Meas: Req: chan: %u\n",
+		       pmeas_req->req.basic.channel);
+		PRINTM(MINFO, "Meas: Req: strt: %llu\n",
+		       wlan_le64_to_cpu(pmeas_req->req.basic.start_time));
+		PRINTM(MINFO, "Meas: Req:  dur: %u\n",
+		       wlan_le16_to_cpu(pmeas_req->req.basic.duration));
+		break;
+	default:
+		PRINTM(MINFO, "Meas: Req: <unhandled>\n");
+		break;
+	}
+
+	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+	LEAVE();
+}
+
+/**
+ *  @brief Debug print display of the input measurement report
+ *
+ *  @param pmeas_rpt  Pointer to measurement report to display
+ *
+ *  @return          N/A
+ */
+static
+	void
+wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
+{
+	MeasType_t type;
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+	PRINTM(MINFO, "Meas: Rpt: mac_addr: " MACSTR "\n",
+	       MAC2STR(pmeas_rpt->mac_addr));
+
+	PRINTM(MINFO, "Meas: Rpt:  dlgTkn: %d\n", pmeas_rpt->dialog_token);
+
+	PRINTM(MINFO, "Meas: Rpt: rptMode: (%x): Rfs[%c] ICp[%c] Lt[%c]\n",
+	       *(t_u8 *)&pmeas_rpt->rpt_mode,
+	       pmeas_rpt->rpt_mode.refused ? 'X' : ' ',
+	       pmeas_rpt->rpt_mode.incapable ? 'X' : ' ',
+	       pmeas_rpt->rpt_mode.late ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+	PRINTM(MINFO, "Meas: Rpt: measTyp: %s\n",
+	       wlan_meas_get_meas_type_str(pmeas_rpt->meas_type));
+#endif
+
+	type = wlan_le32_to_cpu(pmeas_rpt->meas_type);
+	switch (type) {
+	case WLAN_MEAS_BASIC:
+		PRINTM(MINFO, "Meas: Rpt: chan: %u\n",
+		       pmeas_rpt->rpt.basic.channel);
+		PRINTM(MINFO, "Meas: Rpt: strt: %llu\n",
+		       wlan_le64_to_cpu(pmeas_rpt->rpt.basic.start_time));
+		PRINTM(MINFO, "Meas: Rpt:  dur: %u\n",
+		       wlan_le16_to_cpu(pmeas_rpt->rpt.basic.duration));
+		PRINTM(MINFO, "Meas: Rpt:  bas: (%x): unmsd[%c], radar[%c]\n",
+		       *(t_u8 *)&(pmeas_rpt->rpt.basic.map),
+		       pmeas_rpt->rpt.basic.map.unmeasured ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.radar ? 'X' : ' ');
+		PRINTM(MINFO, "Meas: Rpt:  bas: unidSig[%c] ofdm[%c] bss[%c]\n",
+		       pmeas_rpt->rpt.basic.map.unidentified_sig ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.ofdm_preamble ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.bss ? 'X' : ' ');
+		break;
+	default:
+		PRINTM(MINFO, "Meas: Rpt: <unhandled>\n");
+		break;
+	}
+
+	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+	LEAVE();
+}
+
+/**
+ *  @brief Retrieve a measurement report from the firmware
+ *
+ *  Callback from command processing when a measurement report is received
+ *    from the firmware.  Perform the following when a report is received:
+ *
+ *   -# Debug displays the report if compiled with the appropriate flags
+ *   -# If we are pending on a specific measurement report token, and it
+ *      matches the received report's token, store the report and wake up
+ *      any pending threads
+ *
+ *  @param pmpriv Private driver information structure
+ *  @param resp HostCmd_DS_COMMAND struct returned from the firmware command
+ *              passing a HostCmd_DS_MEASUREMENT_REPORT structure.
+ *
+ *  @return     MLAN_STATUS_SUCCESS
+ */
+static int
+wlan_meas_cmdresp_get_report(mlan_private *pmpriv,
+			     const HostCmd_DS_COMMAND *resp)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt = &resp->params.meas_rpt;
+
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Rpt: %#x-%u, Seq=%u, Ret=%u\n",
+	       resp->command, resp->size, resp->seq_num, resp->result);
+
+	/* Debug displays the measurement report */
+	wlan_meas_dump_meas_rpt(pmeas_rpt);
+
+	/*
+	 * Check if we are pending on a measurement report and it matches
+	 *  the dialog token of the received report:
+	 */
+	if (pmadapter->state_meas.meas_rpt_pend_on
+	    && pmadapter->state_meas.meas_rpt_pend_on ==
+	    pmeas_rpt->dialog_token) {
+		PRINTM(MINFO, "Meas: Rpt: RCV'd Pend on meas #%d\n",
+		       pmadapter->state_meas.meas_rpt_pend_on);
+
+		/* Clear the pending report indicator */
+		pmadapter->state_meas.meas_rpt_pend_on = 0;
+
+		/* Copy the received report into the measurement state for retrieval */
+		memcpy(pmadapter, &pmadapter->state_meas.meas_rpt_returned,
+		       pmeas_rpt,
+		       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(pmpriv->adapter, &pcmd_ptr->params.meas_req, pmeas_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(pmpriv->adapter, pcmd_ptr->params.meas_rpt.mac_addr,
+	       pmpriv->curr_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 100644
index 0000000..60240ec
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_meas.h
@@ -0,0 +1,55 @@
+/**
+ *  @file mlan_meas.h
+ *
+ *  @brief Interface for the measurement module implemented in mlan_meas.c
+ *
+ *  Driver interface functions and type declarations for the measurement module
+ *    implemented in mlan_meas.c
+ *
+ *  @sa mlan_meas.c
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+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(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);
+
+/* 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 100644
index 0000000..467ecba
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_misc.c
@@ -0,0 +1,5222 @@
+/**
+ * @file mlan_misc.c
+ *
+ *  @brief This file include miscellaneous functions for MLAN module
+ *
+ *  Copyright (C) 2009-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+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_sdio.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+extern mlan_operations *mlan_ops[];
+#endif
+extern t_u8 ac_to_tid[4][2];
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/** 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(IN pmlan_private pmpriv, IN 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(IN pmlan_private pmpriv,
+			      IN pmlan_ioctl_req pioctl_req,
+			      IN t_u16 mask,
+			      IN custom_ie *ie_data, OUT 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(IN pmlan_private pmpriv,
+			      IN pmlan_ioctl_req pioctl_req,
+			      IN custom_ie *ie_data, IN 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(pmpriv->adapter, del_ie, ie_data->ie_buffer,
+	       MIN(MAX_IE_SIZE, ie_data->ie_length));
+	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)
+			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(pmpriv->adapter, ie,
+				       pmpriv->mgmt_ie[index].ie_buffer, cnt);
+				if (pmpriv->mgmt_ie[index].ie_length >
+				    (cnt + del_len))
+					memcpy(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)));
+				memset(pmpriv->adapter,
+				       &pmpriv->mgmt_ie[index].ie_buffer, 0,
+				       sizeof(pmpriv->mgmt_ie[index].
+					      ie_buffer));
+				memcpy(pmpriv->adapter,
+				       &pmpriv->mgmt_ie[index].ie_buffer, ie,
+				       pmpriv->mgmt_ie[index].ie_length -
+				       del_len);
+				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     Do ACS
+ *
+ *  @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_acs(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_misc_acs *acs = MNULL;
+
+	ENTER();
+
+	if (pioctl_req != MNULL) {
+		misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+		acs = &misc->param.acs;
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	} else {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_ACS,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, (t_void *)acs);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(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;
+
+	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(IN pmlan_adapter pmadapter,
+			      IN 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(IN pmlan_adapter pmadapter,
+			 IN 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->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_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->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_cons_cmd_assoc_failure =
+			pmadapter->dbg.num_cons_cmd_assoc_failure;
+		debug_info->num_tx_timeout = pmadapter->dbg.num_tx_timeout;
+		debug_info->num_cmd_timeout = pmadapter->num_cmd_timeout;
+		debug_info->dbg_num_cmd_timeout =
+			pmadapter->dbg.num_cmd_timeout;
+		debug_info->timeout_cmd_id = pmadapter->dbg.timeout_cmd_id;
+		debug_info->timeout_cmd_act = pmadapter->dbg.timeout_cmd_act;
+		memcpy(pmadapter, debug_info->last_cmd_id,
+		       pmadapter->dbg.last_cmd_id,
+		       sizeof(pmadapter->dbg.last_cmd_id));
+		memcpy(pmadapter, debug_info->last_cmd_act,
+		       pmadapter->dbg.last_cmd_act,
+		       sizeof(pmadapter->dbg.last_cmd_act));
+		debug_info->last_cmd_index = pmadapter->dbg.last_cmd_index;
+		memcpy(pmadapter, debug_info->last_cmd_resp_id,
+		       pmadapter->dbg.last_cmd_resp_id,
+		       sizeof(pmadapter->dbg.last_cmd_resp_id));
+		debug_info->last_cmd_resp_index =
+			pmadapter->dbg.last_cmd_resp_index;
+		memcpy(pmadapter, debug_info->last_event,
+		       pmadapter->dbg.last_event,
+		       sizeof(pmadapter->dbg.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;
+		debug_info->mp_rd_bitmap = pmadapter->mp_rd_bitmap;
+		debug_info->mp_wr_bitmap = pmadapter->mp_wr_bitmap;
+		debug_info->curr_rd_port = pmadapter->curr_rd_port;
+		debug_info->curr_wr_port = pmadapter->curr_wr_port;
+		debug_info->mp_invalid_update = pmadapter->mp_invalid_update;
+		debug_info->num_of_irq = pmadapter->num_of_irq;
+		memcpy(pmadapter, debug_info->mp_update, pmadapter->mp_update,
+		       sizeof(pmadapter->mp_update));
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+		memcpy(pmadapter, debug_info->mpa_tx_count,
+		       pmadapter->mpa_tx_count,
+		       sizeof(pmadapter->mpa_tx_count));
+		debug_info->mpa_sent_last_pkt = pmadapter->mpa_sent_last_pkt;
+		debug_info->mpa_sent_no_ports = pmadapter->mpa_sent_no_ports;
+		debug_info->last_recv_wr_bitmap =
+			pmadapter->last_recv_wr_bitmap;
+		debug_info->last_mp_index = pmadapter->last_mp_index;
+		memcpy(pmadapter, debug_info->last_mp_wr_bitmap,
+		       pmadapter->last_mp_wr_bitmap,
+		       sizeof(pmadapter->last_mp_wr_bitmap));
+		memcpy(pmadapter, debug_info->last_mp_wr_ports,
+		       pmadapter->last_mp_wr_ports,
+		       sizeof(pmadapter->last_mp_wr_ports));
+		memcpy(pmadapter, debug_info->last_mp_wr_len,
+		       pmadapter->last_mp_wr_len,
+		       sizeof(pmadapter->last_mp_wr_len));
+		memcpy(pmadapter, debug_info->last_mp_wr_info,
+		       pmadapter->last_mp_wr_info,
+		       sizeof(pmadapter->last_mp_wr_info));
+		memcpy(pmadapter, debug_info->last_curr_wr_port,
+		       pmadapter->last_curr_wr_port,
+		       sizeof(pmadapter->last_curr_wr_port));
+		debug_info->mpa_buf = pmadapter->mpa_buf;
+		debug_info->mpa_buf_size = pmadapter->mpa_buf_size;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+		debug_info->sdio_rx_aggr = pmadapter->sdio_rx_aggr_enable;
+		memcpy(pmadapter, debug_info->mpa_rx_count,
+		       pmadapter->mpa_rx_count,
+		       sizeof(pmadapter->mpa_rx_count));
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+		debug_info->mp_aggr_pkt_limit =
+			pmadapter->psdio_device->mp_aggr_pkt_limit;
+#endif
+		debug_info->data_sent = pmadapter->data_sent;
+		debug_info->cmd_sent = pmadapter->cmd_sent;
+		debug_info->cmd_resp_received = pmadapter->cmd_resp_received;
+		debug_info->tx_pkts_queued =
+			util_scalar_read(pmadapter->pmoal_handle,
+					 &pmpriv->wmm.tx_pkts_queued, MNULL,
+					 MNULL);
+#ifdef UAP_SUPPORT
+		debug_info->num_bridge_pkts =
+			util_scalar_read(pmadapter->pmoal_handle,
+					 &pmadapter->pending_bridge_pkts,
+					 pmadapter->callbacks.moal_spin_lock,
+					 pmadapter->callbacks.moal_spin_unlock);
+		debug_info->num_drop_pkts = pmpriv->num_drop_pkts;
+#endif
+		debug_info->fw_hang_report = pmadapter->fw_hang_report;
+		debug_info->mlan_processing = pmadapter->mlan_processing;
+		debug_info->mlan_rx_processing = pmadapter->mlan_rx_processing;
+		debug_info->rx_pkts_queued = pmadapter->rx_pkts_queued;
+		debug_info->mlan_adapter = pmadapter;
+		debug_info->mlan_adapter_size = sizeof(mlan_adapter);
+		debug_info->mlan_priv_num = pmadapter->priv_num;
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			debug_info->mlan_priv[i] = pmadapter->priv[i];
+			debug_info->mlan_priv_size[i] = sizeof(mlan_private);
+		}
+	}
+
+	pioctl_req->data_read_written =
+		sizeof(mlan_debug_info) + MLAN_SUB_COMMAND_SIZE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get the MAC control configuration.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter,
+			    IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		misc->param.mac_ctrl = pmpriv->curr_pkt_filter;
+	} else {
+		pmpriv->curr_pkt_filter = misc->param.mac_ctrl;
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+		/* Send command to firmware */
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_MAC_CONTROL,
+				       cmd_action, 0,
+				       (t_void *)pioctl_req,
+				       &misc->param.mac_ctrl);
+
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This timer function handles wakeup card timeout.
+ *
+ *  @param function_context   A pointer to function_context
+ *  @return        N/A
+ */
+t_void
+wlan_wakeup_card_timeout_func(void *function_context)
+{
+	pmlan_adapter pmadapter = (pmlan_adapter)function_context;
+
+	ENTER();
+
+	PRINTM(MERROR, "%s: ps_state=%d\n", __FUNCTION__, pmadapter->ps_state);
+	if (pmadapter->ps_state != PS_STATE_AWAKE) {
+		PRINTM(MERROR, "Wakeup card timeout!\n");
+		wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+				MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+	}
+	pmadapter->wakeup_fw_timer_is_set = MFALSE;
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function wakes up the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *  @param timeout          set timeout flag
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pm_wakeup_card(IN pmlan_adapter pmadapter, IN t_u8 timeout)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 age_ts_usec;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+	PRINTM(MEVENT, "Wakeup device...\n");
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->pm_wakeup_in_secs,
+						  &age_ts_usec);
+
+	if (timeout) {
+		pmadapter->callbacks.moal_start_timer(pmadapter->pmoal_handle,
+						      pmadapter->
+						      pwakeup_fw_timer, MFALSE,
+						      MRVDRV_TIMER_3S);
+		pmadapter->wakeup_fw_timer_is_set = MTRUE;
+	}
+	ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+				  HOST_TO_CARD_EVENT_REG, HOST_POWER_UP);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function resets the PM setting of the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pm_reset_card(IN 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 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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 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();
+
+	/* make sure that the data length is at least SDIO block size */
+	data_len =
+		(data_len + MLAN_SDIO_BLOCK_SIZE -
+		 1) / MLAN_SDIO_BLOCK_SIZE * MLAN_SDIO_BLOCK_SIZE;
+
+	/* 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;
+		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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			IN 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;
+#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);
+
+		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(pmadapter, &pmpriv->ops, mlan_ops[j],
+				       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(IN pmlan_adapter pmadapter,
+			       IN pmlan_ioctl_req pioctl_req,
+			       IN 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(pmadapter,
+							       (t_u8 *)ie_data +
+							       len, &i,
+							       sizeof(ie_data->
+								      ie_index));
+							len += sizeof(ie_data->
+								      ie_index);
+							memcpy(pmadapter,
+							       (t_u8 *)ie_data +
+							       len,
+							       &pmpriv->
+							       mgmt_ie[i].
+							       mgmt_subtype_mask,
+							       sizeof(ie_data->
+								      mgmt_subtype_mask));
+							len += sizeof(ie_data->
+								      mgmt_subtype_mask);
+							memcpy(pmadapter,
+							       (t_u8 *)ie_data +
+							       len,
+							       &pmpriv->
+							       mgmt_ie[i].
+							       ie_length,
+							       sizeof(ie_data->
+								      ie_length));
+							len += sizeof(ie_data->
+								      ie_length);
+							if (pmpriv->mgmt_ie[i].
+							    ie_length) {
+								memcpy(pmadapter, (t_u8 *)ie_data + len, &pmpriv->mgmt_ie[i].ie_buffer, 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) {
+						ret = MLAN_STATUS_SUCCESS;
+						goto done;
+					}
+					tmp_ie = (t_u8 *)&pmpriv->
+						mgmt_ie[index].ie_buffer;
+					memcpy(pmadapter,
+					       tmp_ie +
+					       pmpriv->mgmt_ie[index].ie_length,
+					       &ie_data->ie_buffer,
+					       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(pmadapter, &ie_data->ie_buffer,
+					       &pmpriv->mgmt_ie[index].
+					       ie_buffer,
+					       pmpriv->mgmt_ie[index].
+					       ie_length);
+					misc->param.cust_ie.len +=
+						pmpriv->mgmt_ie[index].
+						ie_length +
+						MLAN_CUSTOM_IE_HDR_SIZE;
+				}
+			} else {
+				if (index >= pmadapter->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(pmadapter, (t_u8 *)ie_data,
+					       &pmpriv->mgmt_ie[index],
+					       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(pmadapter,
+					       &pmpriv->mgmt_ie[index], ie_data,
+					       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(IN pmlan_adapter pmadapter,
+			  IN 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:
+		cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
+		break;
+	case MLAN_REG_BBP:
+		cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
+		break;
+	case MLAN_REG_RF:
+		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;
+	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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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,
+			     MNULL,
+			     MNULL))) {
+		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;
+	mlan_adapter *pmadapter = priv->adapter;
+
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		goto done;
+	if (priv->adapter->callbacks.
+	    moal_malloc(priv->adapter->pmoal_handle, sizeof(sta_node),
+			MLAN_MEM_DEF, (t_u8 **)&sta_ptr)) {
+		PRINTM(MERROR, "Failed to allocate memory for station node\n");
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		LEAVE();
+		return MNULL;
+	}
+	memset(priv->adapter, sta_ptr, 0, sizeof(sta_node));
+	memcpy(priv->adapter, sta_ptr->mac_addr, mac, MLAN_MAC_ADDR_LENGTH);
+	util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->sta_list,
+			       (pmlan_linked_list)sta_ptr,
+			       MNULL,
+			       MNULL);
+done:
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return sta_ptr;
+}
+
+/**
+ *  @brief This function will delete a station entry from station list
+ *
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     station's mac address
+ *
+ *  @return	   N/A
+ */
+t_void
+wlan_delete_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	mlan_adapter *pmadapter = priv->adapter;
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr) {
+		util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list,
+				 (pmlan_linked_list)sta_ptr,
+				 MNULL,
+				 MNULL);
+		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
+						    (t_u8 *)sta_ptr);
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Clean up wapi station list
+ *
+ *  @param priv  Pointer to the mlan_private driver data struct
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_delete_station_list(pmlan_private priv)
+{
+	sta_node *sta_ptr = MNULL;
+	mlan_adapter *pmadapter = priv->adapter;
+	pmadapter->callbacks.moal_spin_lock(
+			pmadapter->pmoal_handle,
+			priv->wmm.ra_list_spinlock);
+
+	ENTER();
+	while ((sta_ptr =
+		(sta_node *)util_dequeue_list(priv->adapter->pmoal_handle,
+					      &priv->sta_list,
+					      MNULL,
+					      MNULL))) {
+		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
+						    (t_u8 *)sta_ptr);
+	}
+	pmadapter->callbacks.moal_spin_unlock(
+			pmadapter->pmoal_handle,
+			priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief 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,
+					     MNULL,
+					     MNULL);
+	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(priv->adapter, peer_info->mac_addr,
+			       sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH);
+			memcpy(priv->adapter, peer_info->ht_cap,
+			       &sta_ptr->HTcap, sizeof(IEEEtypes_HTCap_t));
+			memcpy(priv->adapter, peer_info->ext_cap,
+			       &sta_ptr->ExtCap, sizeof(IEEEtypes_ExtCap_t));
+			memcpy(priv->adapter, peer_info->vht_cap,
+			       &sta_ptr->vht_cap, sizeof(IEEEtypes_VHTCap_t));
+			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(IN pmlan_adapter pmadapter,
+			    IN 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(pmpriv->adapter, (t_u8 *)tdls_evt->peer_mac_addr,
+			       tdls_all_cfg->u.tdls_tear_down.peer_mac_addr,
+			       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)pMrvlTlv->header.len;
+				memset(pmadapter, pmpriv->chan_supp, 0,
+				       sizeof(pmpriv->chan_supp));
+				memcpy(pmadapter, pmpriv->chan_supp,
+				       pMrvlTlv->data, MIN(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)pMrvlTlv->header.len;
+				memset(pmadapter, pmpriv->supp_regulatory_class,
+				       0,
+				       sizeof(pmpriv->supp_regulatory_class));
+				memcpy(pmadapter, pmpriv->supp_regulatory_class,
+				       pMrvlTlv->data, MIN(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	        N/A
+ */
+t_void
+wlan_tdls_config(IN pmlan_private pmpriv, IN 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	        N/A
+ */
+t_void
+wlan_tdls_cs_param_config(IN 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	         N/A
+ */
+t_void
+wlan_tdls_cs_start(IN pmlan_private pmpriv,
+		   IN t_u8 *peer_mac_addr, IN 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(pmpriv->adapter, tdls_config, &misc->param.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(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(pmpriv->adapter,
+		       tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr,
+		       peer_mac_addr, 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->
+							       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();
+}
+
+/**
+ *  @brief stop tdls channel switch
+ *
+ *  @param pmpriv	A pointer to mlan_private structure
+ *  @param peer_mac_addr 	A pointer to peer mac address
+ *  @return	                N/A
+ */
+t_void
+wlan_tdls_cs_stop(IN pmlan_private pmpriv, IN 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(pmpriv->adapter,
+	       tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
+	       peer_mac_addr, 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();
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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(pmpriv->adapter,
+				       (t_u8 *)tdls_evt->peer_mac_addr,
+				       ptdls_oper->peer_mac,
+				       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
+ */
+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(pmadapter, (t_u8 *)ext_cap,
+		       (t_u8 *)pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t),
+		       pbss_desc->pext_cap->ieee_hdr.len);
+	}
+	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(IN pmlan_adapter pmadapter,
+			     IN 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(pmadapter, &sta_ptr->vht_oprat,
+			       tdls_ies->vht_oprat,
+			       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(pbss_desc->
+							       channel);
+		}
+		if (vht_oprat &&
+		    vht_oprat->ieee_hdr.element_id == VHT_OPERATION) {
+			ht_info->ht_info.field2 =
+				wlan_get_second_channel_offset(pbss_desc->
+							       channel);
+			ht_info->ht_info.field2 |= MBIT(2);
+		}
+		if (sta_ptr)
+			memcpy(pmadapter, &sta_ptr->HTInfo, tdls_ies->ht_info,
+			       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(pmadapter, pSupp_chan->data, pmpriv->chan_supp,
+			       pmpriv->chan_supp_len);
+		} else {
+			pSupp_chan->ieee_hdr.len = sizeof(supp_chan);
+			memcpy(pmadapter, pSupp_chan->data, supp_chan,
+			       sizeof(supp_chan));
+		}
+		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(pmadapter, pRegulatory_class->data,
+			       pmpriv->supp_regulatory_class,
+			       pmpriv->supp_regulatory_class_len);
+		} else {
+			pRegulatory_class->ieee_hdr.len =
+				sizeof(regulatory_class);
+			memcpy(pmadapter, pRegulatory_class->data,
+			       regulatory_class, sizeof(regulatory_class));
+		}
+		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 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(IN pmlan_adapter pmadapter, IN 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;
+}
+
+#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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(IN mlan_private *priv,
+			       IN t_u8 *payload,
+			       IN t_u32 payload_len, IN 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;
+	MrvlIETypes_MgmtFrameSet_t *tlv;
+	pmlan_buffer pmbuf;
+	sta_node *sta_ptr = MNULL;
+	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:
+		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(pmadapter, (t_u8 *)&tlv->frame_control, &pieee_pkt_hdr->frm_ctl,
+						sizeof(IEEEtypes_FrameCtl_t));
+						pmbuf->data_len += sizeof(MrvlIETypes_MgmtFrameSet_t);
+						memcpy(pmadapter, pmbuf->pbuf + pmbuf->data_offset + pmbuf->data_len, payload + 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;
+	case SUBTYPE_DISASSOC:
+	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_DEAUTH:
+		if (memcmp
+		    (pmadapter, pieee_pkt_hdr->addr1, broadcast,
+		     MLAN_MAC_ADDR_LENGTH))
+			unicast = MTRUE;
+		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));
+				}
+			}
+			if(priv->bss_role == MLAN_BSS_ROLE_STA){
+				if(priv->curr_bss_params.host_mlme){
+					if(memcmp(pmadapter, pieee_pkt_hdr->addr2,(t_u8 *)priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH)){
+						PRINTM(MINFO, "Dropping mgmt frame from others: type=%d "MACSTR"\n",
+						sub_type,MAC2STR(pieee_pkt_hdr->addr2));
+						LEAVE();
+						return ret;
+					}
+					PRINTM_NETINTF(MMSG, priv);
+					PRINTM(MMSG, "wlan: HostMlme Disconnected: sub_type=%d\n",sub_type);
+					pmadapter->pending_disconnect_priv = priv;
+					wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
+				}
+			}
+		break;
+	case SUBTYPE_ACTION:
+		category = *(payload + sizeof(wlan_802_11_header));
+		action_code = *(payload + sizeof(wlan_802_11_header) + 1);
+		if (category == IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK) {
+			PRINTM(MINFO,
+			       "Drop BLOCK ACK action frame: action_code=%d\n",
+			       action_code);
+			LEAVE();
+			return ret;
+		}
+		if ((category == IEEE_MGMT_ACTION_CATEGORY_PUBLIC) &&
+		    (action_code == BSS_20_40_COEX)) {
+			PRINTM(MINFO,
+			       "Drop 20/40 BSS Coexistence Management frame\n");
+			LEAVE();
+			return ret;
+		}
+		if ((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(pmadapter, (t_u8 *)pevent->event_buf,
+		       &mgmt->u.ft_resp.target_ap_addr, MLAN_MAC_ADDR_LENGTH);
+		memcpy(pmadapter,
+		       (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+		       payload + FT_ACTION_HEAD_LEN,
+		       payload_len - FT_ACTION_HEAD_LEN);
+	} 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(pmadapter, (t_u8 *)pevent->event_buf, mgmt->sa,
+		       MLAN_MAC_ADDR_LENGTH);
+		memcpy(pmadapter,
+		       (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+		       payload + AUTH_PACKET_LEN,
+		       payload_len - AUTH_PACKET_LEN);
+	} else {
+		pevent->event_id = MLAN_EVENT_ID_DRV_MGMT_FRAME;
+		pevent->event_len = payload_len + sizeof(pevent->event_id);
+		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+		       (t_u8 *)&pevent->event_id, sizeof(pevent->event_id));
+		memcpy(pmadapter,
+		       (t_u8 *)(pevent->event_buf + sizeof(pevent->event_id)),
+		       payload, 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(IN pmlan_adapter pmadapter,
+		       IN 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(pmpriv->adapter, &misc->param.ext_cap,
+		       &pmpriv->def_ext_cap, sizeof(misc->param.ext_cap));
+	else if (MLAN_ACT_SET == pioctl_req->action) {
+		memcpy(pmpriv->adapter, &pmpriv->ext_cap, &misc->param.ext_cap,
+		       sizeof(misc->param.ext_cap));
+		/* Save default Extended Capability */
+		memcpy(pmpriv->adapter, &pmpriv->def_ext_cap, &pmpriv->ext_cap,
+		       sizeof(pmpriv->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(IN pmlan_adapter pmadapter, IN 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 pptlv_out          A pointer to TLV to fill in
+ *
+ *  @return                   N/A
+ */
+void
+wlan_add_ext_capa_info_ie(IN mlan_private *pmpriv, OUT 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);
+	memcpy(pmpriv->adapter, &pext_cap->ext_cap, &pmpriv->ext_cap,
+	       sizeof(pmpriv->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(IN pmlan_adapter pmadapter,
+			IN 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;
+#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(priv->adapter, &frame_control,
+			       (t_u8 *)&(mgmt_tlv->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);
+				if (pht_cap) {
+					PRINTM(MCMND, "STA supports 11n\n");
+					sta_ptr->is_11n_enabled = MTRUE;
+					memcpy(priv->adapter,
+					       (t_u8 *)&sta_ptr->HTcap, pht_cap,
+					       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);
+				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");
+				}
+#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);
+				erp = wlan_get_specific_ie(priv, assoc_req_ie,
+							   ie_len, ERP_INFO);
+				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_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
+				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
+ *
+ *  @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_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;
+
+	ENTER();
+
+	DBG_HEXDUMP(MCMD_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);
+		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 (element_id == id) {
+			PRINTM(MCMND, "Find IE: id=%d\n", id);
+			DBG_HEXDUMP(MCMND, "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(IN pmlan_adapter pmadapter, IN 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)
+	    || pmadapter->sdio_ireg) {
+		pm_cfg->param.ps_info.is_suspend_allowed = MFALSE;
+		PRINTM(MIOCTL,
+		       "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d sdio_ireg=0x%x\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),
+		       pmadapter->sdio_ireg);
+	}
+	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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(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_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 (!ant_cfg->tx_antenna ||
+			    bitcount(ant_cfg->tx_antenna & 0xFFFF) >
+			    pmadapter->number_of_antenna) {
+				PRINTM(MERROR, "Invalid antenna setting\n");
+				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 & 0xFFFF) >
+				    pmadapter->number_of_antenna) {
+					PRINTM(MERROR,
+					       "Invalid antenna setting\n");
+					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(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];
+
+	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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			       IN 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 (!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(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];
+
+	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(IN pmlan_adapter pmadapter,
+			       IN 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 < 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_HRDSSS0) &&
+			    (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_MCS0) &&
+			    (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 (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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			      IN 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(IN pmlan_adapter pmadapter,
+				 IN 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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_P2P_PARAMS_CONFIG,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc_cfg->param.p2p_config);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set coalesce config
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,
+			     IN 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 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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+				       IN 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 Get/Set channel time and buffer weight 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_multi_chan_config(IN pmlan_adapter pmadapter,
+				  IN 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_MULTI_CHAN_CONFIG,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc->param.multi_chan_cfg);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set multi-channel policy setting
+ *
+ *  @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_multi_chan_policy(IN pmlan_adapter pmadapter,
+				  IN 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) {
+		if (pmadapter->dfs_repeater) {
+			PRINTM(MMSG,
+			       "DFS-Repeater is on, can not enable DRCS\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto fail;
+		}
+		cmd_action = HostCmd_ACT_GEN_SET;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_MULTI_CHAN_POLICY,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc->param.multi_chan_policy);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+fail:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set DRCS 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_drcs_config(IN pmlan_adapter pmadapter,
+			    IN 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_DRCS_CONFIG,
+			       cmd_action,
+			       0, (t_void *)pioctl_req, &misc->param.drcs_cfg);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+				 IN 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;
+		}
+
+		/* If DRCS is on then we should not set
+		 * DFS-repeater mode */
+		if (pmadapter->mc_policy) {
+			PRINTM(MERROR,
+			       "DFS-repeater cannot be started when DRCS is on\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(IN pmlan_adapter pmadapter,
+			     IN 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(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];
+
+	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 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(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_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;
+
+	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(pmadapter,
+					       &sec->param.passphrase.ssid,
+					       &pbss_desc->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/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(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;
+	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  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(IN pmlan_adapter pmadapter,
+			IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(IN pmlan_adapter pmadapter,
+				     IN 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(IN pmlan_adapter pmadapter, IN mlan_ioctl_req *pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_CHAN_REGION_CFG,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+
+}
+
+/**
+ *  @brief  Get CHAN_TPRC setting
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_get_chan_trpc_cfg(IN pmlan_adapter pmadapter,
+		       IN 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(IN pmlan_adapter pmadapter,
+			   IN 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;
+	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(IN pmlan_adapter pmadapter,
+			      IN mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_FW_DUMP_EVENT,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief config boot sleep
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_bootsleep(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req)
+{
+	t_u8 i, global_band = 0;
+	t_u8 chan_offset;
+	t_u8 infra_band = 0;
+	t_u8 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 = (t_u8)radio_cfg->param.band_cfg.config_bands;
+		adhoc_band = (t_u8)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 |= 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
+		pmadapter->chan_bandwidth =
+			(t_u8)radio_cfg->param.band_cfg.adhoc_chan_bandwidth;
+		/*
+		 * 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)
+				    || (pmadapter->adhoc_start_band & BAND_AN)
+					) {
+					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;
+		}
+		/* validate the channel offset */
+		chan_offset = wlan_validate_chan_offset(pmpriv,
+							pmadapter->
+							adhoc_start_band,
+							pmpriv->adhoc_channel,
+							pmadapter->
+							chan_bandwidth);
+
+		if (chan_offset != SEC_CHAN_NONE) {
+			if (chan_offset == SEC_CHAN_ABOVE)
+				pmadapter->chan_bandwidth =
+					CHANNEL_BW_40MHZ_ABOVE;
+			else
+				pmadapter->chan_bandwidth =
+					CHANNEL_BW_40MHZ_BELOW;
+		}
+		if ((adhoc_band & BAND_GN)
+		    || (adhoc_band & BAND_AN)
+			) {
+			pmadapter->adhoc_11n_enabled = MTRUE;
+		} else {
+			pmadapter->adhoc_11n_enabled = MFALSE;
+		}
+#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
+		/* adhoc channel bandwidth */
+		radio_cfg->param.band_cfg.adhoc_chan_bandwidth =
+			pmadapter->chan_bandwidth;
+#endif
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/wlan_sd8987/mlan/mlan_module.c b/wlan_sd8987/mlan/mlan_module.c
new file mode 100644
index 0000000..5a6d0d6
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_module.c
@@ -0,0 +1,55 @@
+/** @file mlan_module.c
+ *
+ *  @brief This file declares the exported symbols from MLAN.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    12/08/2008: initial version
+******************************************************/
+
+#ifdef LINUX
+#include <linux/module.h>
+#include "mlan_decl.h"
+#include "mlan_ioctl.h"
+
+EXPORT_SYMBOL(mlan_dump_adapter);
+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);
+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_interrupt);
+#if defined(SYSKT)
+EXPORT_SYMBOL(mlan_hs_callback);
+#endif /* SYSKT_MULTI || SYSKT */
+
+EXPORT_SYMBOL(mlan_pm_wakeup_card);
+EXPORT_SYMBOL(mlan_is_main_process_running);
+
+MODULE_DESCRIPTION("M-WLAN MLAN Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_VERSION(MLAN_RELEASE_VERSION);
+MODULE_LICENSE("GPL");
+#endif /* LINUX */
diff --git a/wlan_sd8987/mlan/mlan_scan.c b/wlan_sd8987/mlan/mlan_scan.c
new file mode 100644
index 0000000..d9d4ba2
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_scan.c
@@ -0,0 +1,5932 @@
+/** @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 (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_11h.h"
+/********************************************************
+			Local Constants
+********************************************************/
+/** minimum scan time for passive to active scan */
+#define MIN_PASSIVE_TO_ACTIVE_SCAN_TIME 150
+
+/** 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))
+
+/** 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        \
+				+ WPS_TLV_MAX_SIZE)
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/**
+ * Interally used to send a configured scan cmd between
+ * driver routines
+ */
+typedef union {
+    /** Scan configuration (variable length) */
+	wlan_scan_cmd_config config;
+    /** Max allocated block */
+	t_u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
+} wlan_scan_cmd_config_tlv;
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+/** Cipher suite definition */
+enum cipher_suite {
+	CIPHER_SUITE_WEP40,
+	CIPHER_SUITE_TKIP,
+	CIPHER_SUITE_CCMP,
+	CIPHER_SUITE_WEP104,
+	CIPHER_SUITE_GCMP,
+	CIPHER_SUITE_GCMP_256,
+	CIPHER_SUITE_CCMP_256,
+	CIPHER_SUITE_MAX
+};
+
+static t_u8 wpa_oui[CIPHER_SUITE_MAX][4] = {
+	{0x00, 0x50, 0xf2, 0x01},	/* WEP40 */
+	{0x00, 0x50, 0xf2, 0x02},	/* TKIP */
+	{0x00, 0x50, 0xf2, 0x04},	/* AES */
+	{0x00, 0x50, 0xf2, 0x05},	/* WEP104 */
+};
+
+static t_u8 rsn_oui[CIPHER_SUITE_MAX][4] = {
+	{0x00, 0x0f, 0xac, 0x01},	/* WEP40 */
+	{0x00, 0x0f, 0xac, 0x02},	/* TKIP */
+	{0x00, 0x0f, 0xac, 0x04},	/* AES */
+	{0x00, 0x0f, 0xac, 0x05},	/* WEP104 */
+	{0x00, 0x0f, 0xac, 0x08},	/* GCMP */
+	{0x00, 0x0f, 0xac, 0x09},	/* GCMP-256 */
+	{0x00, 0x0f, 0xac, 0x0a},	/* CCMP-256 */
+};
+
+/**
+ *  @brief Convert radio type scan parameter to a band config used in join cmd
+ *
+ *  @param radio_type Scan parameter indicating the radio used for a channel
+ *                    in a scan command.
+ *
+ *  @return          Band type conversion of scanBand used in join/assoc cmds
+ *
+ */
+t_u8
+radio_type_to_band(t_u8 radio_type)
+{
+	t_u8 ret_band;
+
+	switch (radio_type) {
+	case BAND_5GHZ:
+		ret_band = BAND_A;
+		break;
+	case BAND_2GHZ:
+	default:
+		ret_band = BAND_G;
+		break;
+	}
+
+	return ret_band;
+}
+
+/**
+ *  @brief This function will update the channel statistics from scan result
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param pchanstats_tlv   A pointer to MrvlIEtypes_ChannelStats_t tlv
+ *
+ *  @return                NA
+ */
+void
+wlan_update_chan_statistics(mlan_private *pmpriv,
+			    MrvlIEtypes_ChannelStats_t *pchanstats_tlv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 i;
+	ChanStatistics_t *pchan_stats =
+		(ChanStatistics_t *)((t_u8 *)pchanstats_tlv +
+				     sizeof(MrvlIEtypesHeader_t));
+	t_u8 num_chan =
+		wlan_le16_to_cpu(pchanstats_tlv->header.len) /
+		sizeof(ChanStatistics_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(pmadapter,
+		       &pmadapter->pchan_stats[pmadapter->idx_chan_stats],
+		       pchan_stats, sizeof(ChanStatistics_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))) {
+		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 pbss_desc for appropriate IE and then check if WPA IE has AES
+ *  OUI in it. If WPA IE does not have AES in PTK then return 0;
+ *
+ *  @param pbss_desc       A pointer to current BSS descriptor
+ *  @return                0 on failure to find AES OUI, 1 on success.
+ */
+static t_u8
+is_wpa_oui_present(mlan_adapter *pmadapter, BSSDescriptor_t *pbss_desc,
+		   t_u32 cipher_suite)
+{
+	t_u8 *oui = MNULL;
+	IEBody *ie_body = MNULL;
+	t_u8 ret = MLAN_OUI_NOT_PRESENT;
+
+	ENTER();
+	if (((pbss_desc->pwpa_ie) &&
+	     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE))) {
+		ie_body = (IEBody *)pbss_desc->pwpa_ie->data;
+		oui = &wpa_oui[cipher_suite][0];
+		ret = search_oui_in_ie(pmadapter, ie_body, oui);
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief compare config band and a band from the scan result,
+ *  which is defined by functiion radio_type_to_band(t_u8 radio_type) above
+ *
+ *  @param cfg_band:  band configured
+ *         scan_band: band from scan result
+ *
+ *  @return  matched: non-zero. unmatched: 0
+ *
+ */
+static t_u8
+wlan_is_band_compatible(t_u8 cfg_band, t_u8 scan_band)
+{
+	t_u8 band;
+	switch (scan_band) {
+	case BAND_A:
+		band = BAND_A | BAND_AN | BAND_AAC;
+		break;
+	case BAND_G:
+	default:
+		band = BAND_B | BAND_G | BAND_GN | BAND_GAC;
+	}
+	return cfg_band & band;
+}
+
+/**
+ *  @brief This function finds the best SSID in the Scan List
+ *
+ *  Search the scan table for the best SSID that also matches the current
+ *   adapter network preference (infrastructure or adhoc)
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @return             index in BSSID list
+ */
+static t_s32
+wlan_find_best_network_in_list(IN mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u32 mode = pmpriv->bss_mode;
+	t_s32 best_net = -1;
+	t_s32 best_rssi = 0;
+	t_u32 i;
+
+	ENTER();
+
+	PRINTM(MINFO, "Num of BSSIDs = %d\n", pmadapter->num_in_scan_table);
+
+	for (i = 0; i < pmadapter->num_in_scan_table; i++) {
+		switch (mode) {
+		case MLAN_BSS_MODE_INFRA:
+		case MLAN_BSS_MODE_IBSS:
+			if (wlan_is_network_compatible(pmpriv, i, mode) >= 0) {
+				if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+				    best_rssi) {
+					best_rssi =
+						SCAN_RSSI(pmadapter->
+							  pscan_table[i].rssi);
+					best_net = i;
+				}
+			}
+			break;
+		case MLAN_BSS_MODE_AUTO:
+		default:
+			if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+			    best_rssi) {
+				best_rssi =
+					SCAN_RSSI(pmadapter->pscan_table[i].
+						  rssi);
+				best_net = i;
+			}
+			break;
+		}
+	}
+
+	LEAVE();
+	return best_net;
+}
+
+/**
+ *  @brief Create a channel list for the driver to scan based on region info
+ *
+ *  Use the driver region/band information to construct a comprehensive list
+ *    of channels to scan.  This routine is used for any scan that is not
+ *    provided a specific channel list to scan.
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param puser_scan_in    MNULL or pointer to scan configuration parameters
+ *  @param pscan_chan_list  Output parameter: Resulting channel list to scan
+ *  @param filtered_scan    Flag indicating whether or not a BSSID or SSID filter
+ *                          is being sent in the command to firmware.  Used to
+ *                          increase the number of channels sent in a scan
+ *                          command and to disable the firmware channel scan
+ *                          filter.
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_scan_create_channel_list(IN mlan_private *pmpriv,
+			      IN const wlan_user_scan_cfg *puser_scan_in,
+			      OUT ChanScanParamSet_t *pscan_chan_list,
+			      IN t_u8 filtered_scan)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	region_chan_t *pscan_region;
+	chan_freq_power_t *cfp;
+	t_u32 region_idx;
+	t_u32 chan_idx = 0;
+	t_u32 next_chan;
+	t_u8 scan_type;
+	t_u8 radio_type;
+	t_u8 band;
+	t_u16 scan_dur = 0;
+
+	ENTER();
+
+	for (region_idx = 0;
+	     region_idx < NELEMENTS(pmadapter->region_channel); region_idx++) {
+
+		if (wlan_11d_is_enabled(pmpriv) &&
+		    pmpriv->media_connected != MTRUE) {
+			/* Scan all the supported chan for the first scan */
+			if (!pmadapter->universal_channel[region_idx].valid)
+				continue;
+			pscan_region =
+				&pmadapter->universal_channel[region_idx];
+		} else {
+			if (!pmadapter->region_channel[region_idx].valid)
+				continue;
+			pscan_region = &pmadapter->region_channel[region_idx];
+		}
+
+		if (puser_scan_in && !puser_scan_in->chan_list[0].chan_number &&
+		    puser_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
+			radio_type =
+				puser_scan_in->chan_list[0].
+				radio_type & ~BAND_SPECIFIED;
+			if (!radio_type && (pscan_region->band != BAND_B) &&
+			    (pscan_region->band != BAND_G))
+				continue;
+			if (radio_type && (pscan_region->band != BAND_A))
+				continue;
+		}
+		if ((puser_scan_in &&
+		     (puser_scan_in->bss_mode == MLAN_SCAN_MODE_IBSS)) ||
+		    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+			band = pmadapter->adhoc_start_band;
+		else
+			band = pmpriv->config_bands;
+		if (!wlan_is_band_compatible(band, pscan_region->band))
+			continue;
+		for (next_chan = 0;
+		     next_chan < pscan_region->num_cfp;
+		     next_chan++, chan_idx++) {
+			/* 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;
+
+			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_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;
+			} else {
+				pscan_chan_list[chan_idx].chan_scan_mode.
+					passive_scan = MFALSE;
+			}
+
+			pscan_chan_list[chan_idx].chan_number =
+				(t_u8)cfp->channel;
+			PRINTM(MINFO,
+			       "chan=%d, mode=%d, passive_to_active=%d\n",
+			       pscan_chan_list[chan_idx].chan_number,
+			       pscan_chan_list[chan_idx].chan_scan_mode.
+			       passive_scan,
+			       pscan_chan_list[chan_idx].chan_scan_mode.
+			       passive_to_active_scan);
+
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares command of sending acs.
+ *
+ *  @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_acs(IN pmlan_private pmpriv,
+	     IN HostCmd_DS_COMMAND *cmd,
+	     IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	mlan_ds_misc_acs *acs_param = (mlan_ds_misc_acs *) pdata_buf;
+	HostCmd_DS_ACS *acs_cmd = (HostCmd_DS_ACS *) & cmd->params.acs;
+	t_u8 *ptlv_pos = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchanlist_tlv = MNULL;
+	MrvlIEtypes_ScanChanGap_t *pscangap_tlv = MNULL;
+	t_u32 buf_size = 0;
+	ChanScanParamSet_t *pscan_chan_list = MNULL;
+	t_u32 i = 0;
+	t_u32 scan_type = 0;
+	t_u16 scan_dur = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ACS);
+	cmd->size = sizeof(HostCmd_DS_ACS) + S_DS_GEN;
+
+	buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
+	status = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
+				  MLAN_MEM_DEF, (t_u8 **)&pscan_chan_list);
+	if (status != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
+		PRINTM(MERROR,
+		       "wlan_cmd_acs: Failed to allocate scan_chan_list\n");
+		goto done;
+	}
+	memset(pmadapter, pscan_chan_list, 0x00, buf_size);
+
+    /** Prepare channel list, we will use it to fill into MrvlIEtypes_ChanListParamSet_t */
+	if (acs_param->ch_stats_num) {
+		PRINTM(MCMND, "ACS using user specified channels\n");
+		for (i = 0; i < MIN(MAX_CH_STATS, acs_param->ch_stats_num); i++) {
+			if (!acs_param->ch_stats[i].chan_num)
+				continue;
+
+	    /** Set the fields in pscan_chan_list */
+	    /** Set chan_number */
+			pscan_chan_list[i].chan_number =
+				acs_param->ch_stats[i].chan_num;
+
+	    /** Set bandcfg */
+			if (acs_param->ch_stats[i].chan_num <= 14)
+				pscan_chan_list[i].bandcfg.chanBand = BAND_2GHZ;
+			else
+				pscan_chan_list[i].bandcfg.chanBand = BAND_5GHZ;
+			if (pscan_chan_list[i].bandcfg.chanBand == BAND_5GHZ) {
+				if (pmadapter->fw_bands & BAND_A)
+					PRINTM(MINFO,
+					       "UserScan request for A Band channel %d!!\n",
+					       pscan_chan_list[i].chan_number);
+				else {
+					PRINTM(MERROR,
+					       "Scan in A band is not allowed!!\n");
+					status = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+			}
+
+	    /** Set chan_scan_mode */
+			scan_type = pmadapter->scan_type;
+	    /** Prevent active scanning on a radar controlled channel */
+			if (pscan_chan_list[i].bandcfg.chanBand == BAND_5GHZ) {
+				if (wlan_11h_radar_detect_required
+				    (pmpriv, pscan_chan_list[i].chan_number))
+					scan_type = MLAN_SCAN_TYPE_PASSIVE;
+			}
+			if (pscan_chan_list[i].bandcfg.chanBand == BAND_2GHZ) {
+				if (wlan_bg_scan_type_is_passive
+				    (pmpriv, pscan_chan_list[i].chan_number))
+					scan_type = MLAN_SCAN_TYPE_PASSIVE;
+			}
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				pscan_chan_list[i].chan_scan_mode.passive_scan =
+					MTRUE;
+			} else
+				pscan_chan_list[i].chan_scan_mode.passive_scan =
+					MFALSE;
+
+	    /** Set min_scan_time & max_scan_time */
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
+				scan_dur = pmadapter->passive_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;
+			pscan_chan_list[i].min_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+			pscan_chan_list[i].max_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+		}
+	} else {
+		PRINTM(MCMND, "ACS using full region channel list\n");
+		wlan_scan_create_channel_list(pmpriv, MNULL, pscan_chan_list,
+					      MFALSE);
+	}
+
+	ptlv_pos = acs_cmd->tlv_buffer;
+
+	if (!pscan_chan_list[0].chan_number) {
+		PRINTM(MERROR, "No valid chan_number in pscan_chan_list\n");
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pchanlist_tlv = (MrvlIEtypes_ChanListParamSet_t *)ptlv_pos;
+	pchanlist_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+	pchanlist_tlv->header.len = 0;
+	PRINTM(MCMND, "--- pscan_chan_list ---\n");
+	for (i = 0;
+	     i < WLAN_USER_SCAN_CHAN_MAX && pscan_chan_list[i].chan_number;
+	     i++) {
+		memcpy(pmadapter, &(pchanlist_tlv->chan_scan_param[i]),
+		       &(pscan_chan_list[i]), sizeof(ChanScanParamSet_t));
+		pchanlist_tlv->header.len += sizeof(ChanScanParamSet_t);
+		PRINTM(MCMND,
+		       "[%d] chan_number=%d bandcfg=0x%x chan_scan_mode=0x%x scan_time=%d~%d\n",
+		       i, pscan_chan_list[i].chan_number,
+		       pscan_chan_list[i].bandcfg,
+		       pscan_chan_list[i].chan_scan_mode,
+		       pscan_chan_list[i].min_scan_time,
+		       pscan_chan_list[i].max_scan_time);
+	}
+	ptlv_pos += sizeof(pchanlist_tlv->header) + pchanlist_tlv->header.len;
+	pchanlist_tlv->header.len = wlan_cpu_to_le16(pchanlist_tlv->header.len);
+
+	pscangap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
+	pscangap_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
+	pscangap_tlv->header.len = sizeof(pscangap_tlv->gap);
+	pscangap_tlv->gap = wlan_cpu_to_le16(acs_param->scan_chan_gap);
+	ptlv_pos += sizeof(pscangap_tlv->header) + pscangap_tlv->header.len;
+	pscangap_tlv->header.len = wlan_cpu_to_le16(pscangap_tlv->header.len);
+
+	cmd->size += ptlv_pos - acs_cmd->tlv_buffer;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+done:
+	if (pscan_chan_list)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pscan_chan_list);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function handles the command response of acs
+ *
+ *  @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_acs(IN pmlan_private pmpriv,
+	     IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *cfg = MNULL;
+	mlan_ds_misc_acs *acs_param = MNULL;
+	HostCmd_DS_ACS *acs_cmd = (HostCmd_DS_ACS *) & resp->params.acs;
+	int left_len = resp->size;
+	t_u8 *tlv_pos = MNULL;
+	MrvlIEtypesHeader_t *tlv_ie = MNULL;
+	MrvlIEtypes_ChannelStats_t *tlv_ch_stats = MNULL;
+	ChanStatistics_t *ch_stats = MNULL;
+	int ch_stats_num = 0;
+	int i = 0;
+	t_u16 tlv_id = 0;
+	int tlv_ie_len = 0;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		acs_param = &cfg->param.acs;
+		memset(pmpriv->adapter, acs_param, 0x00, sizeof(*acs_param));
+		acs_param->best_ch = acs_cmd->best_ch;
+
+		left_len -= S_DS_GEN + sizeof(HostCmd_DS_ACS);
+		tlv_pos = acs_cmd->tlv_buffer;
+		while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+			tlv_ie = (MrvlIEtypesHeader_t *)(tlv_pos);
+			tlv_id = wlan_le16_to_cpu(tlv_ie->type);
+			tlv_ie_len = wlan_le16_to_cpu(tlv_ie->len);
+			PRINTM(MCMND, "[TLV: id=0x%x len=%d]  left_len=%d\n",
+			       tlv_id, tlv_ie_len, left_len);
+			if ((tlv_id == TLV_TYPE_CHANNEL_STATS) &&
+			    (tlv_ie_len >= sizeof(ChanStatistics_t))) {
+				tlv_ch_stats =
+					(MrvlIEtypes_ChannelStats_t *)tlv_ie;
+				ch_stats = tlv_ch_stats->chanStat;
+				ch_stats_num =
+					tlv_ie_len / sizeof(ChanStatistics_t);
+				for (i = 0; i < MIN(ch_stats_num, MAX_CH_STATS);
+				     i++) {
+					if (ch_stats[i].chan_num) {
+						acs_param->ch_stats[i].
+							chan_num =
+							ch_stats[i].chan_num;
+						acs_param->ch_stats[i].
+							total_networks =
+							wlan_le16_to_cpu
+							(ch_stats[i].
+							 total_networks);
+						acs_param->ch_stats[i].
+							cca_busy_duration =
+							wlan_le16_to_cpu
+							(ch_stats[i].
+							 cca_busy_duration);
+						acs_param->ch_stats_num++;
+					}
+				}
+				if (acs_param->ch_stats_num)
+					break;
+			}
+			left_len -= sizeof(*tlv_ie) + tlv_ie_len;
+			tlv_pos += sizeof(*tlv_ie) + tlv_ie_len;
+		}
+
+		/* Indicate ioctl complete */
+		pioctl_buf->data_read_written = sizeof(*acs_param);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN mlan_private *pmpriv, OUT 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(pmpriv->adapter, *pptlv_out,
+		       pmpriv->wps.wps_ie.vend_hdr.oui,
+		       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(IN mlan_private *pmpriv,
+		       IN t_void *pioctl_buf,
+		       IN t_u32 max_chan_per_scan,
+		       IN t_u8 filtered_scan,
+		       OUT wlan_scan_cmd_config *pscan_cfg_out,
+		       OUT MrvlIEtypes_ChanListParamSet_t *pchan_tlv_out,
+		       IN ChanScanParamSet_t *pscan_chan_list)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	ChanScanParamSet_t *ptmp_chan_list;
+	ChanScanParamSet_t *pstart_chan;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+	t_u8 *pchan_tlv_out_temp = MNULL;
+	t_u8 *ptlv_temp = MNULL;
+	t_bool foundJPch14 = MFALSE;
+	t_u16 tlv_buf_len = 0;
+	t_u32 tlv_idx;
+	t_u32 total_scan_time;
+	t_u32 done_early;
+	t_u32 cmd_no;
+	t_u32 first_chan = 1;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+
+	if (!pscan_cfg_out || !pchan_tlv_out || !pscan_chan_list) {
+		PRINTM(MINFO, "Scan: Null detect: %p, %p, %p\n",
+		       pscan_cfg_out, pchan_tlv_out, pscan_chan_list);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (!pscan_chan_list->chan_number) {
+		PRINTM(MERROR, "Scan: No channel configured\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* check expiry before preparing scan list - may affect blacklist */
+	wlan_11h_get_csa_closed_channel(pmpriv);
+
+	pchan_tlv_out->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+
+	/* Set the temp channel struct pointer to the start of the desired list */
+	ptmp_chan_list = pscan_chan_list;
+
+	/*
+	 * Loop through the desired channel list, sending a new firmware scan
+	 * commands for each max_chan_per_scan channels (or for 1,6,11
+	 * individually if configured accordingly)
+	 */
+	while (ptmp_chan_list->chan_number) {
+
+		tlv_idx = 0;
+		total_scan_time = 0;
+		pchan_tlv_out->header.len = 0;
+		pstart_chan = ptmp_chan_list;
+		done_early = MFALSE;
+
+		/*
+		 * Construct the Channel TLV for the scan command.  Continue to
+		 * insert channel TLVs until:
+		 *   - the tlv_idx hits the maximum configured per scan command
+		 *   - the next channel to insert is 0 (end of desired
+		 *     channel list)
+		 *   - done_early is set (controlling individual
+		 *     scanning of 1,6,11)
+		 */
+		while (tlv_idx < max_chan_per_scan &&
+		       ptmp_chan_list->chan_number && !done_early) {
+			if (wlan_is_chan_blacklisted
+			    (pmpriv,
+			     radio_type_to_band(ptmp_chan_list->bandcfg.
+						chanBand),
+			     ptmp_chan_list->chan_number) ||
+			    wlan_is_chan_disabled(pmpriv,
+						  radio_type_to_band
+						  (ptmp_chan_list->bandcfg.
+						   chanBand),
+						  ptmp_chan_list->
+						  chan_number)) {
+				ptmp_chan_list++;
+				continue;
+			}
+
+			if (first_chan) {
+				ptmp_chan_list->chan_scan_mode.first_chan =
+					MTRUE;
+				first_chan = 0;
+			}
+
+			PRINTM(MINFO,
+			       "Scan: Chan(%3d), bandcfg(%x), Mode(%d,%d), Dur(%d)\n",
+			       ptmp_chan_list->chan_number,
+			       ptmp_chan_list->bandcfg,
+			       ptmp_chan_list->chan_scan_mode.passive_scan,
+			       ptmp_chan_list->chan_scan_mode.disable_chan_filt,
+			       wlan_le16_to_cpu(ptmp_chan_list->max_scan_time));
+
+			if (foundJPch14 == MTRUE) {
+				foundJPch14 = MFALSE;
+				/* Restore the TLV buffer */
+				pchan_tlv_out =
+					(MrvlIEtypes_ChanListParamSet_t *)
+					pchan_tlv_out_temp;
+				pchan_tlv_out->header.type =
+					wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+				pchan_tlv_out->header.len = 0;
+				if (ptlv_temp) {
+					memcpy(pmadapter,
+					       pscan_cfg_out->tlv_buf,
+					       ptlv_temp, 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)
+				) {
+
+				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(pmadapter, ptlv_temp, ptlv_pos,
+				       tlv_buf_len);
+
+				/* 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(pmadapter,
+			       pchan_tlv_out->chan_scan_param + tlv_idx,
+			       ptmp_chan_list,
+			       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;
+			}
+		}
+
+		/* The total scan time should be less than scan command timeout value */
+		if (total_scan_time > MRVDRV_MAX_TOTAL_SCAN_TIME ||
+		    !total_scan_time || !pchan_tlv_out->header.len) {
+			PRINTM(MMSG,
+			       "Total scan time %d ms, limit (%d ms), chan tlv len=%d scan skipped\n",
+			       total_scan_time, MRVDRV_MAX_TOTAL_SCAN_TIME,
+			       pchan_tlv_out->header.len);
+
+			if (pioctl_req)
+				pioctl_req->status_code =
+					MLAN_ERROR_CMD_SCAN_FAIL;
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+
+		pchan_tlv_out->header.len =
+			wlan_cpu_to_le16(pchan_tlv_out->header.len);
+
+		pmadapter->pscan_channels = pstart_chan;
+
+		/* Send the scan command to the firmware with the specified cfg */
+		if (pmadapter->ext_scan)
+			cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
+		else
+			cmd_no = HostCmd_CMD_802_11_SCAN;
+		ret = wlan_prepare_cmd(pmpriv,
+				       cmd_no,
+				       HostCmd_ACT_GEN_SET,
+				       0, MNULL, pscan_cfg_out);
+		if (ret)
+			break;
+	}
+
+	LEAVE();
+
+	if (ptlv_temp)
+		pcb->moal_mfree(pmadapter->pmoal_handle, ptlv_temp);
+
+	if (ret)
+		return MLAN_STATUS_FAILURE;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Construct a wlan_scan_cmd_config structure to use in scan commands
+ *
+ *  Application layer or other functions can invoke wlan_scan_networks
+ *    with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
+ *    This structure is used as the basis of one or many wlan_scan_cmd_config
+ *    commands that are sent to the command processing module and sent to
+ *    firmware.
+ *
+ *  Create a wlan_scan_cmd_config based on the following user supplied
+ *    parameters (if present):
+ *             - SSID filter
+ *             - BSSID filter
+ *             - Number of Probes to be sent
+ *             - Channel list
+ *
+ *  If the SSID or BSSID filter is not present, disable/clear the filter.
+ *  If the number of probes is not set, use the adapter default setting
+ *  Qualify the channel
+ *
+ *  @param pmpriv              A pointer to mlan_private structure
+ *  @param puser_scan_in       MNULL or pointer to scan config parameters
+ *  @param pscan_cfg_out       Output parameter: Resulting scan configuration
+ *  @param ppchan_list_out     Output parameter: Pointer to the start of the
+ *                             channel TLV portion of the output scan config
+ *  @param pscan_chan_list     Output parameter: Pointer to the resulting
+ *                             channel list to scan
+ *  @param pmax_chan_per_scan  Output parameter: Number of channels to scan for
+ *                             each issuance of the firmware scan command
+ *  @param pfiltered_scan      Output parameter: Flag indicating whether or not
+ *                             a BSSID or SSID filter is being sent in the
+ *                             command to firmware. Used to increase the number
+ *                             of channels sent in a scan command and to
+ *                             disable the firmware channel scan filter.
+ *  @param pscan_current_only  Output parameter: Flag indicating whether or not
+ *                             we are only scanning our current active channel
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_scan_setup_scan_config(IN mlan_private *pmpriv,
+			    IN wlan_user_scan_cfg *puser_scan_in,
+			    OUT wlan_scan_cmd_config *pscan_cfg_out,
+			    OUT MrvlIEtypes_ChanListParamSet_t
+			    **ppchan_list_out,
+			    OUT ChanScanParamSet_t *pscan_chan_list,
+			    OUT t_u8 *pmax_chan_per_scan,
+			    OUT t_u8 *pfiltered_scan,
+			    OUT 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;
+	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(pmadapter, pscan_cfg_out->specific_bssid,
+		       puser_scan_in->specific_bssid,
+		       sizeof(pscan_cfg_out->specific_bssid));
+
+		if (pmadapter->ext_scan
+		    && 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 = MLAN_MAC_ADDR_LENGTH;
+			memcpy(pmadapter, pbssid_tlv->bssid,
+			       puser_scan_in->specific_bssid,
+			       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(pmadapter, pwildcard_ssid_tlv->ssid,
+			       puser_scan_in->ssid_list[ssid_idx].ssid,
+			       MIN(MLAN_MAX_SSID_LENGTH, ssid_len));
+
+			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 && puser_scan_in->scan_chan_gap) {
+		*pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+		PRINTM(MINFO, "Scan: channel gap = %d\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);
+	}
+	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 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(pmadapter, prates_tlv->rates, rates, 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);
+		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 (wlan_is_ext_capa_support(pmpriv))
+		wlan_add_ext_capa_info_ie(pmpriv, &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);
+	}
+
+	/*
+	 * 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;
+
+				}
+			}
+
+			/* Prevent active scanning on a radar controlled channel */
+			if (radio_type == BAND_5GHZ) {
+				if (wlan_11h_radar_detect_required
+				    (pmpriv, channel)) {
+					scan_type =
+						MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+				}
+			}
+			if (radio_type == BAND_2GHZ) {
+				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;
+			} else {
+				(pscan_chan_list +
+				 chan_list_idx)->chan_scan_mode.passive_scan =
+		      MFALSE;
+			}
+
+			if (puser_scan_in->chan_list[chan_idx].scan_time) {
+				scan_dur =
+					(t_u16)puser_scan_in->
+					chan_list[chan_idx].scan_time;
+			} else {
+				if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
+				    scan_type ==
+				    MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
+					scan_dur = pmadapter->passive_scan_time;
+				} else if (*pfiltered_scan) {
+					scan_dur =
+						pmadapter->specific_scan_time;
+				} else {
+					scan_dur = pmadapter->active_scan_time;
+				}
+			}
+
+			if (pmadapter->coex_scan &&
+			    pmadapter->coex_min_scan_time &&
+			    (pmadapter->coex_min_scan_time > scan_dur))
+				scan_dur = pmadapter->coex_min_scan_time;
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE &&
+			    pmadapter->passive_to_active_scan ==
+			    MLAN_PASS_TO_ACT_SCAN_EN) {
+				(pscan_chan_list +
+				 chan_list_idx)->chan_scan_mode.
+		      passive_to_active_scan = MTRUE;
+				scan_dur =
+					MAX(MIN_PASSIVE_TO_ACTIVE_SCAN_TIME,
+					    scan_dur);
+			}
+			PRINTM(MINFO,
+			       "chan=%d, mode=%d, passive_to_active=%d\n",
+			       (pscan_chan_list + chan_list_idx)->chan_number,
+			       (pscan_chan_list +
+				chan_list_idx)->chan_scan_mode.passive_scan,
+			       (pscan_chan_list +
+				chan_list_idx)->chan_scan_mode.
+			       passive_to_active_scan);
+
+			(pscan_chan_list + chan_list_idx)->min_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+			(pscan_chan_list + chan_list_idx)->max_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+			chan_list_idx++;
+		}
+
+		/* Check if we are only scanning the current channel */
+		if ((chan_idx == 1)
+		    && (puser_scan_in->chan_list[0].chan_number
+			== pmpriv->curr_bss_params.bss_descriptor.channel)) {
+			*pscan_current_only = MTRUE;
+			PRINTM(MINFO, "Scan: Scanning current channel only\n");
+		}
+
+	} else {
+		PRINTM(MINFO, "Scan: Creating full region channel list\n");
+		wlan_scan_create_channel_list(pmpriv, puser_scan_in,
+					      pscan_chan_list, *pfiltered_scan);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Inspect the scan response buffer for pointers to expected TLVs
+ *
+ *  TLVs can be included at the end of the scan response BSS information.
+ *    Parse the data in the buffer for pointers to TLVs that can potentially
+ *    be passed back in the response
+ *
+ *  @param pmadapter        Pointer to the mlan_adapter structure
+ *  @param ptlv             Pointer to the start of the TLV buffer to parse
+ *  @param tlv_buf_size     Size of the TLV buffer
+ *  @param req_tlv_type     Request TLV's type
+ *  @param pptlv            Output parameter: Pointer to the request TLV if found
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_ret_802_11_scan_get_tlv_ptrs(IN pmlan_adapter pmadapter,
+				  IN MrvlIEtypes_Data_t *ptlv,
+				  IN t_u32 tlv_buf_size,
+				  IN t_u32 req_tlv_type,
+				  OUT 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(IN pmlan_adapter pmadapter,
+				OUT BSSDescriptor_t *pbss_entry,
+				IN t_u8 **pbeacon_info,
+				IN t_u32 *bytes_left, IN 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;
+
+	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(pmadapter, &beacon_size, *pbeacon_info,
+		       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(pmadapter, pbss_entry->mac_address, pcurrent_ptr,
+	       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(pmadapter, fixed_ie.time_stamp, pcurrent_ptr, 8);
+	memcpy(pmadapter, pbss_entry->time_stamp, pcurrent_ptr, 8);
+	pcurrent_ptr += 8;
+	bytes_left_for_current_beacon -= 8;
+
+	/* Beacon interval is 2 bytes long */
+	memcpy(pmadapter, &fixed_ie.beacon_interval, pcurrent_ptr, 2);
+	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(pmadapter, &fixed_ie.capabilities, pcurrent_ptr, 2);
+	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(pmadapter, &pbss_entry->cap_info, pcap_info,
+	       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;
+			continue;
+		}
+
+		switch (element_id) {
+
+		case SSID:
+			if (element_len > MRVDRV_MAX_SSID_LENGTH) {
+				bytes_left_for_current_beacon = 0;
+				continue;
+			}
+			if (!pbss_entry->ssid.ssid_len) {
+				pbss_entry->ssid.ssid_len = element_len;
+				memcpy(pmadapter, pbss_entry->ssid.ssid,
+				       (pcurrent_ptr + 2), element_len);
+			}
+			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;
+				continue;
+			}
+			memcpy(pmadapter, pbss_entry->data_rates,
+			       pcurrent_ptr + 2, element_len);
+			memcpy(pmadapter, pbss_entry->supported_rates,
+			       pcurrent_ptr + 2, element_len);
+			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(pmadapter,
+			       &pbss_entry->phy_param_set.fh_param_set,
+			       pfh_param_set, MIN(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(pmadapter,
+			       &pbss_entry->phy_param_set.ds_param_set,
+			       pds_param_set, MIN(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(pmadapter,
+			       &pbss_entry->ss_param_set.cf_param_set,
+			       pcf_param_set, MIN(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(pmadapter,
+			       &pbss_entry->ss_param_set.ibss_param_set,
+			       pibss_param_set, MIN(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(pmadapter, &pbss_entry->country_info,
+			       pcountry_info, pcountry_info->len + 2);
+			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(pmadapter, prate, pcurrent_ptr + 2,
+				       bytes_to_copy);
+
+				prate = (t_u8 *)pbss_entry->supported_rates;
+				prate += rate_size;
+				memcpy(pmadapter, prate, pcurrent_ptr + 2,
+				       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(pmadapter,
+					       (t_u8 *)&pbss_entry->wmm_ie,
+					       pcurrent_ptr, total_ie_len);
+					HEXDUMP("InterpretIE: Resp WMM_IE",
+						(t_u8 *)&pbss_entry->wmm_ie,
+						total_ie_len);
+				}
+			} else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+					   osen_oui, sizeof(osen_oui))) {
+				pbss_entry->posen_ie =
+					(IEEEtypes_Generic_t *)pcurrent_ptr;
+				pbss_entry->osen_offset =
+					(t_u16)(pcurrent_ptr -
+						pbss_entry->pbeacon_buf);
+				HEXDUMP("InterpretIE: Resp OSEN_IE",
+					(t_u8 *)pbss_entry->posen_ie,
+					(*(pbss_entry->posen_ie)).ieee_hdr.len +
+					sizeof(IEEEtypes_Header_t));
+			}
+			break;
+		case RSN_IE:
+			pbss_entry->prsn_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pbss_entry->rsn_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp RSN_IE",
+				(t_u8 *)pbss_entry->prsn_ie,
+				(*(pbss_entry->prsn_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case WAPI_IE:
+			pbss_entry->pwapi_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pbss_entry->wapi_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp WAPI_IE",
+				(t_u8 *)pbss_entry->pwapi_ie,
+				(*(pbss_entry->pwapi_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case HT_CAPABILITY:
+			pbss_entry->pht_cap = (IEEEtypes_HTCap_t *)pcurrent_ptr;
+			pbss_entry->ht_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp HTCAP_IE",
+				(t_u8 *)pbss_entry->pht_cap,
+				(*(pbss_entry->pht_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case HT_OPERATION:
+			pbss_entry->pht_info =
+				(IEEEtypes_HTInfo_t *)pcurrent_ptr;
+			pbss_entry->ht_info_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp HTINFO_IE",
+				(t_u8 *)pbss_entry->pht_info,
+				(*(pbss_entry->pht_info)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case BSSCO_2040:
+			pbss_entry->pbss_co_2040 =
+				(IEEEtypes_2040BSSCo_t *)pcurrent_ptr;
+			pbss_entry->bss_co_2040_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp 2040BSSCOEXISTANCE_IE",
+				(t_u8 *)pbss_entry->pbss_co_2040,
+				(*(pbss_entry->pbss_co_2040)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_CAPABILITY:
+			pbss_entry->pext_cap =
+				(IEEEtypes_ExtCap_t *)pcurrent_ptr;
+			pbss_entry->ext_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTCAP_IE",
+				(t_u8 *)pbss_entry->pext_cap,
+				(*(pbss_entry->pext_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case OVERLAPBSSSCANPARAM:
+			pbss_entry->poverlap_bss_scan_param =
+				(IEEEtypes_OverlapBSSScanParam_t *)pcurrent_ptr;
+			pbss_entry->overlap_bss_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp OBSS_IE",
+				(t_u8 *)pbss_entry->poverlap_bss_scan_param,
+				(*(pbss_entry->poverlap_bss_scan_param)).
+				ieee_hdr.len + sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_CAPABILITY:
+			pbss_entry->pvht_cap =
+				(IEEEtypes_VHTCap_t *)pcurrent_ptr;
+			pbss_entry->vht_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp VHTCAP_IE",
+				(t_u8 *)pbss_entry->pvht_cap,
+				(*(pbss_entry->pvht_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_OPERATION:
+			pbss_entry->pvht_oprat =
+				(IEEEtypes_VHTOprat_t *)pcurrent_ptr;
+			pbss_entry->vht_oprat_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp VHTOPER_IE",
+				(t_u8 *)pbss_entry->pvht_oprat,
+				(*(pbss_entry->pvht_oprat)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_BSS_LOAD:
+			pbss_entry->pext_bssload =
+				(IEEEtypes_ExtBSSload_t *)pcurrent_ptr;
+			pbss_entry->ext_bssload_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTBSSLOAD_IE",
+				(t_u8 *)pbss_entry->pext_bssload,
+				(*(pbss_entry->pext_bssload)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_TX_POWER_ENV:
+			pbss_entry->pvht_txpower =
+				(IEEEtypes_VHTtxpower_t *)pcurrent_ptr;
+			pbss_entry->vht_txpower_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp TXPOW_IE",
+				(t_u8 *)pbss_entry->pvht_txpower,
+				(*(pbss_entry->pvht_txpower)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_POWER_CONSTR:
+			pbss_entry->pext_pwer =
+				(IEEEtypes_ExtPwerCons_t *)pcurrent_ptr;
+			pbss_entry->ext_pwer_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTPOW_IE",
+				(t_u8 *)pbss_entry->pext_pwer,
+				(*(pbss_entry->pext_pwer)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case QUIET_CHAN:
+			pbss_entry->pquiet_chan =
+				(IEEEtypes_QuietChan_t *)pcurrent_ptr;
+			pbss_entry->quiet_chan_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp QUIETCHAN_IE",
+				(t_u8 *)pbss_entry->pquiet_chan,
+				(*(pbss_entry->pquiet_chan)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case BW_CHANNEL_SWITCH:
+			/* RANDYTODO */
+			break;
+		case AID_INFO:
+			break;
+		case OPER_MODE_NTF:
+			pbss_entry->poper_mode =
+				(IEEEtypes_OperModeNtf_t *)pcurrent_ptr;
+			pbss_entry->oper_mode_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp OPERMODENTF_IE",
+				(t_u8 *)pbss_entry->poper_mode,
+				(*(pbss_entry->poper_mode)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case 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(IN mlan_private *pmpriv,
+			    IN 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);
+		}
+	} 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(IN mlan_private *pmpriv,
+				  IN t_u32 beacon_idx,
+				  IN t_u32 num_of_ent,
+				  IN BSSDescriptor_t *pnew_beacon)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 *pbcn_store;
+	t_u32 new_bcn_size;
+	t_u32 old_bcn_size;
+	t_u32 bcn_space;
+	t_u32 adj_idx;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *tmp_buf;
+	t_u16 bcn_size = 0;
+	t_u32 bcn_offset = 0;
+
+	ENTER();
+
+	if (pmadapter->pscan_table[beacon_idx].pbeacon_buf) {
+
+		new_bcn_size = pnew_beacon->beacon_buf_size;
+		old_bcn_size =
+			pmadapter->pscan_table[beacon_idx].beacon_buf_size;
+		bcn_space =
+			pmadapter->pscan_table[beacon_idx].beacon_buf_size_max;
+		pbcn_store = pmadapter->pscan_table[beacon_idx].pbeacon_buf;
+
+		/* Set the max to be the same as current entry unless changed below */
+		pnew_beacon->beacon_buf_size_max = bcn_space;
+
+		if (new_bcn_size == old_bcn_size) {
+			/*
+			 * Beacon is the same size as the previous entry.
+			 *   Replace the previous contents with the scan result
+			 */
+			memcpy(pmadapter, pbcn_store,
+			       pnew_beacon->pbeacon_buf,
+			       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(pmadapter, pbcn_store, pnew_beacon->pbeacon_buf,
+			       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(pmadapter, pbcn_store, pnew_beacon->pbeacon_buf,
+			       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;
+		}
+		/* Point the new entry to its permanent storage space */
+		pnew_beacon->pbeacon_buf = pbcn_store;
+		wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
+	} else {
+		if ((pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+		     SCAN_BEACON_ENTRY_PAD > (pmadapter->bcn_buf +
+					      pmadapter->bcn_buf_size)) &&
+		    (pmadapter->bcn_buf_size < MAX_SCAN_BEACON_BUFFER)) {
+			/* no space for this entry, realloc bcn buffer */
+			ret = pmadapter->callbacks.moal_malloc(pmadapter->
+							       pmoal_handle,
+							       pmadapter->
+							       bcn_buf_size +
+							       DEFAULT_SCAN_BEACON_BUFFER,
+							       MLAN_MEM_DEF,
+							       (t_u8 **)
+							       &tmp_buf);
+
+			if ((ret == MLAN_STATUS_SUCCESS) && (tmp_buf)) {
+				PRINTM(MCMND,
+				       "Realloc Beacon buffer, old size=%d, new_size=%d\n",
+				       pmadapter->bcn_buf_size,
+				       pmadapter->bcn_buf_size +
+				       DEFAULT_SCAN_BEACON_BUFFER);
+				bcn_size =
+					pmadapter->pbcn_buf_end -
+					pmadapter->bcn_buf;
+				memcpy(pmadapter, tmp_buf, pmadapter->bcn_buf,
+				       bcn_size);
+				/* Adjust beacon buffer pointers that are past the current */
+				for (adj_idx = 0; adj_idx < num_of_ent;
+				     adj_idx++) {
+					bcn_offset =
+						pmadapter->pscan_table[adj_idx].
+						pbeacon_buf -
+						pmadapter->bcn_buf;
+					pmadapter->pscan_table[adj_idx].
+						pbeacon_buf =
+						tmp_buf + bcn_offset;
+					wlan_adjust_ie_in_bss_entry(pmpriv,
+								    &pmadapter->
+								    pscan_table
+								    [adj_idx]);
+				}
+				pmadapter->pbcn_buf_end = tmp_buf + bcn_size;
+				pmadapter->callbacks.moal_mfree(pmadapter->
+								pmoal_handle,
+								(t_u8 *)
+								pmadapter->
+								bcn_buf);
+				pmadapter->bcn_buf = tmp_buf;
+				pmadapter->bcn_buf_size +=
+					DEFAULT_SCAN_BEACON_BUFFER;
+			}
+		}
+		/*
+		 * No existing beacon data exists for this entry, check to see
+		 *   if we can fit it in the remaining space
+		 */
+		if (pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+		    SCAN_BEACON_ENTRY_PAD < (pmadapter->bcn_buf +
+					     pmadapter->bcn_buf_size)) {
+
+			/*
+			 * Copy the beacon buffer data from the local entry
+			 * to the adapter dev struct buffer space used to
+			 * store the raw beacon data for each entry in the
+			 * scan table
+			 */
+			memcpy(pmadapter, pmadapter->pbcn_buf_end,
+			       pnew_beacon->pbeacon_buf,
+			       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(IN 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);
+		}
+
+		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 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(IN 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(pmadapter, &pmadapter->pscan_table[j].ssid,
+			       &pmpriv->curr_bss_params.bss_descriptor.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.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(pmadapter,
+			       &pmpriv->curr_bss_params.bss_descriptor,
+			       &pmadapter->pscan_table[j],
+			       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(pmadapter, bss_new_entry,
+					       &pmpriv->curr_bss_params.
+					       bss_descriptor,
+					       sizeof(pmpriv->curr_bss_params.
+						      bss_descriptor));
+					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(pmadapter,
+						       &pmadapter->
+						       pscan_table[pmadapter->
+								   num_in_scan_table
+								   - 1],
+						       bss_new_entry,
+						       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);
+
+	/*
+	 * 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(IN mlan_private *pmpriv, IN 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(pmadapter, pmadapter->pscan_table + del_idx,
+		       pmadapter->pscan_table + del_idx + 1,
+		       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);
+			}
+		}
+	}
+
+	/* The last entry is invalid now that it has been deleted or moved back */
+	memset(pmadapter,
+	       pmadapter->pscan_table + pmadapter->num_in_scan_table - 1, 0x00,
+	       sizeof(BSSDescriptor_t));
+
+	pmadapter->num_in_scan_table--;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Delete all occurrences of a given SSID from the scan table
+ *
+ *  Iterate through the scan table and delete all entries that match a given
+ *    SSID.  Compact the remaining scan table entries.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pdel_ssid    Pointer to an SSID to be used in deleting all
+ *                        matching SSIDs from the scan table
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_scan_delete_ssid_table_entry(IN mlan_private *pmpriv,
+				  IN 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(IN mlan_private *pmpriv,
+			   IN t_u32 index, IN 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 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)) {
+		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
+			    */
+			) {
+			/* WPA enabled */
+			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 {
+					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(IN 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(IN mlan_private *pmpriv,
+		   IN t_void *pioctl_buf, IN wlan_user_scan_cfg *puser_scan_in)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	wlan_scan_cmd_config_tlv *pscan_cfg_out = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchan_list_out;
+	t_u32 buf_size;
+	ChanScanParamSet_t *pscan_chan_list;
+
+	t_u8 keep_previous_scan;
+	t_u8 filtered_scan;
+	t_u8 scan_current_chan_only;
+	t_u8 max_chan_per_scan;
+	t_u8 i;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(wlan_scan_cmd_config_tlv), MLAN_MEM_DEF,
+			       (t_u8 **)&pscan_cfg_out);
+	if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg_out) {
+		PRINTM(MERROR, "Memory allocation for pscan_cfg_out failed!\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF,
+			       (t_u8 **)&pscan_chan_list);
+	if (ret != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
+		PRINTM(MERROR, "Failed to allocate scan_chan_list\n");
+		if (pscan_cfg_out)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_cfg_out);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(pmadapter, pscan_chan_list, 0x00, buf_size);
+	memset(pmadapter, pscan_cfg_out, 0x00,
+	       sizeof(wlan_scan_cmd_config_tlv));
+
+	keep_previous_scan = MFALSE;
+
+	ret = wlan_scan_setup_scan_config(pmpriv,
+					  puser_scan_in,
+					  &pscan_cfg_out->config,
+					  &pchan_list_out,
+					  pscan_chan_list,
+					  &max_chan_per_scan,
+					  &filtered_scan,
+					  &scan_current_chan_only);
+	if (ret != MLAN_STATUS_SUCCESS) {
+
+		PRINTM(MERROR, "Failed to setup scan config\n");
+		if (pscan_cfg_out)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_cfg_out);
+		if (pscan_chan_list)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_chan_list);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (puser_scan_in)
+		keep_previous_scan = puser_scan_in->keep_previous_scan;
+
+	if (keep_previous_scan == MFALSE) {
+		memset(pmadapter, pmadapter->pscan_table, 0x00,
+		       sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
+		pmadapter->num_in_scan_table = 0;
+		pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+
+	}
+	for (i = 0; i < pmadapter->num_in_chan_stats; i++)
+		pmadapter->pchan_stats[i].cca_scan_duration = 0;
+	pmadapter->idx_chan_stats = 0;
+
+	ret = wlan_scan_channel_list(pmpriv,
+				     pioctl_buf,
+				     max_chan_per_scan,
+				     filtered_scan,
+				     &pscan_cfg_out->config,
+				     pchan_list_out, pscan_chan_list);
+
+	/* Get scan command from scan_pending_q and put to cmd_pending_q */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		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(IN mlan_private *pmpriv,
+		     IN HostCmd_DS_COMMAND *pcmd, IN 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(pmpriv->adapter, pscan_cmd->bssid, pscan_cfg->specific_bssid,
+	       sizeof(pscan_cmd->bssid));
+	memcpy(pmpriv->adapter, pscan_cmd->tlv_buffer, pscan_cfg->tlv_buf,
+	       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 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(IN mlan_private *pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = MNULL;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	HostCmd_DS_802_11_SCAN_RSP *pscan_rsp = MNULL;
+	BSSDescriptor_t *bss_new_entry = MNULL;
+	MrvlIEtypes_Data_t *ptlv;
+	MrvlIEtypes_TsfTimestamp_t *ptsf_tlv = MNULL;
+	MrvlIEtypes_ChannelStats_t *pchanstats_tlv = MNULL;
+	t_u8 *pbss_info;
+	t_u32 scan_resp_size;
+	t_u32 bytes_left;
+	t_u32 num_in_table;
+	t_u32 bss_idx;
+	t_u32 idx;
+	t_u32 tlv_buf_size;
+	t_u64 tsf_val;
+	chan_freq_power_t *cfp;
+	MrvlIEtypes_ChanBandListParamSet_t *pchan_band_tlv = MNULL;
+	ChanBandParamSet_t *pchan_band;
+	t_u8 band;
+	t_u8 is_bgscan_resp;
+	t_u32 age_ts_usec;
+	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = { 0 };
+	t_u32 status_code = 0;
+	pmlan_ioctl_req pscan_ioctl_req = MNULL;
+
+	ENTER();
+	pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+	is_bgscan_resp = (resp->command == HostCmd_CMD_802_11_BG_SCAN_QUERY);
+	if (is_bgscan_resp)
+		pscan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
+	else
+		pscan_rsp = &resp->params.scan_resp;
+
+	if (pscan_rsp->number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+		PRINTM(MERROR,
+		       "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
+		       pscan_rsp->number_of_sets);
+		status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bytes_left = wlan_le16_to_cpu(pscan_rsp->bss_descript_size);
+	PRINTM(MINFO, "SCAN_RESP: bss_descript_size %d\n", bytes_left);
+
+	scan_resp_size = resp->size;
+
+	PRINTM(MINFO, "SCAN_RESP: returned %d APs before parsing\n",
+	       pscan_rsp->number_of_sets);
+
+	num_in_table = pmadapter->num_in_scan_table;
+	pbss_info = pscan_rsp->bss_desc_and_tlv_buffer;
+
+	/*
+	 * The size of the TLV buffer is equal to the entire command response
+	 *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
+	 *   BSS Descriptions (bss_descript_size as bytesLef) and the command
+	 *   response header (S_DS_GEN)
+	 */
+	tlv_buf_size = scan_resp_size - (bytes_left
+					 + sizeof(pscan_rsp->bss_descript_size)
+					 + sizeof(pscan_rsp->number_of_sets)
+					 + S_DS_GEN);
+	if (is_bgscan_resp)
+		tlv_buf_size -=
+			sizeof(resp->params.bg_scan_query_resp.
+			       report_condition);
+
+	ptlv = (MrvlIEtypes_Data_t *)(pscan_rsp->bss_desc_and_tlv_buffer +
+				      bytes_left);
+
+	/*
+	 * Search the TLV buffer space in the scan response
+	 * for any valid TLVs
+	 */
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter,
+					  ptlv,
+					  tlv_buf_size,
+					  TLV_TYPE_TSFTIMESTAMP,
+					  (MrvlIEtypes_Data_t **)&ptsf_tlv);
+
+	/*
+	 * Search the TLV buffer space in the scan response
+	 * for any valid TLVs
+	 */
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter,
+					  ptlv,
+					  tlv_buf_size,
+					  TLV_TYPE_CHANNELBANDLIST,
+					  (MrvlIEtypes_Data_t **)
+					  &pchan_band_tlv);
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter, ptlv, tlv_buf_size,
+					  TLV_TYPE_CHANNEL_STATS,
+					  (MrvlIEtypes_Data_t **)
+					  &pchanstats_tlv);
+
+	if (pchanstats_tlv)
+		wlan_update_chan_statistics(pmpriv, pchanstats_tlv);
+
+	/*
+	 * Process each scan response returned (pscan_rsp->number_of_sets).
+	 * Save the information in the bss_new_entry and then insert into
+	 * the driver scan table either as an update to an existing entry
+	 * or as an addition at the end of the table
+	 */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+		status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	for (idx = 0; idx < pscan_rsp->number_of_sets && bytes_left; idx++) {
+		/* Zero out the bss_new_entry we are about to store info in */
+		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+		/* Process the data fields and IEs returned for this BSS */
+		if (wlan_interpret_bss_desc_with_ie(pmadapter,
+						    bss_new_entry,
+						    &pbss_info,
+						    &bytes_left,
+						    MFALSE) ==
+		    MLAN_STATUS_SUCCESS) {
+			PRINTM(MINFO, "SCAN_RESP: BSSID = " MACSTR "\n",
+			       MAC2STR(bss_new_entry->mac_address));
+
+			band = BAND_G;
+			if (pchan_band_tlv) {
+				pchan_band =
+					&pchan_band_tlv->chan_band_param[idx];
+				band = radio_type_to_band(pchan_band->bandcfg.
+							  chanBand);
+				if (!bss_new_entry->channel)
+					bss_new_entry->channel =
+						pchan_band->chan_number;
+			}
+			/*
+			 * Save the band designation for this entry
+			 * for use in join
+			 */
+			bss_new_entry->bss_band = band;
+
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								(t_u8)
+								bss_new_entry->
+								bss_band,
+								(t_u16)
+								bss_new_entry->
+								channel);
+			if (cfp)
+				bss_new_entry->freq = cfp->freq;
+			else
+				bss_new_entry->freq = 0;
+
+			/* Skip entry if on blacklisted channel */
+			if (cfp && cfp->dynamic.blacklist) {
+				PRINTM(MINFO,
+				       "SCAN_RESP: dropping entry on blacklist channel.\n");
+				continue;
+			}
+
+			/*
+			 * Search the scan table for the same bssid
+			 */
+			for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
+				if (!memcmp
+				    (pmadapter, bss_new_entry->mac_address,
+				     pmadapter->pscan_table[bss_idx].
+				     mac_address,
+				     sizeof(bss_new_entry->mac_address))) {
+					/*
+					 * If the SSID matches as well, it is a
+					 * duplicate of this entry.  Keep the
+					 * bss_idx set to this entry so we
+					 * replace the old contents in the table
+					 */
+					if ((bss_new_entry->ssid.ssid_len ==
+					     pmadapter->pscan_table[bss_idx].
+					     ssid.ssid_len)
+					    &&
+					    (!memcmp
+					     (pmadapter,
+					      bss_new_entry->ssid.ssid,
+					      pmadapter->pscan_table[bss_idx].
+					      ssid.ssid,
+					      bss_new_entry->ssid.ssid_len))) {
+						PRINTM(MINFO,
+						       "SCAN_RESP: Duplicate of index: %d\n",
+						       bss_idx);
+
+						break;
+					}
+					/*
+					 * If the SSID is NULL for same BSSID
+					 * keep the bss_idx set to this entry
+					 * so we replace the old contents in
+					 * the table
+					 */
+					if (!memcmp
+					    (pmadapter,
+					     pmadapter->pscan_table[bss_idx].
+					     ssid.ssid, null_ssid,
+					     pmadapter->pscan_table[bss_idx].
+					     ssid.ssid_len)) {
+						PRINTM(MINFO,
+						       "SCAN_RESP: Duplicate of index: %d\n",
+						       bss_idx);
+						break;
+					}
+				}
+			}
+			/*
+			 * If the bss_idx is equal to the number of entries
+			 * in the table, the new entry was not a duplicate;
+			 * append it to the scan table
+			 */
+			if (bss_idx == num_in_table) {
+				/*
+				 * Range check the bss_idx, keep it limited
+				 * to the last entry
+				 */
+				if (bss_idx == MRVDRV_MAX_BSSID_LIST)
+					bss_idx--;
+				else
+					num_in_table++;
+			}
+
+			/*
+			 * 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(pmpriv->adapter, &tsf_val,
+				       &ptsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
+				       sizeof(tsf_val));
+				tsf_val = wlan_le64_to_cpu(tsf_val);
+				memcpy(pmpriv->adapter,
+				       &bss_new_entry->network_tsf, &tsf_val,
+				       sizeof(bss_new_entry->network_tsf));
+			}
+
+			/* Copy the locally created bss_new_entry to the scan table */
+			memcpy(pmadapter, &pmadapter->pscan_table[bss_idx],
+			       bss_new_entry,
+			       sizeof(pmadapter->pscan_table[bss_idx]));
+
+		} else {
+			/* Error parsing/interpreting the scan response, skipped */
+			PRINTM(MERROR,
+			       "SCAN_RESP: wlan_interpret_bss_desc_with_ie returned error\n");
+		}
+	}
+
+	PRINTM(MINFO, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
+	       pscan_rsp->number_of_sets,
+	       num_in_table - pmadapter->num_in_scan_table, num_in_table);
+
+	/* Update the total number of BSSIDs in the scan table */
+	pmadapter->num_in_scan_table = num_in_table;
+	/* Update the age_in_second */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->age_in_secs,
+						  &age_ts_usec);
+	if (is_bgscan_resp)
+		goto done;
+	wlan_request_cmd_lock(pmadapter);
+	if (!util_peek_list
+	    (pmadapter->pmoal_handle, &pmadapter->scan_pending_q, MNULL,
+	     MNULL)) {
+		wlan_release_cmd_lock(pmadapter);
+		/*
+		 * 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(IN mlan_private *pmpriv,
+			 IN HostCmd_DS_COMMAND *pcmd, IN 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);
+
+	pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
+
+	memcpy(pmpriv->adapter, pext_scan_cmd->tlv_buffer,
+	       pscan_cfg->tlv_buf, 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(IN mlan_private *pmpriv,
+			 IN HostCmd_DS_COMMAND *resp, IN 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;
+	ENTER();
+
+	PRINTM(MINFO, "EXT scan returns successfully\n");
+	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 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(IN mlan_private *pmpriv,
+			   IN t_u8 number_of_sets,
+			   IN t_u8 *pscan_resp, IN 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 bss_idx;
+	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;
+	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = { 0 };
+
+	ENTER();
+	pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+	if (number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+		PRINTM(MERROR,
+		       "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
+		       number_of_sets);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bytes_left = scan_resp_size;
+	PRINTM(MINFO, "EXT_SCAN: bss_descript_size %d\n", scan_resp_size);
+	PRINTM(MINFO, "EXT_SCAN: returned %d APs before parsing\n",
+	       number_of_sets);
+
+	num_in_table = pmadapter->num_in_scan_table;
+	ptlv = (MrvlIEtypes_Data_t *)pscan_resp;
+
+	/*
+	 *  Process each scan response returned number_of_sets. Save
+	 *    the information in the bss_new_entry and then insert into the
+	 *    driver scan table either as an update to an existing entry
+	 *    or as an addition at the end of the table
+	 */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	for (idx = 0; idx < number_of_sets && bytes_left >
+	     sizeof(MrvlIEtypesHeader_t); idx++) {
+		tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+		tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+		if (bytes_left < sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+			PRINTM(MERROR,
+			       "EXT_SCAN: Error bytes left < TLV length\n");
+			break;
+		}
+		pscan_rsp_tlv = MNULL;
+		pscan_info_tlv = MNULL;
+		bytes_left_for_tlv = bytes_left;
+		/*
+		 * BSS response TLV with beacon or probe response buffer
+		 * at the initial position of each descriptor
+		 */
+		if (tlv_type == TLV_TYPE_BSS_SCAN_RSP) {
+			pbss_info = (t_u8 *)ptlv;
+			pscan_rsp_tlv = (MrvlIEtypes_Bss_Scan_Rsp_t *)ptlv;
+			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+			bytes_left_for_tlv -=
+				(tlv_len + sizeof(MrvlIEtypesHeader_t));
+		} else
+			break;
+
+		/* Process variable TLV */
+		while (bytes_left_for_tlv >= sizeof(MrvlIEtypesHeader_t) &&
+		       wlan_le16_to_cpu(ptlv->header.type) !=
+		       TLV_TYPE_BSS_SCAN_RSP) {
+			tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+			if (bytes_left_for_tlv <
+			    sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+				PRINTM(MERROR,
+				       "EXT_SCAN: Error in processing TLV, "
+				       "bytes left < TLV length\n");
+				pscan_rsp_tlv = MNULL;
+				bytes_left_for_tlv = 0;
+				continue;
+			}
+			switch (tlv_type) {
+			case TLV_TYPE_BSS_SCAN_INFO:
+				pscan_info_tlv =
+					(MrvlIEtypes_Bss_Scan_Info_t *)ptlv;
+				if (tlv_len !=
+				    sizeof(MrvlIEtypes_Bss_Scan_Info_t) -
+				    sizeof(MrvlIEtypesHeader_t)) {
+					bytes_left_for_tlv = 0;
+					continue;
+				}
+				break;
+			default:
+				break;
+			}
+			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+			bytes_left -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
+			bytes_left_for_tlv -=
+				(tlv_len + sizeof(MrvlIEtypesHeader_t));
+		}
+		/* No BSS response TLV */
+		if (pscan_rsp_tlv == MNULL)
+			break;
+
+		/*
+		 * Advance pointer to the beacon buffer length and
+		 * update the bytes count so that the function
+		 * wlan_interpret_bss_desc_with_ie() can handle the
+		 * scan buffer withut any change
+		 */
+		pbss_info += sizeof(t_u16);
+		bytes_left -= sizeof(t_u16);
+
+		/* Zero out the bss_new_entry we are about to store info in */
+		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+		/* Process the data fields and IEs returned for this BSS */
+		if (wlan_interpret_bss_desc_with_ie(pmadapter,
+						    bss_new_entry,
+						    &pbss_info,
+						    &bytes_left,
+						    MTRUE) ==
+		    MLAN_STATUS_SUCCESS) {
+			PRINTM(MINFO, "EXT_SCAN: BSSID = " MACSTR "\n",
+			       MAC2STR(bss_new_entry->mac_address));
+
+			band = BAND_G;
+			/*
+			 * If the BSS info TLV was appended to the scan results,
+			 * save this entry's TSF value in the networkTSF field.
+			 * The networkTSF is the firmware's TSF value at the
+			 * time the beacon or probe response was received.
+			 */
+			if (pscan_info_tlv) {
+				/* RSSI is 2 byte long */
+				bss_new_entry->rssi =
+					-(t_s32)(wlan_le16_to_cpu
+						 (pscan_info_tlv->rssi));
+				PRINTM(MINFO, "EXT_SCAN: RSSI=%d\n",
+				       bss_new_entry->rssi);
+				memcpy(pmpriv->adapter, &tsf_val,
+				       &pscan_info_tlv->tsf, sizeof(tsf_val));
+				tsf_val = wlan_le64_to_cpu(tsf_val);
+				memcpy(pmpriv->adapter,
+				       &bss_new_entry->network_tsf, &tsf_val,
+				       sizeof(bss_new_entry->network_tsf));
+				band = radio_type_to_band(pscan_info_tlv->
+							  bandcfg.chanBand);
+				if (!bss_new_entry->channel)
+					bss_new_entry->channel =
+						pscan_info_tlv->channel;
+			}
+			/* Save the band designation for this entry for use in join */
+			bss_new_entry->bss_band = band;
+
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								(t_u8)
+								bss_new_entry->
+								bss_band,
+								(t_u16)
+								bss_new_entry->
+								channel);
+			if (cfp)
+				bss_new_entry->freq = cfp->freq;
+			else
+				bss_new_entry->freq = 0;
+
+			/* Skip entry if on blacklisted channel */
+			if (cfp && cfp->dynamic.blacklist) {
+				PRINTM(MINFO,
+				       "EXT_SCAN: dropping entry on blacklist channel.\n");
+				continue;
+			}
+
+			/*
+			 * 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++;
+			}
+
+			/*
+			 * 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;
+			}
+
+			/* Copy the locally created bss_new_entry to the scan table */
+			memcpy(pmadapter, &pmadapter->pscan_table[bss_idx],
+			       bss_new_entry,
+			       sizeof(pmadapter->pscan_table[bss_idx]));
+		} else {
+			/* Error parsing/interpreting the scan response, skipped */
+			PRINTM(MERROR,
+			       "EXT_SCAN: wlan_interpret_bss_desc_with_ie returned error\n");
+		}
+	}
+
+	PRINTM(MINFO, "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(IN mlan_private *pmpriv,
+				  IN 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) {
+		wlan_request_cmd_lock(pmadapter);
+		if (!util_peek_list(pmadapter->pmoal_handle,
+				    &pmadapter->scan_pending_q, MNULL, MNULL)) {
+			wlan_release_cmd_lock(pmadapter);
+			/*
+			 * 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 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(IN mlan_private *pmpriv,
+			      IN HostCmd_DS_COMMAND *pcmd, IN 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(IN mlan_private *pmpriv,
+				IN 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(IN mlan_private *pmpriv,
+		       IN HostCmd_DS_COMMAND *pcmd, IN 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;
+	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;
+
+	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(pmadapter, pwildcard_ssid_tlv->ssid,
+		       bg_scan_in->ssid_list[ssid_idx].ssid,
+		       MIN(MLAN_MAX_SSID_LENGTH, ssid_len));
+		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;
+	}
+
+	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(pmadapter, tlv_ssid->ssid,
+					       bg_scan_in->ees_ssid_cfg[index].
+					       ssid, MIN(MLAN_MAX_SSID_LENGTH,
+							 bg_scan_in->
+							 ees_ssid_cfg[index].
+							 max_len));
+					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);
+			}
+		}
+	}
+
+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(IN mlan_private *pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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(IN mlan_private *pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_scan *pscan = MNULL;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	ENTER();
+	wlan_ret_802_11_scan(pmpriv, resp, MNULL);
+	if (pioctl_buf) {
+		pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
+		pscan->param.scan_resp.pscan_table =
+			(t_u8 *)pmadapter->pscan_table;
+		pscan->param.scan_resp.num_in_scan_table =
+			pmadapter->num_in_scan_table;
+		pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs;
+		pscan->param.scan_resp.pchan_stats =
+			(t_u8 *)pmadapter->pchan_stats;
+		pscan->param.scan_resp.num_in_chan_stats =
+			pmadapter->num_in_chan_stats;
+
+		pioctl_buf->data_read_written = sizeof(mlan_scan_resp) +
+			MLAN_SUB_COMMAND_SIZE;
+
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function finds ssid in ssid list.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param ssid         SSID to find in the list
+ *  @param bssid        BSSID to qualify the SSID selection (if provided)
+ *  @param mode         Network mode: Infrastructure or IBSS
+ *
+ *  @return             index in BSSID list or < 0 if error
+ */
+t_s32
+wlan_find_ssid_in_list(IN mlan_private *pmpriv,
+		       IN mlan_802_11_ssid *ssid, IN t_u8 *bssid, IN 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(IN mlan_private *pmpriv, IN t_u8 *bssid, IN 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(IN pmlan_adapter pmadapter,
+	      IN mlan_802_11_ssid *ssid1, IN 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(IN mlan_private *pmpriv,
+		       OUT 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(pmadapter, &preq_ssid_bssid->ssid, &preq_bss->ssid,
+		       sizeof(mlan_802_11_ssid));
+		memcpy(pmadapter, (t_u8 *)&preq_ssid_bssid->bssid,
+		       (t_u8 *)&preq_bss->mac_address, 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(IN mlan_private *pmpriv,
+			IN t_void *pioctl_buf, IN 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(pmpriv->adapter, pscan_cfg->ssid_list[0].ssid,
+	       preq_ssid->ssid, preq_ssid->ssid_len);
+	pscan_cfg->keep_previous_scan = MTRUE;
+
+	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(IN 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(pmpriv->adapter, pmpriv->pcurr_bcn_buf,
+				       pcurr_bss->pbeacon_buf,
+				       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(IN 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 100644
index 0000000..277c92f
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sdio.c
@@ -0,0 +1,2797 @@
+/** @file mlan_sdio.c
+ *
+ *  @brief This file contains SDIO specific code
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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
+********************************************************/
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB2   28
+/** FW header for CRC check disable */
+static t_u8 fw_crc_header_rb2[FW_CRC_HEADER_RB2] = {
+	0x05, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x0c, 0x00, 0x00, 0x00,
+	0x9d, 0x32, 0xbb, 0x11,
+	0x01, 0x00, 0x00, 0x7f,
+	0x00, 0x00, 0x00, 0x00,
+	0x67, 0xd6, 0xfc, 0x25
+};
+
+/** FW header length for CRC check disable */
+#define FW_CRC_HEADER_RB   24
+/** FW header for CRC check disable */
+static t_u8 fw_crc_header_rb[FW_CRC_HEADER_RB] = {
+	0x01, 0x00, 0x00, 0x00, 0x04, 0xfd, 0x00, 0x04,
+	0x08, 0x00, 0x00, 0x00, 0x26, 0x52, 0x2a, 0x7b,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/********************************************************
+		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;
+
+	const mlan_sdio_device *psdio_device = pmadapter->psdio_device;
+	t_u8 host_int_rsr_reg = psdio_device->host_int_rsr_reg;
+	t_u8 host_int_rsr_mask = psdio_device->reg->sdio_int_mask;
+	t_u8 card_misc_cfg_reg = psdio_device->reg->card_misc_cfg_reg;
+	t_u8 card_config_2_1_reg = psdio_device->card_config_2_1_reg;
+	t_u8 cmd_config_0 = psdio_device->cmd_config_0;
+	t_u8 cmd_config_1 = psdio_device->cmd_config_1;
+
+	ENTER();
+	pmadapter->ioport = 0;
+
+	if (psdio_device->supports_sdio_new_mode) {
+		pmadapter->ioport = MEM_PORT;
+	} else {
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       psdio_device->io_port_0_reg, &reg))
+			pmadapter->ioport |= (reg & 0xff);
+		else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       psdio_device->io_port_1_reg, &reg))
+			pmadapter->ioport |= ((reg & 0xff) << 8);
+		else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       psdio_device->io_port_2_reg, &reg))
+			pmadapter->ioport |= ((reg & 0xff) << 16);
+		else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	PRINTM(MINFO, "SDIO FUNC1 IO port: 0x%x\n", pmadapter->ioport);
+
+	if (psdio_device->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 (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);
+		}
+	}
+	/* 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->mp_rd_bitmap;
+	const mlan_sdio_device *psdio_device = pmadapter->psdio_device;
+	const mlan_sdio_card_reg *reg = psdio_device->reg;
+	t_bool new_mode = psdio_device->supports_sdio_new_mode;
+	t_u8 max_ports = psdio_device->max_ports;
+
+	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->mp_rd_bitmap & CTRL_PORT_MASK)) {
+		pmadapter->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->mp_rd_bitmap);
+	} else {
+		if (pmadapter->mp_rd_bitmap & (1 << pmadapter->curr_rd_port)) {
+			pmadapter->mp_rd_bitmap &=
+				(t_u32)(~(1 << pmadapter->curr_rd_port));
+			*pport = pmadapter->curr_rd_port;
+
+			/* hw rx wraps round only after port (MAX_PORT-1) */
+			if (++pmadapter->curr_rd_port == max_ports)
+				pmadapter->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->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->mp_wr_bitmap;
+	const mlan_sdio_device *psdio_device = pmadapter->psdio_device;
+	const mlan_sdio_card_reg *reg = psdio_device->reg;
+	t_bool new_mode = psdio_device->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->mp_data_port_mask)) {
+		pmadapter->data_sent = MTRUE;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	if (pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port)) {
+		pmadapter->mp_wr_bitmap &=
+			(t_u32)(~(1 << pmadapter->curr_wr_port));
+		*pport = pmadapter->curr_wr_port;
+		if (++pmadapter->curr_wr_port == pmadapter->mp_end_port)
+			pmadapter->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->curr_wr_port, wr_bitmap,
+		       pmadapter->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->mp_wr_bitmap);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function polls the card status register.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param bits       the bit mask
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_poll_card_status(mlan_adapter *pmadapter, t_u8 bits)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 tries;
+	t_u32 cs = 0;
+
+	ENTER();
+
+	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       pmadapter->psdio_device->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->psdio_device->
+						      reg->status_reg_0,
+						      &fws0)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      pmadapter->psdio_device->
+						      reg->status_reg_1,
+						      &fws1)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	*dat = (t_u16)((fws1 << 8) | fws0);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**  @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->psdio_device->
+						      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->psdio_device->
+						       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->psdio_device->
+						       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_prog_fw_w_helper(IN 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;
+	t_u16 card_type = pmadapter->card_type;
+	const mlan_sdio_card_reg *reg = pmadapter->psdio_device->reg;
+	t_u32 read_base_0_reg = reg->base_0_reg;
+	t_u32 read_base_1_reg = reg->base_1_reg;
+	t_u8 crc_buffer = 0;
+	t_u8 *header_crc_fw;
+	t_u8 header_crc_fw_len = 0;
+	if (IS_SD8787(card_type)) {
+		header_crc_fw = fw_crc_header_rb;
+		header_crc_fw_len = FW_CRC_HEADER_RB;
+	} else {
+		header_crc_fw = fw_crc_header_rb2;
+		header_crc_fw_len = FW_CRC_HEADER_RB2;
+	}
+
+	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 (!pmadapter->init_para.fw_crc_check
+	    && (IS_SD8777(card_type) || (IS_SD8787(card_type)))
+		) {
+		/* CRC check not required, use custom header first */
+
+		firmware = header_crc_fw;
+		firmwarelen = header_crc_fw_len;
+
+		crc_buffer = 1;
+	}
+
+	/* 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;
+		}
+
+		if (!crc_buffer)
+			/* 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)) {
+			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);
+
+			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->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;
+		if (crc_buffer && offset >= header_crc_fw_len
+		    && (IS_SD8777(card_type) || (IS_SD8787(card_type)))
+			) {
+			/* Custom header download complete, restore original FW */
+			offset = 0;
+			firmware = fw;
+			firmwarelen = fw_len;
+			crc_buffer = 0;
+		}
+	} 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_host_int(pmlan_adapter pmadapter)
+{
+	mlan_status ret;
+
+	ENTER();
+	ret = wlan_sdio_disable_host_int_mask(pmadapter, HIM_DISABLE);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function decodes the rx packet &
+ *  calls corresponding handlers according to the packet type
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf      A pointer to the SDIO data/cmd buffer
+ *  @param upld_typ  Type of rx packet
+ *  @param lock_flag  flag for spin_lock.
+ *  @return          MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_decode_rx_packet(mlan_adapter *pmadapter, mlan_buffer *pmbuf,
+		      t_u32 upld_typ, t_u8 lock_flag)
+{
+	t_u8 *cmd_buf;
+	t_u32 event;
+
+	ENTER();
+
+	switch (upld_typ) {
+	case MLAN_TYPE_SPA_DATA:
+		PRINTM(MINFO, "--- Rx: SPA Data packet ---\n");
+		pmbuf->data_len = pmadapter->upld_len;
+		if (pmadapter->rx_work_flag) {
+			pmbuf->buf_type = MLAN_BUF_TYPE_SPA_DATA;
+			if (lock_flag)
+				pmadapter->callbacks.moal_spin_lock(pmadapter->
+								    pmoal_handle,
+								    pmadapter->
+								    rx_data_queue.
+								    plock);
+			util_enqueue_list_tail(pmadapter->pmoal_handle,
+					       &pmadapter->rx_data_queue,
+					       (pmlan_linked_list)pmbuf, MNULL,
+					       MNULL);
+			pmadapter->rx_pkts_queued++;
+			if (lock_flag)
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 rx_data_queue.plock);
+		} else {
+			wlan_decode_spa_buffer(pmadapter,
+					       pmbuf->pbuf + pmbuf->data_offset,
+					       pmbuf->data_len);
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+		}
+		pmadapter->data_received = MTRUE;
+		break;
+	case MLAN_TYPE_DATA:
+		PRINTM(MINFO, "--- Rx: Data packet ---\n");
+		if (pmadapter->upld_len > pmbuf->data_len) {
+			PRINTM(MERROR,
+			       "SDIO: Drop packet upld_len=%d data_len=%d \n",
+			       pmadapter->upld_len, pmbuf->data_len);
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+			break;
+		}
+		pmbuf->data_len = (pmadapter->upld_len - INTF_HEADER_LEN);
+		pmbuf->data_offset += INTF_HEADER_LEN;
+		if (pmadapter->rx_work_flag) {
+			if (lock_flag)
+				pmadapter->callbacks.moal_spin_lock(pmadapter->
+								    pmoal_handle,
+								    pmadapter->
+								    rx_data_queue.
+								    plock);
+			util_enqueue_list_tail(pmadapter->pmoal_handle,
+					       &pmadapter->rx_data_queue,
+					       (pmlan_linked_list)pmbuf, MNULL,
+					       MNULL);
+			pmadapter->rx_pkts_queued++;
+			if (lock_flag)
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 rx_data_queue.plock);
+		} else {
+			wlan_handle_rx_packet(pmadapter, pmbuf);
+		}
+		pmadapter->data_received = MTRUE;
+		break;
+
+	case MLAN_TYPE_CMD:
+		PRINTM(MINFO, "--- Rx: Cmd Response ---\n");
+		/* take care of curr_cmd = NULL case */
+		if (!pmadapter->curr_cmd) {
+			cmd_buf = pmadapter->upld_buf;
+			if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
+				wlan_process_sleep_confirm_resp(pmadapter,
+								pmbuf->pbuf +
+								pmbuf->
+								data_offset +
+								INTF_HEADER_LEN,
+								pmadapter->
+								upld_len -
+								INTF_HEADER_LEN);
+			}
+			pmadapter->upld_len -= INTF_HEADER_LEN;
+			memcpy(pmadapter, cmd_buf,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       INTF_HEADER_LEN, MIN(MRVDRV_SIZE_OF_CMD_BUFFER,
+						    pmadapter->upld_len -
+						    INTF_HEADER_LEN));
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+		} else {
+			pmadapter->cmd_resp_received = MTRUE;
+			pmadapter->upld_len -= INTF_HEADER_LEN;
+			pmbuf->data_len = pmadapter->upld_len;
+			pmbuf->data_offset += 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 +
+					       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(pmadapter, pmadapter->event_body,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       MLAN_EVENT_HEADER_LEN,
+			       pmadapter->upld_len - MLAN_EVENT_HEADER_LEN);
+		}
+
+		/* 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 += INTF_HEADER_LEN;
+		pmbuf->data_len -= 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;
+}
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+/**
+ *  @brief This function receives single packet
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_receive_single_packet(mlan_adapter *pmadapter)
+{
+	mlan_buffer *pmbuf;
+	t_u8 port;
+	t_u16 rx_len;
+	t_u32 pkt_type = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	pmbuf = pmadapter->mpa_rx.mbuf_arr[0];
+	port = pmadapter->mpa_rx.start_port;
+	rx_len = pmadapter->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->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->mpa_rx_count[0]++;
+	wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
+done:
+	if (ret != MLAN_STATUS_SUCCESS)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	MP_RX_AGGR_BUF_RESET(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function receives data from the card in aggregate mode.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_receive_mp_aggr_buf(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer mbuf_aggr;
+	mlan_buffer *mbuf_deaggr;
+	t_u32 pind = 0;
+	t_u32 pkt_len, pkt_type = 0;
+	t_u8 *curr_ptr;
+	t_u32 cmd53_port = 0;
+	t_u32 i = 0;
+	t_u32 port_count = 0;
+	t_bool new_mode = pmadapter->psdio_device->supports_sdio_new_mode;
+
+	/* do aggr RX now */
+	PRINTM(MINFO, "do_rx_aggr: num of packets: %d\n",
+	       pmadapter->mpa_rx.pkt_cnt);
+
+	memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+	if (pmadapter->mpa_rx.pkt_cnt == 1)
+		return wlan_receive_single_packet(pmadapter);
+	if (!pmadapter->mpa_rx.buf) {
+		mbuf_aggr.data_len = pmadapter->mpa_rx.buf_len;
+		mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+		mbuf_aggr.use_count = 0;
+		for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) {
+			pmadapter->mpa_rx.mbuf_arr[pind]->data_len =
+				pmadapter->mpa_rx.len_arr[pind];
+			wlan_link_buf_to_aggr(&mbuf_aggr,
+					      pmadapter->mpa_rx.mbuf_arr[pind]);
+		}
+	} else {
+		mbuf_aggr.pbuf = (t_u8 *)pmadapter->mpa_rx.buf;
+		mbuf_aggr.data_len = pmadapter->mpa_rx.buf_len;
+	}
+
+	if (new_mode) {
+		port_count = bitcount(pmadapter->mpa_rx.ports) - 1;
+		/* port_count = pmadapter->mpa_rx.pkt_cnt - 1; */
+		cmd53_port =
+			(pmadapter->
+			 ioport | SDIO_MPA_ADDR_BASE | (port_count << 8))
+			+ pmadapter->mpa_rx.start_port;
+	} else {
+		cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE |
+			      (pmadapter->mpa_rx.ports << 4)) +
+			pmadapter->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->mpa_rx.buf && pmadapter->mpa_rx.pkt_cnt > 1) {
+		for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) {
+			mbuf_deaggr = pmadapter->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->mpa_rx.buf,
+			    MIN(pmadapter->mpa_rx.buf_len, MAX_DATA_DUMP_LEN));
+
+		curr_ptr = pmadapter->mpa_rx.buf;
+
+		for (pind = 0; pind < pmadapter->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->mpa_rx.mbuf_arr[pind];
+			if ((pkt_type == MLAN_TYPE_DATA
+			     || pkt_type == MLAN_TYPE_SPA_DATA) &&
+			    (pkt_len <= pmadapter->mpa_rx.len_arr[pind])) {
+				memcpy(pmadapter,
+				       mbuf_deaggr->pbuf +
+				       mbuf_deaggr->data_offset, curr_ptr,
+				       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->mpa_rx.len_arr[pind]);
+				wlan_free_mlan_buffer(pmadapter, mbuf_deaggr);
+			}
+			curr_ptr += pmadapter->mpa_rx.len_arr[pind];
+		}
+	}
+	if (pmadapter->rx_work_flag)
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      pmadapter->rx_data_queue.
+						      plock);
+	pmadapter->mpa_rx_count[pmadapter->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_device *psdio_device = pmadapter->psdio_device;
+	const mlan_sdio_card_reg *reg = psdio_device->reg;
+	t_bool new_mode = psdio_device->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->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->mp_rd_bitmap & reg->data_port_mask)) ||
+	    (!new_mode &&
+	     (pmadapter->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 (pmadapter->psdio_device->supports_sdio_new_mode) {
+			MP_RX_AGGR_SETUP_NEWMODE(pmadapter, pmbuf, port,
+						 rx_len);
+		} else {
+			MP_RX_AGGR_SETUP_NONEWMODE(pmadapter, pmbuf, port,
+						   rx_len);
+		}
+
+		if (MP_RX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
+		    (((pmadapter->psdio_device->supports_sdio_new_mode) &&
+		      (MP_RX_AGGR_PORT_LIMIT_REACHED_NEWMODE(pmadapter))) ||
+		     ((!pmadapter->psdio_device->supports_sdio_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->ioport + port)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		if ((new_mode && (pkt_type != MLAN_TYPE_DATA)
+		     && (pkt_type != MLAN_TYPE_SPA_DATA)
+		    ) ||
+		    (!new_mode &&
+		     ((port == CTRL_PORT) &&
+		      ((pkt_type != MLAN_TYPE_EVENT) &&
+		       (pkt_type != MLAN_TYPE_CMD))))) {
+			if (new_mode)
+				PRINTM(MERROR,
+				       "receive a wrong pkt from DATA PORT: type=%d, len=%dd\n",
+				       pkt_type, pmbuf->data_len);
+			else
+				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))
+			pmadapter->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 (pmadapter->psdio_device->supports_sdio_new_mode) {
+			MP_RX_AGGR_SETUP_NEWMODE(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->mpa_rx.pkt_cnt; pind++) {
+				wlan_free_mlan_buffer(pmadapter,
+						      pmadapter->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;
+
+}
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/**
+ *  @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_bool new_mode = pmadapter->psdio_device->supports_sdio_new_mode;
+	t_u8 mp_aggr_pkt_limit = pmadapter->psdio_device->mp_aggr_pkt_limit;
+
+	ENTER();
+
+	if (!pmadapter->mpa_tx.pkt_cnt) {
+		LEAVE();
+		return ret;
+	}
+	PRINTM(MINFO, "host_2_card_mp_aggr: Send aggregation buffer."
+	       "%d %d\n", pmadapter->mpa_tx.start_port,
+	       pmadapter->mpa_tx.ports);
+
+	memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+	if (!pmadapter->mpa_tx.buf && pmadapter->mpa_tx.pkt_cnt > 1) {
+		mbuf_aggr.data_len = pmadapter->mpa_tx.buf_len;
+		mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+		mbuf_aggr.use_count = 0;
+		for (i = 0; i < pmadapter->mpa_tx.pkt_cnt; i++)
+			wlan_link_buf_to_aggr(&mbuf_aggr,
+					      pmadapter->mpa_tx.mbuf_arr[i]);
+	} else {
+		mbuf_aggr.pbuf = (t_u8 *)pmadapter->mpa_tx.buf;
+		mbuf_aggr.data_len = pmadapter->mpa_tx.buf_len;
+	}
+
+	if (new_mode) {
+		port_count = bitcount(pmadapter->mpa_tx.ports) - 1;
+		cmd53_port =
+			(pmadapter->
+			 ioport | SDIO_MPA_ADDR_BASE | (port_count << 8))
+			+ pmadapter->mpa_tx.start_port;
+	} else {
+		cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE |
+			      (pmadapter->mpa_tx.ports << 4)) +
+			pmadapter->mpa_tx.start_port;
+	}
+
+	if (pmadapter->mpa_tx.pkt_cnt == 1)
+		cmd53_port = pmadapter->ioport + pmadapter->mpa_tx.start_port;
+    /** only one packet */
+	if (!pmadapter->mpa_tx.buf && pmadapter->mpa_tx.pkt_cnt == 1)
+		ret = wlan_write_data_sync(pmadapter,
+					   pmadapter->mpa_tx.mbuf_arr[0],
+					   cmd53_port);
+	else
+		ret = wlan_write_data_sync(pmadapter, &mbuf_aggr, cmd53_port);
+	if (!pmadapter->mpa_tx.buf) {
+	/** free mlan buffer */
+		for (i = 0; i < pmadapter->mpa_tx.pkt_cnt; i++) {
+			wlan_write_data_complete(pmadapter,
+						 pmadapter->mpa_tx.mbuf_arr[i],
+						 MLAN_STATUS_SUCCESS);
+		}
+	}
+	if (!(pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port))
+	    && (pmadapter->mpa_tx.pkt_cnt < mp_aggr_pkt_limit))
+		pmadapter->mpa_sent_no_ports++;
+	pmadapter->mpa_tx_count[pmadapter->mpa_tx.pkt_cnt - 1]++;
+	pmadapter->last_mp_wr_bitmap[pmadapter->last_mp_index] =
+		pmadapter->mp_wr_bitmap;
+	pmadapter->last_mp_wr_ports[pmadapter->last_mp_index] = cmd53_port;
+	pmadapter->last_mp_wr_len[pmadapter->last_mp_index] =
+		pmadapter->mpa_tx.buf_len;
+	pmadapter->last_curr_wr_port[pmadapter->last_mp_index] =
+		pmadapter->curr_wr_port;
+	memcpy(pmadapter,
+	       (t_u8 *)&pmadapter->last_mp_wr_info[pmadapter->last_mp_index *
+						   mp_aggr_pkt_limit],
+	       (t_u8 *)pmadapter->mpa_tx.mp_wr_info,
+	       mp_aggr_pkt_limit * sizeof(t_u16)
+		);
+	pmadapter->last_mp_index++;
+	if (pmadapter->last_mp_index >= SDIO_MP_DBG_NUM)
+		pmadapter->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->psdio_device->mp_aggr_pkt_limit;
+
+	ENTER();
+
+	PRINTM(MIF_D, "host_2_card_mp_aggr: next_pkt_len: %d curr_port:%d\n",
+	       next_pkt_len, port);
+
+	if (!pmadapter->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->
+				     mp_wr_bitmap & (1 << pmadapter->
+						     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->
+				     mp_wr_bitmap & (1 << pmadapter->
+						     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->
+			     mp_wr_bitmap & (1 << pmadapter->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->mpa_sent_last_pkt++;
+	}
+
+	if (f_precopy_cur_buf) {
+		PRINTM(MINFO, "host_2_card_mp_aggr: Precopy current buffer\n");
+		if (pmadapter->mpa_buf)
+			memcpy(pmadapter, pmadapter->mpa_buf +
+			       (pmadapter->last_mp_index * mp_aggr_pkt_limit +
+				pmadapter->mpa_tx.pkt_cnt) *
+			       MLAN_SDIO_BLOCK_SIZE,
+			       mbuf->pbuf + mbuf->data_offset,
+			       MLAN_SDIO_BLOCK_SIZE);
+		if (!pmadapter->mpa_tx.buf) {
+			if (pmadapter->psdio_device->supports_sdio_new_mode)
+				MP_TX_AGGR_BUF_PUT_SG_NEWMODE(pmadapter, mbuf,
+							      port);
+			else
+				MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(pmadapter, mbuf,
+								port);
+			aggr_sg = MTRUE;
+		} else {
+
+			if (pmadapter->psdio_device->supports_sdio_new_mode)
+				MP_TX_AGGR_BUF_PUT_NEWMODE(pmadapter, mbuf,
+							   port);
+			else
+				MP_TX_AGGR_BUF_PUT_NONEWMODE(pmadapter, mbuf,
+							     port);
+		}
+		if (MP_TX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
+		    (!pmadapter->psdio_device->supports_sdio_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->ioport + port);
+		if (!(pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port)))
+			pmadapter->mpa_sent_no_ports++;
+		pmadapter->last_mp_wr_bitmap[pmadapter->last_mp_index] =
+			pmadapter->mp_wr_bitmap;
+		pmadapter->last_mp_wr_ports[pmadapter->last_mp_index] =
+			pmadapter->ioport + port;
+		pmadapter->last_mp_wr_len[pmadapter->last_mp_index] =
+			mbuf->data_len;
+		memset(pmadapter,
+		       (t_u8 *)&pmadapter->last_mp_wr_info[pmadapter->
+							   last_mp_index *
+							   mp_aggr_pkt_limit],
+		       0, sizeof(t_u16) * mp_aggr_pkt_limit);
+		pmadapter->last_mp_wr_info[pmadapter->last_mp_index *
+					   mp_aggr_pkt_limit] =
+			*(t_u16 *)(mbuf->pbuf + mbuf->data_offset);
+		pmadapter->last_curr_wr_port[pmadapter->last_mp_index] =
+			pmadapter->curr_wr_port;
+		if (pmadapter->mpa_buf)
+			memcpy(pmadapter,
+			       pmadapter->mpa_buf +
+			       (pmadapter->last_mp_index * mp_aggr_pkt_limit *
+				MLAN_SDIO_BLOCK_SIZE),
+			       mbuf->pbuf + mbuf->data_offset,
+			       MLAN_SDIO_BLOCK_SIZE);
+		pmadapter->last_mp_index++;
+		if (pmadapter->last_mp_index >= SDIO_MP_DBG_NUM)
+			pmadapter->last_mp_index = 0;
+		pmadapter->mpa_tx_count[0]++;
+	}
+	if (f_postcopy_cur_buf) {
+		PRINTM(MINFO, "host_2_card_mp_aggr: Postcopy current buffer\n");
+		if (pmadapter->mpa_buf)
+			memcpy(pmadapter, pmadapter->mpa_buf +
+			       (pmadapter->last_mp_index * mp_aggr_pkt_limit +
+				pmadapter->mpa_tx.pkt_cnt) *
+			       MLAN_SDIO_BLOCK_SIZE,
+			       mbuf->pbuf + mbuf->data_offset,
+			       MLAN_SDIO_BLOCK_SIZE);
+		if (!pmadapter->mpa_tx.buf) {
+			if (pmadapter->psdio_device->supports_sdio_new_mode)
+				MP_TX_AGGR_BUF_PUT_SG_NEWMODE(pmadapter, mbuf,
+							      port);
+			else
+				MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(pmadapter, mbuf,
+								port);
+			aggr_sg = MTRUE;
+		} else {
+			if (pmadapter->psdio_device->supports_sdio_new_mode)
+				MP_TX_AGGR_BUF_PUT_NEWMODE(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;
+}
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+/********************************************************
+		Global functions
+********************************************************/
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interface is present
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param val        Winner status (0: winner)
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status
+wlan_check_winner_status(mlan_adapter *pmadapter, t_u32 *val)
+{
+	t_u32 winner = 0;
+	pmlan_callbacks pcb;
+	t_u8 card_fw_status0_reg = pmadapter->psdio_device->reg->status_reg_0;
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_read_reg(pmadapter->pmoal_handle, card_fw_status0_reg,
+			       &winner)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param pollnum    Maximum polling number
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_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 == 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 downloads firmware to card
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param pmfw			A pointer to firmware image
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_dnld_fw(IN pmlan_adapter pmadapter, IN pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Download the firmware image via helper */
+	ret = wlan_prog_fw_w_helper(pmadapter, pmfw->pfw_buf, pmfw->fw_len);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	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->psdio_device->host_int_status_reg,
+			   &sdio_ireg);
+
+	/* Disable host interrupt mask register for SDIO */
+	ret = wlan_disable_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();
+
+	switch (card_type) {
+	case CARD_TYPE_SD8777:
+		pmadapter->psdio_device = &mlan_sdio_sd8777;
+		break;
+	case CARD_TYPE_SD8787:
+		pmadapter->psdio_device = &mlan_sdio_sd8787;
+		break;
+	case CARD_TYPE_SD8887:
+		pmadapter->psdio_device = &mlan_sdio_sd8887;
+		break;
+	case CARD_TYPE_SD8801:
+		pmadapter->psdio_device = &mlan_sdio_sd8801;
+		break;
+	case CARD_TYPE_SD8897:
+		pmadapter->psdio_device = &mlan_sdio_sd8897;
+		break;
+	case CARD_TYPE_SD8797:
+		pmadapter->psdio_device = &mlan_sdio_sd8797;
+		break;
+	case CARD_TYPE_SD8977:
+		pmadapter->psdio_device = &mlan_sdio_sd8977;
+		break;
+	case CARD_TYPE_SD8978:
+		pmadapter->psdio_device = &mlan_sdio_sd8978;
+		break;
+	case CARD_TYPE_SD8997:
+		pmadapter->psdio_device = &mlan_sdio_sd8997;
+		break;
+	case CARD_TYPE_SD8987:
+		pmadapter->psdio_device = &mlan_sdio_sd8987;
+		break;
+	default:
+		PRINTM(MERROR, "can't get right card type \n");
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets interrupt status.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_interrupt(pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer mbuf;
+	t_u32 sdio_ireg = 0;
+
+	t_u8 max_mp_regs = pmadapter->psdio_device->reg->max_mp_regs;
+	t_u8 host_int_status_reg = pmadapter->psdio_device->host_int_status_reg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 i = 0;
+
+	ENTER();
+
+	memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+	mbuf.pbuf = pmadapter->mp_regs;
+	mbuf.data_len = max_mp_regs;
+
+	do {
+		ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf,
+					       REG_PORT |
+					       MLAN_SDIO_BYTE_MODE_MASK, 0);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "moal_read_data_sync: read registers failed\n");
+			pmadapter->dbg.num_int_read_failure++;
+		}
+		if (i++ > 4)
+			goto done;
+	} while (ret != MLAN_STATUS_SUCCESS);
+
+	DBG_HEXDUMP(MIF_D, "SDIO MP Registers", pmadapter->mp_regs,
+		    max_mp_regs);
+	sdio_ireg = pmadapter->mp_regs[host_int_status_reg];
+	pmadapter->dbg.last_int_status = pmadapter->sdio_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->num_of_irq++;
+		pcb->moal_spin_lock(pmadapter->pmoal_handle,
+				    pmadapter->pint_lock);
+		pmadapter->sdio_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 enables the host interrupts.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_enable_host_int(pmlan_adapter pmadapter)
+{
+	mlan_status ret;
+	t_u8 mask = HIM_ENABLE;
+	mask = pmadapter->psdio_device->reg->host_int_enable;
+
+	ENTER();
+	ret = wlan_sdio_enable_host_int_mask(pmadapter, mask);
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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->psdio_device->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->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->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->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;
+}
+#endif
+
+/**
+ *  @brief This function checks the interrupt status and handle it accordingly.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_process_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_device *psdio_device = pmadapter->psdio_device;
+	const mlan_sdio_card_reg *reg = psdio_device->reg;
+	t_bool new_mode = psdio_device->supports_sdio_new_mode;
+	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 = psdio_device->cmd_rd_len_0;
+	t_u8 cmd_rd_len_1 = psdio_device->cmd_rd_len_1;
+
+	ENTER();
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+	sdio_ireg = pmadapter->sdio_ireg;
+	pmadapter->sdio_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->mp_regs[cmd_rd_len_1]) << 8;
+			rx_len |= (t_u16)pmadapter->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 <= 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->
+						   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%d\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->mp_wr_bitmap & pmadapter->mp_data_port_mask)
+			pmadapter->mp_invalid_update++;
+		pmadapter->mp_wr_bitmap =
+			(t_u32)pmadapter->mp_regs[reg->wr_bitmap_l];
+		pmadapter->mp_wr_bitmap |=
+			((t_u32)pmadapter->mp_regs[reg->wr_bitmap_u]) << 8;
+		if (psdio_device->supports_sdio_new_mode) {
+			pmadapter->mp_wr_bitmap |=
+				((t_u32)pmadapter->
+				 mp_regs[reg->wr_bitmap_1l]) << 16;
+			pmadapter->mp_wr_bitmap |=
+				((t_u32)pmadapter->
+				 mp_regs[reg->wr_bitmap_1u]) << 24;
+		}
+		bit_count =
+			bitcount(pmadapter->mp_wr_bitmap & pmadapter->
+				 mp_data_port_mask);
+		if (bit_count) {
+			pmadapter->mp_update[bit_count - 1]++;
+			if (pmadapter->mp_update[bit_count - 1] == 0xffffffff)
+				memset(pmadapter, pmadapter->mp_update, 0,
+				       sizeof(pmadapter->mp_update));
+		}
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+		pmadapter->last_recv_wr_bitmap = pmadapter->mp_wr_bitmap;
+#endif
+		PRINTM(MINTR, "DNLD: wr_bitmap=0x%08x\n",
+		       pmadapter->mp_wr_bitmap);
+		if (pmadapter->data_sent &&
+		    (pmadapter->
+		     mp_wr_bitmap & (1 << pmadapter->curr_wr_port))) {
+			PRINTM(MINFO, " <--- Tx DONE Interrupt --->\n");
+			pmadapter->data_sent = MFALSE;
+		}
+	}
+
+	if ((!psdio_device->supports_sdio_new_mode) &&
+	    (pmadapter->cmd_sent == MTRUE)) {
+		/* Check if firmware has attach buffer at command port and update just that in wr_bit_map. */
+		pmadapter->mp_wr_bitmap |=
+			(t_u32)pmadapter->mp_regs[reg->
+						  wr_bitmap_l] & CTRL_PORT_MASK;
+		if (pmadapter->mp_wr_bitmap & CTRL_PORT_MASK)
+			pmadapter->cmd_sent = MFALSE;
+	}
+
+	PRINTM(MINFO, "cmd_sent=%d, data_sent=%d\n", pmadapter->cmd_sent,
+	       pmadapter->data_sent);
+	if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
+		pmadapter->mp_rd_bitmap =
+			(t_u32)pmadapter->mp_regs[reg->rd_bitmap_l];
+		pmadapter->mp_rd_bitmap |=
+			((t_u32)pmadapter->mp_regs[reg->rd_bitmap_u]) << 8;
+		if (psdio_device->supports_sdio_new_mode) {
+			pmadapter->mp_rd_bitmap |=
+				((t_u32)pmadapter->
+				 mp_regs[reg->rd_bitmap_1l]) << 16;
+			pmadapter->mp_rd_bitmap |=
+				((t_u32)pmadapter->
+				 mp_regs[reg->rd_bitmap_1u]) << 24;
+		}
+		PRINTM(MINTR, "UPLD: rd_bitmap=0x%08x\n",
+		       pmadapter->mp_rd_bitmap);
+
+		while (MTRUE) {
+			ret = wlan_get_rd_port(pmadapter, &port);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MINFO,
+				       "no more rd_port to be handled\n");
+				break;
+			}
+			len_reg_l = rd_len_p0_l + (port << 1);
+			len_reg_u = rd_len_p0_u + (port << 1);
+			rx_len = ((t_u16)pmadapter->mp_regs[len_reg_u]) << 8;
+			rx_len |= (t_u16)pmadapter->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 defined(SDIO_MULTI_PORT_RX_AGGR)
+			if (rx_len <= INTF_HEADER_LEN ||
+			    (rx_blocks * MLAN_SDIO_BLOCK_SIZE) >
+			    pmadapter->mpa_rx.buf_size) {
+#else
+			if (rx_len <= INTF_HEADER_LEN ||
+			    (rx_blocks * MLAN_SDIO_BLOCK_SIZE) >
+			    ALLOC_BUF_SIZE) {
+#endif
+				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)) ||
+			    (rx_len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))
+				pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+							       rx_len, 0,
+							       MOAL_MALLOC_BUFFER);
+			else
+				pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+							       rx_len,
+							       MLAN_RX_HEADER_LEN,
+							       MOAL_ALLOC_MLAN_BUFFER);
+			if (pmbuf == MNULL) {
+				PRINTM(MERROR,
+				       "Failed to allocate 'mlan_buffer'\n");
+				pmadapter->dbg.num_alloc_buffer_failure++;
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+				if (MLAN_STATUS_SUCCESS ==
+				    wlan_sdio_card_to_host_recovery(pmadapter,
+								    port,
+								    rx_len))
+					continue;
+#endif
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(MINFO, "rx_len = %d\n", rx_len);
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+			if (MLAN_STATUS_SUCCESS !=
+			    wlan_sdio_card_to_host_mp_aggr(pmadapter, pmbuf,
+							   port, rx_len)) {
+#else
+			/* 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->ioport + port)) {
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+				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);
+#ifndef SDIO_MULTI_PORT_RX_AGGR
+				wlan_free_mlan_buffer(pmadapter, pmbuf);
+#endif
+				ret = MLAN_STATUS_FAILURE;
+				goto term_cmd53;
+			}
+#ifndef SDIO_MULTI_PORT_RX_AGGR
+			wlan_decode_rx_packet(pmadapter, pmbuf, upld_typ,
+					      MTRUE);
+#endif
+		}
+		/* We might receive data/sleep_cfm at the same time */
+		/* reset data_receive flag to avoid ps_state change */
+		if ((ps_state == PS_STATE_SLEEP_CFM) &&
+		    (pmadapter->ps_state == PS_STATE_SLEEP))
+			pmadapter->data_received = MFALSE;
+	}
+
+	ret = MLAN_STATUS_SUCCESS;
+	goto done;
+
+term_cmd53:
+	/* terminate cmd53 */
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      HOST_TO_CARD_EVENT_REG,
+						      &cr))
+		PRINTM(MERROR, "read CFG reg failed\n");
+	PRINTM(MINFO, "Config Reg val = %d\n", cr);
+	if (MLAN_STATUS_SUCCESS != pcb->moal_write_reg(pmadapter->pmoal_handle,
+						       HOST_TO_CARD_EVENT_REG,
+						       (cr | HOST_TERM_CMD53)))
+		PRINTM(MERROR, "write CFG reg failed\n");
+	PRINTM(MINFO, "write success\n");
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      HOST_TO_CARD_EVENT_REG,
+						      &cr))
+		PRINTM(MERROR, "read CFG reg failed\n");
+	PRINTM(MINFO, "Config reg val =%x\n", cr);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param type      data or command
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include SDIO header)
+ *  @param tx_param  A pointer to mlan_tx_param
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_sdio_host_to_card(mlan_adapter *pmadapter, t_u8 type, mlan_buffer *pmbuf,
+		       mlan_tx_param *tx_param)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 buf_block_len;
+	t_u32 blksz;
+	t_u8 port = 0;
+	t_u32 cmd53_port = 0;
+	t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset;
+
+	ENTER();
+
+	/* Allocate buffer and copy payload */
+	blksz = MLAN_SDIO_BLOCK_SIZE;
+	buf_block_len = (pmbuf->data_len + blksz - 1) / blksz;
+	*(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+	*(t_u16 *)&payload[2] = wlan_cpu_to_le16(type);
+
+	/*
+	 * This is SDIO specific header
+	 *  t_u16 length,
+	 *  t_u16 type (MLAN_TYPE_DATA = 0,
+	 *    MLAN_TYPE_CMD = 1, MLAN_TYPE_EVENT = 3)
+	 */
+	if (type == MLAN_TYPE_DATA) {
+		ret = wlan_get_wr_port_data(pmadapter, &port);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "no wr_port available: wr_bitmap=0x%08x curr_wr_port=%d\n",
+			       pmadapter->mp_wr_bitmap,
+			       pmadapter->curr_wr_port);
+			goto exit;
+		}
+		/* Transfer data to card */
+		pmbuf->data_len = buf_block_len * blksz;
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+		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
+		ret = wlan_write_data_sync(pmadapter, pmbuf,
+					   pmadapter->ioport + port);
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+	} else {
+		/*Type must be MLAN_TYPE_CMD */
+		pmadapter->cmd_sent = MTRUE;
+		if (!pmadapter->psdio_device->supports_sdio_new_mode)
+			pmadapter->mp_wr_bitmap &= (t_u32)(~(1 << CTRL_PORT));
+		if (pmbuf->data_len <= 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 (pmadapter->psdio_device->supports_sdio_new_mode)
+			cmd53_port = (pmadapter->ioport) | CMD_PORT_SLCT;
+		else
+			cmd53_port = pmadapter->ioport + CTRL_PORT;
+		ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port);
+	}
+
+	if (ret == MLAN_STATUS_FAILURE) {
+		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->
+			     mp_wr_bitmap & (1 << pmadapter->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;
+}
+
+/**
+ *  @brief Deaggregate single port aggregation packet
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param buf	A pointer to aggregated data packet
+ *  @param len
+ *
+ *  @return		N/A
+ */
+void
+wlan_decode_spa_buffer(mlan_adapter *pmadapter, t_u8 *buf, t_u32 len)
+{
+	int total_pkt_len;
+	t_u8 block_num = 0;
+	t_u16 block_size = 0;
+	t_u8 *data;
+	t_u32 pkt_len, pkt_type = 0;
+	mlan_buffer *mbuf_deaggr = MNULL;
+
+	ENTER();
+
+	data = (t_u8 *)buf;
+	total_pkt_len = len;
+	if (total_pkt_len < pmadapter->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 + INTF_HEADER_LEN)) {
+		block_num = *(data + OFFSET_OF_BLOCK_NUMBER);
+		block_size = pmadapter->sdio_rx_block_size * block_num;
+		if (block_size > total_pkt_len) {
+			PRINTM(MERROR,
+			       "Error in pkt, block_num=%d, pkt_len=%d\n",
+			       block_num, total_pkt_len);
+			break;
+		}
+		pkt_len =
+			wlan_le16_to_cpu(*(t_u16 *)
+					 (data + OFFSET_OF_SDIO_HEADER));
+		pkt_type =
+			wlan_le16_to_cpu(*(t_u16 *)
+					 (data + OFFSET_OF_SDIO_HEADER + 2));
+		if ((pkt_len + OFFSET_OF_SDIO_HEADER) > block_size) {
+			PRINTM(MERROR,
+			       "Error in pkt, pkt_len=%d, block_size=%d\n",
+			       pkt_len, block_size);
+			break;
+		}
+		mbuf_deaggr =
+			wlan_alloc_mlan_buffer(pmadapter,
+					       pkt_len - 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(pmadapter, mbuf_deaggr->pbuf + mbuf_deaggr->data_offset,
+		       data + OFFSET_OF_SDIO_HEADER + INTF_HEADER_LEN,
+		       pkt_len - INTF_HEADER_LEN);
+		mbuf_deaggr->data_len = pkt_len - INTF_HEADER_LEN;
+		wlan_handle_rx_packet(pmadapter, mbuf_deaggr);
+		data += block_size;
+		total_pkt_len -= block_size;
+		if (total_pkt_len < pmadapter->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(IN 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);
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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(IN 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->psdio_device->mp_aggr_pkt_limit;
+
+	ENTER();
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	if ((pmadapter->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->max_seg_size < pmadapter->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->mpa_tx.head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mpa_tx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP TX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->mpa_tx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->mpa_tx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable TX SG mode\n");
+		pmadapter->mpa_tx.head_ptr = MNULL;
+		pmadapter->mpa_tx.buf = MNULL;
+	}
+	pmadapter->mpa_tx.buf_size = mpa_tx_buf_size;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	if ((pmadapter->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->max_seg_size < pmadapter->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->mpa_rx.head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mpa_rx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP RX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->mpa_rx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->mpa_rx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable RX SG mode\n");
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+	}
+	pmadapter->mpa_rx.buf_size = mpa_rx_buf_size;
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+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(IN mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	if (pmadapter->mpa_tx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mpa_tx.head_ptr);
+		pmadapter->mpa_tx.head_ptr = MNULL;
+		pmadapter->mpa_tx.buf = MNULL;
+		pmadapter->mpa_tx.buf_size = 0;
+	}
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	if (pmadapter->mpa_rx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mpa_rx.head_ptr);
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+		pmadapter->mpa_rx.buf_size = 0;
+	}
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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(IN mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 mp_aggr_pkt_limit = pmadapter->psdio_device->mp_aggr_pkt_limit;
+
+	t_u32 mpa_rx_buf_size = pmadapter->psdio_device->mp_rx_aggr_buf_size;
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	if (pmadapter->mpa_rx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mpa_rx.head_ptr);
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+		pmadapter->mpa_rx.buf_size = 0;
+	}
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+	if (pmadapter->sdio_rx_aggr_enable)
+		mpa_rx_buf_size = MAX(mpa_rx_buf_size, SDIO_CMD53_MAX_SIZE);
+	if ((pmadapter->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->max_seg_size < pmadapter->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->mpa_rx.head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mpa_rx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP RX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->mpa_rx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->mpa_rx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable RX SG mode\n");
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+	}
+	pmadapter->mpa_rx.buf_size = mpa_rx_buf_size;
+	PRINTM(MMSG, "mpa_rx_buf_size=%d\n", mpa_rx_buf_size);
+error:
+	return ret;
+}
+#endif
+
+#endif /* SDIO_MULTI_PORT_TX_AGGR || SDIO_MULTI_PORT_RX_AGGR */
+
+/**
+ *  @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(IN 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->int_mode == INT_MODE_GPIO) {
+		if (pmadapter->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->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,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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(pmpriv->adapter, psdio_gpio_int, pdata_buf,
+		       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;
+}
+
+#define SD8897_FW_RESET_REG  0x0E8
+#define SD8887_FW_RESET_REG  0x0B6
+#define SD8977_SD8978_SD8997_FW_RESET_REG  0x0EE
+#define SD8887_SD8897_FW_RESET_VAL  1
+#define SD8977_SD8978_SD8997_FW_RESET_VAL  0x99
+mlan_status
+wlan_reset_fw(pmlan_adapter pmadapter)
+{
+	t_u32 tries = 0;
+	t_u32 value = 1;
+	t_u32 reset_reg = pmadapter->psdio_device->reg->reset_reg;
+	t_u8 reset_val = pmadapter->psdio_device->reg->reset_val;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	wlan_pm_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 (pmadapter->card_type == CARD_TYPE_SD8977
+	    || pmadapter->card_type == CARD_TYPE_SD8987
+	    || pmadapter->card_type == CARD_TYPE_SD8978
+	    || pmadapter->card_type == CARD_TYPE_SD8997) {
+		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);
+	}
+	/* 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;
+}
diff --git a/wlan_sd8987/mlan/mlan_sdio.h b/wlan_sd8987/mlan/mlan_sdio.h
new file mode 100644
index 0000000..50ea1f5
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sdio.h
@@ -0,0 +1,1240 @@
+/** @file mlan_sdio.h
+  *
+  * @brief This file contains definitions for SDIO interface.
+  * driver.
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/****************************************************
+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 : Host interrupt RSR */
+#define HOST_INT_RSR_REG		0x01
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR		(0x1U)
+#define HOST_INT_RSR_MASK		0xFF
+
+/** Host Control Registers : Host interrupt mask */
+#define HOST_INT_MASK_REG		0x02
+
+/** 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 : Host interrupt status */
+#define HOST_INT_STATUS_REG		0x03
+
+/** 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 status */
+#define UP_LD_HOST_INT_STATUS		(0x1U)
+/** Host Control Registers : Download host interrupt status */
+#define DN_LD_HOST_INT_STATUS		(0x2U)
+
+/** Port for registers */
+#define REG_PORT			0
+/** LSB of read bitmap */
+#define RD_BITMAP_L			0x04
+/** MSB of read bitmap */
+#define RD_BITMAP_U			0x05
+/** LSB of write bitmap */
+#define WR_BITMAP_L			0x06
+/** MSB of write bitmap */
+#define WR_BITMAP_U			0x07
+/** LSB of read length for port 0 */
+#define RD_LEN_P0_L			0x08
+/** MSB of read length for port 0 */
+#define RD_LEN_P0_U			0x09
+/** Ctrl port */
+#define CTRL_PORT			0
+/** Ctrl port mask */
+#define CTRL_PORT_MASK			0x0001
+/** Data port mask */
+#define DATA_PORT_MASK			0xfffe
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT		MBIT(4)
+
+/** Host Control Registers : Host transfer status */
+#define HOST_RESTART_REG		0x28
+/** 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 */
+/** Card Control Registers : Card to host event */
+#define CARD_TO_HOST_EVENT_REG		0x30
+/** 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 interrupt mask register */
+#define HOST_INTERRUPT_MASK_REG		0x34
+/** 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 : Card interrupt status register */
+#define CARD_INTERRUPT_STATUS_REG	0x38
+/** 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 : Card interrupt RSR register */
+#define CARD_INTERRUPT_RSR_REG		0x3c
+/** 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 : SQ Read base address 0 register */
+#define READ_BASE_0_REG			0x40
+/** Card Control Registers : SQ Read base address 1 register */
+#define READ_BASE_1_REG			0x41
+
+/** Card Control Registers : Card revision register */
+#define CARD_REVISION_REG		0x5c
+
+/** Firmware status 0 register (SCRATCH0_0) */
+#define CARD_FW_STATUS0_REG		0x60
+/** Firmware status 1 register (SCRATCH0_1) */
+#define CARD_FW_STATUS1_REG		0x61
+/** Rx length register (SCRATCH0_2) */
+#define CARD_RX_LEN_REG			0x62
+/** Rx unit register (SCRATCH0_3) */
+#define CARD_RX_UNIT_REG		0x63
+
+/** Card Control Registers : Card OCR 0 register */
+#define CARD_OCR_0_REG			0x68
+/** Card Control Registers : Card OCR 1 register */
+#define CARD_OCR_1_REG			0x69
+/** Card Control Registers : Card OCR 3 register */
+#define CARD_OCR_3_REG			0x6A
+/** Card Control Registers : Card config register */
+#define CARD_CONFIG_REG			0x6B
+/** Card Control Registers : Miscellaneous Configuration Register */
+#define CARD_MISC_CFG_REG		0x6C
+
+/** Card Control Registers : Debug 0 register */
+#define DEBUG_0_REG			0x70
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0			(0x1U)
+/** Card Control Registers : Debug 1 register */
+#define DEBUG_1_REG			0x71
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1			(0x1U)
+/** Card Control Registers : Debug 2 register */
+#define DEBUG_2_REG			0x72
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2			(0x1U)
+/** Card Control Registers : Debug 3 register */
+#define DEBUG_3_REG			0x73
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3			(0x1U)
+
+/** Host Control Registers : I/O port 0 */
+#define IO_PORT_0_REG			0x78
+/** Host Control Registers : I/O port 1 */
+#define IO_PORT_1_REG			0x79
+/** Host Control Registers : I/O port 2 */
+#define IO_PORT_2_REG			0x7A
+
+/** Port for memory */
+#define MEM_PORT	                        0x10000
+/** Card Control Registers : cmd53 new mode */
+#define CMD53_NEW_MODE      (0x1U << 0)
+#define CMD_PORT_RD_LEN_EN  (0x1U << 2)
+#define CMD_PORT_AUTO_EN              (0x1U << 0)
+#define CMD_PORT_SLCT                   0x8000
+/** Ctrl port mask */
+#define CTRL_PORT_MASK			0x0001
+/** 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
+
+/** SD8787 card type */
+#define CARD_TYPE_SD8787   0x01
+/** SD8777 card type */
+#define CARD_TYPE_SD8777   0x02
+/** SD8887 card type */
+#define CARD_TYPE_SD8887   0x03
+/** SD8801 card type */
+#define CARD_TYPE_SD8801   0x04
+/** SD8897 card type */
+#define CARD_TYPE_SD8897   0x05
+/** SD8797 card type */
+#define CARD_TYPE_SD8797   0x06
+/** SD8977 card type */
+#define CARD_TYPE_SD8977   0x07
+/** SD8997 card type */
+#define CARD_TYPE_SD8997   0x08
+/** SD8987 card type */
+#define CARD_TYPE_SD8987   0x09
+/** SD8978 card type */
+#define CARD_TYPE_SD8978   0x0A
+
+#define IS_SD8777(ct) (CARD_TYPE_SD8777 == (ct))
+#define IS_SD8787(ct) (CARD_TYPE_SD8787 == (ct))
+#define IS_SD8887(ct) (CARD_TYPE_SD8887 == (ct))
+#define IS_SD8801(ct) (CARD_TYPE_SD8801 == (ct))
+#define IS_SD8897(ct) (CARD_TYPE_SD8897 == (ct))
+#define IS_SD8797(ct) (CARD_TYPE_SD8797 == (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))
+
+/** Event header Len*/
+#define MLAN_EVENT_HEADER_LEN           8
+
+/** SDIO byte mode size */
+#define MAX_BYTE_MODE_SIZE             512
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** The base address for packet with multiple ports aggregation */
+#define SDIO_MPA_ADDR_BASE             0x1000
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+
+/** SDIO Tx aggregation in progress ? */
+#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0)
+
+/** SDIO Tx aggregation buffer room for next packet ? */
+#define MP_TX_AGGR_BUF_HAS_ROOM(a, mbuf, len) \
+			(((a->mpa_tx.buf_len) + len) <= (a->mpa_tx.buf_size))
+
+/** Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */
+#define MP_TX_AGGR_BUF_PUT_NEWMODE(a, mbuf, port) do {                  \
+	pmadapter->callbacks.moal_memmove(a->pmoal_handle, \
+		&a->mpa_tx.buf[a->mpa_tx.buf_len], \
+		mbuf->pbuf+mbuf->data_offset, mbuf->data_len);\
+	a->mpa_tx.buf_len += mbuf->data_len;                        \
+    a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+	if (!a->mpa_tx.pkt_cnt) {                                   \
+	    a->mpa_tx.start_port = port;                            \
+	}                                                           \
+	a->mpa_tx.ports |= (1 << port);                             \
+	a->mpa_tx.pkt_cnt++;                                        \
+} while (0)
+
+#define MP_TX_AGGR_BUF_PUT_SG_NEWMODE(a, mbuf, port) do {               \
+	a->mpa_tx.buf_len += mbuf->data_len;                        \
+    a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+    a->mpa_tx.mbuf_arr[a->mpa_tx.pkt_cnt] = mbuf;               \
+	if (!a->mpa_tx.pkt_cnt) {                                   \
+	    a->mpa_tx.start_port = port;                            \
+	}                                                           \
+	a->mpa_tx.ports |= (1 << port);                             \
+	a->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->mpa_tx.buf[a->mpa_tx.buf_len], \
+		mbuf->pbuf+mbuf->data_offset, mbuf->data_len);\
+	a->mpa_tx.buf_len += mbuf->data_len;                        \
+	a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+	if (!a->mpa_tx.pkt_cnt) {                                   \
+	    a->mpa_tx.start_port = port;                            \
+	}                                                           \
+	if (a->mpa_tx.start_port <= port) {                         \
+	    a->mpa_tx.ports |= (1 << (a->mpa_tx.pkt_cnt));			\
+	} else {                                                    \
+	      a->mpa_tx.ports |= (1 << (a->mpa_tx.pkt_cnt \
+			+ 1 + (a->psdio_device->max_ports - a->mp_end_port)));  \
+	}                                                           \
+	a->mpa_tx.pkt_cnt++;                                       \
+} while (0)
+#define MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(a, mbuf, port) do {                  \
+	a->mpa_tx.buf_len += mbuf->data_len;                        \
+    a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+    a->mpa_tx.mbuf_arr[a->mpa_tx.pkt_cnt] = mbuf;               \
+	if (!a->mpa_tx.pkt_cnt) {                                   \
+	    a->mpa_tx.start_port = port;                            \
+	}                                                           \
+	if (a->mpa_tx.start_port <= port) {                         \
+	    a->mpa_tx.ports |= (1 << (a->mpa_tx.pkt_cnt));			\
+	} else {                                                    \
+	      a->mpa_tx.ports |= (1 << (a->mpa_tx.pkt_cnt \
+			+ 1 + (a->psdio_device->max_ports - a->mp_end_port)));  \
+	}                                                           \
+	a->mpa_tx.pkt_cnt++;                                       \
+} while (0)
+/** SDIO Tx aggregation limit ? */
+#define MP_TX_AGGR_PKT_LIMIT_REACHED(a) ((a->mpa_tx.pkt_cnt) \
+			== (a->mpa_tx.pkt_aggr_limit))
+
+/** SDIO Tx aggregation port limit ? */
+
+#define MP_TX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_wr_port < \
+                a->mpa_tx.start_port) && (((a->psdio_device->max_ports - \
+                a->mpa_tx.start_port) + a->curr_wr_port) >= \
+                    a->psdio_device->mp_aggr_pkt_limit))
+
+/** Reset SDIO Tx aggregation buffer parameters */
+#define MP_TX_AGGR_BUF_RESET(a) do {         \
+	memset(a, a->mpa_tx.mp_wr_info, 0, sizeof(a->mpa_tx.mp_wr_info)); \
+	a->mpa_tx.pkt_cnt = 0;                   \
+	a->mpa_tx.buf_len = 0;                   \
+	a->mpa_tx.ports = 0;                     \
+	a->mpa_tx.start_port = 0;                \
+} while (0)
+
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+
+/** SDIO Rx aggregation limit ? */
+#define MP_RX_AGGR_PKT_LIMIT_REACHED(a) (a->mpa_rx.pkt_cnt \
+		== a->mpa_rx.pkt_aggr_limit)
+
+/** SDIO Rx aggregation port limit ? */
+#define MP_RX_AGGR_PORT_LIMIT_REACHED_NEWMODE(a) \
+			(((a->curr_rd_port < a->mpa_rx.start_port) && \
+			(((a->psdio_device->max_ports - a->mpa_rx.start_port) + a->curr_rd_port) \
+			>= (a->mp_end_port >> 1))) || \
+			((a->curr_rd_port - a->mpa_rx.start_port) >= \
+			(a->mp_end_port >> 1)))
+#define MP_RX_AGGR_PORT_LIMIT_REACHED_NONEWMODE(a) ((a->curr_rd_port < \
+                a->mpa_rx.start_port) && (((a->psdio_device->max_ports - \
+                a->mpa_rx.start_port) + a->curr_rd_port) >= \
+                a->psdio_device->mp_aggr_pkt_limit))
+
+/** SDIO Rx aggregation in progress ? */
+#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0)
+
+/** SDIO Rx aggregation buffer room for next packet ? */
+#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len)   \
+	((a->mpa_rx.buf_len + rx_len) <= a->mpa_rx.buf_size)
+
+/** Prepare to copy current packet from card to SDIO Rx aggregation buffer */
+#define MP_RX_AGGR_SETUP_NEWMODE(a, mbuf, port, rx_len) do {   \
+	a->mpa_rx.buf_len += rx_len;                       \
+	if (!a->mpa_rx.pkt_cnt) {                          \
+	    a->mpa_rx.start_port = port;                   \
+	}                                                  \
+	a->mpa_rx.ports |= (1 << port);                    \
+	a->mpa_rx.mbuf_arr[a->mpa_rx.pkt_cnt] = mbuf;      \
+	a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = rx_len;     \
+	a->mpa_rx.pkt_cnt++;                              \
+} while (0);
+
+#define MP_RX_AGGR_SETUP_NONEWMODE(a, mbuf, port, rx_len) do {   \
+	a->mpa_rx.buf_len += rx_len;                       \
+	if (!a->mpa_rx.pkt_cnt) {                          \
+	    a->mpa_rx.start_port = port;                   \
+	}                                                  \
+	if (a->mpa_rx.start_port <= port) {                  \
+	    a->mpa_rx.ports |= (1 << (a->mpa_rx.pkt_cnt)); \
+	} else {                                           \
+	    a->mpa_rx.ports |= (1 << (a->mpa_rx.pkt_cnt + 1)); \
+	}                                                  \
+	a->mpa_rx.mbuf_arr[a->mpa_rx.pkt_cnt] = mbuf;      \
+	a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = rx_len;     \
+	a->mpa_rx.pkt_cnt++;                               \
+} while (0);
+
+/** Reset SDIO Rx aggregation buffer parameters */
+#define MP_RX_AGGR_BUF_RESET(a) do {         \
+	a->mpa_rx.pkt_cnt = 0;                   \
+	a->mpa_rx.buf_len = 0;                   \
+	a->mpa_rx.ports = 0;                     \
+	a->mpa_rx.start_port = 0;                \
+} while (0)
+
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+/** Register sdio 87xx card structure */
+static const struct _mlan_sdio_card_reg mlan_reg_sd87xx = {
+     /** start read port */
+	.start_rd_port = 1,
+    /** start write port */
+	.start_wr_port = 1,
+    /** base register0 */
+	.base_0_reg = 0x40,	//0x0040,
+    /** base1 register1 */
+	.base_1_reg = 0x41,	//0x0041,
+    /** poll register */
+	.poll_reg = 0x30,
+    /** host interrupt enable */
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK,
+    /** host interrupt status*/
+	.host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS,
+     /** status register0 */
+	.status_reg_0 = 0x60,
+    /** status register 1 */
+	.status_reg_1 = 0x61,
+    /** sdio interrupt mask */
+	.sdio_int_mask = 0x3f,
+    /** data port mask */
+	.data_port_mask = 0x0000fffe,
+    /** maximum mp register */
+	.max_mp_regs = 64,
+     /** read bitmap lower byte */
+	.rd_bitmap_l = 0x04,
+    /** read bitmap upper byte */
+	.rd_bitmap_u = 0x05,
+    /** write bitmap lower byte */
+	.wr_bitmap_l = 0x06,
+    /** write bitmap upper byte */
+	.wr_bitmap_u = 0x07,
+    /** read port0 length lower byte */
+	.rd_len_p0_l = 0x08,
+    /** read port0 length upper byte */
+	.rd_len_p0_u = 0x09,
+    /** card misc configuration register */
+	.card_misc_cfg_reg = 0x6c,
+     /** scratch reg used for reset and check SOC wakeup*/
+	.reset_reg = 0x64,
+    /** reset value, not set for 87xx */
+	.reset_val = 0,
+};
+
+/** Registeri sdio 8887 card structure */
+static const struct _mlan_sdio_card_reg mlan_reg_sd8887 = {
+     /** start read port */
+	.start_rd_port = 0,
+    /** start write port */
+	.start_wr_port = 0,
+    /** base register0 */
+	.base_0_reg = 0x6C,
+    /** base register1 */
+	.base_1_reg = 0x6D,
+    /** poll register */
+	.poll_reg = 0x5C,
+    /** host interrupt enable */
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+		CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+     /** host interrupt status */
+	.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 register0 */
+	.status_reg_0 = 0x90,
+    /** status register1 */
+	.status_reg_1 = 0x91,
+     /** sdio interrupt mask */
+	.sdio_int_mask = 0xff,
+    /** data port mask */
+	.data_port_mask = 0xffffffff,
+    /** maximum mp register */
+	.max_mp_regs = 196,
+    /** read bitmap lower byte */
+	.rd_bitmap_l = 0x10,
+    /** read bitmap upper byte */
+	.rd_bitmap_u = 0x11,
+    /** read bitmap1 lower byte */
+	.rd_bitmap_1l = 0x12,
+    /** read bitmap1 upper byte */
+	.rd_bitmap_1u = 0x13,
+    /** write bitmap lower byte */
+	.wr_bitmap_l = 0x14,
+    /** write bitmap upper byte */
+	.wr_bitmap_u = 0x15,
+    /** write bitmap1 lower byte */
+	.wr_bitmap_1l = 0x16,
+    /** write bitmap1 upper byte */
+	.wr_bitmap_1u = 0x17,
+    /** read port0 length lower byte */
+	.rd_len_p0_l = 0x18,
+    /** read port0 length upper byte */
+	.rd_len_p0_u = 0x19,
+    /** card misc configuration register */
+	.card_misc_cfg_reg = 0xD8,
+     /** scratch reg used for reset and check SOC wakeup*/
+	.reset_reg = 0xB6,
+    /** reset value */
+	.reset_val = 1,
+};
+
+/** Register sdio 8897 card structure */
+static const struct _mlan_sdio_card_reg mlan_reg_sd8897 = {
+     /** start read port */
+	.start_rd_port = 0,
+    /** start write port */
+	.start_wr_port = 0,
+    /** base register0 */
+	.base_0_reg = 0x60,
+    /** base register1 */
+	.base_1_reg = 0x61,
+    /** poll register */
+	.poll_reg = 0x50,
+    /** host interrupt enable */
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+		CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+     /** host interrupt status*/
+	.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 register0 */
+	.status_reg_0 = 0xC0,
+     /** status register1 */
+	.status_reg_1 = 0xC1,
+     /** sdio interrupt mask */
+	.sdio_int_mask = 0xff,
+    /** data port mask */
+	.data_port_mask = 0xffffffff,
+    /** maximum mp register */
+	.max_mp_regs = 184,
+    /** read bitmap lower byte */
+	.rd_bitmap_l = 0x04,
+    /** read bitmap upper byte */
+	.rd_bitmap_u = 0x05,
+    /** read bitmap1 lower byte */
+	.rd_bitmap_1l = 0x06,
+    /** read bitmap1 upper byte */
+	.rd_bitmap_1u = 0x07,
+    /** write bitmap lower byte */
+	.wr_bitmap_l = 0x08,
+    /** write bitmap upper byte */
+	.wr_bitmap_u = 0x09,
+    /** write bitmap1 lower byte */
+	.wr_bitmap_1l = 0x0A,
+    /** write bitmapi1 upper byte */
+	.wr_bitmap_1u = 0x0B,
+    /** read port0 length lower byte */
+	.rd_len_p0_l = 0x0C,
+    /** read port0 length upper byte */
+	.rd_len_p0_u = 0x0D,
+    /** card misc configuration register */
+	.card_misc_cfg_reg = 0xCC,
+     /** scratch reg used for reset and check SOC wakeup*/
+	.reset_reg = 0xE8,
+    /** reset value */
+	.reset_val = 1,
+};
+
+/** Register sdio 8997 card structure */
+static const struct _mlan_sdio_card_reg mlan_reg_sd8977_sd8978_sd8997 = {
+     /** start read port */
+	.start_rd_port = 0,
+    /** start write port */
+	.start_wr_port = 0,
+    /** base register0 */
+	.base_0_reg = 0xf8,
+    /** base register1 */
+	.base_1_reg = 0xf9,
+    /** poll register */
+	.poll_reg = 0x5C,
+    /** host interrupt enable */
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+		CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+     /** host interrupt status*/
+	.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 register0 */
+	.status_reg_0 = 0xe8,
+    /** status register1 */
+	.status_reg_1 = 0xe9,
+     /** sdio interrupt mask */
+	.sdio_int_mask = 0xff,
+     /** data port mask */
+	.data_port_mask = 0xffffffff,
+     /** maximum mp register */
+	.max_mp_regs = 196,
+    /** read bitmap lower byte */
+	.rd_bitmap_l = 0x10,
+    /** read bitmap upper byte */
+	.rd_bitmap_u = 0x11,
+    /** read bitmap1 lower byte */
+	.rd_bitmap_1l = 0x12,
+    /** read bitmap1 upper byte */
+	.rd_bitmap_1u = 0x13,
+    /** write bitmap lower byte */
+	.wr_bitmap_l = 0x14,
+    /** write bitmap upper byte */
+	.wr_bitmap_u = 0x15,
+    /** write bitmap1 lower byte */
+	.wr_bitmap_1l = 0x16,
+    /** write bitmap1 upper byte */
+	.wr_bitmap_1u = 0x17,
+    /** read port0 length lower byte */
+	.rd_len_p0_l = 0x18,
+    /** read port0 length upper byte */
+	.rd_len_p0_u = 0x19,
+    /** card misc configuration register */
+	.card_misc_cfg_reg = 0xd8,
+     /** scratch reg used for reset and check SOC wakeup*/
+	.reset_reg = 0xEE,
+    /** reset value */
+	.reset_val = 0x99,
+};
+
+/** ampdu info for general card */
+static struct _ampdu_info ampdu_info_nov15 = {
+     /** AMPDU station tx window size */
+	.ampdu_sta_txwinsize = MLAN_STA_AMPDU_DEF_TXWINSIZE_NOV15,
+#ifdef UAP_SUPPORT
+    /** AMPDU uAP tx window size */
+	.ampdu_uap_txwinsize = MLAN_UAP_AMPDU_DEF_TXWINSIZE_NOV15,
+    /** AMPDU uAP rx window size */
+	.ampdu_uap_rxwinsize = MLAN_UAP_AMPDU_DEF_RXWINSIZE_NOV15,
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+    /** AMPDU wifi direct txrx window size */
+	.ampdu_wfd_txrxwinsize = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE_NOV15,
+#endif
+};
+
+/** ampdu info for sd8887 and sd8897 */
+static struct _ampdu_info ampdu_info_v15 = {
+     /** AMPDU station tx window size */
+	.ampdu_sta_txwinsize = MLAN_STA_AMPDU_DEF_TXWINSIZE,
+#ifdef UAP_SUPPORT
+     /** AMPDU uAP tx window size */
+	.ampdu_uap_txwinsize = MLAN_UAP_AMPDU_DEF_TXWINSIZE,
+     /** AMPDU uAP rx window size */
+	.ampdu_uap_rxwinsize = MLAN_UAP_AMPDU_DEF_RXWINSIZE,
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+     /** AMPDU wifi direct txrx window size */
+	.ampdu_wfd_txrxwinsize = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE,
+#endif
+};
+
+/** 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)
+
+/** Sdio 8777 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8777 = {
+     /** register */
+	.reg = &mlan_reg_sd87xx,
+    /** maximum ports */
+	.max_ports = 16,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_8,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MFALSE,
+    /** control mask */
+	.has_control_mask = MTRUE,
+     /** io port0 register */
+	.io_port_0_reg = 0x78,
+     /** io port1 register */
+	.io_port_1_reg = 0x79,
+     /** io port2 register */
+	.io_port_2_reg = 0x7A,
+     /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+     /** card_rx_len_reg */
+	.card_rx_len_reg = 0x62,
+     /** card rx unit register */
+	.card_rx_unit_reg = 0x63,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+     /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 0,
+    /** V15 firmware api */
+	.v15_fw_api = 0,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 0,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_nov15,
+};
+
+/** Sdio 8787 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8787 = {
+    /** register */
+	.reg = &mlan_reg_sd87xx,
+    /** maximum ports */
+	.max_ports = 16,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_8,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MFALSE,
+    /** control mask */
+	.has_control_mask = MTRUE,
+     /** io port0 register */
+	.io_port_0_reg = 0x78,
+    /** io port1 register */
+	.io_port_1_reg = 0x79,
+    /** io port2 register */
+	.io_port_2_reg = 0x7A,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+    /** card_rx_len_reg */
+	.card_rx_len_reg = 0x62,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0x63,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 0,
+    /** V15 firmware api */
+	.v15_fw_api = 0,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 0,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_nov15,
+};
+
+/** Sdio 8797 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8797 = {
+     /** register */
+	.reg = &mlan_reg_sd87xx,
+    /** maximum ports */
+	.max_ports = 16,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_8,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MFALSE,
+    /** control mask */
+	.has_control_mask = MTRUE,
+    /** io port0 register */
+	.io_port_0_reg = 0x78,
+    /** io port1 register */
+	.io_port_1_reg = 0x79,
+    /** io port2 register */
+	.io_port_2_reg = 0x7A,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+    /** card_rx_len_reg */
+	.card_rx_len_reg = 0x62,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0x63,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 0,
+    /** V15 firmware api */
+	.v15_fw_api = 0,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 0,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_nov15,
+};
+
+/** Sdio 8887 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8887 = {
+    /** register */
+	.reg = &mlan_reg_sd8887,
+    /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xD9,
+     /** command configuration register0 */
+	.cmd_config_0 = 0xC4,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xC5,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xC0,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xC1,
+    /** io port0 register */
+	.io_port_0_reg = 0xE4,
+    /** io port1 register */
+	.io_port_1_reg = 0xE5,
+    /** io port2 register */
+	.io_port_2_reg = 0xE6,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x04,
+    /** card rx length register */
+	.card_rx_len_reg = 0x92,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0x93,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x08,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x0C,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Sdio 8801 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8801 = {
+     /** register */
+	.reg = &mlan_reg_sd87xx,
+    /** maximum ports */
+	.max_ports = 16,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_8,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MFALSE,
+    /** control mask */
+	.has_control_mask = MTRUE,
+    /** io port0 register */
+	.io_port_0_reg = 0x78,
+    /** io port1 register */
+	.io_port_1_reg = 0x79,
+    /** io port0 register */
+	.io_port_2_reg = 0x7A,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+    /** card rx length register */
+	.card_rx_len_reg = 0x62,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0x63,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_32K,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 0,
+    /** V15 firmware api */
+	.v15_fw_api = 0,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 0,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_nov15,
+};
+
+/** Sdio 8897 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8897 = {
+     /** register */
+	.reg = &mlan_reg_sd8897,
+     /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xCD,
+    /** command configuration register0 */
+	.cmd_config_0 = 0xB8,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xB9,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xB4,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xB5,
+    /** io port0 register */
+	.io_port_0_reg = 0xD8,
+    /** io port1 register */
+	.io_port_1_reg = 0xD9,
+    /** io port2 register */
+	.io_port_2_reg = 0xDA,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x01,
+    /** card rx length register */
+	.card_rx_len_reg = 0xC2,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0xC3,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x02,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x03,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 0,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Sdio 8977 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8977 = {
+     /** register */
+	.reg = &mlan_reg_sd8977_sd8978_sd8997,
+     /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xD9,
+    /** command configuration register0 */
+	.cmd_config_0 = 0xC4,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xC5,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xC0,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xC1,
+    /** io port0 register */
+	.io_port_0_reg = 0xE4,
+    /** io port1 register */
+	.io_port_1_reg = 0xE5,
+    /** io port2 register */
+	.io_port_2_reg = 0xE6,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x04,
+    /** card rx length register */
+	.card_rx_len_reg = 0xEA,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0xEB,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x08,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x0C,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 1,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Sdio 8978 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8978 = {
+     /** register */
+	.reg = &mlan_reg_sd8977_sd8978_sd8997,
+     /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xD9,
+    /** command configuration register0 */
+	.cmd_config_0 = 0xC4,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xC5,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xC0,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xC1,
+    /** io port0 register */
+	.io_port_0_reg = 0xE4,
+    /** io port1 register */
+	.io_port_1_reg = 0xE5,
+    /** io port2 register */
+	.io_port_2_reg = 0xE6,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x04,
+    /** card rx length register */
+	.card_rx_len_reg = 0xEA,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0xEB,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x08,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x0C,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 1,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Sdio 8997 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8997 = {
+    /** register */
+	.reg = &mlan_reg_sd8977_sd8978_sd8997,
+    /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xD9,
+    /** command configuration register0 */
+	.cmd_config_0 = 0xC4,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xC5,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xC0,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xC1,
+    /** io port0 register */
+	.io_port_0_reg = 0xE4,
+    /** io port1 register */
+	.io_port_1_reg = 0xE5,
+    /** io port2 register */
+	.io_port_2_reg = 0xE6,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x04,
+    /** card rx length register */
+	.card_rx_len_reg = 0xEA,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0xEB,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x08,
+    /** host interrupt status register */
+	.host_int_status_reg = 0x0C,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 1,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Sdio 8987 device structure */
+static const struct _mlan_sdio_device mlan_sdio_sd8987 = {
+    /** register */
+	.reg = &mlan_reg_sd8977_sd8978_sd8997,
+    /** maximum ports */
+	.max_ports = 32,
+    /** mp aggregation packet limit */
+	.mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT_16,
+    /** sdio new mode support */
+	.supports_sdio_new_mode = MTRUE,
+    /** control mask */
+	.has_control_mask = MFALSE,
+    /** card configuration_2_1 register */
+	.card_config_2_1_reg = 0xD9,
+    /** command configuration register0 */
+	.cmd_config_0 = 0xC4,
+    /** command configuration register1 */
+	.cmd_config_1 = 0xC5,
+    /** command read length 0 */
+	.cmd_rd_len_0 = 0xC0,
+    /** command read length 1 */
+	.cmd_rd_len_1 = 0xC1,
+    /** io port0 register */
+	.io_port_0_reg = 0xE4,
+    /** io port1 register */
+	.io_port_1_reg = 0xE5,
+    /** io port2 register */
+	.io_port_2_reg = 0xE6,
+    /** host interrupt rsr register */
+	.host_int_rsr_reg = 0x04,
+    /** card rx length register */
+	.card_rx_len_reg = 0xEA,
+    /** card rx unit register */
+	.card_rx_unit_reg = 0xEB,
+    /** host interrupt mask register */
+	.host_int_mask_reg = 0x08,
+    /** host interrupt mask register */
+	.host_int_status_reg = 0x0C,
+    /** mp tx aggregation buffer size */
+	.mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** mp rx aggregation buffer size */
+	.mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX,
+    /** maximum tx buffer size */
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+    /** V15 update */
+	.v15_update = 1,
+    /** V15 firmware api */
+	.v15_fw_api = 1,
+    /** V16 firmware api */
+	.v16_fw_api = 1,
+    /** extend scan */
+	.ext_scan = 1,
+    /** firmware relaod */
+	.fw_reload = 1,
+    /** AMPDU information */
+	.ampdu_info = &ampdu_info_v15,
+};
+
+/** Enable host interrupt */
+mlan_status wlan_enable_host_int(pmlan_adapter pmadapter);
+/** Probe and initialization function */
+mlan_status wlan_sdio_probe(pmlan_adapter pmadapter);
+mlan_status wlan_get_sdio_device(pmlan_adapter pmadapter);
+/** multi interface download check */
+mlan_status wlan_check_winner_status(mlan_adapter *pmadapter, t_u32 *val);
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+mlan_status wlan_send_mp_aggr_buf(mlan_adapter *pmadapter);
+#endif
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+mlan_status wlan_re_alloc_sdio_rx_mpa_buffer(IN mlan_adapter *pmadapter);
+#endif
+
+void wlan_decode_spa_buffer(mlan_adapter *pmadapter, t_u8 *buf, t_u32 len);
+t_void wlan_sdio_deaggr_rx_pkt(IN pmlan_adapter pmadapter, mlan_buffer *pmbuf);
+/** Firmware status check */
+mlan_status wlan_check_fw_status(mlan_adapter *pmadapter, t_u32 pollnum);
+/** Read interrupt status */
+mlan_status wlan_interrupt(pmlan_adapter pmadapter);
+/** Process Interrupt Status */
+mlan_status wlan_process_int_status(mlan_adapter *pmadapter);
+/** 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(IN pmlan_private priv);
+mlan_status wlan_cmd_sdio_gpio_int(pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *cmd,
+				   IN t_u16 cmd_action, IN 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 100644
index 0000000..7ef85d6
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_shim.c
@@ -0,0 +1,1474 @@
+/** @file mlan_shim.c
+ *
+ *  @brief This file contains APIs to MOAL module.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+#include "mlan_11h.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+#ifdef STA_SUPPORT
+mlan_operations mlan_sta_ops = {
+	/* init cmd handler */
+	wlan_ops_sta_init_cmd,
+	/* ioctl handler */
+	wlan_ops_sta_ioctl,
+	/* cmd handler */
+	wlan_ops_sta_prepare_cmd,
+	/* cmdresp handler */
+	wlan_ops_sta_process_cmdresp,
+	/* rx handler */
+	wlan_ops_sta_process_rx_packet,
+	/* Event handler */
+	wlan_ops_sta_process_event,
+	/* txpd handler */
+	wlan_ops_sta_process_txpd,
+	/* BSS role: STA */
+	MLAN_BSS_ROLE_STA,
+};
+#endif
+#ifdef UAP_SUPPORT
+mlan_operations mlan_uap_ops = {
+	/* init cmd handler */
+	wlan_ops_uap_init_cmd,
+	/* ioctl handler */
+	wlan_ops_uap_ioctl,
+	/* cmd handler */
+	wlan_ops_uap_prepare_cmd,
+	/* cmdresp handler */
+	wlan_ops_uap_process_cmdresp,
+	/* rx handler */
+	wlan_ops_uap_process_rx_packet,
+	/* Event handler */
+	wlan_ops_uap_process_event,
+	/* txpd handler */
+	wlan_ops_uap_process_txpd,
+	/* BSS role: uAP */
+	MLAN_BSS_ROLE_UAP,
+};
+#endif
+
+/** mlan function table */
+mlan_operations *mlan_ops[] = {
+#ifdef STA_SUPPORT
+	&mlan_sta_ops,
+#endif
+#ifdef UAP_SUPPORT
+	&mlan_uap_ops,
+#endif
+	MNULL,
+};
+
+/** Global moal_assert callback */
+t_void (*assert_callback) (IN t_void *pmoal_handle, IN 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) (IN t_void *pmoal_handle,
+			  IN t_u32 level, IN char *pformat, IN ...
+	) = MNULL;
+
+/** Global moal_get_system_time callback */
+mlan_status (*get_sys_time_callback) (IN t_void *pmoal_handle,
+				      OUT t_u32 *psec,
+				      OUT t_u32 *pusec) = MNULL;
+
+/** Global driver debug mit masks */
+t_u32 mlan_drvdbg = DEFAULT_DEBUG_MASK;
+#endif
+
+/********************************************************
+			Local Functions
+*******************************************************/
+/**
+ *  @brief This function process pending ioctl
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ */
+void
+wlan_process_pending_ioctl(mlan_adapter *pmadapter)
+{
+	pmlan_ioctl_req pioctl_buf;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	mlan_ds_bss *bss = MNULL;
+#endif
+#ifdef STA_SUPPORT
+	mlan_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();
+}
+
+void
+mlan_dump_adapter(IN t_void *padapter)
+{
+	t_u8 bssidx = 0;
+	pmlan_adapter pmadapter = MNULL;
+	pmlan_private ppriv = MNULL;
+
+	if (padapter == MNULL)
+		return;
+	pmadapter = (pmlan_adapter)padapter;
+	for (bssidx = 0; bssidx < pmadapter->priv_num; bssidx++) {
+		if (pmadapter->priv[bssidx] == MNULL)
+			continue;
+		ppriv = pmadapter->priv[bssidx];
+		PRINTM(MMSG, "dump bss %d info\n", bssidx);
+		// TBD dump rx reorder tbl
+	}
+}
+
+/********************************************************
+			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 (
+ *   IN pmlan_device     pmdevice,
+ *   OUT 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(IN pmlan_device pmdevice, OUT 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);
+
+	if (!pmdevice->callbacks.moal_malloc ||
+	    !pmdevice->callbacks.moal_mfree ||
+	    !pmdevice->callbacks.moal_memset ||
+	    !pmdevice->callbacks.moal_memmove) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Allocate memory for adapter structure */
+	if (pmdevice->callbacks.moal_vmalloc && pmdevice->callbacks.moal_vfree)
+		ret = pmdevice->callbacks.moal_vmalloc(pmdevice->pmoal_handle,
+						       sizeof(mlan_adapter),
+						       (t_u8 **)&pmadapter);
+	else
+		ret = pmdevice->callbacks.moal_malloc(pmdevice->pmoal_handle,
+						      sizeof(mlan_adapter),
+						      MLAN_MEM_DEF,
+						      (t_u8 **)&pmadapter);
+	if ((ret != MLAN_STATUS_SUCCESS) || !pmadapter) {
+		ret = MLAN_STATUS_FAILURE;
+		goto exit_register;
+	}
+
+	pmdevice->callbacks.moal_memset(pmdevice->pmoal_handle, pmadapter,
+					0, sizeof(mlan_adapter));
+
+	pcb = &pmadapter->callbacks;
+
+	/* Save callback functions */
+	pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
+					 &pmdevice->callbacks,
+					 sizeof(mlan_callbacks));
+
+	/* Assertion for all callback functions */
+	MASSERT(pcb->moal_get_hw_spec_complete);
+	MASSERT(pcb->moal_init_fw_complete);
+	MASSERT(pcb->moal_shutdown_fw_complete);
+	MASSERT(pcb->moal_send_packet_complete);
+	MASSERT(pcb->moal_recv_packet);
+	MASSERT(pcb->moal_recv_event);
+	MASSERT(pcb->moal_ioctl_complete);
+
+	MASSERT(pcb->moal_write_reg);
+	MASSERT(pcb->moal_read_reg);
+	MASSERT(pcb->moal_alloc_mlan_buffer);
+	MASSERT(pcb->moal_free_mlan_buffer);
+	MASSERT(pcb->moal_write_data_sync);
+	MASSERT(pcb->moal_read_data_sync);
+	MASSERT(pcb->moal_mfree);
+	MASSERT(pcb->moal_memcpy);
+	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);
+	/* Save pmoal_handle */
+	pmadapter->pmoal_handle = pmdevice->pmoal_handle;
+
+	pmadapter->feature_control = pmdevice->feature_control;
+
+	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;
+	pmadapter->card_type = pmdevice->card_type;
+
+	ret = wlan_get_sdio_device(pmadapter);
+	if (MLAN_STATUS_SUCCESS != ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	/* card specific probing has been deferred until now .. */
+	ret = wlan_sdio_probe(pmadapter);
+	if (MLAN_STATUS_SUCCESS != ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+#ifdef DEBUG_LEVEL1
+	mlan_drvdbg = pmdevice->drvdbg;
+#endif
+
+#ifdef MFG_CMD_SUPPORT
+	pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	pmadapter->max_segs = pmdevice->max_segs;
+	pmadapter->max_seg_size = pmdevice->max_seg_size;
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
+#endif
+	pmadapter->sdio_rx_aggr_enable = pmdevice->sdio_rx_aggr_enable;
+	pmadapter->init_para.auto_ds = pmdevice->auto_ds;
+	pmadapter->init_para.ps_mode = pmdevice->ps_mode;
+	if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
+	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
+	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_12K ||
+	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
+		pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;
+#ifdef STA_SUPPORT
+	pmadapter->init_para.cfg_11d = pmdevice->cfg_11d;
+#else
+	pmadapter->init_para.cfg_11d = 0;
+#endif
+	if (IS_DFS_SUPPORT(pmadapter->feature_control))
+		pmadapter->init_para.dfs_master_radar_det_en =
+			DFS_MASTER_RADAR_DETECT_EN;
+	pmadapter->init_para.dfs_slave_radar_det_en = DFS_SLAVE_RADAR_DETECT_EN;
+	if (IS_SD8777(pmadapter->card_type) || IS_SD8787(pmadapter->card_type))
+		pmadapter->init_para.fw_crc_check = pmdevice->fw_crc_check;
+	pmadapter->init_para.dev_cap_mask = pmdevice->dev_cap_mask;
+	pmadapter->rx_work_flag = pmdevice->rx_work;
+
+	pmadapter->fixed_beacon_buffer = pmdevice->fixed_beacon_buffer;
+
+	pmadapter->multiple_dtim = pmdevice->multi_dtim;
+	pmadapter->inact_tmo = pmdevice->inact_tmo;
+	pmadapter->init_para.drcs_chantime_mode = pmdevice->drcs_chantime_mode;
+	pmadapter->init_para.fw_region = pmdevice->fw_region;
+	pmadapter->hs_wake_interval = pmdevice->hs_wake_interval;
+	if (pmdevice->indication_gpio != 0xff) {
+		pmadapter->ind_gpio = pmdevice->indication_gpio & 0x0f;
+		pmadapter->level = (pmdevice->indication_gpio & 0xf0) >> 4;
+		if (pmadapter->level != 0 && pmadapter->level != 1) {
+			PRINTM(MERROR,
+			       "Indication GPIO level is wrong and will use default value 0.\n");
+			pmadapter->level = 0;
+		}
+	}
+
+	pmadapter->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(pmadapter, &pmadapter->priv[0]->ops, mlan_ops[j],
+			       sizeof(mlan_operations));
+		}
+	}
+    /** back up bss_attr table */
+	memcpy(pmadapter, pmadapter->bss_attr, pmdevice->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 timers */
+	wlan_free_timer(pmadapter);
+	/* Free adapter structure */
+	wlan_free_adapter(pmadapter);
+	/* Free lock variables */
+	wlan_free_lock_list(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
+				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
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+
+exit_register:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function unregisters MOAL from MLAN module.
+ *
+ *  @param pmlan_adapter   A pointer to a mlan_device structure
+ *                         allocated in MOAL
+ *
+ *  @return                MLAN_STATUS_SUCCESS
+ *                             The deregistration succeeded.
+ */
+mlan_status
+mlan_unregister(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_callbacks pcb;
+	t_s32 i = 0;
+
+	MASSERT(pmlan_adapter);
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+	/* Free adapter structure */
+	wlan_free_adapter(pmadapter);
+
+	/* Free timers */
+	wlan_free_timer(pmadapter);
+
+	/* Free lock variables */
+	wlan_free_lock_list(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
+				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
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads the firmware
+ *
+ *  @param pmlan_adapter   A pointer to a t_void pointer to store
+ *                         mlan_adapter structure pointer
+ *  @param pmfw            A pointer to firmware image
+ *
+ *  @return                MLAN_STATUS_SUCCESS
+ *                             The firmware download succeeded.
+ *                         MLAN_STATUS_FAILURE
+ *                             The firmware download failed.
+ */
+mlan_status
+mlan_dnld_fw(IN t_void *pmlan_adapter, IN pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	t_u32 poll_num = 1;
+	t_u32 winner = 0;
+
+	ENTER();
+	MASSERT(pmlan_adapter);
+
+/*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_check_fw_status(pmadapter, poll_num);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		if (pmfw->fw_reload && pmadapter->psdio_device->fw_reload) {
+			ret = wlan_reset_fw(pmadapter);
+			if (ret == MLAN_STATUS_FAILURE) {
+				PRINTM(MERROR, "FW reset failure!");
+				LEAVE();
+				return ret;
+			}
+		} else {
+			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_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;
+	}
+
+	if (pmfw) {
+		/* Download helper/firmware */
+		ret = wlan_dnld_fw(pmadapter, pmfw);
+		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_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_host_int(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function pass init param to MLAN
+ *
+ *  @param pmlan_adapter  A pointer to a t_void pointer to store
+ *                        mlan_adapter structure pointer
+ *  @param pparam         A pointer to mlan_init_param structure
+ *
+ *  @return               MLAN_STATUS_SUCCESS
+ *
+ */
+mlan_status
+mlan_set_init_param(IN t_void *pmlan_adapter, IN pmlan_init_param pparam)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+	ENTER();
+	MASSERT(pmlan_adapter);
+
+    /** Save DPD data in MLAN */
+	if (pparam->pdpd_data_buf || pparam->dpd_data_len) {
+		pmadapter->pdpd_data = pparam->pdpd_data_buf;
+		pmadapter->dpd_data_len = pparam->dpd_data_len;
+	}
+	if (pparam->ptxpwr_data_buf && (pparam->txpwr_data_len > 0)) {
+		pmadapter->ptxpwr_data = pparam->ptxpwr_data_buf;
+		pmadapter->txpwr_data_len = pparam->txpwr_data_len;
+	}
+    /** Save cal data in MLAN */
+	if ((pparam->pcal_data_buf) && (pparam->cal_data_len > 0)) {
+		pmadapter->pcal_data = pparam->pcal_data_buf;
+		pmadapter->cal_data_len = pparam->cal_data_len;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes the firmware
+ *
+ *  @param pmlan_adapter   A pointer to a t_void pointer to store
+ *                         mlan_adapter structure pointer
+ *
+ *  @return                MLAN_STATUS_SUCCESS
+ *                             The firmware initialization succeeded.
+ *                         MLAN_STATUS_PENDING
+ *                             The firmware initialization is pending.
+ *                         MLAN_STATUS_FAILURE
+ *                             The firmware initialization failed.
+ */
+mlan_status
+mlan_init_fw(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+	ENTER();
+	MASSERT(pmlan_adapter);
+
+	pmadapter->hw_status = WlanHardwareStatusGetHwSpec;
+
+	/* Initialize firmware, may return PENDING */
+	ret = wlan_init_fw(pmadapter);
+	PRINTM(MINFO, "wlan_init_fw returned ret=0x%x\n", ret);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Shutdown firmware
+ *
+ *  @param pmlan_adapter    A pointer to mlan_adapter structure
+ *
+ *  @return     MLAN_STATUS_SUCCESS
+ *                              The firmware shutdown call succeeded.
+ *              MLAN_STATUS_PENDING
+ *                              The firmware shutdown call is pending.
+ *              MLAN_STATUS_FAILURE
+ *                              The firmware shutdown call failed.
+ */
+mlan_status
+mlan_shutdown_fw(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_PENDING;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_buffer pmbuf;
+	pmlan_ioctl_req pioctl_buf;
+	pmlan_callbacks pcb;
+	t_s32 i = 0;
+
+	ENTER();
+
+	MASSERT(pmlan_adapter);
+	/* MLAN already shutdown */
+	if (pmadapter->hw_status == WlanHardwareStatusNotReady) {
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	pmadapter->hw_status = WlanHardwareStatusClosing;
+	/* Wait for mlan_process to complete */
+	if (pmadapter->mlan_processing) {
+		PRINTM(MWARN, "MLAN main processing is still running\n");
+		LEAVE();
+		return ret;
+	}
+
+	/* Shut down MLAN */
+	PRINTM(MINFO, "Shutdown MLAN...\n");
+
+	/* Cancel all pending commands and complete ioctls */
+	wlan_cancel_all_pending_cmd(pmadapter);
+
+	/* 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))) {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+	pmadapter->rx_pkts_queued = 0;
+
+	/* Notify completion */
+	ret = wlan_shutdown_fw_complete(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief queue main work
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return			N/A
+ */
+static t_void
+mlan_queue_main_work(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmain_proc_lock);
+
+	/* Check if already processing */
+	if (pmadapter->mlan_processing) {
+		pmadapter->more_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+	} else {
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+		wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+				MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief queue rx_work
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return			N/A
+ */
+static t_void
+mlan_queue_rx_work(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+
+	/* Check if already processing */
+	if (pmadapter->mlan_rx_processing) {
+		pmadapter->more_rx_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+	} else {
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+		wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+				MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief block main process
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param block            MTRUE/MFALSE
+ *
+ *  @return			N/A
+ */
+void
+mlan_block_main_process(mlan_adapter *pmadapter, t_u8 block)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmain_proc_lock);
+	if (!block) {
+		pmadapter->main_lock_flag = MFALSE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+	} else {
+		pmadapter->main_lock_flag = MTRUE;
+		if (pmadapter->mlan_processing) {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->pmain_proc_lock);
+			PRINTM(MEVENT, "wlan: wait main work done...\n");
+			wlan_recv_event(wlan_get_priv
+					(pmadapter, MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK,
+					MNULL);
+		} else {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->pmain_proc_lock);
+		}
+	}
+}
+
+/**
+ *  @brief block rx process
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param block            MTRUE/MFALSE;
+ *
+ *  @return			N/A
+ */
+void
+mlan_block_rx_process(mlan_adapter *pmadapter, t_u8 block)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+	if (!block) {
+		pmadapter->rx_lock_flag = MFALSE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+	} else {
+		pmadapter->rx_lock_flag = MTRUE;
+		if (pmadapter->mlan_rx_processing) {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->prx_proc_lock);
+			PRINTM(MEVENT, "wlan: wait rx work done...\n");
+			wlan_recv_event(wlan_get_priv
+					(pmadapter, MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
+		} else {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->prx_proc_lock);
+		}
+	}
+}
+
+/**
+ *  @brief The receive process
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param rx_pkts		    A pointer to save receive pkts number
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_callbacks pcb;
+	pmlan_buffer pmbuf;
+	t_u8 limit = 0;
+	t_u8 rx_num = 0;
+
+	ENTER();
+
+	MASSERT(pmlan_adapter);
+	pcb = &pmadapter->callbacks;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+	if (pmadapter->mlan_rx_processing || pmadapter->rx_lock_flag) {
+		pmadapter->more_rx_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+		goto exit_rx_proc;
+	} else {
+		pmadapter->mlan_rx_processing = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+	}
+
+	if (rx_pkts)
+		limit = *rx_pkts;
+
+rx_process_start:
+	/* Check for Rx data */
+	while (MTRUE) {
+
+		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);
+		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);
+		}
+		wlan_sdio_deaggr_rx_pkt(pmadapter, pmbuf);
+		if (limit && rx_num >= limit)
+			break;
+	}
+	if (rx_pkts)
+		*rx_pkts = rx_num;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+	if (pmadapter->more_rx_task_flag) {
+		pmadapter->more_rx_task_flag = MFALSE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+		goto rx_process_start;
+	}
+	pmadapter->mlan_rx_processing = MFALSE;
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+			      pmadapter->prx_proc_lock);
+exit_rx_proc:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief The main process
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+mlan_main_process(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	MASSERT(pmlan_adapter);
+
+	pcb = &pmadapter->callbacks;
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmain_proc_lock);
+
+	/* Check if already processing */
+	if (pmadapter->mlan_processing || pmadapter->main_lock_flag) {
+		pmadapter->more_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+		goto exit_main_proc;
+	} else {
+		pmadapter->mlan_processing = MTRUE;
+		pmadapter->main_process_cnt++;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+	}
+process_start:
+	do {
+		/* Is MLAN shutting down or not ready? */
+		if ((pmadapter->hw_status == WlanHardwareStatusClosing) ||
+		    (pmadapter->hw_status == WlanHardwareStatusNotReady))
+			break;
+		if (pmadapter->pending_ioctl) {
+			wlan_process_pending_ioctl(pmadapter);
+			pmadapter->pending_ioctl = MFALSE;
+		}
+		if(pmadapter->pending_disconnect_priv){
+			PRINTM(MEVENT,"HostMlme Reset connect state\n");
+			wlan_reset_connect_state(pmadapter->pending_disconnect_priv, MTRUE);
+			pmadapter->pending_disconnect_priv = MNULL;
+		}
+		if (pmadapter->rx_pkts_queued > HIGH_RX_PENDING) {
+			PRINTM(MEVENT, "Pause\n");
+			pmadapter->delay_task_flag = MTRUE;
+			mlan_queue_rx_work(pmadapter);
+			break;
+		}
+		/* Handle pending SDIO interrupts if any */
+		if (pmadapter->sdio_ireg) {
+			if (pmadapter->hs_activated == MTRUE)
+				wlan_process_hs_config(pmadapter);
+			wlan_process_int_status(pmadapter);
+			if (pmadapter->data_received && pmadapter->rx_work_flag)
+				mlan_queue_rx_work(pmadapter);
+		}
+
+		/* 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)
+		    )) {
+			wlan_pm_wakeup_card(pmadapter, MTRUE);
+			pmadapter->pm_wakeup_fw_try = MTRUE;
+			continue;
+		}
+		if (IS_CARD_RX_RCVD(pmadapter)) {
+			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)
+					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)
+				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;
+		}
+
+		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 pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param pmbuf		A pointer to mlan_buffer structure
+ *
+ *  @return			MLAN_STATUS_PENDING
+ */
+mlan_status
+mlan_send_packet(IN t_void *pmlan_adapter, IN pmlan_buffer pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_PENDING;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	mlan_private *pmpriv;
+	t_u16 eth_type = 0;
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	tdlsStatus_e tdls_status;
+
+	ENTER();
+	MASSERT(pmlan_adapter &&pmbuf);
+
+	if (!pmlan_adapter ||!pmbuf) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	MASSERT(pmbuf->bss_index < pmadapter->priv_num);
+	pmbuf->flags |= MLAN_BUF_FLAG_MOAL_TX_BUF;
+	pmpriv = pmadapter->priv[pmbuf->bss_index];
+
+	eth_type =
+		mlan_ntohs(*(t_u16 *)&pmbuf->
+			   pbuf[pmbuf->data_offset +
+				MLAN_ETHER_PKT_TYPE_OFFSET]);
+	if (((pmadapter->priv[pmbuf->bss_index]->port_ctrl_mode == MTRUE) &&
+	     ((eth_type == MLAN_ETHER_PKT_TYPE_EAPOL)
+	      || (eth_type == MLAN_ETHER_PKT_TYPE_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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+			       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;
+		}
+		PRINTM(MINFO, "mlan_send_pkt(): enq(bybass_txq)\n");
+		wlan_add_buf_bypass_txqueue(pmadapter, pmbuf);
+	} 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(IN t_void *adapter, IN 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);
+		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;
+}
+
+/**
+ *  @brief Packet receive completion callback handler
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param pmbuf		A pointer to mlan_buffer structure
+ *  @param status		Callback status
+ *
+ *  @return			MLAN_STATUS_SUCCESS
+ */
+mlan_status
+mlan_recv_packet_complete(IN t_void *pmlan_adapter,
+			  IN pmlan_buffer pmbuf, IN mlan_status status)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+	ENTER();
+	wlan_recv_packet_complete(pmadapter, pmbuf, status);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief select wmm queue
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param bss_num		BSS number
+ *  @param tid			TID
+ *
+ *  @return			wmm queue priority (0 - 3)
+ */
+t_u8
+mlan_select_wmm_queue(IN t_void *pmlan_adapter, IN t_u8 bss_num, IN t_u8 tid)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_private pmpriv = pmadapter->priv[bss_num];
+	t_u8 ret;
+	ENTER();
+	ret = wlan_wmm_select_queue(pmpriv, tid);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets interrupt status.
+ *
+ */
+/**
+ *  @param adapter  A pointer to mlan_adapter structure
+ *  @return         N/A
+ */
+mlan_status
+mlan_interrupt(IN t_void *adapter)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+	mlan_status ret;
+
+	ENTER();
+	ret = wlan_interrupt(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function wakeup firmware.
+ *
+ *  @param adapter  A pointer to mlan_adapter structure
+ *  @return         N/A
+ */
+t_void
+mlan_pm_wakeup_card(IN t_void *adapter)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+	ENTER();
+	wlan_pm_wakeup_card(pmadapter, MFALSE);
+	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(IN 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;
+}
diff --git a/wlan_sd8987/mlan/mlan_sta_cmd.c b/wlan_sd8987/mlan/mlan_sta_cmd.c
new file mode 100644
index 0000000..8abc2c9
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_cmd.c
@@ -0,0 +1,3022 @@
+/** @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 (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+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_11h.h"
+#include "mlan_sdio.h"
+#include "mlan_meas.h"
+
+/********************************************************
+			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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *pcmd, IN 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_ext
+ *
+ *  @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
+ */
+static mlan_status
+wlan_cmd_802_11_rssi_info_ext(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *pcmd,
+			      IN t_u16 cmd_action, IN 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 +
+			sizeof(HostCmd_DS_802_11_RSSI_INFO_EXT);
+		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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action,
+			 IN t_u32 cmd_oid, IN 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(pmpriv->adapter, psnmp_mib->value, &ul_temp,
+			       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(IN pmlan_private pmpriv, IN 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 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd,
+			    IN t_u16 cmd_action, IN 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(IN 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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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;
+
+	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(pmpriv->adapter,
+		       ((t_u8 *)phs_cfg) + sizeof(HostCmd_DS_802_11_HS_CFG_ENH),
+		       pmadapter->arp_filter, 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(pmadapter, (t_u8 *)mgmt_filter_tlv->filter,
+			       (t_u8 *)mgmt_filter,
+			       i * sizeof(mgmt_frame_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);
+		}
+		cmd->size = wlan_cpu_to_le16(cmd->size);
+		PRINTM(MCMND,
+		       "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x holdoff=%d wake_interval=%d inactivity_timeout=%d\n",
+		       phs_cfg->params.hs_config.conditions,
+		       phs_cfg->params.hs_config.gpio,
+		       phs_cfg->params.hs_config.gap,
+		       pmadapter->min_wake_holdoff, pmadapter->hs_wake_interval,
+		       pmadapter->hs_inactivity_timeout);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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
+ */
+static mlan_status
+wlan_cmd_802_11_mac_address(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, cmd->params.mac_addr.mac_addr,
+		       pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
+		/* HEXDUMP("SET_CMD: MAC ADDRESS-", priv->CurrentAddr, 6); */
+	}
+	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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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(pmpriv->adapter, pmc_addr->mac_list, pmcast_list->mac_list,
+	       pmcast_list->num_multicast_addr * MLAN_MAC_ADDR_LENGTH);
+
+	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(IN pmlan_private pmpriv,
+			       IN t_u16 cmd_no,
+			       IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, pdeauth, (t_u8 *)pdata_buf, 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(IN pmlan_private pmpriv, IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action,
+			     IN t_u32 cmd_oid, IN 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		       pkey->mac_addr, 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		       pkey->mac_addr, 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+	       pkey->mac_addr, 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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wep.key,
+		       pkey->key_material, pkey->key_len);
+		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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.pn,
+		       pkey->pn, PN_SIZE);
+		pkey_material->key_param_set.key_params.wapi.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.key,
+		       pkey->key_material, pkey->key_len);
+		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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.gcmp.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.gcmp.key,
+		       pkey->key_material, pkey->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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.ccmp256.
+			       pn, pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.ccmp256.key,
+		       pkey->key_material, pkey->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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.aes.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.aes.key,
+		       pkey->key_material, pkey->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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.cmac_aes.
+			       ipn, pkey->pn, SEQ_MAX_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+		pkey_material->key_param_set.key_params.cmac_aes.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.cmac_aes.key,
+		       pkey->key_material, pkey->key_len);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set CMAC AES Key\n");
+		goto done;
+	}
+	if (pkey->key_len == WPA_TKIP_KEY_LEN) {
+		if (pkey->
+		    key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.tkip.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.tkip.key,
+		       pkey->key_material, pkey->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 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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *cmd,
+		   IN t_u16 cmd_action, IN 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(pmpriv->adapter, eapol_pkt->tlv_eapol.pkt_buf,
+	       pmbuf->pbuf + pmbuf->data_offset, 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
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_802_11_supplicant_profile(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *cmd,
+				   IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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)
+		    || (pmpriv->adapter->adhoc_start_band & BAND_AN)
+			)
+			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(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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);
+
+	if (pmgmt_ie_list->ds_mgmt_ie.ie_data_list && cust_ie->ie_data_list) {
+		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(pmpriv->adapter,
+			       pmgmt_ie_list->ds_mgmt_ie.ie_data_list,
+			       cust_ie->ie_data_list, cust_ie->len);
+	}
+
+	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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN 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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_setup, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       (t_u8 *)&tdls_all_cfg->u.tdls_set.cap_info,
+		       sizeof(t_u16));
+		memcpy(pmpriv->adapter,
+		       (t_u8 *)ptdls_config_data->tdls_info.tdls_data +
+		       sizeof(t_u16), &tdls_all_cfg->u.tdls_set.tlv_buffer,
+		       travel_len);
+		travel_len += sizeof(t_u16);
+		break;
+	case WLAN_TDLS_DISCOVERY_REQ:
+		travel_len = MLAN_MAC_ADDR_LENGTH;
+		memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       tdls_all_cfg->u.tdls_discovery.peer_mac_addr,
+		       travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_setup, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_tear_down, travel_len);
+		break;
+	case WLAN_TDLS_STOP_CHAN_SWITCH:
+		travel_len = MLAN_MAC_ADDR_LENGTH;
+		memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
+		       travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_chan_switch, travel_len);
+		break;
+	case WLAN_TDLS_CS_PARAMS:
+		travel_len = sizeof(tdls_all_cfg->u.tdls_cs_params);
+		memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_cs_params, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_disable_cs, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_power_mode, travel_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(pmpriv->adapter,
+			       ptdls_config_data->tdls_info.tdls_data,
+			       tdls_all_cfg->u.tdls_link_status_req.
+			       peer_mac_addr, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_debug_data, travel_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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *cmd,
+		   IN t_u16 cmd_action, IN 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(pmpriv->adapter, ptdls_oper->peer_mac, tdls_oper->peer_mac,
+	       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(pmpriv->adapter,
+			       pos + travel_len + sizeof(MrvlIEtypesHeader_t),
+			       sta_ptr->support_rate, Rate_tlv->header.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(pmpriv->adapter, &ExCap->ext_cap,
+				       &sta_ptr->ExtCap.ext_cap,
+				       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(pmpriv->adapter, Rsn_ie->rsn_ie,
+				       sta_ptr->rsn_ie.data,
+				       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(pmpriv->adapter, &LinkID->bssid,
+				       &sta_ptr->link_ie.bssid,
+				       sta_ptr->link_ie.len);
+				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(pmpriv->adapter, &HTcap_tlv->ht_cap,
+				       &sta_ptr->HTcap.ht_cap,
+				       sta_ptr->HTcap.ieee_hdr.len);
+				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(pmpriv->adapter, &HTInfo_tlv->ht_info,
+				       &sta_ptr->HTInfo.ht_info,
+				       sta_ptr->HTInfo.ieee_hdr.len);
+				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(pmpriv->adapter, &BSSCo->bss_co_2040,
+				       &sta_ptr->BSSCO_20_40.bss_co_2040,
+				       sta_ptr->BSSCO_20_40.ieee_hdr.len);
+				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(pmpriv->adapter,
+					       &VHTcap_tlv->vht_cap,
+					       &sta_ptr->vht_cap.vht_cap,
+					       sta_ptr->vht_cap.ieee_hdr.len);
+					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);
+					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(pmpriv->adapter,
+				       &VHTOper_tlv->chan_width,
+				       &sta_ptr->vht_oprat.chan_width,
+				       sta_ptr->vht_oprat.ieee_hdr.len);
+				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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_otp_user_data *user_data =
+		(mlan_ds_misc_otp_user_data *)pdata_buf;
+	HostCmd_DS_OTP_USER_DATA *cmd_user_data =
+		(HostCmd_DS_OTP_USER_DATA *)&cmd->params.otp_user_data;
+	t_u16 cmd_size = 0;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_OTP_READ_USER_DATA);
+	cmd_size = sizeof(HostCmd_DS_OTP_USER_DATA) + S_DS_GEN - 1;
+
+	cmd_user_data->action = wlan_cpu_to_le16(cmd_action);
+	cmd_user_data->reserved = 0;
+	cmd_user_data->user_data_length =
+		wlan_cpu_to_le16(user_data->user_data_length);
+	cmd_size += user_data->user_data_length;
+	cmd->size = wlan_cpu_to_le16(cmd_size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares 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(IN HostCmd_DS_COMMAND *cmd,
+			    IN t_u16 cmd_action, IN 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 pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_low_pwr_mode(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_dfs_repeater *dfs_repeater = MNULL;
+	HostCmd_DS_DFS_REPEATER_MODE *cmd_dfs_repeater =
+		&cmd->params.dfs_repeater;
+
+	ENTER();
+
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_DFS_REPEATER_MODE);
+
+	dfs_repeater = (mlan_ds_misc_dfs_repeater *)pdata_buf;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+	cmd_dfs_repeater->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET)
+		cmd_dfs_repeater->mode = wlan_cpu_to_le16(dfs_repeater->mode);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of coalesce_config.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_coalesce_config(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	HostCmd_DS_COALESCE_CONFIG *coalesce_config =
+		&cmd->params.coalesce_config;
+	mlan_ds_coalesce_cfg *cfg = (mlan_ds_coalesce_cfg *) pdata_buf;
+	t_u16 cnt, idx, length;
+	struct coalesce_filt_field_param *param;
+	struct coalesce_receive_filt_rule *rule;
+	ENTER();
+
+	cmd->size = sizeof(HostCmd_DS_COALESCE_CONFIG) + S_DS_GEN;
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_COALESCE_CFG);
+	coalesce_config->action = wlan_cpu_to_le16(cmd_action);
+	coalesce_config->num_of_rules = wlan_cpu_to_le16(cfg->num_of_rules);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		rule = coalesce_config->rule;
+		for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
+			rule->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_COALESCE_RULE);
+			rule->max_coalescing_delay =
+				wlan_cpu_to_le16(cfg->rule[cnt].
+						 max_coalescing_delay);
+			rule->pkt_type = cfg->rule[cnt].pkt_type;
+			rule->num_of_fields = cfg->rule[cnt].num_of_fields;
+
+			length = 0;
+
+			param = rule->params;
+			for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) {
+				param->operation =
+					cfg->rule[cnt].params[idx].operation;
+				param->operand_len =
+					cfg->rule[cnt].params[idx].operand_len;
+				param->offset =
+					wlan_cpu_to_le16(cfg->rule[cnt].
+							 params[idx].offset);
+				memcpy(pmpriv->adapter,
+				       param->operand_byte_stream,
+				       cfg->rule[cnt].params[idx].
+				       operand_byte_stream, param->operand_len);
+
+				length +=
+					sizeof(struct
+					       coalesce_filt_field_param);
+
+				param++;
+			}
+
+			/* Total rule length is sizeof max_coalescing_delay(t_u16),
+			 * num_of_fields(t_u8), pkt_type(t_u8) and total length of the all
+			 * params
+			 */
+			rule->header.len =
+				wlan_cpu_to_le16(length + sizeof(t_u16) +
+						 sizeof(t_u8) + sizeof(t_u8));
+
+			/* Add the rule length to the command size */
+			cmd->size +=
+				wlan_le16_to_cpu(rule->header.len) +
+				sizeof(MrvlIEtypesHeader_t);
+
+			rule = (void *)((t_u8 *)rule->params + length);
+		}
+
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function sends get sta band channel command to firmware.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action  Command action
+ *  @param pioctl_buf  A pointer to mlan_ioctl_req structure
+ *  @param pdata_buf   A pointer to information buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_sta_config(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action,
+		    IN mlan_ioctl_req *pioctl_buf, IN 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 check if the command is supported by firmware
+ *
+ *  @param priv       A pointer to mlan_private structure
+ *  @param cmd_no       Command number
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_is_cmd_allowed(mlan_private *priv, IN t_u16 cmd_no)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	if (priv->adapter->psdio_device->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 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             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_config_dyn_bw(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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 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(IN t_void *priv,
+			 IN t_u16 cmd_no,
+			 IN t_u16 cmd_action,
+			 IN t_u32 cmd_oid,
+			 IN t_void *pioctl_buf,
+			 IN t_void *pdata_buf, IN 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;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, pdata_buf);
+		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_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);
+		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_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 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_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_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:
+		ret = wlan_cmd_reg_access(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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		ret = wlan_cmd_sdio_gpio_int(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	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;
+	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;
+#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_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_cmd_multi_chan_cfg(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_cmd_multi_chan_policy(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_cmd_drcs_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCMD_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_CMD_STA_CONFIGURE:
+		ret = wlan_cmd_sta_config(pmpriv, cmd_ptr, cmd_action,
+					  pioctl_buf, 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_DYN_BW:
+		ret = wlan_cmd_config_dyn_bw(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	case HostCmd_CMD_ACS:
+		ret = wlan_cmd_acs(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;
+	case HostCmd_CHANNEL_TRPC_CONFIG:
+		ret = wlan_cmd_get_chan_trpc_config(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(IN t_void *priv, IN 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 100644
index 0000000..b52386d
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_cmdresp.c
@@ -0,0 +1,2697 @@
+/** @file mlan_sta_cmdresp.c
+ *
+ *  @brief This file contains the handling of command
+ *  responses generated by firmware.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_11h.h"
+#include "mlan_sdio.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
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @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: command 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 (MTRUE == wlan_is_station_list_empty(pmpriv))
+			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: command 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 mlan_ioctl_req structure
+ *
+ *  @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);
+
+	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_802_11_ASSOCIATE:
+		wlan_reset_connect_state(pmpriv, MTRUE);
+		break;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		pmadapter->sdio_rx_aggr_enable = MFALSE;
+		PRINTM(MMSG, "FW don't support SDIO single port rx aggr\n");
+		break;
+
+	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;
+	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_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
+ */
+static mlan_status
+wlan_ret_802_11_rssi_info_ext(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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 *) ((t_u8 *)prssi_info_rsp +
+						    sizeof
+						    (HostCmd_DS_802_11_RSSI_INFO_EXT));
+		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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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;
+		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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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 *)((t_u8 *)ptxp_cfg
+					      + sizeof(HostCmd_DS_TXPWR_CFG));
+	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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN 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 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
+ */
+static mlan_status
+wlan_ret_802_11_mac_address(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_MAC_ADDRESS *pmac_addr = &resp->params.mac_addr;
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+
+	memcpy(pmpriv->adapter, pmpriv->curr_addr, pmac_addr->mac_addr,
+	       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(pmpriv->adapter, &bss->param.mac_addr, pmpriv->curr_addr,
+		       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 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *resp,
+			       IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	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);
+
+	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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_KEY_MATERIAL *pkey = &resp->params.key_material;
+	mlan_ds_sec_cfg *sec = MNULL;
+
+	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 for WPA/WPA2 h-supp mode\n");
+				pmpriv->port_open = MTRUE;
+				pmpriv->adapter->dbg.num_cons_cmd_assoc_failure = 0;
+			}
+			pmpriv->adapter->scan_block = MFALSE;
+		}
+	} else {
+		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(pmpriv->adapter, sec->param.encrypt_key.mac_addr,
+			       pkey->key_param_set.mac_addr,
+			       MLAN_MAC_ADDR_LENGTH);
+			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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.wapi.key,
+				       sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.wapi.pn,
+				       PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.tkip.key,
+				       sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.tkip.pn,
+				       WPA_PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.aes.key,
+				       sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.aes.pn,
+				       WPA_PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.cmac_aes.
+				       key, sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.cmac_aes.
+				       ipn, IGTK_PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.wep.key,
+				       sec->param.encrypt_key.key_len);
+				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(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(IN pmlan_private pmpriv,
+				IN 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(pmpriv->adapter,
+		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		       pibss_coal_resp->bssid, MLAN_MAC_ADDR_LENGTH);
+
+		/* 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      OUT 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(pmpriv->adapter, &misc->param.cust_ie, cust_ie,
+		       (cust_ie->len + sizeof(MrvlIEtypesHeader_t)));
+		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(pmpriv->adapter,
+				       (t_u8 *)&misc->param.cust_ie +
+				       (cust_ie->len +
+					sizeof(MrvlIEtypesHeader_t)),
+				       max_mgmt_ie,
+				       max_mgmt_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(IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp,
+		     OUT 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(pmpriv->adapter, &misc->param.tdls_config,
+		       &ptdls_config_data->tdls_info,
+		       MIN(sizeof(mlan_ds_misc_tdls_config),
+			   (resp->size - S_DS_GEN)));
+		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);
+			/* 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);
+			link_ptr->u.final_data_rate = final_data_rate / 2;
+
+			link_ptr =
+				(tdls_each_link_status *)(((t_u8 *)link_ptr) +
+							  link_length);
+		}
+		memcpy(pmpriv->adapter, &misc->param.tdls_config,
+		       &ptdls_config_data->tdls_info,
+		       MIN(sizeof(mlan_ds_misc_tdls_config),
+			   (resp->size - S_DS_GEN)));
+		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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *resp, OUT 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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(pmpriv->adapter, user_data->user_data,
+		       cmd_user_data->user_data, user_data->user_data_length);
+		pioctl_buf->data_read_written =
+			sizeof(mlan_ds_misc_otp_user_data) +
+			user_data->user_data_length;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_DFS_REPEATER_MODE *cmd_dfs_repeater =
+		&resp->params.dfs_repeater;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_misc_dfs_repeater *dfs_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		dfs_cfg =
+			(mlan_ds_misc_dfs_repeater *)&misc->param.dfs_repeater;
+		dfs_cfg->mode = wlan_le16_to_cpu(cmd_dfs_repeater->mode);
+	}
+	if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_SET)) {
+		if (wlan_le16_to_cpu(cmd_dfs_repeater->mode) == 1) {
+			/* Set dfs_repeater mode to true/enabled
+			 * for futher references.
+			 */
+			pmpriv->adapter->dfs_repeater = MTRUE;
+		} else {
+			pmpriv->adapter->dfs_repeater = MFALSE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of coalesce config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_coalesce_config(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN mlan_ioctl_req *pioctl_buf)
+{
+	ENTER();
+	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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *resp, IN 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.chanBand,
+				       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;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+		IN HostCmd_DS_COMMAND *resp, IN 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 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(IN t_void *priv,
+			     IN t_u16 cmdresp_no,
+			     IN t_void *pcmd_buf, IN 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;
+	int ctr;
+
+	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;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_ret_sdio_rx_aggr_cfg(pmpriv, resp);
+		break;
+	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_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_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_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_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);
+		pmadapter->tx_buf_size =
+			(pmadapter->tx_buf_size / MLAN_SDIO_BLOCK_SIZE) *
+			MLAN_SDIO_BLOCK_SIZE;
+		pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+		pmadapter->mp_end_port =
+			wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port);
+		pmadapter->mp_data_port_mask =
+			pmadapter->psdio_device->reg->data_port_mask;
+
+		for (ctr = 1;
+		     ctr <=
+		     pmadapter->psdio_device->max_ports -
+		     pmadapter->mp_end_port; ctr++) {
+			pmadapter->mp_data_port_mask &=
+				~(1 <<
+				  (pmadapter->psdio_device->max_ports - ctr));
+		}
+
+		if (pmadapter->psdio_device->supports_sdio_new_mode) {
+			pmadapter->curr_wr_port = 0;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+			pmadapter->mpa_tx.pkt_aggr_limit =
+				MIN(pmadapter->psdio_device->mp_aggr_pkt_limit,
+				    (pmadapter->mp_end_port >> 1));
+#endif
+		} else {
+			pmadapter->curr_wr_port = 1;
+		}
+		PRINTM(MCMND, "end port %d, data port mask %x\n",
+		       wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port),
+		       pmadapter->mp_data_port_mask);
+		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:
+		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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		break;
+	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;
+	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;
+#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_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_ret_multi_chan_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_ret_multi_chan_policy(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_ret_drcs_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	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_STA_CONFIGURE:
+		ret = wlan_ret_sta_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HOST_CMD_PMIC_CONFIGURE:
+		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_DYN_BW:
+		ret = wlan_ret_dyn_bw(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_ACS:
+		ret = wlan_ret_acs(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_BOOT_SLEEP:
+		ret = wlan_ret_boot_sleep(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CHANNEL_TRPC_CONFIG:
+		ret = wlan_ret_get_chan_trpc_config(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 100644
index 0000000..8f70e43
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_event.c
@@ -0,0 +1,1306 @@
+/** @file mlan_sta_event.c
+ *
+ *  @brief This file contains MLAN event handling.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+
+/********************************************************
+			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);
+				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(priv->adapter, tdls_oper.peer_mac,
+				       tdls_event->peer_mac_addr,
+				       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(priv->adapter,
+				       (t_u8 *)tdls_evt->peer_mac_addr,
+				       tdls_event->peer_mac_addr,
+				       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
+ */
+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(priv->adapter, (t_u8 *)tdls_evt->peer_mac_addr,
+			       sta_ptr->mac_addr, 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");
+
+	/* 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);
+
+	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;
+	}
+	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;
+	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;
+
+	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;
+	}
+
+	pevent->bss_index = priv->bss_index;
+	pevent->event_id = MLAN_EVENT_ID_FW_DISCONNECTED;
+	pevent->event_len = sizeof(priv->disconnect_reason_code);
+	memcpy(priv->adapter, pevent->event_buf, &priv->disconnect_reason_code,
+	       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;
+		/* Copy OBSS scan parameters */
+		memcpy(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 = ele_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(IN 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;
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+	sta_node *sta_ptr = MNULL;
+	t_u8 i = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_event *pevent = MNULL;
+	chan_band_info *pchan_band_info = MNULL;
+
+	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++;
+#define PRE_AUTH_NO_VALID 2
+#define FOUR_WAY_HANDSHAKE_TIMEOUT 15
+#define GTK_HANDSHAKE_TIMEOUT 16
+		/* only cover reason 2 for now until have evidence of the other two */
+		if (reason_code == PRE_AUTH_NO_VALID/*||
+		    reason_code == FOUR_WAY_HANDSHAKE_TIMEOUT ||
+		    reason_code == GTK_HANDSHAKE_TIMEOUT*/)
+			pmadapter->dbg.num_cons_cmd_assoc_failure++;
+
+		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(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(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(pmadapter,
+		       (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause),
+		       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;
+			pmpriv->adapter->dbg.num_cons_cmd_assoc_failure = 0;
+		}
+		pmadapter->scan_block = MFALSE;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PORT_RELEASE, MNULL);
+		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(pmadapter, (t_u8 *)&pchan_band_info->bandcfg,
+			       (t_u8 *)&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);
+			wlan_recv_event(pmpriv,
+					MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE,
+					pevent);
+		}
+		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_ANN:
+		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(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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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(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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause),
+		       pevent->event_len);
+		/* Handle / pass event data */
+		ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent);
+
+		/* Also send this event as passthru */
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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_MEAS_REPORT_RDY:
+		PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n",
+		       eventcause);
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_MEASUREMENT_REPORT,
+				       HostCmd_ACT_GEN_SET, 0, 0, MNULL);
+		break;
+	case EVENT_WMM_STATUS_CHANGE:
+		if (pmbuf && pmbuf->data_len
+		    > sizeof(eventcause) + sizeof(MrvlIEtypesHeader_t)) {
+			PRINTM(MEVENT, "EVENT: WMM status changed: %d\n",
+			       pmbuf->data_len);
+
+			evt_buf = (pmbuf->pbuf
+				   + pmbuf->data_offset + sizeof(eventcause));
+
+			wlan_ret_wmm_get_status(pmpriv,
+						evt_buf,
+						pmbuf->data_len -
+						sizeof(eventcause));
+		} else {
+			PRINTM(MEVENT, "EVENT: WMM status changed\n");
+			ret = wlan_cmd_wmm_status_change(pmpriv);
+		}
+		break;
+
+	case EVENT_RSSI_LOW:
+		PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n");
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_BCN_RSSI_LOW;
+		pevent->event_len = sizeof(t_u16);
+	    /** Fw send bcnRssi low value in event reason field*/
+		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+		       (t_u8 *)&pmadapter->event_body, 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(pmadapter, (t_u8 *)pevent->event_buf,
+		       (t_u8 *)&pmadapter->event_body, 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));
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmadapter->event_body, 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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmadapter->event_body, pevent->event_len);
+		if (pmadapter->dfs_repeater)
+			wlan_dfs_rep_bw_change(pmadapter);
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		break;
+	case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+		PRINTM(MEVENT, "EVENT: REMAIN_ON_CHANNEL_EXPIRED reason=%d\n",
+		       *(t_u16 *)pmadapter->event_body);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED,
+				MNULL);
+		break;
+#endif /* WIFI_DIRECT_SUPPORT */
+
+	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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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:
+		memcpy(pmadapter, addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		sta_ptr = wlan_add_station_entry(pmpriv, addr);
+		if (sta_ptr) {
+			PRINTM(MMSG,
+			       "wlan: EVENT: IBSS_STA_CONNECT " MACSTR "\n",
+			       MAC2STR(addr));
+			if (pmpriv->adapter->adhoc_11n_enabled) {
+				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->ibss_ampdu[i];
+					else
+						sta_ptr->ampdu_sta[i] =
+							BA_STREAM_NOT_ALLOWED;
+				}
+				memset(pmadapter, sta_ptr->rx_seq, 0xff,
+				       sizeof(sta_ptr->rx_seq));
+			}
+		}
+		break;
+	case EVENT_IBSS_STATION_DISCONNECT:
+		memcpy(pmadapter, addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		PRINTM(MMSG, "wlan: EVENT: IBSS_STA_DISCONNECT " MACSTR "\n",
+		       MAC2STR(addr));
+
+		if (pmpriv->adapter->adhoc_11n_enabled) {
+			wlan_cleanup_reorder_tbl(pmpriv, addr);
+			wlan_11n_cleanup_txbastream_tbl(pmpriv, addr);
+		}
+		wlan_wmm_delete_peer_ralist(pmpriv, addr);
+		wlan_delete_station_entry(pmpriv, addr);
+		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_MULTI_CHAN_INFO:
+		PRINTM(MEVENT, "EVENT: MULTI_CHAN_INFO\n");
+		wlan_handle_event_multi_chan_info(pmpriv, pmbuf);
+		break;
+
+	case EVENT_FW_DUMP_INFO:
+		PRINTM(MEVENT, "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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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;
+
+	case EVENT_MANAGEMENT_FRAME_WAKEUP:
+		PRINTM(MEVENT, "EVENT: EVENT_MANAGEMENT_FRAME_WAKEUP HOST\n");
+		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 100644
index 0000000..758c20f
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_ioctl.c
@@ -0,0 +1,5581 @@
+/** @file mlan_sta_ioctl.c
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_sdio.h"
+#include "mlan_11h.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+			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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			     IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(pmadapter, &info->param.bss_info.ssid, &pbss_desc->ssid,
+	       sizeof(mlan_802_11_ssid));
+
+	/* BSSID */
+	memcpy(pmadapter, &info->param.bss_info.bssid, &pbss_desc->mac_address,
+	       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(pmadapter, &info->param.bss_info.capability_info,
+	       &pbss_desc->cap_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(pmadapter, &info->param.bss_info.ext_cap,
+		       (t_u8 *)pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t),
+		       pbss_desc->pext_cap->ieee_hdr.len);
+	}
+
+	/* Listen Interval */
+	info->param.bss_info.listen_interval = pmpriv->listen_interval;
+
+	/* Association ID */
+	if (pmpriv->assoc_rsp_buf)
+		info->param.bss_info.assoc_id =
+			(t_u16)((IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf)->
+			a_id;
+	else
+		info->param.bss_info.assoc_id = 0;
+
+	/* AP/Peer supported rates */
+	memset(pmadapter, info->param.bss_info.peer_supp_rates, 0,
+	       sizeof(info->param.bss_info.peer_supp_rates));
+	memcpy(pmadapter, info->param.bss_info.peer_supp_rates,
+	       pbss_desc->supported_rates,
+	       MIN(sizeof(info->param.bss_info.peer_supp_rates),
+		   sizeof(pbss_desc->supported_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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *pget_info = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
+
+	switch (pget_info->sub_command) {
+	case MLAN_OID_GET_STATS:
+		status = wlan_get_info_stats(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_SIGNAL:
+		status = wlan_get_info_signal(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_SIGNAL_EXT:
+		status = wlan_get_info_signal_ext(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_FW_INFO:
+		pioctl_req->data_read_written =
+			sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
+		pget_info->param.fw_info.fw_ver = pmadapter->fw_release_number;
+		memcpy(pmadapter, &pget_info->param.fw_info.mac_addr,
+		       pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
+		pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+		pget_info->param.fw_info.region_code = pmadapter->region_code;
+		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;
+		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.fw_supplicant_support =
+			IS_FW_SUPPORT_SUPPLICANT(pmadapter) ? 0x01 : 0x00;
+		pget_info->param.fw_info.antinfo = pmadapter->antinfo;
+		pget_info->param.fw_info.max_ap_assoc_sta =
+			pmadapter->max_sta_conn;
+		break;
+	case MLAN_OID_GET_BSS_INFO:
+		status = wlan_get_info_bss_info(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_DEBUG_INFO:
+		status = wlan_get_info_debug_info(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_VER_EXT:
+		status = wlan_get_info_ver_ext(pmadapter, pioctl_req);
+		break;
+	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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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;
+	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(IN pmlan_adapter pmadapter,
+			   IN 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(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+		       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(IN pmlan_adapter pmadapter,
+				  IN 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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+		       IN 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_AN)
+		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+	else 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) {
+				if (pmadapter->adhoc_11n_enabled)
+					pmadapter->adhoc_start_band =
+						BAND_A | BAND_AN;
+				else
+					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) {
+				if (pmadapter->adhoc_11n_enabled)
+					pmadapter->adhoc_start_band =
+						BAND_A | BAND_AN;
+				else
+					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(IN pmlan_adapter pmadapter, IN 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(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_bss *bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	t_s32 i = -1;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+
+	ENTER();
+	/* Before ASSOC REQ, If "port ctrl" mode is enabled,
+	 * move the port to CLOSED state */
+	if (pmpriv->port_ctrl_mode == MTRUE) {
+		PRINTM(MINFO, "bss_ioctl_start(): port_state=CLOSED\n");
+		pmpriv->prior_port_status = pmpriv->port_open;
+		pmpriv->port_open = MFALSE;
+	}
+	pmadapter->scan_block = MFALSE;
+
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
+		if (!bss->param.ssid_bssid.idx ||
+		    bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table) {
+			/* Search for the requested SSID in the scan table */
+			if (bss->param.ssid_bssid.ssid.ssid_len) {
+				if (memcmp
+				    (pmadapter, &bss->param.ssid_bssid.bssid,
+				     zero_mac, sizeof(zero_mac)))
+					i = wlan_find_ssid_in_list(pmpriv,
+								   &bss->param.
+								   ssid_bssid.
+								   ssid,
+								   (t_u8 *)
+								   &bss->param.
+								   ssid_bssid.
+								   bssid,
+								   MLAN_BSS_MODE_INFRA);
+				else
+					i = wlan_find_ssid_in_list(pmpriv,
+								   &bss->param.
+								   ssid_bssid.
+								   ssid, MNULL,
+								   MLAN_BSS_MODE_INFRA);
+			} else {
+				i = wlan_find_bssid_in_list(pmpriv,
+							    (t_u8 *)&bss->param.
+							    ssid_bssid.bssid,
+							    MLAN_BSS_MODE_INFRA);
+			}
+		} else {
+			/* use bsslist index number to assoicate */
+			i = wlan_is_network_compatible(pmpriv,
+						       bss->param.ssid_bssid.
+						       idx - 1,
+						       pmpriv->bss_mode);
+		}
+
+		if (i >= 0) {
+			/* block if upper-layer tries to reconnect before new scan */
+			if (wlan_11h_get_csa_closed_channel(pmpriv) ==
+			    (t_u8)pmadapter->pscan_table[i].channel) {
+				PRINTM(MINFO,
+				       "Attempt to reconnect on csa_closed_chan(%d)\n",
+				       pmadapter->pscan_table[i].channel);
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				goto start_ssid_done;
+			}
+			PRINTM(MINFO,
+			       "SSID found in scan list ... associating...\n");
+			pmpriv->curr_bss_params.host_mlme =
+				bss->param.ssid_bssid.host_mlme;
+			/* Clear any past association response stored for application retrieval */
+			pmpriv->assoc_rsp_size = 0;
+			pmpriv->curr_chan_flags =
+				bss->param.ssid_bssid.channel_flags;
+			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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			   IN 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 passphrase
+ *
+ *  @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;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ssid_bssid *ssid_bssid = MNULL;
+	mlan_ds_sec_cfg sec;
+	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;
+
+	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(pmadapter, (t_u8 *)&sec_pp->ssid,
+			       &pbss_desc->ssid, sizeof(mlan_802_11_ssid));
+		} else
+			memcpy(pmadapter, (t_u8 *)&sec_pp->bssid,
+			       &ssid_bssid->bssid, MLAN_MAC_ADDR_LENGTH);
+	} else {
+		memcpy(pmadapter, (t_u8 *)&sec_pp->ssid, &ssid_bssid->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);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Search for a BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_bss_ioctl_find_bss(IN pmlan_adapter pmadapter,
+			IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	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;
+		}
+	}
+
+	ret = wlan_find_bss(pmpriv, pioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Check if BSS channel is valid for Station's region
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_bss_ioctl_bss_11d_check_channel(IN pmlan_adapter pmadapter,
+				     IN 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(IN pmlan_adapter pmadapter, IN 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_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(IN pmlan_adapter pmadapter,
+				   IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			   IN t_u16 cmd_no, IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(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_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(IN pmlan_adapter pmadapter, IN 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;
+	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(IN pmlan_adapter pmadapter,
+		      IN pmlan_ioctl_req pioctl_req, IN 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(IN pmlan_adapter pmadapter,
+				 IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(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_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(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_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(IN pmlan_adapter pmadapter,
+			IN 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(pmadapter, (t_u8 *)pmadapter->mgmt_filter,
+		       (t_u8 *)pm_cfg->param.mgmt_filter,
+		       (i + 1) * sizeof(mlan_mgmt_frame_wakeup));
+	} 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(IN pmlan_adapter pmadapter, IN 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(priv->adapter, priv->wpa_ie, ie_data_ptr, ie_len);
+		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(priv->adapter, priv->osen_ie, ie_data_ptr, ie_len);
+		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(priv->adapter, priv->wapi_ie, ie_data_ptr, ie_len);
+		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(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_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(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_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(IN pmlan_adapter pmadapter,
+				IN 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(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_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(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_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		sec->param.encrypt_mode = pmpriv->sec_info.encryption_mode;
+	else
+		pmpriv->sec_info.encryption_mode = sec->param.encrypt_mode;
+
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Random charactor
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return		random charactor
+ */
+t_u8
+wlan_get_random_charactor(pmlan_adapter pmadapter)
+{
+	t_u32 sec, usec;
+	t_u8 ch = 0;
+
+	ENTER();
+
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+						  &usec);
+	sec = (sec & 0xFFFF) + (sec >> 16);
+	usec = (usec & 0xFFFF) + (usec >> 16);
+	ch = (((sec << 16) + usec) % 26) + 'a';
+	LEAVE();
+	return ch;
+}
+
+/**
+ *  @brief Set/Get WPA status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_sec_ioctl_wpa_enable(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_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(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_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,
+						       MNULL,
+						       &sec->param.encrypt_key);
+				goto exit;
+			}
+			PRINTM(MERROR, "Key_index is invalid\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+		index = sec->param.encrypt_key.key_index;
+	}
+
+	if ((sec->param.encrypt_key.key_disable == MTRUE)||
+	    (sec->param.encrypt_key.key_remove == MTRUE)) {
+		pmpriv->sec_info.wep_status = Wlan802_11WEPDisabled;
+		/* remove key */
+		if (sec->param.encrypt_key.key_remove == MTRUE) {
+			memset(pmadapter, &pmpriv->wep_key[index], 0,
+			       sizeof(mrvl_wep_key_t));
+			/* call firmware remove key */
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_802_11_KEY_MATERIAL,
+					       HostCmd_ACT_GEN_SET,
+					       0,
+					       MNULL, &sec->param.encrypt_key);
+			if (ret)
+				goto exit;
+		}
+	} else {
+		if (sec->param.encrypt_key.key_len) {
+			if ((sec->param.encrypt_key.key_len !=
+			     WEP_104_BIT_LEN)&&(sec->param.encrypt_key.
+						key_len != WEP_40_BIT_LEN)) {
+				PRINTM(MERROR, "Invalid wep key len=%d\n",
+				       sec->param.encrypt_key.key_len);
+				/* We will use random key to clear the key buffer in FW */
+				if (sec->param.encrypt_key.key_len <
+				    WEP_40_BIT_LEN)
+					sec->param.encrypt_key.key_len =
+						WEP_40_BIT_LEN;
+				else
+					sec->param.encrypt_key.key_len =
+						WEP_104_BIT_LEN;
+				for (i = 0; i < sec->param.encrypt_key.key_len;
+				     i++)
+					sec->param.encrypt_key.key_material[i] =
+						wlan_get_random_charactor
+						(pmadapter);
+			}
+			pwep_key = &pmpriv->wep_key[index];
+			/* Cleanup */
+			memset(pmadapter, pwep_key, 0, sizeof(mrvl_wep_key_t));
+			/* Copy the key in the driver */
+
+			memcpy(pmadapter, pwep_key->key_material,
+			       sec->param.encrypt_key.key_material,
+			       sec->param.encrypt_key.key_len);
+			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 (0
+				    || &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(pmadapter, sec->param.encrypt_key.key_material,
+			       pwep_key->key_material,
+			       sec->param.encrypt_key.key_len);
+		}
+		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(pmadapter,
+				       sec->param.encrypt_key.key_material,
+				       pwep_key->key_material,
+				       sec->param.encrypt_key.key_len);
+			}
+			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(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_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;
+	}
+	wlan_reset_pn_value(pmpriv, &sec->param.encrypt_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;
+
+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(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_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(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->wep_key[index].key_material,
+			       MIN(MLAN_MAX_KEY_LENGTH,
+				   pmpriv->wep_key[index].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(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->aes_key.key_material,
+			       MIN(MLAN_MAX_KEY_LENGTH,
+				   pmpriv->aes_key.key_len));
+			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(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->wep_key[index].key_material,
+			       MIN(MLAN_MAX_KEY_LENGTH,
+				   pmpriv->wep_key[index].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(IN pmlan_adapter pmadapter,
+			   IN 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(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_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(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_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(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];
+	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(IN pmlan_adapter pmadapter, IN 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(priv->adapter, temp, &priv->ext_cap,
+			       sizeof(priv->ext_cap));
+			for (i = 0;
+			     i < MIN(sizeof(priv->ext_cap), pvendor_ie->len);
+			     i++)
+				temp[i] |= ie_data_ptr[2 + i];
+			memcpy(priv->adapter, &priv->ext_cap, temp,
+			       sizeof(temp));
+		} 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(priv->adapter, (t_u8 *)&priv->wps.wps_ie,
+				       ie_data_ptr, ie_len);
+				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(priv->adapter,
+				       priv->gen_ie_buf + priv->gen_ie_buf_len,
+				       ie_data_ptr, ie_len);
+				/* Increment the stored buffer length by
+				 * the size passed */
+				priv->gen_ie_buf_len += ie_len;
+			} else {
+				/* Passed data does not fit in the
+				 * remaining buffer space */
+				ret = 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(IN pmlan_adapter pmadapter,
+			IN 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(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_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(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];
+
+	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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			   IN 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)
+	    || (pmadapter->adhoc_start_band & BAND_AN)
+		) {
+		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(IN pmlan_adapter pmadapter,
+				      IN 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(IN pmlan_adapter pmadapter, IN 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;
+#if defined(DFS_TESTING_SUPPORT)
+	case MLAN_OID_11H_DFS_TESTING:
+		status = wlan_11h_ioctl_dfs_testing(pmadapter, pioctl_req);
+		break;
+#endif
+	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(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;
+
+	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(pmadapter, misc->param.gen_ie.ie_data,
+			       pmpriv->wpa_ie, misc->param.gen_ie.len);
+		} 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(pmadapter, pmadapter->arp_filter,
+			       misc->param.gen_ie.ie_data,
+			       misc->param.gen_ie.len);
+			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(IN pmlan_adapter pmadapter,
+			   IN 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;
+	t_u16 mc_policy = pmadapter->mc_policy;
+	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);
+    /** 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))) {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+	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;
+	}
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MULTI_CHAN_POLICY,
+			       HostCmd_ACT_GEN_SET, 0, MNULL, &mc_policy);
+	if (ret == MLAN_STATUS_FAILURE) {
+		LEAVE();
+		return ret;
+	}
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	if (ret == MLAN_STATUS_PENDING)
+		pmadapter->pwarm_reset_ioctl_req = pioctl_req;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+			      IN 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->mpa_tx.buf_size =
+					mpa_ctrl->tx_buf_size;
+
+			if (mpa_ctrl->rx_buf_size > 0)
+				pmadapter->mpa_rx.buf_size =
+					mpa_ctrl->rx_buf_size;
+
+			if (wlan_alloc_sdio_mpa_buffers(pmadapter,
+							pmadapter->mpa_tx.
+							buf_size,
+							pmadapter->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->mpa_tx.pkt_aggr_limit =
+				mpa_ctrl->tx_max_ports;
+		if (mpa_ctrl->rx_max_ports > 0)
+			pmadapter->mpa_rx.pkt_aggr_limit =
+				mpa_ctrl->rx_max_ports;
+
+		pmadapter->mpa_tx.enabled = (t_u8)mpa_ctrl->tx_enable;
+		pmadapter->mpa_rx.enabled = (t_u8)mpa_ctrl->rx_enable;
+
+	} else {
+		mpa_ctrl->tx_enable = (t_u16)pmadapter->mpa_tx.enabled;
+		mpa_ctrl->rx_enable = (t_u16)pmadapter->mpa_rx.enabled;
+		mpa_ctrl->tx_buf_size = (t_u16)pmadapter->mpa_tx.buf_size;
+		mpa_ctrl->rx_buf_size = (t_u16)pmadapter->mpa_rx.buf_size;
+		mpa_ctrl->tx_max_ports =
+			(t_u16)pmadapter->mpa_tx.pkt_aggr_limit;
+		mpa_ctrl->rx_max_ports =
+			(t_u16)pmadapter->mpa_rx.pkt_aggr_limit;
+	}
+
+exit:
+	LEAVE();
+	return ret;
+}
+#endif /* SDIO_MULTI_PORT_TX_AGGR || SDIO_MULTI_PORT_RX_AGGR */
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			      IN 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(pmadapter, misc->param.assoc_resp.assoc_resp_buf,
+		       pmpriv->assoc_rsp_buf, MIN(ASSOC_RSP_BUF_SIZE,
+						  pmpriv->assoc_rsp_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(IN pmlan_adapter pmadapter,
+			   IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_SOFT_RESET,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get the thermal reading
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_thermal(IN pmlan_adapter pmadapter,
+			IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		PRINTM(MERROR, "Thermal reading setting is not allowed!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	}
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_802_11_SNMP_MIB,
+			       cmd_action,
+			       Thermal_i, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set subscribe event
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_subscribe_evt(IN pmlan_adapter pmadapter,
+			      IN 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
+ */
+mlan_status
+wlan_ipaddr_arp_filter(IN pmlan_adapter pmadapter,
+		       IN pmlan_ioctl_req pioctl_req, IN 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(pmadapter, pmadapter->arp_filter, buf, len);
+		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;
+}
+
+#define FLTR_BUF_IP_OFFSET              24
+#define FLTR_BUF_IP_OFFSET_2_IP_1       9
+#define FLTR_BUF_IP_OFFSET_2_IP_2       26
+
+/**
+ *  @brief Enable/Disable Auto ARP resonse
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *  @param ipv4_addr    ipv4 Address
+ *  @param num_ipv4     Number of ipv4 Addresses
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_ipaddr_auto_arp_resp(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req,
+			  IN t_u32 *ipv4_addr, IN t_u8 num_ipv4)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_GEN *hostcmd_hdr;
+	HostCmd_DS_MEF_CFG *mefcmd;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_ds_misc_cmd *hostcmd;
+	t_u32 buf_len = 0;
+	t_u8 *buf, *filter;
+
+	t_u8 fltr_buf[] = { 0x01, 0x10, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0x08, 0x06, 0x02, 0x02, 0x14, 0x00, 0x00,
+		0x00, 0x01, 0x41, 0x01, 0x00, 0x00, 0x00, 0x01,
+		0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e, 0x00,
+		0x00, 0x00, 0x01, 0x41, 0x44
+	};
+	t_u8 fltr_buf_2_ip[] = { 0x01, 0x10, 0x33, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e,
+		0x00, 0x00, 0x00, 0x01, 0x41, 0x01, 0x00, 0x00,
+		0x00, 0x01, 0xc0, 0xa8, 0x02, 0x6d, 0x04, 0x02,
+		0x2e, 0x00, 0x00, 0x00, 0x01, 0x41, 0x45, 0x01,
+		0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x02, 0x02,
+		0x14, 0x00, 0x00, 0x00, 0x01, 0x41, 0x44
+	};
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_cmd),
+			       MLAN_MEM_DEF, (t_u8 **)&hostcmd);
+
+	if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
+		PRINTM(MERROR, "Failed to allocate hostcmd  buffer\n");
+		pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(pmpriv->adapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
+	buf = hostcmd->cmd;
+
+	/* Prepare hostcmd buffer */
+	hostcmd_hdr = (HostCmd_DS_GEN *)(buf);
+	hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
+	mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN);
+	buf_len = S_DS_GEN;
+
+	if (!ipv4_addr) {
+		PRINTM(MINFO, "Disable Auto ARP Response\n");
+		mefcmd->criteria = wlan_cpu_to_le32(0);
+		mefcmd->nentries = wlan_cpu_to_le16(0);
+		buf_len += sizeof(HostCmd_DS_MEF_CFG);
+	} else {
+		/* Event bit (bit2) of HS conditions should be masked out */
+		mefcmd->criteria =
+			wlan_cpu_to_le32(pmpriv->adapter->hs_cfg.
+					 conditions & ~MBIT(2));
+		mefcmd->nentries = wlan_cpu_to_le16(1);
+		buf_len += sizeof(HostCmd_DS_MEF_CFG);
+		filter = buf + buf_len;
+		if (num_ipv4 == 1) {
+			memcpy(pmpriv->adapter, filter, fltr_buf,
+			       sizeof(fltr_buf));
+			memcpy(pmpriv->adapter, &filter[FLTR_BUF_IP_OFFSET],
+			       &ipv4_addr[0], sizeof(t_u32));
+			buf_len += sizeof(fltr_buf);
+		} else if (num_ipv4 >= 2) {
+			memcpy(pmpriv->adapter, filter, fltr_buf_2_ip,
+			       sizeof(fltr_buf_2_ip));
+			memcpy(pmpriv->adapter,
+			       &filter[FLTR_BUF_IP_OFFSET_2_IP_1],
+			       &ipv4_addr[0], sizeof(t_u32));
+			memcpy(pmpriv->adapter,
+			       &filter[FLTR_BUF_IP_OFFSET_2_IP_2],
+			       &ipv4_addr[1], sizeof(t_u32));
+			buf_len += sizeof(fltr_buf_2_ip);
+		}
+	}
+	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+	hostcmd->len = buf_len;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       0,
+			       0, 0, (t_void *)pioctl_req, (t_void *)hostcmd);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief MEF configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_mef_cfg(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_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(pmpriv->adapter, filter, fltr_buf, sizeof(fltr_buf));
+		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(pmpriv->adapter, filter, mef_cfg->param.cmd_buf.cmd,
+		       mef_cfg->param.cmd_buf.len);
+		buf_len += mef_cfg->param.cmd_buf.len;
+		break;
+	default:
+		PRINTM(MERROR, "Invalid sub ID parameter\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+		break;
+	}
+	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+	hostcmd->len = buf_len;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       0,
+			       0, 0, (t_void *)pioctl_req, (t_void *)hostcmd);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+done:
+	if (hostcmd)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief ipaddr configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_ipaddr_cfg(IN pmlan_adapter pmadapter,
+			   IN 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];
+	int i = 0;
+
+	ENTER();
+
+	/* GET operation */
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		memcpy(pmadapter, misc->param.ipaddr_cfg.ip_addr,
+		       pmpriv->ip_addr, IPADDR_LEN);
+		misc->param.ipaddr_cfg.op_code = pmpriv->op_code;
+		goto done;
+	}
+	/* only one IP is supported in current firmware */
+	for (i = 0; i < misc->param.ipaddr_cfg.ip_addr_num; i++) {
+		memcpy(pmadapter, &ipv4_addr[i],
+		       misc->param.ipaddr_cfg.ip_addr[i], 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;
+	if (misc->param.ipaddr_cfg.op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP)
+		ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req,
+						ipv4_addr,
+						misc->param.ipaddr_cfg.
+						ip_addr_num);
+	else if (pmpriv->op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP)
+		ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req, MNULL,
+						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(pmadapter, pmpriv->ip_addr,
+		       misc->param.ipaddr_cfg.ip_addr, IPADDR_LEN);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief CFP code configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_cfp_code_cfg(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 = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_ds_misc_cfp_code *cfp_code = MNULL;
+	t_u32 region_bg = 0;
+	t_u32 region_a = 0;
+	int i;
+
+	ENTER();
+
+	cfp_code = &misc->param.cfp_code;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+			PRINTM(MERROR,
+			       "ForceRegionRule is set in the on-chip OTP"
+			       "memory\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		/* Save the values in MLAN */
+		if (!cfp_code->cfp_code_bg)
+			cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+			/* Use the region code to search for the index */
+			if (cfp_code->cfp_code_bg == region_code_index[i]) {
+				region_bg = cfp_code->cfp_code_bg;
+				break;
+			}
+		}
+		if (!cfp_code->cfp_code_a)
+			cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+			/* Use the region code to search for the index */
+			if (cfp_code->cfp_code_a == region_code_index[i]) {
+				region_a = cfp_code->cfp_code_a;
+				break;
+			}
+		}
+		if (!region_a) {
+			for (i = 0; i < MRVDRV_MAX_CFP_CODE_A; i++) {
+				/* Use the CFP code to search for the index */
+				if (cfp_code->cfp_code_a == cfp_code_index_a[i])
+					break;
+			}
+			if (i >= MRVDRV_MAX_CFP_CODE_A) {
+				PRINTM(MERROR,
+				       "CFP Code not identified for A\n");
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		pmadapter->cfp_code_bg = (t_u8)cfp_code->cfp_code_bg;
+		pmadapter->cfp_code_a = (t_u8)cfp_code->cfp_code_a;
+		if (region_bg && region_a && (region_bg == region_a))
+			pmadapter->region_code = pmadapter->cfp_code_a;
+		else
+			pmadapter->region_code = 0;
+		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+					 pmadapter->config_bands | pmadapter->
+					 adhoc_start_band)) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	} else {
+		/* GET operation */
+		cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+		cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets up country code and downloads CMD to FW
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_ioctl_country_code(IN pmlan_adapter pmadapter,
+			     IN 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(pmadapter, pmadapter->country_code,
+		       country_code->country_code, COUNTRY_CODE_LEN);
+	} else {
+		/* GET operation */
+		memcpy(pmadapter, country_code->country_code,
+		       pmadapter->country_code, COUNTRY_CODE_LEN);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Configure MFPC and MFPR for management frame protection
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_pmfcfg(IN pmlan_adapter pmadapter, IN 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 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(IN pmlan_adapter pmadapter,
+		       IN 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 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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+
+	if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
+		PRINTM(MERROR, "Request buffer not found!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	switch (misc->sub_command) {
+	case MLAN_OID_MISC_GEN_IE:
+		status = wlan_misc_ioctl_gen_ie(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_REGION:
+		status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_WARM_RESET:
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &pmadapter->ioctl_pending_q,
+				       (pmlan_linked_list)pioctl_req,
+				       pmadapter->callbacks.moal_spin_lock,
+				       pmadapter->callbacks.moal_spin_unlock);
+		pmadapter->pending_ioctl = MTRUE;
+		status = MLAN_STATUS_PENDING;
+		break;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	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;
+	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;
+	case MLAN_OID_MISC_MULTI_CHAN_CFG:
+		status = wlan_misc_ioctl_multi_chan_config(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_MISC_MULTI_CHAN_POLICY:
+		status = wlan_misc_ioctl_multi_chan_policy(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_MISC_DRCS_CFG:
+		status = wlan_misc_ioctl_drcs_config(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_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_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_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_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_ROBUSTCOEX:
+		status = wlan_misc_robustcoex(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;
+	case MLAN_OID_MISC_ACS:
+		status = wlan_misc_acs(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;
+	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(IN pmlan_adapter pmadapter,
+		      IN pmlan_ioctl_req pioctl_req, IN 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;
+	}
+	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;
+	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(IN pmlan_adapter pmadapter, IN 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(pmadapter, mac, &bss->param.ssid_bssid.bssid,
+			       sizeof(mac));
+			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(pmadapter, &bss->param.ssid_bssid.ssid, &pbss_desc->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(pmadapter, (t_u8 *)&bss->param.ssid_bssid.bssid,
+		       (t_u8 *)&pbss_desc->mac_address, 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;
+	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 100644
index 0000000..03aacf4
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_rx.c
@@ -0,0 +1,669 @@
+/** @file mlan_sta_rx.c
+ *
+ *  @brief This file contains the handling of RX in MLAN
+ *  module.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+
+/********************************************************
+		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 Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/********************************************************
+		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;
+
+#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 = pos[1];
+			for (i = 0; i < pos[1]; i++)
+				sta_ptr->support_rate[i] = pos[2 + i];
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+			for (i = 0; i < pos[1]; i++)
+				sta_ptr->support_rate[sta_ptr->rate_len + i] =
+					pos[2 + i];
+			sta_ptr->rate_len += pos[1];
+			break;
+		case HT_CAPABILITY:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->HTcap, pos,
+			       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(priv->adapter, &sta_ptr->HTInfo, pos,
+			       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(priv->adapter, (t_u8 *)&sta_ptr->BSSCO_20_40,
+			       pos, sizeof(IEEEtypes_2040BSSCo_t));
+			break;
+		case EXT_CAPABILITY:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->ExtCap, pos,
+			       pos[1] + sizeof(IEEEtypes_Header_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS Extended capability",
+				    (t_u8 *)(&sta_ptr->ExtCap),
+				    sta_ptr->ExtCap.ieee_hdr.len + 2);
+			break;
+		case RSN_IE:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->rsn_ie, pos,
+			       pos[1] + sizeof(IEEEtypes_Header_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS Rsn ie ",
+				    (t_u8 *)(&sta_ptr->rsn_ie),
+				    pos[1] + 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(priv->adapter, (t_u8 *)&sta_ptr->link_ie, pos,
+			       sizeof(IEEEtypes_LinkIDElement_t));
+			break;
+
+		case VHT_CAPABILITY:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->vht_cap, pos,
+			       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(priv->adapter, (t_u8 *)&sta_ptr->vht_oprat, pos,
+			       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(priv->adapter, (t_u8 *)&sta_ptr->aid_info, pos,
+			       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 };
+
+	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(pmadapter, peth_hdr->src_addr,
+		       prx_pkt->eth803_hdr.src_addr,
+		       sizeof(peth_hdr->src_addr));
+		memcpy(pmadapter, peth_hdr->dest_addr,
+		       prx_pkt->eth803_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);
+
+	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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	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(IN t_void *adapter, IN 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_u8 adj_rx_rate = 0;
+	t_u8 antenna = 0;
+	ENTER();
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	/* Endian conversion */
+	endian_convert_RxPD(prx_pd);
+
+	rx_pkt_type = prx_pd->rx_pkt_type;
+	prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+	priv->rxpd_rate_info = prx_pd->rate_info;
+	if (!priv->adapter->psdio_device->v15_fw_api)
+		priv->rxpd_rate_info =
+			wlan_convert_v14_rate_ht_info(priv->rxpd_rate_info);
+	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 ((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;
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		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);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		goto done;
+	}
+
+	/*
+	 * 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)
+	     && !IS_11N_ADHOC_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(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+		       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(pmadapter, ta,
+		       priv->curr_bss_params.bss_descriptor.mac_address,
+		       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)
+		) {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+
+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 100644
index 0000000..0c5a5cd
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_tx.c
@@ -0,0 +1,303 @@
+/** @file mlan_sta_tx.c
+ *
+ *  @brief This file contains the handling of data packet
+ *  transmission in MLAN module.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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_sdio.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(IN t_void *priv, IN 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(pmpriv->adapter, &pkt_type,
+		       pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type));
+		memcpy(pmpriv->adapter, &tx_control,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+		       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;
+	}
+	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 = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf, MNULL);
+
+	switch (ret) {
+	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:
+		pmadapter->data_sent = MFALSE;
+		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 100644
index 0000000..a2a0d20
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_txrx.c
@@ -0,0 +1,395 @@
+/**
+ * @file mlan_txrx.c
+ *
+ *  @brief This file contains the handling of TX/RX in MLAN
+ *
+ *  Copyright (C) 2009-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/*************************************************************
+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"
+#include "mlan_sdio.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
+	TxPD *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
+
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf,
+				     tx_param);
+done:
+	switch (ret) {
+	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;
+			plocal_tx_pd->flags = 0;
+		}
+#endif
+		PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
+		break;
+	case MLAN_STATUS_FAILURE:
+		pmadapter->data_sent = MFALSE;
+		PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
+		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(IN pmlan_adapter pmadapter,
+			 IN pmlan_buffer pmbuf, IN 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 (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);
+		}
+	}
+
+	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(IN pmlan_adapter pmadapter,
+			  IN pmlan_buffer pmbuf, IN mlan_status status)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	MASSERT(pmadapter && pmbuf);
+	if (!pmadapter || !pmbuf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pcb = &pmadapter->callbacks;
+	MASSERT(pmbuf->bss_index < pmadapter->priv_num);
+
+	if (pmbuf->pparent) {
+	/** we will free the pparaent at the end of deaggr */
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	} else {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+
+	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();
+	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) {
+				PRINTM(MINFO, "Dequeuing bypassed packet %p\n",
+				       pmbuf);
+				/* XXX: nex_pkt_len ??? */
+				tx_param.next_pkt_len = 0;
+				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 */
+					util_enqueue_list_head(pmadapter->
+							       pmoal_handle,
+							       &priv->
+							       bypass_txq,
+							       (pmlan_linked_list)
+							       pmbuf,
+							       pmadapter->
+							       callbacks.
+							       moal_spin_lock,
+							       pmadapter->
+							       callbacks.
+							       moal_spin_unlock);
+				} else {
+					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);
+				}
+				break;
+			} else {
+				PRINTM(MINFO, "Nothing to send\n");
+			}
+		}
+	}
+	LEAVE();
+}
diff --git a/wlan_sd8987/mlan/mlan_uap.h b/wlan_sd8987/mlan/mlan_uap.h
new file mode 100644
index 0000000..d510877
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_uap.h
@@ -0,0 +1,89 @@
+/** @file mlan_uap.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of uap functionalities
+ *
+ *  Copyright (C) 2009-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+Change log:
+    02/05/2009: initial version
+********************************************************/
+
+#ifndef _MLAN_UAP_H_
+#define _MLAN_UAP_H_
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert TxPD to little endian format from CPU format */
+#define uap_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 uap_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);            \
+	    (x)->hi_rx_count32 = wlan_le32_to_cpu((x)->hi_rx_count32);      \
+	    (x)->lo_rx_count16 = wlan_le16_to_cpu((x)->lo_rx_count16);      \
+	}
+#else
+/** Convert TxPD to little endian format from CPU format */
+#define uap_endian_convert_TxPD(x)  do {} while (0)
+/** Convert RxPD from little endian format to CPU format */
+#define uap_endian_convert_RxPD(x)  do {} while (0)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+mlan_status wlan_uap_get_channel(IN pmlan_private pmpriv);
+
+mlan_status wlan_uap_set_channel(IN pmlan_private pmpriv,
+				 IN Band_Config_t uap_band_cfg,
+				 IN t_u8 channel);
+
+mlan_status wlan_uap_get_beacon_dtim(IN pmlan_private pmpriv);
+
+mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_ops_uap_prepare_cmd(IN t_void *priv,
+				     IN t_u16 cmd_no,
+				     IN t_u16 cmd_action,
+				     IN t_u32 cmd_oid,
+				     IN t_void *pioctl_buf,
+				     IN t_void *pdata_buf, IN t_void *pcmd_buf);
+
+mlan_status wlan_ops_uap_process_cmdresp(IN t_void *priv,
+					 IN t_u16 cmdresp_no,
+					 IN t_void *pcmd_buf,
+					 IN t_void *pioctl);
+
+mlan_status wlan_ops_uap_process_rx_packet(IN t_void *adapter,
+					   IN pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_process_event(IN t_void *priv);
+
+t_void *wlan_ops_uap_process_txpd(IN t_void *priv, IN pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_init_cmd(IN t_void *priv, IN 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 100644
index 0000000..8918f77
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_uap_cmdevent.c
@@ -0,0 +1,5064 @@
+/** @file mlan_uap_cmdevent.c
+ *
+ *  @brief This file contains the handling of AP mode command and event
+ *
+ *  Copyright (C) 2009-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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_sdio.h"
+#include "mlan_11n.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief This function handles the command response error
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             N/A
+ */
+static mlan_status
+uap_process_cmdresp_error(mlan_private *pmpriv, HostCmd_DS_COMMAND *resp,
+			  mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	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) {
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		pmadapter->sdio_rx_aggr_enable = MFALSE;
+		PRINTM(MMSG, "FW don't support SDIO single port rx aggr\n");
+		break;
+
+	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_CHAN_REGION_CFG:
+		ret = MLAN_STATUS_SUCCESS;
+		PRINTM(MCMND, "FW don't support chan region cfg command!\n");
+		break;
+	default:
+		break;
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+	pmadapter->curr_cmd = MNULL;
+	wlan_release_cmd_lock(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will return the pointer to station entry in station list
+ *          table which matches the give mac address
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+void
+wlan_notify_station_deauth(mlan_private *priv)
+{
+	sta_node *sta_ptr;
+	t_u8 event_buf[100];
+	mlan_event *pevent = (mlan_event *)event_buf;
+	t_u8 *pbuf;
+
+	ENTER();
+	sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+					     &priv->sta_list,
+					     priv->adapter->callbacks.
+					     moal_spin_lock,
+					     priv->adapter->callbacks.
+					     moal_spin_unlock);
+	if (!sta_ptr) {
+		LEAVE();
+		return;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		memset(priv->adapter, event_buf, 0, sizeof(event_buf));
+		pevent->bss_index = priv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT;
+		pevent->event_len = MLAN_MAC_ADDR_LENGTH + 2;
+		pbuf = (t_u8 *)pevent->event_buf;
+		/* reason field set to 0, Unspecified */
+		memcpy(priv->adapter, pbuf + 2, sta_ptr->mac_addr,
+		       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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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_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(pmadapter, (t_u8 *)mgmt_filter_tlv->filter,
+			       (t_u8 *)mgmt_filter,
+			       i * sizeof(mgmt_frame_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);
+		}
+	}
+	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,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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;
+
+	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(pmpriv->adapter, tlv_mac->mac,
+		       &bss->param.bss_config.mac_addr, 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(pmpriv->adapter, tlv_ssid->ssid,
+		       bss->param.bss_config.ssid.ssid,
+		       bss->param.bss_config.ssid.ssid_len);
+		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);
+	}
+
+	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);
+	}
+	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(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);
+		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);
+		}
+
+		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(pmpriv->adapter, tlv_passphrase->passphrase,
+			       bss->param.bss_config.wpa_cfg.passphrase,
+			       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);
+		}
+	} 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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key0.key,
+			       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key1.key,
+			       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key2.key,
+			       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key3.key,
+			       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(pmpriv->adapter, tlv_htcap->ht_cap.supported_mcs_set,
+		       bss->param.bss_config.supported_mcs_set, 16);
+		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.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(pmpriv->adapter, tlv_wmm_parameter->wmm_para.ouitype,
+		       bss->param.bss_config.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);
+	}
+	if (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,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action,
+			   IN pmlan_ioctl_req pioctl_buf, IN t_void *pdata_buf)
+{
+	mlan_ds_bss *bss = MNULL;
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config;
+	MrvlIEtypes_MacAddr_t *mac_tlv = MNULL;
+	MrvlIEtypes_channel_band_t *pdat_tlv_cb = MNULL;
+	MrvlIEtypes_beacon_period_t *bcn_pd_tlv = MNULL, *pdat_tlv_bcnpd =
+		MNULL;
+	MrvlIEtypes_dtim_period_t *dtim_pd_tlv = MNULL, *pdat_tlv_dtimpd =
+		MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	MrvlIEtypes_channel_band_t *chan_band_tlv = MNULL;
+	MrvlIEtypes_chan_bw_oper_t *poper_class_tlv = MNULL;
+	t_u8 length = 0;
+	t_u8 curr_oper_class = 1;
+	t_u8 *oper_class_ie = (t_u8 *)sys_config->tlv_buffer;
+	t_u16 i = 0;
+	t_u8 ac = 0;
+	mlan_ds_misc_custom_ie *cust_ie = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	MrvlIEtypesHeader_t *ie_header =
+		(MrvlIEtypesHeader_t *)sys_config->tlv_buffer;
+	MrvlIEtypesHeader_t *pdata_header = (MrvlIEtypesHeader_t *)pdata_buf;
+	t_u8 *ie = (t_u8 *)sys_config->tlv_buffer + sizeof(MrvlIEtypesHeader_t);
+	t_u16 req_len = 0, travel_len = 0;
+	custom_ie *cptr = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
+	sys_config->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN);
+	if (pioctl_buf == MNULL) {
+
+		if (pdata_buf) {
+			switch (pdata_header->type) {
+			case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
+				pdat_tlv_cb =
+					(MrvlIEtypes_channel_band_t *)pdata_buf;
+				chan_band_tlv =
+					(MrvlIEtypes_channel_band_t *)
+					sys_config->tlv_buffer;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_channel_band_t));
+				chan_band_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+				chan_band_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_channel_band_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				if (cmd_action) {
+					chan_band_tlv->bandcfg =
+						pdat_tlv_cb->bandcfg;
+					chan_band_tlv->channel =
+						pdat_tlv_cb->channel;
+				}
+				ret = MLAN_STATUS_SUCCESS;
+				break;
+			case TLV_TYPE_UAP_BEACON_PERIOD:
+				pdat_tlv_bcnpd =
+					(MrvlIEtypes_beacon_period_t *)
+					pdata_buf;
+				bcn_pd_tlv =
+					(MrvlIEtypes_beacon_period_t *)
+					sys_config->tlv_buffer;
+				cmd->size =
+					sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+					S_DS_GEN +
+					sizeof(MrvlIEtypes_beacon_period_t);
+				bcn_pd_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_BEACON_PERIOD);
+				bcn_pd_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_beacon_period_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				if (cmd_action) {
+					bcn_pd_tlv->beacon_period =
+						wlan_cpu_to_le16
+						(pdat_tlv_bcnpd->beacon_period);
+				}
+				/* Add TLV_UAP_DTIM_PERIOD if it follws in pdata_buf */
+				pdat_tlv_dtimpd =
+					(MrvlIEtypes_dtim_period_t
+					 *)(((t_u8 *)pdata_buf)
+					    +
+					    sizeof
+					    (MrvlIEtypes_beacon_period_t));
+				if (TLV_TYPE_UAP_DTIM_PERIOD ==
+				    pdat_tlv_dtimpd->header.type) {
+					dtim_pd_tlv =
+						(MrvlIEtypes_dtim_period_t
+						 *)(sys_config->tlv_buffer +
+						    sizeof
+						    (MrvlIEtypes_beacon_period_t));
+					cmd->size +=
+						sizeof
+						(MrvlIEtypes_dtim_period_t);
+					dtim_pd_tlv->header.type =
+						wlan_cpu_to_le16
+						(TLV_TYPE_UAP_DTIM_PERIOD);
+					dtim_pd_tlv->header.len =
+						wlan_cpu_to_le16(sizeof
+								 (MrvlIEtypes_dtim_period_t)
+								 -
+								 sizeof
+								 (MrvlIEtypesHeader_t));
+					if (cmd_action) {
+						dtim_pd_tlv->dtim_period =
+							pdat_tlv_dtimpd->
+							dtim_period;
+					}
+				}
+				/* Finalize cmd size */
+				cmd->size = wlan_cpu_to_le16(cmd->size);
+				ret = MLAN_STATUS_SUCCESS;
+				break;
+			case TLV_TYPE_MGMT_IE:
+				cust_ie = (mlan_ds_misc_custom_ie *)pdata_buf;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypesHeader_t) +
+							 cust_ie->len);
+				ie_header->type =
+					wlan_cpu_to_le16(TLV_TYPE_MGMT_IE);
+				ie_header->len = wlan_cpu_to_le16(cust_ie->len);
+
+				if (ie && cust_ie->ie_data_list) {
+					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(pmpriv->adapter, ie,
+					       cust_ie->ie_data_list,
+					       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;
+
+			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(pmpriv->adapter, mac_tlv->mac,
+				       &bss->param.mac_addr,
+				       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.chanBand,
+				       bss->param.ap_channel.channel);
+			}
+		} else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG) &&
+			   (cmd_action == HostCmd_ACT_GEN_SET)) {
+			ret = wlan_uap_cmd_ap_config(pmpriv, cmd, cmd_action,
+						     pioctl_buf);
+			goto done;
+		}
+	} else if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		if ((misc->sub_command == MLAN_OID_MISC_GEN_IE) &&
+		    (misc->param.gen_ie.type == MLAN_IE_TYPE_GEN_IE)
+			) {
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof(MrvlIEtypesHeader_t) +
+						 misc->param.gen_ie.len);
+			ie_header->type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE);
+			ie_header->len =
+				wlan_cpu_to_le16(misc->param.gen_ie.len);
+			if (cmd_action == HostCmd_ACT_GEN_SET)
+				memcpy(pmpriv->adapter, ie,
+				       misc->param.gen_ie.ie_data,
+				       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 && misc->param.cust_ie.ie_data_list) {
+				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(pmpriv->adapter, ie,
+					       misc->param.cust_ie.ie_data_list,
+					       misc->param.cust_ie.len);
+			}
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles command resp for get uap settings
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_cmd_ap_config(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(pmpriv->adapter, &bss->param.bss_config.mac_addr,
+			       tlv_mac->mac, 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(pmpriv->adapter, bss->param.bss_config.ssid.ssid,
+			       tlv_ssid->ssid, MIN(MLAN_MAX_SSID_LENGTH,
+						   tlv_len));
+			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(pmpriv->adapter, bss->param.bss_config.rates,
+			       tlv_rates->rates, MIN(MAX_DATA_RATES, tlv_len));
+			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(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);
+			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;
+			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(pmpriv->adapter,
+			       bss->param.bss_config.wpa_cfg.passphrase,
+			       tlv_passphrase->passphrase,
+			       bss->param.bss_config.wpa_cfg.length);
+			break;
+#ifdef WIFI_DIRECT_SUPPORT
+		case TLV_TYPE_UAP_PSK:
+			tlv_psk = (MrvlIEtypes_psk_t *)tlv;
+			memcpy(pmpriv->adapter, bss->param.bss_config.psk,
+			       tlv_psk->psk, MIN(MLAN_MAX_KEY_LENGTH, tlv_len));
+			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(pmpriv->adapter, pkey->key,
+				       tlv_wep_key->key, 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(pmpriv->adapter,
+			       bss->param.bss_config.supported_mcs_set,
+			       tlv_htcap->ht_cap.supported_mcs_set, 16);
+			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));
+	}
+	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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *resp,
+			IN mlan_ioctl_req *pioctl_buf)
+{
+	int resp_len = 0, travel_len = 0;
+	int i = 0;
+	custom_ie *cptr;
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	MrvlIEtypes_MacAddr_t *tlv =
+		(MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer;
+	mlan_ds_misc_custom_ie *cust_ie = MNULL;
+	tlvbuf_max_mgmt_ie *max_mgmt_ie = MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter =
+		(MrvlIEtypes_wmm_parameter_t *)sys_config->tlv_buffer;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list =
+		(MrvlIEtypes_ChanListParamSet_t *)sys_config->tlv_buffer;
+	MrvlIEtypes_channel_band_t *chan_band_tlv =
+		(MrvlIEtypes_channel_band_t *)sys_config->tlv_buffer;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	t_u8 ac = 0;
+	MrvlIEtypes_channel_band_t *tlv_cb = MNULL;
+	MrvlIEtypes_beacon_period_t *tlv_bcnpd = MNULL;
+	MrvlIEtypes_dtim_period_t *tlv_dtimpd = MNULL;
+
+	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(pmpriv->adapter,
+					       &bss->param.mac_addr, tlv->mac,
+					       MLAN_MAC_ADDR_LENGTH);
+				}
+			} else if (bss->sub_command ==
+				   MLAN_OID_UAP_CFG_WMM_PARAM) {
+				if (TLV_TYPE_AP_WMM_PARAM ==
+				    wlan_le16_to_cpu(tlv_wmm_parameter->header.
+						     type)) {
+					if (wlan_le16_to_cpu
+					    (tlv_wmm_parameter->header.len) <
+					    sizeof(bss->param.ap_wmm_para)) {
+						PRINTM(MCMND,
+						       "FW don't support AP WMM PARAM\n");
+					} else {
+						bss->param.ap_wmm_para.
+							reserved =
+							MLAN_STATUS_COMPLETE;
+						for (ac = 0; ac < 4; ac++) {
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								aci_aifsn.
+								aifsn =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								aci_aifsn.aifsn;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								aci_aifsn.aci =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								aci_aifsn.aci;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								ecw.ecw_max =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								ecw.ecw_max;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								ecw.ecw_min =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								ecw.ecw_min;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								tx_op_limit =
+								wlan_le16_to_cpu
+								(tlv_wmm_parameter->
+								 wmm_para.
+								 ac_params[ac].
+								 tx_op_limit);
+							PRINTM(MCMND,
+							       "ac=%d, aifsn=%d, aci=%d, ecw_max=%d, ecw_min=%d, tx_op=%d\n",
+							       ac,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       aci_aifsn.aifsn,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       aci_aifsn.aci,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       ecw.ecw_max,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       ecw.ecw_min,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       tx_op_limit);
+						}
+					}
+				}
+			} else if (bss->sub_command ==
+				   MLAN_OID_UAP_SCAN_CHANNELS) {
+				if (TLV_TYPE_CHANLIST ==
+				    wlan_le16_to_cpu(tlv_chan_list->header.
+						     type)) {
+					pscan_chan =
+						tlv_chan_list->chan_scan_param;
+					bss->param.ap_scan_channels.
+						num_of_chan = 0;
+					for (i = 0;
+					     i <
+					     wlan_le16_to_cpu(tlv_chan_list->
+							      header.len) /
+					     sizeof(ChanScanParamSet_t); i++) {
+						if (bss->param.ap_scan_channels.
+						    remove_nop_channel &&
+						    wlan_11h_is_channel_under_nop
+						    (pmpriv->adapter,
+						     pscan_chan->chan_number)) {
+							bss->param.
+								ap_scan_channels.
+								num_remvoed_channel++;
+							PRINTM(MCMND,
+							       "Remove nop channel=%d\n",
+							       pscan_chan->
+							       chan_number);
+							pscan_chan++;
+							continue;
+						}
+						bss->param.ap_scan_channels.
+							chan_list[bss->param.
+								  ap_scan_channels.
+								  num_of_chan].
+							chan_number =
+							pscan_chan->chan_number;
+						bss->param.ap_scan_channels.
+							chan_list[bss->param.
+								  ap_scan_channels.
+								  num_of_chan].
+							bandcfg =
+							pscan_chan->bandcfg;
+						bss->param.ap_scan_channels.
+							num_of_chan++;
+						pscan_chan++;
+					}
+					PRINTM(MCMND,
+					       "AP scan channel list=%d\n",
+					       bss->param.ap_scan_channels.
+					       num_of_chan);
+				}
+			} else if (bss->sub_command == MLAN_OID_UAP_CHANNEL) {
+				if (TLV_TYPE_UAP_CHAN_BAND_CONFIG ==
+				    wlan_le16_to_cpu(chan_band_tlv->header.
+						     type)) {
+					bss->param.ap_channel.bandcfg =
+						chan_band_tlv->bandcfg;
+					bss->param.ap_channel.channel =
+						chan_band_tlv->channel;
+					bss->param.ap_channel.is_11n_enabled =
+						pmpriv->is_11n_enabled;
+					bss->param.ap_channel.is_dfs_chan =
+						wlan_11h_radar_detect_required
+						(pmpriv,
+						 bss->param.ap_channel.channel);
+					if (chan_band_tlv->bandcfg.chanWidth ==
+					    CHAN_BW_80MHZ)
+						bss->param.ap_channel.
+							center_chan =
+							wlan_get_center_freq_idx
+							(pmpriv, BAND_AAC,
+							 chan_band_tlv->channel,
+							 CHANNEL_BW_80MHZ);
+					PRINTM(MCMND,
+					       "AP channel, band=0x%x, channel=%d, is_11n_enabled=%d center_chan=%d\n",
+					       bss->param.ap_channel.bandcfg.
+					       chanBand,
+					       bss->param.ap_channel.channel,
+					       bss->param.ap_channel.
+					       is_11n_enabled,
+					       bss->param.ap_channel.
+					       center_chan);
+				}
+			} else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG)
+				   && (pioctl_buf->action == MLAN_ACT_GET)) {
+				wlan_uap_ret_cmd_ap_config(pmpriv, resp,
+							   pioctl_buf);
+			}
+		}
+		if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+			misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+			cust_ie =
+				(mlan_ds_misc_custom_ie *)sys_config->
+				tlv_buffer;
+			if ((pioctl_buf->action == MLAN_ACT_GET ||
+			     pioctl_buf->action == MLAN_ACT_SET) &&
+			    (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)) {
+
+				cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+				resp_len = cust_ie->len =
+					wlan_le16_to_cpu(cust_ie->len);
+				travel_len = 0;
+				/* conversion for index, mask, len */
+				if (resp_len == sizeof(t_u16))
+					cust_ie->ie_data_list[0].ie_index =
+						wlan_cpu_to_le16(cust_ie->
+								 ie_data_list
+								 [0].ie_index);
+
+				while (resp_len > sizeof(t_u16)) {
+					cptr = (custom_ie
+						*)(((t_u8 *)cust_ie->
+						    ie_data_list) + travel_len);
+					cptr->ie_index =
+						wlan_le16_to_cpu(cptr->
+								 ie_index);
+					cptr->mgmt_subtype_mask =
+						wlan_le16_to_cpu(cptr->
+								 mgmt_subtype_mask);
+					cptr->ie_length =
+						wlan_le16_to_cpu(cptr->
+								 ie_length);
+					travel_len +=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+					resp_len -=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+				}
+				memcpy(pmpriv->adapter, &misc->param.cust_ie,
+				       cust_ie,
+				       MIN(sizeof(mlan_ds_misc_custom_ie) -
+					   sizeof(tlvbuf_max_mgmt_ie),
+					   (cust_ie->len +
+					    sizeof(MrvlIEtypesHeader_t))));
+				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(pmpriv->adapter,
+						       (t_u8 *)&misc->param.
+						       cust_ie + (cust_ie->len +
+								  sizeof
+								  (MrvlIEtypesHeader_t)),
+						       max_mgmt_ie,
+						       MIN(sizeof
+							   (tlvbuf_max_mgmt_ie),
+							   max_mgmt_ie->len +
+							   sizeof
+							   (MrvlIEtypesHeader_t)));
+					}
+				}
+			}
+		}
+	} else {		/* no ioctl: driver generated get/set */
+		switch (wlan_le16_to_cpu(tlv->header.type)) {
+		case TLV_TYPE_UAP_MAC_ADDRESS:
+			memcpy(pmpriv->adapter, pmpriv->curr_addr, tlv->mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			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,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action,
+		      IN t_u32 cmd_oid,
+		      IN pmlan_ioctl_req pioctl_buf, IN t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = &cmd->params.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 *)&psnmp_mib->oid;
+			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(IN pmlan_private pmpriv, IN 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(IN pmlan_private pmpriv, IN 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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(pmadapter, &data, psnmp_oid, 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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;
+		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,
+			IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, pcmd_sta_deauth->mac, deauth->mac_addr,
+	       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,
+			IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, pcmd_report_mic->mac, pdata_buf,
+	       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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action,
+			  IN t_u16 cmd_oid, IN 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		       pkey->mac_addr, 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+	       pkey->mac_addr, 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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wep.key,
+		       pkey->key_material, pkey->key_len);
+		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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.pn,
+		       pkey->pn, PN_SIZE);
+		pkey_material->key_param_set.key_params.wapi.key_len =
+			wlan_cpu_to_le16(MIN(WAPI_KEY_SIZE, pkey->key_len));
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.key,
+		       pkey->key_material, MIN(WAPI_KEY_SIZE, pkey->key_len));
+		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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.aes.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.aes.key,
+		       pkey->key_material, pkey->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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.cmac_aes.
+			       ipn, pkey->pn, SEQ_MAX_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+		pkey_material->key_param_set.key_params.cmac_aes.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.cmac_aes.key,
+		       pkey->key_material, pkey->key_len);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set CMAC AES Key\n");
+		goto done;
+	}
+	if (pkey->key_len == WPA_TKIP_KEY_LEN) {
+		if (pkey->
+		    key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.tkip.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.tkip.key,
+		       pkey->key_material, pkey->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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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;
+
+	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);
+		tlv = (MrvlIEtypes_sta_info_t *)((t_u8 *)sta_list +
+						 sizeof(HostCmd_DS_STA_LIST));
+		info->param.sta_list.sta_count =
+			MIN(info->param.sta_list.sta_count, MAX_NUM_CLIENTS);
+		for (i = 0; i < info->param.sta_list.sta_count; i++) {
+			memcpy(pmpriv->adapter,
+			       info->param.sta_list.info[i].mac_address,
+			       tlv->mac_address, MLAN_MAC_ADDR_LENGTH);
+			info->param.sta_list.info[i].power_mfg_status =
+				tlv->power_mfg_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(pmpriv->adapter,
+				       &(info->param.sta_list.info[i].stats),
+				       &(sta_ptr->stats), sizeof(sta_stats));
+			} else
+				info->param.sta_list.info[i].bandmode = 0xFF;
+			tlv++;
+		}
+	}
+
+	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;
+	priv->wmm_enabled = MFALSE;
+	priv->pkt_fwd = MFALSE;
+	priv->is_11n_enabled = MFALSE;
+
+	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 == 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 == 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(priv->adapter, &wmm_param_ie,
+				       ((t_u8 *)tlv + 2),
+				       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(priv->adapter, (t_u8 *)&pchan_band_info->bandcfg,
+			       (t_u8 *)&pchan_info->bandcfg, 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(priv->adapter, (t_u8 *)tx_pn,
+			       wapi_tlv->multicast_PN, PN_SIZE);
+			for (i = 0; i < 4; i++)
+				tx_pn[i] = mlan_ntohl(tx_pn[i]);
+			memcpy(priv->adapter, wapi_tlv->multicast_PN,
+			       (t_u8 *)tx_pn, PN_SIZE);
+			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(priv->adapter, pevent->event_buf,
+	       pmbuf->pbuf + pmbuf->data_offset + 6, 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(priv->adapter, &frame_control,
+			       (t_u8 *)&(mgmt_tlv->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(priv->adapter,
+				       pevent->event_buf + pevent->event_len,
+				       assoc_req_ie, ie_len);
+				pevent->event_len += ie_len;
+				break;
+			}
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+	PRINTM(MEVENT, "STA assoc event len=%d\n", pevent->event_len);
+	DBG_HEXDUMP(MCMD_D, "STA assoc event", pevent->event_buf,
+		    pevent->event_len);
+	wlan_recv_event(priv, pevent->event_id, pevent);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles repsonse of acs_scan.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_cmd_uap_acs_scan(IN pmlan_private pmpriv,
+			  const IN HostCmd_DS_COMMAND *resp,
+			  IN 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,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	HostCmd_DS_UAP_OPER_CTRL *poper_ctl =
+		(HostCmd_DS_UAP_OPER_CTRL *) & cmd->params.uap_oper_ctrl;
+	mlan_ds_bss *bss = (mlan_ds_bss *)pdata_buf;
+	mlan_uap_oper_ctrl *uap_oper_ctrl = &bss->param.ap_oper_ctrl;
+	Band_Config_t *bandcfg = MNULL;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_OPER_CTRL);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_UAP_OPER_CTRL) + S_DS_GEN);
+	poper_ctl->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		poper_ctl->ctrl = wlan_cpu_to_le16(uap_oper_ctrl->ctrl_value);
+		if (uap_oper_ctrl->ctrl_value == 2) {
+			poper_ctl->chan_opt =
+				wlan_cpu_to_le16(uap_oper_ctrl->chan_opt);
+			if (uap_oper_ctrl->chan_opt == 3) {
+				poper_ctl->channel_band.header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+				poper_ctl->channel_band.header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_channel_band_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				bandcfg = &poper_ctl->channel_band.bandcfg;
+				if (uap_oper_ctrl->channel > 14)
+					bandcfg->chanBand = BAND_5GHZ;
+				bandcfg->chanWidth = uap_oper_ctrl->band_cfg;
+				if (bandcfg->chanWidth)
+					bandcfg->chan2Offset =
+						wlan_get_second_channel_offset
+						(uap_oper_ctrl->channel);
+				bandcfg->scanMode = SCAN_MODE_MANUAL;
+				poper_ctl->channel_band.channel =
+					uap_oper_ctrl->channel;
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of uap operation control
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_oper_ctrl(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_UAP_OPER_CTRL *poper_ctl =
+		(HostCmd_DS_UAP_OPER_CTRL *) & resp->params.uap_oper_ctrl;
+	mlan_ds_bss *bss = MNULL;
+	mlan_uap_oper_ctrl *uap_oper_ctrl = MNULL;
+	Band_Config_t *bandcfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf && pioctl_buf->action == MLAN_ACT_GET) {
+		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+		uap_oper_ctrl =
+			(mlan_uap_oper_ctrl *) & bss->param.ap_oper_ctrl;
+		uap_oper_ctrl->ctrl_value = wlan_le16_to_cpu(poper_ctl->ctrl);
+		uap_oper_ctrl->chan_opt = wlan_le16_to_cpu(poper_ctl->chan_opt);
+		uap_oper_ctrl->channel = poper_ctl->channel_band.channel;
+		bandcfg = &poper_ctl->channel_band.bandcfg;
+		uap_oper_ctrl->band_cfg = bandcfg->chanWidth;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief	Check 11B support Rates
+ *
+ *
+ *  @param pmadapter	Private mlan adapter structure
+ *
+ *  @return MTRUE/MFALSE
+ *
+ */
+t_u8
+wlan_check_11B_support_rates(MrvlIEtypes_RatesParamSet_t *prates_tlv)
+{
+	int i;
+	t_u8 rate;
+	t_u8 ret = MTRUE;
+	for (i = 0; i < prates_tlv->header.len; i++) {
+		rate = prates_tlv->rates[i] & 0x7f;
+		if ((rate != 0x02) && (rate != 0x04)
+		    && (rate != 0x0b) && (rate != 0x16)) {
+			ret = MFALSE;
+			break;
+		}
+	}
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of sys_config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   cmd action
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_uap_cmd_add_station(pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN 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_StaFlag_t *pstaflag;
+
+	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(pmadapter, new_sta->peer_mac, bss->param.sta_info.peer_mac,
+	       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 TLV_TYPE_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 (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;
+		default:
+			break;
+		}
+		tlv_len = tlv->len;
+		tlv->type = wlan_cpu_to_le16(tlv->type);
+		tlv->len = wlan_cpu_to_le16(tlv->len);
+		memcpy(pmadapter, pos, (t_u8 *)tlv,
+		       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_11ac_enabled) {
+		if (pmpriv->uap_channel <= 14)
+			sta_ptr->bandmode = BAND_GAC;
+		else
+			sta_ptr->bandmode = BAND_AAC;
+	} else 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;
+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(IN t_void *priv,
+			 IN t_u16 cmd_no,
+			 IN t_u16 cmd_action,
+			 IN t_u32 cmd_oid,
+			 IN t_void *pioctl_buf,
+			 IN t_void *pdata_buf, IN 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);
+		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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		ret = wlan_cmd_sdio_gpio_int(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_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;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, pdata_buf);
+		break;
+	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_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);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		cmd_ptr->command =
+			wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) +
+					 S_DS_GEN);
+		pmpriv->tx_rate = 0;
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_cmd_wifi_direct_mode(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+	case HOST_CMD_P2P_PARAMS_CONFIG:
+		ret = wlan_cmd_p2p_params_config(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_RF_ANTENNA:
+		ret = wlan_cmd_802_11_rf_antenna(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_cmd_11ac_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_802_11_EEPROM_ACCESS:
+		ret = wlan_cmd_reg_access(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;
+	case HostCmd_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_cmd_multi_chan_cfg(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_cmd_multi_chan_policy(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_cmd_drcs_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+#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_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;
+
+#ifdef STA_SUPPORT
+	case HostCmd_CMD_ACS:
+		ret = wlan_cmd_acs(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+#endif
+	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_FW_DUMP_EVENT:
+		ret = wlan_cmd_fw_dump_event(pmpriv, cmd_ptr, cmd_action,
+					     pdata_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;
+	case HostCmd_CHANNEL_TRPC_CONFIG:
+		ret = wlan_cmd_get_chan_trpc_config(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(IN t_void *priv,
+			     IN t_u16 cmdresp_no,
+			     IN t_void *pcmd_buf, IN 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;
+	int ctr;
+	const mlan_sdio_device *psdio_device = pmadapter->psdio_device;
+	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);
+		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;
+		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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		break;
+	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;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_ret_sdio_rx_aggr_cfg(pmpriv, resp);
+		break;
+	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_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);
+		pmadapter->tx_buf_size =
+			(pmadapter->tx_buf_size / MLAN_SDIO_BLOCK_SIZE) *
+			MLAN_SDIO_BLOCK_SIZE;
+		pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+		pmadapter->mp_end_port =
+			wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port);
+		pmadapter->mp_data_port_mask =
+			psdio_device->reg->data_port_mask;
+
+		for (ctr = 1;
+		     ctr <= psdio_device->max_ports - pmadapter->mp_end_port;
+		     ctr++) {
+			pmadapter->mp_data_port_mask &=
+				~(1 << (psdio_device->max_ports - ctr));
+		}
+
+		if (psdio_device->supports_sdio_new_mode) {
+			pmadapter->curr_wr_port = 0;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+			pmadapter->mpa_tx.pkt_aggr_limit =
+				MIN(psdio_device->mp_aggr_pkt_limit,
+				    (pmadapter->mp_end_port >> 1));
+#endif
+		} else {
+			pmadapter->curr_wr_port = 1;
+		}
+		PRINTM(MCMND, "end port %d, data port mask %x\n",
+		       wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port),
+		       pmadapter->mp_data_port_mask);
+		PRINTM(MCMND, "max_tx_buf_size=%d, tx_buf_size=%d\n",
+		       pmadapter->max_tx_buf_size, pmadapter->tx_buf_size);
+		break;
+	case HostCmd_CMD_AMSDU_AGGR_CTRL:
+		ret = wlan_ret_amsdu_aggr_ctrl(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11N_CFG:
+		ret = wlan_ret_11n_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_REJECT_ADDBA_REQ:
+		ret = wlan_ret_reject_addba_req(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_BF_CFG:
+		ret = wlan_ret_tx_bf_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_VERSION_EXT:
+		ret = wlan_ret_ver_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RX_MGMT_IND:
+		ret = wlan_ret_rx_mgmt_ind(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_CFG_TX_DATA_PAUSE:
+		ret = wlan_uap_ret_txdatapause(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_RADIO_CONTROL:
+		ret = wlan_ret_802_11_radio_control(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_RATE_CFG:
+		ret = wlan_ret_tx_rate_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		ret = wlan_ret_802_11_tx_rate_query(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_ret_remain_on_channel(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_ret_wifi_direct_mode(pmpriv, resp, pioctl_buf);
+		break;
+	case HOST_CMD_P2P_PARAMS_CONFIG:
+		ret = wlan_ret_p2p_params_config(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_RF_ANTENNA:
+		ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_ret_11ac_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_802_11_EEPROM_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;
+	case HostCmd_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_ret_multi_chan_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_ret_multi_chan_policy(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_ret_drcs_cfg(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_802_11_PS_INACTIVITY_TIMEOUT:
+		break;
+	case HostCmd_CMD_GET_TSF:
+		ret = wlan_ret_get_tsf(pmpriv, resp, pioctl_buf);
+		break;
+
+#ifdef STA_SUPPORT
+	case HostCmd_CMD_ACS:
+		ret = wlan_ret_acs(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		ret = wlan_ret_chan_region_cfg(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;
+	case HostCmd_CHANNEL_TRPC_CONFIG:
+		ret = wlan_ret_get_chan_trpc_config(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(IN 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;
+
+	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(pmadapter, pmpriv->curr_addr, pmadapter->event_body + 2,
+		       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);
+		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->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(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(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(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		sta_ptr = wlan_add_station_entry(pmpriv, sta_addr);
+		PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_ASSOC " MACSTR "\n",
+		       MAC2STR(sta_addr));
+		if (!sta_ptr)
+			break;
+		if (pmpriv->is_11n_enabled) {
+			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);
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + 4, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		memcpy(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		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));
+		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(MEVENT, "EVENT: Radar Detected\n");
+
+		/* 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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		pevent->event_id = 0;	/* clear to avoid resending at end of fcn */
+
+		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,
+							MNULL);
+			} else {
+				PRINTM(MEVENT,
+				       "Ignore Event Radar Detected - handling"
+				       " already in progress.\n");
+			}
+		} else {
+
+#ifdef DFS_TESTING_SUPPORT
+			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 {
+#endif
+				pmpriv->intf_state_11h.tx_disabled = MTRUE;
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_FW_RADAR_DETECTED,
+						MNULL);
+
+#ifdef DFS_TESTING_SUPPORT
+			}
+#endif
+		}
+
+		break;
+	case EVENT_CHANNEL_REPORT_RDY:
+		PRINTM(MEVENT, "EVENT: Channel Report Ready\n");
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause),
+		       pevent->event_len);
+		/* Handle / pass event data, and free buffer */
+		ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent);
+
+		if (pmpriv->intf_state_11h.is_11h_host) {
+			*((t_u8 *)pevent->event_buf) =
+				pmpriv->adapter->state_dfs.dfs_radar_found;
+			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(MEVENT, "EVENT: CHANNEL_SWITCH new channel %d\n",
+		       channel);
+		pmpriv->uap_channel = channel;
+
+		if ((pmpriv->adapter->state_rdh.stage != RDH_OFF &&
+		     !pmpriv->intf_state_11h.is_11h_host)
+#ifdef DFS_TESTING_SUPPORT
+		    || pmpriv->adapter->dfs_test_params.
+		    no_channel_change_on_radar ||
+		    pmpriv->adapter->dfs_test_params.fixed_new_channel_on_radar
+#endif
+			) {
+			/* 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(pmadapter, (t_u8 *)&pchan_band_info->bandcfg,
+			       (t_u8 *)&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;
+#ifdef WIFI_DIRECT_SUPPORT
+	case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+		PRINTM(MEVENT, "EVENT: REMAIN_ON_CHANNEL_EXPIRED reason=%d\n",
+		       *(t_u16 *)pmadapter->event_body);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL);
+		pevent->event_id = MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED;
+		break;
+#endif
+	case EVENT_MULTI_CHAN_INFO:
+		PRINTM(MEVENT, "EVENT: MULTI_CHAN_INFO\n");
+		wlan_handle_event_multi_chan_info(pmpriv, pmbuf);
+		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(pmadapter,
+		       (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause),
+		       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_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:
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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 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(IN t_void *priv, IN 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;
+		}
+	}
+
+	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 100644
index 0000000..6f20c85
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_uap_ioctl.c
@@ -0,0 +1,2163 @@
+/** @file mlan_uap_ioctl.c
+ *
+ *  @brief This file contains the handling of AP mode ioctls
+ *
+ *  Copyright (C) 2009-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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_sdio.h"
+#include "mlan_11n.h"
+#include "mlan_fw.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+			Global Variables
+********************************************************/
+extern t_u8 tos_to_tid_inv[];
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief Stop BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_stop(IN pmlan_adapter pmadapter,
+			IN 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 (!priv->adapter->mc_policy &&
+	    (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(IN 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,
+							   pmpriv->
+							   uap_state_chan_cb.
+							   bandcfg,
+							   &puap_state_chan_cb->
+							   channel);
+
+			if (ret == MLAN_STATUS_SUCCESS) {
+
+				wlan_11h_update_bandcfg(&pmpriv->
+							uap_state_chan_cb.
+							bandcfg,
+							puap_state_chan_cb->
+							channel);
+				PRINTM(MCMD_D,
+				       "NOP: uap band config:0x%x  channel=%d\n",
+				       pmpriv->uap_state_chan_cb.bandcfg,
+				       puap_state_chan_cb->channel);
+
+				ret = wlan_uap_set_channel(pmpriv,
+							   pmpriv->
+							   uap_state_chan_cb.
+							   bandcfg,
+							   puap_state_chan_cb->
+							   channel);
+				if (ret == MLAN_STATUS_SUCCESS) {
+					if (under_nop) {
+						PRINTM(MMSG,
+						       "Channel %d under NOP,"
+						       " switched to new channel %d successfully.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					} else {
+						PRINTM(MMSG,
+						       "Radar found on channel %d,"
+						       " switched to new channel %d successfully.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					}
+				} else {
+					if (under_nop) {
+						PRINTM(MMSG,
+						       "Channel %d under NOP,"
+						       " switch to new channel %d failed.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					} else {
+						PRINTM(MMSG,
+						       "Radar found on channel %d,"
+						       " switch to new channel %d failed.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					}
+					pcb->moal_ioctl_complete(pmpriv->
+								 adapter->
+								 pmoal_handle,
+								 puap_state_chan_cb->
+								 pioctl_req_curr,
+								 MLAN_STATUS_FAILURE);
+					goto done;
+				}
+			} else {
+				if (under_nop) {
+					PRINTM(MMSG,
+					       "Channel %d under NOP, no switch channel available.\n",
+					       old_channel);
+				} else {
+					PRINTM(MMSG,
+					       "Radar found on channel %d, no switch channel available.\n",
+					       old_channel);
+				}
+				/* No command sent with the ioctl, need manually signal completion */
+				pcb->moal_ioctl_complete(pmpriv->adapter->
+							 pmoal_handle,
+							 puap_state_chan_cb->
+							 pioctl_req_curr,
+							 MLAN_STATUS_FAILURE);
+				goto done;
+			}
+		} else {
+			PRINTM(MINFO, "No Radar found on channel %d\n",
+			       puap_state_chan_cb->channel);
+		}
+	}
+
+prep_bss_start:
+	/* else okay to send command:  not DFS channel or no radar */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_APCMD_BSS_START,
+			       HostCmd_ACT_GEN_SET,
+			       0,
+			       (t_void *)puap_state_chan_cb->pioctl_req_curr,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+done:
+	puap_state_chan_cb->pioctl_req_curr = MNULL;	/* prevent re-use */
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Start BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+/**
+ *  @sa         wlan_uap_callback_bss_ioctl_start
+ */
+static mlan_status
+wlan_uap_bss_ioctl_start(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			 IN 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 =
+		pmadapter->psdio_device->ampdu_info->ampdu_uap_txwinsize;
+	pmpriv->add_ba_param.rx_win_size =
+		pmadapter->psdio_device->ampdu_info->ampdu_uap_rxwinsize;
+	pmpriv->user_rxwinsize = pmpriv->add_ba_param.rx_win_size;
+
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		pmpriv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i];
+		pmpriv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i];
+		pmpriv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+	}
+	pmpriv->aggr_prio_tbl[6].ampdu_user =
+		pmpriv->aggr_prio_tbl[7].ampdu_user = BA_STREAM_NOT_ALLOWED;
+	pmpriv->addba_reject[6] =
+		pmpriv->addba_reject[7] = ADDBA_RSP_STATUS_REJECT;
+
+	/* hs_configured, hs_activated are reset by main loop */
+	pmadapter->hs_cfg.conditions = HOST_SLEEP_DEF_COND;
+	pmadapter->hs_cfg.gpio = HOST_SLEEP_DEF_GPIO;
+	pmadapter->hs_cfg.gap = HOST_SLEEP_DEF_GAP;
+
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_APCMD_SYS_RESET,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+*  @brief This function to process add station.
+*
+*  @param pmadapter       A pointer to pmadapter.
+*
+*  @param pioctl_req      A pointer to pioctl_req
+*
+*  @return            	  MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+*/
+mlan_status
+wlan_uap_bss_ioctl_add_station(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+		       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(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get scan channels
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_scan_channels(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get UAP channel
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_channel(IN pmlan_adapter pmadapter,
+			       IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get UAP operation control vaule
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_oper_ctrl(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pmadapter->fw_ver == HOST_API_VERSION_V15
+	    && pmadapter->fw_min_ver >= FW_MINOR_VERSION_1) {
+		bss = (mlan_ds_bss *)pioctl_req->pbuf;
+		if (pioctl_req->action == MLAN_ACT_SET)
+			cmd_action = HostCmd_ACT_GEN_SET;
+		else
+			cmd_action = HostCmd_ACT_GEN_GET;
+		/* Send request to firmware */
+		ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_OPER_CTRL,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       (t_void *)pioctl_req->pbuf);
+
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	} else {
+		PRINTM(MMSG, "FW don't support uap oper ctrl\n");
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Uap statistics
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_get_stats(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			      IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	const t_u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	sta_node *sta_ptr = MNULL;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pmpriv->uap_host_based & UAP_FLAG_HOST_MLME) {
+		if (memcmp
+		    (pmpriv->adapter, bss->param.deauth_param.mac_addr, bc_mac,
+		     MLAN_MAC_ADDR_LENGTH)) {
+			sta_ptr =
+				wlan_get_station_entry(pmpriv,
+						       bss->param.deauth_param.
+						       mac_addr);
+			if (!sta_ptr) {
+				PRINTM(MCMND,
+				       "Skip deauth to station " MACSTR "\n",
+				       MAC2STR(bss->param.deauth_param.
+					       mac_addr));
+				LEAVE();
+				return ret;
+			}
+		}
+	}
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_APCMD_STA_DEAUTH,
+			       HostCmd_ACT_GEN_SET,
+			       0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&bss->param.deauth_param);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get station list
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_get_sta_list(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(priv->adapter, priv->wapi_ie, misc->param.gen_ie.ie_data,
+		       misc->param.gen_ie.len);
+		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(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;
+	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(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_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(IN pmlan_adapter pmadapter,
+				    IN 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(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_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;
+	}
+	wlan_reset_pn_value(pmpriv, &sec->param.encrypt_key);
+	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(IN pmlan_adapter pmadapter, IN 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(pmadapter, &info->param.bss_info.bssid, pmpriv->curr_addr,
+	       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(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_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 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(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_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(IN 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(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];
+
+	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(IN 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(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_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) {
+#ifdef DFS_TESTING_SUPPORT
+			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;
+			}
+#endif
+			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(IN 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_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);
+		}
+	}
+
+	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;
+
+	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(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_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(IN pmlan_adapter pmadapter,
+			    IN 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(IN 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(IN pmlan_private pmpriv,
+		     IN Band_Config_t uap_band_cfg, IN 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(IN pmlan_private pmpriv)
+{
+	t_u8 tlv_buffer[sizeof(MrvlIEtypes_beacon_period_t) +
+			sizeof(MrvlIEtypes_dtim_period_t)];
+	MrvlIEtypes_beacon_period_t *ptlv_beacon_pd;
+	MrvlIEtypes_dtim_period_t *ptlv_dtim_pd;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(pmpriv->adapter, &tlv_buffer, 0, sizeof(tlv_buffer));
+	ptlv_beacon_pd = (MrvlIEtypes_beacon_period_t *)tlv_buffer;
+	ptlv_beacon_pd->header.type = TLV_TYPE_UAP_BEACON_PERIOD;
+	ptlv_beacon_pd->header.len = sizeof(MrvlIEtypes_beacon_period_t)
+		- sizeof(MrvlIEtypesHeader_t);
+
+	ptlv_dtim_pd = (MrvlIEtypes_dtim_period_t *)(tlv_buffer
+						     +
+						     sizeof
+						     (MrvlIEtypes_beacon_period_t));
+	ptlv_dtim_pd->header.type = TLV_TYPE_UAP_DTIM_PERIOD;
+	ptlv_dtim_pd->header.len = sizeof(MrvlIEtypes_dtim_period_t)
+		- sizeof(MrvlIEtypesHeader_t);
+
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, tlv_buffer);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get deauth control.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_uap_snmp_mib_ctrl_deauth(IN pmlan_adapter pmadapter,
+			      IN 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_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)
+	mlan_ds_scan *pscan;
+#endif
+
+	ENTER();
+
+	switch (pioctl_req->req_id) {
+	case MLAN_IOCTL_BSS:
+		bss = (mlan_ds_bss *)pioctl_req->pbuf;
+		if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR)
+			status = wlan_uap_bss_ioctl_mac_address(pmadapter,
+								pioctl_req);
+		else if (bss->sub_command == MLAN_OID_BSS_STOP)
+			status = wlan_uap_bss_ioctl_stop(pmadapter, pioctl_req);
+		else if (bss->sub_command == MLAN_OID_BSS_START)
+			status = wlan_uap_bss_ioctl_start(pmadapter,
+							  pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_BSS_CONFIG)
+			status = wlan_uap_bss_ioctl_config(pmadapter,
+							   pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_DEAUTH_STA)
+			status = wlan_uap_bss_ioctl_deauth_sta(pmadapter,
+							       pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_BSS_RESET)
+			status = wlan_uap_bss_ioctl_reset(pmadapter,
+							  pioctl_req);
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		else if (bss->sub_command == MLAN_OID_BSS_ROLE) {
+			util_enqueue_list_tail(pmadapter->pmoal_handle,
+					       &pmadapter->ioctl_pending_q,
+					       (pmlan_linked_list)pioctl_req,
+					       pmadapter->callbacks.
+					       moal_spin_lock,
+					       pmadapter->callbacks.
+					       moal_spin_unlock);
+			pmadapter->pending_ioctl = MTRUE;
+			status = MLAN_STATUS_PENDING;
+		}
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		else if (bss->sub_command == MLAN_OID_WIFI_DIRECT_MODE)
+			status = wlan_bss_ioctl_wifi_direct_mode(pmadapter,
+								 pioctl_req);
+#endif
+		else if (bss->sub_command == MLAN_OID_BSS_REMOVE)
+			status = wlan_bss_ioctl_bss_remove(pmadapter,
+							   pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_CFG_WMM_PARAM)
+			status = wlan_uap_bss_ioctl_uap_wmm_param(pmadapter,
+								  pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_SCAN_CHANNELS)
+			status = wlan_uap_bss_ioctl_uap_scan_channels(pmadapter,
+								      pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_CHANNEL)
+			status = wlan_uap_bss_ioctl_uap_channel(pmadapter,
+								pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_ACS_SCAN)
+			status = wlan_uap_bss_ioctl_acs_scan(pmadapter,
+							     pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_OPER_CTRL)
+			status = wlan_uap_bss_ioctl_uap_oper_ctrl(pmadapter,
+								  pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_ADD_STATION)
+			status = wlan_uap_bss_ioctl_add_station(pmadapter,
+								pioctl_req);
+
+		break;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	case MLAN_IOCTL_SCAN:
+		pscan = (mlan_ds_scan *)pioctl_req->pbuf;
+		if ((pscan->sub_command == MLAN_OID_SCAN_NORMAL) &&
+		    (pioctl_req->action == MLAN_ACT_GET)) {
+			PRINTM(MIOCTL, "Get scan table in uap\n");
+			pscan->param.scan_resp.pscan_table =
+				(t_u8 *)pmadapter->pscan_table;
+			pscan->param.scan_resp.num_in_scan_table =
+				pmadapter->num_in_scan_table;
+			pscan->param.scan_resp.age_in_secs =
+				pmadapter->age_in_secs;
+			pioctl_req->data_read_written =
+				sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
+			pscan->param.scan_resp.pchan_stats =
+				(t_u8 *)pmadapter->pchan_stats;
+			pscan->param.scan_resp.num_in_chan_stats =
+				pmadapter->num_in_chan_stats;
+		}
+		break;
+#endif
+	case MLAN_IOCTL_GET_INFO:
+		pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
+		if (pget_info->sub_command == MLAN_OID_GET_VER_EXT)
+			status = wlan_get_info_ver_ext(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_DEBUG_INFO)
+			status = wlan_get_info_debug_info(pmadapter,
+							  pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_STATS)
+			status = wlan_uap_get_stats(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_UAP_STATS_LOG)
+			status = wlan_uap_get_stats_log(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_UAP_STA_LIST)
+			status = wlan_uap_get_sta_list(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_BSS_INFO)
+			status = wlan_uap_get_bss_info(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_FW_INFO) {
+			pioctl_req->data_read_written =
+				sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
+			memcpy(pmadapter, &pget_info->param.fw_info.mac_addr,
+			       pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
+			pget_info->param.fw_info.fw_ver =
+				pmadapter->fw_release_number;
+			pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+			pget_info->param.fw_info.ecsa_enable =
+				pmadapter->ecsa_enable;
+			pget_info->param.fw_info.getlog_enable =
+				pmadapter->getlog_enable;
+			pget_info->param.fw_info.hw_dev_mcs_support =
+				pmadapter->hw_dev_mcs_support;
+			pget_info->param.fw_info.hw_dot_11n_dev_cap =
+				pmadapter->hw_dot_11n_dev_cap;
+			pget_info->param.fw_info.usr_dev_mcs_support =
+				pmpriv->usr_dev_mcs_support;
+			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.region_code =
+				pmadapter->region_code;
+			pget_info->param.fw_info.fw_supplicant_support =
+				IS_FW_SUPPORT_SUPPLICANT(pmadapter) ? 0x01 :
+				0x00;
+			pget_info->param.fw_info.antinfo = pmadapter->antinfo;
+			pget_info->param.fw_info.max_ap_assoc_sta =
+				pmadapter->max_sta_conn;
+		}
+		break;
+	case MLAN_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);
+		if (misc->sub_command == MLAN_OID_MISC_MULTI_CHAN_CFG)
+			status = wlan_misc_ioctl_multi_chan_config(pmadapter,
+								   pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_MULTI_CHAN_POLICY)
+			status = wlan_misc_ioctl_multi_chan_policy(pmadapter,
+								   pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_DRCS_CFG)
+			status = wlan_misc_ioctl_drcs_config(pmadapter,
+							     pioctl_req);
+#ifdef RX_PACKET_COALESCE
+		if (misc->sub_command == MLAN_OID_MISC_RX_PACKET_COALESCE)
+			status = wlan_misc_ioctl_rx_pkt_coalesce_config
+				(pmadapter, pioctl_req);
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		if (misc->sub_command == MLAN_OID_MISC_WIFI_DIRECT_CONFIG)
+			status = wlan_misc_p2p_config(pmadapter, pioctl_req);
+#endif
+
+		if (misc->sub_command == MLAN_OID_MISC_DFS_REAPTER_MODE) {
+			mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+			misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+			misc_cfg->param.dfs_repeater.mode =
+				pmadapter->dfs_repeater;
+			pioctl_req->data_read_written =
+				sizeof(mlan_ds_misc_dfs_repeater);
+
+			status = MLAN_STATUS_SUCCESS;
+		}
+		if (misc->sub_command == MLAN_OID_MISC_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_FW_DUMP_EVENT)
+			status = wlan_misc_ioctl_fw_dump_event(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_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);
+#ifdef STA_SUPPORT
+		if (misc->sub_command == MLAN_OID_MISC_ACS)
+			status = wlan_misc_acs(pmadapter, pioctl_req);
+#endif
+		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_GET_REGIONPWR_CFG)
+			status = wlan_get_rgchnpwr_cfg(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 defined(DFS_TESTING_SUPPORT)
+		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);
+#endif
+		if (cfg11h->sub_command == MLAN_OID_11H_CHAN_REPORT_REQUEST)
+			status = wlan_11h_ioctl_dfs_cancel_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);
+		break;
+	case MLAN_IOCTL_RADIO_CFG:
+		radiocfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+		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_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;
+		status = 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 100644
index 0000000..9e222c4
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_uap_txrx.c
@@ -0,0 +1,694 @@
+/** @file mlan_uap_txrx.c
+ *
+ *  @brief This file contains AP mode transmit and receive functions
+ *
+ *  Copyright (C) 2009-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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_sdio.h"
+#include "mlan_wmm.h"
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+			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
+	UapRxPD *prx_pd;
+	ENTER();
+	prx_pd = (UapRxPD *)(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(UapRxPD), 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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	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(IN t_void *priv, IN pmlan_buffer pmbuf)
+{
+	pmlan_private pmpriv = (pmlan_private)priv;
+	UapTxPD *plocal_tx_pd;
+	t_u8 *head_ptr = MNULL;
+	t_u32 pkt_type;
+	t_u32 tx_control;
+
+	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(pmpriv->adapter, &pkt_type,
+		       pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type));
+		memcpy(pmpriv->adapter, &tx_control,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+		       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(UapTxPD) + pmpriv->intf_hr_len +
+				  DMA_ALIGNMENT)) {
+		PRINTM(MERROR,
+		       "not enough space for UapTxPD: headroom=%d pkt_len=%d, required=%d\n",
+		       pmbuf->data_offset, pmbuf->data_len,
+		       sizeof(UapTxPD) + 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(UapTxPD) -
+		pmpriv->intf_hr_len;
+	head_ptr = (t_u8 *)((t_ptr)head_ptr & ~((t_ptr)(DMA_ALIGNMENT - 1)));
+
+	plocal_tx_pd = (UapTxPD *)(head_ptr + pmpriv->intf_hr_len);
+	memset(pmpriv->adapter, plocal_tx_pd, 0, sizeof(UapTxPD));
+
+	/* 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;
+	}
+
+	uap_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(IN t_void *adapter, IN pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	UapRxPD *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;
+	t_u8 adj_rx_rate = 0;
+	t_u8 antenna = 0;
+	t_u32 last_rx_sec = 0;
+	t_u32 last_rx_usec = 0;
+
+	ENTER();
+
+	prx_pd = (UapRxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	/* Endian conversion */
+	uap_endian_convert_RxPD(prx_pd);
+	priv->rxpd_rate = prx_pd->rx_rate;
+
+	priv->rxpd_rate_info = prx_pd->rate_info;
+	if (!priv->adapter->psdio_device->v15_fw_api)
+		priv->rxpd_rate_info =
+			wlan_convert_v14_rate_ht_info(priv->rxpd_rate_info);
+
+	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);
+	}
+
+	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;
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		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);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		goto done;
+	}
+
+	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;
+	}
+
+	pmbuf->priority = prx_pd->priority;
+	memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+	       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;
+	}
+	/* 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)) {
+		wlan_free_mlan_buffer(pmadapter, 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_uap_recv_packet(IN mlan_private *priv, IN 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(UapTxPD) + 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(pmadapter,
+				       (t_u8 *)newbuf->pbuf +
+				       newbuf->data_offset,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pmbuf->data_len);
+				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(UapTxPD) + 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(pmadapter,
+				       (t_u8 *)newbuf->pbuf +
+				       newbuf->data_offset,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pmbuf->data_len);
+				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(IN mlan_private *priv, IN pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	UapRxPD *prx_pd;
+	RxPacketHdr_t *prx_pkt;
+	pmlan_buffer newbuf = MNULL;
+
+	ENTER();
+
+	prx_pd = (UapRxPD *)(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(UapRxPD), 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(UapTxPD) + 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(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);
+				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 */
+			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;
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+			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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+done:
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_util.h b/wlan_sd8987/mlan/mlan_util.h
new file mode 100644
index 0000000..d80d112
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_util.h
@@ -0,0 +1,537 @@
+/** @file mlan_util.h
+ *
+ *  @brief This file contains wrappers for linked-list,
+ *  spinlock and timer defines.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    10/28/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_UTIL_H_
+#define _MLAN_UTIL_H_
+
+/** Circular doubly linked list */
+typedef struct _mlan_linked_list {
+    /** Pointer to previous node */
+	struct _mlan_linked_list *pprev;
+    /** Pointer to next node */
+	struct _mlan_linked_list *pnext;
+} mlan_linked_list, *pmlan_linked_list;
+
+/** List head */
+typedef struct _mlan_list_head {
+    /** Pointer to previous node */
+	struct _mlan_linked_list *pprev;
+    /** Pointer to next node */
+	struct _mlan_linked_list *pnext;
+    /** Pointer to lock */
+	t_void *plock;
+} mlan_list_head, *pmlan_list_head;
+
+/**
+ *  @brief This function initializes a list without locking
+ *
+ *  @param phead		List head
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_init_list(pmlan_linked_list phead)
+{
+	/* Both next and prev point to self */
+	phead->pprev = phead->pnext = (pmlan_linked_list)phead;
+}
+
+/**
+ *  @brief This function initializes a list
+ *
+ *  @param phead		List head
+ *  @param lock_required	A flag for spinlock requirement
+ *  @param moal_init_lock	A pointer to init lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_init_list_head(t_void *pmoal_handle,
+		    pmlan_list_head phead,
+		    t_u8 lock_required,
+		    mlan_status (*moal_init_lock) (t_void *handle,
+						   t_void **pplock))
+{
+	/* Both next and prev point to self */
+	util_init_list((pmlan_linked_list)phead);
+	if (lock_required)
+		moal_init_lock(pmoal_handle, &phead->plock);
+	else
+		phead->plock = 0;
+}
+
+/**
+ *  @brief This function frees a list
+ *
+ *  @param phead		List head
+ *  @param moal_free_lock	A pointer to free lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_free_list_head(t_void *pmoal_handle,
+		    pmlan_list_head phead,
+		    mlan_status (*moal_free_lock) (t_void *handle,
+						   t_void *plock))
+{
+	phead->pprev = phead->pnext = 0;
+	if (phead->plock)
+		moal_free_lock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function peeks into a list
+ *
+ *  @param phead		List head
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			List node
+ */
+static INLINE pmlan_linked_list
+util_peek_list(t_void *pmoal_handle,
+	       pmlan_list_head phead,
+	       mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+	       mlan_status (*moal_spin_unlock) (t_void *handle, t_void *plock))
+{
+	pmlan_linked_list pnode = 0;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	if (phead->pnext != (pmlan_linked_list)phead)
+		pnode = phead->pnext;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+	return pnode;
+}
+
+/**
+ *  @brief This function queues a node at the list tail
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to queue
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_enqueue_list_tail(t_void *pmoal_handle,
+		       pmlan_list_head phead,
+		       pmlan_linked_list pnode,
+		       mlan_status (*moal_spin_lock) (t_void *handle,
+						      t_void *plock),
+		       mlan_status (*moal_spin_unlock) (t_void *handle,
+							t_void *plock))
+{
+	pmlan_linked_list pold_last;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pold_last = phead->pprev;
+	pnode->pprev = pold_last;
+	pnode->pnext = (pmlan_linked_list)phead;
+
+	phead->pprev = pold_last->pnext = pnode;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function adds a node at the list head
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to add
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_enqueue_list_head(t_void *pmoal_handle,
+		       pmlan_list_head phead,
+		       pmlan_linked_list pnode,
+		       mlan_status (*moal_spin_lock) (t_void *handle,
+						      t_void *plock),
+		       mlan_status (*moal_spin_unlock) (t_void *handle,
+							t_void *plock))
+{
+	pmlan_linked_list pold_first;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pold_first = phead->pnext;
+	pnode->pprev = (pmlan_linked_list)phead;
+	pnode->pnext = pold_first;
+
+	phead->pnext = pold_first->pprev = pnode;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function removes a node from the list
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to remove
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_unlink_list(t_void *pmoal_handle,
+		 pmlan_list_head phead,
+		 pmlan_linked_list pnode,
+		 mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		 mlan_status (*moal_spin_unlock) (t_void *handle,
+						  t_void *plock))
+{
+	pmlan_linked_list pmy_prev;
+	pmlan_linked_list pmy_next;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pmy_prev = pnode->pprev;
+	pmy_next = pnode->pnext;
+	pmy_next->pprev = pmy_prev;
+	pmy_prev->pnext = pmy_next;
+
+	pnode->pnext = pnode->pprev = 0;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function dequeues a node from the list
+ *
+ *  @param phead		List head
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			List node
+ */
+static INLINE pmlan_linked_list
+util_dequeue_list(t_void *pmoal_handle,
+		  pmlan_list_head phead,
+		  mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		  mlan_status (*moal_spin_unlock) (t_void *handle,
+						   t_void *plock))
+{
+	pmlan_linked_list pnode;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pnode = phead->pnext;
+	if (pnode && (pnode != (pmlan_linked_list)phead))
+		util_unlink_list(pmoal_handle, phead, pnode, 0, 0);
+	else
+		pnode = 0;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+	return pnode;
+}
+
+/** Access controlled scalar variable */
+typedef struct _mlan_scalar {
+    /** Value */
+	t_s32 value;
+    /** Pointer to lock */
+	t_void *plock;
+    /** Control flags */
+	t_u32 flags;
+} mlan_scalar, *pmlan_scalar;
+
+/** Flag to scalar lock acquired */
+#define MLAN_SCALAR_FLAG_UNIQUE_LOCK	MBIT(16)
+
+/** scalar conditional value list */
+typedef enum _MLAN_SCALAR_CONDITIONAL {
+	MLAN_SCALAR_COND_EQUAL,
+	MLAN_SCALAR_COND_NOT_EQUAL,
+	MLAN_SCALAR_COND_GREATER_THAN,
+	MLAN_SCALAR_COND_GREATER_OR_EQUAL,
+	MLAN_SCALAR_COND_LESS_THAN,
+	MLAN_SCALAR_COND_LESS_OR_EQUAL
+} MLAN_SCALAR_CONDITIONAL;
+
+/**
+ *  @brief This function initializes a scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param val				Initial scalar value
+ *  @param plock_to_use		A new lock is created if NULL, else lock to use
+ *  @param moal_init_lock	A pointer to init lock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_init(t_void *pmoal_handle,
+		 pmlan_scalar pscalar,
+		 t_s32 val,
+		 t_void *plock_to_use,
+		 mlan_status (*moal_init_lock) (t_void *handle,
+						t_void **pplock))
+{
+	pscalar->value = val;
+	pscalar->flags = 0;
+	if (plock_to_use) {
+		pscalar->flags &= ~MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+		pscalar->plock = plock_to_use;
+	} else {
+		pscalar->flags |= MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+		moal_init_lock(pmoal_handle, &pscalar->plock);
+	}
+}
+
+/**
+ *  @brief This function frees a scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_free_lock	A pointer to free lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_scalar_free(t_void *pmoal_handle,
+		 pmlan_scalar pscalar,
+		 mlan_status (*moal_free_lock) (t_void *handle, t_void *plock))
+{
+	if (pscalar->flags & MLAN_SCALAR_FLAG_UNIQUE_LOCK)
+		moal_free_lock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function reads value from scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					Stored value
+ */
+static INLINE t_s32
+util_scalar_read(t_void *pmoal_handle,
+		 pmlan_scalar pscalar,
+		 mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		 mlan_status (*moal_spin_unlock) (t_void *handle,
+						  t_void *plock))
+{
+	t_s32 val;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	val = pscalar->value;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+	return val;
+}
+
+/**
+ *  @brief This function writes value to scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param val				Value to write
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_write(t_void *pmoal_handle,
+		  pmlan_scalar pscalar,
+		  t_s32 val,
+		  mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		  mlan_status (*moal_spin_unlock) (t_void *handle,
+						   t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value = val;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function increments the value in scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_increment(t_void *pmoal_handle,
+		      pmlan_scalar pscalar,
+		      mlan_status (*moal_spin_lock) (t_void *handle,
+						     t_void *plock),
+		      mlan_status (*moal_spin_unlock) (t_void *handle,
+						       t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value++;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function decrements the value in scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_decrement(t_void *pmoal_handle,
+		      pmlan_scalar pscalar,
+		      mlan_status (*moal_spin_lock) (t_void *handle,
+						     t_void *plock),
+		      mlan_status (*moal_spin_unlock) (t_void *handle,
+						       t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value--;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function adds an offset to the value in scalar,
+ *         and returns the new value
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param offset			Offset value (can be negative)
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					Value after offset
+ */
+static INLINE t_s32
+util_scalar_offset(t_void *pmoal_handle,
+		   pmlan_scalar pscalar,
+		   t_s32 offset,
+		   mlan_status (*moal_spin_lock) (t_void *handle,
+						  t_void *plock),
+		   mlan_status (*moal_spin_unlock) (t_void *handle,
+						    t_void *plock))
+{
+	t_s32 newval;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	newval = (pscalar->value += offset);
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+	return newval;
+}
+
+/**
+ *  @brief This function writes the value to the scalar
+ *         if existing value compared with other value is true.
+ *
+ *  @param pscalar          Pointer to scalar
+ *  @param condition        Condition to check
+ *  @param val_compare      Value to compare against current value
+ *                          ((A X B), where B = val_compare)
+ *  @param val_to_set       Value to set if comparison is true
+ *  @param moal_spin_lock   A pointer to spin lock handler
+ *  @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ *  @return                 Comparison result (MTRUE or MFALSE)
+ */
+static INLINE t_u8
+util_scalar_conditional_write(t_void *pmoal_handle,
+			      pmlan_scalar pscalar,
+			      MLAN_SCALAR_CONDITIONAL condition,
+			      t_s32 val_compare,
+			      t_s32 val_to_set,
+			      mlan_status (*moal_spin_lock) (t_void *handle,
+							     t_void *plock),
+			      mlan_status (*moal_spin_unlock) (t_void *handle,
+							       t_void *plock))
+{
+	t_u8 update;
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+
+	switch (condition) {
+	case MLAN_SCALAR_COND_EQUAL:
+		update = (pscalar->value == val_compare);
+		break;
+	case MLAN_SCALAR_COND_NOT_EQUAL:
+		update = (pscalar->value != val_compare);
+		break;
+	case MLAN_SCALAR_COND_GREATER_THAN:
+		update = (pscalar->value > val_compare);
+		break;
+	case MLAN_SCALAR_COND_GREATER_OR_EQUAL:
+		update = (pscalar->value >= val_compare);
+		break;
+	case MLAN_SCALAR_COND_LESS_THAN:
+		update = (pscalar->value < val_compare);
+		break;
+	case MLAN_SCALAR_COND_LESS_OR_EQUAL:
+		update = (pscalar->value <= val_compare);
+		break;
+	default:
+		update = MFALSE;
+		break;
+	}
+	if (update)
+		pscalar->value = val_to_set;
+
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+	return (update) ? MTRUE : MFALSE;
+}
+
+/**
+ *  @brief This function counts the bits of unsigned int number
+ *
+ *  @param num  number
+ *  @return     number of bits
+ */
+static INLINE t_u32
+bitcount(t_u32 num)
+{
+	t_u32 count = 0;
+	static t_u32 nibblebits[] = {
+		0, 1, 1, 2, 1, 2, 2, 3,
+		1, 2, 2, 3, 2, 3, 3, 4
+	};
+	for (; num != 0; num >>= 4)
+		count += nibblebits[num & 0x0f];
+	return count;
+}
+
+#endif /* !_MLAN_UTIL_H_ */
diff --git a/wlan_sd8987/mlan/mlan_wmm.c b/wlan_sd8987/mlan/mlan_wmm.c
new file mode 100644
index 0000000..17281c9
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_wmm.c
@@ -0,0 +1,3773 @@
+/** @file mlan_wmm.c
+ *
+ *  @brief This file contains functions for WMM.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/** Maximum value FW can accept for driver delay in packet transmission */
+#define DRV_PKT_DELAY_TO_FW_MAX   512
+
+/*
+ * Upper and Lower threshold for packet queuing in the driver
+
+ *    - When the number of packets queued reaches the upper limit,
+ *      the driver will stop the net queue in the app/kernel space.
+
+ *    - When the number of packets drops beneath the lower limit after
+ *      having reached the upper limit, the driver will restart the net
+ *      queue.
+ */
+
+/** Lower threshold for packet queuing in the driver.
+  * When the number of packets drops beneath the lower limit after having
+  * reached the upper limit, the driver will restart the net queue.
+  */
+#define WMM_QUEUED_PACKET_LOWER_LIMIT   180
+
+/** Upper threshold for packet queuing in the driver.
+  * When the number of packets queued reaches the upper limit, the driver
+  * will stop the net queue in the app/kernel space.
+  */
+#define WMM_QUEUED_PACKET_UPPER_LIMIT   200
+
+/** Offset for TOS field in the IP header */
+#define IPTOS_OFFSET 5
+
+/** WMM information IE */
+static const t_u8 wmm_info_ie[] = { WMM_IE, 0x07,
+	0x00, 0x50, 0xf2, 0x02,
+	0x00, 0x01, 0x00
+};
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _wmm_ac_e {
+	AC_BE,
+	AC_BK,
+	AC_VI,
+	AC_VO
+} MLAN_PACK_END wmm_ac_e;
+
+/**
+ * AC Priorities go from AC_BK to AC_VO.  The ACI enumeration for AC_BK (1)
+ *   is higher than the enumeration for AC_BE (0); hence the needed
+ *   mapping conversion for wmm AC to priority Queue Index
+ */
+static const t_u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE,
+	WMM_AC_BK,
+	WMM_AC_VI,
+	WMM_AC_VO
+};
+
+/**
+ * This table will be used to store the tid values based on ACs.
+ * It is initialized to default values per TID.
+ */
+t_u8 tos_to_tid[] = {
+	/* TID        DSCP_P2   DSCP_P1  DSCP_P0   WMM_AC   */
+	0x01,			/*    0         1        0       AC_BK   */
+	0x02,			/*    0         0        0       AC_BK   */
+	0x00,			/*    0         0        1       AC_BE   */
+	0x03,			/*    0         1        1       AC_BE   */
+	0x04,			/*    1         0        0       AC_VI   */
+	0x05,			/*    1         0        1       AC_VI   */
+	0x06,			/*    1         1        0       AC_VO   */
+	0x07			/*    1         1        1       AC_VO   */
+};
+
+/**
+ * This table inverses the tos_to_tid operation to get a priority
+ * which is in sequential order, and can be compared.
+ * Use this to compare the priority of two different TIDs.
+ */
+t_u8 tos_to_tid_inv[] = { 0x02,	/* from tos_to_tid[2] = 0 */
+	0x00,			/* from tos_to_tid[0] = 1 */
+	0x01,			/* from tos_to_tid[1] = 2 */
+	0x03,
+	0x04,
+	0x05,
+	0x06,
+	0x07
+};
+
+/**
+ * This table will provide the tid value for given ac. This table does not
+ * change and will be used to copy back the default values to tos_to_tid in
+ * case of disconnect.
+ */
+const t_u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} };
+
+/* Map of TOS UP values to WMM AC */
+static const mlan_wmm_ac_e tos_to_ac[] = { WMM_AC_BE,
+	WMM_AC_BK,
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VI,
+	WMM_AC_VO,
+	WMM_AC_VO
+};
+
+raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid,
+				    t_u8 *ra_addr);
+
+/********************************************************
+			Local Functions
+********************************************************/
+#ifdef DEBUG_LEVEL2
+/**
+ *  @brief Debug print function to display the priority parameters for a WMM AC
+ *
+ *  @param pac_param	Pointer to the AC parameters to display
+ *
+ *  @return		N/A
+ */
+static void
+wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t *pac_param)
+{
+	const char *ac_str[] = { "BK", "BE", "VI", "VO" };
+
+	ENTER();
+
+	PRINTM(MINFO, "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
+	       "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
+	       ac_str[wmm_aci_to_qidx_map[pac_param->aci_aifsn.aci]],
+	       pac_param->aci_aifsn.aci, pac_param->aci_aifsn.acm,
+	       pac_param->aci_aifsn.aifsn, pac_param->ecw.ecw_min,
+	       pac_param->ecw.ecw_max,
+	       wlan_le16_to_cpu(pac_param->tx_op_limit));
+
+	LEAVE();
+}
+
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param) wlan_wmm_ac_debug_print(pac_param)
+#else
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param)
+#endif
+
+/**
+ *  @brief Allocate route address
+ *
+ *  @param pmadapter       Pointer to the mlan_adapter structure
+ *  @param ra              Pointer to the route address
+ *
+ *  @return         ra_list
+ */
+static
+raListTbl *
+wlan_wmm_allocate_ralist_node(pmlan_adapter pmadapter, t_u8 *ra)
+{
+	raListTbl *ra_list = MNULL;
+
+	ENTER();
+
+	if (pmadapter->callbacks.
+	    moal_malloc(pmadapter->pmoal_handle, sizeof(raListTbl),
+			MLAN_MEM_DEF, (t_u8 **)&ra_list)) {
+		PRINTM(MERROR, "Fail to allocate ra_list\n");
+		goto done;
+	}
+	util_init_list((pmlan_linked_list)ra_list);
+	util_init_list_head((t_void *)pmadapter->pmoal_handle,
+			    &ra_list->buf_head, MFALSE,
+			    pmadapter->callbacks.moal_init_lock);
+
+	memcpy(pmadapter, ra_list->ra, ra, 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;
+#if defined(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;
+	}
+#if defined(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(MDATA, "Drop packets to unknown station\n");
+			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(priv->adapter, pout_buf, (t_u8 *)"TSPEC:", 6);
+	pout_buf += 6;
+
+	memcpy(priv->adapter, pout_buf, (t_u8 *)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(priv->adapter, pout_buf, (t_u8 *)"]:TID", 5);
+	pout_buf += 5;
+	*pout_buf++ = tid + '0';
+
+	memcpy(priv->adapter, pout_buf, (t_u8 *)":UP", 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 = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf,
+					     &tx_param);
+		switch (ret) {
+		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:
+			pmadapter->data_sent = MFALSE;
+			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 = -1;
+	int tid_add = -1;
+	int tid=0;
+
+	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 (!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);
+					memcpy(priv->adapter,ra, ptr->ra, sizeof(ra));
+					tid_add = tid;
+
+				}
+			} 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);
+				}
+			}
+		}
+		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);
+		}
+	}
+	if(tid_add >=0 && tid_add < 8)
+		wlan_send_addba(priv, tid_add, ra);
+	if(tid_del >=0 && tid_del < 8)
+		wlan_send_delba(priv, MNULL, tid_del, ra, 1);
+
+
+	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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       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
+#define BA_SETUP_PACKET_OFFSET          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) +
+		BA_SETUP_PACKET_OFFSET;
+	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);
+	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(pmadapter, tos_to_tid, ac_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;
+#if defined(UAP_SUPPORT)
+	priv->num_drop_pkts = 0;
+#endif
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	memset(pmadapter, pmadapter->mpa_tx_count, 0,
+	       sizeof(pmadapter->mpa_tx_count));
+	pmadapter->mpa_sent_no_ports = 0;
+	pmadapter->mpa_sent_last_pkt = 0;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	memset(pmadapter, pmadapter->mpa_rx_count, 0,
+	       sizeof(pmadapter->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 = BA_STREAM_NOT_ALLOWED;
+				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 =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_sta_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 =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_wfd_txrxwinsize;
+				priv->add_ba_param.rx_win_size =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_wfd_txrxwinsize;
+			}
+#endif
+#ifdef UAP_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+				priv->add_ba_param.tx_win_size =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_uap_txwinsize;
+				priv->add_ba_param.rx_win_size =
+					pmadapter->psdio_device->ampdu_info->
+					ampdu_uap_rxwinsize;
+			}
+#endif
+			priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
+			priv->add_ba_param.tx_amsdu = MFALSE;
+			priv->add_ba_param.rx_amsdu = MFALSE;
+			memset(priv->adapter, priv->rx_seq, 0xff,
+			       sizeof(priv->rx_seq));
+			wlan_wmm_default_queue_priorities(priv);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Setup the queue priorities and downgrade any queues as required
+ *         by the WMM info.  Setups default values if WMM is not active
+ *         for this association.
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         N/A
+ */
+void
+wlan_wmm_setup_queues(pmlan_private priv)
+{
+	ENTER();
+	wlan_wmm_setup_queue_priorities(priv, MNULL);
+	wlan_wmm_setup_ac_downgrade(priv);
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief  Send a command to firmware to retrieve the current WMM status
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         MLAN_STATUS_SUCCESS; MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_wmm_status_change(pmlan_private priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, 0, 0, 0,
+			       MNULL);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Check if wmm TX queue is empty
+ *
+ *  @param pmadapter  Pointer to the mlan_adapter driver data struct
+ *
+ *  @return         MFALSE if not empty; MTRUE if empty
+ */
+int
+wlan_wmm_lists_empty(pmlan_adapter pmadapter)
+{
+	int j;
+	pmlan_private priv;
+
+	ENTER();
+
+	for (j = 0; j < pmadapter->priv_num; ++j) {
+		priv = pmadapter->priv[j];
+		if (priv) {
+			if ((priv->port_ctrl_mode == MTRUE) &&
+			    (priv->port_open == MFALSE)) {
+				PRINTM(MINFO,
+				       "wmm_lists_empty: PORT_CLOSED Ignore pkts from BSS%d\n",
+				       j);
+				continue;
+			}
+			if (priv->tx_pause)
+				continue;
+
+			if (util_scalar_read(pmadapter->pmoal_handle,
+					     &priv->wmm.tx_pkts_queued,
+					     pmadapter->callbacks.
+					     moal_spin_lock,
+					     pmadapter->callbacks.
+					     moal_spin_unlock)) {
+				LEAVE();
+				return MFALSE;
+			}
+		}
+	}
+
+	LEAVE();
+	return MTRUE;
+}
+
+/**
+ *   @brief Get ralist node
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param tid      TID
+ *   @param ra_addr  Pointer to the route address
+ *
+ *   @return         ra_list or MNULL
+ */
+raListTbl *
+wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 *ra_addr)
+{
+	raListTbl *ra_list;
+	ENTER();
+	ra_list =
+		(raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					    &priv->wmm.tid_tbl_ptr[tid].ra_list,
+					    MNULL, MNULL);
+	while (ra_list && (ra_list != (raListTbl *)
+			   &priv->wmm.tid_tbl_ptr[tid].ra_list)) {
+		if (!memcmp
+		    (priv->adapter, ra_list->ra, ra_addr,
+		     MLAN_MAC_ADDR_LENGTH)) {
+			LEAVE();
+			return ra_list;
+		}
+		ra_list = ra_list->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *   @brief Check if RA list is valid or not
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param ra_list  Pointer to raListTbl
+ *   @param ptrindex TID pointer index
+ *
+ *   @return         MTRUE- valid. MFALSE- invalid.
+ */
+int
+wlan_is_ralist_valid(mlan_private *priv, raListTbl *ra_list, int ptrindex)
+{
+	raListTbl *rlist;
+
+	ENTER();
+
+	rlist = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					    &priv->wmm.tid_tbl_ptr[ptrindex].
+					    ra_list, MNULL, MNULL);
+
+	while (rlist && (rlist != (raListTbl *)
+			 &priv->wmm.tid_tbl_ptr[ptrindex].ra_list)) {
+		if (rlist == ra_list) {
+			LEAVE();
+			return MTRUE;
+		}
+
+		rlist = rlist->pnext;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief  Update an existing raList with a new RA and 11n capability
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *  @param old_ra   Old receiver address
+ *  @param new_ra   New receiver address
+ *
+ *  @return         integer count of updated nodes
+ */
+int
+wlan_ralist_update(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra)
+{
+	t_u8 tid;
+	int update_count;
+	raListTbl *ra_list;
+
+	ENTER();
+
+	update_count = 0;
+
+	for (tid = 0; tid < MAX_NUM_TID; ++tid) {
+
+		ra_list = wlan_wmm_get_ralist_node(priv, tid, old_ra);
+
+		if (ra_list) {
+			update_count++;
+
+			if (queuing_ra_based(priv)) {
+				ra_list->is_11n_enabled =
+					wlan_is_11n_enabled(priv, new_ra);
+				if (ra_list->is_11n_enabled)
+					ra_list->max_amsdu =
+						get_station_max_amsdu_size(priv,
+									   new_ra);
+			} else {
+				ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+				if (ra_list->is_11n_enabled)
+					ra_list->max_amsdu = priv->max_amsdu;
+			}
+
+			ra_list->tx_pause = MFALSE;
+			ra_list->packet_count = 0;
+			ra_list->ba_packet_threshold =
+				wlan_get_random_ba_threshold(priv->adapter);
+			ra_list->amsdu_in_ampdu = MFALSE;
+			ra_list->ba_status = BA_STREAM_NOT_SETUP;
+			PRINTM(MINFO,
+			       "ralist_update: %p, %d, " MACSTR "-->" MACSTR
+			       "\n", ra_list, ra_list->is_11n_enabled,
+			       MAC2STR(ra_list->ra), MAC2STR(new_ra));
+
+			memcpy(priv->adapter, ra_list->ra, new_ra,
+			       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;
+#if defined(UAP_SUPPORT)
+	sta_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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       MLAN_MAC_ADDR_LENGTH);
+	/** put multicast/broadcast packet in the same ralist */
+		if (ra[0] & 0x01)
+			memset(pmadapter, ra, 0xff, sizeof(ra));
+#if defined(UAP_SUPPORT)
+		else if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			sta_ptr = wlan_get_station_entry(priv, ra);
+			if (sta_ptr) {
+				if (!sta_ptr->is_wmm_enabled
+				    && !priv->is_11ac_enabled) {
+					tid_down =
+						wlan_wmm_downgrade_tid(priv,
+								       0xff);
+				}
+			}
+		}
+#endif
+		ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, ra);
+	}
+
+	if (!ra_list) {
+		PRINTM_NETINTF(MWARN, priv);
+		PRINTM(MWARN,
+		       "Drop packet %p, ra_list=%p, media_connected=%d\n",
+		       pmbuf, ra_list, priv->media_connected);
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+		LEAVE();
+		return;
+	}
+
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA,
+	       "Adding pkt %p (priority=%d, tid_down=%d) to ra_list %p\n",
+	       pmbuf, pmbuf->priority, tid_down, ra_list);
+	util_enqueue_list_tail(pmadapter->pmoal_handle, &ra_list->buf_head,
+			       (pmlan_linked_list)pmbuf, MNULL, MNULL);
+
+	ra_list->total_pkts++;
+	ra_list->packet_count++;
+
+	priv->wmm.pkts_queued[tid_down]++;
+	if (ra_list->tx_pause) {
+		priv->wmm.pkts_paused[tid_down]++;
+	} else {
+		util_scalar_increment(pmadapter->pmoal_handle,
+				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+		/* if highest_queued_prio < prio(tid_down), set it to prio(tid_down) */
+		util_scalar_conditional_write(pmadapter->pmoal_handle,
+					      &priv->wmm.highest_queued_prio,
+					      MLAN_SCALAR_COND_LESS_THAN,
+					      tos_to_tid_inv[tid_down],
+					      tos_to_tid_inv[tid_down],
+					      MNULL, MNULL);
+	}
+	/* Record the current time the packet was queued; used to determine
+	 *   the amount of time the packet was queued in the driver before it
+	 *   was sent to the firmware.  The delay is then sent along with the
+	 *   packet to the firmware for aggregate delay calculation for stats
+	 *   and MSDU lifetime expiry.
+	 */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmbuf->in_ts_sec,
+						  &pmbuf->in_ts_usec);
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Process the GET_WMM_STATUS command response from firmware
+ *
+ *  The GET_WMM_STATUS response may contain multiple TLVs for:
+ *      - AC Queue status TLVs
+ *      - Current WMM Parameter IE TLV
+ *      - Admission Control action frame TLVs
+ *
+ *  This function parses the TLVs and then calls further functions
+ *   to process any changes in the queue prioritize or state.
+ *
+ *  @param priv      Pointer to the mlan_private driver data struct
+ *  @param ptlv      Pointer to the tlv block returned in the response.
+ *  @param resp_len  Length of TLV block
+ *
+ *  @return MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_get_status(pmlan_private priv, t_u8 *ptlv, int resp_len)
+{
+	t_u8 *pcurrent = ptlv;
+	t_u32 tlv_len;
+	t_u8 send_wmm_event;
+	MrvlIEtypes_Data_t *ptlv_hdr;
+	MrvlIEtypes_WmmQueueStatus_t *ptlv_wmm_q_status;
+	IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
+	WmmAcStatus_t *pac_status;
+
+	MrvlIETypes_ActionFrame_t *ptlv_action;
+	IEEEtypes_Action_WMM_AddTsRsp_t *padd_ts_rsp;
+	IEEEtypes_Action_WMM_DelTs_t *pdel_ts;
+
+	ENTER();
+
+	send_wmm_event = MFALSE;
+
+	PRINTM(MINFO, "WMM: WMM_GET_STATUS cmdresp received: %d\n", resp_len);
+	HEXDUMP("CMD_RESP: WMM_GET_STATUS", pcurrent, resp_len);
+
+	while (resp_len >= sizeof(ptlv_hdr->header)) {
+		ptlv_hdr = (MrvlIEtypes_Data_t *)pcurrent;
+		tlv_len = wlan_le16_to_cpu(ptlv_hdr->header.len);
+		if ((tlv_len + sizeof(ptlv_hdr->header)) > resp_len) {
+			PRINTM(MERROR,
+			       "WMM get status: Error in processing  TLV buffer\n");
+			resp_len = 0;
+			continue;
+		}
+
+		switch (wlan_le16_to_cpu(ptlv_hdr->header.type)) {
+		case TLV_TYPE_WMMQSTATUS:
+			ptlv_wmm_q_status =
+				(MrvlIEtypes_WmmQueueStatus_t *)ptlv_hdr;
+			PRINTM(MEVENT, "WMM_STATUS: QSTATUS TLV: %d\n",
+			       ptlv_wmm_q_status->queue_index);
+
+			PRINTM(MINFO,
+			       "CMD_RESP: WMM_GET_STATUS: QSTATUS TLV: %d, %d, %d\n",
+			       ptlv_wmm_q_status->queue_index,
+			       ptlv_wmm_q_status->flow_required,
+			       ptlv_wmm_q_status->disabled);
+
+			pac_status =
+				&priv->wmm.ac_status[ptlv_wmm_q_status->
+						     queue_index];
+			pac_status->disabled = ptlv_wmm_q_status->disabled;
+			pac_status->flow_required =
+				ptlv_wmm_q_status->flow_required;
+			pac_status->flow_created =
+				ptlv_wmm_q_status->flow_created;
+			break;
+
+		case TLV_TYPE_VENDOR_SPECIFIC_IE:	/* WMM_IE */
+			/*
+			 * Point the regular IEEE IE 2 bytes into the Marvell 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(priv->adapter,
+			       (t_u8 *)&priv->curr_bss_params.bss_descriptor.
+			       wmm_ie, pwmm_param_ie,
+			       MIN(sizeof(IEEEtypes_WmmParameter_t),
+				   (pwmm_param_ie->vend_hdr.len + 2)));
+			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 Marvell 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(priv->adapter, pwmm_tlv->wmm_ie, &wmm_info_ie[2],
+		       pwmm_tlv->header.len);
+		if (pwmm_ie->qos_info.qos_uapsd)
+			memcpy(priv->adapter,
+			       (t_u8 *)(pwmm_tlv->wmm_ie +
+					pwmm_tlv->header.len -
+					sizeof(priv->wmm_qosinfo)),
+			       &priv->wmm_qosinfo, sizeof(priv->wmm_qosinfo));
+
+		ret_len = sizeof(pwmm_tlv->header) + pwmm_tlv->header.len;
+		pwmm_tlv->header.len = wlan_cpu_to_le16(pwmm_tlv->header.len);
+
+		HEXDUMP("ASSOC_CMD: WMM IE", (t_u8 *)pwmm_tlv, ret_len);
+		*ppassoc_buf += ret_len;
+	}
+
+	LEAVE();
+	return ret_len;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *   @brief Compute the time delay in the driver queues for a given packet.
+ *
+ *   When the packet is received at the OS/Driver interface, the current
+ *     time is set in the packet structure.  The difference between the present
+ *     time and that received time is computed in this function and limited
+ *     based on pre-compiled limits in the driver.
+ *
+ *   @param priv   Ptr to the mlan_private driver data struct
+ *   @param pmbuf  Ptr to the mlan_buffer which has been previously timestamped
+ *
+ *   @return  Time delay of the packet in 2ms units after having limit applied
+ */
+t_u8
+wlan_wmm_compute_driver_packet_delay(pmlan_private priv,
+				     const pmlan_buffer pmbuf)
+{
+	t_u8 ret_val = 0;
+	t_u32 out_ts_sec, out_ts_usec;
+	t_s32 queue_delay;
+
+	ENTER();
+
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &out_ts_sec,
+						      &out_ts_usec);
+
+	queue_delay = (t_s32)(out_ts_sec - pmbuf->in_ts_sec) * 1000;
+	queue_delay += (t_s32)(out_ts_usec - pmbuf->in_ts_usec) / 1000;
+
+	/*
+	 * Queue delay is passed as a uint8 in units of 2ms (ms shifted
+	 *  by 1). Min value (other than 0) is therefore 2ms, max is 510ms.
+	 *
+	 * Pass max value if queue_delay is beyond the uint8 range
+	 */
+	ret_val = (t_u8)(MIN(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1);
+
+	PRINTM(MINFO, "WMM: Pkt Delay: %d ms, %d ms sent to FW\n",
+	       queue_delay, ret_val);
+
+	LEAVE();
+	return ret_val;
+}
+
+/**
+ *  @brief Transmit the highest priority packet awaiting in the WMM Queues
+ *
+ *  @param pmadapter Pointer to the mlan_adapter driver data struct
+ *
+ *  @return        N/A
+ */
+void
+wlan_wmm_process_tx(pmlan_adapter pmadapter)
+{
+	ENTER();
+
+	do {
+		if (wlan_dequeue_tx_packet(pmadapter))
+			break;
+		if (pmadapter->sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) {
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+			wlan_send_mp_aggr_buf(pmadapter);
+#endif
+			break;
+		}
+
+		/* 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(IN pmlan_private pmpriv,
+		       OUT HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter,
+	       pcmd_addts->tspec_data,
+	       paddts->ie_data, MIN(WMM_TSPEC_SIZE, paddts->ie_data_len));
+
+	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(IN pmlan_private pmpriv,
+		       const IN HostCmd_DS_COMMAND *resp,
+		       OUT 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(pmpriv->adapter,
+			       paddts->ie_data,
+			       presp_addts->tspec_data, paddts->ie_data_len);
+		} 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(IN pmlan_private pmpriv,
+		       OUT HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter,
+	       pcmd_delts->tspec_data,
+	       pdelts->ie_data, MIN(WMM_TSPEC_SIZE, pdelts->ie_data_len));
+
+	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(IN pmlan_private pmpriv,
+		       const IN HostCmd_DS_COMMAND *resp,
+		       OUT 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(IN pmlan_private pmpriv,
+			 OUT HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			 const IN HostCmd_DS_COMMAND *resp,
+			 OUT 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(IN pmlan_private pmpriv,
+		       OUT HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, (t_void *)pcmd_ts_status, (t_void *)pts_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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       OUT 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(pmpriv->adapter,
+		       (t_void *)&pwmm->param.ts_status,
+		       (t_void *)presp_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(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_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(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_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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_private pmpriv,
+			  OUT HostCmd_DS_COMMAND *cmd,
+			  IN t_u8 cmd_action, IN 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(pmpriv->adapter, pcmd_cfg->ac_params, ac_params,
+		       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(IN pmlan_private pmpriv,
+			  const IN HostCmd_DS_COMMAND *resp,
+			  OUT 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(pmpriv->adapter, pwmm->param.ac_params, pcfg->ac_params,
+		       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(IN pmlan_private pmpriv,
+			  OUT HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			  const IN HostCmd_DS_COMMAND *resp,
+			  OUT 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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter, IN 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(priv->adapter, plist->ra, ra_list->ra,
+				       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 100644
index 0000000..30122e5
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_wmm.h
@@ -0,0 +1,244 @@
+/** @file mlan_wmm.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of wmm functionalities
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/****************************************************
+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, raListTbl *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(IN mlan_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(IN mlan_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(IN pmlan_private pmpriv,
+				      OUT HostCmd_DS_COMMAND *cmd,
+				      IN t_u8 cmd_action, IN t_void *pdata_buf);
+
+/* process wmm_param_config command response */
+mlan_status wlan_ret_wmm_param_config(IN pmlan_private pmpriv,
+				      const IN HostCmd_DS_COMMAND *resp,
+				      OUT 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(IN pmlan_private pmpriv,
+					  OUT HostCmd_DS_COMMAND *cmd,
+					  IN t_void *pdata_buf);
+/** WMM DELTS request command handler */
+extern mlan_status wlan_cmd_wmm_delts_req(IN pmlan_private pmpriv,
+					  OUT HostCmd_DS_COMMAND *cmd,
+					  IN t_void *pdata_buf);
+/** WMM QUEUE_STATS command handler */
+extern mlan_status wlan_cmd_wmm_queue_stats(IN pmlan_private pmpriv,
+					    OUT HostCmd_DS_COMMAND *cmd,
+					    IN t_void *pdata_buf);
+/** WMM TS_STATUS command handler */
+extern mlan_status wlan_cmd_wmm_ts_status(IN pmlan_private pmpriv,
+					  OUT HostCmd_DS_COMMAND *cmd,
+					  IN 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(IN pmlan_private priv,
+					   IN t_u8 *ptlv, IN int resp_len);
+/** WMM ADDTS request command response handler */
+extern mlan_status wlan_ret_wmm_addts_req(IN pmlan_private pmpriv,
+					  const IN HostCmd_DS_COMMAND *resp,
+					  OUT mlan_ioctl_req *pioctl_buf);
+/** WMM DELTS request command response handler */
+extern mlan_status wlan_ret_wmm_delts_req(IN pmlan_private pmpriv,
+					  const IN HostCmd_DS_COMMAND *resp,
+					  OUT mlan_ioctl_req *pioctl_buf);
+/** WMM QUEUE_STATS command response handler */
+extern mlan_status wlan_ret_wmm_queue_stats(IN pmlan_private pmpriv,
+					    const IN HostCmd_DS_COMMAND *resp,
+					    OUT mlan_ioctl_req *pioctl_buf);
+/** WMM TS_STATUS command response handler */
+extern mlan_status wlan_ret_wmm_ts_status(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  OUT mlan_ioctl_req *pioctl_buf);
+#endif /* STA_SUPPORT */
+
+/** WMM QUEUE_CONFIG command handler */
+extern mlan_status wlan_cmd_wmm_queue_config(IN pmlan_private pmpriv,
+					     OUT HostCmd_DS_COMMAND *cmd,
+					     IN t_void *pdata_buf);
+
+/** WMM QUEUE_CONFIG command response handler */
+extern mlan_status wlan_ret_wmm_queue_config(IN pmlan_private pmpriv,
+					     const IN HostCmd_DS_COMMAND *resp,
+					     OUT mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_wmm_cfg_ioctl(IN pmlan_adapter pmadapter,
+			       IN 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 100644
index 0000000..f8b25c6
--- /dev/null
+++ b/wlan_sd8987/mlinux/mlan.h
@@ -0,0 +1,35 @@
+/** @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 (C) 2008-2019, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+/******************************************************
+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 100644
index 0000000..a308809
--- /dev/null
+++ b/wlan_sd8987/mlinux/mlan_decl.h
@@ -0,0 +1,1478 @@
+/** @file mlan_decl.h
+ *
+ *  @brief This file declares the generic data structures and APIs.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    11/07/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_DECL_H_
+#define _MLAN_DECL_H_
+
+/** MLAN release version */
+#define MLAN_RELEASE_VERSION		 "C637.P9"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef signed char t_s8;
+/** Unsigned char (1-byte) */
+typedef unsigned char t_u8;
+/** Signed short (2-bytes) */
+typedef short t_s16;
+/** Unsigned short (2-bytes) */
+typedef unsigned short t_u16;
+/** Signed long (4-bytes) */
+typedef int t_s32;
+/** Unsigned long (4-bytes) */
+typedef unsigned int t_u32;
+/** Signed long long 8-bytes) */
+typedef long long t_s64;
+/** Unsigned long long 8-bytes) */
+typedef unsigned long long t_u64;
+/** Void pointer (4-bytes) */
+typedef void t_void;
+/** 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)
+
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM         (16)
+
+/** NET IP alignment */
+#define MLAN_NET_IP_ALIGN        2
+
+/** DMA alignment */
+/* SDIO3.0 Inrevium Adapter require 32 bit DMA alignment */
+#define DMA_ALIGNMENT            32
+
+/** max size of TxPD */
+#define MAX_TXPD_SIZE            32
+
+/** Minimum data header length */
+#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT+MAX_TXPD_SIZE)
+
+/** rx data header length */
+#define MLAN_RX_HEADER_LEN       MLAN_MIN_DATA_HEADER_LEN
+
+/** This is current limit on Maximum Tx AMPDU allowed */
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED          16
+#define MLAN_MAX_TX_BASTREAM_DEFAULT            2
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED_NOV15    2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED     16
+
+/** station ampdu tx win size */
+#define MLAN_STA_AMPDU_DEF_TXWINSIZE_NOV15      32
+/** uap ampdu tx win size */
+#define MLAN_UAP_AMPDU_DEF_TXWINSIZE_NOV15      32
+/** uap ampdu rx win size */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE_NOV15      32
+#ifdef WIFI_DIRECT_SUPPORT
+/** wfd ampdu tx/rx win size */
+#define MLAN_WFD_AMPDU_DEF_TXRXWINSIZE_NOV15    32
+#endif
+
+#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       48
+/** Default Win size attached during ADDBA response */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE       32
+/** 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 7 */
+#define MLAN_RATE_INDEX_MCS7    7
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9    9
+/** 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 command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (4 * 1024)
+/** Upload size */
+#define WLAN_UPLD_SIZE            MRVDRV_SIZE_OF_CMD_BUFFER
+/** Size of rx data buffer 4096+256 */
+#define MLAN_RX_DATA_BUF_SIZE     4352
+/** Size of rx command buffer */
+#define MLAN_RX_CMD_BUF_SIZE      MRVDRV_SIZE_OF_CMD_BUFFER
+
+#define MLAN_USB_RX_DATA_BUF_SIZE       MLAN_RX_DATA_BUF_SIZE
+
+/** 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
+
+/** 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)
+/** SDIO MP aggr pkt limit 16*/
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_16	 (16)
+/** max SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX	 (16)
+
+/** SDIO IO Port mask */
+#define MLAN_SDIO_IO_PORT_MASK		0xfffff
+/** SDIO Block/Byte mode mask */
+#define MLAN_SDIO_BYTE_MODE_MASK	0x80000000
+
+/** Max retry number of IO write */
+#define MAX_WRITE_IOMEM_RETRY		2
+
+/** 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)
+
+/** 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)
+
+#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 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,
+	MLAN_STATUS_COMPLETE,
+} 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,
+	MLAN_BUF_TYPE_SPA_DATA,
+} mlan_buf_type;
+
+/** 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 bit mask */
+#define BSS_ROLE_BIT_MASK    MBIT(0)
+
+/** Get BSS role */
+#define GET_BSS_ROLE(priv)   ((priv)->bss_role & BSS_ROLE_BIT_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,
+	/* 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_STORE_HOST_CMD_RESP = 0x80000029,
+} mlan_event_id;
+
+/** Data Structures */
+/** mlan_image data structure */
+typedef struct _mlan_fw_image {
+    /** Helper image buffer pointer */
+	t_u8 *phelper_buf;
+    /** Helper image length */
+	t_u32 helper_len;
+    /** 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;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Data_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Data */
+	t_u8 data[1];
+} MLAN_PACK_END MrvlIEtypes_Data_t;
+
+#define OID_TYPE_CAL    0x2
+/** DPD PM-PM data type*/
+#define OID_TYPE_DPD              0xa
+/** DPD AM-AM AM-PM and APPD data */
+#define OID_TYPE_DPD_OTHER        0xb
+/** Unknow DPD length, Flag to trigger FW DPD training */
+#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,
+};
+
+/** 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 MARVELL_CHANNEL_NO_OFDM         MBIT(9)
+#define MARVELL_CHANNEL_NO_CCK          MBIT(8)
+#define MARVELL_CHANNEL_DISABLED		MBIT(7)
+/* BIT 5/6 resevered for FW */
+#define MARVELL_CHANNEL_NOHT160			MBIT(4)
+#define MARVELL_CHANNEL_NOHT80			MBIT(3)
+#define MARVELL_CHANNEL_NOHT40			MBIT(2)
+#define MARVELL_CHANNEL_DFS				MBIT(1)
+#define MARVELL_CHANNEL_PASSIVE			MBIT(0)
+
+/** CFP dynamic (non-const) elements */
+typedef struct _cfp_dyn_t {
+	/** extra flags to specify channel usability
+	 *  bit 9 : if set, channel is non-OFDM
+	 *  bit 8 : if set, channel is non-CCK
+	 *  bit 7 : if set, channel is disabled
+	 *  bit  5/6 resevered for FW
+	 *  bit 4 : if set, 160MHz on channel is disabled
+	 *  bit 3 : if set, 80MHz on channel is disabled
+	 *  bit 2 : if set, 40MHz on channel is disabled
+	 *  bit 1 : if set, channel is DFS channel
+	 *  bit 0 : if set, channel is passive
+	 */
+	t_u16 flags;
+    /** TRUE: Channel is blacklisted (do not use) */
+	t_bool blacklist;
+} cfp_dyn_t;
+
+/** Chan-Freq-TxPower mapping table*/
+typedef struct _chan_freq_power_t {
+    /** Channel Number */
+	t_u16 channel;
+    /** Frequency of this Channel */
+	t_u32 freq;
+    /** Max allowed Tx power level */
+	t_u16 max_tx_power;
+    /** TRUE:radar detect required for BAND A or passive scan for BAND B/G;
+      * FALSE:radar detect not required for BAND A or active scan for BAND B/G*/
+	t_bool passive_scan_or_radar_detect;
+    /** Elements associated to cfp that change at run-time */
+	cfp_dyn_t dynamic;
+} chan_freq_power_t;
+
+/** mlan_event data structure */
+typedef struct _mlan_event {
+    /** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+    /** Event ID */
+	mlan_event_id event_id;
+    /** Event length */
+	t_u32 event_len;
+    /** Event buffer */
+	t_u8 event_buf[0];
+} 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;
+
+/** 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;
+    /** Offset to data */
+	t_u32 data_offset;
+    /** Data length */
+	t_u32 data_len;
+    /** Buffer type: data, cmd, event etc. */
+	mlan_buf_type buf_type;
+
+    /** Fields below are valid for data packet only */
+    /** QoS priority */
+	t_u32 priority;
+    /** Time stamp when packet is received (seconds) */
+	t_u32 in_ts_sec;
+    /** Time stamp when packet is received (micro seconds) */
+	t_u32 in_ts_usec;
+    /** Time stamp when packet is processed (seconds) */
+	t_u32 out_ts_sec;
+    /** Time stamp when packet is processed (micro seconds) */
+	t_u32 out_ts_usec;
+    /** tx_seq_num */
+	t_u32 tx_seq_num;
+
+    /** Fields below are valid for MLAN module only */
+    /** Pointer to parent mlan_buffer */
+	struct _mlan_buffer *pparent;
+    /** Use count for this buffer */
+	t_u32 use_count;
+} mlan_buffer, *pmlan_buffer;
+
+/** mlan_fw_info data structure */
+typedef struct _mlan_hw_info {
+    /** Firmware capabilities */
+	t_u32 fw_cap;
+} mlan_hw_info, *pmlan_hw_info;
+
+/** mlan_bss_attr data structure */
+typedef struct _mlan_bss_attr {
+    /** BSS type */
+	t_u32 bss_type;
+    /** Data frame type: Ethernet II, 802.11, etc. */
+	t_u32 frame_type;
+    /** The BSS is active (non-0) or not (0). */
+	t_u32 active;
+    /** BSS Priority */
+	t_u32 bss_priority;
+    /** BSS number */
+	t_u32 bss_num;
+    /** The BSS is virtual */
+	t_u32 bss_virtual;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+/** bss tbl data structure */
+typedef struct _mlan_bss_tbl {
+    /** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+} mlan_bss_tbl, *pmlan_bss_tbl;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** Type enumeration for the command result */
+typedef MLAN_PACK_START enum _mlan_cmd_result_e {
+	MLAN_CMD_RESULT_SUCCESS = 0,
+	MLAN_CMD_RESULT_FAILURE = 1,
+	MLAN_CMD_RESULT_TIMEOUT = 2,
+	MLAN_CMD_RESULT_INVALID_DATA = 3
+} MLAN_PACK_END mlan_cmd_result_e;
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} MLAN_PACK_END mlan_wmm_ac_e;
+
+/** Type enumeration for the action field in the Queue Config command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e {
+	MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_config_action_e;
+
+/** Type enumeration for the action field in the queue stats command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e {
+	MLAN_WMM_STATS_ACTION_START = 0,
+	MLAN_WMM_STATS_ACTION_STOP = 1,
+	MLAN_WMM_STATS_ACTION_GET_CLR = 2,
+	MLAN_WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_stats_action_e;
+
+/**
+ *  @brief IOCTL structure for a Traffic stream status.
+ *
+ */
+typedef MLAN_PACK_START struct {
+    /** TSID: Range: 0->7 */
+	t_u8 tid;
+    /** TSID specified is valid */
+	t_u8 valid;
+    /** AC TSID is active on */
+	t_u8 access_category;
+    /** UP specified for the TSID */
+	t_u8 user_priority;
+    /** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 psb;
+    /** Upstream(0), Downlink(1), Bidirectional(3) */
+	t_u8 flow_dir;
+    /** Medium time granted for the TSID */
+	t_u16 medium_time;
+} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t,
+/** Type definition of mlan_ds_wmm_ts_status for MLAN_OID_WMM_CFG_TS_STATUS */
+mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status;
+
+/** Max Ie length */
+#define MAX_IE_SIZE             256
+
+/** custom IE */
+typedef MLAN_PACK_START struct _custom_ie {
+    /** IE Index */
+	t_u16 ie_index;
+    /** Mgmt Subtype Mask */
+	t_u16 mgmt_subtype_mask;
+    /** IE Length */
+	t_u16 ie_length;
+    /** IE buffer */
+	t_u8 ie_buffer[MAX_IE_SIZE];
+} MLAN_PACK_END custom_ie;
+
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW         4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX               26
+
+/** custom IE info */
+typedef MLAN_PACK_START struct _custom_ie_info {
+    /** size of buffer */
+	t_u16 buf_size;
+    /** no of buffers of buf_size */
+	t_u16 buf_count;
+} MLAN_PACK_END custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** No of tuples */
+	t_u16 count;
+    /** custom IE info tuples */
+	custom_ie_info info[MAX_MGMT_IE_INDEX];
+} MLAN_PACK_END tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef MLAN_PACK_START struct _tlvbuf_custom_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** IE data */
+	custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW];
+    /** Max mgmt IE TLV */
+	tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+/** 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[0];
+} 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[0];
+		} 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[0];
+		} 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[0];
+		} 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;
+
+/** 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) (IN t_void *pmoal_handle,
+					 IN t_u32 offset,
+					 IN t_u32 len, OUT t_u8 *pbuf);
+    /** moal_get_hw_spec_complete */
+	mlan_status (*moal_get_hw_spec_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status,
+						  IN mlan_hw_info * phw,
+						  IN pmlan_bss_tbl ptbl);
+    /** moal_init_fw_complete */
+	mlan_status (*moal_init_fw_complete) (IN t_void *pmoal_handle,
+					      IN mlan_status status);
+    /** moal_shutdown_fw_complete */
+	mlan_status (*moal_shutdown_fw_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status);
+    /** moal_send_packet_complete */
+	mlan_status (*moal_send_packet_complete) (IN t_void *pmoal_handle,
+						  IN pmlan_buffer pmbuf,
+						  IN mlan_status status);
+    /** moal_recv_complete */
+	mlan_status (*moal_recv_complete) (IN t_void *pmoal_handle,
+					   IN pmlan_buffer pmbuf,
+					   IN t_u32 port,
+					   IN mlan_status status);
+    /** moal_recv_packet */
+	mlan_status (*moal_recv_packet) (IN t_void *pmoal_handle,
+					 IN pmlan_buffer pmbuf);
+    /** moal_recv_event */
+	mlan_status (*moal_recv_event) (IN t_void *pmoal_handle,
+					IN pmlan_event pmevent);
+    /** moal_ioctl_complete */
+	mlan_status (*moal_ioctl_complete) (IN t_void *pmoal_handle,
+					    IN pmlan_ioctl_req pioctl_req,
+					    IN mlan_status status);
+
+    /** moal_alloc_mlan_buffer */
+	mlan_status (*moal_alloc_mlan_buffer) (IN t_void *pmoal_handle,
+					       IN t_u32 size,
+					       OUT pmlan_buffer *pmbuf);
+    /** moal_free_mlan_buffer */
+	mlan_status (*moal_free_mlan_buffer) (IN t_void *pmoal_handle,
+					      IN pmlan_buffer pmbuf);
+
+    /** moal_write_reg */
+	mlan_status (*moal_write_reg) (IN t_void *pmoal_handle,
+				       IN t_u32 reg, IN t_u32 data);
+    /** moal_read_reg */
+	mlan_status (*moal_read_reg) (IN t_void *pmoal_handle,
+				      IN t_u32 reg, OUT t_u32 *data);
+    /** moal_write_data_sync */
+	mlan_status (*moal_write_data_sync) (IN t_void *pmoal_handle,
+					     IN pmlan_buffer pmbuf,
+					     IN t_u32 port, IN t_u32 timeout);
+    /** moal_read_data_sync */
+	mlan_status (*moal_read_data_sync) (IN t_void *pmoal_handle,
+					    IN OUT pmlan_buffer pmbuf,
+					    IN t_u32 port, IN t_u32 timeout);
+    /** moal_malloc */
+	mlan_status (*moal_malloc) (IN t_void *pmoal_handle,
+				    IN t_u32 size,
+				    IN t_u32 flag, OUT t_u8 **ppbuf);
+    /** moal_mfree */
+	mlan_status (*moal_mfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_vmalloc */
+	mlan_status (*moal_vmalloc) (IN t_void *pmoal_handle,
+				     IN t_u32 size, OUT t_u8 **ppbuf);
+    /** moal_vfree */
+	mlan_status (*moal_vfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_memset */
+	t_void *(*moal_memset) (IN t_void *pmoal_handle,
+				IN t_void *pmem, IN t_u8 byte, IN t_u32 num);
+    /** moal_memcpy */
+	t_void *(*moal_memcpy) (IN t_void *pmoal_handle,
+				IN t_void *pdest,
+				IN const t_void *psrc, IN t_u32 num);
+    /** moal_memmove */
+	t_void *(*moal_memmove) (IN t_void *pmoal_handle,
+				 IN t_void *pdest,
+				 IN const t_void *psrc, IN t_u32 num);
+    /** moal_memcmp */
+	t_s32 (*moal_memcmp) (IN t_void *pmoal_handle,
+			      IN const t_void *pmem1,
+			      IN const t_void *pmem2, IN t_u32 num);
+    /** moal_udelay */
+	t_void (*moal_udelay) (IN t_void *pmoal_handle, IN t_u32 udelay);
+    /** moal_get_boot_ktime */
+	mlan_status (*moal_get_boot_ktime) (IN t_void *pmoal_handle,
+					    OUT t_u64 *pnsec);
+    /** moal_get_system_time */
+	mlan_status (*moal_get_system_time) (IN t_void *pmoal_handle,
+					     OUT t_u32 *psec, OUT t_u32 *pusec);
+    /** moal_usleep */
+	mlan_status (*moal_usleep) (IN t_void *pmoal_handle,
+				    IN t_u64 min, IN t_u64 max);
+
+    /** moal_init_timer*/
+	mlan_status (*moal_init_timer) (IN t_void *pmoal_handle,
+					OUT t_void **pptimer,
+					IN t_void (*callback) (t_void
+							       *pcontext),
+					IN t_void *pcontext);
+    /** moal_free_timer */
+	mlan_status (*moal_free_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_start_timer*/
+	mlan_status (*moal_start_timer) (IN t_void *pmoal_handle,
+					 IN t_void *ptimer,
+					 IN t_u8 periodic, IN t_u32 msec);
+    /** moal_stop_timer*/
+	mlan_status (*moal_stop_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_init_lock */
+	mlan_status (*moal_init_lock) (IN t_void *pmoal_handle,
+				       OUT t_void **pplock);
+    /** moal_free_lock */
+	mlan_status (*moal_free_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_lock */
+	mlan_status (*moal_spin_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_unlock */
+	mlan_status (*moal_spin_unlock) (IN t_void *pmoal_handle,
+					 IN t_void *plock);
+    /** moal_print */
+	t_void (*moal_print) (IN t_void *pmoal_handle,
+			      IN t_u32 level, IN char *pformat, IN ...
+		);
+    /** moal_print_netintf */
+	t_void (*moal_print_netintf) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index, IN t_u32 level);
+    /** moal_assert */
+	t_void (*moal_assert) (IN t_void *pmoal_handle, IN t_u32 cond);
+    /** moal_hist_data_add */
+	t_void (*moal_hist_data_add) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index,
+				      IN t_u8 rx_rate,
+				      IN t_s8 snr,
+				      IN t_s8 nflr, IN t_u8 antenna);
+	t_void (*moal_updata_peer_signal) (IN t_void *pmoal_handle,
+					   IN t_u32 bss_index,
+					   IN t_u8 *peer_addr,
+					   IN t_s8 snr, IN t_s8 nflr);
+} 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
+
+/** 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
+
+/** 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(6)
+/** Control bit for DFS support */
+#define FEATURE_CTRL_DFS_SUPPORT    MBIT(7)
+
+/** Default feature control */
+#define FEATURE_CTRL_DEFAULT        0xffffffff
+
+/** 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
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#ifdef DEBUG_LEVEL1
+    /** Driver debug bit masks */
+	t_u32 drvdbg;
+#endif
+    /** allocate fixed buffer size for scan beacon buffer*/
+	t_u32 fixed_beacon_buffer;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** SDIO MPA Rx */
+	t_u32 mpa_rx_cfg;
+#endif
+	/** SDIO Single port rx aggr */
+	t_u8 sdio_rx_aggr_enable;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/* 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
+    /** FW download CRC check flag */
+	t_u32 fw_crc_check;
+    /** Feature control bitmask */
+	t_u32 feature_control;
+    /** enable/disable rx work */
+	t_u8 rx_work;
+    /** dev cap mask */
+	t_u32 dev_cap_mask;
+    /** dtim interval */
+	t_u16 multi_dtim;
+    /** IEEE ps inactivity timeout value */
+	t_u16 inact_tmo;
+	/** card type */
+	t_u16 card_type;
+    /** Host sleep wakeup interval */
+	t_u32 hs_wake_interval;
+    /** GPIO to indicate wakeup source */
+	t_u8 indication_gpio;
+    /** channel time and mode for DRCS*/
+	t_u32 drcs_chantime_mode;
+	t_bool fw_region;
+} mlan_device, *pmlan_device;
+
+/** MLAN API function prototype */
+#define MLAN_API
+
+/** oops dump */
+MLAN_API void mlan_dump_adapter(IN t_void *pmlan_adapter);
+
+/** Registration */
+MLAN_API mlan_status mlan_register(IN pmlan_device pmdevice,
+				   OUT t_void **ppmlan_adapter);
+
+/** Un-registration */
+MLAN_API mlan_status mlan_unregister(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Downloading */
+MLAN_API mlan_status mlan_dnld_fw(IN t_void *pmlan_adapter,
+				  IN pmlan_fw_image pmfw);
+
+/** Custom data pass API */
+MLAN_API mlan_status mlan_set_init_param(IN t_void *pmlan_adapter,
+					 IN pmlan_init_param pparam);
+
+/** Firmware Initialization */
+MLAN_API mlan_status mlan_init_fw(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Shutdown */
+MLAN_API mlan_status mlan_shutdown_fw(IN t_void *pmlan_adapter
+	);
+
+/** Main Process */
+MLAN_API mlan_status mlan_main_process(IN t_void *pmlan_adapter
+	);
+
+/** Rx process */
+mlan_status mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts);
+
+/** Packet Transmission */
+MLAN_API mlan_status mlan_send_packet(IN t_void *pmlan_adapter,
+				      IN pmlan_buffer pmbuf);
+
+/** Packet Reception complete callback */
+MLAN_API mlan_status mlan_recv_packet_complete(IN t_void *pmlan_adapter,
+					       IN pmlan_buffer pmbuf,
+					       IN mlan_status status);
+
+/** interrupt handler */
+MLAN_API mlan_status mlan_interrupt(IN t_void *pmlan_adapter);
+
+#if defined(SYSKT)
+/** GPIO IRQ callback function */
+MLAN_API t_void mlan_hs_callback(IN t_void *pctx);
+#endif /* SYSKT_MULTI || SYSKT */
+
+MLAN_API t_void mlan_pm_wakeup_card(IN t_void *pmlan_adapter);
+
+MLAN_API t_u8 mlan_is_main_process_running(IN t_void *adapter);
+
+/** mlan ioctl */
+MLAN_API mlan_status mlan_ioctl(IN t_void *pmlan_adapter,
+				IN pmlan_ioctl_req pioctl_req);
+/** mlan select wmm queue */
+MLAN_API t_u8 mlan_select_wmm_queue(IN t_void *pmlan_adapter,
+				    IN t_u8 bss_num, IN t_u8 tid);
+#endif /* !_MLAN_DECL_H_ */
diff --git a/wlan_sd8987/mlinux/mlan_ieee.h b/wlan_sd8987/mlinux/mlan_ieee.h
new file mode 100644
index 0000000..9cf442c
--- /dev/null
+++ b/wlan_sd8987/mlinux/mlan_ieee.h
@@ -0,0 +1,2016 @@
+/** @file mlan_ieee.h
+ *
+ *  @brief This file contains IEEE information element related
+ *  definitions used in MLAN and MOAL module.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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
+
+/** 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,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	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_IE = VENDOR_SPECIFIC_221,
+	RSN_IE = 48,
+	VS_IE = VENDOR_SPECIFIC_221,
+	WAPI_IE = 68,
+	FRAGMENT = 242,
+	EXTENSION = 255
+} MLAN_PACK_END IEEEtypes_ElementId_e;
+
+/** IEEE IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_Header_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+} MLAN_PACK_END IEEEtypes_Header_t, *pIEEEtypes_Header_t;
+
+/** Vendor specific IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorHeader_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+    /** OUI */
+	t_u8 oui[3];
+    /** OUI type */
+	t_u8 oui_type;
+    /** OUI subtype */
+	t_u8 oui_subtype;
+    /** Version */
+	t_u8 version;
+} MLAN_PACK_END IEEEtypes_VendorHeader_t, *pIEEEtypes_VendorHeader_t;
+
+/** Vendor specific IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorSpecific_t {
+    /** Vendor specific IE header */
+	IEEEtypes_VendorHeader_t vend_hdr;
+    /** IE Max - size of previous fields */
+	t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_VendorHeader_t)];
+} MLAN_PACK_END IEEEtypes_VendorSpecific_t, *pIEEEtypes_VendorSpecific_t;
+
+/** IEEE IE */
+typedef MLAN_PACK_START struct _IEEEtypes_Generic_t {
+    /** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+    /** IE Max - size of previous fields */
+	t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_Header_t)];
+} MLAN_PACK_END IEEEtypes_Generic_t, *pIEEEtypes_Generic_t;
+
+/**ft capability policy*/
+typedef MLAN_PACK_START struct _IEEEtypes_FtCapPolicy_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Reserved */
+	t_u8 reserved:6;
+    /** RIC support */
+	t_u8 ric:1;
+    /** FT over the DS capable */
+	t_u8 ft_over_ds:1;
+#else
+    /** FT over the DS capable */
+	t_u8 ft_over_ds:1;
+    /** RIC support */
+	t_u8 ric:1;
+    /** Reserved */
+	t_u8 reserved:6;
+#endif
+} MLAN_PACK_END IEEEtypes_FtCapPolicy_t;
+
+/** Mobility domain IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MobilityDomain_t {
+    /** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+    /** Mobility Domain ID */
+	t_u16 mdid;
+    /** FT Capability policy */
+	t_u8 ft_cap;
+} MLAN_PACK_END IEEEtypes_MobilityDomain_t;
+
+/**FT MIC Control*/
+typedef MLAN_PACK_START struct _IEEEtypes_FT_MICControl_t {
+	/** reserved */
+	t_u8 reserved;
+	/** element count */
+	t_u8 element_count;
+} MLAN_PACK_END IEEEtypes_FT_MICControl_t;
+
+/** FTIE MIC LEN */
+#define FTIE_MIC_LEN  16
+
+/**FT IE*/
+typedef MLAN_PACK_START struct _IEEEtypes_FastBssTransElement_t {
+    /** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** mic control */
+	IEEEtypes_FT_MICControl_t mic_control;
+	/** mic */
+	t_u8 mic[FTIE_MIC_LEN];
+	/** ANonce */
+	t_u8 a_nonce[32];
+	/** SNonce */
+	t_u8 s_nonce[32];
+	/** sub element */
+	t_u8 sub_element[1];
+} MLAN_PACK_END IEEEtypes_FastBssTransElement_t;
+
+/*Category for FT*/
+#define FT_CATEGORY 6
+/** FT ACTION request */
+#define FT_ACTION_REQUEST 1
+/** FT ACTION response */
+#define FT_ACTION_RESPONSE 2
+
+/*FT response and FT ack*/
+typedef MLAN_PACK_START struct {
+    /** category */
+	t_u8 category;
+    /** action */
+	t_u8 action;
+    /** sta address */
+	t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+    /** target ap address */
+	t_u8 target_ap_addr[MLAN_MAC_ADDR_LENGTH];
+    /** status code */
+	t_u16 status_code;
+    /** varible */
+	t_u8 variable[0];
+} 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[0];
+} 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[0];
+} 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[0];
+} 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_CfParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_CfParamSet_t {
+    /** CF peremeter : Element ID */
+	t_u8 element_id;
+    /** CF peremeter : Length */
+	t_u8 len;
+    /** CF peremeter : Count */
+	t_u8 cfp_cnt;
+    /** CF peremeter : Period */
+	t_u8 cfp_period;
+    /** CF peremeter : Maximum duration */
+	t_u16 cfp_max_duration;
+    /** CF peremeter : Remaining duration */
+	t_u16 cfp_duration_remaining;
+} MLAN_PACK_END IEEEtypes_CfParamSet_t, *pIEEEtypes_CfParamSet_t;
+
+/** IEEEtypes_IbssParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_IbssParamSet_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+    /** ATIM window value in milliseconds */
+	t_u16 atim_window;
+} MLAN_PACK_END IEEEtypes_IbssParamSet_t, *pIEEEtypes_IbssParamSet_t;
+
+/** IEEEtypes_SsParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_SsParamSet_t {
+    /** SS parameter : CF parameter set */
+	IEEEtypes_CfParamSet_t cf_param_set;
+    /** SS parameter : IBSS parameter set */
+	IEEEtypes_IbssParamSet_t ibss_param_set;
+} MLAN_PACK_END IEEEtypes_SsParamSet_t, *pIEEEtypes_SsParamSet_t;
+
+/** IEEEtypes_FhParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_FhParamSet_t {
+    /** FH parameter : Element ID */
+	t_u8 element_id;
+    /** FH parameter : Length */
+	t_u8 len;
+    /** FH parameter : Dwell time in milliseconds */
+	t_u16 dwell_time;
+    /** FH parameter : Hop set */
+	t_u8 hop_set;
+    /** FH parameter : Hop pattern */
+	t_u8 hop_pattern;
+    /** FH parameter : Hop index */
+	t_u8 hop_index;
+} MLAN_PACK_END IEEEtypes_FhParamSet_t, *pIEEEtypes_FhParamSet_t;
+
+/** IEEEtypes_DsParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_DsParamSet_t {
+    /** DS parameter : Element ID */
+	t_u8 element_id;
+    /** DS parameter : Length */
+	t_u8 len;
+    /** DS parameter : Current channel */
+	t_u8 current_chan;
+} MLAN_PACK_END IEEEtypes_DsParamSet_t, *pIEEEtypes_DsParamSet_t;
+
+/** IEEEtypes_PhyParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_PhyParamSet_t {
+    /** FH parameter set */
+	IEEEtypes_FhParamSet_t fh_param_set;
+    /** DS parameter set */
+	IEEEtypes_DsParamSet_t ds_param_set;
+} MLAN_PACK_END IEEEtypes_PhyParamSet_t, *pIEEEtypes_PhyParamSet_t;
+
+/** IEEEtypes_ERPInfo_t */
+typedef MLAN_PACK_START struct _IEEEtypes_ERPInfo_t {
+    /** Element ID */
+	t_u8 element_id;
+    /** Length */
+	t_u8 len;
+    /** ERP flags */
+	t_u8 erp_flags;
+} MLAN_PACK_END IEEEtypes_ERPInfo_t, *pIEEEtypes_ERPInfo_t;
+
+/** IEEEtypes_AId_t */
+typedef t_u16 IEEEtypes_AId_t;
+
+/** IEEEtypes_StatusCode_t */
+typedef t_u16 IEEEtypes_StatusCode_t;
+
+/** Fixed size in assoc_resp */
+#define ASSOC_RESP_FIXED_SIZE      6
+
+/** IEEEtypes_SeqCtl_t */
+typedef MLAN_PACK_START struct _IEEEtypes_SeqCtl_t {
+/** Fragment Number */
+	t_u16 FragNum:4;
+/** Sequence Number */
+	t_u16 SeqNum:12;
+} MLAN_PACK_END IEEEtypes_SeqCtl_t;
+
+/** IEEEtypes_MgmtHdr_t */
+typedef MLAN_PACK_START struct _IEEEtypes_MgmtHdr_t {
+/** FrmCtl*/
+	t_u16 FrmCtl;
+/** Duration*/
+	t_u16 Duration;
+/** Destination Addr*/
+	t_u8 DestAddr[6];
+/** Source Addr*/
+	t_u8 SrcAddr[6];
+/** BSSID */
+	t_u8 BssId[6];
+/** IEEEtypes_SeqCtl_t */
+	IEEEtypes_SeqCtl_t SeqCtl;
+} MLAN_PACK_END IEEEtypes_MgmtHdr_t;
+
+/** IEEEtypes_AssocRsp_t */
+typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t {
+    /** Capability information */
+	IEEEtypes_CapInfo_t capability;
+    /** Association response status code */
+	IEEEtypes_StatusCode_t status_code;
+    /** Association ID */
+	IEEEtypes_AId_t a_id;
+    /** IE data buffer */
+	t_u8 ie_buffer[1];
+} MLAN_PACK_END IEEEtypes_AssocRsp_t, *pIEEEtypes_AssocRsp_t;
+
+/** 802.11 supported rates */
+typedef t_u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES];
+
+/** cipher TKIP */
+#define WPA_CIPHER_TKIP		2
+/** cipher AES */
+#define WPA_CIPHER_AES_CCM	4
+/** AKM: 8021x */
+#define RSN_AKM_8021X		1
+/** AKM: PSK */
+#define RSN_AKM_PSK         2
+/** AKM: PSK SHA256 */
+#define RSN_AKM_PSK_SHA256	6
+
+/** AKM: PSK SHA256 */
+#define RSN_AKM_SAE	8
+/** AKM: PSK SHA256 */
+#define RSN_AKM_OWE	18
+
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN    4
+/** AKM Suite length */
+#define AKM_SUITE_LEN    4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT    7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT    6
+/** PMF ORing mask */
+#define PMF_MASK    0x00c0
+#endif
+
+/** wpa_suite_t */
+typedef MLAN_PACK_START struct _wpa_suite_t {
+    /** OUI */
+	t_u8 oui[3];
+    /** tyep */
+	t_u8 type;
+} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t;
+
+/** wpa_suite_ucast_t */
+typedef MLAN_PACK_START struct {
+	/* count */
+	t_u16 count;
+    /** wpa_suite list */
+	wpa_suite list[1];
+} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+
+/** IEEEtypes_Rsn_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t {
+    /** Rsn : Element ID */
+	t_u8 element_id;
+    /** Rsn : Length */
+	t_u8 len;
+    /** Rsn : version */
+	t_u16 version;
+    /** Rsn : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Rsn : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t;
+
+/** IEEEtypes_Wpa_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t {
+    /** Wpa : Element ID */
+	t_u8 element_id;
+    /** Wpa : Length */
+	t_u8 len;
+    /** Wpa : oui */
+	t_u8 oui[4];
+    /** version */
+	t_u16 version;
+    /** Wpa : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Wpa : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Reserved */
+	t_u8 reserved:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aifsn */
+	t_u8 aifsn:4;
+#else
+    /** Aifsn */
+	t_u8 aifsn:4;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn;   /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;		    /**< Ecw */
+	t_u16 tx_op_limit;		      /**< Tx op limit */
+} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t {
+
+    /**
+     * WMM Info IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [7]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [0]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+
+} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t {
+    /**
+     * WMM Parameter IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [24]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [1]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+    /** Reserved */
+	t_u8 reserved;
+
+    /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/** Enumerator for TSPEC direction */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e {
+
+	TSPEC_DIR_UPLINK = 0,
+	TSPEC_DIR_DOWNLINK = 1,
+	/* 2 is a reserved value */
+	TSPEC_DIR_BIDIRECT = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e;
+
+/** Enumerator for TSPEC PSB */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e {
+
+	TSPEC_PSB_LEGACY = 0,
+	TSPEC_PSB_TRIG = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e;
+
+/** Enumerator for TSPEC Ack Policy */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e {
+
+	TSPEC_ACKPOLICY_NORMAL = 0,
+	TSPEC_ACKPOLICY_NOACK = 1,
+	/* 2 is reserved */
+	TSPEC_ACKPOLICY_BLOCKACK = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e;
+
+/** Enumerator for TSPEC Trafffice type */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e {
+
+	TSPEC_TRAFFIC_APERIODIC = 0,
+	TSPEC_TRAFFIC_PERIODIC = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e;
+
+/** Data structure of WMM TSPEC information */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+	t_u8 Schedule:1;
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 AccessPolicy1:1;	/* ! */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+#else
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 AccessPolicy1:1;	/* ! */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 Schedule:1;
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t;
+
+/** Data structure of WMM TSPEC Nominal Size */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+	t_u16 Size:15;		/* ! Nominal size in octets */
+#else
+	t_u16 Size:15;		/* ! Nominal size in octets */
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t;
+
+/** Data structure of WMM TSPEC SBWA */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Whole:3;		/* ! Whole portion */
+	t_u16 Fractional:13;	/* ! Fractional portion */
+#else
+	t_u16 Fractional:13;	/* ! Fractional portion */
+	t_u16 Whole:3;		/* ! Whole portion */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA;
+
+/** Data structure of WMM TSPEC Body */
+typedef MLAN_PACK_START struct {
+
+    /** TS Information */
+	IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo;
+    /** NomMSDU size */
+	IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize;
+    /** MAximum MSDU size */
+	t_u16 MaximumMSDUSize;
+    /** Minimum Service Interval */
+	t_u32 MinServiceInterval;
+    /** Maximum Service Interval */
+	t_u32 MaxServiceInterval;
+    /** Inactivity Interval */
+	t_u32 InactivityInterval;
+    /** Suspension Interval */
+	t_u32 SuspensionInterval;
+    /** Service Start Time */
+	t_u32 ServiceStartTime;
+    /** Minimum Data Rate */
+	t_u32 MinimumDataRate;
+    /** Mean Data Rate */
+	t_u32 MeanDataRate;
+    /** Peak Data Rate */
+	t_u32 PeakDataRate;
+    /** Maximum Burst Size */
+	t_u32 MaxBurstSize;
+    /** Delay Bound */
+	t_u32 DelayBound;
+    /** Minimum Phy Rate */
+	t_u32 MinPHYRate;
+    /** Surplus BA Allowance */
+	IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance;
+    /** Medium Time */
+	t_u16 MediumTime;
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t;
+
+/** Data structure of WMM TSPEC all elements */
+typedef MLAN_PACK_START struct {
+    /** Element ID */
+	t_u8 ElementId;
+    /** Length */
+	t_u8 Len;
+    /** Oui Type */
+	t_u8 OuiType[4];	/* 00:50:f2:02 */
+    /** Ouisubtype */
+	t_u8 OuiSubType;	/* 01 */
+    /** Version */
+	t_u8 Version;
+
+    /** TspecBody */
+	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 {
+
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+    /** Action */
+	IEEEtypes_WMM_Tspec_Action_e action;
+    /** Dialog Token */
+	t_u8 dialogToken;
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t;
+
+/** WMM TSPEC AddTS request structure */
+typedef MLAN_PACK_START struct {
+
+    /** Tspec action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Status Code */
+	t_u8 statusCode;
+    /** tspecIE */
+	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 {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Reason Code */
+	t_u8 reasonCode;
+    /** tspecIE */
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t;
+
+/** union of WMM TSPEC structures */
+typedef MLAN_PACK_START union {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+
+    /** add TS request */
+	IEEEtypes_Action_WMM_AddTsReq_t addTsReq;
+    /** add TS response */
+	IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp;
+    /** Delete TS */
+	IEEEtypes_Action_WMM_DelTs_t delTs;
+
+} MLAN_PACK_END IEEEtypes_Action_WMMAC_t;
+
+/** union of WMM TSPEC & Action category */
+typedef MLAN_PACK_START union {
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+
+    /** wmmAc */
+	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;
+
+/** 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;
+    /** Channel width */
+	t_u8 chan_width;
+    /** Channel center frequency 1 */
+	t_u8 chan_center_freq_1;
+    /** Channel center frequency 2 */
+	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;
+    /** maximum tx power */
+	t_u8 max_tx_power;
+    /** channel center frequency */
+	t_u8 chan_center_freq;
+    /** channel width */
+	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;
+    /** MIMO capability count */
+	t_u8 MU_MIMO_capa_count;
+    /** stream under utilization */
+	t_u8 stream_underutilization;
+    /** VHT 40 util */
+	t_u8 VHT40_util;
+    /** VHT 80 util */
+	t_u8 VHT80_util;
+    /** VHT 160 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;
+    /** AP quiet mode */
+	t_u8 AP_quiet_mode;
+    /** Quiet count */
+	t_u8 quiet_count;
+    /** Quiet period */
+	t_u8 quiet_period;
+    /** Quiet duration */
+	t_u16 quiet_dur;
+    /** Quiet offset */
+	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;
+    /** New channel width */
+	t_u8 new_chan_width;
+    /** New channel center frequency 1 */
+	t_u8 new_chan_center_freq_1;
+    /** New channel center frequency 2 */
+	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;
+
+/** default channel switch count */
+#define DEF_CHAN_SWITCH_COUNT       5
+
+/*  IEEE Channel Switch Announcement Element (7.3.2.20) */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a chan switch element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;	/**< IEEE Element ID = 37 */
+	t_u8 len;		/**< Element length after id and len */
+	t_u8 chan_switch_mode;	/**< STA should not transmit any frames if 1 */
+	t_u8 new_channel_num;	/**< Channel # that AP/IBSS is moving to */
+	t_u8 chan_switch_count;	/**< # of TBTTs before channel switch */
+
+} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t;
+
+/** data structure for extended channel switch */
+typedef MLAN_PACK_START struct {
+   /** IEEE element ID = 60 */
+	t_u8 element_id;
+    /** Element length after id and len, set to 4 */
+	t_u8 len;
+    /** STA should not transmit any frames if 1 */
+	t_u8 chan_switch_mode;
+    /** Operate class # that AP/IBSS is moving to */
+	t_u8 new_oper_class;
+    /** Channel # that AP/IBSS is moving to */
+	t_u8 new_channel_num;
+    /** of TBTTs before channel switch */
+	t_u8 chan_switch_count;
+} MLAN_PACK_END IEEEtypes_ExtChanSwitchAnn_t;
+
+/*  IEEE Wide Bandwidth Channel Switch Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a wide bandwidth chan
+ *    switch element.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 194*/
+	IEEEtypes_Header_t ieee_hdr;
+    /** New channel width */
+	t_u8 new_channel_width;
+    /** New channel center frequency 0*/
+	t_u8 new_channel_center_freq0;
+    /** New channel center frequency 1*/
+	t_u8 new_channel_center_freq1;
+} MLAN_PACK_END IEEEtypes_WideBWChanSwitch_t;
+
+/*  IEEE VHT Transmit Power Envelope Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise the max
+ *    TX power in sepeate bandwidth and as a sub element of Channel Switch
+ *    Wrapper IE.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 195*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 tpc_info;		/**< Transmit Power Information>*/
+	t_u8 local_max_tp_20mhz;/**< Local Maximum Transmit Power for 20 MHZ>*/
+	t_u8 local_max_tp_40mhz;/**< Local Maximum Transmit Power for 40 MHZ>*/
+	t_u8 local_max_tp_80mhz;/**< Local Maximum Transmit Power for 80 MHZ>*/
+} MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t;
+
+/** 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 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
+
+/** 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;
+
+/**
+ *  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;
+    /** flag to filer only probe response */
+	t_u8 proberesp_only;
+} 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];
+} MLAN_PACK_END wlan_bgscan_cfg;
+#endif /* STA_SUPPORT */
+
+/** 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;
+} MLAN_PACK_END ChanStatistics_t;
+
+#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 */
+	t_u32 channel;
+
+    /** Freq */
+	t_u32 freq;
+
+    /** Beacon period */
+	t_u16 beacon_period;
+
+    /** ATIM window */
+	t_u32 atim_window;
+
+    /** ERP flags */
+	t_u8 erp_flags;
+
+    /** Type of network in use */
+	WLAN_802_11_NETWORK_TYPE network_type_use;
+
+    /** Network infrastructure mode */
+	t_u32 bss_mode;
+
+    /** Network supported rates */
+	WLAN_802_11_RATES supported_rates;
+
+    /** Supported data rates */
+	t_u8 data_rates[WLAN_SUPPORTED_RATES];
+
+    /** Current channel bandwidth
+     *  0 : 20MHZ
+     *  1 : 40MHZ
+     *  2 : 80MHZ
+     *  3 : 160MHZ
+     */
+	t_u8 curr_bandwidth;
+
+    /** Network band.
+     * BAND_B(0x01): 'b' band
+     * BAND_G(0x02): 'g' band
+     * BAND_A(0X04): 'a' band
+     */
+	t_u16 bss_band;
+
+    /** TSF timestamp from the current firmware TSF */
+	t_u64 network_tsf;
+
+    /** TSF value included in the beacon/probe response */
+	t_u8 time_stamp[8];
+
+    /** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+
+    /** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+
+    /** Capability information */
+	IEEEtypes_CapInfo_t cap_info;
+
+    /** WMM IE */
+	IEEEtypes_WmmParameter_t wmm_ie;
+
+    /** 802.11h BSS information */
+	wlan_11h_bss_info_t wlan_11h_bss_info;
+
+    /** Indicate disabling 11n when associate with AP */
+	t_u8 disable_11n;
+    /** 802.11n BSS information */
+    /** HT Capabilities IE */
+	IEEEtypes_HTCap_t *pht_cap;
+    /** HT Capabilities Offset */
+	t_u16 ht_cap_offset;
+    /** HT Information IE */
+	IEEEtypes_HTInfo_t *pht_info;
+    /** HT Information Offset */
+	t_u16 ht_info_offset;
+    /** 20/40 BSS Coexistence IE */
+	IEEEtypes_2040BSSCo_t *pbss_co_2040;
+    /** 20/40 BSS Coexistence Offset */
+	t_u16 bss_co_2040_offset;
+    /** Extended Capabilities IE */
+	IEEEtypes_ExtCap_t *pext_cap;
+    /** Extended Capabilities Offset */
+	t_u16 ext_cap_offset;
+    /** Overlapping BSS Scan Parameters IE */
+	IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param;
+    /** Overlapping BSS Scan Parameters Offset */
+	t_u16 overlap_bss_offset;
+
+    /** VHT Capabilities IE */
+	IEEEtypes_VHTCap_t *pvht_cap;
+    /** VHT Capabilities IE offset */
+	t_u16 vht_cap_offset;
+    /** VHT Operations IE */
+	IEEEtypes_VHTOprat_t *pvht_oprat;
+    /** VHT Operations IE offset */
+	t_u16 vht_oprat_offset;
+    /** VHT Transmit Power Envelope IE */
+	IEEEtypes_VHTtxpower_t *pvht_txpower;
+    /** VHT Transmit Power Envelope IE offset */
+	t_u16 vht_txpower_offset;
+    /** Extended Power Constraint IE */
+	IEEEtypes_ExtPwerCons_t *pext_pwer;
+    /** Extended Power Constraint IE offset */
+	t_u16 ext_pwer_offset;
+    /** Extended BSS Load IE  */
+	IEEEtypes_ExtBSSload_t *pext_bssload;
+    /** Extended BSS Load IE offset */
+	t_u16 ext_bssload_offset;
+    /** Quiet Channel IE */
+	IEEEtypes_QuietChan_t *pquiet_chan;
+    /** Quiet Channel IE offset */
+	t_u16 quiet_chan_offset;
+    /** Operating Mode Notification IE */
+	IEEEtypes_OperModeNtf_t *poper_mode;
+    /** Operating Mode Notification IE offset */
+	t_u16 oper_mode_offset;
+
+#ifdef STA_SUPPORT
+    /** Country information set */
+	IEEEtypes_CountryInfoFullSet_t country_info;
+#endif				/* STA_SUPPORT */
+
+    /** WPA IE */
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+    /** WPA IE offset in the beacon buffer */
+	t_u16 wpa_offset;
+    /** RSN IE */
+	IEEEtypes_Generic_t *prsn_ie;
+    /** RSN IE offset in the beacon buffer */
+	t_u16 rsn_offset;
+#ifdef STA_SUPPORT
+    /** WAPI IE */
+	IEEEtypes_Generic_t *pwapi_ie;
+    /** WAPI IE offset in the beacon buffer */
+	t_u16 wapi_offset;
+#endif
+	/* Hotspot 2.0 OSEN AKM  IE */
+	IEEEtypes_Generic_t *posen_ie;
+    /** osen IE offset in the beacon buffer */
+	t_u16 osen_offset;
+	/* Mobility domain IE */
+	IEEEtypes_MobilityDomain_t *pmd_ie;
+	/** Mobility domain IE offset in the beacon buffer */
+	t_u16 md_offset;
+
+    /** Pointer to the returned scan response */
+	t_u8 *pbeacon_buf;
+    /** Length of the stored scan response */
+	t_u32 beacon_buf_size;
+    /** Max allocated size for updated scan response */
+	t_u32 beacon_buf_size_max;
+
+} BSSDescriptor_t, *pBSSDescriptor_t;
+
+/**
+ *  Type definitions for TCLAS element
+ */
+#define TCLAS_CLASSIFIER_TYPE_4      4
+
+/**
+ *  IEEE TCLAS Classifier Type 4
+ *
+ *  Type definition for Classifier Type 4 in TCLAS element
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_IPv4_t {
+    /** Version */
+	t_u8 version;
+    /** Source IP address */
+	t_u8 source_ip_addr[4];
+    /** Dest IP address */
+	t_u8 dest_ip_addr[4];
+    /** Source port */
+	t_u8 source_port[2];
+    /** Dest port */
+	t_u8 dest_port[2];
+    /** DSCP value */
+	t_u8 dscp;
+    /** Protocol value */
+	t_u8 protocol;
+    /** Reserved */
+	t_u8 reserved;
+} MLAN_PACK_END IEEEtypes_TCLAS_IPv4_t;
+
+/**
+ *  IEEE TCLAS base
+ *
+ *  Type definition for common parameters for every
+ *    classifier type
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_Base_t {
+    /** Element id */
+	t_u8 element_id;
+    /** Element len */
+	t_u8 element_len;
+    /** User priority */
+	t_u8 user_priority;
+    /** Classifier type */
+	t_u8 classifier_type;
+    /** Classifier mask */
+	t_u8 classifier_mask;
+} MLAN_PACK_END IEEEtypes_TCLAS_Base_t;
+
+/**
+ *  IEEE TCLAS element
+ *
+ *  Type definition for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_t {
+    /** Base structure for TCLAS */
+	IEEEtypes_TCLAS_Base_t tclas_base;
+
+	union MLAN_PACK_START {
+	/** Classifier type 4 */
+		IEEEtypes_TCLAS_IPv4_t ipv4;
+	} MLAN_PACK_END classifier;
+} MLAN_PACK_END IEEEtypes_TCLAS_t;
+
+/**
+ *  TCLAS element TLV
+ *
+ *  Structure that defines TLV for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _tclasElemen_tlv {
+    /** Type */
+	t_u16 type;
+    /** Length of TLV */
+	t_u16 len;
+    /** Tclas Ie */
+	IEEEtypes_TCLAS_t tclas_ie;
+} MLAN_PACK_END tclas_element_tlv_t;
+
+#endif /* !_MLAN_IEEE_H_ */
diff --git a/wlan_sd8987/mlinux/mlan_ioctl.h b/wlan_sd8987/mlinux/mlan_ioctl.h
new file mode 100644
index 0000000..8e30e80
--- /dev/null
+++ b/wlan_sd8987/mlinux/mlan_ioctl.h
@@ -0,0 +1,4393 @@
+/** @file mlan_ioctl.h
+ *
+ *  @brief This file declares the IOCTL data structures and APIs.
+ *
+ *  Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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
+
+	/* 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,
+
+	/* 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_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,
+
+	/* 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,
+
+	/* 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,
+#if defined(DFS_TESTING_SUPPORT)
+	MLAN_OID_11H_DFS_TESTING = 0x00110003,
+#endif
+	MLAN_OID_11H_CHAN_REPORT_REQUEST = 0x00110004,
+	MLAN_OID_11H_CHAN_SWITCH_COUNT = 0x00110005,
+#ifdef DFS_TESTING_SUPPORT
+	MLAN_OID_11H_CHAN_NOP_INFO = 0x00110006,
+#endif
+
+	/* 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,
+
+	/* 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,
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	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,
+	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
+	MLAN_OID_MISC_MULTI_CHAN_CFG = 0x00200023,
+	MLAN_OID_MISC_MULTI_CHAN_POLICY = 0x00200024,
+#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_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_OPER_CLASS = 0x00200038,
+	MLAN_OID_MISC_PMIC_CFG = 0x00200039,
+	MLAN_OID_MISC_GET_TSF = 0x00200045,
+	MLAN_OID_MISC_GET_CHAN_REGION_CFG = 0x00200046,
+	MLAN_OID_MISC_OPER_CLASS_CHECK = 0x00200049,
+	MLAN_OID_MISC_DRCS_CFG = 0x00200050,
+
+	MLAN_OID_MISC_CWMODE_CTRL = 0x00200051,
+	MLAN_OID_MISC_DYN_BW = 0x00200053,
+	MLAN_OID_MISC_FW_DUMP_EVENT = 0x00200054,
+	MLAN_OID_MISC_ROBUSTCOEX = 0x00200056,
+	MLAN_OID_MISC_CFP_INFO = 0x00200060,
+	MLAN_OID_MISC_BOOT_SLEEP = 0x00200061,
+	MLAN_OID_MISC_ACS = 0x00200063,
+	MLAN_OID_MISC_GET_CHAN_TRPC_CFG = 0x00200070,
+	MLAN_OID_MISC_GET_REGIONPWR_CFG = 0x00200071,
+};
+
+/** 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
+};
+
+/** 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
+
+/** 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
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES      4
+
+/** Default number of probes to send on each channel */
+#define DEFAULT_PROBES  4
+
+/** MAX BG channel */
+#define MAX_BG_CHANNEL 14
+
+/**
+ *  @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;
+    /** 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;
+
+/** tx status event structure */
+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[0]; */
+} 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;
+
+/** 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;
+} 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;
+
+/** mlan_ssid_bssid  data structure for
+ *  MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS
+ */
+typedef struct _mlan_ssid_bssid {
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+    /** index in BSSID list, start from 1 */
+	t_u32 idx;
+    /** Receive signal strength in dBm */
+	t_s32 rssi;
+    /**channel*/
+	t_u16 channel;
+    /**mobility domain value*/
+	t_u16 ft_md;
+    /**ft capability*/
+	t_u8 ft_cap;
+    /**band*/
+	t_u16 bss_band;
+    /** channel flag */
+	t_u32 channel_flags;
+    /** host mlme flag*/
+	t_u8 host_mlme;
+    /** assoicate resp frame/ie from firmware */
+	mlan_ds_misc_assoc_rsp assoc_rsp;
+} mlan_ssid_bssid;
+
+/** 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   10
+/** 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           16
+
+/* 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
+
+/** 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;
+
+/** 5G band */
+#define BAND_CONFIG_5G        0x01
+/** 2.4 G band */
+#define BAND_CONFIG_2G        0x00
+/** 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;
+
+} mlan_uap_bss_param;
+
+/** mlan_uap_scan_channels */
+typedef struct _mlan_uap_scan_channels {
+    /** flag for remove nop channel*/
+	t_u8 remove_nop_channel;
+	/** num of removed channel */
+	t_u8 num_remvoed_channel;
+    /** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+    /** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+} mlan_uap_scan_channels;
+
+/** mlan_uap_oper_ctrl */
+typedef struct _mlan_uap_oper_ctrl {
+    /** control value
+      *  0: do nothing,
+      *  2: uap stops and restarts automaticaly
+     */
+	t_u16 ctrl_value;
+    /** channel opt
+      *  1: uap restart on default 2.4G/channel 6
+      *  2: uap restart on the band/channel configured by driver previously
+      *  3: uap restart on the band/channel specified by band_cfg and channel
+	*/
+	t_u16 chan_opt;
+    /** band cfg   0
+      *  0: 20Mhz  2: 40 Mhz  3: 80Mhz
+     */
+	t_u8 band_cfg;
+    /** channel */
+	t_u8 channel;
+} mlan_uap_oper_ctrl;
+
+/** mlan_uap_acs_scan */
+typedef struct _mlan_uap_acs_scan {
+	/** band */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 chan;
+} mlan_uap_acs_scan;
+
+/** station is authorized (802.1X) */
+#define STA_FLAG_AUTHORIZED     MBIT(1)
+/** Station is capable of receiving frames with short barker preamble */
+#define STA_FLAG_SHORT_PREAMBLE MBIT(2)
+/** station is WME/QoS capable */
+#define STA_FLAG_WME            MBIT(3)
+/** station uses management frame protection */
+#define STA_FLAG_MFP            MBIT(4)
+/** station is authenticated */
+#define STA_FLAG_AUTHENTICATED  MBIT(5)
+/** station is a TDLS peer */
+#define STA_FLAG_TDLS_PEER      MBIT(6)
+/** station is associated */
+#define STA_FLAG_ASSOCIATED     MBIT(7)
+/** mlan_ds_sta_info */
+typedef struct _mlan_ds_sta_info {
+    /** aid */
+	t_u16 aid;
+    /** peer_mac */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+    /** Listen Interval */
+	int listen_interval;
+    /** Capability Info */
+	t_u16 cap_info;
+    /** station flag */
+	t_u32 sta_flags;
+	/** tlv len */
+	t_u16 tlv_len;
+    /** tlv start */
+	t_u8 tlv[0];
+} 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 uap flag for MLAN_OID_BSS_START */
+		t_u8 host_based;
+	/** BSS param for AP mode for MLAN_OID_UAP_BSS_CONFIG */
+		mlan_uap_bss_param bss_config;
+	/** AP Wmm parameters for MLAN_OID_UAP_CFG_WMM_PARAM */
+		wmm_parameter_t ap_wmm_para;
+	/** ap scan channels for MLAN_OID_UAP_SCAN_CHANNELS*/
+		mlan_uap_scan_channels ap_scan_channels;
+	/** ap channel for MLAN_OID_UAP_CHANNEL*/
+		chan_band_info ap_channel;
+	/** ap operation control for MLAN_OID_UAP_OPER_CTRL*/
+		mlan_uap_oper_ctrl ap_oper_ctrl;
+	/** AP acs scan 	    MLAN_OID_UAP_ACS_SCAN */
+		mlan_uap_acs_scan ap_acs_scan;
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	/** BSS role for MLAN_OID_BSS_ROLE */
+		t_u8 bss_role;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	/** wifi direct mode for MLAN_OID_WIFI_DIRECT_MODE */
+		t_u16 wfd_mode;
+#endif
+#ifdef STA_SUPPORT
+	/** Listen interval for MLAN_OID_BSS_LISTEN_INTERVAL */
+		t_u16 listen_interval;
+	/** STA channel info for MLAN_OID_BSS_CHAN_INFO */
+		chan_band_info sta_channel;
+#endif
+#ifdef UAP_SUPPORT
+		/** STA info for MLAN_OID_UAP_ADD_STATION */
+		mlan_ds_sta_info sta_info;
+#endif
+	} param;
+} mlan_ds_bss, *pmlan_ds_bss;
+
+/* OTP Region info */
+typedef MLAN_PACK_START struct _otp_region_info {
+	t_u8 country_code[2];
+	t_u8 region_code;
+	t_u8 environment;
+	t_u16 force_reg:1;
+	t_u16 reserved:15;
+} MLAN_PACK_END otp_region_info_t;
+
+/** Type definition of mlan_ds_custom_reg_domain */
+typedef struct _mlan_ds_custom_reg_domain {
+	otp_region_info_t region;
+    /** num of 2g channels in custom_reg_domain */
+	t_u8 num_bg_chan;
+    /** num of 5g channels in custom_reg_domain */
+	t_u8 num_a_chan;
+    /** cfp table */
+	chan_freq_power_t cfp_tbl[0];
+} 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,
+};
+
+/** 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;
+    /** Ad-hoc channel bandwidth */
+	t_u32 adhoc_chan_bandwidth;
+    /** 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_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 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
+
+/** filt field param structure */
+struct filt_field_param {
+	/** Operation */
+	t_u8 operation;
+	/** Operand len */
+	t_u8 operand_len;
+	/** offset */
+	t_u16 offset;
+	/** Operand byte stream */
+	t_u8 operand_byte_stream[COALESCE_MAX_BYTESEQ];
+};
+
+/** coalesce rule structure */
+struct coalesce_rule {
+	/** max coalescing delay */
+	t_u16 max_coalescing_delay;
+	/** number of fields */
+	t_u8 num_of_fields;
+	/** packet type */
+	t_u8 pkt_type;
+	struct filt_field_param params[COALESCE_MAX_FILTERS];
+};
+
+/** coalesce configuration structure */
+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
+};
+
+/** Get stats org structure */
+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;
+} mlan_ds_get_stats, *pmlan_ds_get_stats;
+
+/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_uap_stats {
+    /** tkip mic failures */
+	t_u32 tkip_mic_failures;
+    /** ccmp decrypt errors */
+	t_u32 ccmp_decrypt_errors;
+    /** wep undecryptable count */
+	t_u32 wep_undecryptable_count;
+    /** wep icv error count */
+	t_u32 wep_icv_error_count;
+    /** decrypt failure count */
+	t_u32 decrypt_failure_count;
+    /** dot11 multicast tx count */
+	t_u32 mcast_tx_count;
+    /** dot11 failed count */
+	t_u32 failed_count;
+    /** dot11 retry count */
+	t_u32 retry_count;
+    /** dot11 multi retry count */
+	t_u32 multi_retry_count;
+    /** dot11 frame duplicate count */
+	t_u32 frame_dup_count;
+    /** dot11 rts success count */
+	t_u32 rts_success_count;
+    /** dot11 rts failure count */
+	t_u32 rts_failure_count;
+    /** dot11 ack failure count */
+	t_u32 ack_failure_count;
+    /** dot11 rx ragment count */
+	t_u32 rx_fragment_count;
+    /** dot11 mcast rx frame count */
+	t_u32 mcast_rx_frame_count;
+    /** dot11 fcs error count */
+	t_u32 fcs_error_count;
+    /** dot11 tx frame count */
+	t_u32 tx_frame_count;
+    /** dot11 rsna tkip cm invoked */
+	t_u32 rsna_tkip_cm_invoked;
+    /** dot11 rsna 4way handshake failures */
+	t_u32 rsna_4way_hshk_failures;
+} mlan_ds_uap_stats, *pmlan_ds_uap_stats;
+
+/** Mask of last beacon RSSI */
+#define BCN_RSSI_LAST_MASK              0x00000001
+/** Mask of average beacon RSSI */
+#define BCN_RSSI_AVG_MASK               0x00000002
+/** Mask of last data RSSI */
+#define DATA_RSSI_LAST_MASK             0x00000004
+/** Mask of average data RSSI */
+#define DATA_RSSI_AVG_MASK              0x00000008
+/** Mask of last beacon SNR */
+#define BCN_SNR_LAST_MASK               0x00000010
+/** Mask of average beacon SNR */
+#define BCN_SNR_AVG_MASK                0x00000020
+/** Mask of last data SNR */
+#define DATA_SNR_LAST_MASK              0x00000040
+/** Mask of average data SNR */
+#define DATA_SNR_AVG_MASK               0x00000080
+/** Mask of last beacon NF */
+#define BCN_NF_LAST_MASK                0x00000100
+/** Mask of average beacon NF */
+#define BCN_NF_AVG_MASK                 0x00000200
+/** Mask of last data NF */
+#define DATA_NF_LAST_MASK               0x00000400
+/** Mask of average data NF */
+#define DATA_NF_AVG_MASK                0x00000800
+/** Mask of all RSSI_INFO */
+#define ALL_RSSI_INFO_MASK              0x00000fff
+#define MAX_PATH_NUM                    3
+/** path A */
+#define PATH_A							0x01
+/** path B */
+#define PATH_B							0x02
+/** path AB */
+#define PATH_AB							0x03
+/** ALL the path */
+#define PATH_ALL						0
+/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */
+typedef struct _mlan_ds_get_signal {
+    /** Selector of get operation */
+	/*
+	 * Bit0:  Last Beacon RSSI,  Bit1:  Average Beacon RSSI,
+	 * Bit2:  Last Data RSSI,    Bit3:  Average Data RSSI,
+	 * Bit4:  Last Beacon SNR,   Bit5:  Average Beacon SNR,
+	 * Bit6:  Last Data SNR,     Bit7:  Average Data SNR,
+	 * Bit8:  Last Beacon NF,    Bit9:  Average Beacon NF,
+	 * Bit10: Last Data NF,      Bit11: Average Data NF
+	 *
+	 * Bit0: PATH A
+	 * Bit1: PATH B
+	 */
+	t_u16 selector;
+
+    /** RSSI */
+    /** RSSI of last beacon */
+	t_s16 bcn_rssi_last;
+    /** RSSI of beacon average */
+	t_s16 bcn_rssi_avg;
+    /** RSSI of last data packet */
+	t_s16 data_rssi_last;
+    /** RSSI of data packet average */
+	t_s16 data_rssi_avg;
+
+    /** SNR */
+    /** SNR of last beacon */
+	t_s16 bcn_snr_last;
+    /** SNR of beacon average */
+	t_s16 bcn_snr_avg;
+    /** SNR of last data packet */
+	t_s16 data_snr_last;
+    /** SNR of data packet average */
+	t_s16 data_snr_avg;
+
+    /** NF */
+    /** NF of last beacon */
+	t_s16 bcn_nf_last;
+    /** NF of beacon average */
+	t_s16 bcn_nf_avg;
+    /** NF of last data packet */
+	t_s16 data_nf_last;
+    /** NF of data packet average */
+	t_s16 data_nf_avg;
+} mlan_ds_get_signal, *pmlan_ds_get_signal;
+
+/** bit for 2.4 G antenna diversity */
+#define ANT_DIVERSITY_2G   MBIT(3)
+/** bit for 5 G antenna diversity */
+#define ANT_DIVERSITY_5G   MBIT(7)
+
+/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */
+typedef struct _mlan_fw_info {
+    /** Firmware version */
+	t_u32 fw_ver;
+    /** MAC address */
+	mlan_802_11_mac_addr mac_addr;
+    /** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+    /** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+    /** user's MCS setting */
+	t_u8 usr_dev_mcs_support;
+    /** 802.11ac device capabilities */
+	t_u32 hw_dot_11ac_dev_cap;
+    /** 802.11ac device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11ac_dev_cap_bg;
+    /** 802.11ac device Capabilities for 5GHz */
+	t_u32 usr_dot_11ac_dev_cap_a;
+    /** 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_u8 fw_bands;
+	/** region code */
+	t_u16 region_code;
+    /** 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;
+} mlan_fw_info, *pmlan_fw_info;
+
+/** Version string buffer length */
+#define MLAN_MAX_VER_STR_LEN    128
+
+/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */
+typedef struct _mlan_ver_ext {
+    /** Selected version string */
+	t_u32 version_str_sel;
+    /** Version string */
+	char version_str[MLAN_MAX_VER_STR_LEN];
+} mlan_ver_ext, *pmlan_ver_ext;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+    /** Extended Capabilities value */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit77: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 MaxAMSDU:2;	/* bit 63-bit 64 */
+	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 MaxAMSDU:2;	/* bit 63-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 rsvdBit77:1;	/* bit 77 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#endif
+
+/** ExtCap : TDLS prohibited */
+#define IS_EXTCAP_TDLS_PROHIBITED(ext_cap) (ext_cap.TDLSProhibited)
+/** ExtCap : TDLS channel switch prohibited */
+#define IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ext_cap) (ext_cap.TDLSChlSwitchProhib)
+
+/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */
+typedef struct _mlan_bss_info {
+    /** BSS mode */
+	t_u32 bss_mode;
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** Table index */
+	t_u32 scan_table_idx;
+    /** Channel */
+	t_u32 bss_chan;
+    /** Band */
+	t_u8 bss_band;
+    /** Region code */
+	t_u32 region_code;
+    /** Connection status */
+	t_u32 media_connected;
+    /** Radio on */
+	t_u32 radio_on;
+    /** Max power level in dBm */
+	t_s32 max_power_level;
+    /** Min power level in dBm */
+	t_s32 min_power_level;
+    /** Adhoc state */
+	t_u32 adhoc_state;
+    /** NF of last beacon */
+	t_s32 bcn_nf_last;
+    /** wep status */
+	t_u32 wep_status;
+    /** scan block status */
+	t_u8 scan_block;
+     /** Host Sleep configured flag */
+	t_u32 is_hs_configured;
+    /** Deep Sleep flag */
+	t_u32 is_deep_sleep;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+#ifdef STA_SUPPORT
+    /** Capability Info */
+	t_u16 capability_info;
+    /** Beacon Interval */
+	t_u16 beacon_interval;
+    /** Listen Interval */
+	t_u16 listen_interval;
+    /** Association Id  */
+	t_u16 assoc_id;
+    /** AP/Peer supported rates */
+	t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES];
+    /** extend capability for AP */
+	ExtCap_t ext_cap;
+#endif				/* STA_SUPPORT */
+    /** Mobility Domain ID */
+	t_u16 mdid;
+    /** FT Capability policy */
+	t_u8 ft_cap;
+    /** 11h active */
+	t_bool is_11h_active;
+    /** dfs check channel */
+	t_u8 dfs_check_channel;
+} mlan_bss_info, *pmlan_bss_info;
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID     8
+
+/** Max RX Win size */
+#define MAX_RX_WINSIZE  64
+
+/** rx_reorder_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** TA */
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+    /** Start window */
+	t_u32 start_win;
+    /** Window size */
+	t_u32 win_size;
+    /** amsdu flag */
+	t_u8 amsdu;
+    /** buffer status */
+	t_u32 buffer[MAX_RX_WINSIZE];
+} rx_reorder_tbl;
+
+/** tx_ba_stream_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** RA */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+    /** amsdu flag */
+	t_u8 amsdu;
+} tx_ba_stream_tbl;
+
+/** Debug command number */
+#define DBG_CMD_NUM	10
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** 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;
+
+/** 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;
+    /** Corresponds to is_hs_configured member of mlan_adapter */
+	t_u8 is_hs_configured;
+    /** Corresponds to hs_activated member of mlan_adapter */
+	t_u8 hs_activated;
+    /** Corresponds to pps_uapsd_mode member of mlan_adapter */
+	t_u16 pps_uapsd_mode;
+    /** Corresponds to sleep_period.period member of mlan_adapter */
+	t_u16 sleep_pd;
+    /** Corresponds to wmm_qosinfo member of mlan_private */
+	t_u8 qos_cfg;
+    /** Corresponds to tx_lock_flag member of mlan_adapter */
+	t_u8 tx_lock_flag;
+    /** Corresponds to port_open member of mlan_private */
+	t_u8 port_open;
+    /** bypass pkt count */
+	t_u16 bypass_pkt_count;
+    /** Corresponds to scan_processing member of mlan_adapter */
+	t_u32 scan_processing;
+    /** Corresponds to mlan_processing member of mlan_adapter */
+	t_u32 mlan_processing;
+    /** Corresponds to main_lock_flag member of mlan_adapter */
+	t_u32 main_lock_flag;
+    /** Corresponds to main_process_cnt member of mlan_adapter */
+	t_u32 main_process_cnt;
+	/** Corresponds to delay_task_flag member of mlan_adapter */
+	t_u32 delay_task_flag;
+    /** mlan_rx_processing */
+	t_u32 mlan_rx_processing;
+    /** rx pkts queued */
+	t_u32 rx_pkts_queued;
+    /** Number of host to card command failures */
+	t_u32 num_cmd_host_to_card_failure;
+    /** Number of host to card sleep confirm failures */
+	t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+    /** Number of host to card Tx failures */
+	t_u32 num_tx_host_to_card_failure;
+    /** Number of allocate buffer failure */
+	t_u32 num_alloc_buffer_failure;
+	/** Number of pkt dropped */
+	t_u32 num_pkt_dropped;
+    /** 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;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** Number of packets tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+    /** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+	/** last recv wr_bitmap */
+	t_u32 last_recv_wr_bitmap;
+    /** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+    /** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+	/** last len for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+    /** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+    /** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+    /** last mp_index */
+	t_u8 last_mp_index;
+    /** buffer for mp debug */
+	t_u8 *mpa_buf;
+    /** length info for mp buf size */
+	t_u32 mpa_buf_size;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** Number of packets rx aggr */
+	t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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 command failures */
+	t_u32 num_cons_cmd_assoc_failure;
+    /** Number of Tx timeouts */
+	t_u32 num_tx_timeout;
+    /** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+    /** Number of command timeouts */
+	t_u32 dbg_num_cmd_timeout;
+    /** Timeout command ID */
+	t_u16 timeout_cmd_id;
+    /** Timeout command action */
+	t_u16 timeout_cmd_act;
+    /** List of last command IDs */
+	t_u16 last_cmd_id[DBG_CMD_NUM];
+    /** List of last command actions */
+	t_u16 last_cmd_act[DBG_CMD_NUM];
+    /** Last command index */
+	t_u16 last_cmd_index;
+    /** List of last command response IDs */
+	t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+    /** Last command response index */
+	t_u16 last_cmd_resp_index;
+    /** List of last events */
+	t_u16 last_event[DBG_CMD_NUM];
+    /** Last event index */
+	t_u16 last_event_index;
+    /** Number of no free command node */
+	t_u16 num_no_cmd_node;
+    /** pending command id */
+	t_u16 pending_cmd;
+    /** time stamp for dnld last cmd */
+	t_u32 dnld_cmd_in_secs;
+    /** Corresponds to data_sent member of mlan_adapter */
+	t_u8 data_sent;
+    /** Corresponds to cmd_sent member of mlan_adapter */
+	t_u8 cmd_sent;
+    /** SDIO multiple port read bitmap */
+	t_u32 mp_rd_bitmap;
+    /** SDIO multiple port write bitmap */
+	t_u32 mp_wr_bitmap;
+    /** Current available port for read */
+	t_u8 curr_rd_port;
+    /** Current available port for write */
+	t_u8 curr_wr_port;
+    /** Corresponds to cmdresp_received member of mlan_adapter */
+	t_u8 cmd_resp_received;
+    /** Corresponds to event_received member of mlan_adapter */
+	t_u8 event_received;
+    /**  pendig tx pkts */
+	t_u32 tx_pkts_queued;
+#ifdef UAP_SUPPORT
+    /**  pending bridge pkts */
+	t_u16 num_bridge_pkts;
+    /**  dropped pkts */
+	t_u32 num_drop_pkts;
+#endif
+    /** FW hang report */
+	t_u8 fw_hang_report;
+    /** mlan_adapter pointer */
+	t_void *mlan_adapter;
+    /** mlan_adapter_size */
+	t_u32 mlan_adapter_size;
+    /** mlan_priv vector */
+	t_void *mlan_priv[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_size */
+	t_u32 mlan_priv_size[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_num */
+	t_u8 mlan_priv_num;
+} mlan_debug_info, *pmlan_debug_info;
+
+#ifdef UAP_SUPPORT
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS         MAX_STA_COUNT
+
+/** station info */
+typedef struct _sta_info {
+    /** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+    /** station bandmode */
+	t_u8 bandmode;
+    /** station stats */
+	sta_stats stats;
+} sta_info;
+
+/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */
+typedef struct _mlan_ds_sta_list {
+    /** station count */
+	t_u16 sta_count;
+    /** station list */
+	sta_info info[MAX_NUM_CLIENTS];
+} mlan_ds_sta_list, *pmlan_ds_sta_list;
+#endif
+
+/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */
+typedef struct _mlan_ds_get_info {
+    /** Sub-command */
+	t_u32 sub_command;
+
+    /** Status information parameter */
+	union {
+	/** Signal information for MLAN_OID_GET_SIGNAL */
+		mlan_ds_get_signal signal;
+		/** Signal path id for MLAN_OID_GET_SIGNAL_EXT */
+		t_u16 path_id;
+	/** Signal information for MLAN_OID_GET_SIGNAL_EXT */
+		mlan_ds_get_signal signal_ext[MAX_PATH_NUM];
+	/** Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_get_stats stats;
+	/** 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_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_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,
+};
+
+/** 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
+/** PMK length */
+#define MLAN_PMK_HEXSTR_LENGTH        64
+/* A few details needed for WEP (Wireless Equivalent Privacy) */
+/** 104 bits */
+#define MAX_WEP_KEY_SIZE	13
+/** 40 bits RC4 - WEP */
+#define MIN_WEP_KEY_SIZE	5
+/** packet number size */
+#define PN_SIZE			16
+/** max seq size of wpa/wpa2 key */
+#define SEQ_MAX_SIZE        8
+
+/** key flag for tx_seq */
+#define KEY_FLAG_TX_SEQ_VALID	0x00000001
+/** key flag for rx_seq */
+#define KEY_FLAG_RX_SEQ_VALID	0x00000002
+/** key flag for group key */
+#define KEY_FLAG_GROUP_KEY      0x00000004
+/** key flag for tx */
+#define KEY_FLAG_SET_TX_KEY     0x00000008
+/** key flag for mcast IGTK */
+#define KEY_FLAG_AES_MCAST_IGTK 0x00000010
+/** key flag for remove key */
+#define KEY_FLAG_REMOVE_KEY     0x80000000
+/** key flag for GCMP */
+#define KEY_FLAG_GCMP           0x00000020
+/** key flag for GCMP_256 */
+#define KEY_FLAG_GCMP_256           0x00000040
+/** key flag for CCMP_256 */
+#define KEY_FLAG_CCMP_256           0x00000080
+/** Type definition of mlan_ds_encrypt_key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */
+typedef struct _mlan_ds_encrypt_key {
+    /** Key disabled, all other fields will be
+     *  ignore when this flag set to MTRUE
+     */
+	t_u32 key_disable;
+    /** key removed flag, when this flag is set
+     *  to MTRUE, only key_index will be check
+     */
+	t_u32 key_remove;
+    /** Key index, used as current tx key index
+     *  when is_current_wep_key is set to MTRUE
+     */
+	t_u32 key_index;
+    /** Current Tx key flag */
+	t_u32 is_current_wep_key;
+    /** Key length */
+	t_u32 key_len;
+    /** Key */
+	t_u8 key_material[MLAN_MAX_KEY_LENGTH];
+    /** mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+    /** wapi key flag */
+	t_u32 is_wapi_key;
+    /** Initial packet number */
+	t_u8 pn[PN_SIZE];
+    /** key flags */
+	t_u32 key_flags;
+} mlan_ds_encrypt_key, *pmlan_ds_encrypt_key;
+
+/** Type definition of mlan_passphrase_t */
+typedef struct _mlan_passphrase_t {
+    /** Length of passphrase */
+	t_u32 passphrase_len;
+    /** Passphrase */
+	t_u8 passphrase[MLAN_MAX_PASSPHRASE_LENGTH];
+} mlan_passphrase_t;
+
+/** Type 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;
+	/** 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;
+
+/*-----------------------------------------------------------------*/
+/** 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_AUTO = 0xFF,
+};
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE   18
+
+/** 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;
+} 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;
+	} param;
+} mlan_ds_power_cfg, *pmlan_ds_power_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;
+	} 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;
+
+/** 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,
+};
+
+/** 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 */
+/*-----------------------------------------------------------------*/
+#if defined(DFS_TESTING_SUPPORT)
+/** 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;
+} 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;
+#endif
+
+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;
+
+/** 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;
+#if defined(DFS_TESTING_SUPPORT)
+	/** 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;
+#endif
+		mlan_ds_11h_chan_rep_req chan_rpt_req;
+		t_s8 cs_count;
+	} param;
+} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Miscellaneous Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** 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;
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** 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;
+
+/** 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;
+
+/* 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_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;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** flag for NOA */
+#define WIFI_DIRECT_NOA         1
+/** flag for OPP_PS */
+#define WIFI_DIRECT_OPP_PS      2
+/** Type definition of mlan_ds_wifi_direct_config
+ *  for MLAN_OID_MISC_WIFI_DIRECT_CONFIG
+ */
+typedef struct _mlan_ds_wifi_direct_config {
+    /** flags for NOA/OPP_PS */
+	t_u8 flags;
+     /** NoA enable/disable */
+	t_u8 noa_enable;
+    /** index */
+	t_u16 index;
+    /** NoA count */
+	t_u8 noa_count;
+    /** NoA duration */
+	t_u32 noa_duration;
+    /** NoA interval */
+	t_u32 noa_interval;
+    /** opp ps enable/disable */
+	t_u8 opp_ps_enable;
+    /** CT window value */
+	t_u8 ct_window;
+} mlan_ds_wifi_direct_config;
+#endif
+
+#if defined(STA_SUPPORT)
+/** mlan_ds_misc_pmfcfg structure */
+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
+
+/** mlan_ds_multi_chan_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_multi_chan_cfg {
+    /** Channel Time */
+	t_u32 channel_time;
+    /** Buffer Weight */
+	t_u8 buffer_weight;
+    /** tlv len */
+	t_u16 tlv_len;
+    /** TLV buffer */
+	t_u8 tlv_buf[0];
+} MLAN_PACK_END mlan_ds_multi_chan_cfg;
+
+/** mlan_ds_drcs_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_drcs_cfg {
+    /** Channel Index*/
+	t_u16 chan_idx;
+    /** Channel time (in TU) for chan_idx */
+	t_u8 chantime;
+    /** Channel swith time (in TU) for chan_idx */
+	t_u8 switchtime;
+    /** Undoze time (in TU) for chan_idx */
+	t_u8 undozetime;
+    /** Rx traffic control scheme when channel switch*/
+    /** only valid for GC/STA interface*/
+	t_u8 mode;
+} MLAN_PACK_END mlan_ds_drcs_cfg;
+
+/**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
+
+/** mlan_ds_misc_dfs_repeater structure */
+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
+
+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;
+
+/** 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;
+
+/** channel statictics */
+typedef struct _ChStat_t {
+    /** channle number */
+	t_u8 chan_num;
+    /** total network */
+	t_u16 total_networks;
+    /** busy duration */
+	t_u16 cca_busy_duration;
+} ChStat_t, *pChStat_t;
+
+#define MAX_CH_STATS    MAX_BG_CHANNEL
+/** Type definition of mlan_acs_scan */
+typedef struct _mlan_ds_misc_acs {
+    /** Best Channel Number */
+	t_u8 best_ch;
+    /** Scan channel gap */
+	t_u16 scan_chan_gap;
+    /** Channel Statistics Number */
+	t_u8 ch_stats_num;
+    /** Channel Statistics */
+	ChStat_t ch_stats[MAX_CH_STATS];
+} mlan_ds_misc_acs, *pmlan_ds_misc_acs;
+
+/** 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;
+
+typedef struct _mlan_ds_misc_chnrgpwr_cfg {
+    /** length */
+	t_u16 length;
+    /** chnrgpwr buf */
+	t_u8 chnrgpwr_buf[2048];
+} mlan_ds_misc_chnrgpwr_cfg;
+
+/** 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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;
+	/** 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;
+	/** Tx control */
+		t_u32 tx_control;
+#if defined(STA_SUPPORT)
+		mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+	/** Multi-channel config for MLAN_OID_MISC_MULTI_CHAN_CFG */
+		mlan_ds_multi_chan_cfg multi_chan_cfg;
+	/** Multi-channel policy for MLAN_OID_MISC_MULTI_CHAN_POLICY */
+		t_u16 multi_chan_policy;
+	/** channel drcs time slicing config for MLAN_OID_MISC_DRCS_CFG */
+		mlan_ds_drcs_cfg drcs_cfg[2];
+#ifdef WIFI_DIRECT_SUPPORT
+		mlan_ds_wifi_direct_config p2p_config;
+#endif
+		mlan_ds_coalesce_cfg coalesce_cfg;
+		t_u8 low_pwr_mode;
+		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;
+	/** Bandwidth Channel operation */
+		mlan_ds_bw_chan_oper bw_chan_oper;
+    /** misc tsf */
+		t_u64 misc_tsf;
+    /** Custom regulatory domain */
+		mlan_ds_custom_reg_domain custom_reg_domain;
+		mlan_ds_misc_robustcoex_params robustcoexparams;
+    /** boot sleep enable or disable */
+		t_u16 boot_sleep;
+    /** ACS */
+		mlan_ds_misc_acs acs;
+		mlan_ds_misc_chan_trpc_cfg trpc_cfg;
+		mlan_ds_misc_chnrgpwr_cfg rgchnpwr_cfg;
+	} 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 100644
index 0000000..644bebb
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_cfg80211.c
@@ -0,0 +1,4055 @@
+/** @file moal_cfg80211.c
+  *
+  * @brief This file contains the functions for CFG80211.
+  *
+  * Copyright (C) 2011-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include    "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},
+};
+
+/********************************************************
+				Global Variables
+********************************************************/
+extern int cfg80211_wext;
+
+struct ieee80211_supported_band cfg80211_band_2ghz = {
+	.channels = cfg80211_channels_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,
+	.n_channels = ARRAY_SIZE(cfg80211_channels_5ghz),
+	.bitrates = cfg80211_rates + 4,
+	.n_bitrates = ARRAY_SIZE(cfg80211_rates) - 4,
+};
+
+#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
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+extern int host_mlme;
+#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;
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+								      ,
+								      (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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+								      ,
+								      (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:
+	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;
+			memcpy(priv->uap_wep_key[key_index].key, key, key_len);
+			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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+		    cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+		    cipher != WLAN_CIPHER_SUITE_GCMP &&
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+		    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) {
+			memcpy(sec->param.encrypt_key.key_material, key,
+			       key_len);
+			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) {
+				memcpy(sec->param.encrypt_key.pn, seq, PN_SIZE);
+				DBG_HEXDUMP(MCMD_D, "WAPI PN",
+					    sec->param.encrypt_key.pn, seq_len);
+			}
+		}
+		if (addr) {
+			memcpy(sec->param.encrypt_key.mac_addr, addr, ETH_ALEN);
+			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;
+		} else {
+			memcpy(sec->param.encrypt_key.mac_addr, bcast_addr,
+			       ETH_ALEN);
+			sec->param.encrypt_key.key_flags =
+				KEY_FLAG_GROUP_KEY | KEY_FLAG_SET_TX_KEY;
+		}
+		if (seq && seq_len) {
+			memcpy(sec->param.encrypt_key.pn, seq, seq_len);
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_RX_SEQ_VALID;
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+		if (cipher == WLAN_CIPHER_SUITE_GCMP)
+			sec->param.encrypt_key.key_flags |= KEY_FLAG_GCMP;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+		else if (cipher == WLAN_CIPHER_SUITE_GCMP_256)
+			sec->param.encrypt_key.key_flags |= KEY_FLAG_GCMP_256;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+		else 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+		    || cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256
+#endif
+			) {
+
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_AES_MCAST_IGTK;
+		}
+	} 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)
+			memcpy(sec->param.encrypt_key.mac_addr, addr, ETH_ALEN);
+	}
+
+	/* 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);
+		/* 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
+
+#if defined(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, channnel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		default:
+			PRINTM(MMSG,
+			       "wlan: %s Unknow P2P Action Frame, channel=%d, subtype=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0, subtype);
+			break;
+		}
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @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 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;
+	}
+
+	/* 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 && V14_FEATURE */
+
+/**
+ * @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 CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
+				  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);
+
+#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 = 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 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
+
+	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_ADHOC:
+		bss->param.bss_mode = MLAN_BSS_MODE_IBSS;
+		priv->wdev->iftype = NL80211_IFTYPE_ADHOC;
+		PRINTM(MINFO, "Setting interface type to adhoc\n");
+		break;
+	case NL80211_IFTYPE_STATION:
+#if defined(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 && V14_FEATURE */
+#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;
+#if defined(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 && V14_FEATURE */
+	case NL80211_IFTYPE_AP:
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	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 (MLAN_STATUS_SUCCESS != status) {
+		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
+	mlan_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 == MLAN_FRAG_RTS_DISABLED)
+		rts_thr = MLAN_RTS_MAX_VALUE;
+	if (frag_thr == 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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+		      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;
+	}
+	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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+		      bool pairwise,
+#endif
+		      const t_u8 *mac_addr)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
+
+	ENTER();
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_del_key in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+			      , bool ucast, bool mcast
+#endif
+	)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
+	mlan_bss_info bss_info;
+
+	ENTER();
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+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
+
+#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);
+		memcpy(entry->bssid, pmksa->bssid, ETH_ALEN);
+		memcpy(entry->pmkid, pmksa->pmkid, 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);
+		memcpy(entry->pmkid, pmksa->pmkid, 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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+			  struct net_device *dev,
+#endif
+			  struct ieee80211_channel *chan,
+			  enum nl80211_channel_type channel_type)
+{
+	int ret = 0;
+	moal_private *priv = NULL;
+
+	ENTER();
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+/**
+ * @brief Functions check whether the pattern is supported
+ *
+ * @param pat             A pointer to cfg80211_pkt_pattern structure
+ * @param byte_seq        Byte sequence
+ * @param max_byte_seq    Maximum byte sequence
+ *
+ * @return                true -- success, otherwise false
+ */
+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) {
+				memcpy(byte_seq + valid_byte_cnt,
+				       &pat->pattern[j * 8 + k], 1);
+				valid_byte_cnt++;
+				if (dont_care_byte)
+					return false;
+			} else {
+				if (valid_byte_cnt)
+					dont_care_byte = true;
+			}
+
+			if (valid_byte_cnt > max_byte_seq)
+				return false;
+		}
+	}
+
+	byte_seq[max_byte_seq] = valid_byte_cnt;
+
+	return true;
+}
+
+/**
+ * @brief Get coalesce packet type
+ *
+ * @param byte_seq        Byte Sequence
+
+ * @return                0 -- success, otherwise fail
+ */
+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;
+}
+
+/**
+ * @brief Functions fills the coalesce rule information
+ *
+ * @param crule           A pointer to cfg80211_coalesce_rules structure
+ * @param mrule           A pointer to coalesce_rules structure
+ *
+ * @return                0-- success, otherwise fail
+ */
+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];
+		memcpy(param->operand_byte_stream, byte_seq,
+		       param->operand_len);
+		param->offset = crule->patterns[i].pkt_offset;
+		param++;
+
+		mrule->num_of_fields++;
+	}
+
+	if (!mrule->pkt_type) {
+		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
+ */
+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;
+
+	memcpy(&misc_cfg->param.coalesce_cfg, 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	/* Fill MCS rates */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	rate_cfg->bitmap_rates[2] = mask->control[band].ht_mcs[0];
+#else
+	rate_cfg->bitmap_rates[2] = mask->control[band].mcs[0];
+#endif
+#if defined(SD_8XXX)
+	if (priv->phandle->card_type ==
+#if defined(SD_8XXX)
+	    CARD_TYPE_SD8797
+#endif
+		)
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		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 (MLAN_STATUS_SUCCESS != status) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+/**
+ * @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 (MLAN_STATUS_SUCCESS != status) {
+		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 (MLAN_STATUS_SUCCESS != status) {
+		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
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+/**
+ * @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
+/**
+ * @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
+{
+#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);
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	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: mgmt_subtype_mask=0x%x last_mgmt_subtype_mask=0x%x\n",
+	       dev->name, 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. */
+		status = 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+/**
+ * @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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		      struct net_device *dev,
+#else
+		      struct wireless_dev *wdev,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		      struct cfg80211_mgmt_tx_params *params,
+#else
+		      struct ieee80211_channel *chan, bool offchan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+		      enum nl80211_channel_type channel_type,
+		      bool channel_type_valid,
+#endif
+		      unsigned int wait, const u8 *buf, size_t len,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+		      bool no_cck,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+		      bool dont_wait_for_ack,
+#endif
+#endif
+		      u64 * cookie)
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct net_device *dev = wdev->netdev;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	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;
+
+	ENTER();
+
+	if (buf == NULL || len == 0) {
+		PRINTM(MERROR, "woal_cfg80211_mgmt_tx() corrupt data\n");
+		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) &&
+	    ieee80211_is_probe_resp(((struct ieee80211_mgmt *)buf)->
+				    frame_control)) {
+		PRINTM(MIOCTL, "Skip send probe_resp in GO/UAP mode\n");
+		goto done;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	if ((ieee80211_is_action(((struct ieee80211_mgmt *)buf)->frame_control)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	     || 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 ((priv->phandle->chan.center_freq !=
+			     chan->center_freq)
+				) {
+				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 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;
+		}
+#ifdef STA_CFG80211
+		/** cancel pending scan */
+		woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+#endif
+
+		duration =
+			(wait >
+			 MGMT_TX_DEFAULT_WAIT_TIME) ? wait :
+			MGMT_TX_DEFAULT_WAIT_TIME;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+		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 connnection fail */
+			woal_sched_timeout(2);
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+			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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+			priv->phandle->channel_type = channel_type;
+#endif
+			memcpy(&priv->phandle->chan, chan,
+			       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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+	*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;
+	/* Add pkt_type and tx_control */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset, &pkt_type, sizeof(pkt_type));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type), &tx_control,
+	       sizeof(tx_control));
+	/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */
+#define PACKET_ADDR4_POS		(2 + 2 + 6 + 6 + 6 + 2)
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &packet_len,
+	       sizeof(packet_len));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
+	       sizeof(packet_len), buf, PACKET_ADDR4_POS);
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
+	       sizeof(packet_len)
+	       + PACKET_ADDR4_POS, addr, MLAN_MAC_ADDR_LENGTH);
+	memcpy(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);
+
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	     || host_mlme
+#endif
+	    )) {
+		pmbuf->flags = MLAN_BUF_FLAG_TX_STATUS;
+		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) {
+				memcpy(skb->data, buf, 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->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,
+		 * becuase 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		     || host_mlme
+#endif
+		    )) {
+			if (tx_info)
+				break;
+			else
+				woal_sched_timeout(30);
+		}
+
+		/* Notify the mgmt tx status */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		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 int
+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 *custom_ie = NULL;
+	t_u8 *pos = NULL;
+	t_u16 len = 0;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	custom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), GFP_KERNEL);
+	if (!custom_ie) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	custom_ie->type = TLV_TYPE_MGMT_IE;
+
+	pos = (t_u8 *)custom_ie->ie_data_list;
+	if (beacon_ies_data) {
+		len = sizeof(*beacon_ies_data) - MAX_IE_SIZE
+			+ beacon_ies_data->ie_length;
+		memcpy(pos, beacon_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+
+	if (proberesp_ies_data) {
+		len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE
+			+ proberesp_ies_data->ie_length;
+		memcpy(pos, proberesp_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+
+	if (assocresp_ies_data) {
+		len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE
+			+ assocresp_ies_data->ie_length;
+		memcpy(pos, assocresp_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+
+	if (probereq_ies_data) {
+		len = sizeof(*probereq_ies_data) - MAX_IE_SIZE
+			+ probereq_ies_data->ie_length;
+		memcpy(pos, probereq_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+	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;
+
+	memcpy(&misc->param.cust_ie, custom_ie, sizeof(mlan_ds_misc_custom_ie));
+
+	status = woal_request_ioctl(priv, ioctl_req, wait_option);
+	if (MLAN_STATUS_SUCCESS != status) {
+		ret = -EFAULT;
+		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;
+	}
+
+	if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL)
+		ret = -EFAULT;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	kfree(custom_ie);
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,14,0)
+/**
+ * @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;
+
+		memcpy(qos_map_ie.data, (t_u8 *)qos_map->dscp_exception,
+		       2 * qos_map->num_des);
+		memcpy(&qos_map_ie.data[2 * qos_map->num_des],
+		       (t_u8 *)qos_map->up, sizeof(qos_map->up));
+		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);
+
+		/* 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 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_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 */
+					memcpy(ie_out + out_len, pos,
+					       length + 2);
+					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) {
+					memcpy(ie_out + out_len, pos,
+					       length + 2);
+					out_len += length + 2;
+				}
+			} 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) {
+					memcpy(ie_out + out_len, pos,
+					       length + 2);
+					out_len += length + 2;
+				}
+			} else if (mask & IE_MASK_VENDOR) {
+				memcpy(ie_out + out_len, pos, length + 2);
+				out_len += length + 2;
+			}
+		}
+		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 specifc 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;
+	t_u8 id = 0;
+
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		id = *pos;
+		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 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_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;
+	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;
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+		case WLAN_EID_ERP_INFO:
+		case HT_CAPABILITY:
+		case HT_OPERATION:
+		case VHT_CAPABILITY:
+		case VHT_OPERATION:
+		case REGULATORY_CLASS:
+		case OVERLAPBSSSCANPARAM:
+		case WAPI_IE:
+			break;
+		case EXT_CAPABILITY:
+			/* filter out EXTCAP */
+			if (wps_flag & IE_MASK_EXTCAP) {
+				ie_len = length + 2;
+				woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						    (t_u8 *)pos, &ie_len,
+						    MOAL_IOCTL_WAIT);
+				break;
+			}
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			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;
+			}
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			break;
+		default:
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			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
+ */
+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 > sizeof(TLV_Generic_t)) {
+		tlv_type = ntohs(tlv->type);
+		tlv_len = ntohs(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,
+						       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_SUCCESS !=
+			    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;
+		}
+	}
+	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;
+			assocresp_ies_data->ie_length = assocresp_ies_len;
+			pos = assocresp_ies_data->ie_buffer;
+			memcpy(pos, assocresp_ies, assocresp_ies_len);
+			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_SUCCESS !=
+		    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 (MLAN_CUSTOM_IE_AUTO_IDX_MASK == beacon_vendor_index)
+				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,
+						     IE_MASK_VENDOR);
+			DBG_HEXDUMP(MCMD_D, "beacon vendor IE",
+				    beacon_ies_data->ie_buffer,
+				    beacon_ies_data->ie_length);
+		} else if (beacon_vendor_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+			/* 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_SUCCESS !=
+			    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,
+						       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, 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_SUCCESS !=
+			    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 (MLAN_CUSTOM_IE_AUTO_IDX_MASK == proberesp_index)
+				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,
+						       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 (MLAN_CUSTOM_IE_AUTO_IDX_MASK == assocresp_index)
+				assocresp_ies_data->mgmt_subtype_mask |=
+					MLAN_CUSTOM_IE_NEW_MASK;
+			assocresp_ies_data->ie_length = assocresp_ies_len;
+			pos = assocresp_ies_data->ie_buffer;
+			memcpy(pos, assocresp_ies, assocresp_ies_len);
+			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;
+#if defined(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,
+							       IE_MASK_P2P |
+							       IE_MASK_WFD |
+							       IE_MASK_EXTCAP,
+							       NULL, 0);
+			} else {
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+				probereq_ies_data->ie_length = probereq_ies_len;
+				pos = probereq_ies_data->ie_buffer;
+				memcpy(pos, probereq_ies, probereq_ies_len);
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+			}
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+			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_SUCCESS !=
+		    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 informations
+ *  @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)
+		memcpy(ht_info->mcs.rx_mask, mcs_set,
+		       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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+/**
+ *  @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 (MLAN_STATUS_SUCCESS != status) {
+		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 = (t_u16)cfg_11ac->param.vht_cfg.vht_rx_mcs;
+	vht_cap->vht_mcs.rx_highest =
+		(t_u16)cfg_11ac->param.vht_cfg.vht_rx_max_rate;
+	vht_cap->vht_mcs.tx_mcs_map = (t_u16)cfg_11ac->param.vht_cfg.vht_tx_mcs;
+	vht_cap->vht_mcs.tx_highest =
+		(t_u16)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();
+	return;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+/**
+ * @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;
+		memcpy(&evt->chan_info, pchan_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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	struct cfg80211_chan_def chandef;
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+	enum nl80211_channel_type type;
+	enum ieee80211_band band;
+	int freq = 0;
+#endif
+#endif
+	ENTER();
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_chandef_create(priv, &chandef, pchan_info)) {
+		mutex_lock(&priv->wdev->mtx);
+		cfg80211_ch_switch_notify(priv->netdev, &chandef);
+		mutex_unlock(&priv->wdev->mtx);
+		priv->channel = pchan_info->channel;
+#ifdef UAP_CFG80211
+		memcpy(&priv->chan, &chandef, sizeof(struct cfg80211_chan_def));
+#endif
+	}
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ * @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();
+	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
+
+/**
+ * @brief Get second channel offset
+ *
+ * @param chan             channel num
+ * @return                second channel offset
+ */
+t_u8
+woal_get_second_channel_offset(int chan)
+{
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+
+	switch (chan) {
+	case 36:
+	case 44:
+	case 52:
+	case 60:
+	case 100:
+	case 108:
+	case 116:
+	case 124:
+	case 132:
+	case 140:
+	case 149:
+	case 157:
+		chan2Offset = SEC_CHAN_ABOVE;
+		break;
+	case 40:
+	case 48:
+	case 56:
+	case 64:
+	case 104:
+	case 112:
+	case 120:
+	case 128:
+	case 136:
+	case 144:
+	case 153:
+	case 161:
+		chan2Offset = SEC_CHAN_BELOW;
+		break;
+	case 165:
+		/* Special Case: 20Mhz-only Channel */
+		chan2Offset = SEC_CHAN_NONE;
+		break;
+	}
+	return chan2Offset;
+}
diff --git a/wlan_sd8987/mlinux/moal_cfg80211.h b/wlan_sd8987/mlinux/moal_cfg80211.h
new file mode 100644
index 0000000..fb31bc0
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_cfg80211.h
@@ -0,0 +1,464 @@
+/** @file moal_cfg80211.h
+  *
+  * @brief This file contains the CFG80211 specific defines.
+  *
+  * Copyright (C) 2011-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _MOAL_CFG80211_H_
+#define _MOAL_CFG80211_H_
+
+#include    "moal_main.h"
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR
+#define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+#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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+#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_DELETE_MASK      0x0
+#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
+
+/**
+ * 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 */
+moal_private *woal_get_scan_interface(moal_handle *handle);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/** 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(moal_private *priv, t_u16 reason_code);
+void woal_host_mlme_work_queue(struct work_struct *work);
+#endif
+#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 CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
+				      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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+			  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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+			  bool pairwise,
+#endif
+			  const t_u8 *mac_addr);
+#ifdef STA_SUPPORT
+/** Opportunistic Key Caching APIs support */
+struct pmksa_entry *woal_get_pmksa_entry(moal_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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+	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,
+					     mlan_ssid_bssid *ssid_bssid,
+					     t_u8 wait_option);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+int woal_cfg80211_set_channel(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+			      struct net_device *dev,
+#endif
+			      struct ieee80211_channel *chan,
+			      enum nl80211_channel_type channel_type);
+#endif
+
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
+				       struct net_device *netdev,
+				       t_u8 key_index);
+#endif
+
+void woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+				       struct wireless_dev *wdev,
+#else
+				       struct net_device *dev,
+#endif
+				       t_u16 frame_type, bool reg);
+
+int woal_cfg80211_mgmt_tx(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+			  struct wireless_dev *wdev,
+#else
+			  struct net_device *dev,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			  struct cfg80211_mgmt_tx_params *params,
+#else
+			  struct ieee80211_channel *chan, bool offchan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+			  enum nl80211_channel_type channel_type,
+			  bool channel_type_valid,
+#endif
+			  unsigned int wait, const u8 *buf, size_t len,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+			  bool no_cck,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+			  bool dont_wait_for_ack,
+#endif
+#endif
+			  u64 * cookie);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+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;
+
+#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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+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);
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+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)
+/* 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);
+
+void woal_remove_virtual_interface(moal_handle *handle);
+
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+
+/** Define for remain on channel duration timer */
+#define MAX_REMAIN_ON_CHANNEL_DURATION      (1000)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+				  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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+int woal_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
+			     struct bss_parameters *params);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+int woal_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *dev,
+			      const struct cfg80211_acl_data *params);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+int woal_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev,
+				 struct ieee80211_txq_params *params);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+int woal_cfg80211_set_coalesce(struct wiphy *wiphy,
+			       struct cfg80211_coalesce *coalesce);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+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 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, 12, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+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_cac_timer_func(void *context);
+void woal_csa_work_queue(struct work_struct *work);
+#endif
+#endif /* UAP_CFG80211 */
+#if defined(UAP_SUPPORT) || defined(STA_SUPPORT)
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+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
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+mlan_status woal_chandef_create(moal_private *priv,
+				struct cfg80211_chan_def *chandef,
+				chan_band_info * pchan_info);
+#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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+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,
+			mlan_ds_misc_assoc_rsp *assoc_rsp);
+
+t_u8 woal_get_second_channel_offset(int chan);
+
+#endif /* _MOAL_CFG80211_H_ */
diff --git a/wlan_sd8987/mlinux/moal_cfgvendor.c b/wlan_sd8987/mlinux/moal_cfgvendor.c
new file mode 100644
index 0000000..8cd710b
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_cfgvendor.c
@@ -0,0 +1,951 @@
+/** @file moal_cfgvendor.c
+  *
+  * @brief This file contains the functions for CFG80211 vendor.
+  *
+  * Copyright (C) 2011-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include    "moal_cfgvendor.h"
+#include    "moal_cfg80211.h"
+
+/********************************************************
+				Local Variables
+********************************************************/
+
+/********************************************************
+				Global Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+extern int disable_regd_by_driver;
+/********************************************************
+				Local Functions
+********************************************************/
+
+/********************************************************
+				Global Functions
+********************************************************/
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+/**marvell vendor command and event*/
+#define MRVL_VENDOR_ID  0x005043
+/** vendor events */
+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_rssi_monitor,},	/*event_id 0x1501 */
+	{.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 */
+	/**add vendor event here*/
+};
+
+/**
+ * @brief get the event id of the events array
+ *
+ * @param event     vendor event
+ *
+ * @return    index of events array
+ */
+int
+woal_get_event_id(int event)
+{
+	int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(vendor_events); i++) {
+		if (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(IN moal_private *priv,
+			   IN int event, IN t_u8 *data, IN 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	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);
+	memcpy(pos, data, len);
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief send vendor event to kernel
+ *
+ * @param priv       A pointer to moal_private
+ * @param event    vendor event
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+struct sk_buff *
+woal_cfg80211_alloc_vendor_event(IN moal_private *priv,
+				 IN int event, IN int len)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int event_id = 0;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "Not find this event %d \n", event_id);
+		goto done;
+	}
+	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);
+		goto done;
+	}
+
+	/**allocate skb*/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	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");
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return skb;
+}
+
+/**
+ * @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();
+	return;
+}
+
+/**
+ * @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));
+	memcpy(pos, &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];
+	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 woal_cfg80211_subcmd_get_valid_channels\n");
+
+	err = nla_parse(tb, ATTR_WIFI_MAX, data, len, NULL
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err) {
+		PRINTM(MERROR, "%s: nla_parse fail\n", __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+
+	if (!tb[ATTR_CHANNELS_BAND]) {
+		PRINTM(MERROR, "%s: null attr: tb[ATTR_GET_CH]=%p\n",
+		       __FUNCTION__, 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", __FUNCTION__, 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;
+	}
+
+	nla_put_u32(skb, ATTR_NUM_CHANNELS, nchannel);
+	nla_put(skb, ATTR_CHANNEL_LIST, nchannel * sizeof(ch_out[0]), ch_out);
+	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();
+	memcpy(drv_version, &priv->phandle->driver_version,
+	       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)
+		memcpy(pos, pos + 3, strlen(pos) - 3);
+
+	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 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;
+	t_u32 reply_len = 0;
+	int ret = 0;
+	t_u32 supp_feature_set = 0;
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_fw_info fw_info;
+	ENTER();
+
+	supp_feature_set = WIFI_FEATURE_INFRA
+#if defined(UAP_SUPPORT) && defined(STA_SUPPORT)
+		| WIFI_FEATURE_AP_STA
+#endif
+		| WIFI_FEATURE_RSSI_MONITOR;
+
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (fw_info.fw_bands & BAND_A)
+		supp_feature_set |= WIFI_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;
+	}
+	nla_put_u32(skb, ATTR_FEATURE_SET, supp_feature_set);
+	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 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(sizeof(country) - 1, nla_len(iter)));
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			return ret;
+		}
+	}
+	if (!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;
+}
+
+#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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, 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);
+	memcpy(pos, data, 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 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+		  , NULL
+#endif
+		);
+	if (!tb_vendor[ATTR_ND_OFFLOAD_CONTROL]) {
+		PRINTM(MINFO, "%s: ATTR_ND_OFFLOAD not found\n", __FUNCTION__);
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	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;
+	int ret = 1;
+
+	ENTER();
+
+	/** 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;
+}
+
+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,
+	 },
+	{
+	 .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,
+	 },
+#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,
+	 },
+#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,
+	 },
+
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+
+};
+
+/**
+ * @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_cfgvendor.h b/wlan_sd8987/mlinux/moal_cfgvendor.h
new file mode 100644
index 0000000..80d3728
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_cfgvendor.h
@@ -0,0 +1,184 @@
+/** @file moal_cfgvendor.h
+  *
+  * @brief This file contains the CFG80211 vendor specific defines.
+  *
+  * Copyright (C) 2011-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _MOAL_CFGVENDOR_H_
+#define _MOAL_CFGVENDOR_H_
+
+#include   "moal_main.h"
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+
+#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)
+
+/* Feature enums */
+#define WIFI_FEATURE_INFRA              0x0001	// Basic infrastructure mode
+#define WIFI_FEATURE_INFRA_5G           0x0002	// Support for 5 GHz Band
+#define WIFI_FEATURE_HOTSPOT            0x0004	// Support for GAS/ANQP
+#define WIFI_FEATURE_P2P                0x0008	// Wifi-Direct
+#define WIFI_FEATURE_SOFT_AP            0x0010	// Soft AP
+#define WIFI_FEATURE_GSCAN              0x0020	// Google-Scan APIs
+#define WIFI_FEATURE_NAN                0x0040	// Neighbor Awareness Networking
+#define WIFI_FEATURE_D2D_RTT            0x0080	// Device-to-device RTT
+#define WIFI_FEATURE_D2AP_RTT           0x0100	// Device-to-AP RTT
+#define WIFI_FEATURE_BATCH_SCAN         0x0200	// Batched Scan (legacy)
+#define WIFI_FEATURE_PNO                0x0400	// Preferred network offload
+#define WIFI_FEATURE_ADDITIONAL_STA     0x0800	// Support for two STAs
+#define WIFI_FEATURE_TDLS               0x1000	// Tunnel directed link setup
+#define WIFI_FEATURE_TDLS_OFFCHANNEL    0x2000	// Support for TDLS off channel
+#define WIFI_FEATURE_EPR                0x4000	// Enhanced power reporting
+#define WIFI_FEATURE_AP_STA             0x8000	// Support for AP STA Concurrency
+#define WIFI_FEATURE_LINK_LAYER_STATS   0x10000	// Link layer stats collection
+#define WIFI_FEATURE_LOGGER             0x20000	// WiFi Logger
+#define WIFI_FEATURE_HAL_EPNO           0x40000	// WiFi PNO enhanced
+#define WIFI_FEATURE_RSSI_MONITOR       0x80000	// RSSI Monitor
+#define WIFI_FEATURE_MKEEP_ALIVE        0x100000	// WiFi mkeep_alive
+#define WIFI_FEATURE_CONFIG_NDO         0x200000	// ND offload configure
+#define WIFI_FEATURE_TX_TRANSMIT_POWER  0x400000	// Capture Tx transmit power levels
+#define WIFI_FEATURE_CONTROL_ROAMING    0x800000	// Enable/Disable firmware roaming
+#define WIFI_FEATURE_IE_WHITELIST       0x1000000	// Support Probe IE white listing
+#define WIFI_FEATURE_SCAN_RAND          0x2000000	// Support MAC & Probe Sequence Number randomization
+// 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_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_MAX,
+} 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_rssi_monitor = 0x1501,
+	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_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_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_MAX,
+};
+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_dfs_capability = 0x0005,
+	sub_cmd_nd_offload = 0x0100,
+	sub_cmd_get_valid_channels = 0x1009,
+	sub_cmd_get_wifi_supp_feature_set = 0x100a,
+	sub_cmd_set_country_code = 0x100d,
+	sub_cmd_get_fw_version = 0x1404,
+	sub_cmd_get_drv_version = 0x1406,
+	sub_cmd_rssi_monitor = 0x1500,
+	sub_cmd_max,
+};
+
+void woal_register_cfg80211_vendor_command(struct wiphy *wiphy);
+int woal_cfg80211_vendor_event(IN moal_private *priv,
+			       IN int event, IN t_u8 *data, IN 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_MAX,
+} ND_OFFLOAD_ATTR;
+
+#endif
+#endif /* _MOAL_CFGVENDOR_H_ */
diff --git a/wlan_sd8987/mlinux/moal_debug.c b/wlan_sd8987/mlinux/moal_debug.c
new file mode 100644
index 0000000..c68552d
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_debug.c
@@ -0,0 +1,1305 @@
+/** @file moal_debug.c
+  *
+  * @brief This file contains functions for debug proc file.
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    11/03/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+
+/********************************************************
+		Global Variables
+********************************************************/
+/** MLAN debug info */
+extern mlan_debug_info info;
+
+/********************************************************
+		Local Variables
+********************************************************/
+#ifdef CONFIG_PROC_FS
+
+/** Get info item size */
+#define item_size(n) (sizeof(info.n))
+/** Get info item address */
+#define item_addr(n) ((t_ptr) &(info.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 STA_SUPPORT
+static struct debug_data items[] = {
+#ifdef DEBUG_LEVEL1
+	{"drvdbg", sizeof(drvdbg), (t_ptr)&drvdbg},
+#endif
+	{"mlan_processing", item_size(mlan_processing),
+	 item_addr(mlan_processing)},
+	{"main_process_cnt", item_size(main_process_cnt),
+	 item_addr(main_process_cnt)},
+	{"main_lock_flag", item_size(main_lock_flag),
+	 item_addr(main_lock_flag)},
+	{"delay_task_flag", item_size(delay_task_flag),
+	 item_addr(delay_task_flag)},
+	{"mlan_rx_processing", item_size(mlan_rx_processing),
+	 item_addr(mlan_rx_processing)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"wmm_ac_vo", item_size(wmm_ac_vo), item_addr(wmm_ac_vo)},
+	{"wmm_ac_vi", item_size(wmm_ac_vi), item_addr(wmm_ac_vi)},
+	{"wmm_ac_be", item_size(wmm_ac_be), item_addr(wmm_ac_be)},
+	{"wmm_ac_bk", item_size(wmm_ac_bk), item_addr(wmm_ac_bk)},
+	{"max_tx_buf_size", item_size(max_tx_buf_size),
+	 item_addr(max_tx_buf_size)},
+	{"tx_buf_size", item_size(tx_buf_size), item_addr(tx_buf_size)},
+	{"curr_tx_buf_size", item_size(curr_tx_buf_size),
+	 item_addr(curr_tx_buf_size)},
+	{"ps_mode", item_size(ps_mode), item_addr(ps_mode)},
+	{"ps_state", item_size(ps_state), item_addr(ps_state)},
+	{"is_deep_sleep", item_size(is_deep_sleep), item_addr(is_deep_sleep)},
+	{"wakeup_dev_req", item_size(pm_wakeup_card_req),
+	 item_addr(pm_wakeup_card_req)},
+	{"wakeup_tries", item_size(pm_wakeup_fw_try),
+	 item_addr(pm_wakeup_fw_try)},
+	{"hs_configured", item_size(is_hs_configured),
+	 item_addr(is_hs_configured)},
+	{"hs_activated", item_size(hs_activated), item_addr(hs_activated)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"tx_pkts_queued", item_size(tx_pkts_queued),
+	 item_addr(tx_pkts_queued)},
+	{"pps_uapsd_mode", item_size(pps_uapsd_mode),
+	 item_addr(pps_uapsd_mode)},
+	{"sleep_pd", item_size(sleep_pd), item_addr(sleep_pd)},
+	{"qos_cfg", item_size(qos_cfg), item_addr(qos_cfg)},
+	{"tx_lock_flag", item_size(tx_lock_flag), item_addr(tx_lock_flag)},
+	{"port_open", item_size(port_open), item_addr(port_open)},
+	{"bypass_pkt_count", item_size(bypass_pkt_count),
+	 item_addr(bypass_pkt_count)},
+	{"scan_processing", item_size(scan_processing),
+	 item_addr(scan_processing)},
+	{"num_tx_timeout", item_size(num_tx_timeout),
+	 item_addr(num_tx_timeout)},
+	{"num_cmd_timeout", item_size(num_cmd_timeout),
+	 item_addr(num_cmd_timeout)},
+	{"dbg.num_cmd_timeout", item_size(dbg_num_cmd_timeout),
+	 item_addr(dbg_num_cmd_timeout)},
+	{"timeout_cmd_id", item_size(timeout_cmd_id),
+	 item_addr(timeout_cmd_id)},
+	{"timeout_cmd_act", item_size(timeout_cmd_act),
+	 item_addr(timeout_cmd_act)},
+	{"last_cmd_id", item_size(last_cmd_id), item_addr(last_cmd_id)},
+	{"last_cmd_act", item_size(last_cmd_act), item_addr(last_cmd_act)},
+	{"last_cmd_index", item_size(last_cmd_index),
+	 item_addr(last_cmd_index)},
+	{"last_cmd_resp_id", item_size(last_cmd_resp_id),
+	 item_addr(last_cmd_resp_id)},
+	{"last_cmd_resp_index", item_size(last_cmd_resp_index),
+	 item_addr(last_cmd_resp_index)},
+	{"last_event", item_size(last_event), item_addr(last_event)},
+	{"last_event_index", item_size(last_event_index),
+	 item_addr(last_event_index)},
+	{"num_no_cmd_node", item_size(num_no_cmd_node),
+	 item_addr(num_no_cmd_node)},
+	{"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
+	 item_addr(num_cmd_host_to_card_failure)},
+	{"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)},
+	{"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
+	 item_addr(num_tx_host_to_card_failure)},
+	{"num_alloc_buffer_failure", item_size(num_alloc_buffer_failure),
+	 item_addr(num_alloc_buffer_failure)},
+	{"num_cmdevt_c2h_fail", item_size(num_cmdevt_card_to_host_failure),
+	 item_addr(num_cmdevt_card_to_host_failure)},
+	{"num_rx_c2h_fail", item_size(num_rx_card_to_host_failure),
+	 item_addr(num_rx_card_to_host_failure)},
+	{"num_int_read_fail", item_size(num_int_read_failure),
+	 item_addr(num_int_read_failure)},
+	{"last_int_status", item_size(last_int_status),
+	 item_addr(last_int_status)},
+	{"num_of_irq", item_size(num_of_irq), item_addr(num_of_irq)},
+	{"mp_invalid_update", item_size(mp_invalid_update),
+	 item_addr(mp_invalid_update)},
+	{"sdio_rx_aggr", item_size(sdio_rx_aggr), item_addr(sdio_rx_aggr)},
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	{"mpa_sent_last_pkt", item_size(mpa_sent_last_pkt),
+	 item_addr(mpa_sent_last_pkt)},
+	{"mpa_sent_no_ports", item_size(mpa_sent_no_ports),
+	 item_addr(mpa_sent_no_ports)},
+#endif
+	{"num_evt_deauth", item_size(num_event_deauth),
+	 item_addr(num_event_deauth)},
+	{"num_evt_disassoc", item_size(num_event_disassoc),
+	 item_addr(num_event_disassoc)},
+	{"num_evt_link_lost", item_size(num_event_link_lost),
+	 item_addr(num_event_link_lost)},
+	{"num_cmd_deauth", item_size(num_cmd_deauth),
+	 item_addr(num_cmd_deauth)},
+	{"num_cmd_assoc_ok", item_size(num_cmd_assoc_success),
+	 item_addr(num_cmd_assoc_success)},
+	{"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure),
+	 item_addr(num_cmd_assoc_failure)},
+	{"num_cons_cmd_assoc_failure", item_size(num_cons_cmd_assoc_failure),
+	 item_addr(num_cons_cmd_assoc_failure)},
+	{"cmd_sent", item_size(cmd_sent), item_addr(cmd_sent)},
+	{"data_sent", item_size(data_sent), item_addr(data_sent)},
+	{"mp_rd_bitmap", item_size(mp_rd_bitmap), item_addr(mp_rd_bitmap)},
+	{"curr_rd_port", item_size(curr_rd_port), item_addr(curr_rd_port)},
+	{"mp_wr_bitmap", item_size(mp_wr_bitmap), item_addr(mp_wr_bitmap)},
+	{"curr_wr_port", item_size(curr_wr_port), item_addr(curr_wr_port)},
+	{"cmd_resp_received", item_size(cmd_resp_received),
+	 item_addr(cmd_resp_received)},
+	{"event_received", item_size(event_received),
+	 item_addr(event_received)},
+
+	{"ioctl_pending", item_handle_size(ioctl_pending),
+	 item_handle_addr(ioctl_pending)},
+	{"tx_pending", item_handle_size(tx_pending),
+	 item_handle_addr(tx_pending)},
+	{"rx_pending", item_handle_size(rx_pending),
+	 item_handle_addr(rx_pending)},
+	{"lock_count", item_handle_size(lock_count),
+	 item_handle_addr(lock_count)},
+	{"malloc_count", item_handle_size(malloc_count),
+	 item_handle_addr(malloc_count)},
+	{"vmalloc_count", item_handle_size(vmalloc_count),
+	 item_handle_addr(vmalloc_count)},
+	{"mbufalloc_count", item_handle_size(mbufalloc_count),
+	 item_handle_addr(mbufalloc_count)},
+	{"main_state", item_handle_size(main_state),
+	 item_handle_addr(main_state)},
+	{"driver_state", item_handle_size(driver_state),
+	 item_handle_addr(driver_state)},
+#ifdef SDIO_MMC_DEBUG
+	{"sdiocmd53w", item_handle_size(cmd53w), item_handle_addr(cmd53w)},
+	{"sdiocmd53r", item_handle_size(cmd53r), item_handle_addr(cmd53r)},
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+	{"hs_skip_count", item_handle_size(hs_skip_count),
+	 item_handle_addr(hs_skip_count)},
+	{"hs_force_count", item_handle_size(hs_force_count),
+	 item_handle_addr(hs_force_count)},
+#endif
+};
+
+#endif
+
+#ifdef UAP_SUPPORT
+static struct debug_data uap_items[] = {
+#ifdef DEBUG_LEVEL1
+	{"drvdbg", sizeof(drvdbg), (t_ptr)&drvdbg},
+#endif
+	{"mlan_processing", item_size(mlan_processing),
+	 item_addr(mlan_processing)},
+	{"main_process_cnt", item_size(main_process_cnt),
+	 item_addr(main_process_cnt)},
+	{"main_lock_flag", item_size(main_lock_flag),
+	 item_addr(main_lock_flag)},
+	{"delay_task_flag", item_size(delay_task_flag),
+	 item_addr(delay_task_flag)},
+	{"mlan_rx_processing", item_size(mlan_rx_processing),
+	 item_addr(mlan_rx_processing)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"wmm_ac_vo", item_size(wmm_ac_vo), item_addr(wmm_ac_vo)},
+	{"wmm_ac_vi", item_size(wmm_ac_vi), item_addr(wmm_ac_vi)},
+	{"wmm_ac_be", item_size(wmm_ac_be), item_addr(wmm_ac_be)},
+	{"wmm_ac_bk", item_size(wmm_ac_bk), item_addr(wmm_ac_bk)},
+	{"max_tx_buf_size", item_size(max_tx_buf_size),
+	 item_addr(max_tx_buf_size)},
+	{"tx_buf_size", item_size(tx_buf_size), item_addr(tx_buf_size)},
+	{"curr_tx_buf_size", item_size(curr_tx_buf_size),
+	 item_addr(curr_tx_buf_size)},
+	{"ps_mode", item_size(ps_mode), item_addr(ps_mode)},
+	{"ps_state", item_size(ps_state), item_addr(ps_state)},
+	{"wakeup_dev_req", item_size(pm_wakeup_card_req),
+	 item_addr(pm_wakeup_card_req)},
+	{"wakeup_tries", item_size(pm_wakeup_fw_try),
+	 item_addr(pm_wakeup_fw_try)},
+	{"hs_configured", item_size(is_hs_configured),
+	 item_addr(is_hs_configured)},
+	{"hs_activated", item_size(hs_activated), item_addr(hs_activated)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"tx_pkts_queued", item_size(tx_pkts_queued),
+	 item_addr(tx_pkts_queued)},
+	{"bypass_pkt_count", item_size(bypass_pkt_count),
+	 item_addr(bypass_pkt_count)},
+	{"num_bridge_pkts", item_size(num_bridge_pkts),
+	 item_addr(num_bridge_pkts)},
+	{"num_drop_pkts", item_size(num_drop_pkts), item_addr(num_drop_pkts)},
+	{"num_tx_timeout", item_size(num_tx_timeout),
+	 item_addr(num_tx_timeout)},
+	{"num_cmd_timeout", item_size(num_cmd_timeout),
+	 item_addr(num_cmd_timeout)},
+	{"timeout_cmd_id", item_size(timeout_cmd_id),
+	 item_addr(timeout_cmd_id)},
+	{"timeout_cmd_act", item_size(timeout_cmd_act),
+	 item_addr(timeout_cmd_act)},
+	{"last_cmd_id", item_size(last_cmd_id), item_addr(last_cmd_id)},
+	{"last_cmd_act", item_size(last_cmd_act), item_addr(last_cmd_act)},
+	{"last_cmd_index", item_size(last_cmd_index),
+	 item_addr(last_cmd_index)},
+	{"last_cmd_resp_id", item_size(last_cmd_resp_id),
+	 item_addr(last_cmd_resp_id)},
+	{"last_cmd_resp_index", item_size(last_cmd_resp_index),
+	 item_addr(last_cmd_resp_index)},
+	{"last_event", item_size(last_event), item_addr(last_event)},
+	{"last_event_index", item_size(last_event_index),
+	 item_addr(last_event_index)},
+	{"num_no_cmd_node", item_size(num_no_cmd_node),
+	 item_addr(num_no_cmd_node)},
+	{"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
+	 item_addr(num_cmd_host_to_card_failure)},
+	{"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)},
+	{"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
+	 item_addr(num_tx_host_to_card_failure)},
+	{"num_alloc_buffer_failure", item_size(num_alloc_buffer_failure),
+	 item_addr(num_alloc_buffer_failure)},
+	{"num_cmdevt_c2h_fail", item_size(num_cmdevt_card_to_host_failure),
+	 item_addr(num_cmdevt_card_to_host_failure)},
+	{"num_rx_c2h_fail", item_size(num_rx_card_to_host_failure),
+	 item_addr(num_rx_card_to_host_failure)},
+	{"num_int_read_fail", item_size(num_int_read_failure),
+	 item_addr(num_int_read_failure)},
+	{"last_int_status", item_size(last_int_status),
+	 item_addr(last_int_status)},
+	{"num_of_irq", item_size(num_of_irq), item_addr(num_of_irq)},
+	{"mp_invalid_update", item_size(mp_invalid_update),
+	 item_addr(mp_invalid_update)},
+	{"sdio_rx_aggr", item_size(sdio_rx_aggr), item_addr(sdio_rx_aggr)},
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	{"mpa_sent_last_pkt", item_size(mpa_sent_last_pkt),
+	 item_addr(mpa_sent_last_pkt)},
+	{"mpa_sent_no_ports", item_size(mpa_sent_no_ports),
+	 item_addr(mpa_sent_no_ports)},
+#endif
+	{"cmd_sent", item_size(cmd_sent), item_addr(cmd_sent)},
+	{"data_sent", item_size(data_sent), item_addr(data_sent)},
+	{"mp_rd_bitmap", item_size(mp_rd_bitmap), item_addr(mp_rd_bitmap)},
+	{"curr_rd_port", item_size(curr_rd_port), item_addr(curr_rd_port)},
+	{"mp_wr_bitmap", item_size(mp_wr_bitmap), item_addr(mp_wr_bitmap)},
+	{"curr_wr_port", item_size(curr_wr_port), item_addr(curr_wr_port)},
+	{"cmd_resp_received", item_size(cmd_resp_received),
+	 item_addr(cmd_resp_received)},
+	{"event_received", item_size(event_received),
+	 item_addr(event_received)},
+
+	{"ioctl_pending", item_handle_size(ioctl_pending),
+	 item_handle_addr(ioctl_pending)},
+	{"tx_pending", item_handle_size(tx_pending),
+	 item_handle_addr(tx_pending)},
+	{"rx_pending", item_handle_size(rx_pending),
+	 item_handle_addr(rx_pending)},
+	{"lock_count", item_handle_size(lock_count),
+	 item_handle_addr(lock_count)},
+	{"malloc_count", item_handle_size(malloc_count),
+	 item_handle_addr(malloc_count)},
+	{"vmalloc_count", item_handle_size(vmalloc_count),
+	 item_handle_addr(vmalloc_count)},
+	{"mbufalloc_count", item_handle_size(mbufalloc_count),
+	 item_handle_addr(mbufalloc_count)},
+	{"main_state", item_handle_size(main_state),
+	 item_handle_addr(main_state)},
+	{"driver_state", item_handle_size(driver_state),
+	 item_handle_addr(driver_state)},
+#ifdef SDIO_MMC_DEBUG
+	{"sdiocmd53w", item_handle_size(cmd53w), item_handle_addr(cmd53w)},
+	{"sdiocmd53r", item_handle_size(cmd53r), item_handle_addr(cmd53r)},
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+	{"hs_skip_count", item_handle_size(hs_skip_count),
+	 item_handle_addr(hs_skip_count)},
+	{"hs_force_count", item_handle_size(hs_force_count),
+	 item_handle_addr(hs_force_count)},
+#endif
+};
+#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_u8 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->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
+ *  @param antenna             Antenna
+ *  @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);
+}
+
+/**
+ *  @brief This function set histogram data
+ *
+ *  @param priv 		A pointer to moal_private
+ *  @param rx_rate              rx rate
+ *  @param snr			snr
+ *  @param nflr			NF
+ *  @param antenna              Antenna
+ *  @return   N/A
+ */
+static void
+woal_hist_data_set(moal_private *priv, t_u8 rx_rate, t_s8 snr, t_s8 nflr,
+		   t_u8 antenna)
+{
+	hgm_data *phist_data = priv->hist_data[antenna];
+
+	atomic_inc(&(phist_data->num_samples));
+	atomic_inc(&(phist_data->rx_rate[rx_rate]));
+	atomic_inc(&(phist_data->snr[snr]));
+	atomic_inc(&(phist_data->noise_flr[128 + nflr]));
+	atomic_inc(&(phist_data->sig_str[nflr - snr]));
+}
+
+/**
+ *  @brief This function add histogram data
+ *
+ *  @param priv 		A pointer to moal_private
+ *  @param rx_rate              rx rate
+ *  @param snr			snr
+ *  @param nflr			NF
+ *  @param antenna              Antenna
+ *  @return   N/A
+ */
+void
+woal_hist_data_add(moal_private *priv, t_u8 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->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 RATE_INDEX_MCS0   12
+/**
+ *  @brief histogram info in proc
+ *
+ *  @param sfp     A pointer to seq_file structure
+ *  @param data    void pointer to 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;
+	wlan_hist_proc_data *hist_data = (wlan_hist_proc_data *) sfp->private;
+	moal_private *priv = (moal_private *)hist_data->priv;
+	t_u8 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");
+
+	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" : "");
+			}
+		}
+	}
+	for (i = 0; i < SNR_MAX; i++) {
+		value = atomic_read(&(phist_data->snr[i]));
+		if (value)
+			seq_printf(sfp, "snr[%02ddB] = %d\n", i, 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", i,
+				   value);
+	}
+
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc read function for histogram
+ *
+ *  @param sfp     A pointer to seq_file structure
+ *  @param data    Void pointer to 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 (!priv->hist_data) {
+		LEAVE();
+		return -EFAULT;
+	}
+	if (hist_data->ant_idx < priv->phandle->histogram_table_num)
+		woal_histogram_info(sfp, priv->hist_data[hist_data->ant_idx]);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc open function for histogram
+ *
+ *  @param inode     A pointer to inode structure
+ *  @param file      A pointer to file structure
+ *
+ *  @return         0--sucess, otherise fail
+**/
+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     A pointer to seq_file structure
+ *  @param data    void pointer to 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     A pointer to seq_file structure
+ *  @param data    Void pointer to 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;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	unsigned int j;
+	t_u8 mp_aggr_pkt_limit = 0;
+#endif
+
+	ENTER();
+
+	if (priv == NULL) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	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 (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 {
+			unsigned int j;
+			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")
+			)
+			seq_printf(sfp, "%s=0x%x\n", d[i].name, val);
+		else
+			seq_printf(sfp, "%s=%d\n", d[i].name, val);
+	}
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	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);
+	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");
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	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
+	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);
+#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++) {
+			unsigned int j;
+
+			seq_printf(sfp,
+				   "tid = %d, ta =  %02x:%02x:%02x:%02x:%02x:%02x, start_win = %d, "
+				   "win_size = %d, amsdu=%d\n",
+				   (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, "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++) {
+		unsigned int j;
+		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;
+#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;
+	}
+
+	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;
+}
+
+/**
+ *  @brief debug proc open function
+ *
+ *  @param inode     A pointer to inode structure
+ *  @param file      A pointer to file structure
+ *
+ *  @return         0--sucess, otherise fail
+**/
+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
+}
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+/********************************************************
+		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;
+	int handle_items;
+	char hist_entry[50];
+
+	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;
+		}
+		memcpy(priv->items_priv.items, 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;
+		}
+		memcpy(priv->items_priv.items, uap_items, sizeof(uap_items));
+		priv->items_priv.num_of_items = ARRAY_SIZE(uap_items);
+	}
+#endif
+
+	priv->items_priv.priv = priv;
+	handle_items = 9;
+#ifdef SDIO_MMC_DEBUG
+	handle_items += 2;
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+	handle_items += 2;
+#endif
+	for (i = 1; i <= handle_items; i++)
+		priv->items_priv.items[priv->items_priv.num_of_items -
+				       i].addr += (t_ptr)(priv->phandle);
+
+	/* 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->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->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 100644
index 0000000..81f4b76
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_eth_ioctl.c
@@ -0,0 +1,14145 @@
+/** @file  moal_eth_ioctl.c
+  *
+  * @brief This file contains private ioctl functions
+  *
+  * Copyright (C) 2014-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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
+#include	"moal_sdio.h"
+#ifdef STA_CFG80211
+#include    "moal_sta_cfg80211.h"
+#endif
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#include    "moal_cfgvendor.h"
+#endif
+#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_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,
+};
+
+/** Bands supported in Ad-Hoc mode */
+static t_u8 SupportedAdhocBand[] = {
+	BAND_B, BAND_B | BAND_G, BAND_G,
+	BAND_GN, BAND_B | BAND_G | BAND_GN, BAND_G | BAND_GN,
+	BAND_GN | BAND_GAC, BAND_B | BAND_G | BAND_GN | BAND_GAC,
+		BAND_G | BAND_GN | BAND_GAC,
+	BAND_A,
+	BAND_AN, BAND_A | BAND_AN,
+	BAND_AN | BAND_AAC, BAND_A | BAND_AN | BAND_AAC,
+};
+
+/********************************************************
+			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
+extern int cfg80211_wext;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+extern int hw_test;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+extern int host_mlme;
+#endif
+extern int cntry_txpwr;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+extern int disable_regd_by_driver;
+#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
+ */
+mlan_status
+parse_arguments(t_u8 *pos, int *data, int datalen, int *user_data_len)
+{
+	unsigned 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 <= strlen(pos); i++) {
+		if ((k == 0) && (i <= (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 >= sizeof(cdata)) {
+				PRINTM(MERROR, "Invalid numerical arguments\n");
+				break;
+			}
+			cdata[k] = pos[i];
+			k++;
+		}
+	}
+
+	*user_data_len = j;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/** Convert character to integer */
+#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0'))
+/**
+ * @brief Converts a string to hex value
+ *
+ * @param str      A pointer to the string
+ * @param raw      A pointer to the raw data buffer
+ * @param raw_size      raw data buffer size
+ * @return         Number of bytes read
+ **/
+int
+string2raw(char *str, unsigned char *raw, int raw_size)
+{
+	int len = (strlen(str) + 1) / 2;
+	int i = 0;
+
+	do {
+		if (strlen(str) < 2)
+			return -1;
+		if (!isxdigit(*str) || !isxdigit(*(str + 1)))
+			return -1;
+		*str = toupper(*str);
+		*raw = CHAR2INT(*str) << 4;
+		++str;
+		*str = toupper(*str);
+		*raw |= CHAR2INT(*str);
+		++raw;
+		i++;
+	} while (*++str != '\0' && i < raw_size);
+	return len;
+}
+
+#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
+ */
+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.
+ */
+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, (respbuflen - 1));
+		memcpy(respbuf, buf, ret);
+	} 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_MARVELL) + strlen(PRIV_CMD_HOSTCMD));
+	buf_len = *((t_u32 *)data_ptr);
+	memcpy(&cmd_header, data_ptr + sizeof(buf_len), 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 */
+	memcpy(misc_cfg->param.hostcmd.cmd, data_ptr + sizeof(buf_len),
+	       misc_cfg->param.hostcmd.len);
+
+	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_MARVELL) + strlen(PRIV_CMD_HOSTCMD);
+	if (ret > respbuflen) {
+		ret = -EFAULT;
+		goto error;
+	}
+	memcpy(data_ptr + sizeof(buf_len), misc_cfg->param.hostcmd.cmd,
+	       misc_cfg->param.hostcmd.len);
+	memcpy(data_ptr, (t_u8 *)&misc_cfg->param.hostcmd.len, sizeof(t_u32));
+
+error:
+	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.
+ */
+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 *custom_ie = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	data_ptr = respbuf + (strlen(CMD_MARVELL) + strlen(PRIV_CMD_CUSTOMIE));
+
+	custom_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 ((custom_ie->len == 0)||(custom_ie->len ==
+				    sizeof(custom_ie->ie_data_list[0].
+					   ie_index)))
+		ioctl_req->action = MLAN_ACT_GET;
+	else
+		ioctl_req->action = MLAN_ACT_SET;
+
+	memcpy(&misc->param.cust_ie, 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;
+	}
+	custom_ie = (mlan_ds_misc_custom_ie *)data_ptr;
+	memcpy(custom_ie, &misc->param.cust_ie, sizeof(mlan_ds_misc_custom_ie));
+	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.
+ */
+int
+woal_setget_priv_bandcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	unsigned int i;
+	int data[4];
+	int user_data_len = 0;
+	t_u32 infra_band = 0;
+	t_u32 adhoc_band = 0;
+	t_u32 adhoc_channel = 0;
+	t_u32 adhoc_chan_bandwidth = 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_MARVELL) + strlen(PRIV_CMD_BANDCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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); 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;
+			}
+		}
+		if (user_data_len == 4) {
+			if (!(adhoc_band & (BAND_GN
+					    | BAND_GAC | BAND_AN | BAND_AAC))) {
+				PRINTM(MERROR,
+				       "11n is not enabled for adhoc, can not set HT/VHT channel bandwidth\n");
+				ret = -EINVAL;
+				goto error;
+			}
+			adhoc_chan_bandwidth = data[3];
+			/* sanity test */
+			if ((adhoc_chan_bandwidth != CHANNEL_BW_20MHZ) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_ABOVE) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_BELOW)
+			    && (adhoc_chan_bandwidth != CHANNEL_BW_80MHZ)
+				) {
+				PRINTM(MERROR,
+				       "Invalid secondary channel bandwidth, only allowed 0, 1, 3 or 4\n");
+				ret = -EINVAL;
+				goto error;
+			}
+
+			/* VHT 80 MHz is valid only for 5G band */
+			if ((adhoc_chan_bandwidth == CHANNEL_BW_80MHZ) &&
+			    ((adhoc_band & BAND_AAC) == 0)) {
+				PRINTM(MERROR,
+				       "Invalid adhoc band for 11ac 80 Mhz, only 5G is allowed.\n");
+				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;
+		radio_cfg->param.band_cfg.adhoc_chan_bandwidth =
+			adhoc_chan_bandwidth;
+	}
+
+	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;
+
+	memcpy(band_cfg, &radio_cfg->param.band_cfg, sizeof(mlan_ds_band_cfg));
+
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_HTTXCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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]);
+	}
+
+	memcpy(respbuf, data, sizeof(data));
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_HTCAPINFO))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ADDBAPARA))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DELBA);
+
+	if (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)
+		memcpy(del_ba->peer_mac_addr, peer_mac, ETH_ALEN);
+
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_REJECTADDBAREQ))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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
+ */
+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)
+		memcpy(cfg_11n->param.addba_reject, 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)
+		memcpy(addba_reject, cfg_11n->param.addba_reject,
+		       sizeof(cfg_11n->param.addba_reject));
+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
+ */
+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)
+		memcpy(&cfg_11n->param.aggr_prio_tbl, 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)
+		memcpy(aggr_prio_tbl, &cfg_11n->param.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
+ */
+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)
+		memcpy(&cfg_11n->param.addba_param, 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)
+		memcpy(addba_param, &cfg_11n->param.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
+ */
+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] != 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
+ */
+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] != 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_AGGRPRIOTBL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ADDBAREJECT))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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_MARVELL) + 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);
+	memcpy(vhtcfg, &cfg_11ac->param.vht_cfg, sizeof(mlan_ds_11ac_vht_cfg));
+	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++;
+		memcpy(vhtcfg, &cfg_11ac->param.vht_cfg,
+		       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.
+ */
+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_MARVELL) +
+			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;
+	memcpy(opermodecfg, &(cfg_11ac->param.opermode_cfg),
+	       sizeof(*opermodecfg));
+	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.
+ */
+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;
+
+	memcpy(data_rate, &rate->param.data_rate, sizeof(mlan_data_rate));
+
+	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.
+ */
+int
+woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[3];
+	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;
+
+	ENTER();
+
+	if (strlen(respbuf) ==
+	    (strlen(CMD_MARVELL) + strlen(PRIV_CMD_TXRATECFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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] >= 3)) {
+			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_VHT)
+				) {
+				PRINTM(MERROR, "Invalid format selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			rate->param.rate_cfg.rate_format = data[0];
+		}
+
+		if ((user_data_len >= 2) && (data[0] != AUTO_RATE)) {
+			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))
+				) {
+				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 ((user_data_len >= 3) && (data[0] != AUTO_RATE)) {
+			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];
+		}
+	}
+
+	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)
+			ratecfg->nss = rate->param.rate_cfg.nss;
+	}
+
+	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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+			memcpy(stats, &info->param.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.
+ */
+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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ESUPPMODE))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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_MARVELL) + 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);
+			strncpy((char *)sec->param.passphrase.ssid.ssid, end,
+				MIN(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;
+			memcpy(sec->param.passphrase.psk.passphrase.passphrase,
+			       end,
+			       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;
+	}
+
+	memset(respbuf, 0, respbuflen);
+	if (sec->param.passphrase.ssid.ssid_len) {
+		len += sprintf(respbuf + len, "ssid:");
+		memcpy(respbuf + len, sec->param.passphrase.ssid.ssid,
+		       sec->param.passphrase.ssid.ssid_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);
+
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DEAUTH))) {
+		/* Deauth mentioned BSSID */
+		woal_mac2u8(mac,
+			    respbuf + strlen(CMD_MARVELL) +
+			    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_MARVELL) + strlen(PRIV_CMD_AP_DEAUTH));
+	memset(&deauth_param, 0, sizeof(mlan_deauth_param));
+	memcpy(&deauth_param, data_ptr, 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;
+
+	memcpy(&bss->param.deauth_param, &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;
+	}
+
+	memcpy(data_ptr, &ioctl_req->status_code, sizeof(t_u32));
+	ret = sizeof(t_u32);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap get station list 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_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_MARVELL) +
+				     strlen(PRIV_CMD_GET_STA_LIST));
+	memcpy(sta_list, &info->param.sta_list, sizeof(mlan_ds_sta_list));
+	ret = sizeof(mlan_ds_sta_list);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap bss_config 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_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_MARVELL) + strlen(PRIV_CMD_BSS_CONFIG);
+	memcpy((u8 *)&action, respbuf + offset, 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 */
+		memcpy(&bss->param.bss_config, respbuf + offset,
+		       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) {
+		memcpy(respbuf + offset, &bss->param.bss_config,
+		       sizeof(mlan_uap_bss_param));
+	}
+	ret = sizeof(mlan_uap_bss_param);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if defined(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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_BSSROLE))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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 && V14_FEATURE */
+
+#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.
+ */
+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 */
+	memcpy((char *)&scan_cfg,
+	       respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_SETUSERSCAN),
+	       sizeof(wlan_user_scan_cfg));
+	/* Call for scan */
+	if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_cfg))
+		ret = -EFAULT;
+
+	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
+ */
+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.
+ */
+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 */
+	memcpy(&scan_start,
+	       respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_GETSCANTABLE),
+	       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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_EXTCAPCFG);
+	if (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));
+		memcpy(&cfg->param.ext_cap, ie + 1, ie->len);
+	}
+
+	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);
+	memcpy(ie + 1, &cfg->param.ext_cap, sizeof(ExtCap_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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DEEPSLEEP))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_WPSSESSION))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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_MARVELL) +
+			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]);
+		memcpy(respbuf, otp->user_data, ret);
+	}
+
+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.
+ */
+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_MARVELL) + 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);
+		memcpy(country_code->country_code, respbuf + header,
+		       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);
+		memcpy(respbuf, country_code->country_code, COUNTRY_CODE_LEN);
+	}
+
+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.
+ */
+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;
+	int header = 0, data_length = 0;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header = strlen(CMD_MARVELL) + strlen(PRIV_CMD_CFPINFO);
+	data_length = strlen(respbuf) - header;
+
+	/* 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;
+	}
+	memcpy(respbuf, (t_u8 *)req->pbuf, req->data_read_written);
+	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.
+ */
+int
+woal_priv_setgettcpackenh(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[1];
+	int ret = 0;
+	int user_data_len = 0;
+
+	ENTER();
+
+	if (strlen(respbuf) ==
+	    (strlen(CMD_MARVELL) + strlen(PRIV_CMD_TCPACKENH))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				strlen(PRIV_CMD_TCPACKENH), data,
+				ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len >= 2) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (user_data_len == 0) {
+		/* get operation */
+		respbuf[0] = priv->enable_tcp_ack_enh;
+	} else {
+		/* set operation */
+		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);
+		} else {
+			PRINTM(MERROR, "Unknown option = %u\n", data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		respbuf[0] = priv->enable_tcp_ack_enh;
+	}
+	ret = 1;
+
+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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ASSOCBSSID);
+	else
+		header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ASSOCESSID);
+
+	if (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, (sizeof(buf) - 1));
+	memset(buf, 0, sizeof(buf));
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+	memcpy(buf, respbuf + header_len, buflen);
+	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 */
+	memcpy(ssid_bssid.ssid.ssid, buf + i,
+	       MIN(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;
+	}
+	memcpy(&priv->prev_ssid_bssid, &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.
+ */
+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_MARVELL) + 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_LISTENINTERVAL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DRVDBG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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);
+
+	memcpy(respbuf, &drvdbg, sizeof(drvdbg));
+
+	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 "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
+ */
+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_MARVELL);
+
+	if (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 >
+		    MAX_MGMT_FRAME_FILTER * sizeof(mlan_mgmt_frame_wakeup)) {
+			PRINTM(MERROR, "%d: Invalid arguments\n", __LINE__);
+			ret = -EINVAL;
+			goto done;
+		}
+		memcpy((t_u8 *)pm_cfg->param.mgmt_filter, argument, data_len);
+		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
+ */
+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_MARVELL) + strlen(PRIV_CMD_HSCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		arguments =
+			respbuf + strlen(CMD_MARVELL) + 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] != 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 */
+		memcpy(respbuf, &hscfg, sizeof(mlan_ds_hs_cfg));
+		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
+ */
+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_MARVELL) + 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_MARVELL) +
+				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_MARVELL, PRIV_CMD_HSCFG,
+			respbuf + (strlen(CMD_MARVELL) +
+				   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
+ */
+int
+woal_priv_set_get_scancfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0;
+	int arg_len = 8;
+	int data[arg_len];
+	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_MARVELL) + strlen(PRIV_CMD_SCANCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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] > 2)) {
+			PRINTM(MERROR, "Invalid argument for extended scan\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		memcpy(&scan->param.scan_cfg, data, sizeof(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;
+	}
+	memcpy(respbuf, &scan->param.scan_cfg, sizeof(mlan_scan_cfg));
+	ret = sizeof(mlan_scan_cfg);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#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_MARVELL) + 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;
+		}
+		memcpy(&ssid_bssid.bssid, awrq->sa_data, ETH_ALEN);
+	}
+
+	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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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_MARVELL) + 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 (hw_test) {
+		PRINTM(MIOCTL, "block set power in hw_test mode\n");
+		LEAVE();
+		return ret;
+	}
+
+	data_ptr = respbuf + (strlen(CMD_MARVELL) + 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_MARVELL) + 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 */
+		memcpy(req_ssid.ssid, mwr->u.essid.pointer,
+		       MIN(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);
+		memcpy(&ssid_bssid.ssid, &req_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;
+		}
+	} 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);
+
+	/* 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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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_MARVELL) + 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)
+{
+	int ret = 0;
+	mlan_bss_info bss_info;
+	struct mwreq *mwr;
+	t_u8 *data_ptr;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_MARVELL) + 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) {
+		memcpy(mwr->u.ap_addr.sa_data, &bss_info.bssid,
+		       MLAN_MAC_ADDR_LENGTH);
+	} else {
+		memset(mwr->u.ap_addr.sa_data, 0, MLAN_MAC_ADDR_LENGTH);
+	}
+
+	mwr->u.ap_addr.sa_family = ARPHRD_ETHER;
+	ret = strlen(CMD_MARVELL) + 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_MARVELL) + 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_MARVELL) + 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_MARVELL) + strlen(PRIV_CMD_PSMODE);
+
+	if (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;
+	}
+
+	/* 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;
+
+	memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+	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;
+	int intf_num;
+	moal_handle *handle = priv->phandle;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+#if defined(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 && V14_FEATURE */
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	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);
+#if defined(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 && V14_FEATURE */
+	}
+
+	/* 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;
+		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) {
+			ret = -EFAULT;
+			if (status != MLAN_STATUS_PENDING)
+				kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+
+	/* 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 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_MARVELL) + strlen(PRIV_CMD_TXPOWERCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		arguments =
+			respbuf + strlen(CMD_MARVELL) +
+			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 */
+		memcpy(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)));
+		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_MARVELL) + strlen(PRIV_CMD_PSCFG);
+
+	if (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;
+		memcpy(&pm_cfg->param.ps_cfg, data,
+		       MIN(sizeof(pm_cfg->param.ps_cfg), sizeof(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;
+	}
+	memcpy(data, &pm_cfg->param.ps_cfg,
+	       MIN((sizeof(int) * allowed), sizeof(pm_cfg->param.ps_cfg)));
+	memcpy(respbuf, (t_u8 *)data, sizeof(int) * allowed);
+	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_MARVELL) + 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_MARVELL) + strlen(PRIV_CMD_SLEEPPD);
+
+	if (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");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	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;
+		memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_TXCONTROL);
+
+	if (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");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	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;
+		memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_REGRDWR);
+
+	if (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) {
+		memcpy(respbuf, &reg_mem->param.reg_rw,
+		       sizeof(reg_mem->param.reg_rw));
+		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_MARVELL) + strlen(PRIV_CMD_RDEEPROM);
+
+	if (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) {
+		memcpy(respbuf, &reg_mem->param.rd_eeprom,
+		       sizeof(reg_mem->param.rd_eeprom));
+		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_MARVELL) + strlen(PRIV_CMD_MEMRDWR);
+
+	if (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) {
+		memcpy(respbuf, &reg_mem->param.mem_rw,
+		       sizeof(reg_mem->param.mem_rw));
+		ret = sizeof(reg_mem->param.mem_rw);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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_MARVELL) + strlen(PRIV_CMD_SDCMD52RW);
+	memset((t_u8 *)buf, 0, sizeof(buf));
+
+	if (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) {
+		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 {
+		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;
+		}
+	}
+
+	/* Action = GET */
+	buf[0] = data;
+
+	memcpy(respbuf, &buf, sizeof(int));
+	ret = sizeof(int);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#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_MARVELL) + strlen(PRIV_CMD_ARPFILTER));
+	buf_len = *((t_u16 *)data_ptr);
+	misc->param.gen_ie.len = buf_len;
+	memcpy((void *)(misc->param.gen_ie.ie_data), data_ptr + sizeof(buf_len),
+	       buf_len);
+
+	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 */
+
+#if defined(SDIO_SUSPEND_RESUME)
+/**
+ *  @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.
+ */
+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_MARVELL) + 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_MARVELL) +
+				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");
+	}
+
+	memcpy(respbuf, &handle->hs_auto_arp, sizeof(handle->hs_auto_arp));
+	ret = sizeof(handle->hs_auto_arp);
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @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_MARVELL) + strlen(PRIV_CMD_DEAUTH_CTRL);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	ret = sizeof(data);
+
+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;
+	memcpy(pos, &misc->param.rgchnpwr_cfg,
+	       sizeof(t_u16) + misc->param.rgchnpwr_cfg.length);
+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)) {
+		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;
+	memcpy(pos, &misc->param.trpc_cfg,
+	       sizeof(t_u16) + sizeof(t_u16) + misc->param.trpc_cfg.length);
+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 (!IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	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;
+		}
+		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 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
+ */
+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_MARVELL) + strlen(PRIV_CMD_HOTSPOTCFG);
+	if (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;
+	memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+	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
+ */
+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_MARVELL) + strlen(PRIV_CMD_MGMT_FRAME_CTRL);
+	if (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;
+	memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+	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_MARVELL) + 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));
+
+	memcpy((t_u8 *)&addts_ioctl, data_ptr, sizeof(addts_ioctl));
+
+	cfg->param.addts.timeout = addts_ioctl.timeout_ms;
+	cfg->param.addts.ie_data_len = addts_ioctl.ie_data_len;
+
+	memcpy(cfg->param.addts.ie_data,
+	       addts_ioctl.ie_data, cfg->param.addts.ie_data_len);
+
+	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;
+
+	memcpy(addts_ioctl.ie_data,
+	       cfg->param.addts.ie_data, cfg->param.addts.ie_data_len);
+
+	copy_len = (sizeof(addts_ioctl)
+		    - sizeof(addts_ioctl.ie_data)
+		    + cfg->param.addts.ie_data_len);
+
+	memcpy(respbuf, (t_u8 *)&addts_ioctl, copy_len);
+	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_MARVELL) + 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 (strlen(respbuf) > header_len) {
+		copy_len = MIN(strlen(data_ptr), sizeof(delts_ioctl));
+		memcpy((t_u8 *)&delts_ioctl, data_ptr, copy_len);
+
+		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;
+
+		memcpy(cfg->param.delts.ie_data,
+		       delts_ioctl.ie_data, cfg->param.delts.ie_data_len);
+
+		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);
+		memcpy(respbuf, (t_u8 *)&delts_ioctl, copy_len);
+		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_MARVELL) + strlen(PRIV_CMD_QCONFIG));
+
+	memcpy((t_u8 *)&qcfg_ioctl, data_ptr, 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;
+	memcpy(data_ptr, (t_u8 *)&qcfg_ioctl, sizeof(qcfg_ioctl));
+	ret = strlen(CMD_MARVELL) + 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_MARVELL) + 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 (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));
+		memcpy((void *)&qstatus_ioctl, (void *)&pwmm->param.q_status,
+		       sizeof(qstatus_ioctl));
+		memcpy(respbuf, (t_u8 *)&qstatus_ioctl, sizeof(qstatus_ioctl));
+		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_MARVELL) + 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));
+
+	memcpy((t_u8 *)&ts_status_ioctl, data_ptr, 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));
+	memcpy((void *)&ts_status_ioctl, (void *)&pwmm->param.ts_status,
+	       sizeof(ts_status_ioctl));
+	memcpy(respbuf, (t_u8 *)&ts_status_ioctl, sizeof(ts_status_ioctl));
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_MAC_CTRL);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.mac_ctrl, sizeof(data));
+	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
+ */
+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) {
+			memcpy(respbuf, (t_u8 *)&bss_info.bssid,
+			       MLAN_MAC_ADDR_LENGTH);
+		} 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) {
+			memcpy(respbuf, priv->current_addr,
+			       MLAN_MAC_ADDR_LENGTH);
+		} 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_REGION_CODE);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.region_code, sizeof(data));
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get channel time and buffer weight
+ *
+ *  @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.
+ */
+int
+woal_priv_multi_chan_config(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	t_u8 *data_ptr;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr =
+		respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_MULTI_CHAN_CFG);
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_MULTI_CHAN_CFG);
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		user_data_len = sizeof(mlan_ds_multi_chan_cfg);
+	}
+
+	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_MULTI_CHAN_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		memcpy(&cfg->param.multi_chan_cfg, data_ptr,
+		       sizeof(mlan_ds_multi_chan_cfg));
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, (mlan_ds_multi_chan_cfg *)&cfg->param.multi_chan_cfg,
+	       req->buf_len);
+	ret = req->buf_len;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get multi_channel policy 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.
+ */
+int
+woal_priv_multi_chan_policy(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	int data = 0;
+	t_u16 enable;
+	t_u8 action;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_MULTI_CHAN_POLICY);
+	if (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;
+	}
+
+	if (user_data_len == 0) {
+		action = MLAN_ACT_GET;
+	} else {
+		action = MLAN_ACT_SET;
+		enable = (t_u16)data;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_mc_policy_cfg(priv, &enable, MOAL_IOCTL_WAIT, action)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memcpy(respbuf, &enable, sizeof(t_u16));
+	ret = sizeof(t_u16);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get drcs time slicing 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.
+ */
+int
+woal_priv_drcs_time_slicing_cfg(moal_private *priv, t_u8 *respbuf,
+				t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_ds_drcs_cfg *drcs_cfg = NULL;
+	t_u8 *data_ptr;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	int data[8];
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr = respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_DRCS_CFG);
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_DRCS_CFG);
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(data_ptr, data, ARRAY_SIZE(data),
+				&user_data_len);
+	}
+
+	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_DRCS_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		drcs_cfg = (mlan_ds_drcs_cfg *) & cfg->param.drcs_cfg[0];
+		drcs_cfg->chantime = (t_u8)data[0];
+		drcs_cfg->switchtime = (t_u8)data[1];
+		drcs_cfg->undozetime = (t_u8)data[2];
+		drcs_cfg->mode = (t_u8)data[3];
+		/* Set the same parameters for two channels */
+		if (user_data_len < ARRAY_SIZE(data))
+			drcs_cfg->chan_idx = 0x03;
+		else {
+			/* Set the different parameters for two channels */
+			drcs_cfg->chan_idx = 0x1;
+			drcs_cfg =
+				(mlan_ds_drcs_cfg *) & cfg->param.drcs_cfg[1];
+			drcs_cfg->chan_idx = 0x2;
+			drcs_cfg->chantime = (t_u8)data[4];
+			drcs_cfg->switchtime = (t_u8)data[5];
+			drcs_cfg->undozetime = (t_u8)data[6];
+			drcs_cfg->mode = (t_u8)data[7];
+		}
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.drcs_cfg, req->buf_len);
+	ret = req->buf_len;
+
+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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_RX_COAL_CFG);
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_RX_COAL_CFG);
+	if (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;
+	}
+
+	memcpy(respbuf,
+	       (mlan_ds_misc_rx_packet_coalesce *)&cfg->param.rx_coalesce,
+	       req->buf_len);
+	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
+ */
+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_MARVELL) + 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 (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);
+		memcpy(bss->param.mac_addr, data, ETH_ALEN);
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, bss->param.mac_addr, sizeof(data));
+	ret = sizeof(data);
+	HEXDUMP("FW MAC Addr:", respbuf, ETH_ALEN);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_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
+ */
+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_MARVELL) + strlen(PRIV_CMD_OFFCHANNEL);
+
+	if (header_len == 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
+ */
+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_MARVELL) + strlen(PRIV_CMD_DSCP_MAP);
+	if (strlen(respbuf) != header_len) {
+		/* SET operation */
+		pos = respbuf + header_len;
+		memcpy(priv->dscp_map, pos, sizeof(priv->dscp_map));
+	}
+
+	copy_size = MIN(sizeof(priv->dscp_map), respbuflen);
+	memcpy(respbuf, priv->dscp_map, copy_size);
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_VEREXT);
+
+	if (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);
+	memcpy(respbuf, info->param.ver_ext.version_str, copy_size);
+	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;
+}
+
+#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_MARVELL) + strlen(PRIV_CMD_RADIO_CTRL);
+
+	if (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);
+		memcpy(respbuf, &bss_info.radio_on, sizeof(bss_info.radio_on));
+		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_MARVELL) + strlen(PRIV_CMD_WMM_CFG);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &wmm->param.wmm_enable, sizeof(wmm->param.wmm_enable));
+	ret = sizeof(wmm->param.wmm_enable);
+
+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_MARVELL) + strlen(PRIV_CMD_11D_CFG);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &pcfg_11d->param.enable_11d,
+	       sizeof(pcfg_11d->param.enable_11d));
+	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_MARVELL) + strlen(PRIV_CMD_11D_CLR_TBL);
+
+	if (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
+
+/**
+ *  @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_MARVELL) + strlen(PRIV_CMD_WWS_CFG);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &wws->param.wws_cfg, sizeof(wws->param.wws_cfg));
+	ret = sizeof(wws->param.wws_cfg);
+
+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 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_MARVELL) + strlen(PRIV_CMD_REASSOCTRL);
+
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		data = (int)(priv->reassoc_on);
+		memcpy(respbuf, &data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_TXBUF_CFG);
+
+	if (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;
+	memcpy(respbuf, &buf_size, sizeof(buf_size));
+	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_MARVELL) + strlen(PRIV_CMD_AUTH_TYPE);
+
+	if (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;
+		memcpy(respbuf, &auth_type, sizeof(auth_type));
+		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_FT))
+			    && (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_MARVELL) + strlen(PRIV_CMD_POWER_CONS);
+
+	if (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;
+		memcpy(respbuf, &data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_HT_STREAM_CFG);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	ret = sizeof(data);
+
+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_MARVELL) + strlen(PRIV_CMD_THERMAL);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	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_MARVELL) + strlen(PRIV_CMD_BCN_INTERVAL);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	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 buflen = 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_MARVELL) + strlen(PRIV_CMD_GET_SIGNAL);
+
+	if (strlen(respbuf) != header_len)
+		parse_arguments(respbuf + header_len, in_data, IN_DATA_SIZE,
+				&user_data_len);
+	buflen = MIN(user_data_len, IN_DATA_SIZE);
+
+	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;
+	}
+
+	memcpy(respbuf, out_data, (data_length * sizeof(int)));
+	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_MARVELL) + strlen(PRIV_CMD_GET_SIGNAL_EXT);
+
+	if (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) {
+		memcpy(signal_get, info->param.signal_ext, sizeof(signal_get));
+		path_num = MAX_PATH_NUM;
+	} else
+		memcpy(signal_get, info->param.signal_ext,
+		       sizeof(mlan_ds_get_signal));
+
+	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;
+	}
+	memcpy(respbuf, out_data,
+	       (MIN((PATH_SIZE * MAX_PATH_NUM), data_len) * sizeof(int)));
+	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_MARVELL) + strlen(PRIV_CMD_GET_SIGNAL_EXT_V2);
+	if (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) {
+		memcpy(signal_get, info->param.signal_ext, sizeof(signal_get));
+		path_num = MAX_PATH_NUM;
+	} else
+		memcpy(signal_get, info->param.signal_ext,
+		       sizeof(mlan_ds_get_signal));
+
+	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;
+	}
+	memcpy(respbuf, out_data,
+	       (MIN((PATH_SIZE * MAX_PATH_NUM), data_len) * sizeof(int)));
+	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_MARVELL) + strlen(PRIV_CMD_SIGNALEXT_CFG);
+	if (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
+ */
+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_MARVELL) + strlen(PRIV_CMD_PMFCFG);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.pmfcfg,
+	       sizeof(mlan_ds_misc_pmfcfg));
+	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_MARVELL) + strlen(PRIV_CMD_INACTIVITYTO);
+	memset(data, 0, sizeof(data));
+	if (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;
+
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		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];
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + 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 (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;
+
+	memcpy(respbuf, (t_u8 *)data, sizeof(data));
+	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_MARVELL) + 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 (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;
+
+	memcpy(respbuf, (t_u8 *)&bf_cap, sizeof(bf_cap));
+	ret = sizeof(bf_cap);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @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_MARVELL) + strlen(PRIV_CMD_SDIO_CLOCK);
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		memcpy(respbuf, (t_u8 *)&clock_state, sizeof(clock_state));
+		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;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ * @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_MARVELL) + strlen(PRIV_CMD_MPA_CTRL);
+	if (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]);
+
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		ret = sizeof(data);
+		goto done;
+	}
+
+	switch (user_data_len) {
+	case 6:
+		misc->param.mpa_ctrl.rx_max_ports = data[5];
+	case 5:
+		misc->param.mpa_ctrl.tx_max_ports = data[4];
+	case 4:
+		misc->param.mpa_ctrl.rx_buf_size = data[3];
+	case 3:
+		misc->param.mpa_ctrl.tx_buf_size = data[2];
+	case 2:
+		misc->param.mpa_ctrl.rx_enable = data[1];
+	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[][35] = { {"sleep clock error in ppm"},
+	{"wakeup offset in usec"},
+	{"clock stabilization time in usec"},
+	{"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_MARVELL) + strlen(PRIV_CMD_SLEEP_PARAMS);
+	if (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;
+
+	memcpy(respbuf, (t_u8 *)data, sizeof(data));
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ * @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[4];
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + 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 (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 != 4) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[0] > 0xFFFFF) {
+			PRINTM(MERROR,
+			       "The maximum user CAC is 1048575 msec (17 mins approx).\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[1] > 0xFFFFF) {
+			PRINTM(MERROR,
+			       "The maximum user NOP is 1048575 msec (17 mins approx).\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_u32)data[0];
+		ds_11hcfg->param.dfs_testing.usr_nop_period_sec =
+			(t_u32)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 / 1000;
+		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;
+		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;
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif /* DFS_SUPPORT && DFS_TESTING_SUPPORT */
+
+/**
+ * @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];
+	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_MARVELL) + 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 (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;
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		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_MARVELL) + 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 (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];
+		} 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;
+			memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		} 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;
+			memcpy(respbuf, (t_u8 *)data, sizeof(data));
+			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_MARVELL) + strlen(PRIV_CMD_SYSCLOCK);
+	memset(data, 0, sizeof(data));
+	if (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++;
+
+		memcpy(respbuf, data, sizeof(int) * data_length);
+		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_MARVELL) + strlen(PRIV_CMD_GET_KEY);
+	if (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;
+	memcpy(respbuf, &key_ascii, copy_len);
+	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_MARVELL) + strlen(PRIV_CMD_ASSOCIATE);
+	if (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, (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;
+	}
+
+	memcpy(buf, respbuf + header_len, buflen);
+
+	/* 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;
+	memcpy(ssid_bssid.ssid.ssid, buf + i, 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)) {
+		memcpy(&priv->prev_ssid_bssid.ssid,
+		       &bss_info.ssid, sizeof(mlan_802_11_ssid));
+		memcpy(&priv->prev_ssid_bssid.bssid,
+		       &bss_info.bssid, MLAN_MAC_ADDR_LENGTH);
+	}
+#endif /* REASSOCIATION */
+
+done:
+	LEAVE();
+	return 0;
+}
+
+/* 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 MAX_TX_BF_GLOBAL_ARGS   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;
+	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_MARVELL) + strlen(PRIV_CMD_TX_BF_CFG);
+	if (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 > sizeof(buf)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		memcpy(buf, respbuf + header_len, copy_len);
+
+		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:
+		memcpy(respbuf, bf_global, sizeof(mlan_bf_global_cfg_args));
+		ret = sizeof(mlan_bf_global_cfg_args);
+		break;
+	case TRIGGER_SOUNDING_FOR_PEER:
+		memcpy(respbuf, bf_sound, sizeof(mlan_bf_global_cfg_args));
+		ret = sizeof(mlan_bf_global_cfg_args);
+		break;
+	case SET_GET_BF_PERIODICITY:
+		memcpy(respbuf, bf_periodicity,
+		       sizeof(mlan_bf_periodicity_args));
+		ret = sizeof(mlan_bf_periodicity_args);
+		break;
+	case TX_BF_FOR_PEER_ENBL:
+		memcpy(respbuf, tx_bf_peer, sizeof(mlan_tx_bf_peer_args));
+		ret = sizeof(mlan_tx_bf_peer_args);
+		break;
+	case SET_SNR_THR_PEER:
+		memcpy(respbuf, bf_snr, sizeof(mlan_snr_thr_args));
+		ret = sizeof(mlan_snr_thr_args);
+		break;
+	default:
+		ret = 0;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @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, func, 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_MARVELL) + 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;
+	}
+	memcpy(&cmd_len, respbuf + header_len, sizeof(cmd_len));
+	buf = respbuf + header_len + sizeof(cmd_len);
+
+	rw = buf[0];		/* read/write (0/1) */
+	func = buf[1];		/* func (0/1/2) */
+	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, func = %d, addr = %#x, mode = %d, "
+	       "block size = %d, block(byte) number = %d\n",
+	       func, 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 < 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;
+}
+
+/**
+ * @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_MARVELL) + strlen(PRIV_CMD_PORT_CTRL);
+	if (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) {
+		memcpy(respbuf, &sec->param.port_ctrl_enabled, sizeof(int));
+		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_MARVELL) + 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);
+
+	memcpy(skb_put(skb, copyLen), respbuf + header_len, 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];
+	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 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_MARVELL) + strlen(PRIV_CMD_BOOTSLEEP);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &misc->param.boot_sleep,
+	       sizeof(misc->param.boot_sleep));
+	ret = sizeof(misc->param.boot_sleep);
+
+	PRINTM(MIOCTL, "boot sleep cfg: 0x%u\n", misc->param.boot_sleep);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(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_MARVELL) + 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 (strlen(respbuf) == header_len) {
+		/* GET operation */
+		memcpy(respbuf, &noa_cfg, sizeof(noa_cfg));
+		ret = sizeof(noa_cfg);
+	} else {
+		switch (user_data_len) {
+		case 5:
+			noa_cfg.noa_interval = (t_u32)data[4];
+		case 4:
+			noa_cfg.noa_duration = (t_u32)data[3];
+		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];
+		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];
+		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_MARVELL) + 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 (strlen(respbuf) == header_len) {
+		/* GET operation */
+		memcpy(respbuf, &opp_ps_cfg, sizeof(opp_ps_cfg));
+		ret = sizeof(opp_ps_cfg);
+	} else {
+		switch (user_data_len) {
+		case 2:
+			opp_ps_cfg.ct_window = (t_u8)data[1];
+		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;
+		default:
+			break;
+		}
+		woal_p2p_config(priv, MLAN_ACT_SET, &opp_ps_cfg);
+	}
+
+done:
+
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+#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];
+	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_MARVELL) + 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 (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) {
+		memcpy(respbuf, (t_u8 *)dfs_repeater,
+		       sizeof(mlan_ds_misc_dfs_repeater));
+		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_MARVELL) + strlen(PRIV_CMD_MIRACAST_CFG);
+
+	if (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;
+
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		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
+ */
+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_MARVELL) + 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 (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) {
+		memcpy(respbuf, (t_u8 *)&cfg_11n->param.coex_rx_winsize,
+		       sizeof(t_u32));
+		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_MARVELL) + 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 (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) {
+		memcpy(respbuf, (t_u8 *)&cfg_11n->param.txaggrctrl,
+		       sizeof(t_u32));
+		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_MARVELL) + strlen(PRIV_CMD_AUTO_TDLS);
+
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		data = priv->enable_auto_tdls;
+		memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+		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;
+}
+
+#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;
+
+	ENTER();
+
+	if (priv && priv->wdev)
+		wiphy = priv->wdev->wiphy;
+	if (!wiphy) {
+		PRINTM(MERROR, "wiphy is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	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_MARVELL) + 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;
+		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 (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_MARVELL) + strlen(PRIV_CMD_TDLS_IDLE_TIME);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&misc->param.tdls_idle_time, sizeof(t_u16));
+	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_MARVELL) + strlen(PRIV_CMD_DYN_BW);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&misc->param.dyn_bw, sizeof(t_u16));
+	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 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
+ */
+
+t_u8
+woal_get_center_freq_idx(IN moal_private *priv,
+			 IN t_u8 band, IN t_u32 pri_chan, IN 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;
+			}
+		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;
+			}
+		case 52:
+		case 56:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 54;
+				break;
+			}
+		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;
+			}
+		case 68:
+		case 72:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 70;
+				break;
+			}
+		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;
+			}
+		case 84:
+		case 88:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 86;
+				break;
+			}
+		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;
+			}
+		case 100:
+		case 104:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 102;
+				break;
+			}
+		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;
+			}
+		case 116:
+		case 120:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 118;
+				break;
+			}
+		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;
+			}
+		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;
+			}
+		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;
+			}
+		case 165:
+		case 169:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 167;
+				break;
+			}
+		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;
+			}
+		case 184:
+		case 188:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 186;
+				break;
+			}
+		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;
+			}
+
+		default:	/* error. go to the default */
+			center_freq_idx = 42;
+		}
+	}
+	return center_freq_idx;
+}
+
+/**
+ ** @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 };
+	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;
+
+	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_ChanSwitchAnn_t);
+	pcust_chansw_ie->mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP;	/*Add IE for BEACON/probe resp */
+
+	parse_arguments(respbuf + strlen(CMD_MARVELL) +
+			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;
+		goto done;
+	}
+	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 = data[0];
+	chan_switch->new_channel_num = data[2];
+	chan_switch->chan_switch_count = data[3];
+	DBG_HEXDUMP(MCMD_D, "CSA IE", (t_u8 *)pcust_chansw_ie->ie_buffer,
+		    pcust_chansw_ie->ie_length);
+
+	if (data[1] != 0) {
+		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 = data[0];
+		ext_chan_switch->new_oper_class = data[1];
+		ext_chan_switch->new_channel_num = data[2];
+		ext_chan_switch->chan_switch_count = data[3];
+		if (woal_check_valid_channel_operclass(priv, data[2], data[1])) {
+			PRINTM(MERROR, "Wrong channel switch parameters!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		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 (data[4] && data[2] > 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, data[2],
+						 data[4]);
+		if (data[4] == CHANNEL_BW_40MHZ_ABOVE ||
+		    data[4] == CHANNEL_BW_40MHZ_BELOW) {
+			pbwchansw_ie->new_channel_width = 0;
+			pbwchansw_ie->new_channel_center_freq0 =
+				center_freq_idx;
+		} else if (data[4] == 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 (data[4] == 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;
+		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 (data[0]) {
+		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 * (data[3] + 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;
+}
+
+/**
+ * @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               Issue ACS command to FW to get best channel and channel stats
+ *
+ * @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_acs(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0;
+	int data[MAX_BG_CHANNEL + 1];
+	int user_data_len = 0;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_acs *acs = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int i = 0, j = 0;
+	int ch_cnt = 0;
+	int resp_len = 0;
+	acs_result *pacs_result = NULL;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ACS_SCAN);
+
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+	if (user_data_len < 0 || user_data_len > MAX_CH_STATS) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+    /** Input format: [channels on 2.4G] */
+    /** Check validity of input channels if enable */
+	if (user_data_len < 2 && user_data_len != 0) {
+		PRINTM(MERROR,
+		       "If specify channels, at least specify 2 channels.\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	for (i = 0; i < user_data_len; i++) {
+		if (data[i] < 1 || data[i] > MAX_BG_CHANNEL) {
+			PRINTM(MERROR, "Invalid input channel %d.\n", data[i]);
+			ret = -EINVAL;
+			goto done;
+		}
+		for (j = 0; j < i; j++) {
+			if (data[j] == data[i]) {
+				PRINTM(MERROR, "Duplicate input channel %d.\n",
+				       data[i]);
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		ch_cnt++;
+	}
+
+	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;
+	req->action = MLAN_ACT_SET;
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_ACS;
+	acs = &(misc->param.acs);
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	acs->scan_chan_gap = priv->phandle->scan_chan_gap;
+#endif
+	for (i = 0; i < ch_cnt; i++)
+		acs->ch_stats[i].chan_num = data[i];
+	acs->ch_stats_num = ch_cnt;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	resp_len = sizeof(acs_result) + acs->ch_stats_num * sizeof(ChStat_t);
+	if (respbuflen < resp_len) {
+		PRINTM(MERROR, "response buffer length is too short!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+    /** Fill respond buf */
+	pacs_result = (acs_result *) respbuf;
+	pacs_result->best_ch = acs->best_ch;
+	pacs_result->ch_stats_num = acs->ch_stats_num;
+	memcpy(pacs_result->ch_stats, acs->ch_stats,
+	       sizeof(ChStat_t) * MIN(MAX_CH_STATS, pacs_result->ch_stats_num));
+
+	ret = resp_len;
+
+done:
+	if (req && status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	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;
+
+	ENTER();
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	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
+	memcpy(&cmd_buf, &priv_cmd.buf, sizeof(cmd_buf));
+#else
+	cmd_buf = priv_cmd.buf;
+#endif
+	if (copy_from_user(buf, 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_MARVELL, strlen(CMD_MARVELL)) &&
+	    woal_check_driver_status(priv->phandle)) {
+		PRINTM(MERROR, "%s fail when driver hang\n", buf);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (strncmp(buf, CMD_MARVELL, strlen(CMD_MARVELL)) == 0) {
+		/* This command has come from mlanutl app */
+
+		/* Check command */
+		if (strnicmp
+		    (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_MEMRDWR,
+			    strlen(PRIV_CMD_MEMRDWR)) == 0) {
+			/* Memory Read/Write */
+			len = woal_priv_memrdwr(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_SDCMD52RW,
+			    strlen(PRIV_CMD_SDCMD52RW)) == 0) {
+			/* Cmd52 read/write register */
+			len = woal_priv_sdcmd52rw(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#ifdef STA_SUPPORT
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_ARPFILTER,
+			    strlen(PRIV_CMD_ARPFILTER)) == 0) {
+			/* ARPFilter Configuration */
+			len = woal_priv_arpfilter(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#endif
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_QOS_CFG,
+			    strlen(PRIV_CMD_QOS_CFG)) == 0) {
+			t_u32 action = MLAN_ACT_GET;
+			if (strlen(buf) ==
+			    strlen(CMD_MARVELL) + strlen(PRIV_CMD_QOS_CFG)) {
+				pdata = buf;	/* GET operation */
+			} else {
+				pdata = buf + strlen(CMD_MARVELL) +
+					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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_DRCS_CFG,
+			    strlen(PRIV_CMD_DRCS_CFG)) == 0) {
+			/* DRCS configuration for mc_cfg_ext */
+			len = woal_priv_drcs_time_slicing_cfg(priv, buf,
+							      priv_cmd.
+							      total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_MULTI_CHAN_CFG,
+			    strlen(PRIV_CMD_MULTI_CHAN_CFG)) == 0) {
+			/* Channel time and buffer weight configuration */
+			len = woal_priv_multi_chan_config(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL),
+			    PRIV_CMD_MULTI_CHAN_POLICY,
+			    strlen(PRIV_CMD_MULTI_CHAN_POLICY)) == 0) {
+			/* Multi-channel Policy enable/disable */
+			len = woal_priv_multi_chan_policy(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_FWMACADDR,
+			    strlen(PRIV_CMD_FWMACADDR)) == 0) {
+			/* Set FW MAC address */
+			len = woal_priv_fwmacaddr(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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;
+#if defined(STA_SUPPORT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#if defined(REASSOCIATION)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL),
+			    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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#endif
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#if defined(DFS_TESTING_SUPPORT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#endif
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_ROBUSTCOEX,
+			    strlen(PRIV_CMD_ROBUSTCOEX)) == 0) {
+			/* Set Robustcoex GPIOcfg */
+			pdata = buf + strlen(CMD_MARVELL) +
+				strlen(PRIV_CMD_ROBUSTCOEX);
+			len = priv_cmd.total_len - strlen(PRIV_CMD_ROBUSTCOEX) -
+				strlen(CMD_MARVELL);
+			len = woal_priv_robustcoex(priv, pdata, len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(UAP_CFG80211)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL),
+			    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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL),
+			    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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_ACS_SCAN,
+			    strlen(PRIV_CMD_ACS_SCAN)) == 0) {
+			len = woal_priv_acs(priv, buf, priv_cmd.total_len);
+			goto handled;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL),
+			    PRIV_CMD_GET_CFG_CHAN_LIST,
+			    strlen(PRIV_CMD_GET_CFG_CHAN_LIST)) == 0) {
+			/* Get txpwrlimit */
+			len = woal_priv_getcfgchanlist(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+#endif
+		} else {
+			PRINTM(MERROR,
+			       "Unknown MARVELL 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 (!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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if(host_mlme)
+		goto done;
+#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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if(host_mlme)
+		goto done;
+#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));
+		memcpy(country_code, buf + strlen("COUNTRY") + 1, copy_len);
+		PRINTM(MIOCTL, "Set COUNTRY %s\n", country_code);
+		if (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 (!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 <= 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);
+		memcpy(buf, priv->current_addr, ETH_ALEN);
+		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 (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(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();
+
+	memcpy(ptmp_buf, pbss_desc->time_stamp, sizeof(pbss_desc->time_stamp));
+	ptmp_buf += sizeof(pbss_desc->time_stamp);
+
+	memcpy(ptmp_buf, &pbss_desc->beacon_period,
+	       sizeof(pbss_desc->beacon_period));
+	ptmp_buf += sizeof(pbss_desc->beacon_period);
+
+	memcpy(ptmp_buf, &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;
+	memcpy(ptmp_buf, tmp_ssid_hdr, sizeof(tmp_ssid_hdr));
+	ptmp_buf += sizeof(tmp_ssid_hdr);
+
+	memcpy(ptmp_buf, pbss_desc->ssid.ssid, 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;
+		memcpy(ptmp_buf, &pbss_desc->wmm_ie, 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;
+			memcpy(ptmp_buf, pbss_desc->pwpa_ie, 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;
+			memcpy(ptmp_buf, pbss_desc->prsn_ie, 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));
+
+	memcpy(tmp_rsp_entry.fixed_fields.bssid,
+	       pbss_desc->mac_address, 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.network_tsf = pbss_desc->network_tsf;
+	tmp_rsp_entry.bss_info_length = variable_size;
+
+	/*
+	 *  Copy fixed fields to user space
+	 */
+	memcpy(pcurrent, &tmp_rsp_entry, fixed_size);
+	pcurrent += fixed_size;
+
+	if (pbss_desc->pbeacon_buf) {
+		/*
+		 *  Copy variable length elements to user space
+		 */
+		memcpy(pcurrent, pbss_desc->pbeacon_buf,
+		       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
+ */
+int
+woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	int ret = 0;
+
+	ENTER();
+
+	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 100644
index 0000000..5afa086
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_eth_ioctl.h
@@ -0,0 +1,487 @@
+
+/** @file moal_eth_ioctl.h
+ *
+ * @brief This file contains definition for private IOCTL call.
+ *
+ * Copyright (C) 2014-2019, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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
+
+/** Marvell private command identifier string */
+#define CMD_MARVELL     "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
+#if defined(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_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_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"
+#define PRIV_CMD_SDCMD52RW      "sdcmd52rw"
+#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"
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+#define PRIV_CMD_RADIO_CTRL     "radioctrl"
+#endif
+#define PRIV_CMD_WMM_CFG        "wmmcfg"
+#if defined(STA_SUPPORT)
+#define PRIV_CMD_11D_CFG        "11dcfg"
+#define PRIV_CMD_11D_CLR_TBL    "11dclrtbl"
+#endif
+#define PRIV_CMD_WWS_CFG        "wwscfg"
+#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_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"
+#define PRIV_CMD_SDIO_CLOCK         "sdioclock"
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+#define PRIV_CMD_MPA_CTRL           "mpactrl"
+#endif
+#define PRIV_CMD_SLEEP_PARAMS       "sleepparams"
+#if defined(DFS_TESTING_SUPPORT)
+#define PRIV_CMD_DFS_TESTING        "dfstesting"
+#endif
+#define PRIV_CMD_CFP_CODE           "cfpcode"
+#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"
+#define PRIV_CMD_SD_CMD53_RW        "sdcmd53rw"
+#ifdef RX_PACKET_COALESCE
+#define PRIV_CMD_RX_COAL_CFG "rxpktcoal_cfg"
+#endif
+#define PRIV_CMD_MULTI_CHAN_CFG "mc_cfg"
+#define PRIV_CMD_MULTI_CHAN_POLICY "mc_policy"
+#define PRIV_CMD_DRCS_CFG "mc_cfg_ext"
+#if defined(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_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"
+
+#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
+
+#if defined(SDIO_SUSPEND_RESUME)
+#define PRIV_CMD_AUTO_ARP	"auto_arp"
+#endif
+
+#define PRIV_CMD_DEAUTH_CTRL    "ctrldeauth"
+
+/** 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_BOOTSLEEP            "bootsleep"
+
+int woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+
+/*
+ * 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 {
+  /** The value of the parameter itself */
+	t_s32 value;
+  /** Hardware should not use auto select */
+	t_u8 fixed;
+  /** Disable the feature */
+	t_u8 disabled;
+  /** Various specifc flags (if any) */
+	t_u16 flags;
+};
+
+/*
+ *  For all data larger than 16 octets, we need to use a
+ *  pointer to memory allocated in user space.
+ */
+struct mw_point {
+  /** Pointer to the data  (in user space) */
+	t_u8 *pointer;
+  /** number of fields or size in bytes */
+	t_u16 length;
+  /** Optional params */
+	t_u16 flags;
+};
+
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ */
+union mwreq_data {
+    /** Config - generic */
+	char name[IFNAMSIZ];
+
+    /** Extended network name */
+	struct mw_point essid;
+    /** Operation mode */
+	t_u32 mode;
+    /** PM duration/timeout */
+	struct mw_param power;
+    /** Access point address */
+	struct sockaddr ap_addr;
+    /** Other small parameters */
+	struct mw_param param;
+    /** Other large parameters */
+	struct mw_point data;
+};
+
+ /* The structure to exchange data for ioctl */
+struct mwreq {
+	union {
+	/** if name, e.g. "eth0" */
+		char ifrn_name[IFNAMSIZ];
+	} ifr_ifrn;
+
+    /** Data part */
+	union mwreq_data u;
+};
+
+/** woal HT capacity info structure */
+typedef struct woal_priv_ht_cap_info {
+    /** HT capacity info for bg */
+	t_u32 ht_cap_info_bg;
+    /** HT capacity info for a */
+	t_u32 ht_cap_info_a;
+} woal_ht_cap_info;
+
+/** woal private addba structure */
+typedef struct woal_priv_addba {
+    /** Time out */
+	t_u32 time_out;
+    /** Transmission window size */
+	t_u32 tx_win_size;
+    /** Receiver window size */
+	t_u32 rx_win_size;
+    /** Tx amsdu */
+	t_u32 tx_amsdu;
+    /** Rx amsdu */
+	t_u32 rx_amsdu;
+} woal_addba;
+
+/** 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;
+} woal_tx_rate_cfg;
+
+/** woal embedded supplicant structure */
+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);
+mlan_status woal_ioctl_aggr_prio_tbl(moal_private *priv, t_u32 action,
+				     mlan_ds_11n_aggr_prio_tbl *aggr_prio_tbl);
+
+int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req);
+
+#define PRIV_CMD_ACS_SCAN "acs"
+
+/** Type definition of mlan_acs_scan */
+typedef struct _acs_result {
+    /** Best Channel Number */
+	t_u8 best_ch;
+    /** Channel Statistics Number */
+	t_u8 ch_stats_num;
+    /** Channel Statistics */
+	ChStat_t ch_stats[0];
+} acs_result, *pacs_result;
+
+/** 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;
+} __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[0];
+} __ATTRIB_PACK__ wlan_ieee80211_chan_list;
+#endif /** _WOAL_ETH_PRIV_H_ */
diff --git a/wlan_sd8987/mlinux/moal_ioctl.c b/wlan_sd8987/mlinux/moal_ioctl.c
new file mode 100644
index 0000000..1ab08ea
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_ioctl.c
@@ -0,0 +1,6412 @@
+/** @file moal_ioctl.c
+  *
+  * @brief This file contains ioctl function to MLAN
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include    "moal_main.h"
+#include    "moal_eth_ioctl.h"
+#include    "moal_sdio.h"
+#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_cfgvendor.h"
+#endif
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+#define MRVL_TLV_HEADER_SIZE            4
+/* Marvell 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[] = {
+	{"WW", 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    */
+};
+
+/** EEPROM Region code mapping table */
+static region_code_mapping_t hw_region_code_mapping[] = {
+	{"WW ", 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"
+};
+
+/********************************************************
+			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
+extern int cfg80211_wext;
+int disconnect_on_suspend;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+extern int dfs_offload;
+#endif
+#endif
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief This function converts region string to region code
+ *
+ *  @param country_code     Region string
+ *
+ *  @return                 Region code
+ */
+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
+ */
+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 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)
+{
+	int 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)
+		memcpy(&mlist->mac_list[mlist->num_multicast_addr], mac,
+		       ETH_ALEN);
+	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)
+			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_IOCTL_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 = *(t_u32 *)req->pbuf;
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (sub_command != MLAN_OID_GET_DEBUG_INFO) {
+		if (priv->phandle->surprise_removed == MTRUE ||
+		    priv->phandle->driver_state) {
+			PRINTM(MERROR,
+			       "IOCTL is not allowed while the device is not present or hang\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#if defined(SDIO_SUSPEND_RESUME)
+		if (priv->phandle->is_suspended == MTRUE) {
+			PRINTM(MERROR,
+			       "IOCTL is not allowed while suspended\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);
+#ifdef DFS_TESTING_SUPPORT
+		if (priv->phandle->cac_period_jiffies) {
+			cac_left_jiffies = priv->phandle->cac_period_jiffies -
+				(jiffies - priv->phandle->meas_start_jiffies);
+		}
+#endif
+		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 && 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;
+				memcpy(&priv->phandle->delay_ssid_bssid,
+				       &bss->param.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:
+		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
+ *
+ *  @return       MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ *                  -- success, otherwise fail
+ */
+mlan_status
+woal_request_set_mac_address(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_MAC_ADDR;
+	memcpy(&bss->param.mac_addr, priv->current_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, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
+		HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
+	} else {
+		PRINTM(MERROR,
+		       "set mac address failed! status=%d, error_code=0x%x\n",
+		       status, req->status_code);
+	}
+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;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_NO_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)
+		memcpy(&bss->param.deauth_param.mac_addr, mac,
+		       sizeof(mlan_802_11_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
+
+#ifdef UAP_SUPPORT
+/**
+ *  @brief Check current uap/go connection status
+ *         Need handle channel switch if current channel is DFS channel
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param new channel 		new channel
+ *  @return              N/A
+ */
+void
+woal_check_uap_dfs_status(moal_private *priv, t_u8 wait_option,
+			  t_u8 new_channel)
+{
+	chan_band_info channel;
+	mlan_bss_info bss_info;
+#if defined(UAP_SUPPORT)
+	IEEEtypes_ChanSwitchAnn_t *chan_switch = NULL;
+	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;
+	t_u8 bw = 0, oper_class = 0;
+#endif
+
+	/* Get BSS information */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, wait_option, &bss_info))
+		goto done;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_ap_channel(priv, MLAN_ACT_GET, wait_option, &channel))
+		goto done;
+	PRINTM(MCMND, "is_11h_active=%d dfs_check_channel=%d\n",
+	       bss_info.is_11h_active, bss_info.dfs_check_channel);
+	PRINTM(MCMND, "uap current channel=%d new_channel=%d\n",
+	       channel.channel, new_channel);
+#if defined(UAP_SUPPORT)
+	if (new_channel == channel.channel)
+		goto done;
+	if (bss_info.is_11h_active &&
+	    (bss_info.dfs_check_channel == channel.channel)) {
+		if (new_channel < MAX_BG_CHANNEL) {
+			bw = 20;
+		} else {
+			switch (channel.bandcfg.chanWidth) {
+			case CHAN_BW_20MHZ:
+				bw = 20;
+				break;
+			case CHAN_BW_40MHZ:
+				bw = 40;
+				break;
+			case CHAN_BW_80MHZ:
+				bw = 80;
+				break;
+			default:
+				break;
+			}
+		}
+		woal_priv_get_nonglobal_operclass_by_bw_channel(priv, bw,
+								new_channel,
+								&oper_class);
+		PRINTM(MCMND,
+		       "Switch the uap channel from %d to %d, oper_class=%d bw=%d\n",
+		       channel.channel, new_channel, oper_class, bw);
+		ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+		if (ioctl_req) {
+			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 */
+			if (!oper_class) {
+				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 =
+					sizeof(IEEEtypes_ChanSwitchAnn_t) -
+					sizeof(IEEEtypes_Header_t);
+				chan_switch->chan_switch_mode = 1;	/* STA should not transmit */
+				chan_switch->new_channel_num = new_channel;
+				chan_switch->chan_switch_count =
+					DEF_CHAN_SWITCH_COUNT;
+				DBG_HEXDUMP(MCMD_D, "CSA IE",
+					    (t_u8 *)pcust_chansw_ie->ie_buffer,
+					    pcust_chansw_ie->ie_length);
+			} else {
+				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;
+				ext_chan_switch->element_id =
+					EXTEND_CHANNEL_SWITCH_ANN;
+				ext_chan_switch->len =
+					sizeof(IEEEtypes_ExtChanSwitchAnn_t) -
+					sizeof(IEEEtypes_Header_t);
+				ext_chan_switch->chan_switch_mode = 1;	/* STA should not transmit */
+				ext_chan_switch->new_channel_num = new_channel;
+				ext_chan_switch->chan_switch_count =
+					DEF_CHAN_SWITCH_COUNT;
+				ext_chan_switch->new_oper_class = oper_class;
+				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,
+						    wait_option);
+			if (status != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Failed to set CSA IE\n");
+				goto done;
+			}
+			PRINTM(MCMND, "CSA/ECSA ie index=%d\n",
+			       pcust_chansw_ie->ie_index);
+			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 *
+							 (DEF_CHAN_SWITCH_COUNT
+							  + 2) * 110 / 1000);
+
+			pcust_chansw_ie->ie_index = 0xffff;
+			pcust_chansw_ie->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			status = woal_request_ioctl(priv, ioctl_req,
+						    MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Failed to clear CSA/ECSA IE\n");
+			}
+		}
+	}
+#endif
+done:
+#if defined(UAP_SUPPORT)
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+#endif
+	return;
+}
+#endif
+
+/**
+ *  @brief Check current multi-channel connections
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param new channel 	new channel
+ *
+ *  @return              N/A
+ */
+void
+woal_check_mc_connection(moal_private *priv, t_u8 wait_option, t_u8 new_channel)
+{
+#ifdef UAP_SUPPORT
+	moal_handle *handle = priv->phandle;
+	int i;
+#endif
+	t_u16 enable = 0;
+
+	woal_mc_policy_cfg(priv, &enable, wait_option, MLAN_ACT_GET);
+	if (!enable)
+		return;
+#ifdef UAP_SUPPORT
+	for (i = 0; i < handle->priv_num; i++) {
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
+			if (handle->priv[i]->bss_started == MTRUE)
+				woal_check_uap_dfs_status(handle->priv[i],
+							  wait_option,
+							  new_channel);
+		}
+	}
+#endif
+	return;
+}
+
+/**
+ *  @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;
+	mlan_ssid_bssid temp_ssid_bssid;
+
+	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);
+	}
+	if (!ssid_bssid) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	memcpy(&temp_ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_find_best_network(priv, wait_option, &temp_ssid_bssid))
+		woal_check_mc_connection(priv, wait_option,
+					 temp_ssid_bssid.channel);
+
+	/* 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)
+		memcpy(&bss->param.ssid_bssid, 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)
+		memcpy(ssid_bssid, &bss->param.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)
+			memcpy(bss_info, &info->param.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)
+			memcpy(misc->param.gen_ie.ie_data, ie, *ie_len);
+	}
+
+	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)
+			memcpy(ie, misc->param.gen_ie.ie_data, *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(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 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(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(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)
+		memcpy(&pcfg->param.power_cfg, power_cfg,
+		       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)
+		memcpy(power_cfg, &pcfg->param.power_cfg,
+		       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(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
+ */
+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);
+	memcpy(country_code->country_code, country, 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))
+		memcpy(&rate->param.rate_cfg, datarate,
+		       sizeof(mlan_rate_cfg_t));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret == MLAN_STATUS_SUCCESS && datarate && action == MLAN_ACT_GET)
+		memcpy(datarate, &rate->param.rate_cfg,
+		       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)
+		memcpy(assoc_rsp, &misc->param.assoc_resp,
+		       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_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)
+			memcpy(priv->current_addr,
+			       &info->param.fw_info.mac_addr,
+			       sizeof(mlan_802_11_mac_addr));
+		memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
+		if (fw_info)
+			memcpy(fw_info, &info->param.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);
+	memcpy(buf, &cfg->param.ext_cap, sizeof(ExtCap_t));
+	ret = sizeof(ExtCap_t);
+out:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef PROC_DEBUG
+/**
+ *  @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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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) {
+			memcpy(debug_info, &info->param.debug_info,
+			       sizeof(mlan_debug_info));
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+#endif /* PROC_DEBUG */
+
+#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 *custom_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;
+	custom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), flag);
+	if (!custom_ie) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (copy_from_user
+	    (custom_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 ((custom_ie->len == 0)||(custom_ie->len ==
+				    sizeof(custom_ie->ie_data_list[0].
+					   ie_index)))
+		ioctl_req->action = MLAN_ACT_GET;
+	else
+		ioctl_req->action = MLAN_ACT_SET;
+
+	memcpy(&misc->param.cust_ie, 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(custom_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;
+	memcpy(pcust_bcn_ie->ie_buffer, ie, ie_len);
+
+	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;
+
+	memcpy(&misc->param.tdls_config, tdls_data,
+	       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_IOCTL_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(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(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)
+#if defined(WIFI_DIRECT_SUPPORT)
+		    || (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
+#endif
+			) {
+			PRINTM(MWARN, "Invalid BSS role\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (bss_role == 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(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 */
+
+#if defined(SDIO_SUSPEND_RESUME)
+/**
+ *  @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) {
+			memcpy(ipaddr_cfg.ip_addr[ipaddr_cfg.ip_addr_num],
+			       priv->ip_addr, 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;
+	memcpy(&misc->param.ipaddr_cfg, &ipaddr_cfg, sizeof(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;
+}
+
+#endif
+
+/**
+ *  @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_IOCTL_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)
+		memcpy(&pmcfg->param.hs_cfg, hscfg, 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) {
+			memcpy(hscfg, &pmcfg->param.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 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)
+{
+	moal_handle *handle = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_hs_cfg hscfg;
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	handle = priv->phandle;
+	/* 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 defined(SDIO_SUSPEND_RESUME)
+	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);
+	}
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO_SUSPEND_RESUME)
+/**  @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
+
+	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 (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_IOCTL_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
+
+	if (handle->hs_auto_arp) {
+		PRINTM(MIOCTL, "Host Sleep enabled... set FW auto arp\n");
+		/* Set auto arp response configuration to Fw */
+		woal_set_auto_arp(handle, MTRUE);
+	}
+
+	/* 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);
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	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 {
+		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 */
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	if (hs_actived != MTRUE) {
+		handle->hs_skip_count++;
+#ifdef SDIO_SUSPEND_RESUME
+		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;
+}
+#endif
+
+#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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	union {
+		t_u32 l;
+		t_u8 c[4];
+	} ver;
+	char fw_ver[32];
+
+	ENTER();
+
+	ver.l = handle->fw_release_number;
+	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 drvdbg       Driver debug level
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_set_drvdbg(moal_private *priv, t_u32 drvdbg)
+{
+	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 = drvdbg;
+
+	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_IOCTL_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)
+		memcpy(&misc->param.mgmt_subtype_mask,
+		       pmgmt_subtype_mask,
+		       sizeof(misc->param.mgmt_subtype_mask));
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+
+	if (req->action == MLAN_ACT_GET)
+		memcpy(pmgmt_subtype_mask, &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;
+	memcpy(&bf_cfg->param.tx_bf, 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)
+		memcpy(tx_bf_cfg, &bf_cfg->param.tx_bf,
+		       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)
+{
+	ENTER();
+
+	if (priv == NULL) {
+		LEAVE();
+		return;
+	}
+	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) {
+			memcpy(pm_info, &pmcfg->param.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 && 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;
+#ifdef UAP_SUPPORT
+	chan_band_info chan;
+	chan_band_info uapchan;
+#endif
+	ENTER();
+
+	if (priv->skip_cac) {
+		LEAVE();
+		return ret;
+	}
+
+	/* 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)) {
+		/* When any other interface is active
+		 * Get rid of CAC timer when drcs is disabled */
+		t_u16 enable = 0;
+		if (priv->phandle->card_info->drcs)
+			ret = woal_mc_policy_cfg(priv, &enable, wait_option,
+						 MLAN_ACT_GET);
+		if (!enable) {
+			LEAVE();
+			return ret;
+		}
+#ifdef UAP_SUPPORT
+		else {
+			woal_get_active_intf_channel(priv, &chan);
+			woal_set_get_ap_channel(priv, MLAN_ACT_GET,
+						MOAL_IOCTL_WAIT, &uapchan);
+			if (chan.channel != uapchan.channel) {
+				if (uapchan.is_dfs_chan) {
+					PRINTM(MERROR,
+					       "DFS channel is not allowed when another connection exists on different channel\n");
+					PRINTM(MERROR,
+					       "Another connection's channel=%d, dfs channel=%d\n",
+					       chan.channel, uapchan.channel);
+					return -EINVAL;
+				} else {
+					//check if we need move first uap0 from DFS channel to new non dfs channel
+					woal_check_mc_connection(priv,
+								 wait_option,
+								 uapchan.
+								 channel);
+				}
+			}
+		}
+#endif
+	}
+
+	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 && 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();
+
+	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;
+	memcpy(&radio_cfg->param.remain_chan, pchan,
+	       sizeof(mlan_ds_remain_chan));
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		memcpy(pchan, &radio_cfg->param.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;
+}
+
+#if defined(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;
+	memcpy(&misc_cfg->param.p2p_config, p2p_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)
+			memcpy(p2p_config, &misc_cfg->param.p2p_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)
+{
+	int ret = 0;
+	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");
+		ret = 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)
+		memcpy(channel, &(bss->param.sta_channel), sizeof(*channel));
+
+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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+			memcpy(signal, &info->param.signal,
+			       sizeof(mlan_ds_get_signal));
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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;
+	memcpy((void *)&scan->param.scan_resp, (void *)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) {
+			memcpy(scan_resp, &scan->param.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;
+
+		memcpy(scan->param.scan_req.scan_ssid.ssid,
+		       req_ssid->ssid,
+		       MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len));
+		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));
+	memcpy(&bss->param.ssid_bssid.ssid, &bss_info.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;
+	t_u8 *mac = 0;
+
+	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;
+
+	memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		memcpy(ssid_bssid, &bss->param.ssid_bssid,
+		       sizeof(mlan_ssid_bssid));
+		mac = (t_u8 *)&ssid_bssid->bssid;
+		PRINTM(MINFO, "Find network: ssid=%s, " MACSTR ", idx=%d\n",
+		       ssid_bssid->ssid.ssid, MAC2STR(mac),
+		       (int)ssid_bssid->idx);
+	}
+
+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;
+	t_u8 *mac = 0;
+
+	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;
+
+	memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
+
+	mac = (t_u8 *)&ssid_bssid->bssid;
+	PRINTM(MINFO, "ssid=%s, " MACSTR ", idx=%d\n",
+	       ssid_bssid->ssid.ssid, MAC2STR(mac), (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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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;
+	memcpy(scan->param.user_scan.scan_cfg_buf, 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)
+		memcpy(scan_cfg, &scan->param.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);
+	memcpy(&scan->param.scan_cfg, &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(cfg80211_wext) && handle->scan_request) {
+	    /** 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;
+	struct 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) {
+	/** skip check the scan age out */
+		ret = woal_find_best_network(priv, wait_option, ssid_bssid);
+		LEAVE();
+		return ret;
+	}
+#endif
+	do_gettimeofday(&t);
+/** scan result timeout value */
+#define SCAN_RESULT_AGEOUT      10
+	if (t.tv_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;
+	memcpy(scan->param.user_scan.scan_cfg_buf, scan_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;
+		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;
+	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;
+		sprintf(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;
+}
+
+/**
+ *  @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);
+	memcpy(&scan->param.scan_cfg, &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);
+	memcpy(&scan->param.scan_cfg, &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;
+
+	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 */
+
+/**
+ * @brief Set/Get configure multi-channel policy
+ *
+ * @param priv		A pointer to moal_private structure
+ * @param enable	A pointer to enable
+ * @param wait_option	wait_option of ioctl
+ * @param action	action of ioctl
+ *
+ * @return          MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_mc_policy_cfg(moal_private *priv, t_u16 *enable,
+		   t_u8 wait_option, t_u8 action)
+{
+	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) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_MULTI_CHAN_POLICY;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = action;
+	if (MLAN_ACT_SET == action)
+		cfg->param.multi_chan_policy = *enable;
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (MLAN_ACT_GET == action)
+		*enable = cfg->param.multi_chan_policy;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @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;
+	memcpy(del_ba->peer_mac_addr, zero_mac, ETH_ALEN);
+
+	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;
+	}
+}
+
+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");
diff --git a/wlan_sd8987/mlinux/moal_main.c b/wlan_sd8987/mlinux/moal_main.c
new file mode 100644
index 0000000..536b49c
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_main.c
@@ -0,0 +1,10221 @@
+/** @file moal_main.c
+  *
+  * @brief This file contains the major functions in WLAN
+  * driver.
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+#include    "moal_sdio.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include    "moal_cfg80211.h"
+#include    "moal_cfgvendor.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
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/** card info for sd877 */
+static struct _card_info card_info_sd8777 = {
+	.embedded_supp = 1,
+	.drcs = 0,
+	.go_noa = 0,
+	.v15_update = 0,
+	.v16_fw_api = 0,
+	.rx_rate_max = 76,
+};
+
+/** card info for sd8787 */
+static struct _card_info card_info_sd8787 = {
+	.embedded_supp = 1,
+	.drcs = 0,
+	.go_noa = 0,
+	.v15_update = 0,
+	.v16_fw_api = 0,
+	.rx_rate_max = 76,
+};
+
+/** card info for sd8797 */
+static struct _card_info card_info_sd8797 = {
+	.embedded_supp = 1,
+	.drcs = 0,
+	.go_noa = 0,
+	.v15_update = 0,
+	.v16_fw_api = 0,
+	.rx_rate_max = 76,
+};
+
+/** card info for sd887 */
+static struct _card_info card_info_sd8887 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v15_update = 1,
+	.v16_fw_api = 0,
+	.rx_rate_max = 196,
+};
+
+/** card info for sd8801 */
+static struct _card_info card_info_sd8801 = {
+	.embedded_supp = 0,
+	.drcs = 0,
+	.go_noa = 0,
+	.v15_update = 0,
+	.v16_fw_api = 0,
+	.rx_rate_max = 76,
+};
+
+/** card info for sd8897 */
+static struct _card_info card_info_sd8897 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v15_update = 1,
+	.v16_fw_api = 0,
+	.rx_rate_max = 196,
+};
+
+/** card info for sd8977 */
+static struct _card_info card_info_sd8977 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v15_update = 1,
+	.v16_fw_api = 1,
+	.rx_rate_max = 76,
+};
+
+/** card info for sd8978 */
+static struct _card_info card_info_sd8978 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v15_update = 1,
+	.v16_fw_api = 1,
+	.rx_rate_max = 76,
+};
+
+static struct _card_info card_info_sd8997 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v15_update = 1,
+	.v16_fw_api = 1,
+	.rx_rate_max = 196,
+};
+
+static struct _card_info card_info_sd8987 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 0,
+	.v15_update = 1,
+	.v16_fw_api = 1,
+	.rx_rate_max = 196,
+};
+
+#define KERN_VERSION    "4X"
+
+/** Driver version */
+char driver_version[] =
+	"SD8XXX-%s-C" KERN_VERSION "15" MLAN_RELEASE_VERSION
+	"-GPL" "-(" "FP" FPNUM ")"
+#ifdef	DEBUG_LEVEL2
+	"-dbg"
+#endif
+	" ";
+
+/** SD8787 Card */
+#define CARD_SD8787     "SD8787"
+/** SD8777 Card */
+#define CARD_SD8777     "SD8777"
+/** SD8887 Card */
+#define CARD_SD8887     "SD8887"
+/** SD8801 Card */
+#define CARD_SD8801     "SD8801"
+/** SD8897 Card */
+#define CARD_SD8897     "SD8897"
+/** SD8797 Card */
+#define CARD_SD8797     "SD8797"
+/** SD8977 Card */
+#define CARD_SD8977     "SD8977"
+/** SD8978 Card */
+#define CARD_SD8978     "SD8978"
+/** SD8997 Card */
+#define CARD_SD8997     "SD8997"
+/** SD8987 Card */
+#define CARD_SD8987     "SD8987"
+
+/** Firmware name */
+char *fw_name;
+int req_fw_nowait=1;
+int fw_reload;
+
+/** MAC address */
+char *mac_addr;
+
+#ifdef MFG_CMD_SUPPORT
+/** Mfg mode */
+int mfg_mode;
+#endif
+
+/** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+int intmode = INT_MODE_SDIO;
+/** GPIO interrupt pin number */
+int gpiopin;
+
+#ifdef CONFIG_OF
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+extern int disable_regd_by_driver;
+/** Region alpha2 string */
+extern char *reg_alpha2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int country_ie_ignore;
+extern int beacon_hints;
+#endif
+#endif
+extern int cfg80211_drcs;
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+extern int host_mlme;
+#endif
+#endif
+
+int drcs_chantime_mode = 0;
+
+/** Auto deep sleep */
+int auto_ds;
+
+/** IEEE PS mode */
+int ps_mode;
+
+/** Max Tx buffer size */
+int max_tx_buf;
+
+#ifdef STA_SUPPORT
+/** Max STA interfaces */
+int max_sta_bss = DEF_STA_BSS;
+/** STA interface name */
+char *sta_name;
+#endif
+
+#ifdef UAP_SUPPORT
+/** Max uAP interfaces */
+int max_uap_bss = DEF_UAP_BSS;
+/** uAP interface name */
+char *uap_name;
+/** Max uAP station number */
+int uap_max_sta = 0;
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+/** Max WIFIDIRECT interfaces */
+int max_wfd_bss = DEF_WIFIDIRECT_BSS;
+/** WIFIDIRECT interface name */
+char *wfd_name;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+/** max VIRTUAL bss */
+int max_vir_bss = DEF_VIRTUAL_BSS;
+#endif
+#endif
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+int pm_keep_power = 1;
+/** HS when shutdown */
+int shutdown_hs;
+#endif
+
+/** SDIO slew rate */
+int slew_rate = 3;
+
+#if defined(STA_SUPPORT)
+/** 802.11d configuration */
+int cfg_11d;
+#endif
+
+/** FW download CRC check */
+int fw_crc_check = 1;
+
+/** fw serial download check */
+int fw_serial = 1;
+
+/** napi support*/
+int napi;
+
+/** DPD data config file */
+char *dpd_data_cfg;
+
+/** CAL data config file */
+char *cal_data_cfg;
+/** Init config file (MAC address, register etc.) */
+char *init_cfg;
+
+/** Set configuration data of Tx power limitation */
+char *txpwrlimit_cfg;
+/** Set configuration data of Tx power limitatio */
+char *country_txpwrlimit;
+/** Allow setting tx power table of country */
+int cntry_txpwr = 0;
+
+/** Init hostcmd file */
+char *init_hostcmd_cfg;
+
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+/** CFG80211 and WEXT mode */
+int cfg80211_wext = STA_WEXT_MASK | UAP_WEXT_MASK;
+#else
+/** CFG80211 mode */
+int cfg80211_wext = STA_CFG80211_MASK | UAP_CFG80211_MASK;
+#endif
+
+int fw_region = 0;
+
+/** Work queue priority */
+int wq_sched_prio;
+/** Work queue scheduling policy */
+int wq_sched_policy = SCHED_NORMAL;
+/** rx_work flag */
+int rx_work;
+
+int low_power_mode_enable;
+
+int hw_test;
+
+#ifdef CONFIG_OF
+int dts_enable = 1;
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+int p2p_enh;
+#endif
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+int dfs_offload = 0;
+#endif
+
+#ifdef ANDROID_KERNEL
+int wakelock_timeout = WAKE_LOCK_TIMEOUT;
+#endif
+
+/** woal_callbacks */
+static mlan_callbacks woal_callbacks = {
+	.moal_get_fw_data = moal_get_fw_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_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,
+
+	.moal_write_reg = moal_write_reg,
+	.moal_read_reg = moal_read_reg,
+	.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,
+	.moal_memset = moal_memset,
+	.moal_memcpy = moal_memcpy,
+	.moal_memmove = moal_memmove,
+	.moal_memcmp = moal_memcmp,
+	.moal_udelay = moal_udelay,
+	.moal_get_system_time = moal_get_system_time,
+	.moal_get_boot_ktime = moal_get_boot_ktime,
+	.moal_usleep = moal_usleep,
+	.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,
+};
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#if defined(WIFI_DIRECT_SUPPORT)
+int drv_mode = (DRV_MODE_STA | DRV_MODE_UAP | DRV_MODE_WIFIDIRECT);
+#else
+int drv_mode = (DRV_MODE_STA | DRV_MODE_UAP);
+#endif
+#else
+#ifdef STA_SUPPORT
+int drv_mode = DRV_MODE_STA;
+#else
+int drv_mode = DRV_MODE_UAP;
+#endif /* STA_SUPPORT */
+#endif /* STA_SUPPORT & UAP_SUPPORT */
+
+int pmic = 0;
+
+int antcfg = 0;
+
+t_u32 uap_oper_ctrl = 0;
+
+int hs_wake_interval = 400;
+int indication_gpio = 0xff;
+
+/** all the feature are enabled */
+#define DEFAULT_DEV_CAP_MASK 0xffffffff
+t_u32 dev_cap_mask = DEFAULT_DEV_CAP_MASK;
+int sdio_rx_aggr = MTRUE;
+/********************************************************
+		Global Variables
+********************************************************/
+
+/** 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];
+
+/** The global variable of scan beacon buffer **/
+int fixed_beacon_buffer = 0;
+/** the pointer of new fwdump fname for each dump**/
+char *fwdump_fname = NULL;
+
+#ifdef WIFI_DIRECT_SUPPORT
+int GoAgeoutTime = 0;
+#endif
+
+t_u16 multi_dtim = 0;
+
+t_u16 inact_tmo = 0;
+
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define	DEFAULT_DEBUG_MASK	(0xffffffff)
+#else
+#define DEFAULT_DEBUG_MASK	(MMSG | MFATAL | MERROR)
+#endif /* DEBUG_LEVEL2 */
+t_u32 drvdbg = DEFAULT_DEBUG_MASK;
+
+#endif /* DEBUG_LEVEL1 */
+
+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);
+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)
+u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb,
+		      struct net_device *sb_dev,
+		      select_queue_fallback_t fallback);
+#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
+
+void woal_sdio_reg_dbg(moal_handle *phandle);
+
+mlan_debug_info info;
+
+static moal_handle *reset_handle;
+/** Hang workqueue */
+static struct workqueue_struct *hang_workqueue;
+/** Hang work */
+static struct work_struct hang_work;
+
+static void
+woal_oops_dump(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason)
+{
+	int cardidx = 0;
+	moal_handle *handle = NULL;
+
+	printk("woal oops dump for reason: %d\n", reason);
+	for (cardidx = 0; cardidx < MAX_MLAN_ADAPTER; cardidx++) {
+		if (m_handle[cardidx] == NULL)
+			continue;
+		handle = m_handle[cardidx];
+		if (handle->pmlan_adapter) {
+			printk("dump adapter %d info\n", cardidx);
+			mlan_dump_adapter(handle->pmlan_adapter);
+		}
+	}
+}
+
+void
+woal_register_kdump_func(moal_handle *handle)
+{
+	int res = 0;
+
+	if (handle == NULL || handle->kdumper.dump)
+		return;
+	handle->kdumper.dump = woal_oops_dump;
+	res = kmsg_dump_register(&handle->kdumper);
+	if (res) {
+		printk("failed to register kdumper for card: %d\n",
+		       handle->handle_idx);
+		handle->kdumper.dump = NULL;
+	}
+}
+
+void
+woal_unregister_kdump_func(moal_handle *handle)
+{
+	if (handle == NULL || handle->kdumper.dump == NULL)
+		return;
+	kmsg_dump_unregister(&handle->kdumper);
+	handle->kdumper.dump = NULL;
+}
+
+/**
+ *  @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;
+	ENTER();
+	if (!reset_handle) {
+		LEAVE();
+		return;
+	}
+	for (i = 0; i < reset_handle->priv_num; i++) {
+		if (reset_handle->priv[i] && reset_handle->priv[i]->netdev) {
+			PRINTM(MMSG, "Close netdev %s\n",
+			       reset_handle->priv[i]->netdev->name);
+			rtnl_lock();
+			dev_close(reset_handle->priv[i]->netdev);
+			rtnl_unlock();
+			break;
+		}
+	}
+	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;
+		mlan_ioctl(handle->pmlan_adapter, NULL);
+		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++) {
+#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
+#if defined(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 */
+		memcpy(priv->ip_addr, &ifa->ifa_address,
+		       sizeof(ifa->ifa_address));
+		priv->ip_addr_type = IPADDR_TYPE_IPV4;
+#ifdef STA_CFG80211
+		if (!hw_test && priv->roaming_enabled) {
+			sprintf(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;
+}
+
+/**
+ *  @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
+
+#if defined(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)) {
+					memcpy(&ssid_bssid->ssid,
+					       &bss_info.ssid,
+					       sizeof(bss_info.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)) {
+				memcpy(&ssid_bssid->bssid, &bss_info.bssid,
+				       MLAN_MAC_ADDR_LENGTH);
+				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 Get mode
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option   Wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
+ *
+ *  @return              Wireless mode
+ */
+t_u32
+woal_get_mode(moal_private *priv, t_u8 wait_option)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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
+ */
+static void
+woal_update_firmware_name(moal_handle *handle)
+{
+	if (fw_name) {
+		handle->drv_mode.fw_name = fw_name;
+	} else {
+#if defined(UAP_SUPPORT) && defined(STA_SUPPORT)
+		if (handle->card_type == CARD_TYPE_SD8777)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8777;
+		else if (handle->card_type == CARD_TYPE_SD8787)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8787;
+		else if (handle->card_type == CARD_TYPE_SD8887)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8887;
+		else if (handle->card_type == CARD_TYPE_SD8801)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8801;
+		else if (handle->card_type == CARD_TYPE_SD8897)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8897;
+		else if (handle->card_type == CARD_TYPE_SD8797)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8797;
+		else if (handle->card_type == CARD_TYPE_SD8977)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8977;
+		else if (handle->card_type == CARD_TYPE_SD8978)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8978;
+		else if (handle->card_type == CARD_TYPE_SD8997)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8997;
+		else if (handle->card_type == CARD_TYPE_SD8987)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8987;
+		else
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME;
+#else
+#ifdef UAP_SUPPORT
+		if (handle->card_type == CARD_TYPE_SD8777)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8777;
+		else if (handle->card_type == CARD_TYPE_SD8787)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8787;
+		else if (handle->card_type == CARD_TYPE_SD8887)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8887;
+		else if (handle->card_type == CARD_TYPE_SD8801)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8801;
+		else if (handle->card_type == CARD_TYPE_SD8897)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8897;
+		else if (handle->card_type == CARD_TYPE_SD8797)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8797;
+		else if (handle->card_type == CARD_TYPE_SD8977)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8977;
+		else if (handle->card_type == CARD_TYPE_SD8978)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8978;
+		else if (handle->card_type == CARD_TYPE_SD8997)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8997;
+		else if (handle->card_type == CARD_TYPE_SD8987)
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8987;
+		else
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME;
+#else
+		if (handle->card_type == CARD_TYPE_SD8777)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8777;
+		else if (handle->card_type == CARD_TYPE_SD8787)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8787;
+		else if (handle->card_type == CARD_TYPE_SD8887)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8887;
+		else if (handle->card_type == CARD_TYPE_SD8801)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8801;
+		else if (handle->card_type == CARD_TYPE_SD8897)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8897;
+		else if (handle->card_type == CARD_TYPE_SD8797)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8797;
+		else if (handle->card_type == CARD_TYPE_SD8977)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8977;
+		else if (handle->card_type == CARD_TYPE_SD8978)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8978;
+		else if (handle->card_type == CARD_TYPE_SD8997)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8997;
+		else if (handle->card_type == CARD_TYPE_SD8987)
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME_8987;
+		else
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME;
+#endif /* UAP_SUPPORT */
+#endif /* UAP_SUPPORT && STA_SUPPORT */
+	}
+}
+
+/**
+ *  @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;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	int last_wfd_index = 0;
+#endif
+#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;
+	}
+#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;
+	}
+#endif /* UAP_SUPPORT */
+
+#if defined(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;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+		intf_num += max_vir_bss;
+#endif
+	}
+#endif /* WIFI_DIRECT_SUPPORT  && V14_FEATURE */
+
+	/* 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 >= 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 >= 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 */
+
+#if defined(WIFI_DIRECT_SUPPORT)
+	if (drv_mode_local & DRV_MODE_WIFIDIRECT) {
+		for (j = 0; j < max_wfd_bss; j++) {
+			if (i >= 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 && V14_FEATURE */
+
+#if defined(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 >= 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 = 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;
+}
+
+#ifdef CONFIG_OF
+/**
+ *  @brief This function read the initial parameter from device tress
+ *
+ *  @return         N/A
+ */
+static 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, "sd8xxx-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;
+			}
+		}
+#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);
+			}
+		}
+#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
+#if defined(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
+#if defined(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;
+			}
+		} else if (!strncmp(prop->name, "p2p_enh", strlen("p2p_enh"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "p2p_enh=0x%x\n", data);
+				p2p_enh = data;
+			}
+		} else if (!strncmp
+			   (prop->name, "cfg80211_drcs",
+			    strlen("cfg80211_drcs"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "cfg80211_drcs=0x%x\n", data);
+				cfg80211_drcs = 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, "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);
+			}
+		}
+#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, "drcs_chantime_mode",
+			  strlen("drcs_chantime_mode"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				drcs_chantime_mode = data;
+				PRINTM(MIOCTL, "drcs_chantime_mode=%d\n",
+				       drcs_chantime_mode);
+			}
+		} 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
+#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;
+			}
+		}
+#endif
+	}
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function initializes software
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_init_sw(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	unsigned int i;
+	mlan_device device;
+	t_void *pmlan;
+
+	ENTER();
+
+	/* Initialize moal_handle structure */
+	handle->hardware_status = HardwareStatusInitializing;
+	handle->main_state = MOAL_STATE_IDLE;
+
+#ifdef STA_SUPPORT
+	if ((drv_mode & DRV_MODE_STA)
+#ifdef STA_WEXT
+	    && !IS_STA_WEXT(cfg80211_wext)
+#endif
+#ifdef STA_CFG80211
+	    && !IS_STA_CFG80211(cfg80211_wext)
+#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
+
+	/* Update driver version */
+	if (handle->card_type == CARD_TYPE_SD8787)
+		memcpy(driver_version, CARD_SD8787, strlen(CARD_SD8787));
+	else if (handle->card_type == CARD_TYPE_SD8777)
+		memcpy(driver_version, CARD_SD8777, strlen(CARD_SD8777));
+	else if (handle->card_type == CARD_TYPE_SD8887)
+		memcpy(driver_version, CARD_SD8887, strlen(CARD_SD8887));
+	else if (handle->card_type == CARD_TYPE_SD8801)
+		memcpy(driver_version, CARD_SD8801, strlen(CARD_SD8801));
+	else if (handle->card_type == CARD_TYPE_SD8897)
+		memcpy(driver_version, CARD_SD8897, strlen(CARD_SD8897));
+	else if (handle->card_type == CARD_TYPE_SD8797)
+		memcpy(driver_version, CARD_SD8797, strlen(CARD_SD8797));
+	else if (handle->card_type == CARD_TYPE_SD8977)
+		memcpy(driver_version, CARD_SD8977, strlen(CARD_SD8977));
+	else if (handle->card_type == CARD_TYPE_SD8978)
+		memcpy(driver_version, CARD_SD8977, strlen(CARD_SD8978));
+	else if (handle->card_type == CARD_TYPE_SD8997)
+		memcpy(driver_version, CARD_SD8997, strlen(CARD_SD8997));
+	else if (handle->card_type == CARD_TYPE_SD8987)
+		memcpy(driver_version, CARD_SD8987, strlen(CARD_SD8987));
+	memcpy(handle->driver_version, driver_version, strlen(driver_version));
+
+	if (woal_update_drv_tbl(handle, 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);
+
+#if defined(SDIO_SUSPEND_RESUME)
+	handle->is_suspended = MFALSE;
+	handle->hs_activated = MFALSE;
+	handle->hs_auto_arp = MTRUE;
+	handle->suspend_fail = MFALSE;
+#ifdef SDIO_SUSPEND_RESUME
+	handle->suspend_notify_req = MFALSE;
+#endif
+	handle->hs_skip_count = 0;
+	handle->hs_force_count = 0;
+	handle->cmd52_func = 0;
+	handle->cmd52_reg = 0;
+	handle->cmd52_val = 0;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	handle->scan_chan_gap = DEF_SCAN_CHAN_GAP;
+#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
+	init_waitqueue_head(&handle->hs_activate_wait_q);
+#endif
+
+	/* 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
+
+#ifdef DFS_TESTING_SUPPORT
+	handle->cac_period_jiffies = 0;
+#endif
+#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 */
+
+#if defined(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.sdio_rx_aggr_enable = sdio_rx_aggr;
+
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode)
+		device.mfg_mode = (t_u32)MLAN_INIT_PARA_ENABLED;
+
+#endif
+	device.int_mode = (t_u32)intmode;
+	device.gpio_pin = (t_u32)gpiopin;
+#ifdef DEBUG_LEVEL1
+	device.drvdbg = drvdbg;
+#endif
+	device.fixed_beacon_buffer = (t_u32)fixed_beacon_buffer;
+	device.auto_ds = (t_u32)auto_ds;
+	device.ps_mode = (t_u32)ps_mode;
+	device.max_tx_buf = (t_u32)max_tx_buf;
+#if defined(STA_SUPPORT)
+	device.cfg_11d = (t_u32)cfg_11d;
+#endif
+	if (handle->card_type == CARD_TYPE_SD8787 ||
+	    handle->card_type == CARD_TYPE_SD8777)
+		device.fw_crc_check = (t_u32)fw_crc_check;
+	device.drcs_chantime_mode = (t_u32)drcs_chantime_mode;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+#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);
+#endif
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+#ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
+	device.mpa_tx_cfg = MLAN_INIT_PARA_ENABLED;
+#else
+	device.mpa_tx_cfg = MLAN_INIT_PARA_DISABLED;
+#endif
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+#ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
+	device.mpa_rx_cfg = MLAN_INIT_PARA_ENABLED;
+#else
+	device.mpa_rx_cfg = MLAN_INIT_PARA_DISABLED;
+#endif
+#endif
+	device.feature_control = FEATURE_CTRL_DEFAULT;
+	if (handle->card_type == CARD_TYPE_SD8777 ||
+	    handle->card_type == CARD_TYPE_SD8787 ||
+	    handle->card_type == CARD_TYPE_SD8801 ||
+	    handle->card_type == CARD_TYPE_SD8887 ||
+	    handle->card_type == CARD_TYPE_SD8977 ||
+	    handle->card_type == CARD_TYPE_SD8978 ||
+	    handle->card_type == CARD_TYPE_SD8987)
+		device.feature_control &= ~FEATURE_CTRL_STREAM_2X2;
+	handle->feature_control = device.feature_control;
+
+	if (rx_work == MLAN_INIT_PARA_ENABLED)
+		device.rx_work = MTRUE;
+	else if (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 (napi)
+		device.rx_work = MTRUE;
+
+	device.dev_cap_mask = dev_cap_mask;
+
+	device.multi_dtim = multi_dtim;
+
+	device.inact_tmo = inact_tmo;
+	device.hs_wake_interval = hs_wake_interval;
+	device.indication_gpio = indication_gpio;
+
+	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;
+	}
+	memcpy(&device.callbacks, &woal_callbacks, sizeof(mlan_callbacks));
+	if (fw_region)
+		device.fw_region = MTRUE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	if (MLAN_STATUS_SUCCESS == mlan_register(&device, &pmlan))
+		handle->pmlan_adapter = pmlan;
+	else
+		ret = MLAN_STATUS_FAILURE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees the structure of moal_handle
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         N/A
+ */
+static void
+woal_free_moal_handle(moal_handle *handle)
+{
+	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);
+		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);
+
+	/* 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));
+	}
+	/* Free allocated memory for fwdump filename */
+	kfree(handle->fwdump_fname);
+	if (fwdump_fname) {
+		kfree(fwdump_fname);
+		fwdump_fname = 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 >= 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 < 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;
+}
+
+/**
+ * @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;
+}
+
+#define SD8801_MAC_SLEW_RATE_REG	0x8000231C
+#define SD8801_MAC_SLEW_RATE_PAD_OFFSET		14
+#define SD8887_SD8897_SD8987_SD8997_MAC_SLEW_RATE_REG	0x80002328
+#define SD8887_SD8897_SD8987_SD8997_MAC_SLEW_RATE_PAD_OFFSET	12
+
+
+/**
+ *    @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;
+	t_u32 mac_reg = 0;
+	t_u8 bit_offset = 0;
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv)
+		return MLAN_STATUS_FAILURE;
+	if (slew_rate > 3 || slew_rate < 0)
+		return MLAN_STATUS_FAILURE;
+	if (handle->card_type == CARD_TYPE_SD8801) {
+		mac_reg = SD8801_MAC_SLEW_RATE_REG;
+		bit_offset = SD8801_MAC_SLEW_RATE_PAD_OFFSET;
+	} else if (handle->card_type == CARD_TYPE_SD8887 ||
+		   handle->card_type == CARD_TYPE_SD8897 ||
+		   handle->card_type == CARD_TYPE_SD8987 ||
+		   handle->card_type == CARD_TYPE_SD8997) {
+		mac_reg = SD8887_SD8897_SD8987_SD8997_MAC_SLEW_RATE_REG;
+		bit_offset = SD8887_SD8897_SD8987_SD8997_MAC_SLEW_RATE_PAD_OFFSET;
+	}
+
+	ret = woal_getset_regrdwr(priv, MLAN_ACT_GET, MLAN_REG_MAC, mac_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 << bit_offset);
+	new_value |= (t_u32)slew_rate << bit_offset;
+	/* Set 0x8000231C[15:14] = 0-3 */
+	if (value != new_value) {
+		PRINTM(MMSG, "Set REG 0x%8x: 0x%x slew_rate=%d\n",
+		       mac_reg, new_value, slew_rate);
+		ret = woal_getset_regrdwr(priv, MLAN_ACT_SET, MLAN_REG_MAC,
+					  mac_reg, &new_value);
+		if (ret < 0) {
+			PRINTM(MERROR,
+			       "woal_getset_regrdwr get REG_MAC failed\n");
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+done:
+	return ret;
+}
+
+#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;
+
+	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;
+	}
+
+	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 ((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);
+#if defined(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])) {
+							PRINTM(MERROR,
+							       "Set MAC address failed\n");
+							goto done;
+						}
+						memcpy(handle->priv[i]->netdev->
+						       dev_addr,
+						       handle->priv[i]->
+						       current_addr, 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 */
+			strncpy(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)));
+			memcpy(buf + strlen(CMD_STR), &cmd_len, sizeof(t_u32));
+
+			/* 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
+
+/**
+ * @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_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
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+woal_set_user_init_data(moal_handle *handle, int type, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 *cfg_data = NULL;
+	t_size len;
+
+	ENTER();
+
+	if (type == INIT_CFG_DATA) {
+		if (req_fw_nowait && !handle->fw_reload) {
+#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
+				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 (req_fw_nowait && !handle->fw_reload) {
+#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
+				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 {
+			int status =
+				request_firmware(&handle->user_data,
+						 country_txpwrlimit,
+						 handle->hotplug_device);
+			/* File does not exist, skip download */
+			if (status == -ENOENT) {
+				PRINTM(MIOCTL,
+				       "Country power table file does not exist\n");
+				LEAVE();
+				return MLAN_STATUS_SUCCESS;
+			} else if (status) {
+				PRINTM(MERROR,
+				       "country txpwrlimit config file request_firmware() failed\n");
+				goto done;
+			}
+		}
+	} else if (type == INIT_HOSTCMD_CFG_DATA) {
+		if (req_fw_nowait && !handle->fw_reload) {
+#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
+				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 (handle->user_data) {
+		cfg_data = (t_u8 *)(handle->user_data)->data;
+		len = (handle->user_data)->size;
+		if (type == INIT_HOSTCMD_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);
+
+/**
+ * @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();
+
+#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 (mfg_mode == MLAN_INIT_PARA_ENABLED)
+		goto done;
+#endif
+
+	if (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;
+		}
+	}
+
+	/* Add low power mode check */
+	if ((handle->card_type == CARD_TYPE_SD8801 ||
+	     handle->card_type == CARD_TYPE_SD8887) && low_power_mode_enable &&
+	    woal_set_low_pwr_mode(handle, MOAL_IOCTL_WAIT)) {
+		/* Proceed with Warning */
+		PRINTM(MERROR, "Unable to set Low Power Mode\n");
+	}
+
+	if (handle->card_type == CARD_TYPE_SD8801 ||
+	    handle->card_type == CARD_TYPE_SD8887 ||
+	    handle->card_type == CARD_TYPE_SD8897 ||
+	    handle->card_type == CARD_TYPE_SD8987 ||
+	    handle->card_type == CARD_TYPE_SD8997)
+		woal_set_sdio_slew_rate(handle);
+
+	if (pmic
+	    && ((handle->card_type == CARD_TYPE_SD8997) ||
+		(handle->card_type == CARD_TYPE_SD8987) ||
+		(handle->card_type == CARD_TYPE_SD8978) ||
+		(handle->card_type == CARD_TYPE_SD8977))
+		) {
+		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 (antcfg
+	    && ((handle->card_type == CARD_TYPE_SD8887) ||
+		(handle->card_type == CARD_TYPE_SD8897) ||
+		(handle->card_type == CARD_TYPE_SD8987) ||
+		(handle->card_type == CARD_TYPE_SD8997))
+		) {
+		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 (uap_oper_ctrl)
+		woal_set_uap_operation_ctrl(handle);
+#endif
+
+#ifdef MFG_CMD_SUPPORT
+done:
+#endif
+err:
+	if (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);
+
+		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 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;
+	int status;
+
+	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 (fw_reload == FW_RELOAD_SDIO_INBAND_RESET)
+			fw.fw_reload = fw_reload;
+		else {
+			if (handle->fw_reload == FW_RELOAD_NO_EMULATION)
+				fw.fw_reload = FW_RELOAD_NO_EMULATION;
+			else
+				fw.fw_reload = 0;
+		}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+		ret = mlan_dnld_fw(handle->pmlan_adapter, &fw);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+		if (ret == MLAN_STATUS_FAILURE) {
+			PRINTM(MERROR,
+			       "WLAN: Fail download FW with nowwait: %d\n",
+			       req_fw_nowait);
+			woal_sdio_reg_dbg(handle);
+			goto done;
+		}
+		PRINTM(MMSG, "WLAN FW is active\n");
+	}
+
+    /** data request */
+	memset(&param, 0, sizeof(mlan_init_param));
+
+	if (dpd_data_cfg && strncmp(dpd_data_cfg, "none", strlen("none"))) {
+		if (req_fw_nowait && !handle->fw_reload) {
+#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
+				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;
+		}
+	}
+	if (txpwrlimit_cfg && strncmp(txpwrlimit_cfg, "none", strlen("none"))) {
+		if (req_fw_nowait && !handle->fw_reload) {
+#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
+				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;
+		}
+	}
+
+	if (cal_data_cfg && strncmp(cal_data_cfg, "none", strlen("none"))) {
+		if (req_fw_nowait && !handle->fw_reload) {
+#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
+				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) {
+		if (handle->card_type == CARD_TYPE_SD8887 ||
+		    handle->card_type == CARD_TYPE_SD8977 ||
+		    handle->card_type == CARD_TYPE_SD8997 ||
+		    handle->card_type == CARD_TYPE_SD8987 ||
+		    handle->card_type == CARD_TYPE_SD8978) {
+			PRINTM(MERROR,
+			       "Please add cal_data_cfg for 8887/8977/8997/8987/9098/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;
+	}
+
+	handle->hardware_status = HardwareStatusFwReady;
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (handle->fw_reload)
+		goto done;
+	handle->init_wait_q_woken = MFALSE;
+
+	ret = mlan_set_init_param(handle->pmlan_adapter, &param);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	ret = mlan_init_fw(handle->pmlan_adapter);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	if (ret == MLAN_STATUS_FAILURE)
+		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,
+			   5 * HZ);
+
+	if (handle->hardware_status != HardwareStatusReady) {
+		woal_moal_debug_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
+				     handle, MTRUE);
+#if defined(DEBUG_LEVEL1)
+		if (drvdbg & MFW_D) {
+			drvdbg &= ~MFW_D;
+			woal_dump_firmware_info(handle);
+		}
+#endif
+		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;
+	struct timeval tstamp;
+
+	ENTER();
+
+	if (!firmware) {
+		do_gettimeofday(&tstamp);
+		if (tstamp.tv_sec >
+		    (handle->req_fw_time.tv_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)
+{
+	ENTER();
+	woal_request_fw_dpc((moal_handle *)context, firmware);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+	if (firmware)
+		release_firmware(firmware);
+#endif
+	LEAVE();
+	return;
+}
+
+#define SD8887_REV_REG  0xc8
+#define SD8887_A0       0x0
+#define SD8887_A2       0x2
+#define SD8977_V0       0x0
+#define SD8977_V1       0x8
+#define SD8977_V2       0x9
+#define SD8978_V0       0x0
+#define SD8997_Z       0x02
+#define SD8997_V2       0x10
+#define MAGIC_REG		0xf0
+#define MAGIC_VAL		0x24
+/**
+ * @brief   Get FW name for differnt chip revision
+ *
+ * @param handle  A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+void
+woal_check_fw_name(moal_handle *handle)
+{
+	t_u32 rev_id_reg = 0;
+	t_u32 revision_id = 0;
+	t_u32 magic_val = 0;
+
+	if (handle->card_type == CARD_TYPE_SD8887 ||
+	    handle->card_type == CARD_TYPE_SD8977 ||
+	    handle->card_type == CARD_TYPE_SD8987 ||
+	    handle->card_type == CARD_TYPE_SD8997 ||
+	    handle->card_type == CARD_TYPE_SD8978)
+		rev_id_reg = SD8887_REV_REG;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	woal_read_reg(handle, rev_id_reg, &revision_id);
+	woal_read_reg(handle, MAGIC_REG, &magic_val);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	/* Check revision ID */
+	if (handle->card_type == CARD_TYPE_SD8887) {
+		switch (revision_id) {
+		case SD8887_A0:
+			if (fw_serial)
+				handle->drv_mode.fw_name = SD8887_A0_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8887_WLAN_A0_FW_NAME;
+			break;
+		case SD8887_A2:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8887_A2_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8887_WLAN_A2_FW_NAME;
+			break;
+		default:
+			break;
+		}
+	} else if (handle->card_type == CARD_TYPE_SD8977) {
+		switch (revision_id) {
+		case SD8977_V0:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8977_V0_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8977_WLAN_V0_FW_NAME;
+			break;
+		case SD8977_V1:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8977_V1_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8977_WLAN_V1_FW_NAME;
+			break;
+		case SD8977_V2:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8977_V2_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8977_WLAN_V2_FW_NAME;
+			break;
+		default:
+			break;
+		}
+	} else if (handle->card_type == CARD_TYPE_SD8978) {
+		switch (revision_id) {
+		case SD8978_V0:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8978_V0_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8978_WLAN_V0_FW_NAME;
+			break;
+		default:
+			break;
+		}
+	}
+
+	else if (handle->card_type == CARD_TYPE_SD8997) {
+		switch (revision_id) {
+		case SD8997_Z:
+			if (fw_serial && !handle->fw_reload && !fw_reload)
+				handle->drv_mode.fw_name = SD8997_Z_FW_NAME;
+			else
+				handle->drv_mode.fw_name =
+					SD8997_WLAN_Z_FW_NAME;
+			break;
+		case SD8997_V2:
+			if (fw_serial && !handle->fw_reload && !fw_reload) {
+				if ((magic_val & 0xff) == MAGIC_VAL)
+					handle->drv_mode.fw_name =
+						SD8997_V3_FW_NAME;
+				else
+					handle->drv_mode.fw_name =
+						SD8997_V2_FW_NAME;
+			} else {
+				if ((magic_val & 0xff) == MAGIC_VAL)
+					handle->drv_mode.fw_name =
+						SD8997_WLAN_V3_FW_NAME;
+				else
+					handle->drv_mode.fw_name =
+						SD8997_WLAN_V2_FW_NAME;
+			}
+			break;
+		default:
+			break;
+		}
+	} else if (handle->card_type == CARD_TYPE_SD8987) {
+		if (fw_serial && !handle->fw_reload && !fw_reload)
+			handle->drv_mode.fw_name = SD8987_FW_NAME;
+		else
+			handle->drv_mode.fw_name = SD8987_WLAN_FW_NAME;
+	}
+	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)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err;
+
+	ENTER();
+
+	if (!fw_name &&
+	    (handle->card_type == CARD_TYPE_SD8887 ||
+	     handle->card_type == CARD_TYPE_SD8977 ||
+	     handle->card_type == CARD_TYPE_SD8987 ||
+	     handle->card_type == CARD_TYPE_SD8997 ||
+	     handle->card_type == CARD_TYPE_SD8978))
+		woal_check_fw_name(handle);
+	PRINTM(MMSG, "Request firmware: %s\n", handle->drv_mode.fw_name);
+	if (req_fw_nowait && !handle->fw_reload) {
+#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
+		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);
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes firmware
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_init_fw(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	do_gettimeofday(&handle->req_fw_time);
+
+	ret = woal_request_fw(handle);
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MFATAL, "woal_request_fw failed\n");
+		goto done;
+	}
+
+done:
+	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
+ */
+static void
+woal_fill_mlan_buffer(moal_private *priv,
+		      mlan_buffer *pmbuf, struct sk_buff *skb)
+{
+	struct timeval tstamp;
+	struct ethhdr *eth;
+	t_u8 tid;
+	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;
+			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.
+	 */
+	do_gettimeofday(&tstamp);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+	skb->tstamp = timeval_to_ktime(tstamp);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+	skb_set_timestamp(skb, &tstamp);
+#else
+	memcpy(&skb->stamp, &tstamp, sizeof(skb->stamp));
+#endif
+
+	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 = 0;
+	pmbuf->in_ts_sec = (t_u32)tstamp.tv_sec;
+	pmbuf->in_ts_usec = (t_u32)tstamp.tv_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,
+	.ndo_do_ioctl = woal_do_ioctl,
+	.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(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(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,
+	.ndo_do_ioctl = woal_uap_do_ioctl,
+	.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(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 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 (sta_name)
+		snprintf(name, sizeof(name), "%s%%d", sta_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 (uap_name)
+		snprintf(name, sizeof(name), "%s%%d", 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
+#if defined(WIFI_DIRECT_SUPPORT)
+	memset(name, 0, sizeof(name));
+	if (wfd_name)
+		snprintf(name, sizeof(name), "%s%%d", 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;
+#if defined(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 LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	SET_MODULE_OWNER(dev);
+#endif
+#ifdef STA_SUPPORT
+	if (bss_type == MLAN_BSS_TYPE_STA
+#if defined(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
+	    && (mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		) {
+		if (init_cfg) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_user_init_data(handle, INIT_CFG_DATA,
+						    MOAL_IOCTL_WAIT)) {
+				PRINTM(MFATAL,
+				       "Set user init data and param failed\n");
+				goto error;
+			}
+		}
+		if (init_hostcmd_cfg) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_user_init_data(handle,
+						    INIT_HOSTCMD_CFG_DATA,
+						    MOAL_IOCTL_WAIT)) {
+				PRINTM(MFATAL,
+				       "Set user init hostcmd data and param failed\n");
+				goto error;
+			}
+		}
+	}
+
+	handle->priv_num++;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	if (!priv->phandle->wiphy && IS_STA_OR_UAP_CFG80211(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(cfg80211_wext)) {
+		if (bss_type == MLAN_BSS_TYPE_STA
+#if defined(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;
+			}
+	}
+#endif /* STA_SUPPORT */
+#endif /* STA_CFG80211 */
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+	if ((priv->bss_role == MLAN_BSS_ROLE_UAP) &&
+	    IS_UAP_CFG80211(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 */
+
+	/* 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: Marvell 802.11 Adapter\n", dev->name);
+
+	if (bss_type == MLAN_BSS_TYPE_STA ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		mlan_fw_info fw_info;
+		woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+		if (handle->card_type == CARD_TYPE_SD8887 ||
+		    handle->card_type == CARD_TYPE_SD8987) {
+
+			if ((fw_info.antinfo & ANT_DIVERSITY_2G)&&(fw_info.
+								   antinfo &
+								   ANT_DIVERSITY_5G))
+				handle->histogram_table_num = 4;
+		}
+
+		for (i = 0; i < handle->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;
+			}
+		}
+		if (priv->hist_data)
+			woal_hist_data_reset(priv);
+	}
+#ifdef CONFIG_PROC_FS
+	woal_create_proc_entry(priv);
+#ifdef PROC_DEBUG
+	woal_debug_entry(priv);
+#endif /* PROC_DEBUG */
+#endif /* CONFIG_PROC_FS */
+
+	LEAVE();
+	return priv;
+error:
+	handle->priv_num = bss_index;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	/* Unregister wiphy device and free */
+	if (priv) {
+		if (priv->wdev && IS_STA_OR_UAP_CFG80211(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(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);
+
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_flush_tdls_list(priv);
+#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 ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		for (i = 0; i < handle->histogram_table_num; i++) {
+			kfree(priv->hist_data[i]);
+			priv->hist_data[i] = NULL;
+		}
+	}
+#ifdef CONFIG_PROC_FS
+#ifdef PROC_DEBUG
+	/* Remove proc debug */
+	woal_debug_remove(priv);
+#endif /* PROC_DEBUG */
+	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 defined(STA_CFG80211) || defined(UAP_CFG80211)
+	/* Unregister wiphy device and free */
+	if (priv->wdev && IS_STA_OR_UAP_CFG80211(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
+
+	/* Clear the priv in handle */
+	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;
+
+	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_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) {
+		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 = low_power_mode_enable;
+	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
+ */
+static 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
+ */
+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 cancel all works in the queue
+ *  and destroy the main workqueue.
+ *
+ *  @param handle    A pointer to moal_handle
+ *
+ *  @return        N/A
+ */
+static 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;
+	}
+
+	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);
+	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(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. */
+	{
+		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 defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (!p2p_enh) {
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+		    IS_STA_CFG80211(cfg80211_wext)) {
+			priv->phandle->wiphy->interface_modes |=
+				MBIT(NL80211_IFTYPE_P2P_GO) |
+				MBIT(NL80211_IFTYPE_P2P_CLIENT);
+		}
+	}
+#endif
+#endif
+#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);
+
+	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;
+		rcu_read_lock();
+		cfg80211_sched_scan_stopped(priv->wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+					    , priv->bg_scan_reqid
+#endif
+			);
+		rcu_read_unlock();
+		priv->sched_scanning = MFALSE;
+	}
+#endif
+#endif
+#endif
+	if (!priv->bss_virtual)
+		woal_stop_queue(priv->netdev);
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (!p2p_enh) {
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+		    !priv->bss_virtual &&
+		    IS_STA_CFG80211(cfg80211_wext) &&
+		    IS_UAP_CFG80211(cfg80211_wext)) {
+			priv->phandle->wiphy->interface_modes &=
+				~(MBIT(NL80211_IFTYPE_P2P_GO) |
+				  MBIT(NL80211_IFTYPE_P2P_CLIENT));
+		}
+	}
+#endif
+#endif
+#endif
+	MODULE_PUT;
+
+	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;
+	}
+
+	memcpy(prev_addr, priv->current_addr, 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);
+	memcpy(priv->current_addr, phw_addr->sa_data, ETH_ALEN);
+#if defined(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)) {
+		PRINTM(MERROR, "Set MAC address failed\n");
+		/* For failure restore the MAC address */
+		memcpy(priv->current_addr, prev_addr, ETH_ALEN);
+		ret = -EFAULT;
+		goto done;
+	}
+	HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
+	memcpy(dev->dev_addr, priv->current_addr, 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;
+	struct timeval t;
+	int i = 0;
+	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
+	do_gettimeofday(&t);
+	if (info.pending_cmd &&
+	    (t.tv_sec > (info.dnld_cmd_in_secs + MOAL_CMD_TIMEOUT_MAX))) {
+		if (t.tv_sec > (info.dnld_cmd_in_secs + MOAL_CMD_TIMEOUT) &&
+		    !info.num_cmd_timeout) {
+			PRINTM(MERROR, "Ignore invalid time, wait=%d\n",
+			       (int)(t.tv_sec - info.dnld_cmd_in_secs));
+		} else {
+			PRINTM(MERROR, "Timeout cmd id = 0x%x wait=%d\n",
+			       info.pending_cmd,
+			       (int)(t.tv_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.tv_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.tv_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->phandle->driver_state) {
+		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_MULTI_PORT_TX_AGGR
+	int j;
+	t_u8 mp_aggr_pkt_limit = 0;
+#endif
+	char str[512] = { 0 };
+	char *s;
+
+	ENTER();
+
+	if (!priv || 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, "num_cmd_timeout = %d\n", info.num_cmd_timeout);
+	PRINTM(MERROR, "dbg.num_cmd_timeout = %d\n", info.dbg_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);
+
+	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, "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_cmd_assoc_failure = %d\n",
+	       info.num_cons_cmd_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, "data_sent=%d cmd_sent=%d\n", info.data_sent,
+	       info.cmd_sent);
+
+	PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", info.ps_mode, info.ps_state);
+	PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d\n",
+	       info.pm_wakeup_card_req, info.pm_wakeup_fw_try);
+	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);
+
+	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_invalid_update=%d\n", info.mp_invalid_update);
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	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
+	for (i = 0; i < 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);
+	}
+
+	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
+ */
+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)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+
+	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) {
+		woal_mlan_debug_info(priv);
+		woal_moal_debug_info(priv, NULL, MFALSE);
+		woal_broadcast_event(priv, CUS_EVT_DRIVER_HANG,
+				     strlen(CUS_EVT_DRIVER_HANG));
+#if defined(STA_CFG80211) || defined(UAP_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
+		priv->phandle->driver_state = MTRUE;
+		woal_process_hang(priv->phandle);
+	}
+
+	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)
+		  , 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();
+
+	/*
+	 * 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);
+}
+
+/**
+ *  @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();
+}
+
+/**
+ *  @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
+ */
+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();
+	memcpy(ra, skb->data, MLAN_MAC_ADDR_LENGTH);
+	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
+
+/**
+ *  @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
+ */
+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);
+				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
+ */
+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);
+			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
+ */
+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) {
+			/* 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, iph->saddr,
+						tcph->source, iph->daddr,
+						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 = iph->saddr;
+			tcp_session->dst_ip_addr = iph->daddr;
+			tcp_session->src_tcp_port = tcph->source;
+			tcp_session->dst_tcp_port = 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)) {
+			memcpy(skb->data, pmbuf->pbuf + pmbuf->data_offset,
+			       pmbuf->data_len);
+			tcp_session->ack_seq = ack_seq;
+			ret = DROP_TCP_ACK;
+			skb->cb[0]++;
+//We will drop 90% tcp ack
+#define TCP_ACK_MAX_HOLD    9
+			if (skb->cb[0] >= 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
+ */
+int
+woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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();
+	PRINTM(MDATA, "%lu : %s (bss=%d): Data <= kernel\n",
+	       jiffies, dev->name, priv->bss_index);
+
+	if (priv->phandle->surprise_removed == MTRUE) {
+		dev_kfree_skb_any(skb);
+		priv->stats.tx_dropped++;
+		goto done;
+	}
+	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;
+	}
+	if (skb->cloned || (skb_headroom(skb) < (MLAN_MIN_DATA_HEADER_LEN +
+						 sizeof(mlan_buffer) +
+						 priv->extra_tx_head_len))) {
+		PRINTM(MWARN,
+		       "Tx: skb cloned %d or Insufficient skb headroom %d\n",
+		       skb->cloned, skb_headroom(skb));
+		/* 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);
+		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;
+	}
+#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
+
+#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:
+		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);
+			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 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;
+	}
+	memcpy(mac_buff, buf, strlen(buf));
+
+	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();
+	woal_request_set_multicast_list(priv, dev);
+	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;
+		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
+	}
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		priv->bss_started = 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
+#endif
+	}
+#endif
+
+	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;
+#endif
+
+	priv->enable_tcp_ack_enh = MTRUE;
+
+	priv->enable_auto_tdls = MFALSE;
+	priv->tdls_check_tx = MFALSE;
+
+	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);
+		memcpy(priv->current_addr, priv->phandle->mac_addr, ETH_ALEN);
+	}
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+			if (priv->bss_virtual) {
+				if (priv->pa_netdev) {
+					memcpy(priv->current_addr,
+					       priv->pa_netdev->dev_addr,
+					       ETH_ALEN);
+					priv->current_addr[4] ^= 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 and let them different with each other */
+	if (priv->bss_index > 0
+#ifdef WIFI_DIRECT_SUPPORT
+	    && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+		) {
+		priv->current_addr[4] += priv->bss_index;
+		PRINTM(MCMND, "Set %s device addr: " MACSTR "\n",
+		       priv->netdev->name, MAC2STR(priv->current_addr));
+	}
+
+	/* Set MAC address to fw */
+	woal_request_set_mac_address(priv);
+	memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
+
+#ifdef UAP_SUPPORT
+#if defined(DFS_TESTING_SUPPORT)
+	priv->user_cac_period_msec = 0;
+#endif
+#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;
+
+	/* 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);
+
+#ifdef STA_SUPPORT
+	woal_cancel_scan(priv, wait_option);
+#endif
+
+	/* 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 defined(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;
+}
+
+#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);
+		memcpy(NLMSG_DATA(nlh), netdev->name, IFNAMSIZ);
+		memcpy(((t_u8 *)(NLMSG_DATA(nlh))) + IFNAMSIZ, payload, len);
+
+		/* 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);
+
+		/* 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));
+			memcpy(&req_ssid,
+			       &priv->prev_ssid_bssid.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");
+					memcpy(&ssid_bssid.bssid,
+					       &priv->prev_ssid_bssid.bssid,
+					       MLAN_MAC_ADDR_LENGTH);
+				} else {
+					/* Search AP by ESSID for asynced essid setting */
+					PRINTM(MINFO,
+					       "Set asynced essid: Search AP by ESSID\n");
+				}
+
+				memcpy(&ssid_bssid.ssid,
+				       &priv->prev_ssid_bssid.ssid,
+				       sizeof(mlan_802_11_ssid));
+			} else {
+				/* Search AP by BSSID first */
+				PRINTM(MINFO,
+				       "Reassoc: Search AP by BSSID first\n");
+				memcpy(&ssid_bssid.bssid,
+				       &priv->prev_ssid_bssid.bssid,
+				       MLAN_MAC_ADDR_LENGTH);
+			}
+
+			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));
+				memcpy(&ssid_bssid.ssid,
+				       &priv->prev_ssid_bssid.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 {
+						memcpy(&priv->prev_ssid_bssid.
+						       ssid, &bss_info.ssid,
+						       sizeof
+						       (mlan_802_11_ssid));
+						memcpy(&priv->prev_ssid_bssid.
+						       bssid, &bss_info.bssid,
+						       MLAN_MAC_ADDR_LENGTH);
+					}
+					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 */
+
+#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;
+		}
+		memcpy(dscp_except,
+		       (t_u8 *)qos_mapping_ie + sizeof(IEEEtypes_Header_t),
+		       dscp_except_num * sizeof(DSCP_Exception_t));
+		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
+	t_u16 reason_code = 0;
+
+	ENTER();
+	priv->media_connected = MFALSE;
+	if (!disconnect_reason)
+		reason_code = MLAN_REASON_DEAUTH_LEAVING;
+	else
+		reason_code = disconnect_reason;
+	woal_stop_queue(priv->netdev);
+	if (netif_carrier_ok(priv->netdev))
+		netif_carrier_off(priv->netdev);
+	woal_flush_tcp_sess_queue(priv);
+
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_flush_tdls_list(priv);
+#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 && priv->hist_data)
+		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->iftype != NL80211_IFTYPE_ADHOC &&
+		    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);
+			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;
+		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);
+	strncpy(event_buf, CUS_EVT_AP_CONNECTED,
+		MIN((sizeof(event_buf) - 1), custom_len));
+	woal_broadcast_event(priv, event_buf, custom_len + ETH_ALEN);
+	LEAVE();
+}
+#endif /* STA_SUPPORT */
+
+#define OFFSET_SEQNUM 4
+/**
+ *  @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)
+{
+	struct file *pfile_fwdump = NULL;
+	loff_t pos = 0;
+	t_u16 seqnum;
+	t_u8 path_name[64];
+
+	ENTER();
+	if (phandle->fwdump_fname)
+		pfile_fwdump =
+			filp_open(phandle->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+	else {
+		seqnum = woal_le16_to_cpu(*(t_u16 *)
+					  (pmevent->event_buf + OFFSET_SEQNUM));
+		if (seqnum == 1) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	    /** Create dump directort*/
+			woal_create_dump_dir(phandle, path_name,
+					     sizeof(path_name));
+#else
+			memset(path_name, 0, sizeof(path_name));
+			strcpy(path_name, "/data");
+#endif
+			PRINTM(MMSG, "Firmware Dump directory name is %s\n",
+			       path_name);
+			woal_dump_drv_info(phandle, path_name);
+			if (fwdump_fname) {
+				memset(fwdump_fname, 0, 64);
+			} else {
+				gfp_t flag;
+				flag = (in_atomic() ||
+					irqs_disabled())? GFP_ATOMIC :
+					GFP_KERNEL;
+				fwdump_fname = kzalloc(64, flag);
+			}
+			sprintf(fwdump_fname, "%s/file_fwdump", path_name);
+			pfile_fwdump =
+				filp_open(fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+			if (IS_ERR(pfile_fwdump)) {
+				memset(fwdump_fname, 0, 64);
+				sprintf(fwdump_fname, "%s/%s", "/var",
+					"file_fwdump");
+				pfile_fwdump =
+					filp_open(fwdump_fname,
+						  O_CREAT | O_WRONLY | O_APPEND,
+						  0644);
+			}
+		} else
+			pfile_fwdump =
+				filp_open(fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+	}
+	if (IS_ERR(pfile_fwdump)) {
+		PRINTM(MERROR, "Cannot create firmware dump file\n");
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile_fwdump, pmevent->event_buf, pmevent->event_len, &pos);
+#else
+	kernel_write(pfile_fwdump, pmevent->event_buf, pmevent->event_len,
+		     &pos);
+#endif
+	filp_close(pfile_fwdump, NULL);
+	LEAVE();
+	return;
+}
+
+#define DRV_INFO_SIZE 0x60000
+#define ROW_SIZE_16      16
+#define ROW_SIZE_32      32
+/**
+ *  @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 < (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;
+}
+
+#define SDIO_SCRATCH_REG 0x60
+/**
+ *  @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_dump_sdio_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 = SDIO_SCRATCH_REG;
+	unsigned int reg_table_8887_8977_8978_8997[] =
+		{ 0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62,
+		0x64, 0x65, 0x66, 0x68, 0x69, 0x6a
+	};
+	unsigned int reg_table_8897[] =
+		{ 0x4C, 0x50, 0x54, 0x55, 0x58, 0x59, 0x5c,
+		0x5d
+	};
+    /** for sd8787/sd8777 */
+	unsigned int reg_table_other[] = { 0x28, 0x30, 0x34, 0x38, 0x3c };
+	unsigned int *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;
+	}
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+#define SDIO_SCRATCH_REG_8887 0x90
+#define SDIO_SCRATCH_REG_8897 0xC0
+#define SDIO_SCRATCH_REG_8977_8978_8997 0xE8
+#define SDIO_SCRATCH_REG_OTHER 0x60
+	if (phandle->card_type == CARD_TYPE_SD8887) {
+		reg_table = reg_table_8887_8977_8978_8997;
+		reg_table_size =
+			sizeof(reg_table_8887_8977_8978_8997) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8887;
+	} else if (phandle->card_type == CARD_TYPE_SD8897) {
+		reg_table = reg_table_8897;
+		reg_table_size = sizeof(reg_table_8897) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8897;
+	} else if ((phandle->card_type == CARD_TYPE_SD8977) ||
+		   (phandle->card_type == CARD_TYPE_SD8997) ||
+		   (phandle->card_type == CARD_TYPE_SD8987) ||
+		   (phandle->card_type == CARD_TYPE_SD8978)) {
+		reg_table = reg_table_8887_8977_8978_8997;
+		reg_table_size =
+			sizeof(reg_table_8887_8977_8978_8997) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8977_8978_8997;
+	} else {
+		reg_table = reg_table_other;
+		reg_table_size = sizeof(reg_table_other) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_OTHER;
+	}
+
+	drv_ptr += sprintf(drv_ptr, "--------sdio_reg_debug_info---------\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+#endif
+
+	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;
+			if (phandle->card_type == CARD_TYPE_SD8897) {
+				reg_start = 4;
+				reg_end = 0xB;
+			} else if ((phandle->card_type == CARD_TYPE_SD8887) ||
+				   (phandle->card_type == CARD_TYPE_SD8977) ||
+				   (phandle->card_type == CARD_TYPE_SD8978) ||
+				   (phandle->card_type == CARD_TYPE_SD8997) ||
+				   (phandle->card_type == CARD_TYPE_SD8987)) {
+				reg_start = 0x10;
+				reg_end = 0x17;
+			} else {
+				reg_start = 4;
+				reg_end = 9;
+			}
+		} 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);
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+#endif
+	drv_ptr +=
+		sprintf(drv_ptr, "--------sdio_reg_debug_info End---------\n");
+
+	LEAVE();
+	return drv_ptr - (char *)drv_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;
+	char str_buf[MLAN_MAX_VER_STR_LEN];
+
+	ENTER();
+	if (!phandle || !buf) {
+		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
+		LEAVE();
+		return 0;
+	}
+	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);
+	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));
+#if defined(SDIO_SUSPEND_RESUME)
+	ptr += sprintf(ptr, "hs_skip_count = %u\n", phandle->hs_skip_count);
+	ptr += sprintf(ptr, "hs_force_count = %u\n", phandle->hs_force_count);
+#endif
+
+	ptr += woal_dump_priv_drv_info(phandle, ptr);
+	ptr += sprintf(ptr, "------------moal_debug_info End-------------\n");
+
+	ptr += woal_dump_sdio_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_MULTI_PORT_TX_AGGR
+	int j;
+	t_u8 mp_aggr_pkt_limit = 0;
+#endif
+	char str[11 * DBG_CMD_NUM + 1] = { 0 };
+	char *s;
+
+	ENTER();
+	if (!priv || 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, "num_cmd_timeout = %d\n", info.num_cmd_timeout);
+	ptr += sprintf(ptr, "dbg.num_cmd_timeout = %d\n",
+		       info.dbg_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);
+	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, "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_cmd_assoc_failure = %d\n",
+		       info.num_cons_cmd_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, "data_sent=%d cmd_sent=%d\n", info.data_sent,
+		       info.cmd_sent);
+	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\n",
+		       info.pm_wakeup_card_req, info.pm_wakeup_fw_try);
+	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);
+
+	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_invalid_update=%d\n", info.mp_invalid_update);
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	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
+	ptr += sprintf(ptr, "------------mlan_debug_info End-------------\n");
+
+	LEAVE();
+	return ptr - (char *)buf;
+}
+
+/**
+ *  @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 < len; i += rowsize) {
+		linelen = min(remaining, rowsize);
+		remaining -= rowsize;
+
+		hex_dump_to_buffer(ptr + i, linelen, rowsize, 1, linebuf,
+				   sizeof(linebuf), ascii);
+
+		pos += sprintf(pos, "%s\n", linebuf);
+	}
+
+	return pos - (char *)save_buf;
+}
+
+#define HostCmd_CMD_CFG_DATA                  0x008f
+#define DEF_FW_PATH  "/lib/firmware/"
+#define DEF_HOSTCMD_PATH "/lib/firmware/mrvl/hostcmd.conf"
+/**
+ *  @brief This function save the hostcmd response to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param pevent    A pointer to mlan_cmdresp_event
+ *
+ *  @return          N/A
+ */
+t_void
+woal_save_host_cmdresp(moal_handle *phandle, mlan_cmdresp_event * pevent)
+{
+	HostCmd_DS_GEN *resp;
+	char file_path[256];
+	struct file *pfile = NULL;
+	int ret;
+	t_u8 *buf;
+	t_u16 command;
+	int len = 0;
+	char *ptr;
+	loff_t pos = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	resp = (HostCmd_DS_GEN *)pevent->resp;
+	command = woal_le16_to_cpu(resp->command);
+	memset(file_path, 0, sizeof(file_path));
+	ret = moal_vmalloc(phandle, pevent->event_len * 5, &buf);
+	if (ret != MLAN_STATUS_SUCCESS || !buf) {
+		PRINTM(MERROR, "Fail to allocate memory to save hostcmd\n");
+		return;
+	}
+	memset(buf, 0, pevent->event_len * 5);
+	ptr = (char *)buf;
+	switch (command) {
+	case HostCmd_CMD_CFG_DATA:
+		if (dpd_data_cfg)
+			sprintf(file_path, "%s%s", DEF_FW_PATH, dpd_data_cfg);
+		else
+			sprintf(file_path, "%s", DEF_HOSTCMD_PATH);
+		break;
+	default:
+		sprintf(file_path, "%s", DEF_HOSTCMD_PATH);
+		break;
+	}
+	pfile = filp_open(file_path, O_CREAT | O_WRONLY | O_APPEND, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR, "Cannot create file %s\n", file_path);
+		moal_vfree(phandle, buf);
+		return;
+	}
+	ptr += sprintf(ptr, "hostcmd_%02x=={\n", command);
+	ptr += woal_save_hex_dump(ROW_SIZE_16, resp, pevent->event_len, MFALSE,
+				  ptr);
+	ptr += sprintf(ptr, "}\n");
+	len = ptr - (char *)buf;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	vfs_write(pfile, buf, len, &pos);
+	set_fs(fs);
+#else
+	kernel_write(pfile, buf, len, &pos);
+#endif
+	PRINTM(MMSG, "Save hostcmd 0x%02x, cmd len=%d file len=%d to file %s\n",
+	       command, pevent->event_len, len, file_path);
+	if (buf)
+		moal_vfree(phandle, buf);
+	filp_close(pfile, NULL);
+	return;
+}
+
+/**
+ *  @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++) {
+		ptr += sprintf(ptr, "<--moal_private(%d)-->\n", i);
+		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;
+	ENTER();
+
+	if (!buf || !priv || 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_MULTI_PORT_TX_AGGR
+	if (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;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+/**
+ *  @brief This function create dump directory
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param dir_buf   A pointer to dir_buf buffer
+ *  @param buf_size  Size of dir_buf buffer
+ *
+ *  @return         N/A
+ */
+void
+woal_create_dump_dir(moal_handle *phandle, char *dir_buf, int buf_size)
+{
+	struct dentry *dentry;
+	struct path path;
+	t_u32 sec, usec;
+	int ret;
+
+	ENTER();
+
+	if (!phandle || !dir_buf) {
+		PRINTM(MERROR, "Can't create directory\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	moal_get_system_time(phandle, &sec, &usec);
+	memset(dir_buf, 0, buf_size);
+	sprintf(dir_buf, "%s%u", "/data/dump_", sec);
+
+	dentry = kern_path_create(AT_FDCWD, dir_buf, &path, 1);
+	if (IS_ERR(dentry)) {
+		PRINTM(MERROR,
+		       "Create directory %s error, try create dir in /var",
+		       dir_buf);
+		memset(dir_buf, 0, buf_size);
+		sprintf(dir_buf, "%s%u", "/var/dump_", sec);
+		dentry = kern_path_create(AT_FDCWD, dir_buf, &path, 1);
+	}
+	if (IS_ERR(dentry)) {
+		PRINTM(MERROR, "Create directory %s error, use default folder",
+		       dir_buf);
+		goto default_dir;
+	}
+	ret = vfs_mkdir(path.dentry->d_inode, dentry, 0777);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&path.dentry->d_inode->i_mutex);
+#else
+	inode_unlock(path.dentry->d_inode);
+#endif
+
+	if (ret < 0) {
+		PRINTM(MERROR,
+		       "Create directory failure, use default folder\n");
+		PRINTM(MERROR, "Create directory failure, ret = %d\n", ret);
+		goto default_dir;
+	} else {
+		PRINTM(MERROR, "Create directory %s successfully\n", dir_buf);
+		goto done;
+	}
+
+default_dir:
+	memset(dir_buf, 0, buf_size);
+	sprintf(dir_buf, "%s", "/data");
+done:
+	LEAVE();
+}
+#endif
+
+/**
+ *  @brief This function save dump buf to file
+ *
+ *  @param dir_name  A pointer to directory name
+ *  @param file_name A pointer to file name
+ *  @param buf       A pointer to dump data
+ *  @param buf_len   The length of dump buf
+ *
+ *  @return         SUCCESS OR FAILURE
+ */
+mlan_status
+woal_save_dump_info_to_file(char *dir_name, char *file_name, t_u8 *buf,
+			    t_u32 buf_len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	struct file *pfile = NULL;
+	t_u8 name[64];
+	loff_t pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	if (!dir_name || !file_name || !buf) {
+		PRINTM(MERROR, "Can't save dump info to file\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(name, 0, sizeof(name));
+	sprintf(name, "%s/%s", dir_name, file_name);
+	pfile = filp_open(name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR,
+		       "Create file %s error, try to save dump file in /var\n",
+		       name);
+		memset(name, 0, sizeof(name));
+		sprintf(name, "%s/%s", "/var", file_name);
+		pfile = filp_open(name, O_CREAT | O_RDWR, 0644);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR, "Create Dump file for %s error\n", name);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MERROR, "Dump data %s saved in %s\n", file_name, name);
+
+	pos = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	vfs_write(pfile, buf, buf_len, &pos);
+	set_fs(fs);
+#else
+	kernel_write(pfile, buf, buf_len, &pos);
+#endif
+	filp_close(pfile, NULL);
+
+	PRINTM(MERROR, "Dump data %s saved in %s successfully\n", file_name,
+	       name);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function dump drv info to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param dir_name   A pointer to directory name
+ *
+ *  @return         N/A
+ */
+void
+woal_dump_drv_info(moal_handle *phandle, t_u8 *dir_name)
+{
+	int ret = 0;
+	struct file *pfile = NULL;
+	t_u8 *drv_buf;
+	t_u8 file_name[64];
+	t_u32 len = 0;
+	t_u32 total_len = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	PRINTM(MERROR, "=== START DRIVER INFO DUMP===");
+	ret = moal_vmalloc(phandle, DRV_INFO_SIZE + 1, &drv_buf);
+	if ((ret != MLAN_STATUS_SUCCESS) || !drv_buf) {
+		PRINTM(MERROR, "Error: vmalloc drv buffer failed!\n");
+		goto done;
+	}
+	memset(file_name, 0, sizeof(file_name));
+	sprintf(file_name, "%s/%s", dir_name, "file_drv_info");
+	pfile = filp_open(file_name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR,
+		       "Create file %s error, try create /var/file_drv_info",
+		       file_name);
+		pfile = filp_open("/var/file_drv_info", O_CREAT | O_RDWR, 0644);
+	} else {
+		PRINTM(MERROR, "DRV dump data in %s\n", file_name);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR, "Create file_drv_info file failed\n");
+		goto done;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+#endif
+
+	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;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile, drv_buf, total_len, &pfile->f_pos);
+#else
+	kernel_write(pfile, drv_buf, total_len, &pfile->f_pos);
+#endif
+	PRINTM(MERROR, "Drv info total bytes = %ld (0x%lx)\n",
+	       (long int)total_len, (long unsigned int)total_len);
+
+	filp_close(pfile, NULL);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	set_fs(fs);
+#endif
+	PRINTM(MERROR, "=== DRIVER INFO DUMP END===");
+done:
+	if (drv_buf)
+		moal_vfree(phandle, drv_buf);
+	LEAVE();
+}
+
+#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
+/* SD8777 */
+#define SQRAM_SIZE_8777                        0x33000
+#define DTCM_SIZE_8777                         0x14000
+/* SD8787 */
+#define SQRAM_SIZE_8787                        0x33000
+#define DTCM_SIZE_8787                         0xA700
+/* SD8801 */
+#define SQRAM_SIZE_8801                        0x33000
+#define DTCM_SIZE_8801                         0x14000
+/* SD8797 */
+#define SQRAM_SIZE_8797                        0x7c000
+#define DTCM_SIZE_8797                         0x14000
+
+#define DEBUG_HOST_READY_8977_8978_8997     0xCC
+#define DEBUG_HOST_READY_OTHER     0xEE
+
+#define SQRAM_SIZE                        0x33500
+
+#define DTCM_SIZE                         0x10000
+
+/**
+ *  @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 path_name[64], file_name[32];
+	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 = 0;
+	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->card_type == CARD_TYPE_SD8887) ||
+	    (phandle->card_type == CARD_TYPE_SD8897)) {
+		woal_dump_firmware_info_v2(phandle);
+		return;
+	} else if ((phandle->card_type == CARD_TYPE_SD8977) ||
+		   (phandle->card_type == CARD_TYPE_SD8997) ||
+		   (phandle->card_type == CARD_TYPE_SD8987) ||
+		   (phandle->card_type == CARD_TYPE_SD8978)) {
+		woal_dump_firmware_info_v3(phandle);
+		return;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+    /** Create dump directort*/
+	woal_create_dump_dir(phandle, path_name, sizeof(path_name));
+#else
+	memset(path_name, 0, sizeof(path_name));
+	strcpy(path_name, "/data");
+#endif
+	PRINTM(MMSG, "Directory name is %s\n", path_name);
+
+	woal_dump_drv_info(phandle, path_name);
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+#endif
+	phandle->fw_dump = MTRUE;
+	/* 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;
+	}
+	if (phandle->card_type == CARD_TYPE_SD8787) {
+		dtcm_size = DTCM_SIZE_8787;
+		sqram_size = SQRAM_SIZE_8787;
+	} else if (phandle->card_type == CARD_TYPE_SD8777) {
+		dtcm_size = DTCM_SIZE_8777;
+		sqram_size = SQRAM_SIZE_8777;
+	} else if (phandle->card_type == CARD_TYPE_SD8801) {
+		dtcm_size = DTCM_SIZE_8801;
+		sqram_size = SQRAM_SIZE_8801;
+	} else if (phandle->card_type == CARD_TYPE_SD8797) {
+		dtcm_size = DTCM_SIZE_8797;
+		sqram_size = SQRAM_SIZE_8797;
+	} else
+		dtcm_size = DTCM_SIZE;
+
+	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
+			memset(file_name, 0, sizeof(file_name));
+			sprintf(file_name, "%s", "file_sdio_ITCM");
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_save_dump_info_to_file(path_name, file_name,
+							ITCM_Ptr, ITCM_SIZE))
+				PRINTM(MMSG, "Can't save dump file %s in %s\n",
+				       file_name, path_name);
+			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
+			memset(file_name, 0, sizeof(file_name));
+			sprintf(file_name, "%s", "file_sdio_DTCM");
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_save_dump_info_to_file(path_name, file_name,
+							DTCM_Ptr, dtcm_size))
+				PRINTM(MMSG, "Can't save dump file %s in %s\n",
+				       file_name, path_name);
+			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
+			memset(file_name, 0, sizeof(file_name));
+			sprintf(file_name, "%s", "file_sdio_SQRAM");
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_save_dump_info_to_file(path_name, file_name,
+							SQRAM_Ptr, sqram_size))
+				PRINTM(MMSG, "Can't save dump file %s in %s\n",
+				       file_name, path_name);
+			PRINTM(MMSG, "End output!\n");
+			break;
+		default:
+			break;
+		}
+	} while (ctrl_data != DEBUG_SQRAM_DONE);
+
+	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:
+	phandle->fw_dump = MFALSE;
+#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;
+}
+
+#define DEBUG_DUMP_CTRL_REG_8887               0xA2
+#define DEBUG_DUMP_START_REG_8887              0xA3
+#define DEBUG_DUMP_END_REG_8887                0xAA
+
+#define DEBUG_DUMP_CTRL_REG_8897               0xE2
+#define DEBUG_DUMP_START_REG_8897              0xE3
+#define DEBUG_DUMP_END_REG_8897                0xEA
+
+#define DEBUG_DUMP_CTRL_REG_8977_8978_8997               0xF9
+#define DEBUG_DUMP_START_REG_8977_8978_8997              0xF1
+#define DEBUG_DUMP_END_REG_8977_8978_8997                0xF8
+
+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
+#define MAX_FULL_NAME_LEN               32
+t_u8 *name_prefix = "/data/file_";
+
+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;
+
+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},
+};
+memory_type_mapping mem_type_mapping_tbl_8977_8978_8997 =
+	{ "DUMP", NULL, NULL, 0xDD, 0 };
+
+typedef enum {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+} rdwr_status;
+
+/**
+ *  @brief This function read/write firmware via cmd52
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param doneflag  A flag
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+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 = 0;
+	t_u8 debug_host_ready = 0;
+
+	if (phandle->card_type == CARD_TYPE_SD8887) {
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8887;
+		debug_host_ready = DEBUG_HOST_READY_OTHER;
+	} else if (phandle->card_type == CARD_TYPE_SD8897) {
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8897;
+		debug_host_ready = DEBUG_HOST_READY_OTHER;
+	} else if ((phandle->card_type == CARD_TYPE_SD8977) ||
+		   (phandle->card_type == CARD_TYPE_SD8997) ||
+		   (phandle->card_type == CARD_TYPE_SD8987) ||
+		   (phandle->card_type == CARD_TYPE_SD8978)) {
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8977_8978_8997;
+		debug_host_ready = DEBUG_HOST_READY_8977_8978_8997;
+	}
+	ret = woal_sdio_writeb(phandle, dbg_dump_ctrl_reg, debug_host_ready);
+	if (ret) {
+		PRINTM(MERROR, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	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) {
+		PRINTM(MERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	return RDWR_STATUS_SUCCESS;
+}
+
+/**
+ *  @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 path_name[64], file_name[32];
+	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;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+    /** Create dump directort*/
+	woal_create_dump_dir(phandle, path_name, sizeof(path_name));
+#else
+	memset(path_name, 0, sizeof(path_name));
+	strcpy(path_name, "/data");
+#endif
+	PRINTM(MMSG, "Directory name is %s\n", path_name);
+
+	woal_dump_drv_info(phandle, path_name);
+	if (phandle->card_type == CARD_TYPE_SD8887) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8887;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8887;
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8887;
+	} else if (phandle->card_type == CARD_TYPE_SD8897) {
+		dbg_dump_start_reg = DEBUG_DUMP_START_REG_8897;
+		dbg_dump_end_reg = DEBUG_DUMP_END_REG_8897;
+		dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8897;
+	}
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+	phandle->fw_dump = MTRUE;
+#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);
+	/* 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_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) {
+				PRINTM(MMSG, "%s done:"
+#ifdef MLAN_64BIT
+				       "size = 0x%lx\n",
+#else
+				       "size = 0x%x\n",
+#endif
+				       mem_type_mapping_tbl[idx].mem_name,
+				       dbg_ptr -
+				       mem_type_mapping_tbl[idx].mem_Ptr);
+				memset(file_name, 0, sizeof(file_name));
+				sprintf(file_name, "%s%s", "file_sdio_",
+					mem_type_mapping_tbl[idx].mem_name);
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_save_dump_info_to_file(path_name,
+								file_name,
+								mem_type_mapping_tbl
+								[idx].mem_Ptr,
+								memory_size))
+					PRINTM(MMSG,
+					       "Can't save dump file %s in %s\n",
+					       file_name, path_name);
+				moal_vfree(phandle,
+					   mem_type_mapping_tbl[idx].mem_Ptr);
+				mem_type_mapping_tbl[idx].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:
+	phandle->fw_dump = MFALSE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+#endif
+	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 path_name[64], file_name[32], firmware_dump_file[128];
+	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;
+	memory_type_mapping *pmem_type_mapping_tbl =
+		&mem_type_mapping_tbl_8977_8978_8997;
+
+	if (!phandle) {
+		PRINTM(MERROR, "Could not dump firmwware info\n");
+		return;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+    /** Create dump directort*/
+	woal_create_dump_dir(phandle, path_name, sizeof(path_name));
+#else
+	memset(path_name, 0, sizeof(path_name));
+	strcpy(path_name, "/data");
+#endif
+	PRINTM(MERROR, "Directory name is %s\n", path_name);
+
+	woal_dump_drv_info(phandle, path_name);
+	dbg_dump_start_reg = DEBUG_DUMP_START_REG_8977_8978_8997;
+	dbg_dump_end_reg = DEBUG_DUMP_END_REG_8977_8978_8997;
+	dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG_8977_8978_8997;
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+	phandle->fw_dump = MTRUE;
+#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);
+	/* 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(phandle, temp_Ptr,
+					    pmem_type_mapping_tbl->mem_Ptr,
+					    memory_size);
+				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) {
+			PRINTM(MMSG, "%s done:"
+#ifdef MLAN_64BIT
+			       "size = 0x%lx\n",
+#else
+			       "size = 0x%x\n",
+#endif
+			       pmem_type_mapping_tbl->mem_name,
+			       dbg_ptr - pmem_type_mapping_tbl->mem_Ptr);
+
+			memset(file_name, 0, sizeof(file_name));
+			sprintf(file_name, "%s%s", "file_sdio_",
+				pmem_type_mapping_tbl->mem_name);
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_save_dump_info_to_file(path_name, file_name,
+							pmem_type_mapping_tbl->
+							mem_Ptr,
+							dbg_ptr -
+							pmem_type_mapping_tbl->
+							mem_Ptr))
+				PRINTM(MERROR,
+				       "Can't save dump file %s in %s\n",
+				       file_name, path_name);
+			moal_vfree(phandle, 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 */
+	memset(firmware_dump_file, 0, sizeof(firmware_dump_file));
+	sprintf(firmware_dump_file, "%s/%s", path_name, file_name);
+	memcpy(phandle->firmware_dump_file, firmware_dump_file,
+	       sizeof(firmware_dump_file));
+done:
+	phandle->fw_dump = MFALSE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+#endif
+	if (pmem_type_mapping_tbl->mem_Ptr) {
+		moal_vfree(phandle, pmem_type_mapping_tbl->mem_Ptr);
+		pmem_type_mapping_tbl->mem_Ptr = NULL;
+	}
+	PRINTM(MERROR, "==== DEBUG MODE END ====\n");
+	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;
+	t_u16 card_type = phandle->card_type;
+
+	ENTER();
+
+	switch (card_type) {
+	case CARD_TYPE_SD8777:
+		phandle->card_info = &card_info_sd8777;
+		break;
+	case CARD_TYPE_SD8787:
+		phandle->card_info = &card_info_sd8787;
+		break;
+	case CARD_TYPE_SD8887:
+		phandle->card_info = &card_info_sd8887;
+		break;
+	case CARD_TYPE_SD8801:
+		phandle->card_info = &card_info_sd8801;
+		break;
+	case CARD_TYPE_SD8897:
+		phandle->card_info = &card_info_sd8897;
+		break;
+	case CARD_TYPE_SD8797:
+		phandle->card_info = &card_info_sd8797;
+		break;
+	case CARD_TYPE_SD8977:
+		phandle->card_info = &card_info_sd8977;
+		break;
+	case CARD_TYPE_SD8978:
+		phandle->card_info = &card_info_sd8978;
+		break;
+	case CARD_TYPE_SD8997:
+		phandle->card_info = &card_info_sd8997;
+		break;
+	case CARD_TYPE_SD8987:
+		phandle->card_info = &card_info_sd8987;
+		break;
+	default:
+		PRINTM(MERROR,
+		       "woal_get_card_info can't get right card type \n");
+		ret = -1;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads and displays SDIO registers for debugging
+ *
+ *  @param phandle  A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_sdio_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 = SDIO_SCRATCH_REG;
+	unsigned int reg_table_8887_8977_8978_8997[] =
+		{ 0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62,
+		0x64, 0x65, 0x66, 0x68, 0x69, 0x6a
+	};
+	unsigned int reg_table_8897[] =
+		{ 0x4C, 0x50, 0x54, 0x55, 0x58, 0x59, 0x5c, 0x5d };
+	unsigned int reg_table_other[] = { 0x28, 0x30, 0x34, 0x38, 0x3c };
+	unsigned int *reg_table = NULL;
+	t_u8 reg_table_size = 0;
+	char buf[256], *ptr;
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+#define SDIO_SCRATCH_REG_8887 0x90
+#define SDIO_SCRATCH_REG_8897 0xC0
+#define SDIO_SCRATCH_REG_8977_8978_8997 0xE8
+#define SDIO_SCRATCH_REG_OTHER 0x60
+	if (phandle->card_type == CARD_TYPE_SD8887) {
+		reg_table = reg_table_8887_8977_8978_8997;
+		reg_table_size =
+			sizeof(reg_table_8887_8977_8978_8997) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8887;
+	} else if (phandle->card_type == CARD_TYPE_SD8897) {
+		reg_table = reg_table_8897;
+		reg_table_size = sizeof(reg_table_8897) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8897;
+	} else if ((phandle->card_type == CARD_TYPE_SD8977) ||
+		   (phandle->card_type == CARD_TYPE_SD8997) ||
+		   (phandle->card_type == CARD_TYPE_SD8987) ||
+		   (phandle->card_type == CARD_TYPE_SD8978)) {
+		reg_table = reg_table_8887_8977_8978_8997;
+		reg_table_size =
+			sizeof(reg_table_8887_8977_8978_8997) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_8977_8978_8997;
+	} else {
+		reg_table = reg_table_other;
+		reg_table_size = sizeof(reg_table_other) / sizeof(int);
+		scratch_reg = SDIO_SCRATCH_REG_OTHER;
+	}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+#endif
+	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;
+			if (phandle->card_type == CARD_TYPE_SD8897) {
+				reg_start = 4;
+				reg_end = 0xB;
+			} else if ((phandle->card_type == CARD_TYPE_SD8887) ||
+				   (phandle->card_type == CARD_TYPE_SD8977) ||
+				   (phandle->card_type == CARD_TYPE_SD8978) ||
+				   (phandle->card_type == CARD_TYPE_SD8997) ||
+				   (phandle->card_type == CARD_TYPE_SD8987)) {
+				reg_start = 0x10;
+				reg_end = 0x17;
+			} else {
+				reg_start = 4;
+				reg_end = 9;
+			}
+		} 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);
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+#endif
+}
+
+/**
+ *  @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;
+	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;
+	}
+
+	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));
+#if defined(SDIO_SUSPEND_RESUME)
+	PRINTM(MERROR, "hs_skip_count = %u\n", phandle->hs_skip_count);
+	PRINTM(MERROR, "hs_force_count = %u\n", phandle->hs_force_count);
+#endif
+
+	if (priv) {
+		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 < (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)
+			PRINTM(MERROR, "%s: num_tx_timeout = %d\n",
+			       priv->netdev->name, priv->num_tx_timeout);
+	}
+
+#if defined(SDIO_SUSPEND_RESUME)
+	if (phandle->is_suspended == MTRUE) {
+		LEAVE();
+		return;
+	}
+#endif
+
+	/* Display SDIO registers */
+	if (flag &&
+	    ((phandle->main_state == MOAL_END_MAIN_PROCESS) ||
+	     (phandle->main_state == MOAL_STATE_IDLE))) {
+		woal_sdio_reg_dbg(phandle);
+	} else {
+		phandle->sdio_reg_dbg = MTRUE;
+		queue_work(phandle->workqueue, &phandle->main_work);
+	}
+
+	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[] = "txpower_XX.bin";
+	char file_path[256];
+	char *last_slash = 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;
+	}
+	if (fw_region)
+		strncpy(country_name, "rgpower_XX.bin",
+			strlen("rgpower_XX.bin"));
+	handle = priv->phandle;
+
+	/* Replace XX with ISO 3166-1 alpha-2 country code */
+	strncpy(strstr(country_name, "XX"), country, strlen(country));
+
+	memset(file_path, 0, sizeof(file_path));
+	/* file_path should be Null terminated */
+	if (fw_name && (strlen(fw_name) < sizeof(file_path))) {
+		strncpy(file_path, fw_name,
+			MIN((sizeof(file_path) - 1), strlen(fw_name)));
+		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 {
+		strncpy(file_path, "mrvl/", sizeof(file_path));
+	}
+	strncpy(file_path + strlen(file_path), country_name,
+		strlen(country_name));
+	country_txpwrlimit = file_path;
+	PRINTM(MMSG, "Trying download country_power_tble: %s\n", file_path);
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_user_init_data(handle, COUNTRY_POWER_TABLE,
+				    MOAL_IOCTL_WAIT)) {
+		char country_name2[] = "txpower_ROW.bin";
+		if (fw_region)
+			strncpy(country_name2, "rgpower_ROW.bin", strlen("rgpower_ROW.bin"));
+
+		PRINTM(MERROR,
+				"Loading power table:%s Failed. Attempting to load %s\n",
+				country_txpwrlimit, country_name2);
+		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_name2, strlen(country_name2));
+
+		if (MLAN_STATUS_SUCCESS != woal_set_user_init_data(handle,
+								COUNTRY_POWER_TABLE,
+								MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR,"Loading %s Failed as well.\n", country_txpwrlimit);
+			ret = MLAN_STATUS_FAILURE;
+		}
+		else {
+			ret = MLAN_STATUS_SUCCESS;
+		}
+	}
+	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
+ */
+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 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;
+	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;
+		}
+		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
+
+	ENTER();
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return;
+	}
+
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 14, 6)
+	if (handle->rx_bgscan_stop) {
+		handle->rx_bgscan_stop = MFALSE;
+		priv = handle->bg_scan_priv;
+		handle->bg_scan_priv = NULL;
+		if (priv && priv->sched_scanning) {
+			cfg80211_sched_scan_stopped(priv->wdev->wiphy);
+			PRINTM(MEVENT, "Report sched_Scan stopped\n");
+			priv->sched_scanning = MFALSE;
+		}
+	}
+#endif
+#endif
+#endif
+	mlan_rx_process(handle->pmlan_adapter, NULL);
+
+	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);
+#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->sdio_reg_dbg == MTRUE) {
+		handle->sdio_reg_dbg = MFALSE;
+		woal_sdio_reg_dbg(handle);
+#if defined(DEBUG_LEVEL1)
+		if (drvdbg & MFW_D) {
+			drvdbg &= ~MFW_D;
+			woal_dump_firmware_info(handle);
+		}
+#endif
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	/* Change the priority and scheduling policy of main work queue */
+	if ((wq_sched_prio != current->rt_priority) ||
+	    (wq_sched_policy != current->policy)) {
+		PRINTM(MMSG,
+		       "Set work queue priority %d and scheduling policy %d\n",
+		       wq_sched_prio, wq_sched_policy);
+		sched_setscheduler(current, wq_sched_policy, &sp);
+	}
+#endif
+
+	handle->main_state = MOAL_ENTER_WORK_QUEUE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#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;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+
+	LEAVE();
+}
+
+/**
+ * @brief Handles interrupt
+ *
+ */
+/**
+ * @param handle  A pointer to moal_handle struct
+ *
+ * @return        MLAN_STATUS_FAILURE-- when the interrupt is not for us.
+ */
+mlan_status
+woal_interrupt(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	handle->main_state = MOAL_RECV_INT;
+	PRINTM(MINTR, "*\n");
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* call mlan_interrupt to read int status */
+	mlan_interrupt(handle->pmlan_adapter);
+#ifdef SDIO_SUSPEND_RESUME
+	if (handle->is_suspended) {
+		PRINTM(MINTR, "Receive interrupt in hs_suspended\n");
+		LEAVE();
+		return ret;
+	}
+#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();
+	return ret;
+}
+
+/**
+ * @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
+ *
+ *  @return        A pointer to moal_handle structure
+ */
+moal_handle *
+woal_add_card(void *card)
+{
+	moal_handle *handle = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int netlink_num = NETLINK_MARVELL;
+	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;
+
+	/* 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 */
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
+		if (m_handle[index] == NULL)
+			break;
+	}
+	if (index < MAX_MLAN_ADAPTER) {
+		m_handle[index] = handle;
+		handle->handle_idx = index;
+		woal_register_kdump_func(handle);
+	} else {
+		PRINTM(MERROR, "Exceeded maximum cards supported!\n");
+		goto err_kmalloc;
+	}
+
+	if (mac_addr
+#ifdef MFG_CMD_SUPPORT
+	    && mfg_mode != MLAN_INIT_PARA_ENABLED
+#endif
+		) {
+		t_u8 temp[20];
+		t_u8 len = strlen(mac_addr) + 1;
+		if (len < sizeof(temp)) {
+			memcpy(temp, mac_addr, len);
+			handle->set_mac_addr = 1;
+			/* note: the following function overwrites the temp buffer */
+			woal_mac2u8(handle->mac_addr, temp);
+		}
+	}
+
+	/* Update card type */
+	woal_sdio_update_card_type(handle, card);
+	/* Get card info */
+	woal_get_card_info(handle);
+	if ((handle->card_type == CARD_TYPE_SD8887) ||
+	    (handle->card_type == CARD_TYPE_SD8997) ||
+	    (handle->card_type == CARD_TYPE_SD8987))
+		handle->histogram_table_num = 3;
+	else
+		handle->histogram_table_num = 1;
+
+	((struct sdio_mmc_card *)card)->handle = handle;
+#ifdef SPI_SUPPORT
+	((struct woal_spi_card *)card)->handle = handle;
+#endif
+
+#ifdef STA_SUPPORT
+	handle->scan_pending_on_block = MFALSE;
+	MOAL_INIT_SEMAPHORE(&handle->async_sem);
+#endif
+
+	/* 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	MLAN_INIT_WORK(&handle->host_mlme_work, woal_host_mlme_work_queue);
+#endif
+	if (!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 (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);
+	}
+
+#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 (woal_register_dev(handle) != MLAN_STATUS_SUCCESS) {
+		PRINTM(MFATAL, "Failed to register wlan device!\n");
+		goto err_registerdev;
+	}
+#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;
+	}
+
+	if (handle->card_type == CARD_TYPE_SD8777 ||
+	    handle->card_type == CARD_TYPE_SD8887) {
+		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 SD8777/8887-FP75\n");
+		}
+	}
+	LEAVE();
+	return handle;
+
+err_init_fw:
+	woal_unregister_kdump_func(handle);
+	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");
+	woal_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 (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;
+	((struct sdio_mmc_card *)card)->handle = 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;
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode == MLAN_INIT_PARA_ENABLED) {
+		fw_name = NULL;
+		mfg_mode = 0;
+	}
+#endif
+	/* 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;
+	handle->surprise_removed = MTRUE;
+
+	woal_unregister_kdump_func(handle);
+	flush_workqueue(handle->workqueue);
+	flush_workqueue(handle->evt_workqueue);
+	if (handle->rx_workqueue)
+		flush_workqueue(handle->rx_workqueue);
+
+	if (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) {
+			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");
+	}
+	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 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
+#if defined(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
+	/* 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 */
+#ifdef CONFIG_PROC_FS
+	woal_proc_exit(handle);
+#endif
+	/* Unregister device */
+	PRINTM(MINFO, "unregister device\n");
+	woal_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;
+	}
+
+	/* 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");
+	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);
+
+	/* Remove interface */
+	for (i = 0; i < MIN(MLAN_MAX_BSS_NUM, 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));
+		}
+		handle->pmlan_adapter = NULL;
+	}
+
+	handle->priv_num = 0;
+	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
+
+#define FW_POLL_TRIES 100
+#define SD8897_FW_RESET_REG  0x0E8
+#define SD8887_FW_RESET_REG  0x0B6
+#define SD8977_SD8978_SD8997_FW_RESET_REG  0x0EE
+#define SD8887_SD8897_FW_RESET_VAL  1
+#define SD8977_SD8978_SD8997_FW_RESET_VAL  0x99
+
+/**
+ *  @brief This function reload fw
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return        0--success, otherwise failure
+ */
+static int
+woal_reset_and_reload_fw(moal_handle *handle)
+{
+	int ret = 0, tries = 0;
+	t_u32 value = 1;
+	t_u32 reset_reg = 0;
+	t_u8 reset_val = 0;
+
+	ENTER();
+	if ((handle->card_type != CARD_TYPE_SD8887)
+	    && (handle->card_type != CARD_TYPE_SD8897)
+	    && (handle->card_type != CARD_TYPE_SD8977)
+	    && (handle->card_type != CARD_TYPE_SD8978)
+	    && (handle->card_type != CARD_TYPE_SD8997)
+	    && (handle->card_type != CARD_TYPE_SD8987)) {
+		PRINTM(MERROR, "Card type=%d, Don't support FW reload\n",
+		       handle->card_type);
+		LEAVE();
+		return -EFAULT;
+	}
+	mlan_pm_wakeup_card(handle->pmlan_adapter);
+
+	if (handle->card_type == CARD_TYPE_SD8887) {
+		reset_reg = SD8887_FW_RESET_REG;
+		reset_val = SD8887_SD8897_FW_RESET_VAL;
+	} else if (handle->card_type == CARD_TYPE_SD8897) {
+		reset_reg = SD8897_FW_RESET_REG;
+		reset_val = SD8887_SD8897_FW_RESET_VAL;
+	} else if ((handle->card_type == CARD_TYPE_SD8977) ||
+		   (handle->card_type == CARD_TYPE_SD8978) ||
+		   (handle->card_type == CARD_TYPE_SD8997) ||
+		   (handle->card_type == CARD_TYPE_SD8987)) {
+		reset_reg = SD8977_SD8978_SD8997_FW_RESET_REG;
+		reset_val = SD8977_SD8978_SD8997_FW_RESET_VAL;
+	}
+    /** wait SOC fully wake up */
+	for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+		ret = woal_write_reg(handle, reset_reg, 0xba);
+		if (ret == MLAN_STATUS_SUCCESS) {
+			woal_read_reg(handle, reset_reg, &value);
+			if (value == 0xba) {
+				PRINTM(MMSG, "FW wake up\n");
+				break;
+			}
+		}
+		udelay(1000);
+	}
+	/* Write register to notify FW */
+	if (woal_write_reg(handle, reset_reg, reset_val) != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to write register.\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	/* Poll register around 100 ms */
+	for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+		woal_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;
+	}
+	/* 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 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 reload fw
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param mode     FW reload mode
+ *
+ *  @return        0--success, otherwise failure
+ */
+void
+woal_request_fw_reload(moal_handle *handle, t_u8 mode)
+{
+	int intf_num;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+#if defined(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 && V14_FEATURE */
+
+	ENTER();
+
+    /** start block IOCTL */
+	handle->driver_state = MTRUE;
+	if (mode == FW_RELOAD_WITH_EMULATION) {
+		fw_reload = FW_RELOAD_WITH_EMULATION;
+		PRINTM(MMSG, "FW reload with re-emulation...\n");
+		LEAVE();
+		return;
+	}
+
+    /** detach network interface */
+	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);
+	}
+	handle->fw_reload = mode;
+	woal_update_firmware_name(handle);
+	if (mode == FW_RELOAD_NO_EMULATION) {
+		ret = woal_reload_fw(handle);
+	} else if (mode == FW_RELOAD_SDIO_INBAND_RESET)
+		ret = woal_reset_and_reload_fw(handle);
+	else
+		ret = -EFAULT;
+	if (ret) {
+		PRINTM(MERROR, "FW reload fail\n");
+		goto done;
+	}
+    /** un-block IOCTL */
+	handle->fw_reload = 0;
+	handle->driver_state = 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)) {
+			ret = -EFAULT;
+			kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+	handle->hardware_status = HardwareStatusReady;
+	/* Reset all interfaces */
+	ret = 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++) {
+		woal_init_priv(handle->priv[intf_num], MOAL_IOCTL_WAIT);
+#if defined(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 && V14_FEATURE */
+	}
+
+	/* 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;
+}
+
+/**
+ *  @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);
+
+#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);
+
+	/* Register with bus */
+	ret = woal_bus_register();
+	if (ret == MLAN_STATUS_SUCCESS)
+		PRINTM(MMSG, "wlan: Driver loaded successfully\n");
+	else
+		PRINTM(MMSG, "wlan: Driver loading failed\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 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 */
+
+		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(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(cfg80211_wext) &&
+				    handle->scan_request) {
+					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(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 (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 (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 (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;
+	}
+
+	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(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(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_crc_check, int, 0);
+MODULE_PARM_DESC(fw_crc_check,
+		 "1: Enable FW download CRC check (default); 0: Disable FW download CRC check");
+module_param(fw_serial, int, 0);
+MODULE_PARM_DESC(fw_serial,
+		 "0: support parallel download FW; 1: support serial download FW");
+module_param(fw_region, int, 0);
+MODULE_PARM_DESC(fw_region,
+		 "1: load channel regulatory domain during init; 2: dynamic load channel regulatory domain");
+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/2: Download MFG firmware");
+#endif /* MFG_CMD_SUPPORT */
+module_param(drv_mode, int, 0660);
+#if defined(WIFI_DIRECT_SUPPORT)
+MODULE_PARM_DESC(drv_mode, "Bit 0: STA; Bit 1: uAP; Bit 2: WIFIDIRECT");
+#else
+MODULE_PARM_DESC(drv_mode, "Bit 0: STA; Bit 1: uAP");
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+#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 */
+#if defined(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 && V14_FEATURE */
+#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(ps_mode, int, 0660);
+MODULE_PARM_DESC(ps_mode,
+		 "0: MLAN default; 1: Enable IEEE PS mode; 2: Disable IEEE PS mode");
+module_param(max_tx_buf, int, 0);
+MODULE_PARM_DESC(max_tx_buf, "Maximum Tx buffer size (2048/4096/8192)");
+
+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");
+
+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");
+#ifdef SDIO_SUSPEND_RESUME
+module_param(pm_keep_power, int, 0);
+MODULE_PARM_DESC(pm_keep_power, "1: PM keep power; 0: PM no power");
+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
+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,
+		 "Allow setting tx power table of country; 0: disable (default), 1: enable.");
+module_param(init_hostcmd_cfg, charp, 0);
+MODULE_PARM_DESC(init_hostcmd_cfg, "Init hostcmd file name");
+module_param(cfg80211_wext, int, 0660);
+MODULE_PARM_DESC(cfg80211_wext,
+#ifdef STA_WEXT
+		 "Bit 0: STA WEXT; "
+#endif
+#ifdef UAP_WEXT
+		 "Bit 1: UAP WEXT; "
+#endif
+#ifdef STA_CFG80211
+		 "Bit 2: STA CFG80211; "
+#endif
+#ifdef UAP_CFG80211
+		 "Bit 3: UAP CFG80211;"
+#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");
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+module_param(p2p_enh, int, 0);
+MODULE_PARM_DESC(p2p_enh, "1: Enable enhanced P2P; 0: Disable enhanced P2P");
+#endif
+#endif
+#endif
+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(sdio_rx_aggr, int, 0);
+MODULE_PARM_DESC(sdio_rx_aggr,
+		 "1: Enable SDIO rx aggr; 0: Disable SDIO rx aggr");
+
+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]");
+
+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(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(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
+
+module_param(drcs_chantime_mode, int, 0);
+MODULE_PARM_DESC(drcs_chantime_mode,
+		 "0: use default value;Bit31~Bit24:Channel time for channel index0;Bit23~Bit16:mode for channel index0;Bit15~Bit8:Channel time for channel index1;Bit7~Bit0:mode for channel index1; mode:0--PM1,1--Null2Self.");
+
+#ifdef UAP_SUPPORT
+module_param(uap_max_sta, int, 0);
+MODULE_PARM_DESC(uap_max_sta, "Maximum station number for UAP/GO.");
+#endif
+
+MODULE_DESCRIPTION("M-WLAN Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+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 100644
index 0000000..313884c
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_main.h
@@ -0,0 +1,2594 @@
+/** @file moal_main.h
+  *
+  * @brief This file contains wlan driver specific defines etc.
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+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/kmsg_dump.h>
+#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
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include       <linux/config.h>
+#endif
+
+/* 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
+
+#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"
+
+#ifdef OPENWRT
+#ifdef mwiphy_name
+#undef mwiphy_name
+#define mwiphy_name          "phy%d"
+#endif
+#ifdef default_mlan_name
+#undef default_mlan_name
+#define default_mlan_name "wlan%d"
+#endif
+#endif
+
+/**
+ * define write_can_lock() to fix compile issue on ACTIA platform
+ */
+#if !defined(write_can_lock) && defined(CONFIG_PREEMPT_RT_FULL)
+#define write_can_lock(X) 1
+#endif
+
+/** Define BOOLEAN */
+typedef t_u8 BOOLEAN;
+
+/** Driver version */
+extern char driver_version[];
+
+/** Private structure for MOAL */
+typedef struct _moal_private moal_private;
+/** Handle data structure for MOAL  */
+typedef struct _moal_handle moal_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 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);
+}
+
+#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;
+	memcpy(dst, 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(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 */
+#define NUM_TX_TIMEOUT_THRESHOLD      5
+
+/** Custom event : DRIVER HANG */
+#define CUS_EVT_DRIVER_HANG	            "EVENT=DRIVER_HANG"
+
+/** 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"
+
+/** 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"
+
+#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
+
+/** 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_MARVELL     (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 HIGH_RX_PENDING         100
+/** low rx pending packets */
+#define LOW_RX_PENDING          80
+
+/** MAX Tx Pending count */
+#define MAX_TX_PENDING      400
+
+/** 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
+
+/** 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        2
+/** Default uAP BSS */
+#define DEF_UAP_BSS        1
+#endif
+#if defined(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 && V14_FEATURE */
+
+#define DRV_MODE_WLAN            (MBIT(0)|MBIT(1)|MBIT(2)|MBIT(3)|MBIT(4))
+
+/**
+ * the maximum number of adapter supported
+ **/
+#define MAX_MLAN_ADAPTER    2
+
+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;
+
+#ifdef PROC_DEBUG
+/** Debug data */
+struct debug_data {
+    /** Name */
+	char name[32];
+    /** Size */
+	t_u32 size;
+    /** Address */
+	t_ptr addr;
+};
+
+/** 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;
+};
+#endif
+
+/** Maximum IP address buffer length */
+#define IPADDR_MAX_BUF          20
+/** IP address operation: Remove */
+#define IPADDR_OP_REMOVE        0
+
+#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;
+};
+
+/** TX status info structure */
+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 */
+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;
+	};
+};
+
+/** timesync packet info structure */
+
+#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;
+};
+
+/** Number of samples in histogram (/proc/mwlan/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[0];
+} hgm_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;
+
+/** 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;
+	/** 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;
+#ifdef UAP_SUPPORT
+	/** uAP started or not */
+	BOOLEAN bss_started;
+    /** host based uap flag */
+	BOOLEAN uap_host_based;
+	/** uAP skip CAC*/
+	BOOLEAN skip_cac;
+	/** tx block flag */
+	BOOLEAN uap_tx_blocked;
+#if defined(DFS_TESTING_SUPPORT)
+    /** user cac period */
+	t_u32 user_cac_period_msec;
+    /** channel under nop */
+	BOOLEAN chan_under_nop;
+#endif
+#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];
+#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;
+    /** 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;
+#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;
+    /**mobility domain value*/
+	t_u16 ft_md;
+    /**ft capability*/
+	t_u8 ft_cap;
+    /**set true during ft connection*/
+	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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	/** flag for host_mlme */
+	t_u8 host_mlme;
+	/** flag for auth */
+	t_u8 auth_flag;
+#endif
+#endif				/* STA_SUPPORT */
+#endif				/* STA_CFG80211 */
+#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];
+#ifdef PROC_DEBUG
+    /** MLAN debug info */
+	struct debug_data_priv items_priv;
+#endif
+
+    /** tcp session queue */
+	struct list_head tcp_sess_queue;
+    /** TCP Ack enhance flag */
+	t_u8 enable_tcp_ack_enh;
+    /** 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 LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	atomic_t wmm_tx_pending[4];
+#endif
+    /** 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 */
+	hgm_data *hist_data[MAX_ANTENNA_NUM];
+	BOOLEAN assoc_with_mac;
+};
+/** 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 V15_UPDATE*/
+	t_bool v15_update;
+	/** support V16_FW_API*/
+	t_bool v16_fw_api;
+	/** rx_rate_max for hist_data:11AC-ON:196, 11AC-OFF:76*/
+	t_u8 rx_rate_max;
+} card_info;
+
+/** 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_mwlan;
+#endif
+	/** Firmware */
+	const struct firmware *firmware;
+	/** Firmware request start time */
+	struct 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;
+	int fw_reload;
+	/** POWER MANAGEMENT AND PnP SUPPORT */
+	BOOLEAN surprise_removed;
+	/** Firmware release number */
+	t_u32 fw_release_number;
+	/** 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__;
+#if defined(SDIO_SUSPEND_RESUME)
+	/** 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
+	/** 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;
+#endif
+	/** 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;
+#if defined(SDIO_SUSPEND_RESUME)
+	/** hs skip count */
+	t_u32 hs_skip_count;
+	/** hs force count */
+	t_u32 hs_force_count;
+	/** suspend_fail flag */
+	BOOLEAN suspend_fail;
+#endif
+#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;
+    /** 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;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	struct wiphy *wiphy;
+	/** Country code for regulatory domain */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+    /** band */
+	enum ieee80211_band band;
+    /** first scan done flag */
+	t_u8 first_scan_done;
+    /** scan channel gap */
+	t_u16 scan_chan_gap;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 14, 6)
+    /** recieve bgscan stop */
+	t_u8 rx_bgscan_stop;
+    /** bg scan Private pointer */
+	moal_private *bg_scan_priv;
+#endif
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+    /** remain on channel flag */
+	t_u8 remain_on_channel;
+	/** bss index for remain on channel */
+	t_u8 remain_bss_index;
+	/** 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
+	/** Read SDIO registers for debugging */
+	t_u32 sdio_reg_dbg;
+	/** 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;
+    /** 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
+#ifdef DFS_TESTING_SUPPORT
+    /** cac period length, valid only when dfs testing is enabled */
+	long cac_period_jiffies;
+#endif
+    /** handle index - for multiple card supports */
+	t_u8 handle_idx;
+#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;
+#ifdef STA_CFG80211
+	/** CFG80211 scan request description */
+	struct cfg80211_scan_request *scan_request;
+#endif
+#endif
+	/** main state */
+	t_u8 main_state;
+    /** driver state */
+	t_u8 driver_state;
+    /** ioctl timeout */
+	t_u8 ioctl_timeout;
+    /** FW dump state */
+	t_u8 fw_dump;
+    /** FW dump full name */
+	t_u8 firmware_dump_file[128];
+	/** cmd52 function */
+	t_u8 cmd52_func;
+	/** cmd52 register */
+	t_u8 cmd52_reg;
+	/** cmd52 value */
+	t_u8 cmd52_val;
+#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;
+	/** Card type */
+	t_u16 card_type;
+	/** 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;
+	t_u8 histogram_table_num;
+	/* feature_control */
+	t_u8 feature_control;
+	struct notifier_block woal_notifier;
+	struct net_device napi_dev;
+	struct napi_struct napi_rx;
+	struct kmsg_dumper kdumper;
+#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
+
+};
+/**
+ *  @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;
+}
+
+/* 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
+
+/** Host command DS gen structure */
+typedef struct _HostCmd_DS_GEN {
+    /** Command */
+	t_u16 command;
+    /** Size */
+	t_u16 size;
+    /** Sequence number */
+	t_u16 seq_num;
+    /** Result */
+	t_u16 result;
+} HostCmd_DS_GEN;
+
+/** Host command DS 802.11 cfg data structure */
+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;
+
+/** SD8787 card type */
+#define CARD_TYPE_SD8787   0x01
+/** SD8777 card type */
+#define CARD_TYPE_SD8777   0x02
+/** SD8887 card type */
+#define CARD_TYPE_SD8887   0x03
+/** SD8801 card type */
+#define CARD_TYPE_SD8801   0x04
+/** SD8897 card type */
+#define CARD_TYPE_SD8897   0x05
+/** SD8797 card type */
+#define CARD_TYPE_SD8797   0x06
+/** SD8977 card type */
+#define CARD_TYPE_SD8977   0x07
+/** SD8997 card type */
+#define CARD_TYPE_SD8997   0x08
+/** SD8987 card type */
+#define CARD_TYPE_SD8987   0x09
+/** SD8978 card type */
+#define CARD_TYPE_SD8978   0x0A
+
+/** 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);
+/**  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 interface module */
+/** Add card */
+moal_handle *woal_add_card(void *card);
+/** 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
+
+/** Interrupt handler */
+mlan_status woal_interrupt(moal_handle *handle);
+
+/** 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 drvdbg);
+#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);
+/** 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);
+#ifdef CONFIG_PROC_FS
+mlan_status woal_request_soft_reset(moal_handle *handle);
+#endif
+void woal_request_fw_reload(moal_handle *handle, t_u8 mode);
+/** 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 PROC_DEBUG
+/** 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);
+#endif
+/** 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);
+#if defined(SDIO_SUSPEND_RESUME)
+/** Enable Host Sleep configuration */
+int woal_enable_hs(moal_private *priv);
+/** hs active timeout 2 second */
+#define HS_ACTIVE_TIMEOUT  (2 * HZ)
+#endif
+/** Get wakeup reason */
+mlan_status woal_get_wakeup_reason(moal_private *priv,
+				   mlan_ds_hs_wakeup_reason *wakeup_reason);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+void woal_create_dump_dir(moal_handle *phandle, char *dir_buf, int buf_size);
+#endif
+mlan_status woal_save_dump_info_to_file(char *dir_name, char *file_name,
+					t_u8 *buf, t_u32 buf_len);
+void woal_dump_drv_info(moal_handle *phandle, t_u8 *dir_name);
+
+#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
+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);
+/* Store the FW dumps received from events in a file */
+void woal_store_firmware_dump(moal_handle *phandle, mlan_event *pmevent);
+
+/** save hostcmd response to file */
+t_void woal_save_host_cmdresp(moal_handle *phandle,
+			      mlan_cmdresp_event * pevent);
+/** 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);
+/** 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);
+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,
+				moal_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);
+
+#if defined(STA_SUPPORT) || defined(UAP_SUPPORT)
+/** Get statistics information */
+mlan_status woal_get_stats_info(moal_private *priv, t_u8 wait_option,
+				mlan_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
+/** 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,
+					  mlan_ds_remain_chan *pchan);
+void woal_remain_timer_func(void *context);
+
+#if defined(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 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
+
+#ifdef PROC_DEBUG
+/** Create debug proc fs */
+void woal_debug_entry(moal_private *priv);
+/** Remove debug proc fs */
+void woal_debug_remove(moal_private *priv);
+#endif /* PROC_DEBUG */
+
+/** 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 REASSOCIATION
+int woal_reassociation_thread(void *data);
+void woal_reassoc_timer_func(void *context);
+#endif /* REASSOCIATION */
+
+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);
+
+int 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);
+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_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_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);
+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);
+void woal_flush_tdls_list(moal_private *priv);
+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);
+mlan_status woal_mc_policy_cfg(moal_private *priv, t_u16 *enable,
+			       t_u8 wait_option, t_u8 action);
+void woal_check_mc_connection(moal_private *priv, t_u8 wait_option,
+			      t_u8 new_channel);
+#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_u8 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_delba_all(moal_private *priv, t_u8 wait_option);
+
+void woal_ioctl_get_misc_conf(moal_private *priv, mlan_ds_misc_cfg *info);
+#endif /* _MOAL_MAIN_H */
diff --git a/wlan_sd8987/mlinux/moal_priv.c b/wlan_sd8987/mlinux/moal_priv.c
new file mode 100644
index 0000000..ba2f96e
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_priv.c
@@ -0,0 +1,6906 @@
+/** @file  moal_priv.c
+  *
+  * @brief This file contains standard ioctl functions
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+Change log:
+    10/30/2008: initial version
+************************************************************************/
+
+#include	"moal_main.h"
+#include	"moal_sdio.h"
+
+#include    "moal_eth_ioctl.h"
+
+/********************************************************
+			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_GN, BAND_B | BAND_G | BAND_GN, BAND_G | BAND_GN,
+	BAND_GN | BAND_GAC, BAND_B | BAND_G | BAND_GN | BAND_GAC,
+		BAND_G | BAND_GN | BAND_GAC,
+	BAND_A,
+	BAND_AN, BAND_A | BAND_AN,
+	BAND_AN | BAND_AAC, BAND_A | BAND_AN | BAND_AAC,
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+extern int cfg80211_wext;
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ * @brief Associated to a specific indexed entry in the ScanTable
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param wrq          A pointer to iwreq 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;
+	memcpy(ssid_bssid.ssid.ssid, buf + i, 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)) {
+		memcpy(&priv->prev_ssid_bssid.ssid,
+		       &bss_info.ssid, sizeof(mlan_802_11_ssid));
+		memcpy(&priv->prev_ssid_bssid.bssid,
+		       &bss_info.bssid, MLAN_MAC_ADDR_LENGTH);
+	}
+#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;
+	int intf_num;
+	moal_handle *handle = priv->phandle;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+#if defined(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 && V14_FEATURE */
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	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);
+#if defined(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 && V14_FEATURE */
+	}
+
+	/* 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;
+		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) {
+			ret = -EFAULT;
+			if (status != MLAN_STATUS_PENDING)
+				kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+
+	/* 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 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];
+	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 (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] != 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[4];
+	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;
+	t_u32 adhoc_chan_bandwidth = 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 (radio_cfg->param.band_cfg.adhoc_start_band & BAND_GN
+		    || radio_cfg->param.band_cfg.adhoc_start_band & BAND_AN
+		    || radio_cfg->param.band_cfg.adhoc_start_band & BAND_GAC
+		    || radio_cfg->param.band_cfg.adhoc_start_band & BAND_AAC) {
+			/* secondary bandwidth */
+			data[3] =
+				radio_cfg->param.band_cfg.adhoc_chan_bandwidth;
+			wrq->u.data.length = 4;
+		}
+
+		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;
+			}
+		}
+		if (user_data_len == 4) {
+			if (!(adhoc_band & (BAND_GN
+					    | BAND_GAC | BAND_AN | BAND_AAC))) {
+				PRINTM(MERROR,
+				       "11n is not enabled for adhoc, can not set HT/VHT channel bandwidth\n");
+				ret = -EINVAL;
+				goto error;
+			}
+			adhoc_chan_bandwidth = data[3];
+			if ((adhoc_chan_bandwidth != CHANNEL_BW_20MHZ) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_ABOVE) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_BELOW)
+			    && (adhoc_chan_bandwidth != CHANNEL_BW_80MHZ)
+				) {
+				PRINTM(MERROR,
+				       "Invalid secondary channel bandwidth, only allowed 0, 1, 3 or 4\n");
+				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;
+		radio_cfg->param.band_cfg.adhoc_chan_bandwidth =
+			adhoc_chan_bandwidth;
+		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 < pcfg->param.power_ext.num_pwr_grp) &&
+		       (power_ext_len < 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;
+}
+
+/**
+ *  @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;
+}
+
+/**
+ *  @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 "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;
+}
+
+/**
+ * @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;
+}
+
+/**
+ * @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 wrq         A pointer to iwreq 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[][35] = { {"sleep clock error in ppm"},
+	{"wakeup offset in usec"},
+	{"clock stabilization time in usec"},
+	{"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");
+			LEAVE();
+			return -EINVAL;
+		}
+#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 the iwreq structure
+ *
+ *  @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 the iwreq structure
+ *
+ *  @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 the iwreq structure
+ *
+ *  @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 the iwreq structure
+ *
+ *  @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      Pointer to the iwreq structure
+ *
+ *  @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 >= sizeof(buf)) {
+		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;
+	}
+
+	/* 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);
+			strncpy((char *)sec->param.passphrase.ssid.ssid, end,
+				MIN(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;
+			memcpy(sec->param.passphrase.psk.passphrase.passphrase,
+			       end,
+			       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:");
+			memcpy(buf + len, sec->param.passphrase.ssid.ssid,
+			       sec->param.passphrase.ssid.ssid_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 the iwreq structure
+ *
+ *  @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 MAX_TX_BF_GLOBAL_ARGS   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;
+	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 > 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 < 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 < 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 *)wrq->u.data.pointer;
+	pcurrent = (t_u8 *)prsp_info->scan_table_entry_buf;
+
+	pbuffer_end = 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 *)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)
+{
+	int ret = 0;
+	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) {
+		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 */
+	if (copy_from_user
+	    (&scan_start, wrq->u.data.pointer, sizeof(scan_start))) {
+		PRINTM(MERROR, "copy from user failed\n");
+		ret = -EFAULT;
+		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;
+}
+
+/**
+ *  @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) {
+		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 {
+		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;
+		}
+	}
+
+	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, func, 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) */
+	func = buf[1];		/* func (0/1/2) */
+	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, func = %d, addr = %#x, mode = %d, block size = %d, block(byte) number = %d\n",
+	       func, 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 > total_len)
+			pattern_len = total_len;
+		memset(data, 0, WOAL_2K_BYTES);
+
+		/* Copy/duplicate the pattern to data buffer */
+		for (pos = 0; pos < 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;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ * @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];
+	case 5:
+		misc->param.mpa_ctrl.tx_max_ports = data[4];
+	case 4:
+		misc->param.mpa_ctrl.rx_buf_size = data[3];
+	case 3:
+		misc->param.mpa_ctrl.tx_buf_size = data[2];
+	case 2:
+		misc->param.mpa_ctrl.rx_enable = data[1];
+	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 /* SDIO_MULTI_PORT_TX_AGGR || SDIO_MULTI_PORT_RX_AGGR */
+
+/**
+ * @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 arg_len = 7;
+	int data[arg_len], 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;
+
+	ENTER();
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (data_length > arg_len) {
+		ret = -EINVAL;
+		goto done;
+	}
+	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;
+		memcpy(&scan->param.scan_cfg, data, sizeof(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 (!data_length) {
+		memcpy(data, &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 = ARRAY_SIZE(data);
+	}
+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;
+		memcpy(&pm_cfg->param.ps_cfg, data,
+		       MIN(sizeof(pm_cfg->param.ps_cfg), sizeof(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;
+	}
+	memcpy(data, &pm_cfg->param.ps_cfg,
+	       MIN((sizeof(int) * allowed), sizeof(pm_cfg->param.ps_cfg)));
+	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;
+		}
+
+		memcpy(cfg->param.addts.ie_data,
+		       addts_ioctl.ie_data, cfg->param.addts.ie_data_len);
+
+		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;
+
+		memcpy(addts_ioctl.ie_data,
+		       cfg->param.addts.ie_data, cfg->param.addts.ie_data_len);
+
+		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;
+		}
+
+		memcpy(cfg->param.delts.ie_data,
+		       delts_ioctl.ie_data, cfg->param.delts.ie_data_len);
+
+		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;
+		}
+
+		memcpy((void *)pqstats, (void *)&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));
+		memcpy((void *)&qstats_ioctl, (void *)pqstats,
+		       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));
+		memcpy((void *)&qstatus_ioctl, (void *)&pwmm->param.q_status,
+		       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));
+		memcpy((void *)&ts_status_ioctl, (void *)&pwmm->param.ts_status,
+		       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;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ *  @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] > 0xFFFF) {
+			PRINTM(MERROR, "The maximum user CAC is 65535 msec.\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 / 1000;
+		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;
+}
+#endif /* DFS_SUPPORT && DFS_TESTING_SUPPORT */
+
+/**
+ *  @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;
+}
+
+/********************************************************
+			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(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;
+		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;
+		case WOAL_SET_GET_WWS_CFG:
+			ret = woal_wws_cfg(priv, wrq);
+			break;
+		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;
+#if defined(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;
+		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_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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+		case WOAL_SDIO_MPA_CTRL:
+			ret = woal_do_sdio_mpa_ctrl(priv, wrq);
+			break;
+#endif
+		case WOAL_SLEEP_PARAMS:
+			ret = woal_sleep_params_ioctl(priv, wrq);
+			break;
+#if defined(DFS_TESTING_SUPPORT)
+		case WOAL_DFS_TESTING:
+			ret = woal_dfs_testing(priv, wrq);
+			break;
+#endif
+		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;
+		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) {
+		case WOAL_CMD_53RDWR:
+			ret = woal_cmd53rdwr_ioctl(priv, wrq);
+			break;
+		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(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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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) {
+			memcpy(chan_list, &bss->param.chanlist,
+			       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 100644
index 0000000..1d79f14
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_priv.h
@@ -0,0 +1,748 @@
+
+/** @file moal_priv.h
+ *
+ * @brief This file contains definition for extended private IOCTL call.
+ *
+ * Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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
+
+/** 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
+/** 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
+/** 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
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** 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
+#if defined(DFS_TESTING_SUPPORT)
+/** Private command ID to set/get dfs testing settings */
+#define WOAL_DFS_TESTING            33
+#endif
+/** 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 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
+#if defined(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)
+
+/** Private command ID to read/write Command 53 */
+#define WOAL_CMD_53RDWR             2
+
+/** 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
+
+/**
+ * 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"},
+	{
+	 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"},
+	{
+	 WOAL_SET_GET_WWS_CFG,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "wwscfg"},
+#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"},
+#if defined(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"},
+	{
+	 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"},
+	{
+	 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"},
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	{
+	 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"},
+#if defined(DFS_TESTING_SUPPORT)
+	{
+	 WOAL_DFS_TESTING,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "dfstesting"},
+#endif
+	{
+	 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"},
+	{
+	 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,
+	 ""},
+	{
+	 WOAL_CMD_53RDWR,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 "sdcmd53rw"},
+	{
+	 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
+};
+
+/** 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;
+
+#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 100644
index 0000000..9179085
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_proc.c
@@ -0,0 +1,782 @@
+/**  @file moal_proc.c
+  *
+  * @brief This file contains functions for proc file.
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#include    "moal_sdio.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+#ifdef CONFIG_PROC_FS
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+#define PROC_DIR	NULL
+#define MWLAN_PROC_DIR  "mwlan/"
+#define MWLAN_PROC  "mwlan"
+/** Proc top level directory entry */
+struct proc_dir_entry *proc_mwlan;
+int proc_dir_entry_use_count;
+#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
+
+extern int drv_mode;
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief Proc read function for info
+ *
+ *  @param sfp      pointer to seq_file structure
+ *  @param data     void pointer to 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
+
+	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
+	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);
+#if defined(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 < 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 */
+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
+}
+
+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,
+};
+
+#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;
+
+	memcpy(string, buffer + strlen("sdcmd52rw="),
+	       MIN((CMD52_STR_LEN - 1), (len - strlen("sdcmd52rw="))));
+	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;
+}
+
+/**
+ *  @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;
+
+	int func = 0, reg = 0, val = 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)drv_mode)
+			if (woal_switch_drv_mode(handle, config_data) !=
+			    MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Could not switch drv mode\n");
+			}
+	}
+	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);
+	}
+	if (!strncmp(databuf, "debug_dump", strlen("debug_dump"))) {
+		priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+		if (priv) {
+			PRINTM(MERROR, "Recevie debug_dump command\n");
+#ifdef DEBUG_LEVEL1
+			drvdbg &= ~MFW_D;
+#endif
+			woal_mlan_debug_info(priv);
+			woal_moal_debug_info(priv, NULL, MFALSE);
+
+			woal_dump_firmware_info(handle);
+		}
+	}
+
+	if (handle->card_info->v15_update) {
+		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)
+					memcpy(handle->fwdump_fname,
+					       databuf + strlen("fwdump_file="),
+					       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);
+			} else
+				config_data = FW_RELOAD_SDIO_INBAND_RESET;
+			PRINTM(MMSG, "Request fw_reload=%d\n", config_data);
+			woal_request_fw_reload(handle, config_data);
+		}
+	}
+	MODULE_PUT;
+	LEAVE();
+	return (int)count;
+}
+
+/**
+ *  @brief config proc read function
+ *
+ *  @param sfp      pointer to seq_file structure
+ *  @param data     Void pointer to data
+ *
+ *  @return         number of output data
+ */
+static int
+woal_config_read(struct seq_file *sfp, void *data)
+{
+	moal_handle *handle = (moal_handle *)sfp->private;
+
+	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)drv_mode);
+	seq_printf(sfp, "sdcmd52rw=%d 0x%0x 0x%02X\n", handle->cmd52_func,
+		   handle->cmd52_reg, handle->cmd52_val);
+
+	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
+}
+
+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,
+};
+
+/********************************************************
+		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; *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 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_DIR;
+#endif
+	char config_proc_dir[20];
+
+	ENTER();
+
+	PRINTM(MINFO, "Create Proc Interface\n");
+	if (!handle->proc_mwlan) {
+#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(MWLAN_PROC, pde->name)) {
+				/* Directory exists */
+				PRINTM(MWARN,
+				       "proc interface already exists!\n");
+				handle->proc_mwlan = pde;
+				break;
+			}
+		}
+		if (pde == NULL) {
+			handle->proc_mwlan = proc_mkdir(MWLAN_PROC, PROC_DIR);
+			if (!handle->proc_mwlan)
+				PRINTM(MERROR,
+				       "Cannot create proc interface!\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+			else
+				atomic_set(&handle->proc_mwlan->count, 1);
+#endif
+		}
+#else
+		if (!proc_mwlan) {
+			handle->proc_mwlan = proc_mkdir(MWLAN_PROC, PROC_DIR);
+			if (!handle->proc_mwlan) {
+				PRINTM(MERROR,
+				       "Cannot create proc interface!\n");
+			}
+		} else {
+			handle->proc_mwlan = proc_mwlan;
+		}
+#endif
+		if (handle->proc_mwlan) {
+			if (handle->handle_idx)
+				sprintf(config_proc_dir, "config%d",
+					handle->handle_idx);
+			else
+				strcpy(config_proc_dir, "config");
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			r = proc_create_data(config_proc_dir, 0644,
+					     handle->proc_mwlan,
+					     &config_proc_fops, handle);
+			if (r == NULL)
+#else
+			r = create_proc_entry(config_proc_dir, 0644,
+					      handle->proc_mwlan);
+			if (r) {
+				r->data = handle;
+				r->proc_fops = &config_proc_fops;
+			} else
+#endif
+				PRINTM(MMSG, "Fail to create proc config\n");
+			proc_dir_entry_use_count++;
+		}
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+		proc_mwlan = handle->proc_mwlan;
+#endif
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Remove the top level proc directory
+ *
+ *  @param handle   pointer moal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_proc_exit(moal_handle *handle)
+{
+	ENTER();
+
+	PRINTM(MINFO, "Remove Proc Interface\n");
+	if (handle->proc_mwlan) {
+		char config_proc_dir[20];
+
+		if (handle->handle_idx)
+			sprintf(config_proc_dir, "config%d",
+				handle->handle_idx);
+		else
+			strcpy(config_proc_dir, "config");
+		remove_proc_entry(config_proc_dir, handle->proc_mwlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		/* Remove only if we are the only instance using this */
+		if (atomic_read(&(handle->proc_mwlan->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_mwlan->count));
+#endif
+			if (!--proc_dir_entry_use_count) {
+				remove_proc_entry(MWLAN_PROC, PROC_DIR);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+				proc_mwlan = NULL;
+#endif
+			}
+
+			handle->proc_mwlan = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		}
+#endif
+	}
+	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));
+		strcpy(proc_dir_name, MWLAN_PROC_DIR);
+
+		if (strlen(dev->name) >
+		    ((sizeof(proc_dir_name) - 1) - strlen(MWLAN_PROC_DIR))) {
+			PRINTM(MERROR,
+			       "Failed to create proc entry, device name is too long\n");
+			LEAVE();
+			return;
+		}
+		strcat(proc_dir_name, dev->name);
+		/* Try to create mwlan/mlanX first */
+		priv->proc_entry = proc_mkdir(proc_dir_name, PROC_DIR);
+		if (priv->proc_entry) {
+			/* Success. Continue normally */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+			if (!priv->phandle->proc_mwlan) {
+				priv->phandle->proc_mwlan =
+					priv->proc_entry->parent;
+			}
+			atomic_inc(&(priv->phandle->proc_mwlan->count));
+#endif
+		} else {
+			/* Failure. mwlan may not exist. Try to create that first */
+			priv->phandle->proc_mwlan =
+				proc_mkdir(MWLAN_PROC, PROC_DIR);
+			if (!priv->phandle->proc_mwlan) {
+				/* Failure. Something broken */
+				LEAVE();
+				return;
+			} else {
+				/* Success. Now retry creating mlanX */
+				priv->proc_entry =
+					proc_mkdir(proc_dir_name, PROC_DIR);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+				atomic_inc(&(priv->phandle->proc_mwlan->count));
+#endif
+			}
+		}
+#else
+	if (priv->phandle->proc_mwlan && !priv->proc_entry) {
+		priv->proc_entry =
+			proc_mkdir(dev->name, priv->phandle->proc_mwlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		atomic_inc(&(priv->phandle->proc_mwlan->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);
+			if (r == NULL)
+#else
+			r = create_proc_entry("info", 0, priv->proc_entry);
+			if (r) {
+				r->data = dev;
+				r->proc_fops = &info_proc_fops;
+			} else
+#endif
+				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_mwlan && priv->proc_entry) {
+		remove_proc_entry("info", priv->proc_entry);
+		remove_proc_entry(priv->proc_entry_name,
+				  priv->phandle->proc_mwlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		atomic_dec(&(priv->phandle->proc_mwlan->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 100644
index 0000000..f4de425
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_sdio.h
@@ -0,0 +1,193 @@
+/** @file moal_sdio.h

+  *

+  * @brief This file contains definitions for SDIO interface.

+  * driver.

+  *

+  * Copyright (C) 2008-2019, Marvell International Ltd.

+  *

+  * This software file (the "File") is distributed by Marvell International

+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991

+  * (the "License").  You may use, redistribute and/or modify this File in

+  * accordance with the terms and conditions of the License, a copy of which

+  * is available by writing to the Free Software Foundation, Inc.,

+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the

+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.

+  *

+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE

+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE

+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about

+  * this warranty disclaimer.

+  *

+  */

+/****************************************************

+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

+

+#ifdef STA_SUPPORT

+/** Default firmware name */

+

+#define DEFAULT_FW_NAME_8777 "mrvl/sd8777_uapsta.bin"

+#define DEFAULT_FW_NAME_8787 "mrvl/sd8787_uapsta.bin"

+#define DEFAULT_FW_NAME_8887 "mrvl/sd8887_uapsta.bin"

+#define DEFAULT_FW_NAME_8801 "mrvl/sd8801_uapsta.bin"

+#define DEFAULT_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"

+#define DEFAULT_FW_NAME_8897 "mrvl/sd8897_uapsta.bin"

+#define DEFAULT_FW_NAME_8977 "mrvl/sdsd8977_combo.bin"

+#define DEFAULT_FW_NAME_8978 "mrvl/sdsd8978_combo.bin"

+#define SD8977_V2_FW_NAME "mrvl/sdsd8977_combo_v2.bin"

+#define SD8977_V1_FW_NAME "mrvl/sdsd8977_combo_v1.bin"

+#define SD8977_V0_FW_NAME "mrvl/sdsd8977_combo.bin"

+#define SD8978_V0_FW_NAME "mrvl/sdsd8978_combo.bin"

+#define DEFAULT_FW_NAME_8997 "mrvl/sdsd8997_combo.bin"

+#define SD8997_Z_FW_NAME "mrvl/sdsd8997_combo.bin"

+#define SD8997_V2_FW_NAME "mrvl/sdsd8997_combo_v2.bin"

+#define SD8997_V3_FW_NAME "mrvl/sdsd8997_combo_v3.bin"

+#define DEFAULT_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"

+#define SD8987_FW_NAME 		 "mrvl/sdsd8987_combo.bin"

+#define DEFAULT_FW_NAME_8797 "mrvl/sd8797_uapsta.bin"

+#define SD8887_A0_FW_NAME    "mrvl/sd8887_uapsta.bin"

+#define SD8887_A2_FW_NAME    "mrvl/sd8887_uapsta_a2.bin"

+#define SD8887_WLAN_A2_FW_NAME "mrvl/sd8887_wlan_a2.bin"

+#define SD8887_WLAN_A0_FW_NAME "mrvl/sd8887_wlan.bin"

+#define SD8977_WLAN_V2_FW_NAME "mrvl/sd8977_wlan_v2.bin"

+#define SD8977_WLAN_V1_FW_NAME "mrvl/sd8977_wlan_v1.bin"

+#define SD8977_WLAN_V0_FW_NAME "mrvl/sd8977_wlan.bin"

+#define SD8978_WLAN_V0_FW_NAME "mrvl/sd8978_wlan.bin"

+#define SD8997_WLAN_Z_FW_NAME "mrvl/sd8997_wlan.bin"

+#define SD8997_WLAN_V2_FW_NAME "mrvl/sd8997_wlan_v2.bin"

+#define SD8997_WLAN_V3_FW_NAME "mrvl/sd8997_wlan_v3.bin"

+#define SD8987_WLAN_FW_NAME    "mrvl/sd8987_wlan.bin"

+#ifndef DEFAULT_FW_NAME

+#define DEFAULT_FW_NAME ""

+#endif

+#endif /* STA_SUPPORT */

+

+#ifdef UAP_SUPPORT

+/** Default firmware name */

+

+#define DEFAULT_AP_FW_NAME_8777 "mrvl/sd8777_uapsta.bin"

+#define DEFAULT_AP_FW_NAME_8787 "mrvl/sd8787_uapsta.bin"

+#define DEFAULT_AP_FW_NAME_8887 "mrvl/sd8887_uapsta.bin"

+#define DEFAULT_AP_FW_NAME_8801 "mrvl/sd8801_uapsta.bin"

+#define DEFAULT_AP_FW_NAME_8897 "mrvl/sd8897_uapsta.bin"

+#define DEFAULT_AP_FW_NAME_8977 "mrvl/sdsd8977_combo.bin"

+#define DEFAULT_AP_FW_NAME_8978 "mrvl/sdsd8978_combo.bin"

+#define DEFAULT_AP_FW_NAME_8997 "mrvl/sdsd8997_combo.bin"

+#define DEFAULT_AP_FW_NAME_8797 "mrvl/sd8797_uapsta.bin"

+#define DEFAULT_AP_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"

+#define DEFAULT_WLAN_FW_NAME_8977 "mrvl/sd8977_wlan.bin"

+#define DEFAULT_WLAN_FW_NAME_8978 "mrvl/sd8978_wlan.bin"

+#define DEFAULT_WLAN_FW_NAME_8997 "mrvl/sd8997_wlan.bin"

+#define DEFAULT_WLAN_FW_NAME_8987 "mrvl/sd8987_wlan.bin"

+#ifndef DEFAULT_AP_FW_NAME

+#define DEFAULT_AP_FW_NAME ""

+#endif

+#endif /* UAP_SUPPORT */

+

+/** Default firmaware name */

+

+#define DEFAULT_AP_STA_FW_NAME_8777 "mrvl/sd8777_uapsta.bin"

+#define DEFAULT_AP_STA_FW_NAME_8787 "mrvl/sd8787_uapsta.bin"

+#define DEFAULT_AP_STA_FW_NAME_8887 "mrvl/sd8887_uapsta.bin"

+#define DEFAULT_AP_STA_FW_NAME_8801 "mrvl/sd8801_uapsta.bin"

+#define DEFAULT_AP_STA_FW_NAME_8897 "mrvl/sd8897_uapsta.bin"

+#define DEFAULT_AP_STA_FW_NAME_8797 "mrvl/sd8797_uapsta.bin"

+#define DEFAULT_AP_STA_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"

+#define DEFAULT_AP_STA_FW_NAME_8977 "mrvl/sdsd8977_combo.bin"

+#define DEFAULT_AP_STA_FW_NAME_8978 "mrvl/sdsd8978_combo.bin"

+#define DEFAULT_AP_STA_FW_NAME_8997 "mrvl/sdsd8997_combo.bin"

+#define DEFAULT_AP_STA_FW_NAME_8987 "mrvl/sdsd8987_combo.bin"

+#define DEFAULT_WLAN_FW_NAME_8977 "mrvl/sd8977_wlan.bin"

+#define DEFAULT_WLAN_FW_NAME_8978 "mrvl/sd8978_wlan.bin"

+#define DEFAULT_WLAN_FW_NAME_8997 "mrvl/sd8997_wlan.bin"

+#define DEFAULT_WLAN_FW_NAME_8987 "mrvl/sd8987_wlan.bin"

+#ifndef DEFAULT_AP_STA_FW_NAME

+#define DEFAULT_AP_STA_FW_NAME ""

+#endif

+

+/********************************************************

+		Global Functions

+********************************************************/

+/** Function to update the SDIO card type */

+t_void woal_sdio_update_card_type(moal_handle *handle, t_void *card);

+

+/** Function to write register */

+mlan_status woal_write_reg(moal_handle *handle, t_u32 reg, t_u32 data);

+/** Function to read register */

+mlan_status woal_read_reg(moal_handle *handle, t_u32 reg, t_u32 *data);

+/** Function to write register */

+mlan_status woal_sdio_writeb(moal_handle *handle, t_u32 reg, t_u8 data);

+/** Function to read register */

+mlan_status woal_sdio_readb(moal_handle *handle, t_u32 reg, t_u8 *data);

+/** Function to read F0 register */

+mlan_status woal_sdio_f0_readb(moal_handle *handle, t_u32 reg, t_u8 *data);

+/** Function to write data to IO memory */

+mlan_status woal_write_data_sync(moal_handle *handle, mlan_buffer *pmbuf,

+				 t_u32 port, t_u32 timeout);

+/** Function to read data from IO memory */

+mlan_status woal_read_data_sync(moal_handle *handle, mlan_buffer *pmbuf,

+				t_u32 port, t_u32 timeout);

+

+/** Register to bus driver function */

+mlan_status woal_bus_register(void);

+/** Unregister from bus driver function */

+void woal_bus_unregister(void);

+

+/** Register device function */

+mlan_status woal_register_dev(moal_handle *handle);

+/** Unregister device function */

+void woal_unregister_dev(moal_handle *handle);

+

+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 */

+

+/** 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;

+};

+

+/** 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 100644
index 0000000..7486952
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_sdio_mmc.c
@@ -0,0 +1,1167 @@
+/** @file moal_sdio_mmc.c

+ *

+ *  @brief This file contains SDIO MMC IF (interface) module

+ *  related functions.

+ *

+ * Copyright (C) 2008-2019, Marvell International Ltd.

+ *

+ * This software file (the "File") is distributed by Marvell International

+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991

+ * (the "License").  You may use, redistribute and/or modify this File in

+ * accordance with the terms and conditions of the License, a copy of which

+ * is available by writing to the Free Software Foundation, Inc.,

+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the

+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.

+ *

+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE

+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE

+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about

+ * this warranty disclaimer.

+ *

+ */

+/****************************************************

+Change log:

+	02/25/09: Initial creation -

+		  This file supports SDIO MMC only

+****************************************************/

+

+#include <linux/firmware.h>

+

+#include "moal_sdio.h"

+

+/** define marvell vendor id */

+#define MARVELL_VENDOR_ID 0x02df

+

+/********************************************************

+		Local Variables

+********************************************************/

+

+/********************************************************

+		Global Variables

+********************************************************/

+

+#ifdef SDIO_SUSPEND_RESUME

+/** PM keep power */

+extern int pm_keep_power;

+extern int shutdown_hs;

+#endif

+

+extern int disconnect_on_suspend;

+

+/** Device ID for SD8777 */

+#define SD_DEVICE_ID_8777   (0x9131)

+/** Device ID for SD8787 */

+#define SD_DEVICE_ID_8787   (0x9119)

+/** Device ID for SD8887 */

+#define SD_DEVICE_ID_8887   (0x9135)

+/** Device ID for SD8801 FN1 */

+#define SD_DEVICE_ID_8801   (0x9139)

+/** Device ID for SD8897 */

+#define SD_DEVICE_ID_8897   (0x912d)

+/** Device ID for SD8797 */

+#define SD_DEVICE_ID_8797   (0x9129)

+/** Device ID for SD8977 */

+#define SD_DEVICE_ID_8977   (0x9145)

+/** Device ID for SD8997 */

+#define SD_DEVICE_ID_8997   (0x9141)

+/** Device ID for SD8987 */

+#define SD_DEVICE_ID_8987   (0x9149)

+/** Device ID for SD8978 */

+#define SD_DEVICE_ID_8978   (0x9158)

+

+/** WLAN IDs */

+static const struct sdio_device_id wlan_ids[] = {

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8777)},

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8787)},

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8887)},

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8801)},

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8897)},

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8797)},

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8977)},

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8978)},

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8997)},

+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8987)},

+	{},

+};

+

+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_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

+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

+};

+

+#ifdef SDIO_OOB_IRQ

+extern int mrvl_sdio_claim_irq(struct sdio_func *func,

+			       sdio_irq_handler_t * handler);

+extern int mrvl_sdio_release_irq(struct sdio_func *func);

+extern int mrvl_sdio_suspend(struct sdio_func *func);

+extern int mrvl_sdio_resume(struct sdio_func *func);

+#endif

+

+/********************************************************

+		Local Functions

+********************************************************/

+/**  @brief This function dump the sdio register

+ *

+ *  @param handle   A Pointer to the moal_handle structure

+ *  @return         N/A

+ */

+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;

+	int fun1_reg_8897[] = { 0x03, 0x04, 0x05, 0x06, 0x07, 0xC0, 0xC1 };

+	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);

+	}

+

+	if (handle->card_type == CARD_TYPE_SD8897) {

+		fun1_reg = fun1_reg_8897;

+		array_size = sizeof(fun1_reg_8897) / sizeof(int);

+	} else {

+		fun1_reg = fun1_reg_other;

+		array_size = sizeof(fun1_reg_other) / sizeof(int);

+	}

+	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;

+}

+

+/********************************************************

+		Global Functions

+********************************************************/

+/**  @brief This function updates the SDIO card types

+ *

+ *  @param handle   A Pointer to the moal_handle structure

+ *  @param card     A Pointer to card

+ *

+ *  @return         N/A

+ */

+t_void

+woal_sdio_update_card_type(moal_handle *handle, t_void *card)

+{

+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)card;

+

+	/* Update card type */

+	if (cardp->func->device == SD_DEVICE_ID_8777)

+		handle->card_type = CARD_TYPE_SD8777;

+	else if (cardp->func->device == SD_DEVICE_ID_8787)

+		handle->card_type = CARD_TYPE_SD8787;

+	else if (cardp->func->device == SD_DEVICE_ID_8887)

+		handle->card_type = CARD_TYPE_SD8887;

+	else if (cardp->func->device == SD_DEVICE_ID_8801)

+		handle->card_type = CARD_TYPE_SD8801;

+	else if (cardp->func->device == SD_DEVICE_ID_8897)

+		handle->card_type = CARD_TYPE_SD8897;

+	else if (cardp->func->device == SD_DEVICE_ID_8797)

+		handle->card_type = CARD_TYPE_SD8797;

+	else if (cardp->func->device == SD_DEVICE_ID_8977)

+		handle->card_type = CARD_TYPE_SD8977;

+	else if (cardp->func->device == SD_DEVICE_ID_8978)

+		handle->card_type = CARD_TYPE_SD8978;

+	else if (cardp->func->device == SD_DEVICE_ID_8997)

+		handle->card_type = CARD_TYPE_SD8997;

+	else if (cardp->func->device == SD_DEVICE_ID_8987)

+		handle->card_type = CARD_TYPE_SD8987;

+}

+

+/**

+ *  @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;

+

+	PRINTM(MINFO, "*** IN SDIO IRQ ***\n");

+	woal_interrupt(handle);

+

+	LEAVE();

+}

+

+/**  @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;

+

+	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_disable_func(func);

+		sdio_release_host(func);

+		kfree(card);

+		PRINTM(MFATAL, "sdio_enable_func() failed: ret=%d\n", ret);

+		LEAVE();

+		return -EIO;

+	}

+	sdio_release_host(func);

+	if (NULL == woal_add_card(card)) {

+		PRINTM(MERROR, "woal_add_card failed\n");

+		kfree(card);

+		sdio_claim_host(func);

+		sdio_disable_func(func);

+		sdio_release_host(func);

+		ret = MLAN_STATUS_FAILURE;

+	}

+

+	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) {

+			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

+

+#define SHUTDOWN_HOST_SLEEP_DEF_GAP      100

+#define SHUTDOWN_HOST_SLEEP_DEF_GPIO     0x3

+#define SHUTDOWN_HOST_SLEEP_DEF_COND     0x0

+

+/**  @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 timeout = 0;

+	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 (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));

+

+		timeout =

+			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);

+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {

+		PRINTM(MERROR,

+		       "%s: cannot remain alive while host is suspended\n",

+		       sdio_func_id(func));

+		LEAVE();

+		return -ENOSYS;

+	}

+	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 == 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 (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) {

+#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 SDIO_OOB_IRQ

+	mrvl_sdio_suspend(func);

+#endif

+

+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;

+#ifdef SDIO_OOB_IRQ

+	mrvl_sdio_resume(func);

+#endif

+	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);

+	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

+ */

+mlan_status

+woal_write_reg(moal_handle *handle, t_u32 reg, t_u32 data)

+{

+	mlan_status ret = MLAN_STATUS_FAILURE;

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	sdio_writeb(((struct sdio_mmc_card *)handle->card)->func, (t_u8)data,

+		    reg, (int *)&ret);

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	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

+ */

+mlan_status

+woal_read_reg(moal_handle *handle, t_u32 reg, t_u32 *data)

+{

+	mlan_status ret = MLAN_STATUS_FAILURE;

+	t_u8 val;

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	val = sdio_readb(((struct sdio_mmc_card *)handle->card)->func, reg,

+			 (int *)&ret);

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	*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

+ */

+mlan_status

+woal_sdio_writeb(moal_handle *handle, t_u32 reg, t_u8 data)

+{

+	mlan_status ret = MLAN_STATUS_FAILURE;

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	sdio_writeb(((struct sdio_mmc_card *)handle->card)->func, (t_u8)data,

+		    reg, (int *)&ret);

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	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

+ */

+mlan_status

+woal_sdio_readb(moal_handle *handle, t_u32 reg, t_u8 *data)

+{

+	mlan_status ret = MLAN_STATUS_FAILURE;

+	t_u8 val;

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	val = sdio_readb(((struct sdio_mmc_card *)handle->card)->func, reg,

+			 (int *)&ret);

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	*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

+ */

+mlan_status

+woal_sdio_f0_readb(moal_handle *handle, t_u32 reg, t_u8 *data)

+{

+	mlan_status ret = MLAN_STATUS_FAILURE;

+	t_u8 val;

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	val = sdio_f0_readb(((struct sdio_mmc_card *)handle->card)->func, reg,

+			    (int *)&ret);

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	*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

+ */

+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;

+

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	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

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+		return MLAN_STATUS_FAILURE;

+	}

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	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

+ */

+mlan_status

+woal_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

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	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

+	}

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+#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

+ */

+mlan_status

+woal_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

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+	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

+	}

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)

+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+#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_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_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

+ */

+void

+woal_unregister_dev(moal_handle *handle)

+{

+	ENTER();

+	if (handle->card) {

+		/* Release the SDIO IRQ */

+

+		sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);

+#ifdef SDIO_OOB_IRQ

+		mrvl_sdio_release_irq(((struct sdio_mmc_card *)handle->card)->

+				      func);

+#else

+		sdio_release_irq(((struct sdio_mmc_card *)handle->card)->func);

+#endif

+		sdio_disable_func(((struct sdio_mmc_card *)handle->card)->func);

+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);

+

+		sdio_set_drvdata(((struct sdio_mmc_card *)handle->card)->func,

+				 NULL);

+

+		PRINTM(MWARN, "Making the sdio dev card as NULL\n");

+	}

+

+	LEAVE();

+}

+

+/**

+ *  @brief This function registers the device

+ *

+ *  @param handle  A pointer to moal_handle structure

+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE

+ */

+mlan_status

+woal_register_dev(moal_handle *handle)

+{

+	int ret = MLAN_STATUS_SUCCESS;

+	struct sdio_mmc_card *card = handle->card;

+	struct sdio_func *func;

+

+	ENTER();

+

+	func = card->func;

+	sdio_claim_host(func);

+	/* Request the SDIO IRQ */

+#ifdef SDIO_OOB_IRQ

+	ret = mrvl_sdio_claim_irq(func, woal_sdio_interrupt);

+#else

+	ret = sdio_claim_irq(func, woal_sdio_interrupt);

+#endif

+	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);

+

+	handle->hotplug_device = &func->dev;

+

+	LEAVE();

+	return MLAN_STATUS_SUCCESS;

+

+release_irq:

+#ifdef SDIO_OOB_IRQ

+	mrvl_sdio_release_irq(func);

+#else

+	sdio_release_irq(func);

+#endif

+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;

+}

diff --git a/wlan_sd8987/mlinux/moal_shim.c b/wlan_sd8987/mlinux/moal_shim.c
new file mode 100644
index 0000000..0eaf46d
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_shim.c
@@ -0,0 +1,2714 @@
+/** @file moal_shim.c
+  *
+  * @brief This file contains the callback functions registered to MLAN
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+#include	"moal_sdio.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include "moal_cfg80211.h"
+#include "moal_cfgvendor.h"
+#endif
+extern int drv_mode;
+#include <asm/div64.h>
+
+/********************************************************
+		Local Variables
+********************************************************/
+/** moal_lock */
+typedef struct _moal_lock {
+	/** Lock */
+	spinlock_t lock;
+	/** Flags */
+	unsigned long flags;
+} moal_lock;
+
+/********************************************************
+		Global Variables
+********************************************************/
+extern int cfg80211_wext;
+
+extern int hw_test;
+
+#ifdef ANDROID_KERNEL
+extern int wakelock_timeout;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+extern int dfs_offload;
+#endif
+#endif
+
+/** napi support*/
+extern int napi;
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Alloc a buffer
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+	    IN t_u32 size, IN t_u32 flag, OUT t_u8 **ppbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	t_u32 mem_flag = (in_interrupt() || irqs_disabled())?
+		GFP_ATOMIC : GFP_KERNEL;
+
+	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_handle 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(IN t_void *pmoal_handle, IN t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	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_handle 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(IN t_void *pmoal_handle, IN t_u32 size, OUT t_u8 **ppbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	*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_handle 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(IN t_void *pmoal_handle, IN t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	if (!pbuf)
+		return MLAN_STATUS_FAILURE;
+	vfree(pbuf);
+	atomic_dec(&handle->vmalloc_count);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Fill memory with constant byte
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+	    IN t_void *pmem, IN t_u8 byte, IN 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_handle 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(IN t_void *pmoal_handle,
+	    IN t_void *pdest, IN const t_void *psrc, IN t_u32 num)
+{
+	t_void *p = pdest;
+
+	if (pdest && psrc && num)
+		p = memcpy(pdest, psrc, num);
+
+	return p;
+}
+
+/**
+ *  @brief Move memory from one area to another
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+	     IN t_void *pdest, IN const t_void *psrc, IN 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_handle 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(IN t_void *pmoal_handle,
+	    IN const t_void *pmem1, IN const t_void *pmem2, IN t_u32 num)
+{
+	t_s32 result;
+
+	result = memcmp(pmem1, pmem2, num);
+
+	return result;
+}
+
+/**
+ *  @brief Delay function
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param delay  delay in micro-second
+ *
+ *  @return       N/A
+ */
+t_void
+moal_udelay(IN t_void *pmoal_handle, IN t_u32 delay)
+{
+	if (delay >= 1000)
+		mdelay(delay / 1000);
+	if (delay % 1000)
+		udelay(delay % 1000);
+}
+
+/**
+ *  @brief Retrieves the current system time
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, OUT t_u32 *psec, OUT t_u32 *pusec)
+{
+	struct timeval t;
+
+	do_gettimeofday(&t);
+	*psec = (t_u32)t.tv_sec;
+	*pusec = (t_u32)t.tv_usec;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief usleep function
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param usmin        Minimum value for sleep in usecs
+ *  @param usmax        Maximum value for sleep in usecs
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_usleep(IN t_void *pmoal_handle, IN t_u64 min, IN t_u64 max)
+{
+	usleep_range(min, max);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Retrieves the current boot time
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, OUT 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_handle 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(IN t_void *pmoal_handle,
+		OUT t_void **pptimer,
+		IN t_void (*callback) (t_void *pcontext), IN t_void *pcontext)
+{
+	moal_drv_timer *timer = NULL;
+	t_u32 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_handle Pointer to the MOAL context
+ *  @param ptimer   Pointer to the timer
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_free_timer(IN t_void *pmoal_handle, IN 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_handle 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(IN t_void *pmoal_handle,
+		 IN t_void *ptimer, IN t_u8 periodic, IN 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_handle Pointer to the MOAL context
+ *  @param ptimer   Pointer to the timer
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_stop_timer(IN t_void *pmoal_handle, IN 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_handle Pointer to the MOAL context
+ *  @param pplock   Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_init_lock(IN t_void *pmoal_handle, OUT t_void **pplock)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle Pointer to the MOAL context
+ *  @param plock    Lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_free_lock(IN t_void *pmoal_handle, IN t_void *plock)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	moal_lock *mlock = plock;
+
+	kfree(mlock);
+	if (mlock)
+		atomic_dec(&handle->lock_count);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Request a spin lock
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param plock    Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_spin_lock(IN t_void *pmoal_handle, IN t_void *plock)
+{
+	moal_lock *mlock = plock;
+	unsigned long flags = 0;
+
+	if (mlock) {
+		spin_lock_irqsave(&mlock->lock, flags);
+		mlock->flags = flags;
+		return MLAN_STATUS_SUCCESS;
+	} else {
+		return MLAN_STATUS_FAILURE;
+	}
+}
+
+/**
+ *  @brief Request a spin_unlock
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param plock    Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_spin_unlock(IN t_void *pmoal_handle, IN t_void *plock)
+{
+	moal_lock *mlock = (moal_lock *)plock;
+
+	if (mlock) {
+		spin_unlock_irqrestore(&mlock->lock, mlock->flags);
+
+		return MLAN_STATUS_SUCCESS;
+	} else {
+		return MLAN_STATUS_FAILURE;
+	}
+}
+
+/**
+ *  @brief This function reads one block of firmware data from MOAL
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		 IN t_u32 offset, IN t_u32 len, OUT t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	if (!pbuf || !len)
+		return MLAN_STATUS_FAILURE;
+
+	if (offset + len > handle->firmware->size)
+		return MLAN_STATUS_FAILURE;
+
+	memcpy(pbuf, handle->firmware->data + offset, len);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN completes the initialization firmware.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN mlan_status status,
+			  IN mlan_hw_info * phw, IN pmlan_bss_tbl ptbl)
+{
+	ENTER();
+	if (status == MLAN_STATUS_SUCCESS) {
+		PRINTM(MCMND, "Get Hw Spec done, fw_cap=0x%x\n", phw->fw_cap);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN completes the initialization firmware.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle Pointer to the MOAL context
+ *  @param status   The status code for mlan_shutdown request
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_shutdown_fw_complete(IN t_void *pmoal_handle, IN mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle 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(IN t_void *pmoal_handle,
+		    IN pmlan_ioctl_req pioctl_req, IN mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle 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(IN t_void *pmoal_handle,
+		       IN t_u32 size, OUT pmlan_buffer *pmbuf)
+{
+	*pmbuf = woal_alloc_mlan_buffer((moal_handle *)pmoal_handle, size);
+	if (NULL == *pmbuf)
+		return MLAN_STATUS_FAILURE;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function frees mlan_buffer.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf)
+{
+	if (!pmbuf)
+		return MLAN_STATUS_FAILURE;
+	woal_free_mlan_buffer((moal_handle *)pmoal_handle, pmbuf);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN complete send data packet.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+			  IN pmlan_buffer pmbuf, IN mlan_status status)
+{
+	moal_private *priv = NULL;
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle, 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;
+				} else {
+					priv->stats.tx_errors++;
+				}
+#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:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function write a command/data packet to card.
+ *         This function blocks the call until it finishes
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		     IN pmlan_buffer pmbuf, IN t_u32 port, IN t_u32 timeout)
+{
+	return woal_write_data_sync((moal_handle *)pmoal_handle, pmbuf, port,
+				    timeout);
+}
+
+/**
+ *  @brief This function read data packet/event/command from card.
+ *         This function blocks the call until it finish
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		    IN OUT pmlan_buffer pmbuf, IN t_u32 port, IN t_u32 timeout)
+{
+	return woal_read_data_sync((moal_handle *)pmoal_handle, pmbuf, port,
+				   timeout);
+}
+
+/**
+ *  @brief This function writes data into card register.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN t_u32 reg, IN t_u32 data)
+{
+	return woal_write_reg((moal_handle *)pmoal_handle, reg, data);
+}
+
+/**
+ *  @brief This function reads data from card register.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN t_u32 reg, OUT t_u32 *data)
+{
+	return woal_read_reg((moal_handle *)pmoal_handle, reg, data);
+}
+
+/**
+ *  @brief This function uploads the packet to the network stack
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+	struct sk_buff *skb = NULL;
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	ENTER();
+	if (pmbuf) {
+
+		priv = woal_bss_index_to_priv(pmoal_handle, pmbuf->bss_index);
+		skb = (struct sk_buff *)pmbuf->pdesc;
+		if (priv) {
+			if (skb) {
+				skb_reserve(skb, pmbuf->data_offset);
+				if (skb_tailroom(skb) < 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!!! pkt_len=%d flags=0x%x\n",
+				       __func__, pmbuf->data_len, pmbuf->flags);
+				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++;
+					goto done;
+				}
+				skb_reserve(skb, MLAN_NET_IP_ALIGN);
+				memcpy(skb->data,
+				       (t_u8 *)(pmbuf->pbuf +
+						pmbuf->data_offset),
+				       pmbuf->data_len);
+				skb_put(skb, pmbuf->data_len);
+
+			}
+			skb->dev = priv->netdev;
+			skb->protocol = eth_type_trans(skb, priv->netdev);
+			skb->ip_summed = CHECKSUM_NONE;
+
+			priv->stats.rx_bytes += skb->len;
+			priv->stats.rx_packets++;
+#ifdef ANDROID_KERNEL
+			if (wakelock_timeout) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+				__pm_wakeup_event(&handle->ws,
+						  wakelock_timeout);
+#else
+				wake_lock_timeout(&handle->wake_lock,
+						  msecs_to_jiffies
+						  (wakelock_timeout));
+#endif
+			}
+#endif
+			if (in_interrupt())
+				netif_rx(skb);
+			else {
+				if (atomic_read(&handle->rx_pending) >
+				    MAX_RX_PENDING_THRHLD)
+					netif_rx(skb);
+				else
+					netif_rx_ni(skb);
+			}
+		}
+	}
+done:
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function handles event receive
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param pmevent  Pointer to the mlan event structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_recv_event(IN t_void *pmoal_handle, IN 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
+#if defined(SDIO_SUSPEND_RESUME)
+	mlan_ds_ps_info pm_info;
+#endif
+
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+	chan_band_info *pchan_info = NULL;
+#endif
+	t_u8 channel_status;
+	moal_private *remain_priv = NULL;
+
+	ENTER();
+
+	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 (pmevent->event_id == MLAN_EVENT_ID_FW_DUMP_INFO) {
+		woal_store_firmware_dump(pmoal_handle, pmevent);
+		goto done;
+	}
+	if (pmevent->event_id == MLAN_EVENT_ID_STORE_HOST_CMD_RESP) {
+		woal_save_host_cmdresp((moal_handle *)pmoal_handle,
+				       (mlan_cmdresp_event *) pmevent);
+		goto done;
+	}
+	priv = woal_bss_index_to_priv(pmoal_handle, 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;
+	}
+	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);
+			memcpy(wrqu.ap_addr.sa_data, pmevent->event_buf,
+			       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)) {
+			memcpy(priv->cfg_bssid, pmevent->event_buf, 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);
+		memcpy(pmevent->event_buf, CUS_EVT_AP_CONNECTED, 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);
+
+		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) {
+						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 (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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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;
+#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 */
+		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);
+			if (!hw_test && priv->roaming_enabled)
+				woal_config_bgscan_and_rssi(priv, MFALSE);
+			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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 (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 (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_state = MTRUE;
+		woal_moal_debug_info(priv, NULL, MFALSE);
+		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
+		woal_process_hang(priv->phandle);
+		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;
+				woal_get_scan_table(priv, MOAL_NO_WAIT,
+						    &scan_resp);
+				PRINTM(MIOCTL,
+				       "Trigger 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);
+			}
+		}
+#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) {
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 14, 6)
+				priv->phandle->rx_bgscan_stop = MTRUE;
+				priv->phandle->bg_scan_priv = priv;
+				queue_work(priv->phandle->rx_workqueue,
+					   &priv->phandle->rx_work);
+#else
+				rcu_read_lock();
+				if (rtnl_is_locked())
+					cfg80211_sched_scan_stopped_rtnl(priv->
+									 wdev->
+									 wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+									 , 0
+#endif
+						);
+				else
+					cfg80211_sched_scan_stopped(priv->wdev->
+								    wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+								    , 0
+#endif
+						);
+				rcu_read_unlock();
+				priv->sched_scanning = MFALSE;
+#endif
+				PRINTM(MEVENT, "Sched_Scan stopped\n");
+
+			}
+		}
+#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);
+				cfg80211_sched_scan_results(priv->wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+							    ,
+							    priv->bg_scan_reqid
+#endif
+					);
+				priv->last_event = 0;
+				PRINTM(MEVENT,
+				       "Reporting Sched_Scan results\n");
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 14, 6)
+				priv->phandle->rx_bgscan_stop = MTRUE;
+				priv->phandle->bg_scan_priv = priv;
+				queue_work(priv->phandle->rx_workqueue,
+					   &priv->phandle->rx_work);
+#else
+				if (rtnl_is_locked())
+					cfg80211_sched_scan_stopped_rtnl(priv->
+									 wdev->
+									 wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+									 , 0
+#endif
+						);
+				else
+					cfg80211_sched_scan_stopped(priv->wdev->
+								    wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+								    , 0
+#endif
+						);
+				priv->sched_scanning = MFALSE;
+#endif
+				PRINTM(MEVENT, "Sched_Scan stopped\n");
+			}
+		}
+#endif
+#endif
+		break;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	case MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY:
+		if (priv->phandle->is_cac_timer_set) {
+			t_u8 radar_detected = pmevent->event_buf[0];
+			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;
+		}
+		break;
+	case MLAN_EVENT_ID_FW_RADAR_DETECTED:
+		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 {
+			PRINTM(MEVENT, "radar detected during BSS active \n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			if (dfs_offload)
+				woal_cfg80211_dfs_vendor_event(priv,
+							       event_dfs_radar_detected,
+							       &priv->chan);
+			else
+#endif
+				cfg80211_radar_event(priv->wdev->wiphy,
+						     &priv->chan, GFP_KERNEL);
+		}
+		break;
+#endif
+#endif
+	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;
+#endif /* STA_SUPPORT */
+	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)) {
+				memcpy(&priv->chan, &priv->csa_chan,
+				       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_handle,
+				       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_handle,
+				       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_handle,
+				       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_handle,
+				       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
+#if defined(SDIO_SUSPEND_RESUME)
+		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);
+		}
+#endif
+		break;
+	case MLAN_EVENT_ID_DRV_HS_DEACTIVATED:
+#ifdef STA_SUPPORT
+		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
+				       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_handle,
+				       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
+#if defined(SDIO_SUSPEND_RESUME)
+		priv->phandle->hs_activated = MFALSE;
+#endif
+		break;
+#ifdef UAP_SUPPORT
+	case MLAN_EVENT_ID_UAP_FW_BSS_START:
+		if (priv->hist_data)
+			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);
+		memcpy(priv->current_addr, pmevent->event_buf + 6, ETH_ALEN);
+		memcpy(priv->netdev->dev_addr, priv->current_addr, 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_handle,
+				       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 defined(DFS_TESTING_SUPPORT)
+#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);
+			mutex_lock(&priv->wdev->mtx);
+			cfg80211_ch_switch_notify(priv->netdev, &priv->chan);
+			mutex_unlock(&priv->wdev->mtx);
+			priv->chan_under_nop = MFALSE;
+		}
+#endif
+#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)) {
+			chan_band_info *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);
+		break;
+	case MLAN_EVENT_ID_UAP_FW_BSS_IDLE:
+		priv->media_connected = MFALSE;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+		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)
+	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->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
+	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;
+			t_u8 addr[ETH_ALEN];
+
+			sinfo.filled = 0;
+			sinfo.generation = 0;
+			/* copy the station mac address */
+			memset(addr, 0xFF, ETH_ALEN);
+			memcpy(addr, pmevent->event_buf, 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
+				/* 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);
+		}
+#endif /* UAP_CFG80211 */
+		memmove((pmevent->event_buf + strlen(CUS_EVT_STA_CONNECTED) +
+			 1), pmevent->event_buf, pmevent->event_len);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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)
+			/* skip 2 bytes extra header will get the mac address */
+			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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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)) {
+						if(priv->auth_flag & HOST_MLME_AUTH_PENDING){
+							PRINTM(MEVENT,"HostMlme %s: Receive auth\n",priv->netdev->name);
+							priv->auth_flag &= ~ HOST_MLME_AUTH_PENDING;
+							priv->auth_flag |= HOST_MLME_AUTH_DONE;
+							priv->phandle->host_mlme_priv = priv;
+							queue_work(priv->phandle->rx_workqueue, &priv->phandle->host_mlme_work);
+						}
+						else{
+							PRINTM(MERROR,"HostMlme %s: Drop auth pkt,auth_flag=0x%x\n", priv->netdev->name,priv->auth_flag);
+							break;
+						}
+					}
+					else {
+						PRINTM(MEVENT,
+						       "HostMlme: Receive deauth/disassociate\n");
+						woal_cfg80211_mgmt_frame_register
+							(priv->wdev->wiphy,
+							 priv->wdev,
+							 IEEE80211_STYPE_DEAUTH,
+							 MFALSE);
+						woal_cfg80211_mgmt_frame_register
+							(priv->wdev->wiphy,
+							 priv->wdev,
+							 IEEE80211_STYPE_DISASSOC,
+							 MFALSE);
+						priv->host_mlme = MFALSE;
+						priv->auth_flag = 0;
+						if(!priv->wdev->current_bss){
+							PRINTM(MEVENT,"HostMlme: Drop deauth/disassociate, we already disconnected\n");
+							break;
+						}
+					}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+					mutex_lock(&priv->wdev->mtx);
+					cfg80211_rx_mlme_mgmt(priv->netdev,
+							      pkt,
+							      pmevent->
+							      event_len -
+							      sizeof(pmevent->
+								     event_id)
+							      -
+							      MLAN_MAC_ADDR_LENGTH);
+					mutex_unlock(&priv->wdev->mtx);
+#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
+			}
+#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;
+				memcpy(&bss->param.ssid_bssid,
+				       &priv->phandle->delay_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 && 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 (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;
+					}
+				}
+				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
+				}
+#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);
+			memcpy(priv->target_ap_bssid, pmevent->event_buf,
+			       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_handle Pointer to the MOAL context
+ *  @param level    debug level
+ *  @param pformat  point to string format buf
+ *
+ *  @return         N/A
+ */
+t_void
+moal_print(IN t_void *pmoal_handle, IN t_u32 level, IN 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_handle Pointer to the MOAL context
+ *  @param bss_index    BSS index
+ *  @param level        debug level
+ *
+ *  @return            N/A
+ */
+t_void
+moal_print_netintf(IN t_void *pmoal_handle, IN t_u32 bss_index, IN t_u32 level)
+{
+#ifdef DEBUG_LEVEL1
+	moal_handle *phandle = (moal_handle *)pmoal_handle;
+
+	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_handle     A pointer to moal_private structure
+ *  @param cond             Condition to check
+ *
+ *  @return                 N/A
+ */
+t_void
+moal_assert(IN t_void *pmoal_handle, IN t_u32 cond)
+{
+	if (!cond) {
+		panic("Assert failed: Panic!");
+	}
+}
+
+/**
+ *  @brief This function save the histogram data
+ *
+ *  @param pmoal_handle     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(IN t_void *pmoal_handle, IN t_u32 bss_index, IN t_u8 rx_rate,
+		   IN t_s8 snr, IN t_s8 nflr, IN t_u8 antenna)
+{
+	moal_private *priv = NULL;
+	priv = woal_bss_index_to_priv(pmoal_handle, bss_index);
+	if (priv && antenna >= priv->phandle->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_handle     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(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			IN t_u8 *peer_addr, IN t_s8 snr, IN t_s8 nflr)
+{
+	moal_private *priv = NULL;
+	struct tdls_peer *peer = NULL;
+	unsigned long flags;
+	priv = woal_bss_index_to_priv(pmoal_handle, 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(IN t_u64 num, IN t_u32 base)
+{
+	t_u64 val = num;
+	do_div(val, base);
+	return val;
+}
diff --git a/wlan_sd8987/mlinux/moal_shim.h b/wlan_sd8987/mlinux/moal_shim.h
new file mode 100644
index 0000000..b225da0
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_shim.h
@@ -0,0 +1,115 @@
+/** @file moal_shim.h
+  *
+  * @brief This file contains declaration referring to
+  * functions defined in moal module
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change Log:
+    10/21/2008: initial version
+************************************************************/
+
+#ifndef _MOAL_H
+#define _MOAL_H
+
+mlan_status moal_get_fw_data(IN t_void *pmoal_handle,
+			     IN t_u32 offset, IN t_u32 len, OUT t_u8 *pbuf);
+mlan_status moal_get_hw_spec_complete(IN t_void *pmoal_handle,
+				      IN mlan_status status,
+				      IN mlan_hw_info * phw,
+				      IN pmlan_bss_tbl ptbl);
+mlan_status moal_init_fw_complete(IN t_void *pmoal_handle,
+				  IN mlan_status status);
+mlan_status moal_shutdown_fw_complete(IN t_void *pmoal_handle,
+				      IN mlan_status status);
+mlan_status moal_ioctl_complete(IN t_void *pmoal_handle,
+				IN pmlan_ioctl_req pioctl_req,
+				IN mlan_status status);
+mlan_status moal_alloc_mlan_buffer(IN t_void *pmoal_handle, IN t_u32 size,
+				   OUT pmlan_buffer *pmbuf);
+mlan_status moal_free_mlan_buffer(IN t_void *pmoal_handle,
+				  IN pmlan_buffer pmbuf);
+mlan_status moal_send_packet_complete(IN t_void *pmoal_handle,
+				      IN pmlan_buffer pmbuf,
+				      IN mlan_status status);
+
+/** moal_write_reg */
+mlan_status moal_write_reg(IN t_void *pmoal_handle,
+			   IN t_u32 reg, IN t_u32 data);
+/** moal_read_reg */
+mlan_status moal_read_reg(IN t_void *pmoal_handle,
+			  IN t_u32 reg, OUT t_u32 *data);
+mlan_status moal_write_data_sync(IN t_void *pmoal_handle,
+				 IN pmlan_buffer pmbuf,
+				 IN t_u32 port, IN t_u32 timeout);
+mlan_status moal_read_data_sync(IN t_void *pmoal_handle,
+				IN OUT pmlan_buffer pmbuf,
+				IN t_u32 port, IN t_u32 timeout);
+mlan_status moal_recv_packet(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf);
+mlan_status moal_recv_event(IN t_void *pmoal_handle, IN pmlan_event pmevent);
+mlan_status moal_malloc(IN t_void *pmoal_handle,
+			IN t_u32 size, IN t_u32 flag, OUT t_u8 **ppbuf);
+mlan_status moal_mfree(IN t_void *pmoal_handle, IN t_u8 *pbuf);
+mlan_status moal_vmalloc(IN t_void *pmoal_handle,
+			 IN t_u32 size, OUT t_u8 **ppbuf);
+mlan_status moal_vfree(IN t_void *pmoal_handle, IN t_u8 *pbuf);
+t_void *moal_memset(IN t_void *pmoal_handle,
+		    IN t_void *pmem, IN t_u8 byte, IN t_u32 num);
+t_void *moal_memcpy(IN t_void *pmoal_handle,
+		    IN t_void *pdest, IN const t_void *psrc, IN t_u32 num);
+t_void *moal_memmove(IN t_void *pmoal_handle,
+		     IN t_void *pdest, IN const t_void *psrc, IN t_u32 num);
+t_s32 moal_memcmp(IN t_void *pmoal_handle,
+		  IN const t_void *pmem1, IN const t_void *pmem2, IN t_u32 num);
+/** moal_udelay */
+t_void moal_udelay(IN t_void *pmoal_handle, IN t_u32 udelay);
+mlan_status moal_get_boot_ktime(IN t_void *pmoal_handle, OUT t_u64 *pnsec);
+mlan_status moal_get_system_time(IN t_void *pmoal_handle, OUT t_u32 *psec,
+				 OUT t_u32 *pusec);
+
+/** moal_usleep */
+mlan_status moal_usleep(IN t_void *pmoal_handle, IN t_u64 min, IN t_u64 max);
+
+mlan_status moal_init_lock(IN t_void *pmoal_handle, OUT t_void **pplock);
+mlan_status moal_free_lock(IN t_void *pmoal_handle, IN t_void *plock);
+mlan_status moal_spin_lock(IN t_void *pmoal_handle, IN t_void *plock);
+mlan_status moal_spin_unlock(IN t_void *pmoal_handle, IN t_void *plock);
+t_void moal_print(IN t_void *pmoal_handle, IN t_u32 level, IN char *pformat,
+		  IN ...);
+t_void moal_print_netintf(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			  IN t_u32 level);
+t_void moal_assert(IN t_void *pmoal_handle, IN t_u32 cond);
+t_void moal_hist_data_add(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			  IN t_u8 rx_rate, IN t_s8 snr, IN t_s8 nflr,
+			  IN t_u8 antenna);
+
+t_void moal_updata_peer_signal(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			       IN t_u8 *peer_addr, IN t_s8 snr, IN t_s8 nflr);
+t_u64 moal_do_div(IN t_u64 num, IN t_u32 base);
+
+mlan_status moal_init_timer(IN t_void *pmoal_handle,
+			    OUT t_void **pptimer,
+			    IN t_void (*callback) (t_void *pcontext),
+			    IN t_void *pcontext);
+mlan_status moal_free_timer(IN t_void *pmoal_handle, IN t_void *ptimer);
+mlan_status moal_start_timer(IN t_void *pmoal_handle,
+			     IN t_void *ptimer,
+			     IN t_u8 periodic, IN t_u32 msec);
+mlan_status moal_stop_timer(IN t_void *pmoal_handle, IN t_void *ptimer);
+
+#endif /*_MOAL_H */
diff --git a/wlan_sd8987/mlinux/moal_sta_cfg80211.c b/wlan_sd8987/mlinux/moal_sta_cfg80211.c
new file mode 100644
index 0000000..cdbabed
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_sta_cfg80211.c
@@ -0,0 +1,8920 @@
+/** @file moal_sta_cfg80211.c
+  *
+  * @brief This file contains the functions for STA CFG80211.
+  *
+  * Copyright (C) 2011-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include "moal_cfg80211.h"
+#include "moal_cfgvendor.h"
+#include "moal_sta_cfg80211.h"
+#include "moal_eth_ioctl.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#include <linux/sort.h>
+
+extern int cfg80211_wext;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int fw_region;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+
+extern int cntry_txpwr;
+
+/* Supported crypto cipher suits to be advertised to cfg80211 */
+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_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 t_u8 *mac,
+#else
+				     t_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
+
+static int woal_cfg80211_join_ibss(struct wiphy *wiphy,
+				   struct net_device *dev,
+				   struct cfg80211_ibss_params *params);
+
+static int woal_cfg80211_leave_ibss(struct wiphy *wiphy,
+				    struct net_device *dev);
+
+#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 */
+
+#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);
+
+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);
+
+#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)
+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
+
+/** 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,
+	.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
+	.join_ibss = woal_cfg80211_join_ibss,
+	.leave_ibss = woal_cfg80211_leave_ibss,
+	.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
+	.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
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+		.mgmt_frame_register =
+		woal_cfg80211_mgmt_frame_register,.mgmt_tx =
+		woal_cfg80211_mgmt_tx,
+#endif
+#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
+};
+
+/** 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),}
+};
+
+/********************************************************
+				Local Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static const struct ieee80211_txrx_stypes
+ ieee80211_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+	[NL80211_IFTYPE_ADHOC] = {
+				  .tx = BIT(IEEE80211_STYPE_ACTION >> 4),
+				  .rx = BIT(IEEE80211_STYPE_ACTION >> 4),
+				  },
+	[NL80211_IFTYPE_STATION] = {
+				    .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				    BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				    .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				    BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+				    },
+	[NL80211_IFTYPE_AP] = {
+			       .tx = 0xffff,
+			       .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+			       BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+			       BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+			       BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+			       BIT(IEEE80211_STYPE_AUTH >> 4) |
+			       BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+			       BIT(IEEE80211_STYPE_ACTION >> 4),
+			       },
+	[NL80211_IFTYPE_AP_VLAN] = {
+				    .tx = 0x0000,
+				    .rx = 0x0000,
+				    },
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	[NL80211_IFTYPE_P2P_CLIENT] = {
+				       .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				       BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				       .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				       BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+				       },
+	[NL80211_IFTYPE_P2P_GO] = {
+				   .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				   BIT(IEEE80211_STYPE_AUTH >> 4) |
+				   BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) |
+				   BIT(IEEE80211_STYPE_REASSOC_RESP >> 4) |
+				   BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+
+				   .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+				   BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+				   BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+				   BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+				   BIT(IEEE80211_STYPE_AUTH >> 4) |
+				   BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+				   BIT(IEEE80211_STYPE_ACTION >> 4),
+				   },
+#endif
+#endif
+	[NL80211_IFTYPE_MESH_POINT] = {
+				       .tx = 0x0000,
+				       .rx = 0x0000,
+				       },
+
+};
+#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
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	 | MBIT(NL80211_IFTYPE_P2P_GO)
+	 | MBIT(NL80211_IFTYPE_P2P_CLIENT)
+#endif
+#endif
+	 | MBIT(NL80211_IFTYPE_ADHOC)
+	 }
+};
+
+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 moal_handle *m_handle[];
+extern int hw_test;
+extern int ps_mode;
+int disable_regd_by_driver = 1;
+/** Region alpha2 string */
+char *reg_alpha2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+int country_ie_ignore = 0;
+int beacon_hints = 0;
+#endif
+
+/** Set configuration data of Tx power limitation */
+extern char *txpwrlimit_cfg;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+extern int p2p_enh;
+#endif
+#endif
+
+int cfg80211_drcs = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+int host_mlme = 0;
+#endif
+
+#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,
+};
+#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(char *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 NL802.11 channel type into driver channel type
+ *
+ * The mapping is as follows -
+ *      NL80211_CHAN_NO_HT     -> CHANNEL_BW_20MHZ
+ *      NL80211_CHAN_HT20      -> CHANNEL_BW_20MHZ
+ *      NL80211_CHAN_HT40PLUS  -> CHANNEL_BW_40MHZ_ABOVE
+ *      NL80211_CHAN_HT40MINUS -> CHANNEL_BW_40MHZ_BELOW
+ *      Others                 -> CHANNEL_BW_20MHZ
+ *
+ *  @param channel_type     Channel type
+ *
+ *  @return                 Driver channel type
+ */
+static int
+woal_cfg80211_channel_type_to_channel(enum nl80211_channel_type channel_type)
+{
+	int channel;
+
+	ENTER();
+
+	switch (channel_type) {
+	case NL80211_CHAN_NO_HT:
+	case NL80211_CHAN_HT20:
+		channel = CHANNEL_BW_20MHZ;
+		break;
+	case NL80211_CHAN_HT40PLUS:
+		channel = CHANNEL_BW_40MHZ_ABOVE;
+		break;
+	case NL80211_CHAN_HT40MINUS:
+		channel = CHANNEL_BW_40MHZ_BELOW;
+		break;
+	default:
+		channel = CHANNEL_BW_20MHZ;
+	}
+	LEAVE();
+	return channel;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ *  @brief get nl80211_channel_type from cfg80211_chan_def
+ *
+ *  @param chan_def     struct cfg80211_chan_def
+ *
+ *  @return                 nl80211_channel_type type
+ */
+static enum nl80211_channel_type
+woal_channel_to_nl80211_channel_type(struct cfg80211_chan_def *chan_def)
+{
+	enum nl80211_channel_type channel_type = 0;
+
+	ENTER();
+
+	switch (chan_def->width) {
+	case NL80211_CHAN_WIDTH_20:
+		/** Channel width 20MHz**/
+		channel_type = NL80211_CHAN_HT20;
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		/** Channel width 40MHz**/
+		if (chan_def->center_freq1 < chan_def->chan->center_freq)
+			channel_type = NL80211_CHAN_HT40MINUS;
+		else if (chan_def->center_freq1 > chan_def->chan->center_freq)
+			channel_type = NL80211_CHAN_HT40PLUS;
+		break;
+	default:
+		channel_type = NL80211_CHAN_HT20;
+		break;
+	}
+	LEAVE();
+	return channel_type;
+}
+#endif
+
+/**
+ *  @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_ADHOC:
+		return MLAN_BSS_MODE_IBSS;
+	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(hs20_oui))) {
+				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;
+}
+
+/**
+ * @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;
+	}
+
+	if (MTRUE ==
+	    is_cfg80211_special_region_code(priv->phandle->country_code)) {
+		PRINTM(MIOCTL,
+		       "skip region code config, cfg80211 special region code: %s\n",
+		       priv->phandle->country_code);
+		goto done;
+	}
+	PRINTM(MIOCTL, "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;
+
+	/* 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;
+	int chan_width = 0;
+
+	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;
+	chan_width = woal_cfg80211_channel_type_to_channel(channel_type);
+	/* 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);
+	}
+	/* Set channel offset */
+	radio_cfg->param.band_cfg.adhoc_chan_bandwidth = chan_width;
+
+	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, channel bandwidth %d and mode = %d channel=%d\n",
+	       config_bands, radio_cfg->param.band_cfg.adhoc_chan_bandwidth,
+	       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
+ */
+mlan_status
+woal_set_ewpa_mode(moal_private *priv, t_u8 wait_option,
+		   mlan_ssid_bssid *ssid_bssid)
+{
+	int ret = 0;
+	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) {
+		ret = -EOPNOTSUPP;
+		goto error;
+	}
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		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));
+	memcpy(&sec->param.passphrase.ssid, &ssid_bssid->ssid,
+	       sizeof(sec->param.passphrase.ssid));
+	memcpy(&sec->param.passphrase.bssid, &ssid_bssid->bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+	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 < 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 CFG80211_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
+			memcpy(&ts, scan_table[i].time_stamp, sizeof(ts));
+#endif
+			memcpy(&cap_info, &scan_table[i].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;
+
+	memcpy(&ie_buf[sizeof(IEEEtypes_Header_t)],
+	       &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
+	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();
+	if(country_ie_ignore){
+		LEAVE();
+		return 0;
+	}
+	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;
+	}
+
+	if ((priv->phandle->country_code[0] != country_ie[2]) ||
+		(priv->phandle->country_code[1] != country_ie[3])) {
+		t_u8 country_code[COUNTRY_CODE_LEN];
+		memset(country_code, 0, sizeof(country_code));
+		country_code[0] = country_ie[2];
+		country_code[1] = country_ie[3];
+		if (cntry_txpwr) {
+			if (MLAN_STATUS_SUCCESS !=
+				woal_request_country_power_table(priv,
+								 country_code))
+				PRINTM(MERROR, "Set power table failed!\n");
+		}
+	}
+
+	priv->phandle->country_code[0] = country_ie[2];
+	priv->phandle->country_code[1] = country_ie[3];
+	priv->phandle->country_code[2] = ' ';
+	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)));
+	memcpy((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));
+
+	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
+ */
+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));
+	memcpy(scan_req.ssid_list[0].ssid, conn_param->ssid,
+	       conn_param->ssid_len);
+	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++;
+			}
+		}
+	}
+	ret = woal_request_userscan(priv, wait_option, &scan_req);
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+	LEAVE();
+	return ret;
+
+}
+
+/*
+ * @brief check if secondary channs are available
+ *
+ * @param wiphy           A pointer to struct wiphy
+ * @param start_freq      start freq
+ * @param end_freq        end_freq
+ *
+ * @return                MTRUE-OK, MFALSE-channel not avaialble.
+ */
+static t_u8
+woal_is_secondary_chans_ok(struct wiphy *wiphy, u32 start_freq, u32 end_freq)
+{
+	struct ieee80211_channel *chan = NULL;
+	u32 freq;
+
+	for (freq = start_freq; freq <= end_freq; freq += 20) {
+		chan = ieee80211_get_channel(wiphy, freq);
+		if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
+			return MFALSE;
+	}
+
+	return MTRUE;
+}
+
+/*
+ * @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                MTRUE/MFALSE;
+ */
+t_u8
+woal_is_bw80_allowed(moal_private *priv, struct ieee80211_channel *channel)
+{
+	u32 start_freq = 0;
+	u32 end_freq = 0;
+	u32 freq = channel->center_freq;
+	/* 5 GHz, channels 36..48 */
+	if (freq >= 5180 && freq <= 5240) {
+		start_freq = 5180;
+		end_freq = 5240;
+	}
+	/* 5 GHz, channels 52..64 */
+	if (freq >= 5260 && freq <= 5320) {
+		start_freq = 5260;
+		end_freq = 5320;
+	}
+	/* 5 GHz, channels 100..112 */
+	if (freq >= 5500 && freq <= 5560) {
+		start_freq = 5500;
+		end_freq = 5560;
+	}
+	/* 5 GHz, channels 116..128 */
+	if (freq >= 5580 && freq <= 5640) {
+		start_freq = 5580;
+		end_freq = 5640;
+	}
+	/* 5 GHz, channels 132..144 */
+	if (freq >= 5660 && freq <= 5720) {
+		start_freq = 5660;
+		end_freq = 5720;
+	}
+	/* 5 GHz, channels 149..161 */
+	if (freq >= 5745 && freq <= 5805) {
+		start_freq = 5745;
+		end_freq = 5805;
+	}
+	if (start_freq && end_freq)
+		return woal_is_secondary_chans_ok(priv->wdev->wiphy, start_freq,
+						  end_freq);
+	return MTRUE;
+}
+
+#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
+ */
+void
+woal_save_assoc_params(moal_private *priv, struct cfg80211_assoc_request *req,
+		       mlan_ssid_bssid *ssid_bssid)
+{
+	ENTER();
+
+	if (req->bss->channel) {
+		priv->sme_current.channel = &priv->conn_chan;
+		memcpy(priv->sme_current.channel, req->bss->channel,
+		       sizeof(struct ieee80211_channel));
+	}
+	priv->sme_current.bssid = priv->conn_bssid;
+	memcpy((void *)priv->sme_current.bssid, req->bss->bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+	if (req->ie && req->ie_len) {
+		priv->sme_current.ie = kzalloc(req->ie_len, GFP_ATOMIC);
+		if(priv->sme_current.ie){
+			priv->sme_current.ie_len = req->ie_len;
+			memcpy((void *)priv->sme_current.ie, req->ie, req->ie_len);
+		}
+	}
+	memcpy(&priv->sme_current.crypto, &req->crypto,
+	       sizeof(struct cfg80211_crypto_settings));
+	priv->sme_current.flags = req->flags;
+	memcpy(&priv->sme_current.ht_capa, &req->ht_capa,
+	       sizeof(struct ieee80211_ht_cap));
+	memcpy(&priv->sme_current.ht_capa_mask, &req->ht_capa_mask,
+	       sizeof(struct ieee80211_ht_cap));
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	memcpy(&priv->sme_current.vht_capa, &req->vht_capa,
+	       sizeof(struct ieee80211_vht_cap));
+	memcpy(&priv->sme_current.vht_capa_mask, &req->vht_capa_mask,
+	       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);
+		memcpy((void *)priv->sme_current.ssid, ssid_bssid->ssid.ssid,
+		       ssid_bssid->ssid.ssid_len);
+		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
+ */
+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;
+		memcpy((t_u8 *)priv->sme_current.key, req->key, req->key_len);
+	}
+	LEAVE();
+}
+
+/**
+*  @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) {
+		LEAVE();
+		return -EFAULT;
+	}
+#endif
+
+	if (priv->wdev->iftype != NL80211_IFTYPE_STATION
+#if defined(WIFI_DIRECT_SUPPORT)
+	    && priv->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+		) {
+		PRINTM(MERROR,
+		       "Received infra auth request when interface not in infra mode\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	ssid_bssid = kzalloc(sizeof(mlan_ssid_bssid), GFP_ATOMIC);
+	if (!ssid_bssid) {
+		PRINTM(MERROR, "Fail to allocate ssid_bssid buffer\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	memcpy(ssid_bssid->bssid, req->bss->bssid, ETH_ALEN);
+	/* 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;
+		}
+	}
+	kfree(ssid_bssid);
+	if (priv->auth_flag & HOST_MLME_AUTH_PENDING) {
+		PRINTM(MERROR, "pending auth on going\n");
+		LEAVE();
+		return -EBUSY;
+	}
+	/** cancel pending scan */
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+
+#if defined(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 */
+	woal_cfg80211_mgmt_frame_register(wiphy, priv->wdev,
+					  IEEE80211_STYPE_AUTH, MTRUE);
+	woal_cfg80211_mgmt_frame_register(wiphy, priv->wdev,
+					  IEEE80211_STYPE_DEAUTH, MTRUE);
+	woal_cfg80211_mgmt_frame_register(wiphy, priv->wdev,
+					  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;
+	}
+
+	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)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (req->auth_type == NL80211_AUTHTYPE_SHARED_KEY && req->key) {
+		PRINTM(MINFO,"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)) {
+			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)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+#define AUTH_TX_DEFAULT_WAIT_TIME  1200
+	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;
+		memcpy(&(priv->phandle->chan), req->bss->channel, sizeof(struct ieee80211_channel));
+	}
+	else{
+		PRINTM(MMSG, "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 */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset, &pkt_type, sizeof(pkt_type));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+	       &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 = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_AUTH);
+    /**Authentication Frame: Destination Address*/
+	memcpy(mgmt->da, req->bss->bssid, ETH_ALEN);
+    /**Authentication Frame: Source Address*/
+	memcpy(mgmt->sa, priv->current_addr, ETH_ALEN);
+    /**Authentication Frame: BSSID*/
+	memcpy(mgmt->bssid, req->bss->bssid, ETH_ALEN);
+	memcpy(mgmt->addr4, addr, ETH_ALEN);
+
+#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]);
+		}
+		memcpy((t_u8 *)(&mgmt->u.auth.variable), req->auth_data + 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]);
+		}
+		memcpy((t_u8 *)(&mgmt->u.auth.variable), req->sae_data + 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 */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &packet_len,
+	       sizeof(packet_len));
+
+    /**Authentication Frame: Authentication Alg*/
+	mgmt->u.auth.auth_alg = 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;
+		}
+		memcpy((t_u8 *)varptr, req->ie, 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;
+	PRINTM(MCMND, "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);
+		ret = -EFAULT;
+		break;
+	}
+done:
+	if(ret){
+		woal_cfg80211_mgmt_frame_register(wiphy, priv->wdev,
+					  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)
+{
+	mlan_ds_misc_assoc_rsp assoc_rsp;
+	struct cfg80211_bss *bss = NULL;
+	moal_handle *handle = container_of(work, moal_handle, host_mlme_work);
+	moal_private *priv = (moal_private *)handle->host_mlme_priv;
+	unsigned long flags;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	handle->host_mlme_priv = NULL;
+	if (priv) {
+		if(priv->auth_flag & HOST_MLME_AUTH_DONE){
+			priv->auth_flag = 0;
+			woal_cfg80211_mgmt_frame_register(priv->wdev->wiphy,
+			priv->wdev,IEEE80211_STYPE_AUTH,MFALSE);
+			if(priv->phandle->remain_on_channel){
+				woal_cfg80211_remain_on_channel_cfg(priv, MOAL_NO_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);
+		}
+		if(priv->auth_flag & HOST_MLME_ASSOC_DONE) {
+			priv->auth_flag = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+			bss = cfg80211_get_bss(priv->wdev->wiphy, NULL,
+					       priv->conn_bssid, priv->conn_ssid,
+					       priv->conn_ssid_len,
+					       IEEE80211_BSS_TYPE_ESS,
+					       IEEE80211_PRIVACY_ANY);
+#else
+			bss = cfg80211_get_bss(priv->wdev->wiphy, NULL,
+					       priv->conn_bssid, priv->conn_ssid,
+					       priv->conn_ssid_len, WLAN_CAPABILITY_ESS,
+					       WLAN_CAPABILITY_ESS);
+#endif
+
+			if (!bss) {
+				PRINTM(MERROR, "HostMlme %s:Fail to get bss\n", priv->netdev->name);
+				return;
+			}
+
+			memset(&assoc_rsp, 0, sizeof(mlan_ds_misc_assoc_rsp));
+			woal_get_assoc_rsp(priv, &assoc_rsp, MOAL_IOCTL_WAIT);
+
+			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);
+					}
+			spin_unlock_irqrestore(&priv->connect_lock, flags);
+			mutex_lock(&priv->wdev->mtx);
+#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
+				mutex_unlock(&priv->wdev->mtx);
+			}
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+               cfg80211_put_bss(priv->wdev->wiphy, bss);
+#else
+               cfg80211_put_bss(bss);
+#endif
+		}
+	}
+}
+
+/**
+*  @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;
+
+	ENTER();
+
+	if (priv->auth_flag && !(priv->auth_flag & HOST_MLME_AUTH_DONE)) {
+		LEAVE();
+		return -EBUSY;
+	}
+
+	priv->cfg_connect = MTRUE;
+	priv->assoc_status = 0;
+
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+	rcu_read_lock();
+	ssid_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
+	memcpy(ssid_bssid.bssid, req->bss->bssid, ETH_ALEN);
+
+	if (!ssid_ie) {
+		rcu_read_unlock();
+		ret = -EINVAL;
+		goto done;
+	}
+
+	memcpy(ssid_bssid.ssid.ssid, ssid_ie + 2, ssid_ie[1]);
+	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(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 (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 */
+		ret = -EFAULT;
+		goto done;
+	}
+
+	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;
+		if (MTRUE != woal_is_bw80_allowed(priv, req->bss->channel))
+			ssid_bssid.channel_flags |= CHAN_FLAGS_NO_80MHZ;
+		PRINTM(MCMND,
+		       "channel flags=0x%x ssid_bssid.channel_flags=0x%x\n",
+		       req->bss->channel->flags, ssid_bssid.channel_flags);
+	}
+
+	PRINTM(MCMND, "HostMlme: Associate...\n");
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_start(priv, MOAL_IOCTL_WAIT_TIMEOUT, &ssid_bssid)) {
+		PRINTM(MERROR, "HostMlme: bss_start Fails\n");
+		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)
+			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, "HostMlme %s wlan: 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;
+		priv->phandle->host_mlme_priv = priv;
+		queue_work(priv->phandle->rx_workqueue, &priv->phandle->host_mlme_work);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+*  @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)
+{
+#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;
+	 }
+#endif
+	return woal_cfg80211_disconnect(wiphy, dev, req->reason_code);
+}
+
+/**
+*  @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)
+{
+#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;
+	}
+#endif
+	return woal_cfg80211_disconnect(wiphy, dev, req->reason_code);
+}
+#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;
+	enum nl80211_channel_type chan_type = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	struct cfg80211_chan_def *chan_def = NULL;
+#endif
+	struct ieee80211_channel *channel = NULL;
+	t_u16 beacon_interval = 0;
+	bool privacy;
+	struct cfg80211_bss *bss = 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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+		chan_type = ibss_param->channel_type;
+#else
+		chan_type = 0;
+#endif
+#else
+		chan_def = &ibss_param->chandef;
+		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)
+		bss = cfg80211_get_bss(priv->wdev->wiphy, channel, bssid, ssid,
+				       ssid_len, IEEE80211_BSS_TYPE_ESS,
+				       IEEE80211_PRIVACY_ANY);
+#else
+		bss = cfg80211_get_bss(priv->wdev->wiphy, channel, bssid, ssid,
+				       ssid_len, WLAN_CAPABILITY_ESS,
+				       WLAN_CAPABILITY_ESS);
+#endif
+		if (bss) {
+			if (!reg_alpha2 ||
+			    strncmp(reg_alpha2, "99", strlen("99")))
+				woal_process_country_ie(priv, bss);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+			cfg80211_put_bss(priv->wdev->wiphy, bss);
+#else
+			cfg80211_put_bss(bss);
+#endif
+		} else
+			woal_send_domain_info_cmd_fw(priv, wait_option);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(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;
+	}
+
+	memcpy(req_ssid.ssid, ssid, ssid_len);
+	if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
+		PRINTM(MERROR, "Invalid SSID - aborting\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if ((mode == MLAN_BSS_MODE_IBSS) && channel) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		chan_type = woal_channel_to_nl80211_channel_type(chan_def);
+#endif
+		if (MLAN_STATUS_SUCCESS != woal_set_rf_channel(priv,
+							       channel,
+							       chan_type,
+							       wait_option)) {
+			ret = -EFAULT;
+			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(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;
+		}
+	}
+	memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(mlan_802_11_ssid));
+	if (bssid)
+		memcpy(&ssid_bssid.bssid, bssid, ETH_ALEN);
+	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;
+		if (MTRUE != woal_is_bw80_allowed(priv, channel))
+			ssid_bssid.channel_flags |= CHAN_FLAGS_NO_80MHZ;
+		PRINTM(MCMND,
+		       "channel flags=0x%x ssid_bssid.channel_flags=0x%x\n",
+		       channel->flags, ssid_bssid.channel_flags);
+	}
+	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) {
+		memcpy(assoc_rsp, &ssid_bssid.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 */
+		woal_cfg80211_set_auth(priv, MLAN_ENCRYPTION_MODE_NONE, MFALSE,
+				       wait_option);
+		/* 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 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;
+	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
+	};
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	mlan_bss_info bss_info;
+	t_u8 dtim_period = 0;
+#endif
+
+	ENTER();
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	sinfo->filled =
+		BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES)
+		| BIT(NL80211_STA_INFO_RX_PACKETS) |
+		BIT(NL80211_STA_INFO_TX_PACKETS) | BIT(NL80211_STA_INFO_SIGNAL)
+		| BIT(NL80211_STA_INFO_TX_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 |= BIT(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;
+	}
+
+	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 (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;
+	}
+	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 |= BIT(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
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	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)
+{
+	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 (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", 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 creates custom regdomain
+ *
+ *  @param priv             pointer to moal_private
+ *  @param custom_reg         pointer to data structure mlan_ds_custom_reg_domain
+ *
+ *  @return                 N/A
+ */
+static struct ieee80211_regdomain *
+create_custom_regdomain(moal_private *priv, 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;
+	}
+
+#define MARVELL_CHANNEL_TMP_NOHT40 MBIT(15)
+	/* preprocess 2.4G 40MHz support */
+	for (idx = 0; idx < num_chan; idx++) {
+		chan = custom_reg->cfp_tbl[idx].channel;
+		if (!chan) {
+			if (regd)
+				kfree(regd);
+			return NULL;
+		}
+
+		if (chan > 14)
+			continue;
+
+		chflags = custom_reg->cfp_tbl[idx].dynamic.flags;
+
+		if (chflags & MARVELL_CHANNEL_DISABLED)
+			continue;
+
+		/* duplicate a temp flag */
+		if (chflags & MARVELL_CHANNEL_NOHT40)
+			chflags |= MARVELL_CHANNEL_TMP_NOHT40;
+	}
+
+	for (idx = 0; idx < num_chan; idx++) {
+		chan = custom_reg->cfp_tbl[idx].channel;
+		if (!chan) {
+			if (regd)
+				kfree(regd);
+			return NULL;
+		}
+
+		if (chan > 14)
+			continue;
+
+		chflags = custom_reg->cfp_tbl[idx].dynamic.flags;
+
+		if (chflags & MARVELL_CHANNEL_DISABLED)
+			continue;
+
+		/* 40 MHz band of one center channel will spread to upper and lower 2 channels */
+		/* Clear NOHT40 flag for all channels of this 40MHz Band */
+		if (!(chflags & MARVELL_CHANNEL_TMP_NOHT40)) {
+			if (idx >= 2)
+				custom_reg->cfp_tbl[idx - 2].dynamic.flags &=
+					~MARVELL_CHANNEL_NOHT40;
+			if (idx >= 1)
+				custom_reg->cfp_tbl[idx - 1].dynamic.flags &=
+					~MARVELL_CHANNEL_NOHT40;
+			if (idx < (num_chan - 1))
+				custom_reg->cfp_tbl[idx + 1].dynamic.flags &=
+					~MARVELL_CHANNEL_NOHT40;
+			if (idx < (num_chan - 2))
+				custom_reg->cfp_tbl[idx + 2].dynamic.flags &=
+					~MARVELL_CHANNEL_NOHT40;
+		} else {
+			custom_reg->cfp_tbl[idx].dynamic.flags &=
+				~MARVELL_CHANNEL_TMP_NOHT40;
+		}
+	}
+
+	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 & MARVELL_CHANNEL_DISABLED)
+			continue;
+
+		if (band == IEEE80211_BAND_5GHZ) {
+			if (!(chflags & MARVELL_CHANNEL_NOHT80))
+				bw = MHZ_TO_KHZ(80);
+			else if (!(chflags & MARVELL_CHANNEL_NOHT40))
+				bw = MHZ_TO_KHZ(40);
+			else
+				bw = MHZ_TO_KHZ(20);
+		} else {
+			if (!(chflags & MARVELL_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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		if (chflags & MARVELL_CHANNEL_PASSIVE)
+			rule->flags |= NL80211_RRF_NO_IR;
+#endif
+		if (chflags & MARVELL_CHANNEL_DFS)
+			rule->flags |= NL80211_RRF_DFS;
+		if (chflags & MARVELL_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] = priv->phandle->country_code[0];
+		regd->alpha2[1] = priv->phandle->country_code[1];
+	}
+	PRINTM(MCMND, "create_custom_regdomain: %c%c rules=%d\n",
+	       regd->alpha2[0], regd->alpha2[1], valid_rules);
+	for (idx = 0; idx < 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);
+	}
+	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]!= country_code[0]
+        || misc->param.custom_reg_domain.region.country_code[1]!= country_code[1]){
+        PRINTM(MMSG,"User country code %c%c FW country code %c%c\n", country_code[0],
+		country_code[1],
+		misc->param.custom_reg_domain.region.country_code[0],
+		misc->param.custom_reg_domain.region.country_code[1]);
+	}
+	regd = create_custom_regdomain(priv, &misc->param.custom_reg_domain);
+	if (regd) {
+		PRINTM(MMSG, "call regulatory_set_wiphy_regd %c%c",country_code[0],country_code[1]);
+		wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
+		wiphy->regulatory_flags &= ~(REGULATORY_STRICT_REG | REGULATORY_CUSTOM_REG);
+		regulatory_set_wiphy_regd(wiphy, regd);
+		kfree(regd);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#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
+
+	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(MIOCTL, "cfg80211 regulatory domain callback "
+	       "%c%c\n", request->alpha2[0], request->alpha2[1]);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (dfs_offload)
+		woal_update_radar_chans_dfs_state(wiphy);
+#endif
+	memset(region, 0, sizeof(region));
+	memcpy(region, request->alpha2, sizeof(request->alpha2));
+	region[2] = ' ';
+	if ((handle->country_code[0] != request->alpha2[0]) ||
+	    (handle->country_code[1] != request->alpha2[1])) {
+		if (cntry_txpwr) {
+			t_u8 country_code[COUNTRY_CODE_LEN];
+			handle->country_code[0] = request->alpha2[0];
+			handle->country_code[1] = request->alpha2[1];
+			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
+			}
+		}
+	}
+	if (MTRUE != is_cfg80211_special_region_code(region)) {
+		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");
+		break;
+	case NL80211_REGDOM_SET_BY_CORE:
+		PRINTM(MCMND, "Regulatory domain BY_CORE\n");
+		break;
+	case NL80211_REGDOM_SET_BY_USER:
+		PRINTM(MCMND, "Regulatory domain BY_USER\n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+		if (fw_region)
+			woal_update_custom_regdomain(priv, wiphy);
+		else
+#endif
+			regulatory_hint(wiphy, request->alpha2);
+		break;
+		/* TODO: apply driver specific changes in channel flags based
+		   on the request initiator if necessory. * */
+	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_IOCTL_WAIT or MOAL_NO_WAIT)
+ * @param bss_role      bss role
+ *
+ * @return         0 --success, otherwise fail
+ */
+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)
+		memcpy(&radio_cfg->param.band_cfg, band_cfg,
+		       sizeof(mlan_ds_band_cfg));
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto error;
+	}
+	memcpy(band_cfg, &radio_cfg->param.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
+ */
+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;
+}
+
+/**
+ *  @brief check if the scan result expired
+ *
+ *  @param priv         A pointer to moal_private
+ *
+ *
+ *  @return             MTRUE/MFALSE;
+ */
+t_u8
+woal_is_scan_result_expired(moal_private *priv)
+{
+	mlan_scan_resp scan_resp;
+	struct timeval t;
+	ENTER();
+	if (!woal_is_any_interface_active(priv->phandle)) {
+		LEAVE();
+		return MTRUE;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
+		LEAVE();
+		return MTRUE;
+	}
+	do_gettimeofday(&t);
+/** scan result expired value */
+#define SCAN_RESULT_EXPIRTED      1
+	if (t.tv_sec > (scan_resp.age_in_secs + SCAN_RESULT_EXPIRTED)) {
+		LEAVE();
+		return MTRUE;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+#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;
+	mlan_bss_info bss_info;
+	struct ieee80211_channel *chan;
+	int ret = 0, i;
+	unsigned long flags;
+
+	ENTER();
+
+	PRINTM(MINFO, "Received scan request on %s\n", dev->name);
+	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
+	if (priv->fake_scan_complete || !woal_is_scan_result_expired(priv)) {
+		PRINTM(MEVENT,
+		       "scan result not expired or fake scan complete flag is on\n");
+		return -EAGAIN;
+	}
+	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);
+
+	memset(&scan_req, 0x00, sizeof(scan_req));
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+	if (!is_broadcast_ether_addr(request->bssid)) {
+		memcpy(scan_req.specific_bssid, request->bssid, ETH_ALEN);
+		PRINTM(MIOCTL, "scan: bssid=" MACSTR "\n",
+		       MAC2STR(scan_req.specific_bssid));
+	}
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->phandle->miracast_mode ||
+	    woal_is_any_interface_active(priv->phandle))
+		scan_req.scan_chan_gap = priv->phandle->scan_chan_gap;
+	else
+		scan_req.scan_chan_gap = 0;
+#endif
+	for (i = 0; i < priv->phandle->scan_request->n_ssids; i++) {
+		memcpy(scan_req.ssid_list[i].ssid,
+		       priv->phandle->scan_request->ssids[i].ssid,
+		       priv->phandle->scan_request->ssids[i].ssid_len);
+		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 < 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;
+#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))
+			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)
+			scan_req.chan_list[i].scan_time =
+				MIN_SPECIFIC_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) {
+			LEAVE();
+			return ret;
+		} else {
+			PRINTM(MERROR, "Uap SCAN failure\n");
+			goto done;
+		}
+	}
+#endif
+	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);
+	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 */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset, &pkt_type, sizeof(pkt_type));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type), &tx_control,
+	       sizeof(tx_control));
+	/*Add packet len */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &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 = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_ACTION);
+	memcpy(mgmt->da, bssid, ETH_ALEN);
+	memcpy(mgmt->sa, priv->current_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, bssid, ETH_ALEN);
+	memcpy(mgmt->addr4, addr, ETH_ALEN);
+
+	mgmt->u.ft_req.category = 0x06;	/**ft action code 0x6*/
+	mgmt->u.ft_req.action = 0x1; /**ft action request*/
+	memcpy(mgmt->u.ft_req.sta_addr, priv->current_addr, ETH_ALEN);
+	memcpy(mgmt->u.ft_req.target_ap_addr, target_ap, ETH_ALEN);
+
+	if (ie && len)
+		memcpy((t_u8 *)(&mgmt->u.ft_req.variable), 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;
+
+	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 */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset, &pkt_type, sizeof(pkt_type));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type), &tx_control,
+	       sizeof(tx_control));
+	/*Add packet len */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &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 = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_AUTH);
+	memcpy(mgmt->da, bssid, ETH_ALEN);
+	memcpy(mgmt->sa, priv->current_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, bssid, ETH_ALEN);
+	memcpy(mgmt->addr4, addr, ETH_ALEN);
+
+	mgmt->u.auth.auth_alg = cpu_to_le16(WLAN_AUTH_FT);
+	mgmt->u.auth.auth_transaction = cpu_to_le16(1);
+	mgmt->u.auth.status_code = cpu_to_le16(0);
+	if (ie && len)
+		memcpy((t_u8 *)(&mgmt->u.auth.variable), 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;
+
+	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)
+{
+	struct wiphy *wiphy = priv->wdev->wiphy;
+	mlan_bss_info bss_info;
+#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;
+	}
+
+	if (!priv->ft_roaming_triggered_by_driver) {
+		wait_option = MOAL_IOCTL_WAIT;
+		memset(&bss_info, 0, sizeof(bss_info));
+		woal_get_bss_info(priv, wait_option, &bss_info);
+	}
+
+	if (priv->ft_roaming_triggered_by_driver || (priv->media_connected &&
+						     bss_info.mdid ==
+						     priv->ft_md &&
+						     bss_info.ft_cap ==
+						     priv->ft_cap)) {
+		ret = MTRUE;
+
+		/*enable auth register frame */
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		woal_cfg80211_mgmt_frame_register(wiphy, priv->netdev,
+						  IEEE80211_STYPE_AUTH, MTRUE);
+#else
+		woal_cfg80211_mgmt_frame_register(wiphy, priv->wdev,
+						  IEEE80211_STYPE_AUTH, MTRUE);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+#define AUTH_TX_DEFAULT_WAIT_TIME  1200
+		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");
+			memcpy(priv->target_ap_bssid, bssid, ETH_ALEN);
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		woal_cfg80211_remain_on_channel_cfg(priv, wait_option, MTRUE,
+						    &status, NULL, 0, 0);
+#endif
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		woal_cfg80211_mgmt_frame_register(wiphy, priv->netdev,
+						  IEEE80211_STYPE_AUTH, MFALSE);
+#else
+		woal_cfg80211_mgmt_frame_register(wiphy, priv->wdev,
+						  IEEE80211_STYPE_AUTH, MFALSE);
+#endif
+	}
+
+	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;
+	struct ieee80211_channel chan;
+	mlan_bss_info bss_info;
+	int ret = 0;
+	long timeout = 0;
+
+	ENTER();
+
+	if (!priv->ft_roaming_triggered_by_driver)
+		wait_option = MOAL_IOCTL_WAIT;
+
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, wait_option, &bss_info);
+	chan.band = (bss_info.bss_chan < 36) ?
+		IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	chan.center_freq = ieee80211_channel_to_frequency(bss_info.bss_chan
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+							  , chan.band
+#endif
+		);
+
+	if (priv->media_connected) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		woal_cfg80211_remain_on_channel_cfg(priv, wait_option, MFALSE,
+						    &status, &chan, 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");
+			memcpy(priv->target_ap_bssid, bssid, ETH_ALEN);
+		}
+#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
+		);
+
+	priv->ft_roaming_triggered_by_driver = MTRUE;
+	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;
+	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
+#if defined(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 && V14_FEATURE */
+		) {
+		PRINTM(MERROR,
+		       "Received infra assoc request when station not in infra mode\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	ssid_bssid = kzalloc(sizeof(mlan_ssid_bssid), GFP_ATOMIC);
+	if (!ssid_bssid) {
+		PRINTM(MERROR, "Fail to allocate ssid_bssid buffer\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	memcpy(ssid_bssid->ssid.ssid, sme->ssid, sme->ssid_len);
+	ssid_bssid->ssid.ssid_len = sme->ssid_len;
+	if (sme->bssid)
+		memcpy(ssid_bssid->bssid, sme->bssid, ETH_ALEN);
+	/* 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;
+		}
+	}
+	kfree(ssid_bssid);
+
+	/** cancel pending scan */
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+
+#if defined(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
+	/*Fast BSS Transition use ft-over-air */
+	if (priv->media_connected && priv->ft_ie_len &&
+	    !(priv->ft_cap & MBIT(0))) {
+		ret = woal_connect_ft_over_air(priv, (t_u8 *)sme->bssid,
+					       sme->channel);
+		if (ret == MTRUE) {
+			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;
+	}
+	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);
+		priv->ft_ie_len = 0;
+		priv->ft_pre_connect = MFALSE;
+		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);
+	long start_time;
+
+	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
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_disconnect in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (priv->cfg_disconnect) {
+		PRINTM(MERROR, "Disassociation already in progress\n");
+		LEAVE();
+		return 0;
+	}
+
+	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;
+	}
+
+	priv->cfg_disconnect = MTRUE;
+	start_time = jiffies;
+	if (woal_disconnect
+	    (priv, MOAL_IOCTL_WAIT_TIMEOUT, priv->cfg_bssid,
+	     reason_code) != MLAN_STATUS_SUCCESS) {
+		priv->cfg_disconnect = MFALSE;
+		LEAVE();
+		return -EFAULT;
+	}
+       /**Add delay to avoid auth failure after wps success */
+	if ((jiffies - start_time) < 1 * HZ)
+		woal_sched_timeout(1500);
+
+#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 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 t_u8 *mac,
+#else
+			  t_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;
+	}
+
+	memcpy(mac, priv->cfg_bssid, 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 bandcfg  Driver band configuration
+ *
+ *  @return         IEEE band type
+ */
+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 > scan_resp.num_in_chan_stats || idx < 0) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (idx == 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)
+/**
+ * @brief Function gets channel info from cfg80211
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param wdev            A pointer to wireless_dev structure
+ * @param chandef         A pointer to cfg80211_chan_def
+ *
+ * @return                0 -- success, otherwise fail
+ */
+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(MERROR, "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(MERROR,
+			       "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 Join the specified
+ * IBSS (or create if necessary)
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params          A pointer to cfg80211_ibss_params structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+			struct cfg80211_ibss_params *params)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+
+	ENTER();
+
+	if (priv->wdev->iftype != NL80211_IFTYPE_ADHOC) {
+		PRINTM(MERROR,
+		       "Request IBSS join received when station not in ibss mode\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	ret = woal_cfg80211_assoc(priv, (void *)params, MOAL_IOCTL_WAIT, NULL);
+
+	if (!ret) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
+				     params->chandef.chan, GFP_KERNEL);
+#else
+		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
+#endif
+		PRINTM(MINFO, "Joined/created adhoc network with bssid"
+		       MACSTR " successfully\n", MAC2STR(priv->cfg_bssid));
+	} else {
+		PRINTM(MINFO, "Failed creating/joining adhoc network\n");
+		memset(priv->cfg_bssid, 0, ETH_ALEN);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to leave the IBSS
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+	if (priv->cfg_disconnect) {
+		PRINTM(MERROR, "IBSS leave already in progress\n");
+		LEAVE();
+		return -EBUSY;
+	}
+
+	if (priv->media_connected == MFALSE) {
+		LEAVE();
+		return -EINVAL;
+	}
+
+	priv->cfg_disconnect = 1;
+
+	PRINTM(MINFO, "Leaving from IBSS " MACSTR "\n",
+	       MAC2STR(priv->cfg_bssid));
+	if (woal_disconnect
+	    (priv, MOAL_IOCTL_WAIT, priv->cfg_bssid,
+	     DEF_DEAUTH_REASON_CODE) != MLAN_STATUS_SUCCESS) {
+		priv->cfg_disconnect = 0;
+		LEAVE();
+		return -EFAULT;
+	}
+	priv->cfg_disconnect = 0;
+	memset(priv->cfg_bssid, 0, ETH_ALEN);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @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 (hw_test || (ps_mode == MLAN_INIT_PARA_DISABLED)) {
+		PRINTM(MIOCTL, "block set power hw_test=%d ps_mode=%d\n",
+		       hw_test, ps_mode);
+		LEAVE();
+		return -EFAULT;
+	}
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_set_power_mgmt in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+#if defined(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)) {
+		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 CFG80211_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
+	memcpy(&priv->phandle->chan, chan, sizeof(struct ieee80211_channel));
+
+	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;
+	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 < 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 (MLAN_STATUS_SUCCESS ==
+	    woal_request_bgscan(priv, MOAL_IOCTL_WAIT, &priv->scan_cfg)) {
+		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(MIOCTL, "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);
+					cfg80211_sched_scan_results(handle->
+								    priv[i]->
+								    wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+								    , 0
+#endif
+						);
+					rcu_read_lock();
+					cfg80211_sched_scan_stopped(priv->wdev->
+								    wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+								    , 0
+#endif
+						);
+					rcu_read_unlock();
+					handle->priv[i]->sched_scanning =
+						MFALSE;
+					handle->priv[i]->last_event = 0;
+					PRINTM(MIOCTL,
+					       "Report sched scan result in cfg80211 resume\n");
+				}
+				if (!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);
+
+#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->disconnect)
+			wakeup_report.disconnect = true;
+		break;
+	case MAGIC_PATTERN_MATCHED:
+		if (wiphy->wowlan_config->magic_pkt)
+			wakeup_report.magic_pkt = true;
+		if (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->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 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;
+
+	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;
+
+	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;
+	memcpy(misc->param.tdls_oper.peer_mac, peer, ETH_ALEN);
+	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;
+	memcpy(misc->param.tdls_ies.peer_mac, peer, ETH_ALEN);
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (tdls_ies)
+		memcpy(tdls_ies, &misc->param.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(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));
+		memcpy(pos, tdls_ies->ext_cap, 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)
+		memcpy(pos, basic_rates, rate_num);
+	else
+		memcpy(pos, basic_rates_5G, 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;
+	memcpy(pos, ext_rates, 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 = 24;
+	t_u8 wmmInfoIe_len = 7;
+	t_u8 len = 0;
+	t_u8 *pos;
+
+	if (skb_tailroom(skb) < wmmParamIe_len + 2)
+		return;
+
+	qosInfo = (pQosInfo == NULL) ? 0xf : (*pQosInfo);
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		pos = skb_put(skb, wmmParamIe_len + 2);
+		len = wmmParamIe_len;
+	} else {
+		pos = skb_put(skb, wmmInfoIe_len + 2);
+		len = wmmInfoIe_len;
+	}
+
+	*pos++ = wmm_id;
+	*pos++ = len;
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		memcpy(pos, wmmParamElement, sizeof(wmmParamElement));
+		pos += sizeof(wmmParamElement);
+	} else {
+		memcpy(pos, wmmInfoElement, sizeof(wmmInfoElement));
+		pos += sizeof(wmmInfoElement);
+	}
+	*pos++ = qosInfo;
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		*pos++ = reserved;
+		memcpy(pos, ac_be, sizeof(ac_be));
+		pos += sizeof(ac_be);
+		memcpy(pos, ac_bk, sizeof(ac_bk));
+		pos += sizeof(ac_bk);
+		memcpy(pos, ac_vi, sizeof(ac_vi));
+		pos += sizeof(ac_vi);
+		memcpy(pos, 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
+*/
+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
+*/
+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) {
+				memcpy(tdls_peer->peer_addr, peer, ETH_ALEN);
+				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 *tf;
+	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;
+
+	tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+	memcpy(tf->da, peer, ETH_ALEN);
+	memcpy(tf->sa, priv->current_addr, ETH_ALEN);
+	tf->ether_type = cpu_to_be16(MLAN_ETHER_PKT_TYPE_TDLS_ACTION);
+	tf->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);
+
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_REQUEST;
+		skb_put(skb, sizeof(tf->u.setup_req));
+		tf->u.setup_req.dialog_token = dialog_token;
+		tf->u.setup_req.capability = cpu_to_le16(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);
+
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
+
+		skb_put(skb, sizeof(tf->u.setup_resp));
+		tf->u.setup_resp.status_code = cpu_to_le16(status_code);
+		tf->u.setup_resp.dialog_token = dialog_token;
+		tf->u.setup_resp.capability = cpu_to_le16(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);
+
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
+
+		skb_put(skb, sizeof(tf->u.setup_cfm));
+		tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
+		tf->u.setup_cfm.dialog_token = dialog_token;
+
+		break;
+	case WLAN_TDLS_TEARDOWN:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_TEARDOWN;
+
+		skb_put(skb, sizeof(tf->u.teardown));
+		tf->u.teardown.reason_code = cpu_to_le16(status_code);
+		break;
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
+
+		skb_put(skb, sizeof(tf->u.discover_req));
+		tf->u.discover_req.dialog_token = dialog_token;
+		break;
+	default:
+		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]);
+			memcpy(pSupp_chan, tdls_ies->supp_chan,
+			       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]);
+			memcpy(pRegulatory_class, tdls_ies->regulatory_class,
+			       sizeof(IEEEtypes_Header_t) +
+			       tdls_ies->regulatory_class[1]);
+		}
+		woal_tdls_add_ext_capab(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));
+			memcpy(HTcap, tdls_ies->ht_cap,
+			       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));
+			memcpy(VHTcap, tdls_ies->vht_cap,
+			       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));
+			memcpy(AidInfo, tdls_ies->aid_info,
+			       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));
+			memcpy(HTInfo, tdls_ies->ht_info,
+			       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));
+			memcpy(vht_oprat, tdls_ies->vht_oprat,
+			       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);
+	memcpy(mgmt->da, peer, ETH_ALEN);
+	memcpy(mgmt->sa, priv->current_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
+
+	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_ACTION);
+	/* add address 4 */
+	pos = skb_put(skb, ETH_ALEN);
+
+	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.category,
+			1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
+		/** init address 4 */
+		memcpy(pos, addr, ETH_ALEN);
+
+		woal_add_supported_rates_ie(priv, skb, band);
+		woal_add_ext_supported_rates_ie(priv, skb, band);
+		woal_tdls_add_ext_capab(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]);
+			memcpy(pSupp_chan, tdls_ies->supp_chan,
+			       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]);
+			memcpy(pRegulatory_class, tdls_ies->regulatory_class,
+			       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(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;
+
+	memcpy(lnkid->bssid, bssid, ETH_ALEN);
+	memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
+	memcpy(lnkid->resp_sta, peer, ETH_ALEN);
+}
+
+/**
+ * @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));
+	memcpy(pos, &pkt_type, sizeof(pkt_type));
+	memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
+
+	woal_construct_tdls_action_frame(priv, peer, action_code,
+					 dialog_token, status_code, skb);
+
+	if (extra_ies_len)
+		memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
+
+	/* the TDLS link IE is always added last */
+	/* we are the responder */
+	woal_tdls_add_link_ie(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);
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &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)
+		memcpy(skb_put(skb, extra_ies_len), extra_ies, 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(skb, priv->current_addr, peer,
+				      priv->cfg_bssid);
+		break;
+	case WLAN_TDLS_SETUP_RESPONSE:
+		/* we are the responder */
+		woal_tdls_add_link_ie(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);
+		memcpy(event_buf, CUS_EVT_TDLS_CONNECTED, custom_len);
+		memcpy(event_buf + custom_len, peer, ETH_ALEN);
+		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);
+		memcpy(event_buf, CUS_EVT_TDLS_TEARDOWN, custom_len);
+		memcpy(event_buf + custom_len, peer, ETH_ALEN);
+		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;
+	memcpy(tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr, addr, ETH_ALEN);
+	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;
+	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_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;
+	memcpy(tdls_data->tdls_data, addr, ETH_ALEN);
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		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)
+/**
+ * @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 (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
+
+#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;
+	memset(priv->ft_ie, 0, MAX_IE_SIZE);
+	memcpy(priv->ft_ie, ftie->ie, MIN(ftie->ie_len, MAX_IE_SIZE));
+	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;
+	memcpy((void *)priv->sme_current.bssid, &priv->target_ap_bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+	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)
+			memset(&roam_info, 0,
+			       sizeof(struct cfg80211_roam_info));
+			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));
+			priv->ft_ie_len = 0;
+		}
+		priv->ft_roaming_triggered_by_driver = MFALSE;
+
+	} else {
+		PRINTM(MMSG, "Fast BSS Transition use ft-over-air\n");
+		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->cfg_bssid));
+			cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
+						NULL, 0, NULL, 0,
+						woal_get_assoc_status(priv),
+						GFP_KERNEL);
+			memset(priv->cfg_bssid, 0, ETH_ALEN);
+			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);
+	memcpy(&priv->sme_current, sme, sizeof(struct cfg80211_connect_params));
+	if (sme->channel) {
+		priv->sme_current.channel = &priv->conn_chan;
+		memcpy(priv->sme_current.channel, sme->channel,
+		       sizeof(struct ieee80211_channel));
+	}
+	if (sme->bssid) {
+		priv->sme_current.bssid = priv->conn_bssid;
+		memcpy((void *)priv->sme_current.bssid, sme->bssid,
+		       MLAN_MAC_ADDR_LENGTH);
+	}
+	if (sme->ssid && sme->ssid_len) {
+		priv->sme_current.ssid = priv->conn_ssid;
+		memset(priv->conn_ssid, 0, MLAN_MAX_SSID_LENGTH);
+		memcpy((void *)priv->sme_current.ssid, sme->ssid,
+		       sme->ssid_len);
+	}
+	if (sme->ie && sme->ie_len) {
+		priv->sme_current.ie = kzalloc(sme->ie_len, GFP_KERNEL);
+		memcpy((void *)priv->sme_current.ie, sme->ie, sme->ie_len);
+	}
+	if (sme->key && sme->key_len && (sme->key_len <= MAX_WEP_KEY_SIZE)) {
+		priv->sme_current.key = priv->conn_wep_key;
+		memcpy((t_u8 *)priv->sme_current.key, sme->key, sme->key_len);
+	}
+}
+
+/**
+ * @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;
+	LEAVE();
+}
+
+/**
+ * @brief Build new roaming connect ie for okc
+ *
+ * @param priv            A pointer to moal_private
+ * @param entry           A pointer to pmksa_entry
+ **/
+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);
+
+			memcpy(okc_ie_pos, sme_pos, 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);
+			memcpy(okc_ie_pos, entry->pmkid, 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);
+					memcpy(okc_ie_pos, sme_ptr,
+					       (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 {
+			memcpy(okc_ie_pos, sme_pos, 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;
+	memcpy(ssid_bssid.ssid.ssid, priv->sme_current.ssid,
+	       priv->sme_current.ssid_len);
+	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)) {
+		woal_start_ft_roaming(priv, &ssid_bssid);
+		goto done;
+	}
+	/* start roaming to new AP */
+	priv->sme_current.bssid = priv->conn_bssid;
+	memcpy((void *)priv->sme_current.bssid, &ssid_bssid.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	if (IS_STA_CFG80211(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, "Fail 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(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)
+		memset(&roam_info, 0, sizeof(struct cfg80211_roam_info));
+		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;
+	mlan_ds_bss *bss = NULL;
+	t_u8 *pos;
+	t_u8 qosinfo;
+	MrvlIEtypes_Data_t *tlv;
+	mlan_status status;
+	int ret = 0;
+
+	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_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;
+	memcpy(bss->param.sta_info.peer_mac, mac, MLAN_MAC_ADDR_LENGTH);
+	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 CFG80211_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;
+		memcpy(tlv->data, params->ext_capab, 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;
+		memcpy(tlv->data, params->supported_rates, 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);
+		memcpy(tlv->data, &qosinfo, 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);
+		memcpy(tlv->data, params->ht_capa, 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);
+		memcpy(tlv->data, params->vht_capa, 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 CFG80211_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);
+		memcpy(tlv->data, &params->opmode_notif, 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
+	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 reason_code  disconnect reason code
+ *  @return     N/A
+ */
+void
+woal_host_mlme_disconnect(moal_private *priv, t_u16 reason_code)
+{
+	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 = IEEE80211_STYPE_DEAUTH;
+	mgmt->duration = 0;
+	mgmt->seq_ctrl = 0;
+	mgmt->u.deauth.reason_code = reason_code;
+	memcpy(mgmt->da, broadcast_addr, ETH_ALEN);
+	memcpy(mgmt->sa, priv->sme_current.ssid, ETH_ALEN);
+	memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
+#if CFG80211_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
+	priv->host_mlme = MFALSE;
+	priv->auth_flag = 0;
+	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;
+
+	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;
+	}
+#if defined(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;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Initialize the wiphy
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param wait_option     Wait option
+ *
+ * @return                MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_cfg80211_init_wiphy(moal_private *priv, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int retry_count, rts_thr, frag_thr;
+	struct wiphy *wiphy = NULL;
+	mlan_ioctl_req *req = NULL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	mlan_ds_radio_cfg *radio = NULL;
+#endif
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	t_u32 hw_dev_cap;
+#ifdef UAP_SUPPORT
+	mlan_uap_bss_param *sys_cfg = NULL;
+#endif
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 0, 0)
+	t_u16 enable = 0;
+#endif
+
+	ENTER();
+
+	wiphy = priv->phandle->wiphy;
+	/* 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])
+		woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_2GHZ]->
+					   ht_cap, hw_dev_cap,
+					   cfg_11n->param.supported_mcs_set);
+	/* For 2.4G band only card, this shouldn't be set */
+	if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
+		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
+	}
+	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 */
+	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;
+			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;
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 0, 0)
+	/* Enable multi-channel by default if multi-channel is supported */
+	if (cfg80211_iface_comb_ap_sta.num_different_channels > 1)
+		enable = 1;
+	if (priv->phandle->card_info->drcs)
+		ret = woal_mc_policy_cfg(priv, &enable, wait_option,
+					 MLAN_ACT_SET);
+#endif
+
+done:
+	LEAVE();
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	return ret;
+}
+
+/*
+ * 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;
+	int index = 0;
+
+	ENTER();
+
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+
+	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 (host_mlme) {
+		woal_cfg80211_ops.auth = woal_cfg80211_authenticate;
+		woal_cfg80211_ops.assoc = woal_cfg80211_associate;
+		woal_cfg80211_ops.deauth = woal_cfg80211_deauthenticate;
+		woal_cfg80211_ops.disassoc = woal_cfg80211_disassociate;
+		woal_cfg80211_ops.probe_client = woal_cfg80211_probe_client;
+	}
+#endif
+#ifdef CONFIG_PM
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+	wiphy->wowlan = &wowlan_support;
+#else
+	wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT;
+	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_ADHOC) | MBIT(NL80211_IFTYPE_AP);
+
+#if defined(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) {
+		wiphy->bands[IEEE80211_BAND_5GHZ] = &cfg80211_band_5ghz;
+		priv->phandle->band = IEEE80211_BAND_5GHZ;
+	}
+	/* Supported bands */
+	if (fw_info.fw_bands & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
+		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 (!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;
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	if (cfg80211_drcs && priv->phandle->card_info->drcs) {
+		cfg80211_iface_comb_ap_sta.num_different_channels = 2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		cfg80211_iface_comb_ap_sta.radar_detect_widths = 0;
+#endif
+	}
+	/* Initialize interface combinations */
+	wiphy->iface_combinations = &cfg80211_iface_comb_ap_sta;
+	wiphy->n_iface_combinations = 1;
+#endif
+
+	memcpy(wiphy->perm_addr, priv->current_addr, ETH_ALEN);
+	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 (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 (!host_mlme)
+#endif
+		wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#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,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(3,4,0)
+	wiphy->features |= NL80211_FEATURE_HT_IBSS;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,8,0)
+	if (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(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 (host_mlme)
+		wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
+#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 (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 (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
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	if (fw_region && txpwrlimit_cfg)
+		wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
+	else
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		wiphy->regulatory_flags |=
+			REGULATORY_STRICT_REG | REGULATORY_CUSTOM_REG;
+#endif
+	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
+	if (wiphy_register(wiphy) < 0) {
+		PRINTM(MERROR, "Wiphy device registration failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err_wiphy;
+	}
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (!p2p_enh)
+		wiphy->interface_modes &= ~(MBIT(NL80211_IFTYPE_P2P_GO) |
+					    MBIT(NL80211_IFTYPE_P2P_CLIENT));
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	if (fw_region && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED
+	    && txpwrlimit_cfg) {
+		PRINTM(MCMND, "FW region_code=%d\n", fw_info.region_code);
+		country = region_code_2_string(fw_info.region_code);
+		if (country) {
+			memcpy(priv->phandle->country_code, country, 2);
+			woal_update_custom_regdomain(priv, wiphy);
+		}
+	}
+#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 (!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 (!disable_regd_by_driver)
+						regulatory_hint(wiphy, country);
+				}
+			}
+		}
+	}
+	priv->phandle->wiphy = wiphy;
+	woal_cfg80211_init_wiphy(priv, MOAL_IOCTL_WAIT);
+	return ret;
+err_wiphy:
+	if (wiphy)
+		wiphy_free(wiphy);
+	LEAVE();
+	return ret;
+}
+
+module_param(cfg80211_drcs, int, 0);
+MODULE_PARM_DESC(cfg80211_drcs,
+		 "1: Enable DRCS support; 0: Disable DRCS support");
+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
+#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
diff --git a/wlan_sd8987/mlinux/moal_sta_cfg80211.h b/wlan_sd8987/mlinux/moal_sta_cfg80211.h
new file mode 100644
index 0000000..9c98731
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_sta_cfg80211.h
@@ -0,0 +1,42 @@
+/** @file moal_sta_cfg80211.h
+  *
+  * @brief This file contains the STA CFG80211 specific defines.
+  *
+  * Copyright (C) 2014-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _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);
+
+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);
+
+#endif /* _MOAL_STA_CFG80211_H_ */
diff --git a/wlan_sd8987/mlinux/moal_uap.c b/wlan_sd8987/mlinux/moal_uap.c
new file mode 100644
index 0000000..39b6fdc
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap.c
@@ -0,0 +1,4232 @@
+/** @file moal_uap.c
+  *
+  * @brief This file contains the major functions in UAP
+  * driver.
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include    "moal_main.h"
+#include    "moal_uap.h"
+#include    "moal_sdio.h"
+#include    "moal_eth_ioctl.h"
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#include    "moal_cfg80211.h"
+#endif
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+extern int host_mlme;
+#endif
+/********************************************************
+		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;
+	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;
+	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);
+	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 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;
+}
+
+/**
+ *  @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);
+		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;
+		}
+		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);
+		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;
+		}
+	}
+	/* 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;
+}
+
+/**
+ *  @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) > 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;
+		memcpy(cfg11d->param.domain_tlv, tlv,
+		       MIN(MAX_IE_SIZE, (TLV_HEADER_LEN + tlv_data_len)));
+	}
+	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;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ *  @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;
+		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;
+		priv->phandle->cac_period_jiffies =
+			param.usr_cac_period * HZ / 1000;
+		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;
+		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;
+	}
+	/* 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;
+	memcpy(&ds_11hcfg->param.ch_nop_info, ch_info,
+	       sizeof(mlan_ds_11h_chan_nop_info));
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_FAILURE) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memcpy(ch_info, &ds_11hcfg->param.ch_nop_info,
+	       sizeof(mlan_ds_11h_chan_nop_info));
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+#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);
+	memcpy(vhtcfg, &cfg_11ac->param.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++;
+		memcpy(vhtcfg, &cfg_11ac->param.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
+ *  @invoke_hostcmd Argument
+ *
+ *  @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 dev          A pointer to net_device structure
+ *  @param req          A pointer to ifreq 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 > 3)) {
+			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_VHT)
+				) {
+				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))
+					) {
+					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.user_data_cnt == 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;
+			}
+		}
+	}
+
+	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)
+				tx_rate_config.nss = rate->param.rate_cfg.nss;
+		}
+		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;
+	}
+
+	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;
+	case UAP_SDCMD52_RW:
+		ret = woal_uap_sdcmd52_rw(dev, req);
+		break;
+	case UAP_SNMP_MIB:
+		ret = woal_uap_snmp_mib(dev, req);
+		break;
+#ifdef DFS_TESTING_SUPPORT
+	case UAP_DFS_TESTING:
+		ret = woal_uap_dfs_testing(dev, req);
+		break;
+#endif
+	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;
+	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;
+
+	memcpy(&bss->param.deauth_param, &deauth_param,
+	       sizeof(mlan_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;
+	memcpy(sec->param.sta_mac, mac_addr, MLAN_MAC_ADDR_LENGTH);
+
+	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;
+
+	memcpy(sec->param.encrypt_key.mac_addr, key.mac_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+	sec->param.encrypt_key.key_index = key.key_index;
+	sec->param.encrypt_key.key_len = key.key_len;
+	memcpy(sec->param.encrypt_key.key_material, key.key_material,
+	       key.key_len);
+	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)
+		memcpy(&pm_cfg->param.ps_mgmt, ps_mgmt,
+		       sizeof(mlan_ds_ps_mgmt));
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (action == MLAN_ACT_GET)
+			memcpy(ps_mgmt, &pm_cfg->param.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;
+	}
+
+	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;
+		memcpy(&pm_cfg->param.ps_mgmt, &ps_mgmt,
+		       sizeof(mlan_ds_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,
+		     sizeof(mlan_ds_sta_list))) {
+			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;
+	memcpy(sec->param.encrypt_key.mac_addr, key_msg->mac_addr, ETH_ALEN);
+	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;
+	memcpy(sec->param.encrypt_key.key_material, key_msg->key,
+	       sec->param.encrypt_key.key_len);
+
+	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) {
+		memcpy(misc->param.gen_ie.ie_data, wapi_psk_ie,
+		       misc->param.gen_ie.len);
+	} else if (msg->msg[0] & WAPI_MODE_CERT) {
+		memcpy(misc->param.gen_ie.ie_data, wapi_cert_ie,
+		       misc->param.gen_ie.len);
+	} 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)
+		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
+ */
+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;
+	}
+	memcpy(sys_cfg, &info->param.bss_config, 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_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 = 0x20;
+		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 = 0x6f;
+		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();
+	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;
+		sys_cfg->supported_mcs_set[4] = 0x01;
+		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();
+
+	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;
+	}
+	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 Parse AP configuration from ASCII string
+ *
+ *  @param ap_cfg   A pointer to mlan_uap_bss_param structure
+ *  @param buf      A pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_uap_ap_cfg_parse_data(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);
+				memcpy(ap_cfg->wep_cfg.key0.key, value,
+				       MIN(sizeof(ap_cfg->wep_cfg.key0.key),
+					   strlen(value)));
+				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);
+			memcpy(ap_cfg->wpa_cfg.passphrase, value,
+			       MIN(sizeof(ap_cfg->wpa_cfg.passphrase),
+				   strlen(value)));
+			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);
+	memcpy(buf, data, MIN(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(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
+ */
+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;
+
+	memcpy(&bss->param.ap_scan_channels, scan_channels,
+	       sizeof(mlan_uap_scan_channels));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		memcpy(scan_channels, &bss->param.ap_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;
+
+	memcpy(&bss->param.ap_channel, uap_channel, sizeof(chan_band_info));
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		memcpy(uap_channel, &bss->param.ap_channel,
+		       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
+ */
+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
+ */
+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)
+			   || 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");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		bss->sub_command = MLAN_OID_BSS_START;
+		if (priv->uap_host_based) {
+			bss->param.host_based |= UAP_FLAG_HOST_BASED;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			if (host_mlme)
+				bss->param.host_based |= UAP_FLAG_HOST_MLME;
+#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);
+		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
+ */
+int
+woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	int ret = 0;
+	ENTER();
+	PRINTM(MIOCTL, "uap_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 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)
+			memcpy(ustats, &info->param.ustats,
+			       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)
+		memcpy(&bss->param.ap_wmm_para, ap_wmm_para,
+		       sizeof(wmm_parameter_t));
+
+	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)
+		memcpy(ap_wmm_para, &bss->param.ap_wmm_para,
+		       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)
+		memcpy(&bss->param.bss_config, sys_cfg,
+		       sizeof(mlan_uap_bss_param));
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (action == MLAN_ACT_GET)
+		memcpy(sys_cfg, &bss->param.bss_config,
+		       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 100644
index 0000000..e9dabd4
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap.h
@@ -0,0 +1,546 @@
+/** @file moal_uap.h
+  *
+  * @brief This file contains uap driver specific defines etc.
+  *
+  * Copyright (C) 2009-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+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
+/** sdcmd52 read write subcommand */
+#define UAP_SDCMD52_RW      6
+/** 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
+#ifdef DFS_TESTING_SUPPORT
+/** dfs testing subcommand */
+#define UAP_DFS_TESTING     10
+#endif
+/** 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
+
+/** 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
+
+/** TX rate cfg structure */
+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];
+} 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;
+
+/** CAC timer status structure */
+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;
+
+/** Packet inject command ioctl number */
+/** 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)
+#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 _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;
+} addba_param;
+
+/** aggr_prio_tbl */
+typedef struct _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];
+} 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 _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;
+} fw_info;
+
+/** HT TX cfg header parameter structure */
+typedef struct _ht_tx_cfg_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} ht_tx_cfg_para_hdr;
+
+/** TX beamformer parameter header structure */
+typedef struct _tx_bf_cfg_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} tx_bf_cfg_para_hdr;
+
+/** VHT cfg parameter header structure */
+typedef struct _vht_cfg_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} vht_cfg_para_hdr;
+
+/** UAP operation parameter header structure */
+typedef struct _uap_oper_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} uap_oper_para_hdr;
+
+/** 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;
+
+/** 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;
+
+/** 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;
+
+/** SNMP mib parameter structure */
+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[0];
+} 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
+
+#ifdef DFS_TESTING_SUPPORT
+/** 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;
+} dfs_testing_para;
+#endif
+
+/** 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[0];
+} 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);
+int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+int woal_uap_bss_ctrl(moal_private *priv, t_u8 wait_option, int data);
+#ifdef UAP_CFG80211
+#if defined(DFS_TESTING_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+int woal_uap_get_channel_nop_info(moal_private *priv, t_u8 wait_option,
+				  mlan_ds_11h_chan_nop_info * ch_info);
+#endif
+#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,
+			       mlan_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(mlan_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_set_uap_ht_tx_cfg(moal_private *priv, Band_Config_t bandcfg, 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, mlan_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 100644
index 0000000..f0a8598
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_cfg80211.c
@@ -0,0 +1,3147 @@
+/** @file moal_uap_cfg80211.c
+  *
+  * @brief This file contains the functions for uAP CFG80211.
+  *
+  * Copyright (C) 2011-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include "moal_cfg80211.h"
+#include "moal_uap_cfg80211.h"
+/** deauth reason code */
+#define  REASON_CODE_DEAUTH_LEAVING 3
+/********************************************************
+				Local Variables
+********************************************************/
+
+/********************************************************
+				Global Variables
+********************************************************/
+#ifdef WIFI_DIRECT_SUPPORT
+extern int GoAgeoutTime;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+#ifdef UAP_SUPPORT
+extern int uap_max_sta;
+#endif
+/********************************************************
+				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;
+
+	memcpy(bss->param.deauth_param.mac_addr, mac_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+	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 all station
+ *
+ * @param priv            A pointer to moal_private structure
+ *
+ * @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 IEEEtypes_Rsn_t structure
+ * @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 < 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 = 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 < 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 = le16_to_cpu(key_mgmt->count);
+	if (left <
+	    (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 < 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 = 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 < 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 = le16_to_cpu(key_mgmt->count);
+	if (left <
+	    (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 ie              Pointer IE buffer
+ * @param sys_config      Pointer to mlan_uap_bss_param structure
+ *
+ * @return                N/A
+ */
+static t_void
+woal_set_wmm_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;
+	IEEEtypes_VendorSpecific_t *pvendor_ie;
+	IEEEtypes_ElementId_e element_id;
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	t_u8 *poui;
+
+	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;
+			poui = pvendor_ie->vend_hdr.oui;
+			if (!memcmp(poui, wmm_oui, sizeof(wmm_oui))) {
+				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.
+					 */
+					memcpy(&sys_config->wmm_para,
+					       pcurrent_ptr +
+					       sizeof(IEEEtypes_Header_t),
+					       element_len);
+				}
+			}
+
+			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 params          A pointer to cfg80211_ap_settings structure
+ * @return                0 -- success, otherwise fail
+ */
+t_u8
+woal_check_11ac_capability(moal_private *priv,
+			   struct cfg80211_ap_settings *params)
+#else
+/**
+ * @brief initialize AP or GO bss config
+ * @param priv            A pointer to moal private structure
+ * @return                0 -- success, otherwise fail
+ */
+t_u8
+woal_check_11ac_capability(moal_private *priv)
+#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();
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (!(fw_info.fw_bands & BAND_AAC)) {
+		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;
+}
+
+/**
+ * @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;
+}
+
+#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 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(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(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(&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 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(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));
+		memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
+		rate_len = rate_ie->len;
+	}
+	ext_rate_ie =
+		(void *)woal_parse_ie_tlv(tail_ie, tail_len,
+					  WLAN_EID_EXT_SUPP_RATES);
+	if (ext_rate_ie) {
+		memcpy(&bss_cfg->rates[rate_len], ext_rate_ie + 1,
+		       ext_rate_ie->len);
+		rate_len += ext_rate_ie->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;
+	t_u8 *wapi_ie = NULL;
+	int wapi_ie_len = 0;
+#if defined(DFS_TESTING_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	mlan_ds_11h_chan_nop_info chan_nop_info;
+	Band_Config_t bandcfg;
+#endif
+#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;
+		woal_set_get_gen_ie(priv, MLAN_ACT_SET, wapi_ie, &wapi_ie_len,
+				    MOAL_IOCTL_WAIT);
+	}
+	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 (uap_max_sta)
+		sys_config->max_sta_count = 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;
+	memcpy(sys_config->mac_addr, priv->current_addr, ETH_ALEN);
+
+#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 */
+	memcpy(&priv->chan, &params->chandef, sizeof(struct cfg80211_chan_def));
+#endif
+
+#if defined(DFS_TESTING_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	PRINTM(MCMND, "Checking if AP's channel %d is under NOP\n",
+	       priv->channel);
+	woal_convert_chan_to_bandconfig(&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
+#endif
+
+	if (priv->channel) {
+		woal_check_mc_connection(priv, MOAL_IOCTL_WAIT, 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->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)
+				memcpy(sys_config->rates, rates_wfd,
+				       sizeof(rates_wfd));
+			else
+#endif
+				memcpy(sys_config->rates, rates_bg,
+				       sizeof(rates_bg));
+		} else {
+			sys_config->bandcfg.chanBand = BAND_5GHZ;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+			chan2Offset =
+				woal_get_second_channel_offset(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->
+								       channel);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			enable_11ac = woal_check_11ac_capability(priv, 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);
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+				memcpy(sys_config->rates, rates_wfd,
+				       sizeof(rates_wfd));
+			else
+#endif
+				memcpy(sys_config->rates, rates_a,
+				       sizeof(rates_a));
+		}
+
+		/* Replaced with rate from userspace, if exist */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+		woal_set_uap_rates(sys_config, params->beacon.head,
+				   params->beacon.head_len, params->beacon.tail,
+				   params->beacon.tail_len);
+#else
+		woal_set_uap_rates(sys_config, params->head, params->head_len,
+				   params->tail, params->tail_len);
+#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;
+		}
+		if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			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;
+	}
+	memcpy(sys_config->ssid.ssid, params->ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len));
+	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;
+			memcpy(&sys_config->wep_cfg.key0, &priv->uap_wep_key[0],
+			       sizeof(wep_key));
+			memcpy(&sys_config->wep_cfg.key1, &priv->uap_wep_key[1],
+			       sizeof(wep_key));
+			memcpy(&sys_config->wep_cfg.key2, &priv->uap_wep_key[2],
+			       sizeof(wep_key));
+			memcpy(&sys_config->wep_cfg.key3, &priv->uap_wep_key[3],
+			       sizeof(wep_key));
+		}
+		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;
+	}
+	memcpy(sys_config->ssid.ssid, ssid_ie + 2, *(ssid_ie + 1));
+	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;
+		memcpy(&sys_config->wep_cfg.key0, &priv->uap_wep_key[0],
+		       sizeof(wep_key));
+		memcpy(&sys_config->wep_cfg.key1, &priv->uap_wep_key[1],
+		       sizeof(wep_key));
+		memcpy(&sys_config->wep_cfg.key2, &priv->uap_wep_key[2],
+		       sizeof(wep_key));
+		memcpy(&sys_config->wep_cfg.key3, &priv->uap_wep_key[3],
+		       sizeof(wep_key));
+	} 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 (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		/*find and set wmm ie */
+		woal_set_wmm_ies(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, MFALSE);
+		woal_uap_set_11n_status(priv, sys_config, MLAN_ACT_DISABLE);
+	} else {
+		woal_set_uap_ht_tx_cfg(priv, sys_config->bandcfg, 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 (sys_config->bandcfg.chanBand == BAND_5GHZ) {
+		if (enable_11ac && enable_11n) {
+			vhtcap_ie = woal_get_vhtcap_info(ie, ie_len);
+			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 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;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	woal_enable_dfs_support(priv, &priv->chan);
+#endif
+done:
+	kfree(sys_config);
+	LEAVE();
+	return ret;
+}
+
+#if defined(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
+ */
+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
+ */
+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 = (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;
+
+	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);
+	ret = register_netdevice(ndev);
+	if (ret) {
+		handle->priv[new_priv->bss_index] = NULL;
+		handle->priv_num--;
+		if (ndev->reg_state == NETREG_REGISTERED) {
+			unregister_netdevice(ndev);
+			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);
+#ifdef PROC_DEBUG
+	woal_debug_entry(new_priv);
+#endif /* PROC_DEBUG */
+#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
+ */
+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);
+
+	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;
+			}
+		}
+	}
+
+	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
+		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
+#ifdef PROC_DEBUG
+		/* Remove proc debug */
+		woal_debug_remove(vir_priv);
+#endif /* PROC_DEBUG */
+		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)
+			unregister_netdevice(dev);
+	}
+	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
+#ifdef PROC_DEBUG
+				/* Remove proc debug */
+				woal_debug_remove(priv);
+#endif /* PROC_DEBUG */
+				woal_proc_remove(priv);
+#endif /* CONFIG_PROC_FS */
+				netif_device_detach(priv->netdev);
+				if (priv->netdev->reg_state ==
+				    NETREG_REGISTERED)
+					unregister_netdevice(priv->netdev);
+				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) {
+#if defined(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;
+	}
+#if defined(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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	t_u8 wait_option = MOAL_IOCTL_WAIT;
+#endif
+	ENTER();
+
+	PRINTM(MMSG, "wlan: Starting AP\n");
+#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 (dfs_offload)
+			wait_option = MOAL_NO_WAIT;
+#endif
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, 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();
+
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block  woal_cfg80211_del_beacon in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	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 (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 (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_RESET)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		/* Set WLAN MAC addresses */
+		if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(priv)) {
+			PRINTM(MERROR, "Set MAC address failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_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, 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 (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 ||
+		    priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
+#endif
+			woal_deauth_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;
+
+	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_SIGNAL);
+#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;
+		}
+	}
+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;
+	memcpy(mac, info->param.sta_list.info[idx].mac_address, 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;
+	memcpy(sys_config->filter.mac_list, params->mac_addrs,
+	       sys_config->filter.mac_count * sizeof(mlan_802_11_mac_addr));
+	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, 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
+ */
+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:
+		break;
+	case NL80211_CHAN_WIDTH_20:
+		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;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+	case NL80211_CHAN_WIDTH_80P80:
+	case NL80211_CHAN_WIDTH_160:
+		chan2Offset =
+			woal_get_second_channel_offset(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, wait_option, 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;
+	memcpy(&priv->chan, &priv->csa_chan, sizeof(struct cfg80211_chan_def));
+	mutex_lock(&priv->wdev->mtx);
+	cfg80211_ch_switch_notify(priv->netdev, &priv->chan);
+	mutex_unlock(&priv->wdev->mtx);
+	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();
+}
+
+#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;
+	chan_band_info channel;
+	t_u16 enable = 0;
+
+	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;
+	}
+	ret = woal_mc_policy_cfg(priv, &enable, MOAL_IOCTL_WAIT, MLAN_ACT_GET);
+	if (enable) {
+		if (MLAN_STATUS_SUCCESS ==
+		    woal_get_active_intf_channel(priv, &channel)) {
+			if (channel.channel != chandef->chan->hw_value) {
+				PRINTM(MERROR,
+				       "DFS channel is not allowed when another connection exists on different channel\n");
+				PRINTM(MERROR,
+				       "Another connection's channel=%d, dfs channel=%d\n",
+				       channel.channel,
+				       chandef->chan->hw_value);
+				ret = -EINVAL;
+				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(&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 defined(DFS_TESTING_SUPPORT)
+	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);
+	}
+#endif
+
+	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 {
+		memcpy(&handle->dfs_channel, chandef,
+		       sizeof(struct cfg80211_chan_def));
+		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;
+	}
+
+	memcpy(&priv->csa_chan, &params->chandef,
+	       sizeof(struct cfg80211_chan_def));
+	memcpy(&priv->beacon_after, &params->beacon_after,
+	       sizeof(struct cfg80211_beacon_data));
+
+	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 100644
index 0000000..1514fdc
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_cfg80211.h
@@ -0,0 +1,29 @@
+/** @file moal_uap_cfg80211.h
+  *
+  * @brief This file contains the uAP CFG80211 specific defines.
+  *
+  * Copyright (C) 2014-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _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 100644
index 0000000..acc9a01
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_priv.c
@@ -0,0 +1,181 @@
+/** @file  moal_uap_priv.c
+  *
+  * @brief This file contains standard ioctl functions
+  *
+  * Copyright (C) 2010-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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;
+		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, wrq->u.data.pointer,
+						  wrq->u.data.length);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	case WOAL_UAP_SETONEINT_GETONEINT:
+		switch (wrq->u.data.flags) {
+#if defined(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, 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 100644
index 0000000..152ffa5
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_priv.h
@@ -0,0 +1,194 @@
+/** @file  moal_uap_priv.h
+  *
+  * @brief This file contains definition for extended private IOCTL call.
+  *
+  * Copyright (C) 2010-2019, Marvell International Lt.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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)
+#if defined(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)
+
+/**
+ * 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,
+	 ""},
+#if defined(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"},
+};
+
+#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 100644
index 0000000..bdc6f48
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_wext.c
@@ -0,0 +1,1879 @@
+/** @file  moal_uap_wext.c
+  *
+  * @brief This file contains wireless extension standard ioctl functions
+  *
+  * Copyright (C) 2010-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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;
+
+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},
+};
+
+/** 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 < 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, char *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,
+	      char *cwrq, char *extra)
+{
+	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,
+	     struct sockaddr *awrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+
+	ENTER();
+
+	if (priv->bss_started)
+		memcpy(awrq->sa_data, priv->current_addr, MLAN_MAC_ADDR_LENGTH);
+	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,
+	     struct sockaddr *awrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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 < ap_cfg->num_of_chan; i++)
+		if (ap_cfg->chan_list[i].chan_number == chan)
+			break;
+	if (i == 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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+		  t_u32 *uwrq, char *extra)
+{
+	int ret = 0;
+	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,
+		  t_u32 *uwrq, char *extra)
+{
+	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)
+			memcpy(pkey->key, extra, dwrq->length);
+		/* 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)
+					memcpy(pkey, &ap_cfg->wep_cfg.key0,
+					       sizeof(wep_key));
+				if (key_index == 1)
+					memcpy(pkey, &ap_cfg->wep_cfg.key1,
+					       sizeof(wep_key));
+				if (key_index == 2)
+					memcpy(pkey, &ap_cfg->wep_cfg.key2,
+					       sizeof(wep_key));
+				if (key_index == 3)
+					memcpy(pkey, &ap_cfg->wep_cfg.key3,
+					       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,
+		struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+			memcpy(extra, pkey->key, pkey->length);
+			dwrq->flags &= ~IW_ENCODE_DISABLED;
+		} else {
+			ret = -EFAULT;
+		}
+		break;
+	case PROTOCOL_WPA:
+	case PROTOCOL_WPA2:
+	case PROTOCOL_WPA2_MIXED:
+		memcpy(extra, ap_cfg->wpa_cfg.passphrase,
+		       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,
+		struct iw_point *dwrq, 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,
+		struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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");
+			}
+			memcpy(priv->bcn_ie_buf + priv->bcn_ie_len,
+			       ((t_u8 *)tlv),
+			       sizeof(IEEEtypes_Header_t) + tlv->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);
+			}
+			memcpy(priv->bcn_ie_buf + priv->bcn_ie_len,
+			       ((t_u8 *)tlv),
+			       sizeof(IEEEtypes_Header_t) + tlv->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,
+		    struct iw_point *dwrq, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+			memcpy(pwep_key->key, pkey_material, ext->key_len);
+		}
+	} 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;
+		memcpy(sec->param.encrypt_key.key_material, pkey_material,
+		       ext->key_len);
+		memcpy(sec->param.encrypt_key.mac_addr, ext->addr.sa_data,
+		       ETH_ALEN);
+		sec->param.encrypt_key.key_flags = ext->ext_flags;
+		if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->rx_seq,
+			       SEQ_MAX_SIZE);
+			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) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->tx_seq,
+			       SEQ_MAX_SIZE);
+			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,
+		    struct iw_point *dwrq, 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, struct iw_point *dwrq, 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)) {
+		memcpy(sta_addr, (t_u8 *)mlme->addr.sa_data, ETH_ALEN);
+		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;
+			}
+			memcpy(sta_list, &pinfo->param.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++) {
+				memcpy(bss->param.deauth_param.mac_addr,
+				       sta_list->info[i].mac_address, ETH_ALEN);
+				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 {
+			memcpy(bss->param.deauth_param.mac_addr, sta_addr,
+			       ETH_ALEN);
+			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,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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");
+		ret = -EFAULT;
+		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,
+	      struct iw_param *vwrq, 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");
+		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,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_point *dwrq, 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,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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
+
+	memcpy(sys_cfg->ssid.ssid, extra,
+	       MIN(sys_cfg->ssid.ssid_len, MLAN_MAX_SSID_LENGTH));
+	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);
+		memcpy(extra, ap_cfg->ssid.ssid, 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
+********************************************************/
+
+/** 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
+};
+
+/**
+ *  @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_wext.c b/wlan_sd8987/mlinux/moal_wext.c
new file mode 100644
index 0000000..16e5996
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_wext.c
@@ -0,0 +1,3157 @@
+/** @file  moal_wext.c
+  *
+  * @brief This file contains wireless extension standard ioctl functions
+  *
+  * Copyright (C) 2008-2019, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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 */
+/** Macro for minimum size of scan buffer */
+#define MIN_ACCEPTED_GET_SCAN_BUF 8000
+
+/********************************************************
+			Global Variables
+********************************************************/
+extern int hw_test;
+/********************************************************
+			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));
+	memcpy(priv->nick_name, extra, dwrq->length);
+	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, char *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,
+	      char *cwrq, char *extra)
+{
+	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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+		  t_u32 *uwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	     struct sockaddr *awrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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)
+		memcpy(awrq->sa_data, &bss_info.bssid, MLAN_MAC_ADDR_LENGTH);
+	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 sockaddr 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,
+	     struct sockaddr *awrq, 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);
+	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;
+		}
+		memcpy(&ssid_bssid.bssid, awrq->sa_data, ETH_ALEN);
+	}
+
+	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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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,
+		  t_u32 *uwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_param *vwrq, 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,
+	      struct iw_param *vwrq, 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 (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;
+	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;
+		memcpy(sec->param.encrypt_key.key_material, extra,
+		       dwrq->length);
+		/* 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,
+		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;
+	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) {
+		memcpy(extra, sec->param.encrypt_key.key_material,
+		       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,
+		struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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);
+	memcpy(extra, ie, 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,
+		struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+		    struct iw_point *dwrq, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+	memcpy(sec->param.encrypt_key.mac_addr, (u8 *)ext->addr.sa_data,
+	       ETH_ALEN);
+	/* 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;
+		memcpy(sec->param.encrypt_key.key_material, pkey_material,
+		       ext->key_len);
+		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) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->rx_seq,
+			       SEQ_MAX_SIZE);
+			DBG_HEXDUMP(MCMD_D, "Rx PN", sec->param.encrypt_key.pn,
+				    SEQ_MAX_SIZE);
+		}
+		if (ext->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->tx_seq,
+			       SEQ_MAX_SIZE);
+			DBG_HEXDUMP(MCMD_D, "Tx PN", sec->param.encrypt_key.pn,
+				    SEQ_MAX_SIZE);
+		}
+		memcpy(sec->param.encrypt_key.key_material, pkey_material,
+		       ext->key_len);
+		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;
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->tx_seq,
+			       SEQ_MAX_SIZE);
+			memcpy(&sec->param.encrypt_key.pn[SEQ_MAX_SIZE],
+			       (t_u8 *)ext->rx_seq, 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,
+		    struct iw_point *dwrq, 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, struct iw_point *dwrq, 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,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	       struct iw_point *dwrq, char *extra)
+{
+	int i;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+	}
+	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 (!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;
+		}
+		memcpy(country_code, buf + strlen("COUNTRY") + 1,
+		       COUNTRY_CODE_LEN - 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(dwrq->pointer, buf, dwrq->length))
+		ret = -EFAULT;
+done:
+	kfree(buf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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;
+			memcpy(req_ssid.ssid,
+			       (t_u8 *)req->essid, req->essid_len);
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_request_scan(priv, MOAL_NO_WAIT, &req_ssid)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	} else {
+#endif
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_request_scan(priv, MOAL_NO_WAIT, NULL)) {
+			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,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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 */
+		memcpy(req_ssid.ssid, extra,
+		       MIN(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);
+		memcpy(&ssid_bssid.ssid, &req_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 (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) {
+		memcpy(&priv->prev_ssid_bssid.ssid, &req_ssid,
+		       sizeof(mlan_802_11_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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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);
+		memcpy(extra, bss_info.ssid.ssid, 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;
+		memcpy(iwe.u.ap_addr.sa_data, &scan_table[i].mac_address,
+		       ETH_ALEN);
+
+		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;
+					memcpy(buf, praw_data,
+					       element_len +
+					       sizeof(IEEEtypes_Header_t));
+					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 = 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 = &mic;
+	iwrq.data.length = sizeof(mic);
+
+	wireless_send_event(priv->netdev, IWEVMICHAELMICFAILURE, &iwrq,
+			    (char *)&mic);
+
+	LEAVE();
+	return;
+}
+#endif
+
+#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
+};
+
+/**
+ *  @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;
+	woal_get_stats_info(priv, wait_option, NULL);
+
+	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 100644
index 0000000..7ec96a9
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_wext.h
@@ -0,0 +1,51 @@
+/** @file moal_wext.h
+ *
+ * @brief This file contains definition for wireless extension IOCTL call.
+ *
+ * Copyright (C) 2008-2019, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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_ */
diff --git a/wlan_sd8997/Makefile b/wlan_sd8997/Makefile
new file mode 100644
index 0000000..c7d8fca
--- /dev/null
+++ b/wlan_sd8997/Makefile
@@ -0,0 +1,591 @@
+# File: Makefile
+#
+# Copyright (C) 2008-2018, Marvell International Ltd.
+#
+# This software file (the "File") is distributed by Marvell International
+# Ltd. under the terms of the GNU General Public License Version 2, June 1991
+# (the "License").  You may use, redistribute and/or modify this File in
+# accordance with the terms and conditions of the License, a copy of which
+# is available by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# A copy of the GPL is available in file gpl-2.0.txt accompanying in this
+# deliverables.
+#
+# 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.
+
+COMPATDIR=/lib/modules/$(KERNELVERSION_X86)/build/compat-wireless-3.2-rc1-1/include
+CC=		$(CROSS_COMPILE)gcc -I$(COMPATDIR)
+LD=		$(CROSS_COMPILE)ld
+BACKUP=		/root/backup
+YMD=		`date +%Y%m%d%H%M`
+
+ifneq ($(COMPAT_VERSION_CODE),)
+DRV_DIR ?= $(shell pwd)
+export DRV_DIR
+COMPAT_VERSION=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$1}')
+COMPAT_PATCHLEVEL=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$2}')
+COMPAT_SUBLEVEL=$(shell echo $(COMPAT_VERSION_CODE) | awk -F '.' '{print $$3}')
+DECL_HEADER_FILE=$(DRV_DIR)/mlinux/moal_main.h
+$(shell sed -i 's/COMPAT_VERSION_CODE KERNEL_VERSION.*/COMPAT_VERSION_CODE KERNEL_VERSION(\
+		$(COMPAT_VERSION), $(COMPAT_PATCHLEVEL), $(COMPAT_SUBLEVEL))/g' $(DECL_HEADER_FILE))
+endif
+
+#############################################################################
+# Configuration Options
+#############################################################################
+
+# Debug Option
+# DEBUG LEVEL n/1/2:
+# n: NO DEBUG
+# 1: Only PRINTM(MMSG,...), PRINTM(MFATAL,...), ...
+# 2: All PRINTM()
+CONFIG_DEBUG=1
+
+# Proc debug file
+CONFIG_PROC_DEBUG=y
+
+# 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 WIFIDISPLAY support
+CONFIG_WIFI_DISPLAY_SUPPORT=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
+
+# Enable SDIO multi-port Tx aggregation
+CONFIG_SDIO_MULTI_PORT_TX_AGGR=y
+
+# Enable SDIO multi-port Rx aggregation
+CONFIG_SDIO_MULTI_PORT_RX_AGGR=y
+
+# SDIO suspend/resume
+CONFIG_SDIO_SUSPEND_RESUME=y
+
+# DFS testing support
+CONFIG_DFS_TESTING_SUPPORT=y
+
+# Multi-channel support
+CONFIG_MULTI_CHAN_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 += -I$(M)/mlan
+ccflags-y += -DLINUX
+
+
+
+KERNELDIR ?= /usr/src/arm/linux-4.9.61-bg5ct
+CROSS_COMPILE ?= /usr/local/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
+
+LD += -S
+
+BINDIR = ../bin_sd8997
+APPDIR= $(shell if test -d "mapp"; then echo mapp; fi)
+
+#############################################################################
+# Compiler Flags
+#############################################################################
+
+	ccflags-y += -I$(KERNELDIR)/include
+
+	ccflags-y += -DFPNUM='"68"'
+
+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_PROC_DEBUG),y)
+	ccflags-y += -DPROC_DEBUG
+	export CONFIG_PROC_DEBUG
+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_WIFI_DISPLAY_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_WIFI_DISPLAY_SUPPORT=n
+CONFIG_UAP_WEXT=n
+CONFIG_UAP_CFG80211=n
+endif
+
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	ccflags-y += -DWIFI_DIRECT_SUPPORT
+endif
+ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y)
+	ccflags-y += -DWIFI_DISPLAY_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
+
+ifeq ($(CONFIG_SDIO_MULTI_PORT_TX_AGGR),y)
+	ccflags-y += -DSDIO_MULTI_PORT_TX_AGGR
+endif
+
+ifeq ($(CONFIG_SDIO_MULTI_PORT_RX_AGGR),y)
+	ccflags-y += -DSDIO_MULTI_PORT_RX_AGGR
+endif
+
+ifeq ($(CONFIG_SDIO_SUSPEND_RESUME),y)
+	ccflags-y += -DSDIO_SUSPEND_RESUME
+endif
+
+ifeq ($(CONFIG_MULTI_CHAN_SUPPORT),y)
+	ccflags-y += -DMULTI_CHAN_SUPPORT
+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
+
+# 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
+
+#############################################################################
+# 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_UAP_CFG80211=y
+else
+ifeq ($(CPTCFG_CFG80211),m)
+	CONFIG_UAP_CFG80211=y
+else
+	CONFIG_UAP_CFG80211=n
+endif
+endif
+endif
+
+ifneq ($(CONFIG_STA_SUPPORT),y)
+	CONFIG_WIFI_DIRECT_SUPPORT=n
+	CONFIG_WIFI_DISPLAY_SUPPORT=n
+	CONFIG_STA_WEXT=n
+	CONFIG_STA_CFG80211=n
+endif
+
+ifneq ($(CONFIG_UAP_SUPPORT),y)
+	CONFIG_WIFI_DIRECT_SUPPORT=n
+	CONFIG_WIFI_DISPLAY_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
+
+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
+MLANOBJS += mlan/mlan_sdio.o
+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_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_cfgvendor.o
+MOALOBJS += mlinux/moal_sta_cfg80211.o
+endif
+ifeq ($(CONFIG_UAP_CFG80211),y)
+MOALOBJS += mlinux/moal_cfg80211.o
+MOALOBJS += mlinux/moal_cfgvendor.o
+MOALOBJS += mlinux/moal_uap_cfg80211.o
+endif
+
+ifdef CONFIG_PROC_FS
+MOALOBJS += mlinux/moal_proc.o
+ifeq ($(CONFIG_PROC_DEBUG),y)
+MOALOBJS += mlinux/moal_debug.o
+endif
+endif
+
+
+
+
+
+
+
+obj-$(CONFIG_BERLIN_SDIO_WLAN_8997) := 8997mlan.o
+8997mlan-objs := $(MLANOBJS)
+MOALOBJS += mlinux/moal_sdio_mmc.o
+obj-$(CONFIG_BERLIN_SDIO_WLAN_8997) += sd8997.o
+sd8997-objs := $(MOALOBJS)
+
+# Otherwise we were called directly from the command line; invoke the kernel build system.
+else
+
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) modules
+
+endif
+
+###############################################################
+
+export		CC LD ccflags-y KERNELDIR
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+.PHONY: mapp/mlanconfig mapp/mlan2040coex mapp/mlanevent mapp/uaputl mapp/mlanutl clean distclean
+else
+.PHONY: mapp/mlanconfig mapp/mlanevent mapp/mlan2040coex mapp/mlanutl clean distclean
+endif
+else
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+.PHONY: mapp/mlanevent mapp/uaputl clean distclean
+endif
+endif
+	@echo "Finished Making Marvell Wlan Linux Driver"
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+mapp/mlanconfig:
+	$(MAKE) -C $@
+mapp/mlanutl:
+	$(MAKE) -C $@
+mapp/mlan2040coex:
+	$(MAKE) -C $@
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+mapp/uaputl:
+	$(MAKE) -C $@
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+mapp/wifidirectutl:
+	$(MAKE) -C $@
+endif
+mapp/mlanevent:
+	$(MAKE) -C $@
+
+echo:
+
+build:		echo default
+
+	@if [ ! -d $(BINDIR) ]; then \
+		mkdir $(BINDIR); \
+	fi
+
+ifeq ($(CONFIG_MULTI_INTERFACE),y)
+	cp -f mlan_sdio.$(MODEXT) $(BINDIR)/mlan_sdio$(DBG).$(MODEXT)
+else
+	cp -f mlan.$(MODEXT) $(BINDIR)/mlan$(DBG).$(MODEXT)
+endif
+	cp -f sd8xxx.$(MODEXT) $(BINDIR)/sd8997$(DBG).$(MODEXT)
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	cp -f README $(BINDIR)
+	cp -f README_MLAN $(BINDIR)
+	cp -f README_RBC $(BINDIR)
+ifeq ($(CONFIG_OPENWRT_SUPPORT),y)
+	cp -f README_OPENWRT $(BINDIR)
+endif
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/mlanconfig $@ INSTALLDIR=$(BINDIR)
+	$(MAKE) -C mapp/mlanutl $@ INSTALLDIR=$(BINDIR)
+	$(MAKE) -C mapp/mlan2040coex $@ INSTALLDIR=$(BINDIR)
+endif
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	cp -f README_UAP $(BINDIR)
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/uaputl $@ INSTALLDIR=$(BINDIR)
+endif
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	cp -f README_WIFIDIRECT $(BINDIR)
+	cp -rpf script/wifidirect $(BINDIR)
+ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y)
+	cp -rpf script/wifidisplay $(BINDIR)
+endif
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/wifidirectutl $@ INSTALLDIR=$(BINDIR)
+endif
+endif
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/mlanevent $@ 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),)
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	$(MAKE) -C mapp/mlanconfig $@
+	$(MAKE) -C mapp/mlanutl $@
+	$(MAKE) -C mapp/mlan2040coex $@
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	$(MAKE) -C mapp/uaputl $@
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	$(MAKE) -C mapp/wifidirectutl $@
+endif
+	$(MAKE) -C mapp/mlanevent $@
+endif
+
+install: default
+
+	cp -f mlan.$(MODEXT) $(INSTALLDIR)/mlan$(DBG).$(MODEXT)
+	cp -f ../io/sdio/$(PLATFORM)/sdio.$(MODEXT) $(INSTALLDIR)
+	cp -f sd8xxx.$(MODEXT) $(INSTALLDIR)/sd8997$(DBG).$(MODEXT)
+	echo "sd8997 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),)
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	$(MAKE) -C mapp/mlanconfig $@
+	$(MAKE) -C mapp/mlanutl $@
+	$(MAKE) -C mapp/mlan2040coex $@
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	$(MAKE) -C mapp/uaputl $@
+endif
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	$(MAKE) -C mapp/wifidirectutl $@
+endif
+	$(MAKE) -C mapp/mlanevent $@
+endif
+
+# End of file
diff --git a/wlan_sd8997/README b/wlan_sd8997/README
new file mode 100644
index 0000000..6dd9767
--- /dev/null
+++ b/wlan_sd8997/README
@@ -0,0 +1,2393 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2008-2018, Marvell International Ltd.
+ All Rights Reserved
+
+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 up to 4.15.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy firmware image sd8786_uapsta.bin | sd8787_uapsta.bin | ... to
+	   /lib/firmware/mrvl/ directory, create the directory if it doesn't exist.
+	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
+		The default drv_mode is 7.
+			Bit 4 :  NAN
+
+		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 2)
+		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)
+		nan_name: Name of the NAN interface (default: "nan")
+		max_nan_bss: Number of NAN interfaces (default 1)
+	   For example, to install SD8787 driver,
+		insmod mlan.ko
+		insmod sd8787.ko [drv_mode=3] [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in STA only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=1 [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in uAP only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=2 [fw_name=mrvl/sd8787_uapsta.bin]
+
+	   To switch mode between STA only, uAP only and uAPSTA etc. in run time,
+		echo drv_mode=1 > /proc/mwlan/config		// STA mode
+		echo drv_mode=2 > /proc/mwlan/config		// uAP mode
+		echo drv_mode=3 > /proc/mwlan/config		// STA+uAP mode
+		echo drv_mode=7 > /proc/mwlan/config		// STA+uAP+WIFIDIRECT mode
+	c) Uninstall WLAN driver,
+		ifconfig mlanX down
+		ifconfig uapX down
+		rmmod sd8xxx
+		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>
+	  p2p_enh=0|1 <Disable enhanced P2P (default) | Enable enhanced P2P>
+	  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)>
+	  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>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf
+	  sdio_rx_aggr=1|2 <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
+	cfg80211_drcs=1|0 <Enable DRCS support (default) | Disable DRCS support>
+	  reg_alpha2=<Regulatory alpha2 (default NULL)>
+	  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>
+      indrstcfg=<2-byte IR configuration>
+      gpio pin (high byte): GPIO pin no to be used as trigger for out band reset
+        (0xFF: default pin configuration)
+      ir_mode (low byte) : independent reset mode
+        (0: disable, 1: enable out band, 2: enable in band)
+      For example, to enable out band reset via gpio_pin 14
+       indrstcfg=0x0e01
+      To enable out band reset via default gpio_pin
+       indrstcfg=0xff01
+      To enable in band reset and disable out band reset
+       indrstcfg=0x02
+
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sd8xxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+
+	The following info are provided in /proc/net/mwlan/mlanX/info,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX/info.
+
+	driver_name = "wlan"
+	driver_version = <chip id, firmware version and driver version>
+	interface_name = "mlanX"
+	bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown"
+	media_state = "Disconnected" | "Connected"
+	mac_address = <6-byte adapter MAC address>
+	multicase_count = <multicast address count>
+	essid = <current SSID>
+	bssid = <current BSSID>
+	channel = <current channel>
+	region_code = <current region code>
+	multicast_address[n] = <multicast address>
+	num_tx_bytes = <number of bytes sent to device>
+	num_rx_bytes = <number of bytes received from device and sent to kernel>
+	num_tx_pkts = <number of packets sent to device>
+	num_rx_pkts = <number of packets received from device and sent to kernel>
+	num_tx_pkts_dropped = <number of Tx packets dropped by driver>
+	num_rx_pkts_dropped = <number of Rx packets dropped by driver>
+	num_tx_pkts_err = <number of Tx packets failed to send to device>
+	num_rx_pkts_err = <number of Rx packets failed to receive from device>
+	carrier "on" | "off"
+	tx queue "stopped" | "started"
+
+	The following debug info are provided in /proc/net/mwlan/mlanX/debug,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX/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>
+	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>
+	sleep_pd = <sleep period in milliseconds>
+	qos_cfg = <WMM QoS info>
+	tx_lock_flag = <0/1, Tx lock flag>
+	port_open = <0/1, port open flag>
+	scan_processing = <0/1, scan processing flag>
+	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>
+	num_evt_disassoc = <number of disassociated events received from device>
+	num_evt_link_lost = <number of link lost events received from device>
+	num_cmd_deauth = <number of deauthenticate commands sent to device>
+	num_cmd_assoc_ok = <number of associate commands with success return>
+	num_cmd_assoc_fail = <number of associate commands with failure return>
+	cmd_sent = <0/1, send command resources available/sending command to device>
+	data_sent = <0/1, send data resources available/sending data to device>
+	mp_rd_bitmap = <SDIO multi-port read bitmap>
+	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>
+	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>
+	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>
+	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/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/config      # read func 0 address 4
+		cat /proc/mwlan/config                          # display the register value
+		echo "sdcmd52rw= 1 3 0xf" > /proc/mwlan/config  # write 0xf to func 1 address 3
+
+	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 IWPRIV COMMAND
+
+NAME
+	This manual describes the usage of private commands used in Marvell MLAN
+	Linux Driver.
+
+	To use parameters as hex format, a '0x' must precede it for the parameters to
+	be parsed properly.
+
+SYNOPSIS
+	iwpriv <mlanX> <command> [sub-command] ...
+
+	iwpriv mlanX version
+	iwpriv mlanX verext
+	iwpriv mlanX getsignal [m] [n]
+	iwpriv mlanX antcfg [m] [n]
+	iwpriv mlanX regioncode [n]
+	iwpriv mlanX cfpcode [m] [n]
+	iwpriv mlanX wwscfg [m]
+	iwpriv mlanX esuppmode
+	iwpriv mlanX passphrase <ssid/psk/passphrase>
+	iwpriv mlanX httxcfg [<m>] [<n>]
+	iwpriv mlanX htcapinfo [<m>] [<n>]
+	iwpriv mlanX addbapara <m> <n> <o> <p> <q>
+	iwpriv mlanX aggrpriotbl <n>
+	iwpriv mlanX addbareject <n>
+	iwpriv mlanX txbufcfg
+	iwpriv mlanX amsduaggrctrl <n>
+	iwpriv mlanX httxbfcap [cap]
+	iwpriv mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData]"
+	iwpriv mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+	iwpriv mlanX atimwindow [n]
+	iwpriv mlanX deepsleep [n] [m]
+	iwpriv mlanX hscfg [condition [[GPIO# [gap]]]]
+	iwpriv mlanX hssetpara condition [GPIO# [gap]]
+	iwpriv mlanX deauth [n]
+	iwpriv mlanX radioctrl
+	iwpriv mlanX reassoctrl [n]
+	iwpriv mlanX adhocaes
+	iwpriv mlanX bandcfg [l] [m] [n] [o]
+	iwpriv mlanX getlog
+	iwpriv mlanX 11dcfg
+	iwpriv mlanX 11dclrtbl
+	iwpriv mlanX wmmcfg [n]
+	iwpriv mlanX txpowercfg [<RateIndex> [<MinPwr> [<MaxPwr> <step>]]]
+	iwpriv mlanX qoscfg
+	iwpriv mlanX getdatarate
+	iwpriv mlanX txratecfg [n]
+	iwpriv mlanX bcninterval [n]
+	iwpriv mlanX sysclock [clk1] [clk2] [clk3] [clk4]
+	iwpriv mlanX drvdbg [n]
+	iwpriv mlanX mgmtframectrl
+	iwpriv mlanX warmreset
+	iwpriv mlanX regrdwr <type> <offset> [value]
+	iwpriv mlanX rdeeprom <offset> <length>
+	iwpriv mlanX memrdwr <address> [value]
+	iwpriv mlanX inactivityto <n> <m> <l> [k]
+	iwpriv mlanX sdioclock <n>
+	iwpriv mlanX sdcmd52rw <FN no.> <address> [data]
+	iwpriv mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+	iwpriv mlanX sleeppd [n]
+	iwpriv mlanX pscfg [k] [d] [l] ...
+        iwpriv mlanX fwwakeupmethod [n] [g]
+	iwpriv mlanX associate "<bssid> <ssid>"
+	iwpriv mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+	iwpriv mlanX netmon [<act> [<filter> <band> <chan> [offset]]]
+	iwpriv mlanX authtype [n]
+	iwpriv mlanX powercons [n]
+	iwpriv mlanX htstreamcfg [n]
+	iwpriv mlanX ipaddr ["<op>;<ipaddr>"]
+	iwpriv mlanX macctrl [n]
+	iwpriv mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+	iwpriv mlanX thermal
+    iwpriv mlanX indrstcfg <ir_mode> [gpio_pin]
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell 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.
+
+version
+	This is used to get the current version of the driver and the firmware.
+
+verext
+	Retrieve and display an extended version string from the firmware
+
+	Usage:
+		iwpriv mlanX verext [#]
+
+	where [#] is an optional argument to retrieve a specific version string,
+	omission of the argument retrieves the 0 indexed string.
+
+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:
+		iwpriv mlan0 getsignal 1        : Get the RSSI info (beacon last, beacon
+		                                  average, data last and data average)
+		iwpriv mlan0 getsignal 3 4      : Get the NF of data average
+		iwpriv mlan0 getsignal 2 1      : Get the SNR of beacon last
+		iwpriv 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
+
+antcfg
+	This command is used to set/get the mode of Tx/Rx path.
+
+	where value of m is:
+		Bit 0   -- Tx Path A
+		Bit 1   -- Tx Path B
+		Bit 0-1 -- Tx Path A+B
+
+	where value of n is:
+		Bit 0   -- Rx Path A
+		Bit 1   -- Rx Path B
+		Bit 0-1 -- Rx Path A+B
+	The Tx path setting (m) is used if Rx path (n) is not provided.
+
+	Examples:
+		iwpriv mlan0 antcfg             : Get Tx and Rx path
+		iwpriv mlan0 antcfg 3           : Set Tx and Rx path to A+B
+		iwpriv mlan0 antcfg 1 3         : Set Tx path to A and Rx path to A+B
+
+regioncode
+	This command is used to set/get the region code in the station.
+	Note: This command should be issued at beginning before band/channel selection
+	and association.
+
+	where value is 'region code' for various regions like
+	USA FCC, Canada IC, Europe ETSI, Japan ...
+	The special code (0xff) is used for Japan to support channel 1-14 in B/G/N mode.
+
+	Examples:
+		iwpriv mlan0 regioncode         : Get region code
+		iwpriv mlan0 regioncode 0x10    : Set region code to USA (0x10)
+
+	Note : in some case regioncode will be 0 after updated countycode or 80211d
+		i.e. mlanutl mlanX countrycode  (CA, JP, CN, DE, ES AT, BR, RU)
+		or uaputl.exe sys_cfg_80211d state 1 country (CA, JP, CN, DE, ES AT, BR, RU)
+		Please use cfp instead of it.
+
+cfpcode
+	This command is used to set/get the Channel-Frequency-Power table codes.
+	The region table can be selected through region code.
+	The current configuration is returned if no parameter provided.
+
+	where the parameters are,
+		[m]: code of the CFP table for 2.4GHz (0: unchanged)
+		[n]: code of the CFP table for 5GHz (0 or not provided: unchanged)
+
+	Examples:
+		iwpriv mlan0 cfpcode            : Get current configuration
+		iwpriv mlan0 cfpcode 0x30       : Set 2.4GHz CFP table code 0x30 (EU),
+		                                  keep 5GHz table unchanged
+		iwpriv mlan0 cfpcode 0x10 5     : Set 2.4GHz CFP table code 0x10 (USA)
+		                                  and 5GHz table code 5
+
+wwscfg
+	This command is used to set/get the WWS (World Wide Safe) mode.
+
+	where value of m is:
+		0       -- Disable WWS mode (default)
+		1       -- Enable WWS mode
+
+	Examples:
+		iwpriv mlan0 wwscfg             : Get WWS mode
+		iwpriv mlan0 wwscfg 1           : Enable WWS mode
+		iwpriv mlan0 wwscfg 0           : Disable WWS mode
+
+esuppmode
+	This command is used to get the current RSN mode and active pairwise/group
+    cipher for WPA/WPA2 mode.
+	Note: This command is available only when STA is connected.
+
+	These are bits settings used to indicate each RSN mode.
+		Bit 0    : No RSN
+		Bit 1-2  : RFU
+		Bit 3    : WPA
+		Bit 4    : WPA-NONE
+		Bit 5    : WPA2
+		Bit 6    : AES
+		Bit 7-15 : RFU
+
+	These are bits settings used to indicate each pairwise and group cipher.
+		Bit 0    : RFU
+		Bit 1    : RFU
+		Bit 2    : TKIP
+		Bit 3    : AES
+		Bit 2-7  : RFU
+
+	Example:
+		iwpriv mlan0 esuppmode          : Get RSN mode and pairwise/group cipher
+		8 4 4
+		(The current RSN mode is WPA, active pairwise cipher is TKIP and
+		 active group cipher is TKIP.)
+
+passphrase
+	This command is used to set/get passphrase for WPA-PSK/WPA2-PSK mode.
+
+	Where <n>
+		ASCII string for ssid/passphrase/psk.
+
+	1) "0;<ssid=valid ssid>" - This will get the passphrase, AKMP
+	   for specified ssid, if none specified then it will get all.
+
+	Example:
+		iwpriv mlan0 passphrase "0;ssid=marvell"
+
+	2) "1;<psk=64 byte hexpsk>;<passphrase=1-63 byte passphare>
+	   <ssid=valid ssid>" - Passphrase and psk cannot be provided for the same SSID.
+	   This command takes only one SSID at a time, If ssid= is present 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 ';' or '/' has to be used in an SSID then a '/' should be preceded
+	   to ';' or '/' as a escape.
+
+	Examples:
+		iwpriv mlan0 passphrase "1;ssid=mrvlAP;passphrase=abcdefgd"
+		iwpriv mlan0 passphrase "1;ssid=mrvl AP;psk=<64 bytes hexpsk>"
+
+		If user wants to input the ssid as "mrvl; AP" then command has to be
+		iwpriv mlan0 passphrase "1;ssid=mrvl/; AP;passphrase=abcdefgh"
+
+		If user wants to input the ssid as "//;" then command has to be
+		iwpriv mlan0 passphrase "1;ssid=/////;;passphrase=abcdefgh"
+
+	3) "2;<ssid=valid ssid>" - This will clear the passphrase
+	   for specified ssid, if none specified then it will clear all.
+
+	Examples:
+		iwpriv mlan0 passphrase "2;ssid=marvell"
+		iwpriv mlan0 passphrase "2"     : Clear all profiles and disable embedded supplicant
+
+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
+
+	Examples:
+		iwpriv mlanX httxcfg
+		This will display HT Tx configuration.
+		If the configurations for 2.4G and 5G are 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.
+
+		iwpriv mlanX httxcfg 0x62
+		This will enable 20/40 and Short GI but will disable Green field for 2.4G and 5G band.
+
+		iwpriv 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 24: Short GI in 40 Mhz enable/disable
+		Bit 23: Short GI in 20 Mhz 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
+
+	Examples:
+		iwpriv 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.
+
+		iwpriv mlanX htcapinfo 0x1820000
+		This will enable Short GI, Channel BW to 20/40 and disable Green field support for 2.4G and 5G band.
+
+		iwpriv 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).
+
+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:
+	iwpriv mlanX addbapara - This command will get the current addba params
+	iwpriv 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.
+
+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:
+	iwpriv 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
+	iwpriv 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.
+	iwpriv 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.
+
+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:
+	iwpriv 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.
+
+	iwpriv 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]
+
+	iwpriv 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.
+
+txbufcfg
+	This command can be used to get current buffer size.
+
+	eg:
+	iwpriv mlanX txbufcfg 	  - This will display the current buffer size.
+
+	Note:- The actual tx buf size will depends on AP's capability and max transmit buffer size.
+
+amsduaggrctrl
+	This command could be used to enable/disable a feature where firmware gives feedback to driver
+	regarding the optimal AMSDU buffer size to use with the current rate. Firmware will use the
+	current rate to decide the buffer size we could transmit. The max buffer size will still be
+	limited by buffer size provided in txbufcfg. (i.e. if the txbufcfg is 4K, then we could only transmit
+	4K/2K AMSDU packets, if the txbufcfg is 8K then we could transmit 8k/4k/2k based on current rate)
+
+	If enabled AMSDU buffer size at various rates will be as follows
+
+	1.	Legacy B/G rate.
+		No AMSDU aggregation.
+
+	2.	BW20 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 3, 2:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 1, 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 4, 3:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	3.	BW40 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4, 3, 2, 1:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5, 4, 3:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	where <n> is 0/1 (for disable/enable)
+
+	eg:
+	iwpriv mlanx amsduaggrctrl 1 - Enable this feature
+	iwpriv mlanx amsduaggrctrl 0 - Disable this feature
+	iwpriv mlanx amsduaggrctrl - This will get the enable/disable flag
+	and the current AMSDU buffer size). The AMSDU buffer size returned is only
+	valid after association as before association there is no rate info.
+
+	Note:- This command to enable/disable could be given anytime (before/after
+			association). This feature is enabled by default by the driver during
+			initialization.
+
+httxbfcap
+	This command is used to set/get the TX beamforming capabilities.
+
+	Usage:
+		iwpriv mlanX httxbfcap [cap]
+
+	where the parameters are,
+		cap: TX beamforming capabilities
+			 Bit 0    : Implicit TX BF receiving capable
+			 Bit 1    : RX staggered sounding capable
+			 Bit 2    : TX staggered sounding capable
+			 Bit 3    : RX NDP capable
+			 Bit 4    : TX NDP capable
+			 Bit 5    : Implicit TX BF capable
+			 Bit 6-7  : Calibration
+			         0: - not supported
+			         1: - STA can respond to a calibration request using
+			              the CSI Report, but cannot initiate calibration
+			         2: - reserved
+			         3: - STA can both initiate and respond to a calibration request
+			 Bit 8    : Explicit CSI TX BF capable
+			 Bit 9    : Explicit non-compressed steering capable
+			 Bit 10   : Explicit compressed steering capable
+			 Bit 11-12: Explicit TX BF CSI feedback
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 13-14: Explicit non-compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 15-16: Explicit compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 17-18: Minimal grouping
+			         0: - no grouping (STA supports groups of 1)
+			         1: - groups of 1, 2
+			         2: - groups of 1, 4
+			         3: - groups of 1, 2, 4
+			 Bit 19-20: CSI number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 21-22: Non-compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 23-24: Compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 25-26: CSI max number of rows beamformer supported
+			         0: - single row of CSI
+			         1: - 2 rows of CSI
+			         2: - 3 rows of CSI
+			         3: - 4 rows of CSI
+			 Bit 27-28: Channel estimation capability
+			         0: - 1 space time stream
+			         1: - 2 space time streams
+			         2: - 3 space time streams
+			         3: - 4 space time streams
+			 Bit 29-31: Reserved
+
+	Examples:
+		iwpriv mlan0 httxbfcap             : Get the current TX BF capabilities
+		iwpriv mlan0 httxbfcap 0x0000001F  : Set the TX BF capabilities of the
+		                                     Implicit TX BF receiving capable,
+		                                     RX staggered sounding capable,
+		                                     TX staggered sounding capable,
+		                                     RX NDP capable and TX NDP capable
+
+httxbfcfg
+	This command is used to configure the TX beamforming options.
+	Note: Any new subcommand should be inserted in the second
+		argument and each argument of the sub command should be
+		separated by semicolon. For global configuration, the
+		arguments should be separated by space.
+
+	Usage:
+		iwpriv mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData]"
+
+	where the parameters are,
+		action: TX beamforming action
+			0: Control global parameters for beamforming
+		        1: Performs NDP Sounding for PEER
+		        2: TX BF interval in milliseconds
+		        3: Enable/Disable beamforming/sounding for a particular peer
+		        4: TX BF SNR Threshold for peer
+		        .. <for new subcommand>
+		GlobalData: Global parameter arguments.
+		    It contains beamforming enable, sounding enable, FB type, snr_threshold
+		    sounding interval, Beamformig mode values seperated by space.
+		    Syntax:
+			iwpriv mlanX httxbfcfg <action>;<beamforming enable> <sounding enable> <FB type>
+			                       <snr_threshold>  <sounding interval> <Beamforming mode>
+		tsData: Trigger sounding for PEER specific arguments,
+		        it contains PEER MAC and status
+		interval: TX BF interval in milliseconds
+		txPeerData: Enable/Disable beamforming/sounding for the indicated peer,
+		          it contains PEER MAC, sounding, beamfoming options and FB type;
+		snrData: TX BF SNR Threshold for peer, it contains PEER MAC and SNR
+
+	Examples:
+		iwpriv mlan0 httxbfcfg "0"                          : Get current global configuration parameter
+		iwpriv mlan0 httxbfcfg "2;00:50:43:20:BF:64"        : Get the TX BF periodicity for a given peer
+		iwpriv mlan0 httxbfcfg "3"                          : Get the list of MAC addresses that have
+		                                                      beamforming and/or sounding enabled
+		iwpriv mlan0 httxbfcfg "4"                          : Get the list of PEER MAC, SNR tuples
+		                                                      programmed into the firmware.
+		iwpriv mlan0 httxbfcfg "0;0 0 3 10 500 5"           : Disable beamforming, sounding, set FB type
+		                                                      to 3, snr threshold to 10, sounding interval
+		                                                      to 500 ms and beamforming mode to 5
+		iwpriv mlan0 httxbfcfg "1;00:50:43:20:BF:64"        : Perform NDP Trigger sounding to peer
+		                                                      00:50:43:20:BF:64
+		iwpriv mlan0 httxbfcfg "2;00:50:43:20:BF:64;500"    : Set TX BF periodicity for peer 00:50:43:20:BF:64
+		                                                      to 500 milliseconds
+		iwpriv mlan0 httxbfcfg "3;00:50:43:20:BF:43;1;0;3"  : Enable beamforming, disable sounding and set
+		                                                      FB type to 3 for peer 00:50:43:20:BF:43
+		iwpriv mlan0 httxbfcfg "4;00:50:43:20:BF:24;43"     : Set TX BF SNR threshold to peer
+		                                                      00:50:43:20:BF:24 with SNR 43
+
+mgmtframectrl
+	This command is used to get/set mask for the management frames which needs to be forwarded to application layer.
+
+	Usage:
+		iwpriv mlanX mgmtframectrl [m]
+
+	where the parameter [m] is the bit mask of management frame reception.
+		Following are the bit definitions.
+		Bit 0 : Association Request
+		Bit 1 : Association Response
+		Bit 2 : Re-Association Request
+		Bit 3 : Re-Association Response
+		Bit 4 : Probe Request
+		Bit 5 : Probe Response
+		Bit 8 : Beacon Frames
+
+	Examples:
+		iwpriv mlan0 mgmtframectrl         : Get the current Mgmt Frame forwarding mask
+		iwpriv mlan0 mgmtframectrl 0x0020  : Bit 5 is set, Forward probe response
+											 frames to application layer
+
+mpactrl
+	This command is used to set/get the Tx, Rx SDIO aggregation parameters.
+	Note: The parameters can be set only in disconnected state.
+
+	Usage:
+		iwpriv mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+
+	where the parameter are:
+		[tx_ena]: Enable/disable (1/0) Tx MP-A
+		[rx_ena]: Enable/disable (1/0) Rx MP-A
+		[tx_size]: Size of Tx MP-A buffer
+		[rx_size]: Size of Rx MP-A buffer
+		[tx_ports]: Max ports (1-16) for Tx MP-A
+		[rx_ports]: Max ports (1-16) for Rx MP-A
+	default values are 1 1 16384 32768 16 16
+	The MP-A may be disabled by default at build time if the MMC driver byte mode patch
+	is not available in kernel.
+
+	Examples:
+		iwpriv mlan0 mpactrl       : Get MP aggregation parameters
+		iwpriv mlan0 mpactrl 0 0
+		                           : Disable MP aggregation for Tx, Rx respectively
+		iwpriv mlan0 mpactrl 1 1 8192 8192 8 8
+		                           : Enable MP aggregation for Tx, Rx
+		                           : Set Tx, Rx buffer size to 8192 bytes
+		                           : Set maximum Tx, Rx ports to 8
+
+atimwindow
+	This command is used to set/get the ATIM window value in the station.
+	The range of ATIM window is 0 - 50.
+	Value of atim window should be less than the beacon interval.
+	Note: This command should be issued before ad-hoc start/join and ad-hoc
+	power save on.
+
+	Examples:
+		iwpriv mlan0 atimwindow 20      : Set atimwindow to 20
+		iwpriv mlan0 atimwindow         : Get atimwindow
+
+deepsleep
+	This command is used to set/get auto deep sleep mode.
+
+	Usage:
+		iwpriv mlanX deepsleep [n] [m]
+
+	where the parameters are:
+		[n]: Enable/disable auto deep sleep mode (1/0)
+		[m]: Idle time in milliseconds after which firmware will put the device
+		     in deep sleep mode. Default value is 100 ms.
+
+	Examples:
+		iwpriv mlan0 deepsleep          : Display auto deep sleep mode
+		iwpriv mlan0 deepsleep 1        : Enable auto deep sleep mode, idle time unchanged
+		iwpriv mlan0 deepsleep 0        : Disable auto deep sleep mode
+		iwpriv mlan0 deepsleep 1 500    : Enable auto deep sleep mode with idle time 500 ms
+        Note:
+            Deepsleep must be disabled before changing idle time.
+
+hscfg
+	This command is used to configure the host sleep parameters.
+
+	Usage:
+		iwpriv mlanX hscfg [condition [[GPIO# [gap]]]]
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap) parameters for set. If no parameter provided,
+	get is performed.
+
+	where Condition is:
+		bit 0 = 1   -- broadcast data
+		bit 1 = 1   -- unicast data
+		bit 2 = 1   -- mac event
+		bit 3 = 1   -- multicast data
+		bit 6 = 1  --  Wakeup when mgmt frame received.
+		bit 7 = 1  --  Reserved
+		bit 8 = 1  --  Disable non maskable data wakeup.
+
+	The host sleep mode will be canceled if condition is set to -1. The default is 0x7.
+
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+	GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead).
+	The default is 0xff.
+
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff
+	for special setting (host acknowledge required) when GPIO is used to wakeup host.
+	The default is 200.
+
+	The host sleep set except for cancellation will be blocked if host sleep is
+	already activated.
+
+	Examples:
+		iwpriv mlan0 hscfg              : Get current host sleep mode
+		iwpriv mlan0 hscfg -1           : Cancel host sleep mode
+		iwpriv mlan0 hscfg 3            : Broadcast and unicast data
+		                                  Use GPIO and gap set previously
+		iwpriv mlan0 hscfg 2 3          : Unicast data
+		                                  Use GPIO 3 and gap set previously
+		iwpriv mlan0 hscfg 2 1 0xa0     : Unicast data
+		                                  Use GPIO 1 and gap 160 ms
+		iwpriv mlan0 hscfg 2 0xff       : Unicast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap set previously
+		iwpriv mlan0 hscfg 4 3 0xff     : MAC event
+		                                  Use GPIO 3
+		                                  Special host sleep mode
+		iwpriv mlan0 hscfg 1 0xff 0xff  : Broadcast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap 255ms
+
+hssetpara
+	This command is used to set host sleep parameters.
+
+	Usage:
+		iwpriv mlanX hssetpara Condition [GPIO# [gap]]
+
+	Note:
+	1) The usages of parameters are the same as "hscfg" command.
+	2) The parameters will be saved in the driver and be used when host suspends.
+
+deauth
+	This command is used to send a de-authentication to an arbitrary AP.
+	If [n] is omitted, the driver will deauth the associated AP.
+	If in ad-hoc mode this command is used to stop beacon transmission
+	from the station and go into idle state.
+
+	When <n> is supplied as a MAC address, the driver will deauth the
+	  specified AP.  If the AP address matches the driver's associated AP,
+	  the driver will disconnect. Otherwise, the driver remains connected.
+
+radioctrl
+	This command is used to turn on/off the radio.
+	Note: The radio can be disabled only in disconnected state.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 radioctrl 1        : Turn the radio on
+		iwpriv mlan0 radioctrl          : Get radio status
+
+reassoctrl
+	This command is used to turn on/off re-association in driver.
+
+	Usage:
+		iwpriv mlanX reassoctrl [n]
+
+	Where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 reassoctrl         : Get re-association status
+		iwpriv mlan0 reassoctrl 1       : Turn re-association on
+
+adhocaes
+	This command is used to set/get the AES key, when the station is in ad-hoc mode.
+	Note: This command is only available in disconnected state.
+
+	where value can be any 16 byte value.
+
+	Examples:
+		iwpriv mlan0 adhocaes           : Get ad-hoc aes key
+		iwpriv mlan0 adhocaes "1;12345678901234567890123456789012"
+		                                : Set ad-hoc aes key
+		iwpriv mlan0 adhocaes 2         : Clear ad-hoc aes key
+
+bandcfg
+	This command is used to set/get infra/ad-hoc band.
+	Note: This command is only available in disconnected state.
+
+	Usage:
+		iwpriv mlanX bandcfg [l] [m] [n] [o]
+
+	where the parameters:
+		[l]: Infrastructure band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+
+			 bit 5: AC 2.4G
+			 bit 6: AC 5G
+		[m]: Ad-hoc start band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+			 bit 5: AC 2.4G
+			 bit 6: AC 5G
+		[n]: Ad-hoc start channel
+		[o]: 0 - Bandwidth 20Mhz
+		     1 - HT Bandwidth 40Mhz above
+		     3 - HT Bandwidth 40Mhz below
+			 4 - VHT Bandwidth 80Mhz
+	Examples:
+		iwpriv mlan0 bandcfg            : Get infra/ad-hoc band and ad-hoc
+		                                  start channel configurations
+		iwpriv mlan0 bandcfg 1          : Set infra band to B only
+		iwpriv mlan0 bandcfg 3 2 6      : Set infra band to B/G, ad-hoc start band
+		                                  to G and ad-hoc start channel to 6
+		iwpriv mlan0 bandcfg 7 11 6 1   : Set infra band to B/G/A, ad-hoc start band
+		                                  to B/G/GN, ad-hoc start channel to 6 and
+		                                  secondary channel to above
+
+getlog
+	This command is used to get the statistics available in the station.
+
+11dcfg
+	This command is used to control 11D. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 11dcfg 1           : Enable 11D
+		iwpriv mlan0 11dcfg             : Get 11D status
+
+11dclrtbl
+	This command is used to clear the 11D channel table.
+
+	Usage:
+		iwpriv mlanX 11dclrtbl
+
+wmmcfg
+	This command is used to control WMM. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		iwpriv mlan0 wmmcfg 1           : Enable WMM
+		iwpriv mlan0 wmmcfg             : Get WMM status
+
+txpowercfg
+	This command is used to get/set the Tx power configuration.
+
+	Where
+		<RateIndex> - Data rate index
+			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
+			12	MCS0 (BW20)
+			13	MCS1 (BW20)
+			14	MCS2 (BW20)
+			15	MCS3 (BW20)
+			16	MCS4 (BW20)
+			17	MCS5 (BW20)
+			18	MCS6 (BW20)
+			19	MCS7 (BW20)
+			20	MCS8 (BW20)
+			21	MCS9 (BW20)
+			22	MCS10 (BW20)
+			23	MCS11 (BW20)
+			24	MCS12 (BW20)
+			25	MCS13 (BW20)
+			26	MCS14 (BW20)
+			27	MCS15 (BW20)
+			140	MCS0 (BW40)
+			141	MCS1 (BW40)
+			142	MCS2 (BW40)
+			143	MCS3 (BW40)
+			144	MCS4 (BW40)
+			145	MCS5 (BW40)
+			146	MCS6 (BW40)
+			147	MCS7 (BW40)
+  			148	MCS0 (BW40)
+			149	MCS1 (BW40)
+			150	MCS2 (BW40)
+			151	MCS3 (BW40)
+			152	MCS4 (BW40)
+			153	MCS5 (BW40)
+			154	MCS6 (BW40)
+			155	MCS7 (BW40)
+			0xff	Default
+		<MinPwr> - Minimum power level in dBm
+		<MaxPwr> - Maximum power level in dBm
+		<step>   - Power step
+
+	Note: Firmware may adjust the setting if over limit, final value can be
+	      verified using get command.
+
+	Examples:
+		iwpriv mlan0 txpowercfg 0xff        : Default power configuration
+		iwpriv mlan0 txpowercfg 11 12       : Set power level 12 dBm to data rate 54 Mbps
+		iwpriv mlan0 txpowercfg 7 11 16 1   : Set power level 11 dBm to 16 dBm with
+		                                      step 1 to data rate 18 Mbps
+		iwpriv mlan0 txpowercfg             : Get current configuration
+		mlan0     txpowercfg:2  3  13  18  2  1  1  13  18  2  0  0  13  18  2
+		10  11  13  15  2  8  9  13  16  2  6  7  13  17  2  4  5  13  17  2
+		17  19  13  15  2  15  16  13  16  2  13  14  13  17  2  12  12  13  17  2
+		145  147  13  14  1  143  144  13  14  1  141  142  13  14  1  140  140  13  14  1
+
+		 2 -> First rate index is 5.5 Mbps.
+		 3 -> Last rate index is 11 Mbps.
+		13 -> Min Tx power value is 13 dBm.
+		18 -> Max Tx power value is 18 dBm.
+		 2 -> Power adjustment step value is 2.
+
+		Similarly
+		17 -> First rate index is MCS5 (BW20).
+		19 -> Last rate index is MCS7 (BW20).
+		13 -> Min Tx power value is 13 dBm.
+		15 -> Max Tx power value is 15 dBm.
+		 2 -> Power adjustment step value is 2.
+
+		so on...
+
+qoscfg
+	This command sets WMM IE QOS info when an argument is given, and gets current WMM
+	IE QOS info when no argument is given.
+
+	Examples:
+		iwpriv mlan0 qoscfg 0x0f        : Set WMM IE QOS info to 0x0f
+		iwpriv mlan0 qoscfg             : Get WMM IE QOS info
+
+getdatarate
+	This command is used to get the data rate (index) being used in last Tx
+	packet and last Rx packet.
+
+bcninterval
+	This command is used to set/get the beacon interval in ad-hoc mode.
+	The valid beacon interval is between 20 - 1000, default beacon
+	interval is 100.
+
+	Where <n>
+		Beacon interval in TU (Time Unit: 1024 us).
+
+	Examples:
+		iwpriv mlan0 bcninterval 200    : Set ad-hoc beacon interval to 200
+		iwpriv mlan0 bcninterval        : Get ad-hoc beacon interval
+
+sysclock
+	This command is used to set/get system clocks in MHz.
+	The current system clock, configurable system clocks and all of the
+	supported system clocks will be returned if no parameter provided.
+
+	Examples:
+		iwpriv mlan0 sysclock           : Get system clocks
+		80 80 128 128 128 5 11 16 20 22 32 40 44 64 80 106 128 160 ...
+		(The current system clock is 80 MHz.
+		 The configurable system clocks of non-security, security, non-security
+		 A-MPDU and security A-MPDU are 80 MHz, 128 MHz, 128 MHz and 128 MHz.
+		 The supported system clocks are 5 MHz, 11 MHz, ..., 160 MHz, 182 MHz,
+		 213 MHz, 256 MHz, 320 Mhz, 366 MHz , ... . the Max system clocks is different
+		 for different chips, you could use this command to get the supported system clock)
+
+		iwpriv mlanX sysclock 80        : Set system clock in non-security mode
+		                                  to 80 MHz, no change for others
+		iwpriv mlanX sysclock 0 0 128   : Set system clock in non-security A-MPDU
+		                                  mode to 128 MHz, no changes for others
+
+drvdbg
+	This command is used to set/get the bit masks of driver debug message control.
+
+	Usage:
+		iwpriv 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:
+		iwpriv mlan0 drvdbg             : Get the current driver debug masks
+		iwpriv mlan0 drvdbg 0           : Disable all the debug messages
+		iwpriv mlan0 drvdbg 7           : Enable MMSG, MFATAL and MERROR messages
+		iwpriv mlan0 drvdbg 0x20037     : Enable MMSG, MFATAL, MEEROR,
+		                                  MCMND, MEVENT and MCMD_D messages
+		iwpriv mlan0 drvdbg -1          : Enable all the debug messages
+
+warmreset
+	This command is used for warm reset of the interface.
+
+	Usage:
+		iwpriv mlanX warmreset
+
+regrdwr
+	This command is used to read/write the adapter register.
+
+	Usage:
+		iwpriv mlanX regrdwr <type> <offset> [value]
+
+	where the parameters are,
+		<type>:     1:MAC/SOC, 2:BBP, 3:RF, 5:CAU
+		<offset>:   offset of register
+		[value]:    value to be written
+	Note: If highest bit of a 32-bit value needs to be set, use negative input.
+	The calculation is -(0xffffffff - value + 1). Range from -0x80000000 to -1.
+
+	Examples:
+		iwpriv mlan0 regrdwr 1 0xa060       : Read the MAC register
+		iwpriv mlan0 regrdwr 1 0xa060 0x12  : Write the MAC register
+		iwpriv mlan0 regrdwr 1 0xa794 -0x80000000
+		                                    : Write 0x80000000 to MAC register
+		iwpriv mlan0 regrdwr 1 0xa794 -0x00000001
+		                                    : Write 0xffffffff to MAC register
+
+rdeeprom
+	This command is used to read the EEPROM contents of the card.
+
+	Usage:
+		iwpriv mlanX rdeeprom <offset> <length>
+
+	where the parameters are,
+		<offset>:   multiples of 4
+		<length>:   4-20, multiples of 4
+
+	Example:
+		iwpriv mlan0 rdeeprom 0 20      : Read 20 bytes of EEPROM data from offset 0
+
+memrdwr
+	This command is used to read/write the adapter memory.
+
+	Usage:
+		iwpriv mlanX memrdwr <address> [value]
+
+	where the parameters are,
+		<address>:  memory address
+		[value]:    value to be written
+	Note: If highest bit of a 32-bit address/value needs to be set, use negitive input.
+	The calculation is -(0xffffffff - address/value + 1). Range from -0x80000000 to -1.
+
+	Examples:
+		iwpriv mlan0 memrdwr 0x4cf70    : Read memory address 0x4cf70
+		iwpriv mlan0 memrdwr -0x80000000
+		                                : Read memory address 0x80000000
+		iwpriv mlan0 memrdwr -0x7fff6000 -0x40000000
+		                                : Write 0xc0000000 to memory address 0x8000a000
+
+inactivityto
+	This command is used to set/get the inactivity timeout value, which specifies
+	when WLAN device is put to sleep.
+
+	Usage:
+		iwpriv mlanX inactivityto <n> <m> <l> [k]
+
+	where the parameter are:
+		<n>: timeout unit in microseconds.
+		<m>: Inactivity timeout for unicast data.
+		<l>: Inactivity timeout for multicast data.
+		[k]: Inactivity timeout for new Rx traffic after PS notification to AP.
+
+	Examples:
+		iwpriv mlan0 inactivityto           : Get the timeout value
+		iwpriv mlan0 inactivityto 1000 2 3  : Set timeout unit to 1000 us (1 ms),
+		                                      inactivity timeout for unicast data is 2 ms,
+		                                      inactivity timeout for multicast data is 3 ms
+
+sdioclock
+	Turn On(1) or Off(0) the SDIO clock.
+
+	Usage:
+		iwpriv mlanX sdioclock 1 (on)
+		iwpriv mlanX sdioclock 0 (off)
+		iwpriv mlanX sdioclock (get the current clock state)
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		iwpriv mlanX sdcmd52rw <function number> <register address> [value]
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+	Examples:
+		iwpriv mlan0 sdcmd52rw 1 3
+		iwpriv mlan0 sdcmd52rw 1 1 0x3f
+
+scancfg
+	This command is used to set/get scan configuration parameters.
+
+	Usage:
+		iwpriv mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+
+	where the parameters:
+		[t]: Scan Type (0: Unchanged, 1: Active, 2: Passive, default Active)
+		[m]: Scan Mode (0: Unchanged, 1: BSS, 2: IBSS, 3: Any, default Any)
+		[p]: Scan Probes (0: Unchanged, 1-4: Number of probes per channel, default 4)
+		[s]: Specific Scan Time (0: Unchanged, n: Value in ms, default 110 ms, max 500 ms)
+		[a]: Active Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 500 ms)
+		[b]: Passive Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 2000 ms)
+		[ext]: Extended scan (0: Legacy scan, 1: Extended scan)
+
+	No change if the parameter is 0 or the parameter is not provided.
+
+	Examples:
+		iwpriv mlan0 scancfg            : Get all the current scan configuration settings
+		iwpriv mlan0 scancfg 1 3        : Set scan type to active and scan mode to any,
+		                                  all the other scan configurations are unchanged
+		iwpriv mlan0 scancfg 0 1 2 200  : Set scan mode to BSS, number of probes to 2 and
+		                                  specific scan time to 200 ms, all the other scan
+		                                  configurations are unchanged
+
+sleeppd
+	This command is used to configure the sleep period of the WLAN device.
+
+	Usage:
+		iwpriv mlanX sleeppd [<period>]
+
+	Where the parameter is:
+		period: sleep period in milliseconds. Range 10~60. 0 for disable.
+
+	Examples:
+		iwpriv mlan0 sleeppd            : Get sleep period configuration
+		iwpriv mlan0 sleeppd 10         : Set sleep period to 10 ms
+
+pscfg
+	This command is used to set/get PS configuration parameters.
+
+	Usage:
+		iwpriv mlanX pscfg [k] [d] [l] ...
+
+	Where the parameters:
+		[k]: Keep alive null packet interval (0: Unchanged, -1: Disable, n: Interval in seconds)
+		[d]: DTIM interval (    0: Unchanged,
+		                      1-5: Value,
+		                    65534: DTIM will be ignored, listen interval will be used,
+		                    65533: Closest DTIM to the listen interval period will be used )
+		[l]: Local listen interval (     0: Unchanged,
+		                                -1: Disable,
+		                              1-49: Value in beacon intervals,
+		                             >= 50: Value in TUs )
+		[a]: Ad-hoc awake period (0: Unchanged, 1-31: Beacon interval, 255: Firmware
+		                          will go to sleep after beacon send out)
+		[b]: Beacon miss timeout (0: Unchanged, 1-50: Value in milliseconds, 65535: Disable)
+		[p]: Delay to PS (0-65535: Value in milliseconds, default 1000ms)
+		[m]: PS mode (0: Unchanged, 1: Auto mode, 2: PS-Poll mode, 3: PS Null mode)
+	No change if parameters are not provided.
+
+	Examples:
+		iwpriv mlan0 pscfg              : Get all the current PS configuration settings
+		iwpriv mlan0 pscfg 3 4          : Set PS keep alive null packet interval to 3 seconds
+		                                  and DTIM interval to 4, all the other configurations
+		                                  are unchanged
+		iwpriv mlan0 pscfg 0 0xfffe 10 0 20
+		                                : Disable DTIM interval, set local listen interval to
+		                                  10 beacon intervals and beacon miss interval to 20,
+		                                  all the other configurations are unchanged
+		iwpriv mlan0 pscfg 0 0 0 0 0 50 : Set delay to PS to 50 ms, keep the others unchanged
+
+fwwakeupmethod
+	This command is used to set/get the firmware wakeup method.
+
+	where value is:
+	        [n]:
+		1	-- Firmware wakeup through the interface command interrupt
+			    -- (default setting for SDIO/PCIe/USB)
+		2	-- Firmware wakeup through the GPIO pin
+		[g]:If firware wakeup throug GPIO pin, [g] is GPIO pin number
+
+	Examples:
+		iwpriv mlan0 fwwakeupmethod     : Get current firmware wakeup method
+		iwpriv mlan0 fwwakeupmethod 1    : Set firmware wakeup method to Interface mode
+		iwpriv mlan0 fwwakeupmethod 2 5  : Set firmware wakeup method to GPIO mode, GPIO_pin=5
+
+getkey
+	This command is used to get PTK/GTK
+
+	iwpriv mlanX getkey
+associate
+	Request an association to a given SSID/BSSID pair. This the only accurate
+	way to pick a specific AP and ESS for an association. The entry must
+	already exist in the scan table for the association to be attempted.
+
+	iwpriv mlanX associate "xx:xx:xx:xx:xx:xx SSID"
+
+sleepparams
+	This command is used to set the sleepclock configurations
+
+	Usage:
+		iwpriv mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+
+	where:
+		p1 is Sleep clock error in ppm (0-65535)
+		p2 is Wakeup offset in usec (0-65535)
+		p3 is Clock stabilization time in usec (0-65535)
+		p4 is Control periodic calibration (0-2)
+		p5 is Control the use of external sleep clock (0-2)
+		p6 is reserved for debug (0-65535)
+
+	Examples:
+		iwpriv mlan0 sleepparams                      : Get current sleepclock configuration
+		iwpriv mlan0 sleepparams 10 1000 2000 1 0 128 : Set sleepclock configuration
+
+netmon
+	This command is used to set/get sniffer mode configuration.
+	Note: The channel and band config is optional. If not specified, or if
+	any STA/uAP/STA+uAP connection is active, sniffer activity will be started
+	on the current config set in the FW.
+	'rtap' monitor interface will be created on enabling sniffer activity and
+	should be made 'up' for capturing in a sniffer app.
+
+	Usage:
+		iwpriv <interface> netmon [<act> [<filter>]]
+		iwpriv <interface> netmon [<act> [<filter>] [<band> <chan> [offset]]]
+
+	Where the parameters are:
+		<interface> : mlanX, uapX
+		<act>    : (1/0) enable/disable sniffer activity
+		<filter> : network monitor filer flag
+		    bit 0: (1/0) enable/disable management frame
+		    bit 1: (1/0) enable/disable control frame
+		    bit 2: (1/0) enable/disable data frame
+			bit 3: (1/0) enable/disable frames destined to active connection only
+			bit 4: (1/0) enable/disable decrypted unicast data/mgmt frames
+		<band>   : 802.11 band
+		    bit 0: B
+		    bit 1: G
+		    bit 2: A
+		    bit 3: GN
+		    bit 4: AN
+			 bit 5: AC 2.4G
+			 bit 6: AC 5G
+		<chan>   : channel to monitor
+		[offset] : secondary channel bandwidth
+			0 - Bandwidth 20Mhz
+			1 - HT Bandwidth 40Mhz sec channel above
+			3 - HT Bandwidth 40Mhz sec channel below
+			4 - VHT Bandwidth 80Mhz
+
+	Examples:
+		iwpriv mlan0 netmon             : Get the current sniffer mode configuration
+		iwpriv mlan0 netmon 0           : Disable network monitor activity
+		iwpriv uap0 netmon 1 7          : Enable sniffer activity on current channel set in FW,
+											set filter data, control, management frame.
+		iwpriv mlan0 netmon 1 4 11 6    : Enable sniffer activity in absence of active connection,
+											set filter data frame, band B/G/GN and channel 6
+		iwpriv mlan0 netmon 1 7 20 64 1 : Enable sniffer activity in absence of active connection,
+											set filter management, control and data frame, band A/AN,
+											channel 64 and secondary channel above
+		iwpriv uap0 netmon 1 0x0c        : Enable sniffer activity, set filter data frames
+											destined to the active uAP connection only
+
+		iwpriv mlan0 netmon 1 0x1d       : Enable sniffer activity, set filter decrypted data and
+											management frames destined to the active STA connection
+											only
+
+authtype
+	This command is used to set/get authentication type.
+
+	Usage:
+		iwpriv mlanX authtype [n]
+
+	where <n>
+		0: 802.11 open system authentication
+		1: 802.11 shared key authentication
+		255: allow open system or shared key authentication (default)
+
+	Examples:
+		iwpriv mlan0 authtype 0         : use open system authentication
+		iwpriv mlan0 authtype 1         : use shared key authentication
+		iwpriv mlan0 authtype 255       : allow open system or shared key authentication
+		iwpriv mlan0 authtype           : get current setting
+
+powercons
+	This command is used to set the local transmit power constraint.
+	Value is in dbm unit. This command is only used for ad-hoc start.
+
+	Usage:
+		iwpriv mlanX powercons [n]
+
+	Examples:
+		iwpriv mlanX powercons          : get the current setting
+		iwpriv mlanX powercons 12       : set local power constraint to 12 dbm
+
+htstreamcfg
+	This command is used to set/get HT stream configuration.
+	The setting only takes effect in next association.
+
+	Usage:
+		iwpriv mlanX htstreamcfg [n]
+
+	where <n>
+		0x11: HT stream 1x1 mode
+		0x22: HT stream 2x2 mode
+
+	Examples:
+		iwpriv mlan0 htstreamcfg        : Get current setting
+		iwpriv mlan0 htstreamcfg 0x11   : Set HT stream 1x1 mode
+		iwpriv mlan0 htstreamcfg 0x22   : Set HT stream 2x2 mode
+
+ipaddr
+	This command is used to set/get IP address.
+
+	Usage:
+		iwpriv mlanX ipaddr ["<op>;<ipaddr>"]
+
+	where <op>
+		0: Remove the IP address
+		bit 0: Set IP address for broadcast ARP filter, which will be auto enabled
+		       in next host sleep configuration
+		bit 1: Set IP address for auto broadcast ARP response
+
+	Examples:
+		iwpriv mlan0 ipaddr                 : Get current settings
+		iwpriv mlan0 ipaddr "0"             : Remove IP address
+		iwpriv mlan0 ipaddr "1;192.168.0.5" : Set IP address for ARP filter
+		iwpriv mlan0 ipaddr "3;192.168.0.6" : Set IP address for ARP filter
+		                                    : and auto ARP response
+
+macctrl
+	This command is used to set/get MAC control.
+	It's recommended to read the current setting first to avoid override issue.
+
+	Usage:
+		iwpriv mlanX macctrl [n]
+
+	where <n>
+		bit 0:  Rx enabled
+		bit 1:  Tx enabled
+		bit 3:  WEP enabled
+		bit 4:  EthernetII enabled
+		bit 7:  Promiscuous enabled
+		bit 8:  All multicast enabled
+		bit 9:  RTS/CTS enabled (0: CTS to self)
+		bit 11: Force 11n protection disabled
+		bit 12: Ad-hoc g protection disabled
+		...
+
+	Examples:
+		iwpriv mlan0 macctrl            : Get current MAC control
+		iwpriv mlan0 macctrl 0x13       : Set Tx/Rx on and EthernetII on
+		iwpriv mlan0 macctrl 0x813      : Set Tx/Rx on and EthernetII on
+		                                : Disable force 11n protection
+
+dfstesting
+	This command is used to set/get settings for DFS testing.
+
+	Usage:
+	    iwpriv mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+
+	where <user_cac_pd> is user-configured Channel Availability Check in msec
+                        0 = disable, use default period (60000)
+                        1-65535 = enable with that period
+	where <user_nop_pd> is user-configured Non-Occupancy Period in sec
+                        0 = disable, use default period (1800)
+                        1-65535 = enable with that period
+	where <no_chan_change> is enable/disable no channel change on radar
+                           0 = disable, 1 = enable (overrides below)
+	where <fixed_chan_num> is user-configured channel to change to on radar
+                           0 = disable, 1-255 = enable with that channel
+                           (channel validity for region, etc. is not checked)
+                           (only takes effect if no_chan_change = 0)
+
+	Examples:
+		iwpriv mlan0 dfstesting             : Get current dfstesting settings
+		iwpriv mlan0 dfstesting 2000 0 0 0  : user_cac=2sec, others disabled/default
+		iwpriv mlan0 dfstesting 0 0 1 0     : only no_chan_change enabled
+		iwpriv mlan0 dfstesting 0 120 0 64  : user_nop=2min, force chan 64 on radar
+
+thermal
+	This command is used to get the current thermal reading.
+
+	Examples:
+		iwpriv mlan0 thermal            : Get thermal reading
+
+indrstcfg
+    This command is used to set/get settings for independent reset mode
+
+    Usage:
+        iwpriv mlanX indrstcfg <ir_mode> [gpio_pin]
+
+    where <ir_mode>  is independent reset mode
+                     0 = disable independent reset
+                     1 = enable out band and disable in band
+                     2 = enable in band and disable out band
+    where <gpio_pin> is user-configured gpio pin number to be used for oob mode
+                     0xFF = use FW default gpio assignment
+                     0-15 = gpio pin number
+
+    Examples:
+        iwpriv mlan0 indrstcfg              : Get current settings
+        iwpriv mlan0 indrstcfg 1 14         : Enable oob_mode with gpio pin 14
+        iwpriv mlan0 indrstcfg 1 0xff       : Enable oob_mode with default gpio pin
+        iwpriv mlan0 indrstcfg 0            : Disable ir_mode
+        iwpriv mlan0 indrstcfg 2            : Enable in band reset mode
+
+
+===============================================================================
+		U S E R  M A N U A L  F O R  M L A N C O N F I G
+
+NAME
+mlanconfig - configure the additional parameters available for the Marvell mdriver.
+
+SYNOPSIS
+mlanconfig -v
+mlanconfig <mlanX> <command> [parameters] ...
+
+mlanconfig mlanX hostcmd <bg_scan.conf> bgscfg
+mlanconfig mlanX hostcmd <requesttpc.conf> requesttpc
+mlanconfig mlanX hostcmd <crypto_test.conf> crypto_test
+mlanconfig mlanX hostcmd <subevent.conf> subevent_get
+mlanconfig mlanX hostcmd <subevent.conf> subevent_set
+mlanconfig mlanX hostcmd <auto_tx.conf> auto_tx_get
+mlanconfig mlanX hostcmd <auto_tx.conf> nat_keep_alive
+mlanconfig mlanX hostcmd <auto_tx.conf> auto_tx_unreg
+mlanconfig mlanX hostcmd <txrate_cfg.conf> txrate_cfg_get
+mlanconfig mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bg
+mlanconfig mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bgn
+mlanconfig mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_cfg_get
+mlanconfig mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_2g_cfg_set
+mlanconfig mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_5g_cfg_set
+mlanconfig mlanX hostcmd <pad_cfg.conf> pad_cfg_get
+mlanconfig mlanX hostcmd <pad_cfg.conf> pad_cfg_set
+mlanconfig mlanX hostcmd <11n_2040coex.conf> 2040coex
+mlanconfig mlanX hostcmd <robust_btc.conf> mode_get
+mlanconfig mlanX hostcmd <robust_btc.conf> mode_timeshare
+mlanconfig mlanX hostcmd <robust_btc.conf> mode_spatial
+mlanconfig mlanX hostcmd <robust_btc.conf> generictime
+mlanconfig mlanX hostcmd <robust_btc.conf> a2dptime
+mlanconfig mlanX hostcmd <robust_btc.conf> inquirytim
+mlanconfig mlanX hostcmd <robust_btc.conf> ap_generictime
+mlanconfig mlanX hostcmd <robust_btc.conf> ap_a2dptime
+mlanconfig mlanX hostcmd <robust_btc.conf> ap_inquirytime
+mlanconfig mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_get
+mlanconfig mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_set
+mlanconfig mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_disable
+mlanconfig mlanX arpfilter <arpfilter.conf>
+mlanconfig mlanX mefcfg <mef.conf>
+mlanconfig mlanX cfgdata <register type> <conf file>
+mlanconfig mlanX sdcmd52rw <FN no.> <address> [data]
+mlanconfig mlanX sdcmd53rw <FN no.> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+mlanconfig mlanX setuserscan [ARGS]
+mlanconfig mlanX getscantable [ARGS]
+mlanconfig mlanX addts <filename.conf> <section# of tspec> <timeout in ms>
+mlanconfig mlanX delts <filename.conf> <section# of tspec>
+mlanconfig mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+mlanconfig mlanX qconfig get [Queue Id: 0-3]
+mlanconfig mlanX qconfig def [Queue Id: 0-3]
+mlanconfig mlanX qstats on  [Queue Id: 0-3]
+mlanconfig mlanX qstats off [Queue Id: 0-3]
+mlanconfig mlanX qstats get [Queue Id: 0-3]
+mlanconfig mlanX qstatus
+mlanconfig mlanX ts_status
+mlanconfig mlanX regrdwr <type> <offset> [value]
+mlanconfig mlanX memrdwr <address> [value]
+mlanconfig mlanX customie <index> <mask> <IE buffer>
+mlanconfig mlanX tdls_config <0/1>
+mlanconfig mlanX tdls_setinfo <tdls.conf>
+mlanconfig mlanX tdls_setup <tdls.conf>
+mlanconfig mlanX tdls_discovery <tdls.conf>
+mlanconfig mlanX tdls_teardown <tdls.conf>
+mlanconfig mlanX tdls_powermode <tdls.conf>
+mlanconfig mlanX tdls_channel_switch <tdls.conf>
+mlanconfig mlanX tdls_stop_channel_switch <tdls.conf>
+mlanconfig mlanX tdls_cs_params <tdls.conf>
+mlanconfig mlanX tdls_disable_cs <0/1>
+mlanconfig mlanX tdls_link_status
+mlanconfig mlanX tdls_debug "wrong_bss" <0/1>
+mlanconfig mlanX tdls_debug "setup_existing_link" <0/1>
+mlanconfig mlanX tdls_debug "fail_setup_confirm" <0/1>
+mlanconfig mlanX tdls_debug "setup_with_prohibited" <0/1>
+mlanconfig mlanX tdls_debug "higher_lower_mac" <0/1>
+mlanconfig mlanX tdls_debug "ignore_key_expiry" <0/1>
+mlanconfig mlanX tdls_debug "allow_weak_security" <0/1>
+mlanconfig mlanX tdls_debug "stop_rx" <0/1>
+mlanconfig mlanX tdls_debug "cs_im_return" <0/1>
+mlanconfig mlanX mgmtframetx <mgmt_frame.conf>
+
+
+DESCRIPTION
+
+Those commands are used in Marvell specific application called mlanconfig.
+
+===========
+-v
+	This command is used to display the version of mlanconfig utility.
+	Usage:
+		mlanconfig -v
+
+hostcmd bgscfg
+	This command is used to configure the various parameters for PPS/UAPSD
+	or normal background scan.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/bg_scan.conf bgscfg
+
+hostcmd requesttpc
+	This command is used to request 802.11H TPC info.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/requesttpc.conf requesttpc
+
+hostcmd crypto_test
+	This command is used to test the encryption/decryption API of the firmware.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/crypto_test.conf crypto_test
+
+hostcmd subevent_get
+hostcmd subevent_set
+	This command is used to get/set the configurations for event descriptor
+	interface command.
+	subsvent_get: get subscribed event parameters
+	subsvent_set: set subscribed event parameters
+
+	Usage:
+		mlanconfig mlanX hostcmd config/subevent.conf subevent_get
+		mlanconfig mlanX hostcmd config/subevent.conf subevent_set
+
+hostcmd auto_tx_get
+hostcmd nat_keep_alive
+hostcmd auto_tx_unreg
+	This command is used to configures the Frame Auto Transmission parameters.
+	auto_tx_get: get auto_tx parameters
+	nat_keep_alive: register to firmware for sending NAT Keep Alive packet
+	auto_tx_unreg: unregister to firmware auto_tx
+
+	Usage:
+		mlanconfig mlanX hostcmd config/auto_tx.conf auto_tx_get
+		mlanconfig mlanX hostcmd config/auto_tx.conf nat_keep_alive
+		mlanconfig mlanX hostcmd config/auto_tx.conf auto_tx_unreg
+
+hostcmd txrate_cfg_get
+hostcmd txrate_cfg_set_bg
+hostcmd txrate_cfg_set_bgn
+	This command is used to set/get the transmit data rate.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_get
+		mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bg
+		mlanconfig mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bgn
+
+hostcmd txpwrlimit_cfg_get
+hostcmd txpwrlimit_2g_cfg_set
+hostcmd txpwrlimit_5g_cfg_set
+	This command is used to set/get the configuration data of Tx power limitation.
+	Note: The configuration set should be issued when STA is disconnected.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get
+		mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set
+		mlanconfig mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set
+
+hostcmd pad_cfg_get
+hostcmd pad_cfg_set
+	This command is used to set/get the configuration data for PAD OR.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/pad_cfg.conf pad_cfg_get
+		mlanconfig mlanX hostcmd config/pad_cfg.conf pad_cfg_set
+
+hostcmd 2040coex
+	This command is used to send the 11n 20/40 Coex command to firmware.
+	Firmware will send 11n 20/40 Coex management action frame to AP.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/11n_2040coex.conf 2040coex
+
+hostcmd mode_get
+hostcmd mode_timeshare
+hostcmd mode_spatial
+	This command is used to get/set Robust BT Coex.
+	mode_get:       get the current mode
+	mode_timeshare: set Robust BT Coex to timeshare mode  (default on 1x1 chips)
+	mode_spatial:   set Robust BT Coex to spatial mode    (only for, and default on 2x2 chips)
+
+	Usage:
+		mlanconfig mlanX hostcmd config/robust_btc.conf mode_get
+		mlanconfig mlanX hostcmd config/robust_btc.conf mode_timeshare
+		mlanconfig mlanX hostcmd config/robust_btc.conf mode_spatial
+
+hostcmd generictime
+hostcmd a2dptime
+hostcmd inquirytime
+hostcmd ap_generictime
+hostcmd ap_a2dptime
+hostcmd ap_inquirytime
+        This command is used to configure the time slice of COEX (only works in timeshare mode)
+        generictime:       configure the Bttime and Wlantime in Station Generic case
+        a2dptime:          configure the Bttime and Wlantime in Station A2DP case
+        inquirytime:       configure the Bttime and Wlantime in Station Inquiry case
+        ap_generictime:    configure the Bttime and Wlantime in Ap Generic case
+        ap_a2dptime:       configure the Bttime and Wlantime in Ap A2DP case
+        ap_inquirytime:    configure the Bttime and Wlantime in Ap Inquiry case
+
+    Usage:
+                mlanutl mlanX hostcmd config/robust_btc.conf generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf inquirytim
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime
+
+hostcmd sdio_pulldown_get
+hostcmd sdio_pulldown_set
+hostcmd sdio_pulldown_disable
+	This command is used to set/get the settings of pulling up and
+	pulling down of SDIO lines.
+
+	Usage:
+		mlanconfig mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_get
+		mlanconfig mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_set
+		mlanconfig mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_disable
+
+arpfilter
+	This command is used to configure the ARP filtering parameters.
+
+	Usage:
+		mlanconfig mlanX arpfilter config/arpfilter.conf
+
+mefcfg
+	This command is used to set MEF settings.
+
+	Usage:
+		mlanconfig mlanX mefcfg config/mef.conf
+
+cfgdata
+	This command is used to set/get the configuration data to/from firmware.
+
+	Usage:
+		mlanconfig mlanX cfgdata <type> <.conf file name>
+		This command is used to set the cfg data in the .conf file to firmware.
+
+		mlanconfig mlanX cfgdata <type>
+		This command is used to get the cfg data from firmware and display
+		on to the console.
+
+	Where the value of <type> field is:
+		2   -- Cal data download and <.conf file name> is cal_data.conf
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanconfig mlanX sdcmd52rw <function number> <register address> [value]
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+    Examples:
+		mlanconfig mlan0 sdcmd52rw 1 3
+		mlanconfig mlan0 sdcmd52rw 1 1 0x3f
+
+sdcmd53rw
+	This command is used to issue a CMD53 read/write data in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanconfig mlanX sdcmd53rw <func> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+
+	where the parameters are,
+		<func>:     function number (0/1/2/..)
+		<address>:  data address
+		<mode>:     byte mode/block mode (0/1)
+		<blksize>:  block size (32/64/../512, NA for byte mode)
+		<blknum>:   block number or byte number
+		<data1> ... <dataN>:  data for write
+
+	Note: The total data length is block size * block number for block mode
+	or byte number for byte mode. The max data length is 2000-byte.
+	For write the data pattern will be duplicated to data buffer.
+
+	Examples:
+		mlanconfig mlan0 sdcmd53rw 0 0x8000 1 0x40 2
+		mlanconfig mlan0 sdcmd53rw 1 0x10000 0 1 5 0x0a 0x0b 0x0c 0x0d 0x0e
+
+setuserscan
+	Initiate a customized scan and retrieve the results
+
+	Usage:
+		mlanconfig mlanX setuserscan [ARGS]
+
+	Where [ARGS]:
+	  ssid="[SSID]"            specify a SSID filter for the scan
+	  chan=[chan#][band][mode] where band is [a,b,g,n] and mode is
+	                           blank for active or 'p' for passive
+	  bssid=xx:xx:xx:xx:xx:xx  specify a BSSID filter for the scan
+	  wc="[WILDCARD SSID]"     specify a UNIX pattern matching filter (using *
+	                           and ?) for SSIDs found in a broadcast probe
+	  keep=[0 or 1]            keep the previous scan results (1), discard (0)
+	  dur=[scan time]          time to scan for each channel in milliseconds
+	  gap=[time gap]           Time gap between two scans in milliseconds
+	  probes=[#]               number of probe requests to send on each chan
+	                           for each broadcast probe required and each SSID
+	                           specific probe required (1-4)
+	  type=[1,2,3]             BSS type: 1 (Infra), 2(Adhoc), 3(Any)
+
+	Any combination of the above arguments can be supplied on the command line.
+	If the chan token is absent, a full channel scan will be completed by driver.
+	If the dur or probes tokens are absent, the driver default setting will be
+	used. The bssid and ssid fields, if blank, will produce an unfiltered scan.
+	It's allowed to input multiple ssid/wc entries, the max entry number is 10.
+	The type field will default to 3 (Any) and the keep field will default to 0
+	(Discard).
+
+	Examples:
+	1) Perform an active scan on channels 1, 6, and 11 in the 'g' band:
+		setuserscan chan=1g,6g,11g
+
+	2) Perform a passive scan on channel 11 for 20 ms:
+		setuserscan chan=11gp dur=20
+
+	3) Perform an active scan on channels 1, 6, and 11; and a passive scan on
+	   channel 36 in the 'a' band:
+		setuserscan chan=1g,6g,11g,36ap
+
+	4) Perform an active scan on channel 6 and 36 for specific SSID:
+		setuserscan chan=6g,36a ssid=TestAP1 ssid=TestAP2
+
+	5) Scan all available channels (B/G/N, A bands) for a specific BSSID, keep
+	   the current scan table intact, update existing or append new scan data:
+		setuserscan bssid=00:50:43:20:12:82 keep=1
+
+	6) Scan channel 6, for all infrastructure networks, sending two probe
+	   requests.  Keep the previous scan table intact. Update any duplicate
+	   BSSID/SSID matches with the new scan data:
+		setuserscan chan=6g type=1 probes=2 keep=1
+
+	7) Scan channel 1 and 6, for all networks matching the Mrvl*AP
+	   or AP*Mrvl? patterns and for MrvlTst SSID.  Generate 3 broadcast
+	   probes for the patterns and 3 SSID specific probes for MrvlTst on
+	   both channel 1 and channel 6.
+		setuserscan chan=1g,6g probes=3 wc="Mrvl*AP" wc="AP*Mrvl?" ssid="MrvlTst"
+
+	8) Scan all the channels for specified band.
+		setuserscan chan=0g
+
+	9) Scan channel 1 and 6, send 3 probe requests, scan each channel for 40 ms
+	   with time gap of 50ms between 2 scans
+		setuserscan chan=1g,6g probes=3 dur=40 gap=50
+
+	All entries in the scan table (not just the new scan data when keep=1)
+	will be displayed upon completion by use of the getscantable ioctl.
+
+getscantable
+	Display the current contents of the driver scan table
+
+	Usage:
+		mlanconfig mlanX getscantable
+		mlanconfig mlanX getscantable [#]
+		mlanconfig mlanX getscantable tsf
+		mlanconfig mlanX getscantable help
+
+	1) Without argument, the entire scantable is displayed.
+	2) Specifying a # will display detailed information about a specific scan
+	   table entry.  '0' displays driver cached information regarding the
+	   current association (if any).
+	3) The tsf argument will display the entire scan table with the recorded
+	   TSF timestamp for the entry.
+	4) The help argument will display the legend for the capability field.
+
+addts
+	Send an ADDTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in an ADDTS request to the associated AP.
+
+	Return the execution status of the command as well as the ADDTS response
+	  from the AP if any.
+
+	Usage:
+		mlanconfig mlanX addts <filename.conf> <section# of tspec> <timeout(ms)>
+
+delts
+	Send a DELTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in a DELTS request to the associated AP.
+
+	Return the execution status of the command.  There is no response to a
+	  DELTS from the AP.
+
+	Usage:
+		mlanconfig mlanX delts <filename.conf> <section# of tspec>
+
+qconfig
+	Send a WMM AC Queue configuration command to get/set/default params
+
+	Configure or get the parameters of a WMM AC queue. The command takes
+	  an optional Queue Id as a last parameter.  Without the queue id, all
+	  queues will be acted upon.
+
+	Usage:
+		mlanconfig mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+		mlanconfig mlanX qconfig get [Queue Id: 0-3]
+		mlanconfig mlanX qconfig def [Queue Id: 0-3]
+
+qstats
+	Turn on/off or retrieve and clear the queue statistics for an AC
+
+	Turn the queue statistics collection on/off for a given AC or retrieve the
+	  current accumulated stats and clear them from the firmware. The command
+	  takes an optional Queue Id as a last parameter. Without the queue id,
+	  all queues will be acted upon.
+
+	Usage:
+		mlanconfig mlanX qstats on  [Queue Id: 0-3]
+		mlanconfig mlanX qstats off [Queue Id: 0-3]
+		mlanconfig mlanX qstats get [Queue Id: 0-3]
+
+qstatus
+	This command retrieves the current status of the WMM queues. If WMM
+	  is enabled then it displays the information for each AC in a table.
+
+	Usage:
+		mlanconfig mlanX qstatus
+
+ts_status
+	This command queries the FW for the status of TSIDs 0 through 7
+	  configured via call admission control and displays the results in a
+	  table.
+
+	Usage:
+		mlanconfig mlanX ts_status
+
+regrdwr
+	This command is used to read/write the adapter register.
+
+	Usage:
+		mlanconfig mlanX regrdwr <type> <offset> [value]
+
+	where the parameters are,
+		<type>:     1:MAC/SOC, 2:BBP, 3:RF, 5:CAU
+		<offset>:   offset of register
+		[value]:    value to be written
+
+	Examples:
+		mlanconfig mlan0 regrdwr 1 0xa060   : Read the MAC register
+		mlanconfig mlan0 regrdwr 1 0xa794 0x80000000
+		                                    : Write 0x80000000 to MAC register
+
+memrdwr
+	This command is used to read/write the adapter memory.
+
+	Usage:
+		mlanconfig mlanX memrdwr <address> [value]
+
+	where the parameters are,
+		<address>:  memory address
+		[value]:    value to be written
+
+	Examples:
+		mlanconfig mlan0 memrdwr 0x80000000  : Read memory address 0x80000000
+		mlanconfig mlan0 memrdwr 0x80000000 0xffffffff
+		                                     : Write 0xffffffff to memory address 0x80000000
+
+customie
+	This command is used to set or get custom IEs for management frames.
+
+	Usage : customie [INDEX] [MASK] [IEBuffer]
+        empty - Get all IE settings
+        INDEX:  0 - Get/Set IE index 0 setting
+                1 - Get/Set IE index 1 setting
+                2 - Get/Set IE index 2 setting
+               MAX IE Index depends on device memory.
+
+               -1 - Append/Delete IE automatically
+                    Delete will delete the IE from the matching IE buffer
+                    Append will append the IE to the buffer with the same mask
+        MASK :  Management subtype mask value as per bit definitions
+             :  Bit 0 - Association request
+             :  Bit 1 - Association response
+             :  Bit 2 - Reassociation request
+             :  Bit 3 - Reassociation response
+             :  Bit 4 - Probe request
+             :  Bit 5 - Probe response
+             :  Bit 8 - Beacon
+        MASK :  MASK = 0 to clear the mask and the IE buffer
+        IEBuffer :  IE Buffer in hex (max 256 bytes)
+                    The Buffer should not be space separated.
+
+	Example:
+	 ./mlanconfig mlan0 customie
+		Get IE buffer, subtype mask settings for all indices.
+
+	./mlanconfig mlan0 customie 1
+		Get IE buffer and subtype mask for the Index = 1.
+
+	./mlanconfig mlan0 customie 2 0
+		Clear IE buffer and mask value for Index = 2.
+
+	./mlanconfig mlan0 customie 3 0x101 0xdd051234567890
+		Set IE buffer and mask value for Index = 3.
+
+	./mlanconfig mlan0 customie -1 0x101 0xdd051234567890
+		Append the specified IEBuffer at index with mask value of 0x101.
+
+	./mlanconfig mlan0 customie -1 0 0xdd051234567890
+		Delete the specified IEBuffer from all the IEs.
+
+	./mlanconfig mlan0 customie 2 0 0xdd051234567890
+		Delete the specified IEBuffer from the IEs at index 2.
+
+tdls_config
+	This command is used to enable/disable TDLS on device.
+
+	Usage : tdls_config <0/1>
+		1: Enable TDLS
+		0: Disable TDLS
+tdls_setinfo
+	This command is used for setting the capabilities of the TDLS station.
+
+        Usage : tdls_setinfo <tdls.conf>
+		Set capabilities of TDLS station.
+tdls_setup
+	This command is used to send TDLS setup request.
+
+	Usage: tdls_setup <tdls.conf>
+                Send TDLS setup request.
+tdls_discovery
+	This command is used to request TDLS discovery.
+
+	Usage : tdls_discovery <tdls.conf>
+        	Request TDLS discovery.
+tdls_teardown
+	This command is used to send TDLS teardown request.
+
+	Usage : tdls_teardown <tdls.conf>
+		Request teardown of TDLS link.
+tdls_powermode
+	This command is used to send TDLS powermode request.
+
+	Usage : tdls_powermode <tdls.conf>
+		Send TDLS powermode (either 0:Active, 1:PowerSave) command.
+tdls_channel_switch
+	This command is used to send TDLS channel switch request.
+
+	Usage : tdls_channel_switch <tdls.conf>
+		Send TDLS channel switch command.
+tdls_stop_channel_switch
+	This command is used to send stop TDLS channel switch request.
+
+	Usage : tdls_stop_channel_switch <tdls.conf>
+		Send stop TDLS channel switch command.
+tdls_cs_params
+	This command is used to set TDLS channel switch params
+
+	Usage : tdls_cs_params <tdls.conf>
+		Set TDLS channel switch params.
+tdls_disable_cs
+	This command is used to disable TDLS channel switch
+
+	Usage : tdls_disable_cs <0/1>
+		Disable TDLS channel switch.
+tdls_link_status [peer_mac_address]
+	This command is used to get link information about TDLS links or
+    a TDLS link correponding to peer mac address.
+
+	Usage : tdls_link_status
+		Send TDLS command to get current link status.
+tdls_debug
+	This command is used for FW debug functionality and tests.
+
+mgmtframetx
+	This command is used to send mgmt frame
+
+	Usage:
+		mlanconfig mlanX mgmtframetx <mgmt_frame.conf>
+
+===============================================================================
+                U S E R  M A N U A L  F O R  DRIVER COMMAND
+
+NAME
+DRIVER COMMAND - This command is Marvell private command, it can enable and
+                 configure Roaming offload and provide the interface between
+                 between WPA_Supplicant and the Marvell mdriver
+SYNOPSIS
+WPA_CLI: DRIVER SETROAMOFFLOAD data1
+WPA_CLI: DRIVER SETROAMOFFLOAD 0/1/2/3/4/5
+Enable/Disable Roaming offload with different mode:
+data1:
+          0 - disable
+          1 - enable and wakeup host based on roamOffloadAPlist
+          2 - enable and ignore the roamOffloadAPlist
+          3 - based on 2, and reconnect with the same BSSID when disconnect during host suspend
+          4 - based on 2, and reconnect with the same SSID when disconnect during host suspend
+          5 - based 0n 2, no roaming and only reconnect the specific BSSID/SSID when disconnect during host suspend
+
+WPA_CLI: DRIVER SETROAMOFFLAPLIST data1 [data2] ......
+WPA_CLI: DRIVER SETROAMOFFLAPLIST xx:xx:xx:xx:xx:xx
+Download roaming offload AP list to Driver:
+           xx:xx:xx:xx:xx:xx - the BSSID of AP, one or more than one BSSIDs are allowed.
+
+WPA_CLI: DRIVER CFGROAMOFFLOAD [data1 = xx]  [data2 = xx] [data3 = xx] [data4 = xx] .....
+WPA_CLI: DRIVER CFGROAMOFFLOAD [BSSID = xx:xx:xx:xx:xx:xx] [SSID = marvell_ap]
+                                [RETRY_COUNT = 0xff] [MAX_RSSI = 50] [MIN_RSSI=60]  [SETP_RSSI = 5] ......
+
+Configure Roaming offload:
+Note: all parameters are optional.
+Examples:
+       DRIVER CFGROAMOFFLOAD BSSID = 00:50:43:21:30:ca SSID = marvell_ap RETRY_COUNT = 0xff MAX_RSSI = 50
+
+===============================================================================
+		U S E R  M A N U A L  F O R  M L A N 2 0 4 0 C O E X
+
+NAME
+mlan2040coex - This application handles the 11n 20/40 coexistence operation for
+               the Marvell mdriver
+
+SYNOPSIS
+mlan2040coex [-d <n>] [-i <intfname>] [hvB]
+	-d = Device number (n)
+	-i = Interface name (intfname)
+	-h = Help
+	-v = Version
+	-B = Run the process in background
+Note: If device number (n) is not present, then 0 assumed.
+      If intfname is not present, then mlan0 assumed.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANEVENT
+
+NAME
+mlanevent.exe
+
+This tool can be used to listen for and obtain events from the driver
+through the netlink layer.
+
+----------------
+Supported events
+----------------
+STA_DEAUTH
+STA_ASSOC
+BSS_START
+BSS_IDLE
+BSS_ACTIVE
+
+-----------------
+Details of events
+-----------------
+
+STA_DEAUTH
+----------
+    For this event, the following information is shown:
+        + Deauthenticated STA MAC address.
+        + Reason for deauthentication.
+
+STA_ASSOC
+----------
+    For this event, the following information is shown:
+        + STA MAC address.
+
+BSS_START
+----------
+    For this event, the following information is shown:
+        + AP MAC address.
+
+BSS_IDLE
+----------
+    For this event, there is no associated information.
+
+BSS_ACTIVE
+----------
+    For this event, there is no associated information.
+
+===============================================================================
diff --git a/wlan_sd8997/README_MLAN b/wlan_sd8997/README_MLAN
new file mode 100644
index 0000000..ed9ac83
--- /dev/null
+++ b/wlan_sd8997/README_MLAN
@@ -0,0 +1,3727 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2008-2018, Marvell International Ltd.
+ All Rights Reserved
+
+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 up to 4.15.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy firmware image sd8787_uapsta.bin | sd8797_uapsta.bin | ... to
+	   /lib/firmware/mrvl/ directory, create the directory if it doesn't exist.
+	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
+		The default drv_mode is 7.
+			Bit 4 :  NAN
+
+		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 2)
+		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)
+		nan_name: Name of the NAN interface (default: "nan")
+		max_nan_bss: Number of NAN interfaces (default 1)
+	   For example, to install SD8787 driver,
+		insmod mlan.ko
+		insmod sd8787.ko [drv_mode=3] [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in STA only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=1 [fw_name=mrvl/sd8787_uapsta.bin]
+	   To load driver in uAP only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=2 [fw_name=mrvl/sd8787_uapsta.bin]
+
+	   To switch mode between STA only, uAP only and uAPSTA etc. in run time,
+		echo drv_mode=1 > /proc/mwlan/config		// STA mode
+		echo drv_mode=2 > /proc/mwlan/config		// uAP mode
+		echo drv_mode=3 > /proc/mwlan/config		// STA+uAP mode
+		echo drv_mode=7 > /proc/mwlan/config		// STA+uAP+WIFIDIRECT mode
+	c) Uninstall WLAN driver,
+		ifconfig mlanX down
+		ifconfig uapX down
+		rmmod sd8xxx
+		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>
+	  p2p_enh=0|1 <Disable enhanced P2P (default) | Enable enhanced P2P>
+	  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)>
+	  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>
+	  antcfg=0x11|0x13|0x33 <Bit0:Rx Path A, Bit1:Rx Path B, Bit 4:Tx Path A, Bit 5:Tx Path B>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.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
+	  cfg80211_drcs=1|0 <Enable DRCS support (default) | Disable DRCS support>
+	  reg_alpha2=<Regulatory alpha2 (default NULL)>
+	  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>
+	  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.>
+	  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>
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sd8xxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+
+	The following info are provided in /proc/net/mwlan/mlanX|uapX|wfdX/info,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX|uapX|wfdX/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/mlanX|uapX|wfdX/debug,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/mlanX|uapX|wfdX/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>
+	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>
+	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>
+	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/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/config      # read func 0 address 4
+		cat /proc/mwlan/config                          # display the register value
+		echo "sdcmd52rw= 1 3 0xf" > /proc/mwlan/config  # write 0xf to func 1 address 3
+
+	Issue debug_dump command through proc.
+	Usage:
+		echo "debug_dump" > /proc/mwlan/config
+
+	Examples:
+		echo "debug_dump" > /proc/mwlan/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 sd8xxx.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/config   trigger inband firmware reset and reload firmware
+       echo "fw_reload=2" > /proc/mwlan/config   trigger firmware reload
+       echo "fw_reload=3" > /proc/mwlan/config   set firmware reload flag in driver.
+
+    (Note: This feature will be supported on Robin3 and KF2.
+           For CAC-A2, it only work with the board which supports parallel fw download)
+
+
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANUTL
+
+NAME
+    mlanutl - configure the additional parameters available for Marvell mdriver.
+
+SYNOPSIS
+    mlanutl -v
+    mlanutl <mlanX|uapX|wfdx> <command> [parameters] ...
+
+	mlanutl mlanX 11dcfg
+	mlanutl mlanX 11dclrtbl
+	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 addts <filename.conf> <section# of tspec> <timeout in ms>
+	mlanutl mlanX adhocaes
+	mlanutl mlanX aggrpriotbl [<m0> <n0> <m1> <n1> ... <m7> <n7>]
+	mlanutl uapX aggrpriotbl [<m0> <n0> <m1> <n1> ... <m7> <n7>]
+	mlanutl mlanX amsduaggrctrl <n>
+	mlanutl mlanX antcfg [m] [n]
+	mlanutl mlanX/uapX mimoswitch [tx_antmode] [rx_antmode]
+	mlanutl mlanX arpfilter <arpfilter.conf>
+	mlanutl mlanX assocessid <"[essid]">
+	mlanutl mlanX assocessid_bssid <"[bssid] [essid]">
+	mlanutl mlanX associate "<bssid> <ssid>"
+	mlanutl mlanX atimwindow [n]
+	mlanutl mlanX authtype [n]
+	mlanutl mlanX autotdls [n]
+        mlanutl mlanX tdls_idle_time [n]
+        mlanutl uapX dfs_offload [n]
+	mlanutl mlanX bandcfg [l] [m] [n] [o]
+	mlanutl mlanX bcninterval [n]
+	mlanutl wfdX bssrole [l]
+	mlanutl mlanX cfgdata <register type> [<conf file>]
+	mlanutl mlanX cfpcode [m] [n]
+	mlanutl mlanX changraph [<load | anpi | anpiload> <loops>]
+	mlanutl mlanX coex_rx_winsize [m]
+	mlanutl mlanX countrycode [l]
+
+	mlanutl	mlanX cfpinfo
+	mlanutl uapX cfpinfo
+
+	mlanutl	mlanX acs [<chX> <chY> ... <chZ>]
+	mlanutl	uapX acs [<chX> <chY> ... <chZ>]
+
+	mlanutl mlanX customie [[[<index>] <mask>] <IEBuffer>]
+	mlanutl mlanX deauth [l]
+	mlanutl uapX deauth [l]
+	mlanutl mlanX deepsleep [l] [m]
+	mlanutl mlanX delba <l> [<m> <n>]
+	mlanutl uapX delba <l> [<m> <n>]
+	mlanutl mlanX delts <filename.conf> <section# of tspec>
+	mlanutl mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+	mlanutl mlanX dfs_repeater [n]
+	mlanutl mlanX drvdbg [n]
+	mlanutl mlanX esuppmode [l] [m] [n]
+	mlanutl mlanX extcapcfg [<ext_cap>]
+	mlanutl mlanX fwmacaddr [mac_addr]
+	mlanutl mlanX getdatarate
+	mlanutl uapX getdatarate
+	mlanutl mlanX getlog
+	mlanutl mlanX getscantable [ARGS]
+	mlanutl mlanX getsignal [m] [n]
+	mlanutl mlanX signalextcfg [m]
+	mlanutl mlanX getsignalextv2 [m]
+	mlanutl mlanX getsignalext [m]
+        mlanutl mlanX dyn_bw [n]
+	mlanutl uapX getstalist
+	mlanutl uapX channel_switch <switch mode> <oper class> <new channel> <switch count> <bandwidth>
+	mlanutl mlanX hostcmd <11n_2040coex.conf> 2040coex
+	mlanutl mlanX hostcmd <auto_tx.conf> auto_tx_get
+	mlanutl mlanX hostcmd <auto_tx.conf> auto_tx_unreg
+	mlanutl mlanX hostcmd <bg_scan.conf> bgscfg
+
+	mlanutl mlanX hostcmd <pkt_coalescing.conf> coalesce_cfg
+	mlanutl mlanX hostcmd <ed_mac_ctrl.conf> ed_mac_ctrl
+	mlanutl mlanX hostcmd <crypto_test.conf> crypto_test
+	mlanutl mlanX hostcmd <auto_tx.conf> nat_keep_alive
+	mlanutl mlanX hostcmd <pad_cfg.conf> pad_cfg_get
+	mlanutl mlanX hostcmd <pad_cfg.conf> pad_cfg_set
+	mlanutl mlanX hostcmd <requesttpc.conf> requesttpc
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_get
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_timeshare
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_spatial
+	mlanutl mlanX hostcmd <robust_btc.conf> mode_none
+	mlanutl mlanX hostcmd <robust_btc.conf> gpio_cfg
+	mlanutl mlanX hostcmd <robust_btc.conf> generictime
+	mlanutl mlanX hostcmd <robust_btc.conf> a2dptime
+	mlanutl mlanX hostcmd <robust_btc.conf> inquirytim
+	mlanutl mlanX hostcmd <robust_btc.conf> ap_generictime
+	mlanutl mlanX hostcmd <robust_btc.conf> ap_a2dptime
+	mlanutl mlanX hostcmd <robust_btc.conf> ap_inquirytime
+	mlanutl mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_disable
+	mlanutl mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_get
+	mlanutl mlanX hostcmd <sdio_pulldown.conf> sdio_pulldown_set
+	mlanutl mlanX hostcmd <subevent.conf> subevent_get
+	mlanutl mlanX hostcmd <subevent.conf> subevent_set
+	mlanutl mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_2g_cfg_set
+	mlanutl mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_5g_cfg_set
+	mlanutl mlanX hostcmd <txpwrlimit_cfg.conf> txpwrlimit_cfg_get
+	mlanutl mlanX hostcmd <txrate_cfg.conf> txrate_cfg_get
+	mlanutl mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bg
+	mlanutl mlanX hostcmd <txrate_cfg.conf> txrate_cfg_set_bgn
+	mlanutl mlanX hostcmd <conf> generate_raw <raw_data_file>
+	mlanutl mlanX hostcmd <fwdump.conf> fwdump
+
+	mlanutl mlanX hscfg [condition [[GPIO# [gap]]]] [ind_GPIO# [level]]
+	mlanutl mlanX hssetpara condition [GPIO# [gap]] [ind_GPIO# [level]]
+	mlanutl mlanX mgmtfilter <mgmtfilter.conf>
+	mlanutl mlanX auto_arp [n]
+	mlanutl mlanX htcapinfo [<m>] [<n>]
+	mlanutl mlanX htstreamcfg [n]
+	mlanutl mlanX httxbfcap [cap]
+	mlanutl mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData]"
+	mlanutl mlanX httxcfg [<m>] [<n>]
+	mlanutl mlanX inactivityto <n> <m> <l> [k]
+	mlanutl mlanX ipaddr ["<op>;<ipaddr>"]
+	mlanutl mlanX linkstats
+	mlanutl mlanX listeninterval [l]
+	mlanutl mlanX macctrl [n]
+	mlanutl uapX macctrl [n]
+	mlanutl mlanX mefcfg <mef.conf>
+	mlanutl mlanX memrdwr <address> [value]
+	mlanutl mlanX miracastcfg [l] [m] [n]
+	mlanutl mlanX mgmtframectrl [<mask>]
+	mlanutl uapX mgmtframectrl [<mask>]
+	mlanutl mlanX mgmtframetx <mgmt_frame.conf>
+	mlanutl mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+	mlanutl mlanX netmon [<act> [<filter> <band> <chan> [offset]]]
+	mlanutl mlanX offchannel [<l> <m> <n>]
+	mlanutl mlanX otpuserdata <l>
+	mlanutl mlanX passphrase [l]
+	mlanutl mlanX pb_bypass [data_1, data_2, ... data_n]
+	mlanutl mlanX pmfcfg <mfpc> <mfpr>
+	mlanutl mlanX port_ctrl [n]
+	mlanutl mlanX powercons [n]
+	mlanutl mlanX pscfg [k] [d] [l] ...
+	mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p]
+	mlanutl mlanX psmode [l]
+        mlanutl <interface> robustcoex <gpiocfg> [Enable/Disable] [gpionum] [gpiopolarity]
+        mlanutl <interface> keep_connect [Enable/Disable]
+	mlanutl mlanX qconfig def [Queue Id: 0-3]
+	mlanutl mlanX qconfig get [Queue Id: 0-3]
+	mlanutl mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+	mlanutl mlanX qoscfg
+	mlanutl mlanX qstatus
+	mlanutl mlanX radioctrl [n]
+	mlanutl mlanX rdeeprom <offset> <length>
+	mlanutl mlanX reassoctrl [n]
+	mlanutl mlanX regioncode [n]
+	mlanutl mlanX regrdwr <type> <offset> [value]
+	mlanutl mlanX rejectaddbareq [conditions]
+	mlanutl uapX rejectaddbareq [conditions]
+	mlanutl mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+	mlanutl mlanX sdcmd52rw <FN no.> <address> [data]
+	mlanutl mlanX sdcmd53rw <FN no.> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+	mlanutl mlanX sdioclock <n>
+	mlanutl mlanX setuserscan [ARGS]
+	mlanutl mlanX cancelscan
+	mlanutl mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+	mlanutl mlanX sleeppd [n]
+	mlanutl mlanX sysclock [clk1] [clk2] [clk3] [clk4]
+	mlanutl mlanX tcpackenh [l]
+	mlanutl mlanX tdls_channel_switch <tdls.conf>
+	mlanutl mlanX tdls_config <0/1>
+	mlanutl mlanX tdls_cs_params <tdls.conf>
+	mlanutl mlanX tdls_debug "allow_weak_security" <0/1>
+	mlanutl mlanX tdls_debug "cs_im_return" <0/1>
+	mlanutl mlanX tdls_debug "fail_setup_confirm" <0/1>
+	mlanutl mlanX tdls_debug "higher_lower_mac" <0/1>
+	mlanutl mlanX tdls_debug "ignore_key_expiry" <0/1>
+	mlanutl mlanX tdls_debug "setup_existing_link" <0/1>
+	mlanutl mlanX tdls_debug "setup_with_prohibited" <0/1>
+	mlanutl mlanX tdls_debug "stop_rx" <0/1>
+	mlanutl mlanX tdls_debug "wrong_bss" <0/1>
+	mlanutl mlanX tdls_disable_cs <0/1>
+	mlanutl mlanX tdls_discovery <tdls.conf>
+	mlanutl mlanX tdls_link_status
+	mlanutl mlanX tdls_powermode <tdls.conf>
+	mlanutl mlanX tdls_setinfo <tdls.conf>
+	mlanutl mlanX tdls_setup <tdls.conf>
+	mlanutl mlanX tdls_stop_channel_switch <tdls.conf>
+	mlanutl mlanX tdls_teardown <tdls.conf>
+	mlanutl mlanX thermal
+	mlanutl mlanX ts_status
+	mlanutl mlanX tsf
+	mlanutl mlanX txaggrctrl [m]
+	mlanutl mlanX txbufcfg
+	mlanutl mlanX txratecfg [l] [m] [n]
+	mlanutl uapX txratecfg [l] [m] [n]
+    mlanutl mlanX verext
+    mlanutl mlanX version
+	mlanutl mlanX vhtcfg <j> <k> [l] [m] [n] [o]
+	mlanutl uapX vhtcfg <j> <k> [l] [m] [n] [o]
+        mlanutl <interface> per_pkt_cfg [tx_rx_control] [type_num] [ether_type1 ether_type2 ...] [tx_rx_control] [type_num] [ether_type1 ether_type2 ...]
+        mlanutl <interface> dot11_txrx <send/recv> <options>
+	mlanutl mlanX wakeupreason
+	mlanutl uapX wakeupreason
+	mlanutl mlanX warmreset
+	mlanutl mlanX wpssession [n]
+	mlanutl mlanX wmmcfg [n]
+	mlanutl mlanX wmmparamcfg [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+				[AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+				[AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+				[AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+	mlanutl mlanX wwscfg [m]
+	mlanutl mlanX mc_cfg [n]
+	mlanutl mlanX mc_policy [n]
+	mlanutl mlanX mc_cfg_ext [c] [s] [u] [m] <a> <b> <d> <e>
+	mlanutl p2pX cfg_noa [h] [i] [j] [k] [l]
+	mlanutl p2pX cfg_opp_ps [m] [n]
+        mlanutl mlanX get_sensor_temp
+        mlanutl mlanX 11k_enable [n]
+        mlanutl mlanX neighbor_report
+        mlanutl <inteface> indrstcfg <ir_mode> [gpio_pin]
+
+        mlanutl <interface> fwwakeupmethod <method> <GPIO_pin>
+
+        mlanutl uapX ctrldeauth <n>
+
+        mlanutl mlanX/uapX bootsleep <1/0>
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell 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.
+
+11dcfg
+	This command is used to control 11D. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 11dcfg 1           : Enable 11D
+		mlanutl mlan0 11dcfg             : Get 11D status
+
+11dclrtbl
+	This command is used to clear the 11D channel table.
+
+	Usage:
+		mlanutl mlanX 11dclrtbl
+
+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.
+
+addts
+	Send an ADDTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in an ADDTS request to the associated AP.
+
+	Return the execution status of the command as well as the ADDTS response
+	  from the AP if any.
+
+	Usage:
+		mlanutl mlanX addts <filename.conf> <section# of tspec> <timeout(ms)>
+
+adhocaes
+	This command is used to set/get the AES key, when the station is in ad-hoc mode.
+	Note: This command is only available in disconnected state.
+
+	where value can be any 16 byte value.
+
+	Examples:
+		mlanutl mlan0 adhocaes           : Get ad-hoc aes key
+		mlanutl mlan0 adhocaes "1;12345678901234567890123456789012"
+		                                : Set ad-hoc aes key
+		mlanutl mlan0 adhocaes 2         : Clear ad-hoc aes key
+
+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.
+
+amsduaggrctrl
+	This command could be used to enable/disable a feature where firmware gives feedback to driver
+	regarding the optimal AMSDU buffer size to use with the current rate. Firmware will use the
+	current rate to decide the buffer size we could transmit. The max buffer size will still be
+	limited by buffer size provided in txbufcfg. (i.e. if the txbufcfg is 4K, then we could only transmit
+	4K/2K AMSDU packets, if the txbufcfg is 8K then we could transmit 8k/4k/2k based on current rate)
+
+	If enabled AMSDU buffer size at various rates will be as follows
+
+	1.	Legacy B/G rate.
+		No AMSDU aggregation.
+
+	2.	BW20 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 3, 2:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 1, 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 4, 3:
+			a	4K aggregation size (if TX buffer size is 8K/4K)
+			b	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	3.	BW40 HT Rate:
+		When TX rate goes down,
+		MCS 7, 6, 5, 4, 3, 2, 1:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 0:
+			a	No aggregation
+
+		When TX rate goes up,
+		MCS 7, 6, 5, 4, 3:
+			a	8K aggregation size (if TX buffer size is 8K)
+			b	4K aggregation size (if TX buffer size is 4K)
+			c	2K aggregation size (if TX buffer size is 2K)
+
+		MCS 2, 1, 0:
+			a	No aggregation
+
+	where <n> is 0/1 (for disable/enable)
+
+	eg:
+	mlanutl mlan0 amsduaggrctrl 1 - Enable this feature
+	mlanutl mlan0 amsduaggrctrl 0 - Disable this feature
+	mlanutl mlan0 amsduaggrctrl - This will get the enable/disable flag
+	and the current AMSDU buffer size). The AMSDU buffer size returned is only
+	valid after association as before association there is no rate info.
+
+	Note:- This command to enable/disable could be given anytime (before/after
+			association). This feature is enabled by default by the driver during
+			initialization.
+
+antcfg
+	This command is used to set/get the mode of Tx/Rx path.
+
+    For chip which support STREAM_2X2
+	where value of m is:
+		Bit 0   -- Tx Path A or Tx/Rx Path A if [n] is not provided
+		Bit 1   -- Tx Path B or Tx/Rx Path B if [n] is not provided
+		Bit 0-1 -- Tx Path A+B or Tx/Rx Path A+B if [n] is not provided
+	where value of n is:
+		Bit 0   -- Rx Path A
+		Bit 1   -- Rx Path B
+		Bit 0-1 -- Rx Path A+B
+	The Tx path setting (m) is used for both Tx and Rx if Rx path (n) is not provided.
+
+	Examples:
+		mlanutl mlan0 antcfg             : Get Tx and Rx path
+		mlanutl mlan0 antcfg 3           : Set Tx and Rx path to A+B
+		mlanutl mlan0 antcfg 1 3         : Set Tx path to A and Rx path to A+B
+
+mimoswitch
+	This command is used to do MIMO switch for 11n and 11ac mode and is available for all interfaces.
+        mlanutl mlanX/uapX mimoswitch [tx_antmode] [rx_antmode]
+
+	This command takes 2 conditions.
+	The supported options are:
+	   tx_antmode:	1 - ANTENNA A
+			2 - ANTENNA B
+			3 - ANTENNA AB
+	   rx_antmode:	1 - ANTENNA A
+                        2 - ANTENNA B
+                        3 - ANTENNA AB
+       Examples:
+                mlanutl mlan0/uap0 mimoswitch 1 1     : set Tx and Rx path to ANTENNA A
+                mlanutl mlna0/uap0 mimoswitch 2 2     : set Tx and Rx path to ANTENNA B
+                mlanutl mlan0/uap0 mimoswitch 3 3     : set Tx and Rx path to ANTENNA A+B
+                mlnautl mlan0/uap0 mimoswitch 1 3     : set Tx path to ANTENNA A and Rx path to ANTENNA A+B
+
+arpfilter
+	This command is used to configure the ARP filtering parameters.
+
+	Usage:
+		mlanutl mlanX arpfilter <arpfilter.conf>
+
+	Where the parameter is:
+		arpfilter.conf : The configuration file specifying ARP filtering parameters.
+
+	Example:
+		mlanutl mlan0 arpfilter config/arpfilter.conf
+
+assocessid
+	This command is used to assoc essid with asynced mode,
+	and driver will auto retry if driver auto assoc enabled.
+
+	Usage:
+		mlanutl mlanX assocessid <"[essid]">
+
+	Where
+	<"[essid]"> is the essid which need to be associated with asynced mode.
+
+	Examples:
+		mlanutl mlan0 assocessid "Marvell Micro AP"    : Associate to the ESSID "Marvell Micro AP"
+
+assocessid_bssid
+	This command is used to assoc AP by ssid/bssid pair with asynced mode,
+	and driver will auto retry if driver auto assoc enabled.
+
+	Usage:
+		mlanutl mlanX assocessid_bssid <"[bssid] [essid]">
+
+	Where
+	<"[bssid]"> is the bssid which need to be associated with asynced mode.
+	<"[essid]"> is the essid which need to be associated with asynced mode.
+
+	Examples:
+		mlanutl mlan0 assocessid_bssid "xx:xx:xx:xx:xx:xx Marvell Micro AP"   : Associate to the AP which ssid = "Marvell Micro AP", bssid = "xx:xx:xx:xx:xx:xx"
+
+associate
+	Request an association to a given SSID/BSSID pair. This the only accurate
+	way to pick a specific AP and ESS for an association. The entry must
+	already exist in the scan table for the association to be attempted.
+
+	mlanutl mlanX associate "xx:xx:xx:xx:xx:xx SSID"
+
+atimwindow
+	This command is used to set/get the ATIM window value in the station.
+	The range of ATIM window is 0 - 50.
+	Value of atim window should be less than the beacon interval.
+	Note: This command should be issued before ad-hoc start/join and ad-hoc
+	power save on.
+
+	Examples:
+		mlanutl mlan0 atimwindow 20      : Set atimwindow to 20
+		mlanutl mlan0 atimwindow         : Get atimwindow
+
+authtype
+	This command is used to set/get authentication type.
+
+	Usage:
+		mlanutl mlanX authtype [n]
+
+	where <n>
+		0: 802.11 open system authentication
+		1: 802.11 shared key authentication
+		255: allow open system or shared key authentication (default)
+
+	Examples:
+		mlanutl mlan0 authtype 0         : use open system authentication
+		mlanutl mlan0 authtype 1         : use shared key authentication
+		mlanutl mlan0 authtype 255       : allow open system or shared key authentication
+		mlanutl mlan0 authtype           : get current setting
+
+autotdls
+	This command is used to enable/disable auto TDLS.
+
+	Usage:
+		mlanutl mlanX autotdls [n]
+
+	where <n>
+		0: Disable auto tdls
+		1: Enable auto tdls
+
+	Examples:
+		mlanutl mlan0 autotdls 1         : enable auto TDLS
+		mlanutl mlan0 autotdls 0         : disable auto TDLS
+		mlanutl mlan0 autotdls           : get current setting
+
+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
+
+tdls_idle_time
+	This command is used to set/get TDLS idle timeout. The valid value is between 0-0xffff. When set to 0, the tdls_idle_time will use default value(60).
+
+	Usage:
+		mlanutl mlanX tdls_idle_time [n]
+
+	where <n>
+		TDLS idle timeout value
+
+	Examples:
+		mlanutl mlan0 tdls_idle_time 30        : set tdls_idle_time value to 30
+		mlanutl mlan0 tdls_idle_time 0         : use default tdls_idle_time value(60)
+		mlanutl mlan0 tdls_idle_time           : get current setting
+
+dfs_offload
+	This command is used to enable/disable DFS offload. The valid value is 0/1.
+	Note: The parameters can be set only in disconnected state.
+
+	Usage:
+		mlanutl uapX dfs_offload [n]
+
+	where <n>
+		Enable/disable
+
+	Examples:
+		mlanutl uap0 dfs_offload 1         : enable DFS offload
+		mlanutl uap0 dfs_offload 0         : disable DFS offload
+
+bandcfg
+	This command is used to set/get infra/ad-hoc band.
+	Note: This command is only available in disconnected state.
+
+	Usage:
+		mlanutl mlanX bandcfg [l] [m] [n] [o]
+
+	where the parameters:
+		[l]: Infrastructure band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+
+		     bit 5: AC 2.4G
+		     bit 6: AC 5G
+		[m]: Ad-hoc start band
+		     bit 0: B
+		     bit 1: G
+		     bit 2: A
+		     bit 3: GN
+		     bit 4: AN
+		     bit 5: AC 2.4G
+		     bit 6: AC 5G
+		[n]: Ad-hoc start channel
+		[o]: 0 - Bandwidth 20Mhz
+		     1 - HT Bandwidth 40Mhz above
+		     3 - HT Bandwidth 40Mhz below
+			 4 - VHT Bandwidth 80Mhz
+	Examples:
+		mlanutl mlan0 bandcfg            : Get infra/ad-hoc band and ad-hoc
+		                                  start channel configurations
+		mlanutl mlan0 bandcfg 1          : Set infra band to B only
+		mlanutl mlan0 bandcfg 3 2 6      : Set infra band to B/G, ad-hoc start band
+		                                  to G and ad-hoc start channel to 6
+		mlanutl mlan0 bandcfg 7 11 6 1   : Set infra band to B/G/A, ad-hoc start band
+		                                  to B/G/GN, ad-hoc start channel to 6 and
+		                                  secondary channel to above
+
+bcninterval
+	This command is used to set/get the beacon interval in ad-hoc mode.
+	The valid beacon interval is between 20 - 1000, default beacon
+	interval is 100.
+
+	Where <n>
+		Beacon interval in TU (Time Unit: 1024 us).
+
+	Examples:
+		mlanutl mlan0 bcninterval 200    : Set ad-hoc beacon interval to 200
+		mlanutl mlan0 bcninterval        : Get ad-hoc beacon interval
+
+bssrole
+	This command is used to set/get the BSS role.
+
+	Where
+	[l] is <bss_role>
+	<bss_role> - This parameter specifies the BSS role to set.
+		0       : STA
+		1       : uAP
+
+	Examples:
+		mlanutl wfd0 bssrole                 : Get the current BSS role
+		mlanutl wfd0 bssrole 1               : Set the current BSS role to uAP
+
+cfgdata
+	This command is used to set/get the configuration data to/from firmware.
+
+	Usage:
+		mlanutl mlanX cfgdata <type> [<.conf file name>]
+
+	Where the parameters are:
+		type :
+		        2 -- CAL data download and <.conf file name> is cal_data.conf
+		.conf file name : The configuration file used to set/get the configuration data.
+
+	Examples:
+		mlanutl mlan0 cfgdata 2
+			: This command is used to get and display the CAL data from firmware.
+
+cfpcode
+	This command is used to set/get the Channel-Frequency-Power table codes.
+	The region table can be selected through region code.
+	The current configuration is returned if no parameter provided.
+
+	where the parameters are,
+		[m]: code of the CFP table for 2.4GHz (0: unchanged)
+		[n]: code of the CFP table for 5GHz (0 or not provided: unchanged)
+
+	Examples:
+		mlanutl mlan0 cfpcode            : Get current configuration
+		mlanutl mlan0 cfpcode 0x30       : Set 2.4GHz CFP table code 0x30 (EU),
+		                                  keep 5GHz table unchanged
+		mlanutl mlan0 cfpcode 0x10 5     : Set 2.4GHz CFP table code 0x10 (USA)
+		                                  and 5GHz table code 5
+
+changraph
+	Displays 2-dimensional graph, plotting channel number along x-axis and
+	anpi or channel-load along y-axis, depending on whether it is an anpi graph
+	or a channel load graph.
+
+	Usage:
+		mlanutl mlanX changraph [<load | anpi | anpiload> <loops>]
+		where:
+			load:       Only channel vs channel-load graph is displayed
+			anpi:       Only channel vs Average Noise Power Indicator(ANPI)
+						graph is displayed
+			anpiload:   Both the graphs for anpi and for the load are displayed
+			loops:      This is used to calculate the number of times
+						the graph [load or anpi or both] will be printed
+
+coex_rx_winsize
+	This command is used to set/get control to coex RX window size
+
+	where value of m is:
+		0       -- Disable COEX RX winsize (default)
+		1       -- Enable COEX RX winsize
+
+	Examples:
+		mlanutl mlan0 coex_rx_winsize             : Get COEX RX winsize
+		mlanutl mlan0 coex_rx_winsize 1           : Enable COEX RX winsize
+
+countrycode
+	This command is used to set and get the country code.
+
+	Where
+	[l] is Country code
+
+	Examples:
+		mlanutl mlan0 countrycode            : Get current countrycode
+		mlanutl mlan0 countrycode CN         : Set countrycode as China (CN)
+
+cfpinfo
+	This command is used to get region, country, environment codes,
+	channel and power table information from the FW.
+
+	Examples:
+		mlanutl mlan0 cfpinfo		     : Display cfp tables
+		mlanutl uap0 cfpinfo
+
+acs
+	This command is used to issue acs scan, then FW will
+	report the best channel and channel statistics.
+	User could specify channels or not. If channel is not
+	specified, acs scan will be on all supported channels.
+
+	Examples:
+		mlanutl mlan0 acs		     : ACS scan on all supported channels
+		mlanutl uap0 acs		     : ACS scan on all supported channels
+		mlanutl mlan0 acs 5 6 7 8	     : ACS scan on 5 6 7 8 channels
+		mlanutl uap0 acs 1 2 3		     : ACS scan on 1 2 3 channels
+
+customie
+	This command is used to set or get custom IEs for management frames.
+
+	Usage:
+		mlanutl mlanX customie [[[<index>] <mask>] <IEBuffer>]
+
+	Where the parameter is:
+		empty - Get all IE settings
+		<index> :   0 - Get/Set IE index 0 setting
+		            1 - Get/Set IE index 1 setting
+		            2 - Get/Set IE index 2 setting
+		           MAX IE Index depends on device memory.
+		           -1 - Append/Delete IE automatically
+		                Delete will delete the IE from the matching IE buffer
+		                Append will append the IE to the buffer with the same mask
+		<mask>      :  Management subtype mask value as per bit definitions
+		            :  Bit 0 - Association request
+		            :  Bit 1 - Association response
+		            :  Bit 2 - Reassociation request
+		            :  Bit 3 - Reassociation response
+		            :  Bit 4 - Probe request
+		            :  Bit 5 - Probe response
+		            :  Bit 8 - Beacon
+		<mask>      :  mask = 0 to clear the mask and the IE buffer
+		<IEBuffer>  :  IE Buffer in hex (max 256 bytes)
+		               The Buffer should not be space separated.
+
+	Examples:
+		mlanutl mlan0 customie
+			: Get IE buffer, subtype mask settings for all indices.
+
+		mlanutl mlan0 customie 1
+			: Get IE buffer and subtype mask for the Index = 1.
+
+		mlanutl mlan0 customie 2 0
+			: Clear IE buffer and mask value for Index = 2.
+
+		mlanutl mlan0 customie 3 0x101 0xdd051234567890
+			: Set IE buffer and mask value for Index = 3.
+
+		mlanutl mlan0 customie -1 0x101 0xdd051234567890
+			: Append the specified IEBuffer at index with mask value of 0x101.
+
+		mlanutl mlan0 customie -1 0 0xdd051234567890
+			: Delete the specified IEBuffer from all the IEs.
+
+		mlanutl mlan0 customie 2 0 0xdd051234567890
+			: Delete the specified IEBuffer from the IEs at index 2.
+
+deauth
+	This command is used to send a de-authentication to an arbitrary AP.
+	If [l] is omitted, the driver will deauth the associated AP.
+	If in ad-hoc mode this command is used to stop beacon transmission
+	from the station and go into idle state.
+
+	When <l> is supplied as a MAC address, the driver will deauth the
+	  specified AP.  If the AP address matches the driver's associated AP,
+	  the driver will disconnect. Otherwise, the driver remains connected.
+
+	When this command is executed on AP interface, it is used to send
+	a de-authentication to associated station.
+
+deepsleep
+	This command is used to set/get auto deep sleep mode.
+
+	Usage:
+		mlanutl mlanX deepsleep [l] [m]
+
+	where the parameters are:
+		[l]: Enable/disable auto deep sleep mode (1/0)
+		[m]: Idle time in milliseconds after which firmware will put the device
+		     in deep sleep mode. Default value is 100 ms.
+
+	Examples:
+		mlanutl mlan0 deepsleep          : Display auto deep sleep mode
+		mlanutl mlan0 deepsleep 1        : Enable auto deep sleep mode, idle time unchanged
+		mlanutl mlan0 deepsleep 0        : Disable auto deep sleep mode
+		mlanutl mlan0 deepsleep 1 500    : Enable auto deep sleep mode with idle time 500 ms
+        Note:
+            Deepsleep must be disabled before changing idle time.
+
+delba
+	This command is used to delete either all Tx BA or all Rx BA or a specific BA stream
+	based on direction, TID and peer address.
+
+	where <l> [<m> <n>]
+		<l> - This is the direction of BA stream, Tx (bit 0), Rx (bit 1).
+		<m> - This is the TID (0-7, 0xff for all) of BA stream.
+		<n> - This is the peer MAC addres of BA stream.
+
+	eg:
+	mlanutl mlanX delba 2 - This command will delete all the Rx BA streams.
+	mlanutl mlanX delba 3 - This command will delete all the Tx and Rx BA streams.
+	mlanutl mlanX delba 1 0 - This command will delete all the Tx streams with TID 0.
+	mlanutl mlanX delba 2 0xff "00:11:22:33:44:55" - This command will delete all the Rx BA streams
+		with specified peer MAC address
+	mlanutl mlanX delba 1 3 "00:11:22:33:44:55" - This command will delete the Tx BA stream with
+		TID 3 and specified peer MAC address.
+
+delts
+	Send a DELTS command to the associated AP.
+
+	Process a given conf file for a specific TSPEC data block.  Send the
+	  TSPEC along with any other IEs to the driver/firmware for transmission
+	  in a DELTS request to the associated AP.
+
+	Return the execution status of the command.  There is no response to a
+	  DELTS from the AP.
+
+	Usage:
+		mlanutl mlanX delts <filename.conf> <section# of tspec>
+
+dfstesting
+	This command is used to set/get settings for DFS testing.
+
+	Usage:
+	    mlanutl mlanX dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+
+	where <user_cac_pd> is user-configured Channel Availability Check in msec
+                        0 = disable, use default period (60000)
+                        1-65535 = enable with that period
+	where <user_nop_pd> is user-configured Non-Occupancy Period in sec
+                        0 = disable, use default period (1800)
+                        1-65535 = enable with that period
+	where <no_chan_change> is enable/disable no channel change on radar
+                           0 = disable, 1 = enable (overrides below)
+	where <fixed_chan_num> is user-configured channel to change to on radar
+                           0 = disable, 1-255 = enable with that channel
+                           (channel validity for region, etc. is not checked)
+                           (only takes effect if no_chan_change = 0)
+
+	Examples:
+		mlanutl mlan0 dfstesting             : Get current dfstesting settings
+		mlanutl mlan0 dfstesting 2000 0 0 0  : user_cac=2sec, others disabled/default
+		mlanutl mlan0 dfstesting 0 0 1 0     : only no_chan_change enabled
+		mlanutl mlan0 dfstesting 0 120 0 64  : user_nop=2min, force chan 64 on radar
+
+dfs_repeater
+	This command is used to get/set DFS Repeater mode.
+
+	Usage:
+		mlanutl mlan0 dfs_repeater <n>
+
+	where the parameter is <n> :
+		null:	to get current setting
+		1:	to enable dfs_repeater mode
+		0:	to disable dfs_repeater mode
+
+	eg.,
+		mlanutl mlan0 dfs_repeater        :get current setting
+		mlanutl mlan0 dfs_repeater 1	  :enable dfs repeater mode
+		mlanutl mlan0 dfs_repeater 0	  :disable dfs repeater mode
+
+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
+
+esuppmode
+	This command is used to set/get the e-supplicant mode configurations/status.
+
+	Note: The configurations can be set only before association.
+	      For get, the configurations will be returned before association
+	      and the current status will be returned after association.
+
+	Where
+	[l] is <rsn_mode>
+	<rsn_mode> - This parameter specifies the RSN mode configuration
+		Bit 0    : No RSN
+		Bit 1-2  : RFU
+		Bit 3    : WPA
+		Bit 4    : WPA-NONE
+		Bit 5    : WPA2
+		Bit 6-15 : RFU
+	[m] is <pairwise_cipher>
+	<pairwise_cipher> - This parameter specifies the pairwise cipher
+		Bit 0    : RFU
+		Bit 1    : RFU
+		Bit 2    : TKIP
+		Bit 3    : AES
+		Bit 4-7  : RFU
+	[n] is <group_cipher>
+	<group_cipher> - This parameter specifies the group cipher
+		Bit 0    : RFU
+		Bit 1    : RFU
+		Bit 2    : TKIP
+		Bit 3    : AES
+		Bit 4-7  : RFU
+	Note that: the RFU bits cannot be SET.
+
+	Examples:
+		mlanutl mlan0 esuppmode          : Get RSN mode and pairwise/group cipher
+		mlanutl mlan0 esuppmode 8 4 4    : Set RSN mode yo WPA, active pairwise and
+		                                   group ciphers to TKIP
+
+extcapcfg
+	This command is used to set/get extended capabilities.
+
+	Usage:
+		mlanutl mlanX extcapcfg [<ext_cap>]
+
+	where <ext_cap> :  Extended capabilities in hex (max 9 bytes)
+		               The Buffer should not be space separated.
+
+	Examples:
+		mlanutl mlan0 extcapcfg 0x0000008020	: Set TDLS support and Interworking bits.
+
+fwmacaddr
+	This command is used to set/get FW side MAC address but host side address will remain as earlier.
+
+	Usage:
+		mlanutl mlanX fwmacaddr [mac_addr]
+
+	where <mac_addr> is desired MAC address
+
+	Examples:
+		mlanutl mlan0 fwmacaddr                        : Get current FW MAC address
+		mlanutl mlan0 fwmacaddr 00:50:43:20:bc:44      : Set FW side MAC address
+
+getdatarate
+	This command is used to get the data rate being used in last Tx
+	packet and last Rx packet.
+
+getkey
+	This command is used to get PTK/GTK
+
+	mlanutl mlanX getkey
+
+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
+
+per_pkt_cfg
+--------------
+    mlanutl <interface> per_pkt_cfg [tx_rx_control] [type_num] [ether_type1 ether_type2...] [tx_rx_control] [type_num] [ether_type1 ether_type2 ...]
+    This command is used to set tx/rx per packet Txctl and Rxinfo configuration.
+
+    The supported options are:
+       tx_rx_control :
+                        0 - disable Tx and Rx per packet control
+                        1 - enable Tx per packet control
+                        2 - enable Rx Per packet control
+                        3 - enable Tx and Rx Per packet control
+
+       type_num :       Number of ether_types which support per packet control, the Max is 8.
+       ether_type :     Array of ether_types for which need to do per-packet Tx control or get per-packet Rx info.
+
+       Examples:
+                 mlanutl mlan0/uap0 per_pkt_cfg                        : get the configuration of per-packet control
+                 mlanutl mlan0/uap0 per_pkt_cfg 0                      : disable per-packet control
+                 mlanutl mlan0/uap0 per_pkt_cfg 3 1 0x88dc       : set the Tx and Rx per-packet control configuration
+
+dot11_txrx
+    This command is used to send or receive packets.
+
+    Usage:
+            mlanutl <interface> dot11_txrx <send/recv> <options>
+            interface     : mlanX or uapX
+            options  send : <conf_file>
+            conf_file     : config file name
+            options  recv : <protocol> [ verbose_mode ]
+            protocol      : packet protocol type
+            verbose_mode  : v -- enter verbose mode
+
+    Example:
+            mlanutl mlan0 dot11_txrx send config/tx_ctrl.conf         : To send packets
+            mlanutl mlan0 dot11_txrx recv 0x88dc                         : To receive packets of type 0x88dc
+            mlanutl mlan0 dot11_txrx recv 0x88dc v                      : To receive packets of type 0x88dc and
+                                                                            enter verbose mode
+
+getscantable
+	Display the current contents of the driver scan table
+
+	Usage:
+		mlanutl mlanX getscantable
+		mlanutl mlanX getscantable [#]
+		mlanutl mlanX getscantable tsf
+		mlanutl mlanX getscantable ch
+		mlanutl mlanX getscantable help
+
+	1) Without argument, the entire scantable is displayed in terms of channel (ch), signal strength (ss), BSS id (bssid), capability (cap), and SSID,
+		where each column in the capability is described as follows:
+		column 1 indicates the IBSS capability: A (Adhoc), I (Infra)
+		column 2 indicates the encryption capability: P (WEP), W (WPA), 2 (WPA2)
+		column 3 indicates the 11D capability: D (11D)
+		column 4 indicates the WMM capability: W (WMM), C (CAC)
+		column 5 indicates the 11K capability: K (11K)
+		column 6 indicates the 11R capability: R (11R)
+		column 7 indicates the WPS capability: S (WPS)
+		column 8 indicates the 11N/11AC capability: N (11N), A (11AC)
+
+	2) Specifying a # will display detailed information about a specific scan
+	   table entry.  '0' displays driver cached information regarding the
+	   current association (if any).
+	3) The tsf argument will display the entire scan table with the recorded
+	   TSF timestamp for the entry.
+	4) The ch argument will display the entire scan table sorted by channel
+	   number in the ascending order. If this argument is not specified,
+           scan table is sorted by signal strength in the descending order.
+	6) The help argument will display the legend for the capability field.
+
+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.
+
+	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.
+
+	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
+
+getstalist
+    This command is used to get list of associated stations to the AP.
+
+    Example:
+        mlanutl uap0 getstalist
+
+channel_switch <switch mode> <oper class> <new channel> <switch count> <bandwidth>
+    This command is used to do channel switch according to spec.
+
+    Where the paramters are:
+        switch mode : 0 -- no need to block traffic, 1 -- need block traffic
+        oper class  : operating class according to IEEE std802.11 spec, when 0 is used, only CSA IE will be used
+        new channel : the channel will switch to
+        switch count: channel switch time to send ECSA ie
+        bandwidth   : channel width switch to(optional),only for 5G channels.
+                      Support value 1 -- 40M above, 3 -- 40M below, 4 -- 80M, 5 -- 160M
+
+    Example:
+        mlanutl uap0 channel_switch 1 115 36 10      :switch to channel 36, oper class 115
+        mlanutl uap0 channel_switch 1 81 6 10        :switch to channel 6, oper class 81
+        mlanutl uap0 channel_switch 1 0 6 10         :switch to channel 6
+        mlanutl uap0 channel_switch 1 0 36 10 1      :switch to channel 36, bandwidth 40MHz above
+
+hostcmd 2040coex
+	This command is used to send the 11n 20/40 Coex command to firmware.
+	Firmware will send 11n 20/40 Coex management action frame to AP.
+
+	Usage:
+		mlanutl mlanX hostcmd config/11n_2040coex.conf 2040coex
+
+hostcmd auto_tx_get
+hostcmd auto_tx_unreg
+	This command is used to configures the Frame Auto Transmission parameters.
+	auto_tx_get: get auto_tx parameters
+	auto_tx_unreg: unregister to firmware auto_tx
+
+	Usage:
+		mlanutl mlanX hostcmd config/auto_tx.conf auto_tx_get
+		mlanutl mlanX hostcmd config/auto_tx.conf auto_tx_unreg
+
+hostcmd bgscfg
+	This command is used to configure the various parameters for PPS/UAPSD
+	or normal background scan.
+
+	Usage:
+		mlanutl mlanX hostcmd config/bg_scan.conf bgscfg
+
+hostcmd <pkt_coalescing.conf> coalesce_cfg
+	This command is used to set/clear rules to filter and buffer
+	broadcast/multicast packet which reduce unwanted patcket or interrupt to
+	host.
+
+	Usage:
+		mlanutl mlanX hostcmd <pkt_coalescing.conf> coalesce_cfg
+
+hostcmd <ed_mac_ctrl.conf> ed_mac_ctrl
+	This command is used to control ED MAC.
+
+	Usage:
+		mlanutl mlanX hostcmd <ed_mac_ctrl.conf> ed_mac_ctrl
+
+hostcmd crypto_test
+	This command is used to test the encryption/decryption API of the firmware.
+
+	Usage:
+		mlanutl mlanX hostcmd config/crypto_test.conf crypto_test
+
+hostcmd nat_keep_alive
+	This command is used to configures the Frame Auto Transmission parameters.
+	nat_keep_alive: register to firmware for sending NAT Keep Alive packet
+
+	Usage:
+		mlanutl mlanX hostcmd config/auto_tx.conf nat_keep_alive
+
+hostcmd pad_cfg_get
+hostcmd pad_cfg_set
+	This command is used to set/get the configuration data for PAD OR.
+
+	Usage:
+		mlanutl mlanX hostcmd config/pad_cfg.conf pad_cfg_get
+		mlanutl mlanX hostcmd config/pad_cfg.conf pad_cfg_set
+
+hostcmd requesttpc
+	This command is used to request 802.11H TPC info.
+
+	Usage:
+		mlanutl mlanX hostcmd config/requesttpc.conf requesttpc
+
+hostcmd mode_get
+hostcmd mode_timeshare
+hostcmd mode_spatial
+hostcmd mode_none
+	This command is used to get/set Robust BT Coex.
+	mode_get:       get the current mode
+	mode_timeshare: set Robust BT Coex to timeshare mode  (default on 1x1 chips)
+	mode_spatial:   set Robust BT Coex to spatial mode    (only for, and default on 2x2 chips)
+	mode_none:      set Robust BT Coex to mode none       (only for, and default on 2x2_3Antenna chips)
+
+	Usage:
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_get
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_timeshare
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_spatial
+		mlanutl mlanX hostcmd config/robust_btc.conf mode_none
+
+hostcmd gpio_cfg
+	This command is used to enable/disable GPIO cfg.
+	gpio_cfg:       enable/disable GPIO cfg for external bt request  (default is enable with High Polarity)
+
+	Usage:
+		mlanutl mlanX hostcmd config/robust_btc.conf gpio_cfg
+
+hostcmd generictime
+hostcmd a2dptime
+hostcmd inquirytime
+hostcmd ap_generictime
+hostcmd ap_a2dptime
+hostcmd ap_inquirytime
+        This command is used to configure the time slice of COEX (only works in timeshare mode)
+        generictime:       configure the Bttime and Wlantime in Station Generic case
+        a2dptime:          configure the Bttime and Wlantime in Station A2DP case
+        inquirytime:       configure the Bttime and Wlantime in Station Inquiry case
+        ap_generictime:    configure the Bttime and Wlantime in Ap Generic case
+        ap_a2dptime:       configure the Bttime and Wlantime in Ap A2DP case
+        ap_inquirytime:    configure the Bttime and Wlantime in Ap Inquiry case
+
+    Usage:
+                mlanutl mlanX hostcmd config/robust_btc.conf generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf inquirytim
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime
+
+hostcmd sdio_pulldown_get
+hostcmd sdio_pulldown_set
+hostcmd sdio_pulldown_disable
+	This command is used to set/get the settings of pulling up and
+	pulling down of SDIO lines.
+
+	Usage:
+		mlanutl mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_get
+		mlanutl mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_set
+		mlanutl mlanX hostcmd config/sdio_pulldown.conf sdio_pulldown_disable
+
+hostcmd subevent_get
+hostcmd subevent_set
+	This command is used to get/set the configurations for event descriptor
+	interface command.
+	subsvent_get: get subscribed event parameters
+	subsvent_set: set subscribed event parameters
+
+	Usage:
+		mlanutl mlanX hostcmd config/subevent.conf subevent_get
+		mlanutl mlanX hostcmd config/subevent.conf subevent_set
+
+hostcmd txpwrlimit_2g_cfg_set
+hostcmd txpwrlimit_5g_cfg_set
+hostcmd txpwrlimit_cfg_get
+	This command is used to set/get the configuration data of Tx power limitation.
+	Note: The configuration set should be issued when STA is disconnected.
+
+	Usage:
+		mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get
+		mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set
+		mlanutl mlanX hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set
+
+hostcmd txrate_cfg_get
+hostcmd txrate_cfg_set_bg
+hostcmd txrate_cfg_set_bgn
+	This command is used to set/get the transmit data rate.
+
+	Usage:
+		mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_get
+		mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bg
+		mlanutl mlanX hostcmd config/txrate_cfg.conf txrate_cfg_set_bgn
+
+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>
+
+hostcmd fwdump
+	This command is used to trigger firmware dump
+
+	Usage:
+		mlanutl mlanX hostcmd <fwdump.conf> fwdump
+
+hscfg
+	This command is used to configure the host sleep parameters.
+
+	Usage:
+		mlanutl mlanX hscfg [condition [[GPIO# [gap]]]] (optional)[type ind_GPIO# [level]] (optional)[type event_force_ignore event_use_ext_gap ext_gap [gpio_wave]]
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap). If more than three parameters, it can set different or multiple features indicating by type(this is optional):
+
+	If type=1, it will set indication gpio and its level. And the parameter format will be (condition, GPIO#,gap and type,ind_GPIO#) or
+	(condition, GPIO#, gap, type, ind_GPIO# and level).
+
+	If type=2, it will set extend hscfg wakup method. And the parameter format will be (condition, GPIO#, gap, type, force_ignore,
+	use_ext_gap, ext_gap [gpio_wave]). gpio_wave parameter is optional and default value is 0(falling edge). Each bit of
+	event_force_ignore and event_use_ext_gap will be defined to one same event, and set one same event(same bit) in those two
+	parameters is not allowed. Set bit(s) in event_force_ignore means the event(s) will be forced ignore in firmware silently.
+	Set bit(s) in event_use_ext_gap mean the event(s) will use extend gap to inform host. Not set means not handle.
+
+	If type=3, it will set hs_wakeup_interval.
+
+        If no parameter provided, get is performed.
+
+	The usages of parameters for "hscfg" are the same as that for "hssetpara" command.
+
+hssetpara
+	This command is used to set host sleep parameters.
+
+	Usage:
+		mlanutl mlanX hssetpara condition [GPIO# [gap]] (optional)[type ind_GPIO# [level]] (optional)[type event_force_ignore event_use_ext_gap ext_gap [gpio_wave]] (optional)[type hs_wakeup_interval]
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap).If more than three parameters, it can set different or multiple features indicating by type and
+        the detailed usage is the same as hscfg above.
+
+	where Condition is:
+		bit 0 = 1   -- broadcast data
+		bit 1 = 1   -- unicast data
+		bit 2 = 1   -- mac event
+		bit 3 = 1   -- multicast data
+		bit 6 = 1  --  Wakeup when mgmt frame received.
+		Bit 31 = 1  --  Don't wakeup when IPV6 packet received.
+
+	The host sleep mode will be canceled if condition is set to -1. The default is 0x7.
+
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+	GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead).
+	The default is 0xff.
+
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff
+	for special setting (host acknowledge required) when GPIO is used to wakeup host.
+	The default is 200.
+
+	The host sleep set except for cancellation will be blocked if host sleep is
+	already activated.
+
+	where ind_GPIO# is the pin number of GPIO used to indicate wakeup source. The level on
+	this GPIO will indicate normal wakeup source or abnormal wakeup source.
+
+	where level is used to set level(0/1) on ind_GPIO# pin for indication normal wakeup source.
+	The opposite level will indicate abnormal wakeup source. The default value is 0.
+
+	where event_force_ignore is a bitmap,each bit represent one wakeup reason event. Set the bit means this
+	wakeup reason should be force ignored in firmware. Reset the bit means do not handle this reason.
+
+	where event_use_ext_gap is a bitmap, each bit represent one wakeup reason event. Set the bit means this
+	wakeup reason should use ext_gap to indicate host. Reset the bit means do not handle this reason.
+
+	where event_force_ignore and event_use_ext_gap have the same wakeup reason event definition of each bit:
+		bit 0  = 1     --Disconnect
+		bit 1  = 1     --GTK/iGTK rekey failure
+		bit 2  = 1     --Eapol
+		other bits     --Reserved
+	They should not set both for one same wakeup reason.
+
+	where ext_gap is the extend gap based on third parameter Gap. Only valid when use_ext_gap is used.
+	The total gap is (Gap + (x+1)*ext_gap). x means the bit number(start from 0) of this reason in use_ext_gap.
+
+	where gpio_wave is used to set GPIO wave level for hscfg extend. 0 means falling edge, 1 means rising edge.
+	This parameter is optional and default value is 0.
+
+	where hs_wakeup_interval is used to set host sleep wakeup interval and the type must set to 3 to indicate
+	this feature. And the value will round to the nearest multiple dtim*beacon_interval in fw. The unit is milliseconds.
+
+	Examples:
+		mlanutl mlan0 hssetpara -1           : Cancel host sleep mode
+		mlanutl mlan0 hssetpara 3            : Broadcast and unicast data
+		                                       Use GPIO and gap set previously
+		mlanutl mlan0 hssetpara 2 3          : Unicast data
+		                                       Use GPIO 3 and gap set previously
+		mlanutl mlan0 hssetpara 2 1 0xa0     : Unicast data
+		                                       Use GPIO 1 and gap 160 ms
+		mlanutl mlan0 hssetpara 2 0xff       : Unicast data
+		                                       Use interface (e.g. SDIO)
+		                                       Use gap set previously
+		mlanutl mlan0 hssetpara 4 3 0xff     : MAC event
+		                                       Use GPIO 3
+		                                       Special host sleep mode
+		mlanutl mlan0 hssetpara 1 0xff 0xff  : Broadcast data
+
+		mlanutl mlan0 hssetpara 2 1 0xa0 1 5 1 : Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=1 to set indication GPIO feature
+                                                       Use GPIO 5 to indicate wakeup source
+                                                       High level on GPIO 5 means this is a normal wakeup
+		mlanutl mlan0 hssetpara 2 1 0xa0 1 5   : Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=1 to set indication GPIO feature
+                                                       Use GPIO 5 to indicate wakeup source
+                                                       Use level set previously.
+
+		mlanutl mlan0 hssetpara 2 1 0xa0 2 0 0x1 10 1: Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=2 to set extend hscfg feature
+                                                       Force_ignore not used
+                                                       Disconnect will use extend gap to indicate host
+                                                       Use gap 170.
+                                                       Rising edge
+		mlanutl mlan0 hssetpara 2 1 0xa0 2 0x1 0 0 0: Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=2 to set extend hscfg feature
+                                                       Falling edge
+                                                       Force ignore Disconnect
+                                                       Extend gap not used
+                                                       Not used.
+                                                       Falling edge
+		mlanutl mlan0 hssetpara 2 1 0xa0 3 400:  Unicast data
+		                                       Use GPIO 1
+                                                       Gap 160 ms
+                                                       type=3 to set hs_wakeup_interval feature
+                                                       hs_wakeup_interval set to 400ms
+
+	Note: The parameters will be saved in the driver and be used when host suspends.
+              The ind_GPIO# and level parameters only work with specific board and firmware.
+
+mgmtfilter
+        This command is used to set management frame to wake up host when host suspend.
+
+        Usage:
+                mlanutl mlanX mgmtfilter <mgmtfilter.conf>
+
+        where <mgmtfilter.conf>
+                This conf file will set management frame catagory, action and frame mask.
+
+        Examples:
+                mlanutl mlan0 mgmtfilter mgmtfilter.conf
+
+auto_arp
+        This command is used to enable/disable auto arp response in host sleep mode.
+        No argument is used to get.
+
+        where value of n is:
+                0   -- Disable
+                1   -- Enable
+
+        Examples:
+                mlanutl mlan0 auto_arp 0           : Disable auto arp response from FW
+                mlanutl mlan0 auto_arp             : Get auto arp configuration status
+
+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).
+
+htstreamcfg
+	This command is used to set/get HT stream configuration.
+	The setting only takes effect in next association.
+
+	Usage:
+		mlanutl mlanX htstreamcfg [n]
+
+	where <n>
+		0x11: HT stream 1x1 mode
+		0x22: HT stream 2x2 mode
+
+	Examples:
+		mlanutl mlan0 htstreamcfg        : Get current setting
+		mlanutl mlan0 htstreamcfg 0x11   : Set HT stream 1x1 mode
+		mlanutl mlan0 htstreamcfg 0x22   : Set HT stream 2x2 mode
+
+httxbfcap
+	This command is used to set/get the TX beamforming capabilities.
+
+	Usage:
+		mlanutl mlanX httxbfcap [cap]
+
+	where the parameters are,
+		cap: TX beamforming capabilities
+			 Bit 0    : Implicit TX BF receiving capable
+			 Bit 1    : RX staggered sounding capable
+			 Bit 2    : TX staggered sounding capable
+			 Bit 3    : RX NDP capable
+			 Bit 4    : TX NDP capable
+			 Bit 5    : Implicit TX BF capable
+			 Bit 6-7  : Calibration
+			         0: - not supported
+			         1: - STA can respond to a calibration request using
+			              the CSI Report, but cannot initiate calibration
+			         2: - reserved
+			         3: - STA can both initiate and respond to a calibration request
+			 Bit 8    : Explicit CSI TX BF capable
+			 Bit 9    : Explicit non-compressed steering capable
+			 Bit 10   : Explicit compressed steering capable
+			 Bit 11-12: Explicit TX BF CSI feedback
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 13-14: Explicit non-compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 15-16: Explicit compressed BF feedback capable
+			         0: - not supported
+			         1: - delayed feedback
+			         2: - immediate feedback
+			         3: - delayed and immediate feedback
+			 Bit 17-18: Minimal grouping
+			         0: - no grouping (STA supports groups of 1)
+			         1: - groups of 1, 2
+			         2: - groups of 1, 4
+			         3: - groups of 1, 2, 4
+			 Bit 19-20: CSI number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 21-22: Non-compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 23-24: Compressed steering number of beamformer antennas supported
+			         0: - single TX antenna sounding
+			         1: - 2 TX antenna sounding
+			         2: - 3 TX antenna sounding
+			         3: - 4 TX antenna sounding
+			 Bit 25-26: CSI max number of rows beamformer supported
+			         0: - single row of CSI
+			         1: - 2 rows of CSI
+			         2: - 3 rows of CSI
+			         3: - 4 rows of CSI
+			 Bit 27-28: Channel estimation capability
+			         0: - 1 space time stream
+			         1: - 2 space time streams
+			         2: - 3 space time streams
+			         3: - 4 space time streams
+			 Bit 29-31: Reserved
+
+	Examples:
+		mlanutl mlan0 httxbfcap             : Get the current TX BF capabilities
+		mlanutl mlan0 httxbfcap 0x0000001F  : Set the TX BF capabilities of the
+		                                     Implicit TX BF receiving capable,
+		                                     RX staggered sounding capable,
+		                                     TX staggered sounding capable,
+		                                     RX NDP capable and TX NDP capable
+
+httxbfcfg
+	This command is used to configure the TX beamforming options.
+	Note: Any new subcommand should be inserted in the second
+		argument and each argument of the sub command should be
+		separated by semicolon. For global configuration, the
+		arguments should be separated by space.
+
+	Usage:
+		mlanutl mlanX httxbfcfg "<action>[;GlobalData/tsData/interval/txPeerData/snrData/txSounding]"
+
+	where the parameters are,
+		action: TX beamforming action
+			0: Control global parameters for beamforming
+		        1: Performs NDP Sounding for PEER
+		        2: TX BF interval in milliseconds
+		        3: Enable/Disable beamforming/sounding for a particular peer
+		        4: TX BF SNR Threshold for peer
+		        .. <for new subcommand>
+		        5: Get and set transmit sounding configuration
+		GlobalData: Global parameter arguments.
+		    It contains beamforming enable, sounding enable, FB type, snr_threshold
+		    sounding interval, Beamformig mode values seperated by space.
+		    Syntax:
+			mlanutl mlanX httxbfcfg <action>;<beamforming enable> <sounding enable> <FB type>
+			                       <snr_threshold>  <sounding interval> <Beamforming mode>
+		tsData: Trigger sounding for PEER specific arguments,
+		        it contains PEER MAC and status
+		interval: TX BF interval in milliseconds
+		txPeerData: Enable/Disable beamforming/sounding for the indicated peer,
+		          it contains PEER MAC, sounding, beamfoming options and FB type;
+		snrData: TX BF SNR Threshold for peer, it contains PEER MAC and SNR
+                txSounding: the 1st parameter - enable/disable Tx sounding (enable: 1; disable: 0)
+                            the 2nd parameter - sounding type (HT: 1; VHT: 2)
+                            the 3rd parameter - sounding interval (ms, resoultion: 10 ms)
+
+	Examples:
+		mlanutl mlan0 httxbfcfg "0"                          : Get current global configuration parameter
+		mlanutl mlan0 httxbfcfg "2;00:50:43:20:BF:64"        : Get the TX BF periodicity for a given peer
+		mlanutl mlan0 httxbfcfg "3"                          : Get the list of MAC addresses that have
+		                                                      beamforming and/or sounding enabled
+		mlanutl mlan0 httxbfcfg "4"                          : Get the list of PEER MAC, SNR tuples
+		                                                      programmed into the firmware.
+		mlanutl mlan0 httxbfcfg "0;0 0 3 10 500 5"           : Disable beamforming, sounding, set FB type
+		                                                      to 3, snr threshold to 10, sounding interval
+		                                                      to 500 ms and beamforming mode to 5
+		mlanutl mlan0 httxbfcfg "1;00:50:43:20:BF:64"        : Perform NDP Trigger sounding to peer
+		                                                      00:50:43:20:BF:64
+		mlanutl mlan0 httxbfcfg "2;00:50:43:20:BF:64;500"    : Set TX BF periodicity for peer 00:50:43:20:BF:64
+		                                                      to 500 milliseconds
+		mlanutl mlan0 httxbfcfg "3;00:50:43:20:BF:43;1;0;3"  : Enable beamforming, disable sounding and set
+		                                                      FB type to 3 for peer 00:50:43:20:BF:43
+		mlanutl mlan0 httxbfcfg "4;00:50:43:20:BF:24;43"     : Set TX BF SNR threshold to peer
+		                                                      00:50:43:20:BF:24 with SNR 43
+		mlanutl mlan0 httxbfcfg "5;1 2 100"                  : Set TX Sounding: enable Tx Sounding, Sounding Type is VHT, and Sounding Interval is 100 ms.
+
+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-10: Reserved set to 0
+        Bit 9-8: Rx STBC set to 0x01
+        BIT9 BIT8  Description
+         0    0     No spatial streams
+         0    1     One spatial streams supported
+         1    0     Reserved
+         1    1     Reserved
+		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.
+
+inactivityto
+	This command is used to set/get the inactivity timeout value, which specifies
+	when WLAN device is put to sleep.
+
+	Usage:
+		mlanutl mlanX inactivityto <n> <m> <l> [k]
+
+	where the parameter are:
+		<n>: timeout unit in microseconds.
+		<m>: Inactivity timeout for unicast data.
+		<l>: Inactivity timeout for multicast data.
+		[k]: Inactivity timeout for new Rx traffic after PS notification to AP.
+
+	Examples:
+		mlanutl mlan0 inactivityto           : Get the timeout value
+		mlanutl mlan0 inactivityto 1000 2 3  : Set timeout unit to 1000 us (1 ms),
+		                                      inactivity timeout for unicast data is 2 ms,
+		                                      inactivity timeout for multicast data is 3 ms
+
+ipaddr
+	This command is used to set/get IP address.
+
+	Usage:
+		mlanutl mlanX ipaddr ["<op>;<ipaddr>"]
+
+	where <op>
+		0: Remove the IP address
+		bit 0: Set IP address for broadcast ARP filter, which will be auto enabled
+		       in next host sleep configuration
+		bit 1: Set IP address for auto broadcast ARP response
+
+	Examples:
+		mlanutl mlan0 ipaddr                 : Get current settings
+		mlanutl mlan0 ipaddr "0"             : Remove IP address
+		mlanutl mlan0 ipaddr "1;192.168.0.5" : Set IP address for ARP filter
+		mlanutl mlan0 ipaddr "3;192.168.0.6" : Set IP address for ARP filter
+		                                     : and auto ARP response
+
+linkstats
+	This command is used to get the link statistics from the firmware.
+
+	Usage:
+		mlanutl mlanX linkstats
+
+listeninterval
+	This command is used to set/get listen interval in assoc request.
+
+	Usage:
+		mlanutl mlanX listeninterval [l]
+
+	where the parameter:
+		[l]: Value of listen interval [Default 10]
+
+	Examples:
+		mlanutl mlan0 listeninterval     : Display Listen interval
+		mlanutl mlan0 listeninterval 1   : Set Listen interval to 1.
+
+macctrl
+	This command is used to set/get MAC control.
+	It's recommended to read the current setting first to avoid override issue.
+
+	Usage:
+		mlanutl mlanX macctrl [n]
+
+	where <n>
+		bit 0:  Rx enabled
+		bit 1:  Directed Filter enabled
+		bit 2:  LoopBack enabled
+		bit 3:  WEP enabled
+		bit 4:  EthernetII enabled
+		bit 5:  MultiCast enabled
+		bit 6:  BroadCast enabled
+		bit 7:  Promiscuous enabled
+		bit 8:  All MultiCast enabled
+		bit 9:  RTS/CTS enabled (0: CTS to self)
+		bit 10: Enforce Protection enabled
+		bit 11: Force 11N Protection enabled
+		bit 12: Rx 802.11 Packets enabled
+		bit 13: Ad-hoc g Protection enabled
+		bit 14: Reserved
+		bit 15: WEP Type
+		bit 16: BandWidth Indication in RTS enabled
+		bit 17: Dynamic BandWidth Indication Mode in RTS enabled
+		bit 18-31: Reserved
+
+	Examples:
+		mlanutl mlan0 macctrl           : Get current MAC control
+		mlanutl mlan0 macctrl 0x13      : Set Rx enabled and Directed Filter enabled and EthernetII enabled
+		mlanutl mlan0 macctrl 0x813     : Set Rx enabled and Directed Filter enabled and EthernetII enabled
+		                                  Force 11N Protection enabled
+
+mefcfg
+	This command is used to set MEF settings.
+
+	Usage:
+		mlanutl mlanX mefcfg <mef.conf>
+
+	Where the parameter is:
+		mef.conf : The configuration file specifying the MEF settings.
+
+	Example:
+		mlanutl mlan0 mefcfg config/mef.conf
+
+memrdwr
+	This command is used to read/write the adapter memory.
+
+	Usage:
+		mlanutl mlanX memrdwr <address> [value]
+
+	where the parameters are,
+		<address>:  memory address
+		[value]:    value to be written
+
+	Examples:
+		mlanutl mlan0 memrdwr 0x4cf70    : Read memory address 0x4cf70
+		mlanutl mlan0 memrdwr 0x80000000 0xffffffff
+		                                 : Write 0xffffffff to memory address 0x80000000
+
+miracastcfg
+	This command is used to set/get the miracast configuration.
+
+	Usage:
+	mlanutl mlanX miracastcfg [l] [m] [n]
+
+	where the parameters are,
+		[l]:    miracast mode
+				0: Disable
+				1: Source
+				2: Sink
+		[m]:    scan time per channel, in ms
+		[n]:    gap during two scans, in ms
+
+	Examples:
+		mlanutl mlan0 miracastcfg           : Get miracast configuration
+		mlanutl mlan0 miracastcfg 0         : Disable miracast configuration
+		mlanutl mlan0 miracastcfg 1 20 40   : Set miracast mode as source, with scan time
+	                                          20ms per channel and gap during two scans 40ms
+
+mgmtframectrl
+	This command is used to set/get registered frame type to passthrough.
+
+	Usage:
+		mlanutl mlanX mgmtframectrl [<mask>]
+		mlanutl uapX mgmtframectrl [<mask>]
+
+	Where the parameter is:
+		<mask>  : the bit mask of management frame reception.
+			: Bit 0 - Association Request
+			: Bit 1 - Association Response
+			: Bit 2 - Re-Association Request
+			: Bit 3 - Re-Association Response
+			: Bit 4 - Probe Request
+			: Bit 5 - Probe Response
+			: Bit 8 - Beacon Frames
+
+	Examples:
+		mlanutl mlan0 mgmtframectrl        : Get present mask
+		mlanutl mlan0 mgmtframectrl 0x0020 : Bit 5 is set, Forward probe response frames to application layer
+
+mgmtframetx
+	This command is used to send management frame.
+
+	Usage:
+		mlanutl mlanX mgmtframetx <mgmt_frame.conf>
+
+	Where the parameter is:
+		mgmt_frame.conf : The configuration file contains the management frame.
+
+	Examples:
+		mlanutl mlan0 mgmtframetx config/mgmt_frame.conf
+
+mpactrl
+	This command is used to set/get the Tx, Rx SDIO aggregation parameters.
+	Note: The parameters can be set only in disconnected state.
+
+	Usage:
+		mlanutl mlanX mpactrl [tx_ena] [rx_ena] [tx_size] [rx_size] [tx_ports] [rx_ports]
+
+	where the parameter are:
+		[tx_ena]: Enable/disable (1/0) Tx MP-A
+		[rx_ena]: Enable/disable (1/0) Rx MP-A
+		[tx_size]: Size of Tx MP-A buffer
+		[rx_size]: Size of Rx MP-A buffer
+		[tx_ports]: Max ports (1-16) for Tx MP-A
+		[rx_ports]: Max ports (1-16) for Rx MP-A
+	default values are 1 1 16384 32768 16 16
+	The MP-A may be disabled by default at build time if the MMC driver byte mode patch
+	is not available in kernel.
+
+	Examples:
+		mlanutl mlan0 mpactrl       : Get MP aggregation parameters
+		mlanutl mlan0 mpactrl 0 0
+		                           : Disable MP aggregation for Tx, Rx respectively
+		mlanutl mlan0 mpactrl 1 1 8192 8192 8 8
+		                           : Enable MP aggregation for Tx, Rx
+		                           : Set Tx, Rx buffer size to 8192 bytes
+		                           : Set maximum Tx, Rx ports to 8
+
+netmon
+    This command is used to set/get sniffer mode configuration.
+    Note: The channel and band config is optional. If not specified, or if
+    any STA/uAP/STA+uAP connection is active, sniffer activity will be started
+    on the current config set in the FW.
+    'rtap' monitor interface will be created on enabling sniffer activity and
+    should be made 'up' for capturing in a sniffer app.
+
+    Usage:
+        mlanutl <interface> netmon [<act> [<filter>]]
+        mlanutl mlanX netmon [<act> [<filter>] [<band> <chan> [offset]]]
+
+    Where the parameters are:
+        <interface> : mlanX, uapX
+        <act>	: (0) disable sniffer activity
+                : (1) enable sniffer activity
+
+        <filter> : network monitor fitler flag
+            bit 0: (1/0) enable/disable management frame
+            bit 1: (1/0) enable/disable control frame
+            bit 2: (1/0) enable/disable data frame
+            bit 3: (1/0) enable/disable frames destined to active connection only
+            bit 4: (1/0) enable/disable decrypted unicast data/mgmt frames
+
+        <band>   : 802.11 band
+            bit 0: B
+            bit 1: G
+            bit 2: A
+            bit 3: GN
+            bit 4: AN
+            bit 5: AC 2.4G
+            bit 6: AC 5G
+        <chan>   : channel to monitor
+
+        [offset] : secondary channel bandwidth
+            0 - Bandwidth 20Mhz
+            1 - HT Bandwidth 40Mhz sec channel above
+            3 - HT Bandwidth 40Mhz sec channel below
+            4 - VHT Bandwidth 80Mhz
+
+	Examples:
+        mlanutl mlan0 netmon             : Get the current sniffer mode configuration
+        mlanutl mlan0 netmon 0           : Disable network monitor activity
+        mlanutl uap0 netmon 1 7			 : Enable sniffer activity on current channel set in FW,
+                                           set filter data, control, management frame.
+        mlanutl mlan0 netmon 1 4 11 6    : Enable sniffer activity in absence of active connection,
+                                           set filter data frame, band B/G/GN and channel 6
+        mlanutl mlan0 netmon 1 7 20 64 1 : Enable sniffer activity in absence of active connection
+                                           set filter management, control and data frame, band A/AN,
+                                           channel 64 and secondary channel above
+        mlanutl uap0 netmon 1 0x0c	      : Enable sniffer activity, set filter data frames
+                                            destined to the active uAP connection only
+
+        mlanutl mlan0 netmon 1 0x1d       : Enable sniffer activity, set filter decrypted data and
+                                            management frames destined to the active STA connection
+                                            only
+
+offchannel
+	This command is used to set/cancel the offchannel configuration.
+	Note: This command only can be used when cfg80211 is enabled during load time.
+
+	Usage:
+		mlanutl mlanX offchannel [<l> <m> <n>]
+
+	where
+		<l>
+			0 : Cancel the offchannel configuration
+			1 : Set the offchannel configuration
+		<m>
+			The channel to configure
+		<n>
+			The duration for which to configure
+
+	Examples:
+		mlanutl mlan0 offchannel           : Get current offchannel status.
+		mlanutl mlan0 offchannel 0         : Cancel the offchannel configuration.
+		mlanutl mlan0 offchannel 1 3 5     : Configure channel 3 for 5 milliseconds.
+		mlanutl mlan0 offchannel 1 36 5000 : Configure channel 36 for 5000 milliseconds.
+
+otpuserdata
+	This command is used to get the OTP user data.
+
+	Where
+	<l> is <user_data_length>
+	<user_data_length> - This parameter specifies the length of OTP user data to be read
+
+	Examples:
+		mlanutl mlan0 otpuserdata 10         : Get the 10-byte OTP user data
+
+passphrase
+	This command is used to set/get passphrase for WPA-PSK/WPA2-PSK mode.
+
+	Where <l>
+		ASCII string for ssid/passphrase/psk.
+
+	1) "0;<ssid=valid ssid>" - This will get the passphrase, AKMP
+	   for specified ssid, if none specified then it will get all.
+
+	Example:
+		mlanutl mlan0 passphrase "0;ssid=marvell"
+
+	2) "1;<psk=64 byte hexpsk>;<passphrase=1-63 byte passphare>
+	   <ssid=valid ssid>" - Passphrase and psk cannot be provided for the same SSID.
+	   This command takes only one SSID at a time, If ssid= is present 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 ';' or '/' has to be used in an SSID then a '/' should be preceded
+	   to ';' or '/' as a escape.
+
+	Examples:
+		mlanutl mlan0 passphrase "1;ssid=mrvlAP;passphrase=abcdefgd"
+		mlanutl mlan0 passphrase "1;ssid=mrvl AP;psk=<64 bytes hexpsk>"
+
+		If user wants to input the ssid as "mrvl; AP" then command has to be
+		mlanutl mlan0 passphrase "1;ssid=mrvl/; AP;passphrase=abcdefgh"
+
+		If user wants to input the ssid as "//;" then command has to be
+		mlanutl mlan0 passphrase "1;ssid=/////;;passphrase=abcdefgh"
+
+	3) "2;<ssid=valid ssid>" - This will clear the passphrase
+	   for specified ssid, if none specified then it will clear all.
+
+	Examples:
+		mlanutl mlan0 passphrase "2;ssid=marvell"
+		mlanutl mlan0 passphrase "2"     : Clear all profiles and disable embedded supplicant
+
+pb_bypass
+	This command is used to get the By-passed TX packet from upper layer.
+
+	Usage:
+
+	mlanutl mlanX pb_bypass [data_1, data_2, ... data_n]
+
+	where value of data_1, data_2, ... data_n isBypass TX Data
+
+pmfcfg
+	This command is used to set/get management frame protection parameters.
+
+	Usage:
+		mlanutl mlanX pmfcfg <m> <n>
+
+	where
+		<m>: Management Frame Protection Capable (MFPC)
+			1: Management Frame Protection Capable
+			0: Management Frame Protection not Capable
+		<n>: Management Frame Protection Required (MFPR)
+			1: Management Frame Protection Required
+			0: Management Frame Protection Optional
+		Default setting is PMF not capable.
+		m = 0, n = 1 is an invalid combination
+
+        Examples:
+                mlanutl mlan0 pmfcfg            : Get PMF parameters
+                mlanutl mlan0 pmfcfg 1 0        : Set MFPC and make MFPR optional
+
+port_ctrl
+	This command is used to Set/Get Port Control mode. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 port_ctrl 1           : Enable Port Control mode
+		mlanutl mlan0 port_ctrl             : Get Port Control mode status
+
+powercons
+	This command is used to set the local transmit power constraint.
+	Value is in dbm unit. This command is only used for ad-hoc start.
+
+	Usage:
+		mlanutl mlanX powercons [n]
+
+	Examples:
+		mlanutl mlanX powercons          : get the current setting
+		mlanutl mlanX powercons 12       : set local power constraint to 12 dbm
+
+pscfg
+	This command is used to set/get PS configuration parameters.
+
+	Usage:
+		mlanutl mlanX pscfg [k] [d] [l] ...
+
+	Where the parameters:
+		[k]: Keep alive null packet interval (0: Unchanged, -1: Disable, n: Interval in seconds)
+		[d]: DTIM interval (    0: Unchanged,
+		                      1-5: Value,
+		                    65534: DTIM will be ignored, listen interval will be used,
+		                    65533: Closest DTIM to the listen interval period will be used )
+		[l]: Local listen interval (     0: Unchanged,
+		                                -1: Disable,
+		                              1-49: Value in beacon intervals,
+		                             >= 50: Value in TUs )
+		[a]: Ad-hoc awake period (0: Unchanged, 1-31: Beacon interval, 255: Firmware
+		                          will go to sleep after beacon send out)
+		[b]: Beacon miss timeout (0: Unchanged, 1-50: Value in milliseconds, 65535: Disable)
+		[p]: Delay to PS (0-65535: Value in milliseconds, default 1000ms)
+		[m]: PS mode (0: Unchanged, 1: Auto mode, 2: PS-Poll mode, 3: PS Null mode)
+	No change if parameters are not provided.
+
+	Examples:
+		mlanutl mlan0 pscfg              : Get all the current PS configuration settings
+		mlanutl mlan0 pscfg 3 4          : Set PS keep alive null packet interval to 3 seconds
+		                                   and DTIM interval to 4, all the other configurations
+		                                   are unchanged
+		mlanutl mlan0 pscfg 0 0xfffe 10 0 20
+		                                : Disable DTIM interval, set local listen interval to
+		                                  10 beacon intervals and beacon miss interval to 20,
+		                                  all the other configurations are unchanged
+		mlanutl mlan0 pscfg 0 0 0 0 0 50 : Set delay to PS to 50 ms, keep the others unchanged
+
+bcntimeoutcfg
+	This command is used to set Beacon timeout parameters.
+
+	Usage:
+		mlanutl mlanX bcntimeoutcfg [l] [m] [o] [p]
+
+	Where the parameters:
+		[l]: Beacon miss timeout period Rx window (in ms)
+		[m]: Beacon miss timeout period (unit in beacon interval)
+		[o]: Beacon reacquire timeout period Rx window (unit in beacon interval)
+		[p]: Beacon reacquire timeout period (unit in beacon interval)
+		Please note that it would be better [m]+[p] not exceed 64.
+	Examples:
+		mlanutl mlan0 bcntimeoutcfg 10 30 2 30    : Set beacon timeout configure to
+		                                            Beacon miss timeout period Rx window      : 10 (ms)
+		                                            Beacon miss timeout period                : 30 (Beacon Interval)
+		                                            Beacon reacquire timeout period Rx window : 2  (Beacon Interval)
+		                                            Beacon reacquire timeout period           : 30 (Beacon Interval)
+
+psmode
+	This command is used to set/get the IEEE PS mode configuration.
+
+	Usage:
+		mlanutl mlanX psmode [l]
+
+	where the parameter:
+		[l]
+			0 : Disable IEEE PS mode
+			1 : Enable IEEE PS mode
+			<none>: Get IEEE PS mode
+
+	Examples:
+		mlanutl mlan0 psmode   : Get IEEE PS mode.
+		mlanutl mlan0 psmode 1 : Enable IEEE PS mode.
+
+qconfig
+	Send a WMM AC Queue configuration command to get/set/default params
+
+	Configure or get the parameters of a WMM AC queue. The command takes
+	an optional Queue Id as a last parameter.  Without the queue id, all
+	queues will be acted upon.
+
+	Usage:
+		mlanutl mlanX qconfig def [Queue Id: 0-3]
+		mlanutl mlanX qconfig get [Queue Id: 0-3]
+		mlanutl mlanX qconfig set msdu <lifetime in TUs> [Queue Id: 0-3]
+
+qoscfg
+	This command sets WMM IE QOS info when an argument is given, and gets current WMM
+	IE QOS info when no argument is given.
+
+	Examples:
+		mlanutl mlanX qoscfg 0x0f        : Set WMM IE QOS info to 0x0f
+		mlanutl mlanX qoscfg             : Get WMM IE QOS info
+
+qstatus
+	This command retrieves the current status of the WMM queues. If WMM
+	  is enabled then it displays the information for each AC in a table.
+
+	Usage:
+		mlanutl mlanX qstatus
+
+radioctrl
+	This command is used to turn on/off the radio.
+	Note: The radio can be disabled only in disconnected state.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 radioctrl 1        : Turn the radio on
+		mlanutl mlan0 radioctrl          : Get radio status
+
+rdeeprom
+	This command is used to read the EEPROM contents of the card.
+
+	Usage:
+		mlanutl mlanX rdeeprom <offset> <length>
+
+	where the parameters are,
+		<offset>:   multiples of 4
+		<length>:   4-20, multiples of 4
+
+	Example:
+		mlanutl mlan0 rdeeprom 0 20      : Read 20 bytes of EEPROM data from offset 0
+
+reassoctrl
+	This command is used to turn on/off re-association in driver.
+
+	Usage:
+		mlanutl mlanX reassoctrl [n]
+
+	Where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 reassoctrl         : Get re-association status
+		mlanutl mlan0 reassoctrl 1       : Turn re-association on
+
+regioncode
+	This command is used to set/get the region code in the station.
+	Note: This command should be issued at beginning before band/channel selection
+	and association.
+
+	where value is 'region code' for various regions like
+	USA FCC, Canada IC, Europe ETSI, Japan ...
+	The special code (0xff) is used for Japan to support channel 1-14 in B/G/N mode.
+
+	Examples:
+		mlanutl mlan0 regioncode         : Get region code
+		mlanutl mlan0 regioncode 0x10    : Set region code to USA (0x10)
+	Note : in some case regioncode will be 0 after updated countycode or 80211d
+		i.e. mlanutl mlanX countrycode  (CA, JP, CN, DE, ES AT, BR, RU)
+		or uaputl.exe sys_cfg_80211d state 1 country (CA, JP, CN, DE, ES AT, BR, RU)
+		Please use cfp instead of it.
+
+regrdwr
+	This command is used to read/write the adapter register.
+
+	Usage:
+		mlanutl mlanX regrdwr <type> <offset> [value]
+
+	where the parameters are,
+		<type>:     1:MAC/SOC, 2:BBP, 3:RF, 5:CAU, 6:PSU
+		<offset>:   offset of register
+		[value]:    value to be written
+		Note:
+		BBP reg (type 2) 0xXZZZ:
+		X: 0=BBUD, 8=BBUA.
+		ZZZ: offset (0-0xFFF).
+		RF reg (type 3) 0xXYZZ:
+                 X   = Path ID (0-1)
+           	 Y   = Page Number (0-6) in selected Path
+           	 ZZ  = Register offset in selected path/page
+
+	Examples:
+		mlanutl mlan0 regrdwr 1 0xa060   : Read the MAC register
+		mlanutl mlan0 regrdwr 1 0xa794 0x80000000
+		                                 : Write 0x80000000 to MAC register
+
+rejectaddbareq
+	This command is used to set/get the conditions of rejecting addba request.
+
+	Usage:
+		mlanutl mlanX rejectaddbareq [conditions]
+		mlanutl uapX rejectaddbareq [conditions]
+
+	Where conditions are:
+		bit 0 = 1   -- reject the addba request when host sleep activated
+		others      -- reserved
+
+	Examples:
+		mlanutl mlan0 rejectaddbareq      : Get the reject addba request conditions
+		mlanutl mlan0 rejectaddbareq 0x1  : Reject the addba request
+		                                    when host sleep activated
+		mlanutl uap0 rejectaddbareq 0x1   : Reject the addba request
+		                                    when host sleep activated
+
+scancfg
+	This command is used to set/get scan configuration parameters.
+
+	Usage:
+		mlanutl mlanX scancfg [t] [m] [p] [s] [a] [b] [ext]
+
+	where the parameters:
+		[t]: Scan Type (0: Unchanged, 1: Active, 2: Passive, default Active)
+		[m]: Scan Mode (0: Unchanged, 1: BSS, 2: IBSS, 3: Any, default Any)
+		[p]: Scan Probes (0: Unchanged, 1-4: Number of probes per channel, default 4)
+		[s]: Specific Scan Time (0: Unchanged, n: Value in ms, default 110 ms, max 500 ms)
+		[a]: Active Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 500 ms)
+		[b]: Passive Scan Time (0: Unchanged, n: Value in ms, default 200 ms, max 2000 ms)
+		[ext]: Extended scan (0: Legacy scan, 1: Extended scan, 2: Extended scan enhance)
+	No change if the parameter is 0 or the parameter is not provided.
+
+	Examples:
+		mlanutl mlan0 scancfg            : Get all the current scan configuration settings
+		mlanutl mlan0 scancfg 1 3        : Set scan type to active and scan mode to any,
+		                                   all the other scan configurations are unchanged
+		mlanutl mlan0 scancfg 0 1 2 200  : Set scan mode to BSS, number of probes to 2 and
+		                                   specific scan time to 200 ms, all the other scan
+		                                   configurations are unchanged
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanutl mlanX sdcmd52rw <function number> <register address> [value]
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+	Examples:
+		mlanutl mlan0 sdcmd52rw 1 3      : Read SDIO function 1 register 3
+		mlanutl mlan0 sdcmd52rw 1 1 0x3f : Write 0x3f to SDIO function 1 register 1
+
+sdcmd53rw
+	This command is used to issue a CMD53 read/write data in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+		mlanutl mlanX sdcmd53rw <func> <address> <mode> <blksize> <blknum> [data1] ... [dataN]
+
+	where the parameters are,
+		<func>:     function number (0/1/2/..)
+		<address>:  data address
+		<mode>:     byte mode/block mode (0/1)
+		<blksize>:  block size (32/64/../512, NA for byte mode)
+		<blknum>:   block number or byte number
+		<data1> ... <dataN>:  data for write
+
+	Note: The total data length is block size * block number for block mode
+	or byte number for byte mode. The max data length is 2000-byte.
+	For write the data pattern will be duplicated to data buffer.
+
+	Examples:
+		mlanutl mlan0 sdcmd53rw 0 0x8000 1 0x40 2
+		mlanutl mlan0 sdcmd53rw 1 0x10000 0 1 5 0x0a 0x0b 0x0c 0x0d 0x0e
+
+sdioclock
+	Turn On(1) or Off(0) the SDIO clock.
+
+	Usage:
+		mlanutl mlanX sdioclock 1 (on)
+		mlanutl mlanX sdioclock 0 (off)
+		mlanutl mlanX sdioclock (get the current clock state)
+
+setuserscan
+	Initiate a customized scan and retrieve the results
+
+	Usage:
+		mlanutl mlanX setuserscan [ARGS]
+
+	Where [ARGS]:
+	  ssid="[SSID]"            specify a SSID filter for the scan
+	  chan=[chan#][band][mode] where band is [a,b,g,n] and mode is
+	                           blank for unchange, or 'c' for active or 'p' for passive
+	  bssid=xx:xx:xx:xx:xx:xx  specify a BSSID filter for the scan
+	  wc="[WILDCARD SSID]"     specify a UNIX pattern matching filter (using *
+	                           and ?) for SSIDs found in a broadcast probe
+	  keep=[0 or 1]            keep the previous scan results (1), discard (0)
+	  dur=[scan time]          time to scan for each channel in milliseconds
+	  gap=[gap time]           Time gap between two scans in milliseconds
+	  probes=[#]               number of probe requests to send on each chan
+	                           for each broadcast probe required and each SSID
+	                           specific probe required (1-4)
+	  bss_type=[1,2,3]         BSS type: 1 (Infra), 2(Adhoc), 3(Any)
+          sort_by_ch               Sort by channel number in ascending order.
+                                   Default mode: Sort by Signal Strength in descending order.
+	  scan_type=[0,1]          ext scan type (0-1) 0: legacy, 1: enhance scan
+
+	Any combination of the above arguments can be supplied on the command line.
+	If the chan token is absent, a full channel scan will be completed by driver.
+	If the dur or probes tokens are absent, the driver default setting will be
+	used. The bssid and ssid fields, if blank, will produce an unfiltered scan.
+	It's allowed to input multiple ssid/wc entries, the max entry number is 10.
+	The type field will default to 3 (Any) and the keep field will default to 0
+	(Discard).
+
+	Examples:
+	1) Perform an active scan on channels 1, 6, and 11 in the 'g' band:
+		setuserscan chan=1g,6g,11g
+
+	2) Perform a passive scan on channel 11 for 20 ms:
+		setuserscan chan=11gp dur=20
+
+	3) Perform an active scan on channels 1, 6, and 11; and a passive scan on
+	   channel 36 in the 'a' band:
+		setuserscan chan=1g,6g,11g,36ap
+
+	4) Perform an active scan on channel 6 and 36 for specific SSID:
+		setuserscan chan=6g,36a ssid=TestAP1 ssid=TestAP2
+
+	5) Scan all available channels (B/G/N, A bands) for a specific BSSID, keep
+	   the current scan table intact, update existing or append new scan data:
+		setuserscan bssid=00:50:43:20:12:82 keep=1
+
+	6) Scan channel 6, for all infrastructure networks, sending two probe
+	   requests.  Keep the previous scan table intact. Update any duplicate
+	   BSSID/SSID matches with the new scan data:
+		setuserscan chan=6g bss_type=1 probes=2 keep=1
+
+	7) Scan channel 1 and 6, for all networks matching the Mrvl*AP
+	   or AP*Mrvl? patterns and for MrvlTst SSID.  Generate 3 broadcast
+	   probes for the patterns and 3 SSID specific probes for MrvlTst on
+	   both channel 1 and channel 6.
+		setuserscan chan=1g,6g probes=3 wc="Mrvl*AP" wc="AP*Mrvl?" ssid="MrvlTst"
+
+	8) Scan all the channels for specified band.
+		setuserscan chan=0g
+
+	9) Scan channel 1 and 6, send 3 probe requests, scan each channel for 40 ms
+	   with time gap of 50ms between 2 scans
+		setuserscan chan=1g,6g probes=3 dur=40 gap=50
+
+        10) Perform an enhance scan
+                setuserscan scan_type=1
+
+	All entries in the scan table (not just the new scan data when keep=1)
+	will be displayed upon completion by use of the getscantable ioctl.
+cancelscan
+	This command is used to cancel scan
+	Usage:
+		mlanutl mlanX cancelscan
+sleepparams
+	This command is used to set the sleepclock configurations
+
+	Usage:
+		mlanutl mlanX sleepparams [<p1> <p2> <p3> <p4> <p5> <p6>]
+
+	where:
+		p1 is Sleep clock error in ppm (0-65535)
+		p2 is Wakeup offset in usec (0-65535)
+		p3 is Clock stabilization time in usec (0-65535)
+		p4 is Control periodic calibration (0-2)
+		p5 is Control the use of external sleep clock (0-2)
+		p6 is reserved for debug (0-65535)
+
+	Examples:
+		mlanutl mlan0 sleepparams                      : Get current sleepclock configuration
+		mlanutl mlan0 sleepparams 10 1000 2000 1 0 128 : Set sleepclock configuration
+
+sleeppd
+	This command is used to configure the sleep period of the WLAN device.
+
+	Usage:
+		mlanutl mlanX sleeppd [<period>]
+
+	Where the parameter is:
+		period: sleep period in milliseconds. Range 10~60. 0 for disable.
+
+	Examples:
+		mlanutl mlan0 sleeppd            : Get sleep period configuration
+		mlanutl mlan0 sleeppd 10         : Set sleep period to 10 ms
+
+sysclock
+	This command is used to set/get system clocks in MHz.
+	The current system clock, configurable system clocks and all of the
+	supported system clocks will be returned if no parameter provided.
+
+	Examples:
+		mlanutl mlan0 sysclock           : Get system clocks
+		80 80 128 128 128 5 11 16 20 22 32 40 44 64 80 106 128 160 ...
+		(The current system clock is 80 MHz.
+		 The configurable system clocks of non-security, security, non-security
+		 A-MPDU and security A-MPDU are 80 MHz, 128 MHz, 128 MHz and 128 MHz.
+		 The supported system clocks are 5 MHz, 11 MHz, ..., 160 MHz, 182 MHz,
+		 213 MHz, 256 MHz, 320 Mhz, 366 MHz , ... . the Max system clocks is different
+		 for different chips, you could use this command to get the supported system clock)
+
+		mlanutl mlanX sysclock 80        : Set system clock in non-security mode
+		                                  to 80 MHz, no change for others
+		mlanutl mlanX sysclock 0 0 128   : Set system clock in non-security A-MPDU
+		                                  mode to 128 MHz, no changes for others
+
+host_tdls_config
+	This command is used to support channel switch and uapsd for host based tdls
+
+	Usage:
+		mlanutl mlanX host_tdls_config <host_tdls.conf>
+
+
+	Where the parameter is:
+		host_tdls.conf: The configuration file specifying to enable/disable uapsd/cs and related parameters.
+
+	Examples:
+		mlanutl mlan0 host_tdls_config config/host_tdls.conf
+			: enable or disable uapsd/cs, config the channel related ie, based on the configuration file.
+tdls_channel_switch
+	This command is used to send TDLS channel switch request.
+
+	Usage:
+		mlanutl mlanX tdls_channel_switch <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending TDLS channel switch command.
+
+	Examples:
+		mlanutl mlan0 tdls_channel_switch config/tdls.conf
+			: Send TDLS channel switch command, based on the configuration file.
+
+tdls_config
+	This command is used to enable/disable TDLS on device.
+
+	Usage:
+		mlanutl mlanX tdls_config <0/1>
+
+	Where the parameter is:
+		0: Enable TDLS.
+		1: Disable TDLS.
+
+	Examples:
+		mlanutl mlan0 tdls_config 0      : Disable TDLS
+		mlanutl mlan0 tdls_config 1      : Enable TDLS
+
+tdls_cs_params
+	This command is used to set TDLS channel switch params
+
+	Usage:
+		mlanutl mlanX tdls_cs_params <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file specifying the TDLS channel switch params.
+
+	Examples:
+		mlanutl mlan0 tdls_cs_params config/tdls.conf
+			: Set TDLS channel switch params, based on the configuration file.
+
+tdls_debug
+	This command is used for FW debug functionality and tests.
+
+tdls_disable_cs
+	This command is used to disable TDLS channel switch
+
+	Usage:
+		mlanutl mlanX tdls_disable_cs <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file to disable TDLS channel switch.
+
+	Examples:
+		mlanutl mlan0 tdls_disable_cs config/tdls.conf
+			: Disable TDLS channel switch, based on the configuration file.
+
+tdls_discovery
+	This command is used to request TDLS discovery.
+
+	Usage:
+		mlanutl mlanX tdls_discovery <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file to request TDLS discovery.
+
+	Examples:
+		mlanutl mlan0 tdls_discovery config/tdls.conf
+			: Request TDLS discovery based on the configuration file.
+
+tdls_link_status [peer_mac_address]
+	This command is used to get link information about TDLS links or
+    a TDLS link correponding to peer mac address.
+
+	Usage:
+		mlanutl mlanX tdls_link_status <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file to send TDLS command to get current link status.
+
+	Examples:
+		mlanutl mlan0 tdls_link_status config/tdls.conf
+			: Send TDLS command to get current link status based on the configuration file.
+
+tdls_powermode
+	This command is used to send TDLS powermode request.
+
+	Usage:
+		mlanutl mlanX tdls_powermode <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending TDLS powermode command.
+
+	Examples:
+		mlanutl mlan0 tdls_powermode config/tdls.conf
+			: Send TDLS powermode (either 0:Active, 1:PowerSave) command, based on the configuration file.
+
+tdls_setinfo
+	This command is used for setting the capabilities of the TDLS station.
+
+	Usage:
+		mlanutl mlanX tdls_setinfo <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file specifying the capabilities of the TDLS station.
+
+	Examples:
+		mlanutl mlan0 tdls_setinfo config/tdls.conf
+			: Set capabilities of the TDLS station, based on the configuration file.
+
+tdls_setup
+	This command is used to send TDLS setup request.
+
+	Usage:
+		mlanutl mlanX tdls_setup <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending TDLS setup request.
+
+	Examples:
+		mlanutl mlan0 tdls_setup config/tdls.conf
+			: Send TDLS setup request, based on the configuration file.
+
+tdls_stop_channel_switch
+	This command is used to send stop TDLS channel switch request.
+
+	Usage:
+		mlanutl mlanX tdls_stop_channel_switch <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for sending stop TDLS channel switch command.
+
+	Examples:
+		mlanutl mlan0 tdls_stop_channel_switch config/tdls.conf
+			: Send stop TDLS channel switch command, based on the configuration file.
+
+tdls_teardown
+	This command is used to send TDLS teardown request.
+
+	Usage:
+		mlanutl mlanX tdls_teardown <tdls.conf>
+
+	Where the parameter is:
+		tdls.conf: The configuration file for requesting teardown of TDLS link.
+
+	Examples:
+		mlanutl mlan0 tdls_teardown config/tdls.conf
+			: Request teardown of TDLS link, based on the configuration file.
+
+thermal
+	This command is used to get the current thermal reading.
+
+	Examples:
+		mlanutl mlan0 thermal            : Get thermal reading
+
+ts_status
+	This command queries the FW for the status of TSIDs 0 through 7
+	  configured via call admission control and displays the results in a
+	  table.
+
+	Usage:
+		mlanutl mlanX ts_status
+
+tsf
+	Get the TSF timer value for the station. Station maintains a TSF timer with
+	modulus 2^64 counting in increments of microseconds.
+
+	Usage:
+		mlanutl mlanX tsf
+
+txaggrctrl
+	This command is used to enable/disable TX AMPDU on infra link when TDLS link is established
+
+	Usage:
+		mlanutl mlanX txaggrctrl [m]
+
+	Where:
+		[m]: 1 to enable TX AMPDU on infra link; 0 to disable TX AMPDU on infra link
+
+	Examples:
+		mlanutl mlan0 txaggrctrl	: Get current TX AMPDU status on infra link
+		mlanutl mlan0 txaggrctrl 0	: Disable TX AMPDU on infra link
+		mlanutl mlan0 txaggrctrl 1	: Enable TX AMPDU on infra link
+
+	Note:
+		The set command only works when TDLS link is established.
+
+txbufcfg
+	This command can be used to get current buffer size.
+
+	eg:
+	mlanutl mlanX txbufcfg 	  - This will display the current buffer size.
+
+	Note:- The actual tx buf size will depends on AP's capability and max transmit buffer size.
+
+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.
+
+	Where
+	[l] is <format>
+	<format> - This parameter specifies the data rate format used in this command
+		0:    LG
+		1:    HT
+		2:    VHT
+		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
+	[n] is <nss>
+	<nss> - This parameter specifies the NSS. It is valid only for VHT
+	If <format> is 2 (VHT),
+		1	NSS1
+		2	NSS2
+
+	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 0xff     : Disable fixed rate and uses auto rate
+
+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.
+
+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.
+
+opermodecfg
+	This command is used to set and get 11ac Operating Mode Notification configuration.
+
+	where <m> is <bw>
+	<bw> - This is the channel width setting for the opermodecfg
+		1: 20MHz
+		2: 40MHz
+		3: 80MHz
+		4: 160MHz or 80+80MHz
+
+	where <n> is <nss>
+	<nss> - This parameter specifies the nss that the STA can receive.
+		1: NSS1
+		2: NSS2
+		3: NSS3
+		4: NSS4
+		5: NSS5
+		6: NSS6
+		7: NSS7
+		8: NSS8
+
+wakeupreason
+	This command is used to get the host sleep wakeup reason.
+
+	Usage:
+		mlanutl mlanX wakeupreason
+		mlanutl uapX wakeupreason
+	Examples:
+		mlanutl mlan0 wakeupreason        : Get the host sleep wakeup reason
+		mlanutl uap0 wakeupreason         : Get the host sleep wakeup reason
+		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
+		8:  Control frame matched
+		9:  Management frame matched
+		Others: reserved. (0)
+
+warmreset
+	This command is used for warm reset of the interface.
+
+	Usage:
+		mlanutl mlanX warmreset
+
+wpssession
+	This command is used to control wps session. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 wpssession 1           : Enable wpssession
+		mlanutl mlan0 wpssession             : Get wpssession status
+
+wmmcfg
+	This command is used to control WMM. No argument is used to get.
+
+	where value of n is:
+		0   -- Disable
+		1   -- Enable
+
+	Examples:
+		mlanutl mlan0 wmmcfg 1           : Enable WMM
+		mlanutl mlan0 wmmcfg             : Get WMM status
+
+wmmparamcfg
+	This command is used to configure WMM paramameters.
+
+	Usage:
+		mlanutl mlanX wmmparamcfg [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+                                          [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+                                          [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+                                          [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+
+	The supported option are:
+           AC_BE: 0
+           AC_BK: 1
+           AC_VI: 2
+           AC_V0: 3
+           AIFSN: AIFSN value
+           ECW_MAX: ECW max
+           ECW_MIN: ECW min
+           TX_OP: TXOP Limit
+           empty - Get current WMM parameters
+
+        Example:
+        mlanutl mlanX wmmparamcfg 0 3 10 4 0
+           Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        mlanutl mlanX wmmparamcfg 1 7 10 4 0
+           Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        mlanutl mlanX wmmparamcfg 2 2 4 3 94
+           Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+
+        mlanutl mlanX wmmparamcfg 3 2 3 2 47
+           Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        mlanutl mlanX wmmparamcfg
+            Get current WMM parameters
+
+        mlanutl mlanX wmmparamcfg 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+wwscfg
+	This command is used to set/get the WWS (World Wide Safe) mode.
+
+	where value of m is:
+		0       -- Disable WWS mode (default)
+		1       -- Enable WWS mode
+
+	Examples:
+		mlanutl mlan0 wwscfg             : Get WWS mode
+		mlanutl mlan0 wwscfg 1           : Enable WWS mode
+		mlanutl mlan0 wwscfg 0           : Disable WWS mode
+
+mc_cfg
+	This command is used to set/get the channel time.
+
+	Usage:
+		mlanutl mlanX mc_cfg [n]
+
+	where <n> :  Channel time in microseconds.
+
+	Examples:
+		mlanutl mlanX mc_cfg			: Get Channel time and buffer weight.
+		mlanutl mlanX mc_cfg 10000		: Set Channel time to 10000us.
+
+mc_policy
+        This command is used to set/get the multi-channel policy.
+	Note: This is a device specific command. Hence, setting on one interface is
+		reflected on all other interfaces.
+
+        Usage:
+                mlanutl mlanX mc_policy [n]
+
+        where <n> :  Multi-channel policy
+
+        Examples:
+                mlanutl mlanX mc_policy			: Get multi-channel policy setting.
+                mlanutl mlanX mc_policy 1		: Set multi-channel policy to 1.
+                mlanutl mlanX mc_policy 0		: Disable multi-channel policy
+
+mc_cfg_ext
+    This command is used to set/get the drcs parameters.
+
+    Usage:
+        mlanutl mlanX mc_cfg_ext [c] [s] [u] [m] <a> <b> <d> <e>
+
+    where:
+    channel index0:
+        [c] :  chantime(in TU)
+        [s] :  switchtime(in TU)
+        [u] :  undozetime(in TU)
+        [m] :  mode :0x0 --- PM1(default)
+                     0x1 --- Null2Self
+    channel index1:
+        <a> :  chantime(in TU)
+        <b> :  switchtime(in TU)
+        <d> :  undozetime(in TU)
+        <e> :  mode :0x0 --- PM1(default)
+                     0x1 --- Null2Self
+    Note:
+        channel index0: the first channel
+        channel index1: the second channel
+        undozetime should be less than other channel's switchtime
+        If want to set two channels the same parameters, just ignore the last four parameters and
+        use [c] [s] [u] [m] to set.
+    Examples:
+        mlanutl mlanX mc_cfg_ext                        : Get the drcs parameters for two channels.
+        mlanutl mlanX mc_cfg_ext 15 10 5 0              : Set two channels:channeltime 15TU, switchtime 10TU, undozetime 5TU, mode PM1
+        mlanutl mlanX mc_cfg_ext 15 10 5 0 25 15 9 0    : Set channel index0: channeltime 17TU, switchtime 10TU, undozetime 5TU, mode PM1;
+                                                        set channel index1: channeltime 25TU, switchtime 15TU, undozetime 9TU, mode PM1.
+
+cfg_noa
+	This is used to get/set P2P NoA (Notice of Absence) parameters only for P2P GO.
+
+	Usage:
+		mlanutl p2pX cfg_noa [h] [i] [j] [k] [l]
+
+	where:
+		[h] : noa_enable : 1/0 Set to 1 to enable NoA, 0 to disable NoA.
+		[i] : index      : 0 - 255 Identifies an instance of NoA timing.
+		[j] : count      : 1 - 255 Indicates the number of absence intervals.
+				   255 means a continuous schedule.
+		[k] : duration   : Indicates the maximum duration in units of microseconds
+				   that P2P GO can remain absent following the start of
+				   a NoA interval.
+		[l] : interval   : Indicates the length of the NoA interval in units of
+				   microseconds.
+
+        Examples:
+                mlanutl p2pX cfg_noa						: Get noa configuration.
+                mlanutl p2pX cfg_noa 1 1 255 50 100			: Set noa configuration.
+
+cfg_opp_ps
+	This is used to get/set P2P OPP-PS parameters only for P2P GO.
+
+	Usage:
+		mlanutl p2pX cfg_opp_ps [m] [n]
+
+	where:
+		[m] : ps_enable  : 1/0 Set to 1 to indicate P2P GO is using opportunistic
+				   power save. Set to 0 if opportunistic power save is disabled.
+		[n] : ct_window  : A period of time in TU after a TBTT during which P2P GO
+				   is present. 0 indicates that there shall be no
+				   CTWindow (Client Traffic Window).
+
+        Examples:
+                mlanutl p2pX cfg_opp_ps					: Get noa configuration.
+                mlanutl p2pX cfg_opp_ps 1 7				: Set noa configuration.
+
+rxpktcoal_cfg
+	This is used to get/set RX packet coalescing paramters
+	Usage:
+		mlanutl mlanX rxpktcoal_cfg [m] [n]
+
+	where:
+        [m]: pkt_threshold: count after which packets would be sent to host. Valid values 1-7
+        [n]: delay: timeout in ms after which packets would be sent to host. Valid values 1-4
+        Coalescing is disabled if both or either of packet_thershold and delay is zero
+
+        RX packet coalescing parameters can be changed only when device is in
+        idle state i.e. all interfaces are disconnected.
+
+get_sensor_temp
+        This command is used to get SOC temperature
+        Usage:
+                mlanutl mlanX get_sensor_temp
+11k_enable
+        This command is used to control 11K. No argument is used to get.
+        only available when disconnected.
+
+        where value of n is:
+                0   -- Disable
+                1   -- Enable
+
+        Examples:
+                mlanutl mlan0 11k_enable 1           : Enable 11k
+                mlanutl mlan0 11k_enable             : Get 11k status
+
+neighbor_report
+        This command is used to get neighbor AP list.
+        You can open mlanevent to show the AP list result before issue this command.
+
+        Usage:
+                mlanutl mlanX neighbor_report
+
+indrstcfg
+    This command is used to set/ get independent reset mode configuration
+
+    Usage :
+            mlanutl <interface> indrstcfg <ir_mode> [gpio_pin]
+
+            interface : mlanX, uapX
+            ir_mode   : 0 -- Disable
+                        1 -- Enable out band reset, disable in band
+                        2 -- Enable in band, disable out band
+            gpio_pin  : 255 -- Default pin for reset
+                        any other number for changing the gpio for reset.
+
+   Example :
+            mlanutl mlan0 indrstcfg 1 255   : Set default pin on interface mlan0 as reset pin
+            mlanutl mlan0 indrstcfg 0       : Disable the gpio 17 as reset pin on interface mlan0
+            mlanutl mlan0 indrstcfg         : Get the status and the pin used for reset pin
+            mlanutl mlan0 indrstcfg 2       : Enable in band reset mode
+
+    This command is used to set FW wakeup method and GPIO pin
+    Usage :
+            mlanutl <interface> fwwakeupmethod <method> <GPIO_pin>
+            interface : mlanX
+            method:
+                        1       -- Firmware wakeup through the interface command interrupt
+                                -- (default setting for SDIO/PCIe/USB)
+                        2       -- Firmware wakeup through the GPIO pin
+            GPIO_pin:  If firware wakeup throug GPIO pin, [g] is GPIO pin number
+    Example :
+            mlanutl mlan0 fwwakeupmethod     : Get current wakeup method
+            mlanutl mlan0 fwwakeupmethod 1   : Set wakeup method is interface method
+            mlanutl mlan0 fwwakeupmethod 2 5 : Set wakeup method is GPIO method and GPIO pin is 5.
+
+robustcoex
+    This command is used to set robust coex.
+
+    Usage :
+            mlanutl <interface> robustcoex <gpiocfg> [Enable/Disable] [gpionum] [gpiopolarity]
+            Enable/Disable : 0 -- Disable ; 1 -- Enable
+            gpionum : Number of gpio
+            gpiopolarity : polarity of gpio
+
+    Example :
+            mlanutl mlan0 robustcoex gpiocfg 1 4 1 : Enable robustcoex gpio, set gpionum to 4 and gpiopolarity to 1
+            mlanutl mlan0 robustcoex gpiocfg 0     : Disable robustcoex gpio
+
+keep_connect
+    This command is used to refuse disconnect
+
+    Usage :
+            mlanutl <interface> keep_connect [Enable/Disable]
+            Enable/Disable : 0 -- Disable ; 1 -- Enable
+
+    Example :
+            mlanutl mlan0 keep_connect 1 : Enable keep connect
+            mlanutl mlan0 keep_connect 0 : Disable keep connect
+ctrldeauth
+    This command is used to set/get firmware ctrldeauth setting
+    Usage :
+            mlanutl uapX ctrldeauth <n>
+
+    Where value of n is :
+            0 -- Firmware will use default behavior
+            1 -- Firmware will not send deauth packet when uap move to another channel.
+
+    Example :
+            mlanutl uap0 ctrldeauth   : Get current setting
+            mlanutl uap0 ctrldeauth   : Firmware will not send deauth packet when uap move to different channel.
+
+cwmode
+    This command is used to set Cont. Tx/Wave mode.
+
+    Usage:
+            mlanutl <interface> cwmode config/cwmode.conf
+            interface: mlanX
+            cwmode.conf: This config file specifies whether to enable/disable Cont Tx/Wave mode.
+                         User can specify parameters like Channel, datarate, BW, Channel Offset, Band.
+                         Detailed information about parameters is mentioned in the conf file.
+    Example:
+            mlanutl mlan0 cwmode config/cwmode.conf                       : Enable/Disable Cont Tx/Wave mode.
+            mlanutl mlan0 cwmode                                          : Get current Tx mode
+
+bootsleep
+    This command is used to set and get boot sleep configure.
+
+    Usage :
+            mlanutl mlanX/uapX bootsleep <enable>
+            <enable> :  enable boot sleep
+                     :  0 - disable boot sleep
+                     :  1 - enable boot sleep
+
+    Example :
+            mlanutl mlan0/uap0 bootsleep 1       : Enable boot sleep
+            mlanutl mlan0/uap0 bootsleep         : Get boot sleep configure
+
+
+===============================================================================
diff --git a/wlan_sd8997/README_OPENWRT b/wlan_sd8997/README_OPENWRT
new file mode 100644
index 0000000..90a6722
--- /dev/null
+++ b/wlan_sd8997/README_OPENWRT
@@ -0,0 +1,356 @@
+=================================================================================
+        U S E R  M A N U A L  F O R  OpenWrt
+
+This section describes detailed steps to add Marvell Wireless NIC (sdio/usb/pcie)
+driver to OpenWrt build system.
+
+Add marvell driver (sdio/usb/pcie) to OpenWrt build system.
+
+1. Go to the openwrt source code folder
+2. make menuconfig
+	choose x86 platform
+	other general openwrt configurations please refer to:
+	https://wiki.openwrt.org/doc/howto/build
+3. After make menuconfig
+	make sure that following configurations are set in .config
+	CONFIG_PACKAGE_hostapd=y
+	CONFIG_PACKAGE_hostapd-common=y
+	CONFIG_PACKAGE_kmod-cfg80211=y
+4. Go to the openwrt source code folder and Compile openwrt BSP
+	make V=s [-j[number]]
+5. After the first time compiling, openwrt/dl folder will be created
+   , related packages will be downloaded during compiling, so you need
+   network access as long as you need to compile openwrt BSP.
+6. Go to the openwrt source code folder: openwrt/dl/
+7. Find compat-wireless-xxxx-xx-xx.tar.bz2, and uncompress the package
+8. Go to compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/
+9. Modify compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/Kconfig
+
+	source "drivers/net/wireless/marvell/libertas/Kconfig"
+	source "drivers/net/wireless/marvell/libertas_tf/Kconfig"
+	source "drivers/net/wireless/marvell/mwifiex/Kconfig"
+	+source "drivers/net/wireless/marvell/mrvl-pcie/Kconfig"
+	+source "drivers/net/wireless/marvell/mrvl-sd8xxx/Kconfig"
+	+source "drivers/net/wireless/marvell/mrvl-usb/Kconfig"
+
+10. Modify compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/Makefile
+
+	obj-$(CPTCFG_LIBERTAS_THINFIRM)	+= libertas_tf/
+	obj-$(CPTCFG_MWIFIEX)	+= mwifiex/
+	+obj-$(CPTCFG_MRVL_PCIE)  += mrvl-pcie/
+	+obj-$(CPTCFG_MRVL_SD8XXX) += mrvl-sd8xxx/
+	+obj-$(CPTCFG_MRVL_USB) += mrvl-usb/
+
+11. Go to compat-wireless-xxxx-xx-xx/drivers/net/wireless/marvell/
+12. mkdir (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)
+13. copy (pcie/sdio/usb)/wlan_src/* to (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)
+14. Go to mrvl-pcie/mrvl-sd8xxx/mrvl-usb
+15. Add new Kconfig:
+	mrvl-pcie/Kconfig
+
+	+config MRVL_PCIE
+	+	tristate "Marvell Wireless Driver for PCIE 8997"
+	+	depends on m
+	+	depends on PCI
+	+	depends on CFG80211
+	+	depends on WIRELESS_EXT
+	+	---help---
+	+	  This adds support for wireless adapters based on Marvell
+	+	  pcie 8997 chipsets with PCIe interface.
+	+
+	+	  If you choose to build it as a module, it will be called
+	+	  pcie8xxx.
+
+	mrvl-sd8xxx/Kconfig
+
+	+config MRVL_SD8XXX
+	+	tristate "Marvell sdio 802.11n/802.11ac Wireless cards"
+	+	depends on m
+	+	depends on MMC
+	+	depends on CFG80211
+	+	depends on WIRELESS_EXT
+	+	---help---
+	+	  A driver for Marvell sdio 802.11n/802.11ac Wireless cards.
+
+	mrvl-usb/Kconfig
+
+	+config MRVL_USB
+	+	tristate "Marvell sdio 802.11n/802.11ac Wireless cards"
+	+	depends on m
+	+	depends on USB
+	+	depends on CFG80211
+	+	depends on WIRELESS_EXT
+	+	---help---
+	+	A driver for Marvell sdio 802.11n/802.11ac Wireless cards.
+
+16. Open moal_main.h under (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlinux/
+
+	find #define COMPAT_VERSION_CODE KERNEL_VERSION_CODE(x, x, x)
+	modify (x, x, x) to the kernel version code of backports/compat-wireless package
+
+	backported kernel version code could be found in
+	compat-wireless-xxxx-xx-xx/version as following
+
+	'BACKPORTED_KERNEL_VERSION="v4.4-rc5-1913-gc8fdf68"'
+	v4.4 means KERNEL_VERSION(4, 4, 0)
+
+17. Modify (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/Makefile
+
+	# OpenWrt support
+	-CONFIG_OPENWRT_SUPPORT=n
+	+CONFIG_OPENWRT_SUPPORT=y
+
+	...
+
+	#############################################################################
+	# Select Platform Tools
+	#############################################################################
+
+	MODEXT = ko
+	-ccflags-y += -I$(M)/mlan
+	+ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan
+	ccflags-y += -DLINUX
+
+
+	ifeq ($(CONFIG_EMBEDDED_SUPP_AUTH), y)
+	-ccflags-y += -I$(M)/mlan/esa
+	-ccflags-y += -I$(M)/mlan/esa/common
+	+ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan/esa
+	+ccflags-y += -I$(M)/drivers/net/wireless/marvell/(mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/mlan/esa/common
+	endif
+
+18. compress compat-wireless-xxxx-xx-xx to its original .tar.bz2 format
+19. Go to the openwrt source code folder: openwrt/package/kernel/mac80211/
+20. Modify openwrt/package/kernel/mac80211/Makefile.
+
+	PKG_DRIVERS = \
+		adm8211 \
+		ath ath5k ath9k ath9k-common ath9k-htc ath10k \
+		b43 b43legacy \
+		carl9170 \
+		hermes hermes-pci hermes-pcmcia hermes-plx\
+		iwl-legacy iwl3945 iwl4965 iwlwifi \
+		lib80211 \
+		libipw ipw2100 ipw2200 \
+		libertas-sdio libertas-usb libertas-spi \
+		mac80211-hwsim \
+		mt7601u \
+		mwl8k mwifiex-pcie \
+		+mrvl-pcie \
+		+mrvl-sd8xxx \
+		+mrvl-usb \
+		p54-common p54-pci p54-spi p54-usb \
+		rt2x00-lib rt2x00-pci rt2x00-usb \
+		rt2400-pci rt2500-pci rt2500-usb \
+
+	...
+
+	+define KernelPackage/mrvl-pcie
+	+  $(call KernelPackage/mac80211/Default)
+	+  TITLE:=Marvell pcie wireless driver
+	+  URL:=http://wireless.kernel.org/en/users/Drivers/mwifiex
+	+  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT
+	+  FILES:= \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/mlan.ko \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/pcie8xxx.ko
+	+  AUTOLOAD:=$(call AutoProbe,mrvl-pcie)
+	+endef
+
+	+define KernelPackage/mrvl-pcie/description
+	+ Kernel modules for Marvell pcie 802.11n/802.11ac PCIe Wireless cards
+	+endef
+
+	+define KernelPackage/mrvl-sd8xxx
+	+  $(call KernelPackage/mac80211/Default)
+	+  DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT
+	+  TITLE:=Marvell sdio Wireless Driver
+	+  FILES:= \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/mlan.ko \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/sd8xxx.ko
+	+  AUTOLOAD:=$(call AutoProbe, mrvl-sd8xxx)
+	+endef
+
+	+define KernelPackage/mrvl-sd8xxx/description
+	+ Kernel modules for Marvell sdio 802.11n/802.11ac Wireless cards
+	+endef
+
+	+define KernelPackage/mrvl-usb
+	+  $(call KernelPackage/mac80211/Default)
+	+  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
+	+  TITLE:=Marvell usb Wireless Driver
+	+  FILES:= \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/mlan.ko \
+	+	$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/usb8xxx.ko
+	+  AUTOLOAD:=$(call AutoProbe, mrvl-usb)
+	+endef
+
+	+define KernelPackage/mrvl-usb/description
+	+ Kernel modules for Marvell usb 802.11n/802.11ac Wireless cards
+	+endef
+
+	...
+
+	config-$(call config_package,mwl8k) += MWL8K
+	config-$(call config_package,mwifiex-pcie) += MWIFIEX MWIFIEX_PCIE
+	+config-$(call config_package,mrvl-pcie) += MRVL_PCIE
+	+config-$(call config_package,mrvl-sd8xxx) += MRVL_SD8XXX
+	+config-$(call config_package,mrvl-usb) += MRVL_USB
+	config-$(call config_package,rtl8180) += RTL8180
+	config-$(call config_package,rtl8187) += RTL8187
+
+	...
+
+	$(eval $(call KernelPackage,mwl8k))
+	$(eval $(call KernelPackage,mwifiex-pcie))
+	+$(eval $(call KernelPackage,mrvl-pcie))
+	+$(eval $(call KernelPackage,mrvl-sd8xxx))
+	+$(eval $(call KernelPackage,mrvl-usb))
+	$(eval $(call KernelPackage,p54-common))
+
+OpenWrt configuration
+21. Go to OpenWrt srouce code folder
+22. Make menuconfig
+
+   select one of the newly added marvell driver
+	│-> Kernel modules
+	│	-> Wireless Drivers
+	|		->mrvl-pcie
+	|		->mrvl-sd8xxx
+	|		->mrvl-usb
+
+23. Other general configurations, please refer to the https://wiki.openwrt.org/doc/howto/build
+24. after menucofig make soure that following configurations are seletect
+
+	CONFIG_PACKAGE_hostapd=y
+	CONFIG_PACKAGE_hostapd-common=y
+	CONFIG_PACKAGE_kmod-cfg80211=y
+
+	Go to openwrt folder and re-build openwrt BSP
+	make V=s [-j[number]]
+
+	After openwrt BSP is successfully build, kernel modules could be found
+	both in the build folder and the running OS once openwrt is boot up.
+	kernel modules will be written to u-disk while openwrt img is burned to u-disk.
+
+	kernel modules in openwrt build dir:
+	openwrt/build_dir/target-x86_64_uClibc-0.9.33.2/linux-x86_64/compat-wireless-2016-01-10/
+	ipkg-x86_64/kmod-mrvl-(usb/sd8xxx/pcie)/lib/modules/3.18.45/
+
+	kernel modules in openwrt running OS:
+	/lib/modules/xx.xx.xx/
+
+25. To support SDIO card in OpenWrt x86 platforma
+	Add following kernel configurations for OpenWrt
+	Go to OpenWrt source code foler
+
+	make kernel_menuconfig
+
+	Device Drivers---->
+		--- MMC/SD/SDIO card support
+                  [ ]   MMC debugging
+                  [ ]   MMC host clock gating
+                  *** MMC/SD/SDIO Card Drivers ***
+                  < >   MMC block device driver
+                  < >   SDIO UART/GPS class support
+                  < >   MMC host test driver
+                  *** MMC/SD/SDIO Host Controller Drivers ***
+                  <*>   Secure Digital Host Controller Interface support
+                  <*>   SDHCI support on PCI bus
+                  [ ]     Ricoh MMC Controller Disabler
+                  < >   SDHCI platform and OF driver helper
+                  < >   Winbond W83L51xD SD/MMC Card Interface support
+                  < >   TI Flash Media MMC/SD Interface support
+                  < >   ENE CB710 MMC/SD Interface support
+                  < >   VIA SD/MMC Card Reader Driver
+                  < >   Renesas USDHI6ROL0 SD/SDIO Host Controller support
+
+	Compile OpenWrt using Make V=s, then write openwrt img to u-disk and boot up
+
+26. Bring up marvell wireless NIC on OpenWrt system
+
+	copy pcie/sdio/usb firmware to /lib/firmware/mrvl folder
+	On OpenWrt running OS
+	scp usrname@<target_pc ip address>:/path/firmware.bin /lib/firmware/mrvl
+
+	Another way is to add firmware binary to OpenWrt source code
+
+27. load marvell pcie/sdio/usb driver modules
+
+    End with Marvell Wirelss NIC card bring up on OpenWrt
+
+=======================================================================================================
+If firmware is copied to OpenWrt via scp, following steps could be ignored.
+28. Add firmware binary in OpenWrt
+	Copy pcie/usb/sdio firmware to folder:
+	openwrt/build_dir/target-x86_64_uClibc-0.9.33.2/linux-firmware-52442afee9907bc32a058f22bb3295d040677c26/mrvl/
+29. Go to penwrt/package/firmware/linux-firmware
+	Modify marvell.mk as following
+
+	+Package/mrvl-pcie-firmware = $(call Package/firmware-default,Marvell PCIE8997 firmware)
+	+define Package/mrvl-pcie-firmware/install
+	+	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+	+	$(INSTALL_DATA) \
+	+		$(PKG_BUILD_DIR)/mrvl/pcieusb8997_combo_v4.bin \
+	+		$(1)/lib/firmware/mrvl/
+	+endef
+	+$(eval $(call BuildPackage,mrvl-pcie-firmware))
+
+	+Package/mrvl-sd8xxx-firmware = $(call Package/firmware-default,Marvell SDIO8997 firmware)
+	+define Package/mrvl-sd8xxx-firmware/install
+	+	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+	+	$(INSTALL_DATA) \
+	+		$(PKG_BUILD_DIR)/mrvl/sdsd8997_combo_v4.bin \
+	+		$(1)/lib/firmware/mrvl/
+	+endef
+	+$(eval $(call BuildPackage,mrvl-sd8xxx-firmware))
+
+	+Package/mrvl-usb-firmware = $(call Package/firmware-default,Marvell SDIO8997 firmware)
+	+define Package/mrvl-usb-firmware/install
+	+	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+	+	$(INSTALL_DATA) \
+	+		$(PKG_BUILD_DIR)/mrvl/usbusb8997_combo_v4.bin \
+	+		$(1)/lib/firmware/mrvl/
+	+endef
+	+$(eval $(call BuildPackage,mrvl-usb-firmware))
+
+30. re-modify openwrt/package/kernel/mac80211/Makefile
+
+	for PCIE
+	+  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT +mrvl-pcie-firmware
+	for SDIO
+	+  DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT +mrvl-sd8xxx-firmware
+	for USB
+	+  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT +mrvl-usb-firmware
+31. Go to step 25.
+=======================================================================================================
+To support SDIO, USB and PCIE in one OpenWrt BSP
+if no need to support multi bus types in one BSP, ignore the following steps
+32. Re-modify Modify openwrt/package/kernel/mac80211/Makefile.
+	for PCIE
+        +       $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-pcie/mlan-pcie.ko \
+	for SDIO
+	+       $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-sd8xxx/mlan-sdio.ko \
+	for USB
+	+       $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mrvl-usb/mlan-usb.ko \
+33. Re-modify (mrvl-pcie/mrvl-sd8xxx/mrvl-usb)/Makefile
+	for PCIE
+
+	-obj-m := mlan.o
+	-mlan-objs := $(MLANOBJS)
+	+obj-m := mlan-pcie.o
+	+mlan-pcie-objs := $(MLANOBJS)
+
+	for SDIO
+
+	-obj-m := mlan.o
+	-mlan-objs := $(MLANOBJS)
+	+obj-m := mlan-sdio.o
+	+mlan-sdio-objs := $(MLANOBJS)
+
+	for USB
+
+	-obj-m := mlan.o
+	-mlan-objs := $(MLANOBJS)
+	+obj-m := mlan-usb.o
+	+mlan-usb-objs := $(MLANOBJS)
+34. Go to step 25.
diff --git a/wlan_sd8997/README_RBC b/wlan_sd8997/README_RBC
new file mode 100644
index 0000000..c849287
--- /dev/null
+++ b/wlan_sd8997/README_RBC
@@ -0,0 +1,103 @@
+===============================================================================
+            U S E R  M A N U A L for Robust BT-WLAN coex (RBC)
+
+ Copyright (C) 2014-2018, Marvell International Ltd.
+ All Rights Reserved
+===============================================================================
+
+###############################
+
+# Abbreviations and acronyms
+
+###############################
+RBC - Robust BT-WLAN co-existence
+TMD - Time Distribute
+SMPS - Spatial Multiplexing Power Save
+
+###############################
+
+# Default RBC modes:
+
+###############################
+1.  For systems where BT and WLAN have seperate antennas, RBC mode is
+    automatically disabled in FW after detecting this from FEM cal data. e.g.
+    For 1x1 Dual-Ant system and 2x2 3-Ant system RBC mode is disabled.
+2.  For systems where BT and WLAN share an antenna, RBC mode is automatically
+    enabled in FW after detecting this from FEM cal data.
+    Default modes:
+    1x1 single antenna system: TMD RBC
+    2x2 2-antenna system: 1x1 SMPS RBC
+
+
+#################################
+
+# 2x2 2-antenna system RBC modes
+
+#################################
+There are three mutually exclusive RBC modes for a 2x2 system.
+The default RBC mode is 1x1 SMPS RBC. The required RBC mode must be
+configured before starting uAP or associating in-STA. The mode cannot be
+changed dynamically when any of these connections is active. The modes are
+described below:
+1.  1x1 SMPS RBC mode: WLAN switches to 1x1 FEM when BT is turned on. Also,
+    in-STA goes to SMPS mode w.r.t. ext-AP. When BT is turned off, WLAN
+    switches back to 2x2 FEM setting and in-STA moves out of SMPS.
+    uAP starts bss with only 1-stream even BT is off because it cannot
+    dynamically move between 1-stream and 2-stream rates like in-STA. To start
+    uAP with 2-stream, RBC mode has to be disabled.
+2.  1x2 SMPS RBC mode: Similar as 1x1 SMPS RBC mode. WLAN switches to 1x2 FEM
+    when BT is turned on. In this mode, it is expected that when BT is not
+    actively transmitting, WLAN can receive on both the antennas to enhance
+    the range. Note that 1-stream rates are used for receive and transmit.
+3.  2x2 TMD RBC mode: WLAN uses 2x2 antenna setting and timeshares the antenna
+    with BT.
+
+###############################
+
+# RBC mode select:
+
+###############################
+
+User can use robust_btc.conf and hostcmd to select different RBC mode:
+
+hostcmd mode_get
+hostcmd mode_timeshare
+hostcmd mode_spatial
+    This command is used to get/set Robust BT Coex.
+    mode_get:       get the current mode
+    mode_timeshare: set Robust BT Coex to timeshare mode  (default on 1x1 chips)
+    mode_spatial:   set Robust BT Coex to spatial mode    (only for, and default on 2x2 chips)
+
+    Usage:
+        mlanconfig mlanX hostcmd config/robust_btc.conf mode_get
+        mlanconfig mlanX hostcmd config/robust_btc.conf mode_timeshare
+        mlanconfig mlanX hostcmd config/robust_btc.conf mode_spatial
+
+hostcmd gpio_cfg
+    This command is used to enable/disable GPIO cfg.
+    gpio_cfg: enable/disable GPIO cfg for external bt request  (default is enable with High Polarity)
+
+    Usage:
+        mlanconfig mlanX hostcmd config/robust_btc.conf gpio_cfg
+
+hostcmd generictime
+hostcmd a2dptime
+hostcmd inquirytime
+hostcmd ap_generictime
+hostcmd ap_a2dptime
+hostcmd ap_inquirytime
+        This command is used to configure the time slice of COEX (only works in timeshare mode)
+        generictime:       configure the Bttime and Wlantime in Station Generic case
+        a2dptime:          configure the Bttime and Wlantime in Station A2DP case
+        inquirytime:       configure the Bttime and Wlantime in Station Inquiry case
+        ap_generictime:    configure the Bttime and Wlantime in Ap Generic case
+        ap_a2dptime:       configure the Bttime and Wlantime in Ap A2DP case
+        ap_inquirytime:    configure the Bttime and Wlantime in Ap Inquiry case
+
+    Usage:
+                mlanutl mlanX hostcmd config/robust_btc.conf generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf inquirytim
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_generictime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_a2dptime
+                mlanutl mlanX hostcmd config/robust_btc.conf ap_inquirytime
diff --git a/wlan_sd8997/README_UAP b/wlan_sd8997/README_UAP
new file mode 100644
index 0000000..a49b918
--- /dev/null
+++ b/wlan_sd8997/README_UAP
@@ -0,0 +1,2696 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright (C) 2009-2018, Marvell International Ltd.
+ All Rights Reserved
+
+1) FOR DRIVER BUILD
+
+	Goto source code directory wlan_src.
+		make [clean] build
+	The driver binaries can be found in ../bin_xxxx directory.
+	The driver code supports Linux kernel up to 4.14.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy sd8786_uapsta.bin | sd8787_uapsta.bin | ... to /lib/firmware/mrvl/ directory,
+	   create the directory if it doesn't exist.
+	b) Install uAP 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
+		The default drv_mode is 7.
+			Bit 4 :  NAN
+
+		max_uap_bss: Maximum number of uAP BSS (default 1, max 2)
+		uap_name: Name of the uAP interface (default: "uap")
+	   For example, to install SD8787 driver,
+	   To load driver in uAP only mode,
+		insmod mlan.ko
+		insmod sd8787.ko drv_mode=2 [fw_name=mrvl/sd8787_uapsta.bin]
+	   To switch mode between STA only, uAP only and uAPSTA in run time,
+		echo drv_mode=1 > /proc/mwlan/config		// STA mode
+		echo drv_mode=2 > /proc/mwlan/config		// uAP mode
+		echo drv_mode=3 > /proc/mwlan/config		// uAPSTA mode
+	c) Uninstall uAP driver,
+		ifconfig uapX down
+		rmmod sd8xxx
+		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)>
+	  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>
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=mrvl/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=mrvl/cal_data.conf
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=mrvl/txpwrlimit_cfg_set.conf
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=mrvl/init_hostcmd_cfg.conf
+	  sdio_rx_aggr=1|2 <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
+	  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>
+
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sd8xxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+	The following info are provided in /proc/mwlan/uapX/info.
+
+	driver_name = "uap"
+	driver_version = <driver version>
+	InterfaceName= "uapX"
+	State= "Disconnected" | "Connected"
+	MACAddress= <6-byte adapter MAC address>
+	MCCount= <multicast address count>
+	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>
+	num_tx_timeout =  <number of tx timeout>
+	carrier "on" | "off"
+	tx queue "stopped" | "started"
+
+	The following debug info are provided in /proc/mwlan/uapX/debug.
+
+	drvdbg = <bit masks of driver debug message control>
+		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,...)
+	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>
+	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>
+	num_bridge_pkts = <number of bridged packets>
+	num_drop_pkts = <number of dropped packets>
+	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>
+	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>
+	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>
+	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>
+	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>
+
+	Example:
+		echo "drvdbg=0x7" > /proc/mwlan/uapX/debug	#enable MMSG,MFATAL,MERROR messages
+
+	Use dmesg or cat /var/log/debug to check driver debug messages.
+
+	To log driver debug messages to file,
+	a) Edit /etc/rsyslog.conf, add one line "*.debug		/var/log/debug"
+	b) touch /var/log/debug (if the file doesn't exist)
+	c) service rsyslog restart
+
+4) SOFT_RESET command
+   This command is used to perform a "soft reset" on the module.
+   The FW code will disable hardware and jump to boot code.
+   Host software will then need to re-download firmware if required.
+
+   Usage:
+	echo "soft_reset=1" > /proc/mwlan/config
+
+===============================================================================
+
+		U S E R  M A N U A L  F O R  UAPUTL
+
+NAME
+uaputl.exe [options] <command> [command parameters]]
+
+Options:
+	--help 	Display help
+	-v    	Display version
+	-i <interface>
+	-d <debug_level=0|1|2>
+
+Example:
+	./uaputl.exe --help
+		"display help for uaputl"
+
+	./uaputl.exe sys_config --help
+		"display help for sys_config command"
+
+This tool can be used to set/get uAP's settings. To change AP settings, you might
+need to issue "bss_stop" command to stop AP before making change and issue "bss_start"
+command to restart the AP after making change.
+
+------------------
+Supported Commands
+------------------
+version
+debug_level
+sys_config [CONFIG_FILE_NAME]
+bss_config [CONFIG_FILE_NAME]
+sys_info
+sys_reset
+bss_start
+bss_stop
+sta_list
+sta_deauth <STA_MAC_ADDRESS>
+sta_deauth_ext <STA_MAC_ADDRESS> <REASON_CODE>
+radioctrl [0|1]
+txratecfg [l] [m] [n]
+antcfg [m] [n]
+pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE]
+sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]
+coex_config [CONFIG_FILE_NAME]
+hscfg [condition [[GPIO# [gap]]]]
+hssetpara condition [[GPIO# [gap]]]
+sys_cfg_wmm  [qosinfo=<qosinfo>]
+             [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+             [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+             [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+             [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+sys_cfg_ap_wmm [0]
+               [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+               [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+               [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+               [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]
+sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_MAP]
+addbapara [timeout txwinsize rxwinsize txamsdu rxamsdu]
+aggrpriotbl <m0> <n0> <m1> <n1> ... <m7> <n7>
+addbareject <m0> <m1> ... <m7>
+httxbfcfg <ACTION> [ACT_DATA]
+httxcfg [<m>] [<n>]
+htstreamcfg [n]
+deepsleep [MODE] [IDLE_TIME]
+sdcmd52rw <FN no.> <address> [data]
+hostcmd <txpwrlimit_cfg.conf> txpwrlimit_cfg_get
+hostcmd <txpwrlimit_cfg.conf> txpwrlimit_2g_cfg_set
+hostcmd <txpwrlimit_cfg.conf> txpwrlimit_5g_cfg_set
+tx_data_pause [ENABLE][TX_BUF_CNT]
+vhtcfg <j> <k> [l] [m] [n] [o]
+dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]
+cscount [<channel_switch_count>]
+mgmtframectrl [MASK]
+
+-------------------------------------------------------------------
+The following commands can be issued individually for debug purpose
+-------------------------------------------------------------------
+sys_cfg_ap_mac_address [AP_MAC_ADDRESS]
+sys_cfg_ssid [SSID]
+sys_cfg_beacon_period [BEACON_PERIOD]
+sys_cfg_dtim_period [DTIM_PERIOD]
+sys_cfg_channel [CHANNEL] [MODE]
+sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]
+sys_cfg_scan_channels [CHANNEL[.BAND]]
+sys_cfg_rates [RATES]
+sys_cfg_rates_ext [rates RATES] [mbrate RATE]
+sys_cfg_tx_power [TX_POWER]
+sys_cfg_bcast_ssid_ctl [0|1|2]
+sys_cfg_preamble_ctl
+sys_cfg_bss_status
+sys_cfg_rts_threshold [RTS_THRESHOLD]
+sys_cfg_frag_threshold [FRAG_THRESHOLD]
+sys_cfg_rsn_replay_prot [1|0]
+sys_cfg_tx_beacon_rate [TX_BEACON_RATE]
+sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]
+sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]
+sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]
+sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]
+sys_cfg_auth [AUTH_MODE]
+sys_cfg_protocol [PROTOCOL] [AKM_SUITE]
+sys_cfg_pmf [MFPC] [MFPR]
+sys_cfg_wep_key [INDEX ISDEFAULT KEY]
+sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]
+sys_cfg_pwk_cipher [<PROTOCOL>] [PAIRWISE_CIPHER]
+sys_cfg_gwk_cipher [GROUP_CIPHER]
+sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]
+sys_cfg_wpa_passphrase [PASSPHRASE]
+sys_cfg_max_sta_num [STA_NUM]
+sys_cfg_retry_limit [RETRY_LIMIT]
+sys_cfg_sticky_tim_config [ENABLE] [<DURATION> <STICKY_BIT_MASK>]
+sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]
+sys_cfg_2040_coex [ENABLE]
+sys_cfg_eapol_pwk_hsk [<TIMEOUT> <RETRIES>]
+sys_cfg_eapol_gwk_hsk [<TIMEOUT> <RETRIES>]
+sta_filter_table <FILTERMODE> <MACADDRESS_LIST>
+regrdwr <TYPE> <OFFSET> [value]
+memaccess <ADDR> [value]
+rdeeprom <offset> <byteCount>
+cfg_data <type> [*.conf]
+sys_cfg_80211d [state STATE] [country COUNTRY]
+uap_stats
+sys_cfg_tdls_ext_cap [CONFIG_FILE]
+sys_cfg_restrict_client_mode [<ENABLE> [MODE_CONFIG]]
+skip_cac [<MODE>]
+
+-------------------
+Details of Commands
+-------------------
+
+version
+-------
+    "./uaputl.exe -v"
+
+    This command prints the uAP utility version information.
+
+debug_level
+-----------
+    "./uaputl.exe -d <debug_level>"
+
+    The supported debug_level are:
+        0     - no debug
+        1     - enable MSG_DEBUG
+        2     - enable all the debug
+    This command use to control the debug level of uaputl.exe.
+
+    Example:
+	./uaputl.exe -d 2 sys_config
+		Enable all the debug in uaputl.exe
+
+sys_config
+----------
+    "./uaputl.exe sys_config [CONFIG_FILE]"
+    This command is used to set or get the current settings of the Micro AP.
+
+    The supported options are:
+        CONFIG_FILE is file contain all the Micro AP settings.
+        empty - Get current Micro AP settings
+
+    Example:
+	./uaputl.exe sys_config
+		Get current settings of the Micro AP.
+
+	./uaputl.exe sys_config config/uaputl.conf
+		Load Micro AP's settings from uaputl.conf file and set.
+
+bss_config
+----------
+    "./uaputl.exe bss_config [CONFIG_FILE]"
+    This command is used to set or get the current settings of the BSS.
+
+    The supported options are:
+        CONFIG_FILE is file contain all the BSS settings.
+        empty - Get current BSS settings
+
+    Example:
+	./uaputl.exe bss_config
+		Get current settings of the BSS.
+
+	./uaputl.exe bss_config config/uaputl.conf
+		Load BSS settings from uaputl.conf file and set.
+
+sys_info
+--------
+    "./uaputl.exe sys_info"
+
+    This command returns system information such as firmware version number
+    and HW information.
+
+sys_reset
+---------
+    "./uaputl.exe sys_reset"
+
+    This command is used to reset the Micro AP back to its initial state.
+    For example, this can be used to recover from a serious error, or before
+    creating a new BSS.
+
+    This command has the following effects:
+        1. The WLAN hardware MAC is reset.
+        2. All MIB variables are initialized to their respective default
+           values.
+        3. The firmware internal variables are reset to their respective
+           default values.
+        4. The firmware state machines are reset to their respective initial
+           states.
+
+bss_start
+---------
+    "./uaputl.exe bss_start"
+
+    This command starts the BSS.
+    There is no error for redundant bss_start command.
+
+bss_stop
+--------
+    "./uaputl.exe bss_stop"
+
+    This command stops the BSS. The command causes the firmware to:
+        1. Deauthenticate all associated client stations.
+        2. Turn off the radio (hence stopping beaconing).
+    There is no error for redundant bss_stop command.
+
+sta_list
+--------
+    "./uaputl.exe sta_list"
+
+    This command returns the list of client stations that are currently
+    associated with the AP.
+
+    The output is formatted as shown below, for each STA:
+    "STA <STA_NUM> information:
+     ==========================
+     MAC Address: <STA MAC address>
+     Power mfg status: active|power save
+     Rssi:  <RSSI_VALUE>"
+
+sta_deauth
+----------
+    "./uaputl.exe sta_deauth <STA_MAC_ADDRESS>"
+
+    This command is used to de-authentciate a client station for any reason.
+
+radioctrl
+----------
+    "./uaputl.exe radioctrl [0|1]"
+
+    This command is used to set or get the radio settings.
+    The supported options are:
+        1     - Turn radio on
+        0     - Turn radio off
+        empty - Get current radio setting
+
+txratecfg
+----------
+    "./uaputl.exe txratecfg [l] [m] [n]"
+
+    This command is used to set/get the transmit data rate.
+
+    Where
+        [l] is <format>
+        <format> - This parameter specifies the data rate format used in this command
+            0:    LG
+            1:    HT
+            2:    VHT
+            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
+            32   MCS32
+        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
+        [n] is <nss>
+        <nss> - This parameter specifies the NSS. It is valid only for VHT
+        If <format> is 2 (VHT),
+            1    NSS1
+            2    NSS2
+
+    Examples:
+        ./uaputl.exe txratecfg 0 3        : Set fixed Tx rate to 11 Mbps
+        ./uaputl.exe txratecfg 0 11       : Set fixed Tx rate to 54 Mbps
+        ./uaputl.exe txratecfg 1 3        : Set fixed Tx rate to MCS3
+        ./uaputl.exe txratecfg 2 3 2    : Set fixed Tx rate to MCS3 for NSS2
+        ./uaputl.exe txratecfg 0xff     : Disable fixed rate and uses auto rate
+        ./uaputl.exe txratecfg          : Read the current data rate setting
+
+antcfg
+----------
+    "./uaputl.exe antcfg [m] [n]"
+
+    This command is used to set/get the transmit and receive antenna.
+    where value of m is:
+        Bit 0   -- Tx Path A
+        Bit 1   -- Tx Path B
+        Bit 0-1 -- Tx Path A+B
+
+    where value of n is:
+        Bit 0   -- Rx Path A
+        Bit 1   -- Rx Path B
+        Bit 0-1 -- Rx Path A+B
+    The Tx path setting (m) is used if Rx path (n) is not provided.
+
+    Examples:
+        ./uaputl.exe antcfg             : Get Tx and Rx path
+        ./uaputl.exe antcfg 3           : Set Tx and Rx path to A+B
+        ./uaputl.exe antcfg 2 3         : Set Tx path to B and Rx path to A+B
+
+sys_cfg_ap_mac_address
+----------------------
+    "./uaputl.exe sys_cfg_ap_mac_address [AP_MAC_ADDRESS]"
+
+    This command is used to set or get the AP MAC address.
+
+    If no arguments are given, this command returns the current AP MAC
+    address.
+    Otherwise, this MAC address becomes the BSSID of the infrastructure
+    network created by the AP.
+
+    Example:
+	./uaputl.exe sys_cfg_ap_mac_address 00:50:43:20:aa:bb
+		Set AP MAC address to 00:50:43:20:aa:bb
+
+	./uaputl.exe sys_cfg_ap_mac_address
+		Get AP MAC address"
+
+sys_cfg_ssid
+------------
+    "./uaputl.exe sys_cfg_ssid [SSID]"
+
+    This command is used to set or get the AP SSID.
+
+    If no arguments are given, this command returns the current AP SSID.
+    While setting, the maximum length of the SSID can be 32 characters.
+
+    Example:
+	./uaputl.exe sys_cfg_ssid microap
+		Set AP ssid to "microap"
+
+	./uaputl.exe sys_cfg_ssid
+		Get AP ssid
+
+sys_cfg_beacon_period
+---------------------
+    "./uaputl.exe sys_cfg_beacon_period [BEACON_PERIOD]"
+
+    This command is used to set or get the AP beacon period.
+
+    If no arguments are given, this command returns the current AP beacon
+    period.
+
+    Beacon period is represented in milliseconds.
+
+    Example:
+	./uaputl.exe sys_cfg_beacon_period 100
+		Set AP beacon period to 100 TU
+
+	./uaputl.exe sys_cfg_beacon_period
+		Get AP beacon period
+
+sys_cfg_dtim_period
+-------------------
+    "./uaputl.exe sys_cfg_dtim_period [DTIM_PERIOD]
+
+    This command is used to set or get the AP DTIM period.
+
+    If no arguments are given, this command returns the current AP DTIM
+    period.
+
+    Example:
+	./uaputl.exe sys_cfg_dtim_period 3
+		Set AP DTIM period to 3
+
+	./uaputl.exe sys_cfg_dtim_period
+		Get AP DTIM period
+
+sys_cfg_scan_channels
+---------------------
+    "./uaputl.exe sys_cfg_scan_channels [CHANNEL[.BAND]]"
+
+    This command is used to set or get the AP's scan channel list.
+
+    If no arguments are given, this command returns the scan channel list.
+    If BAND is 0, channel is set in 2.4 GHz band and if BAND is 1, channel is set to 5GHz.
+    Channels from only one of the bands should be specified.
+    Each CHANNEL.BAND pair must be separated by a space. BAND parameter is optional.
+
+    Example:
+	./uaputl.exe sys_cfg_scan_channels 1 11 6
+		Set AP scan channel list to 1 11 6
+
+	./uaputl.exe sys_cfg_scan_channels 11.0 6.0
+		Set AP scan channel list to 11 6
+
+	./uaputl.exe sys_cfg_scan_channels
+		Get AP scan channel list
+
+        ./uaputl.exe sys_cfg_scan_channels 8.1 16.1 34
+                Set AP scan channel list to 8 16 and 34 in 5GHz band.
+
+sys_cfg_channel
+---------------
+    "./uaputl.exe sys_cfg_channel [CHANNEL] [MODE]"
+
+    This command is used to set or get the AP radio channel.
+
+    If no arguments are given, this command returns the current AP radio
+    channel.
+
+    MODE: band config mode.
+          Bit 0:  automatic channel selection (ACS) enable/disable
+          Bit 1:  secondary channel is above primary channel enable/disable(only allow for channel 1-7)
+          Bit 2:  secondary channel is below primary channel enable/disable(only allow for channel 5-11)
+          For 'a' band channel:
+          Bit 1:  secondary channel is above primary channel enable/disable
+          Bit 2:  secondary channel is below primary channel enable/disable
+          Only following pairs of channels are valid for secondary channel setting in 5GHz band.
+          36, 40
+          44, 48
+          52, 56
+          60, 64
+          100, 104
+          108, 112
+          116, 120
+          124, 128
+          132, 136
+          149, 153
+          157, 161
+
+    Example:
+        ./uaputl.exe sys_cfg_channel 6
+                Set AP radio channel to 6, and no secondary channel.
+
+        ./uaputl.exe sys_cfg_channel 11 0
+                Set AP radio channel to 11 with Manual Channel Select.
+
+        ./uaputl.exe sys_cfg_channel 0 1
+                Set AP to ACS.
+
+        ./uaputl.exe sys_cfg_channel
+                Get AP radio channel
+
+        ./uaputl.exe sys_cfg_channel 6 2
+                Set AP primary radio channel to 6, and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel 6 4
+                Set AP primary radio channel to 6, and secondary channel is below
+        ./uaputl.exe sys_cfg_channel 0 3
+                Set AP to ACS mode, and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel 0 5
+                Set AP to ACS mode, and secondary channel is below.
+        ./uaputl.exe sys_cfg_channel 36 2
+                Set AP primary radio channel to 36, and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel 40 4
+                Set AP primary radio channel to 40, and secondary channel is below.
+
+sys_cfg_channel_ext
+---------------
+    "./uaputl.exe sys_cfg_channel_ext [CHANNEL] [BAND] [MODE]"
+
+    This command is used to set or get the AP radio channel.
+
+    If no arguments are given, this command returns the current AP radio
+    channel.
+
+    BAND: 0 : 2.4GHz operation
+          1 : 5GHz operation
+    MODE: band config mode.
+          Bit 0:  automatic channel selection (ACS) enable/disable
+          Bit 1:  secondary channel is above primary channel enable/disable(only allow for channel 1-7)
+          Bit 2:  secondary channel is below primary channel enable/disable(only allow for channel 5-11)
+          For 'a' band channel:
+          Bit 1:  secondary channel is above primary channel enable/disable
+          Bit 2:  secondary channel is below primary channel enable/disable
+          Only following pairs of channels are valid for secondary channel setting in 5GHz band.
+          36, 40
+          44, 48
+          52, 56
+          60, 64
+          100, 104
+          108, 112
+          116, 120
+          124, 128
+          132, 136
+          149, 153
+          157, 161
+
+    Example:
+        ./uaputl.exe sys_cfg_channel_ext 6
+Set AP radio channel to 6, and no secondary channel.
+
+        ./uaputl.exe sys_cfg_channel_ext 11 0 0
+                Set AP radio channel to 11 in 2.4GHz band with Manual Channel Select.
+
+        ./uaputl.exe sys_cfg_channel_ext 0 0 1
+                Set AP to ACS mode and 2.4GHz band.
+
+        ./uaputl.exe sys_cfg_channel_ext 8 0
+                Set AP to channel 8 and 2.4GHz band.
+
+        ./uaputl.exe sys_cfg_channel_ext 8 1
+                Set AP to channel 8 and 5GHz band.
+
+        ./uaputl.exe sys_cfg_channel_ext 36 1
+                Set AP to channel 36 and 5GHZ band.
+
+        ./uaputl.exe sys_cfg_channel_ext
+                Get AP radio channel, band and mode.
+
+        ./uaputl.exe sys_cfg_channel_ext 6 0 2
+                Set AP primary radio channel to 6, band to 2.4GHz and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel_ext 6 0 4
+                Set AP primary radio channel to 6, band to 2.4GHz and secondary channel is below
+        ./uaputl.exe sys_cfg_channel_ext 0 0 3
+                Set AP to ACS mode, band to 2.4GHz and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel_ext 0 0 5
+                Set AP to ACS mode, band to 2.4GHz and secondary channel is below.
+        ./uaputl.exe sys_cfg_channel_ext 36 1 2
+                Set AP primary radio channel to 36, band to 5GHz and secondary channel is above.
+        ./uaputl.exe sys_cfg_channel_ext 40 1 4
+                Set AP primary radio channel to 40, band to 5GHz and secondary channel is below.
+
+sys_cfg_rates
+-------------
+    "./uaputl.exe sys_cfg_rates [RATES]"
+
+    If 'Rate' provided, a 'set' is performed else a 'get' is performed
+    RATES is provided as a set of data rates, in unit of 500 kilobits
+    A rate with MSB bit is basic rate, i.e 0x82 is basic rate.
+
+    'set' will not allowed after bss start.
+
+    Valid rates: 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
+    Non-Basic rates: 0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+    Basic rates: 0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc
+
+    Each rate must be separated by a space.
+
+    Example:
+    ./uaputl.exe sys_cfg_rates 0x82 0x84 0x96 0x0c 0x12 0x18
+    ./uaputl.exe sys_cfg_rates
+
+sys_cfg_rates_ext
+-----------------
+    "./uaputl.exe sys_cfg_rates_ext [rates RATES] [mbrate RATE]"
+
+    If 'Rate' provided, a 'set' is performed else a 'get' is performed.
+    RATES is provided as a set of data rates, in unit of 500 kilobits
+    A rate with MSB bit is basic rate, i.e 0x82 is basic rate.
+    If only operational rates is provided, MCBC rate and unicast rate will be set to auto.
+
+    Valid rates: 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
+    Non-Basic rates: 0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+    Basic rates: 0x82, 0x84, 0x8b, 0x96, 0x8C, 0x92, 0x98, 0xA4, 0xB0, 0xC8, 0xE0, 0xEc
+    Rates 2, 4, 11 and 22 (in units of 500 Kbps) must be present in either of
+    basic or non-basic rates. If OFDM rates are enabled then 12, 24 and 48 (in
+    units of 500 Kbps) must be present in either basic or non-basic rates.
+
+    Each rate must be separated by a space.
+
+    rates followed by RATES for setting operational rates.
+    mbrate followed by RATE for setting multicast and broadcast rate.
+
+    operational rates only allow to set before bss start.
+
+    Example:
+    ./uaputl.exe sys_cfg_rates_ext rates 0x82 0x04 11 0x96 12 24 48 mbrate 0x16
+        Set AP operation rates to 0x82,0x04,11,0x96,12,24,48, multicast rate to 0x16
+    ./uaputl.exe sys_cfg_rates_ext rates 0x82 0x04 11 0x96 12 24 48
+		Set AP operation rates to 0x82,0x04,11,0x96,12,24,48.
+
+sys_cfg_tx_power
+----------------
+    "./uaputl.exe sys_cfg_tx_power [TX_POWER]"
+
+    This command is used to set or get the AP Tx power.
+
+    If no arguments are given, this command returns the current AP Tx power.
+
+    Tx power level is represented in dBm.
+
+    Example:
+	./uaputl.exe sys_cfg_tx_power 13
+		Set AP Tx power to 13 dBm
+
+	./uaputl.exe sys_cfg_tx_power
+		Get AP Tx power
+
+sys_cfg_bcast_ssid_ctl
+----------------------
+    "./uaputl.exe sys_cfg_bcast_ssid_ctl [0|1|2]"
+
+    This command is used to set or get the SSID broadcast feature setting.
+
+    The supported options are:
+        0     - Disable SSID broadcast, send empty SSID (length=0) in beacon.
+        1     - Enable SSID broadcast
+        2     - Disable SSID broadcast, clear SSID (ACSII 0) in beacon, but keep the original length
+        empty - Get current SSID broadcast setting
+
+    When broadcast SSID is enabled, the AP responds to probe requests from
+    client stations that contain null SSID.
+
+    When broadcast SSID is disabled (sys_cfg_bcast_ssid_ctl = 0/2), the AP:
+        1. Does not respond to probe requests that contain null SSID.
+        2. when sys_cfg_bcast_ssid_ctl = 0, generates beacons that contain null SSID (length=0).
+        3. when sys_cfg_bcast_ssid_ctl = 2, clear SSID (ACSII 0) in beacon and keep the original length
+
+   Example:
+        ./uaputl.exe sys_cfg_bcast_ssid_ctl 0
+                Disable SSID broadcast, send empty SSID (length=0) in beacon.
+
+	./uaputl.exe sys_cfg_bcast_ssid_ctl 1
+		Enable SSID broadcast
+
+        ./uaputl.exe sys_cfg_bcast_ssid_ctl 2
+                Disable SSID broadcast, clear SSID (ACSII 0) in beacon, but keep the original length
+
+	./uaputl.exe sys_cfg_bcast_ssid_ctl
+		Get SSID broadcast setting
+
+sys_cfg_preamble_ctl
+--------------------
+    "./uaputl.exe sys_cfg_preamble_ctl"
+
+    This command is used to get type of preamble.
+
+    Example:
+	./uaputl.exe sys_cfg_preamble_ctl
+		Get AP preamble setting
+
+sys_cfg_bss_status
+--------------------
+    "./uaputl.exe sys_cfg_bss_status"
+
+    This command is used to get current BSS status.
+
+    Example:
+	./uaputl.exe sys_cfg_bss_status
+		Get current BSS status
+
+sys_cfg_rts_threshold
+---------------------
+    "./uaputl.exe sys_cfg_rts_threshold [RTS_THRESHOLD]"
+
+    This command is used to set or get the RTS threshold value.
+
+    If no arguments are given, this command returns the current RTS threshold
+    value.
+
+    Example:
+	./uaputl.exe sys_cfg_rts_threshold 2347
+		Set AP RTS threshold to 2347
+
+	./uaputl.exe sys_cfg_rts_threshold
+		Get AP RTS threshold
+
+sys_cfg_frag_threshold
+----------------------
+    "./uaputl.exe sys_cfg_frag_threshold [FRAG_THRESHOLD]"
+
+    This command is used to set or get the Fragmentation threshold value.
+
+    If no arguments are given, this command returns the current Fragmentation threshold
+    value.
+
+    Example:
+	./uaputl.exe sys_cfg_frag_threshold 2346
+		Set AP Fragmentation threshold to 2346
+
+	./uaputl.exe sys_cfg_frag_threshold
+		Get AP Fragmentation threshold
+
+    Note: Please use aggrpriotbl command to disable the AMPDU/AMSDU aggregation when frag_threshold is set.
+
+sys_cfg_rsn_replay_prot
+-----------------------
+    "./uaputl.exe sys_cfg_rsn_replay_prot [1|0]"
+
+    This command is used to enable or disable RSN replay protection.
+
+    The supported options are:
+        0     - Disable RSN replay protection
+        1     - Enable RSN replay protection
+        empty - Get current RSN replay protection setting
+
+   Example:
+	./uaputl.exe sys_cfg_rsn_replay_prot 1
+		Enable RSN replay protection
+
+	./uaputl.exe sys_cfg_rsn_replay_prot
+		Get RSN replay protection setting
+
+sys_cfg_tx_beacon_rate
+--------------------
+    "./uaputl.exe sys_cfg_tx_beacon_rate [TX_BEACON_RATE]"
+
+    This command is used to set or get the Tx beacon rate settings.
+
+    The supported options are:
+        0     - Auto rate
+        >0    - Set specified beacon rate
+        empty - Get current beacon rate
+
+    Tx beacon rate is represented in units of 500 kbps. While setting Tx beacon
+    rates, only zero or rates currently configured are allowed.
+
+	Following is the list of supported rates in units of 500 Kbps:
+	    2,    4,    11,   22,   12,   18,   24,   36,   48,   72,   96,   108
+	    0x02, 0x04, 0x0b, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+
+    Example:
+	./uaputl.exe sys_cfg_tx_beacon_rate 0x04
+		Set AP Tx beacon rate to 2 M
+
+   	./uaputl.exe sys_cfg_tx_beacon_rate 4
+		Set AP Tx data beacon to 2 M
+
+	./uaputl.exe sys_cfg_tx_beacon_rate
+		Get AP Tx beacon rate
+
+sys_cfg_mcbc_data_rate
+----------------------
+    "./uaputl.exe sys_cfg_mcbc_data_rate [MCBC_DATA_RATE]"
+
+    This command is used to set or get the MCBC data rate to use for multicast
+    or broadcast packet transmission.
+
+    The supported options are:
+        0     - Auto rate
+        >0    - Set specified MCBC data rate
+        empty - Get current MCBC data rate
+
+    MCBC data rate is represented in units of 500 kbps. While setting MCBC data
+    rates, only zero or one of rates currently configured as basic rates are allowed.
+
+    For example:  If current basic rates is "0x82 0x84 0x8b 0x96", then the allowed
+                  values for MCBC data rate will be "0x2 0x4 0xb 0x16".
+
+    Example:
+	./uaputl.exe sys_cfg_mcbc_data_rate 22
+		Set AP MCBC data rate to 11 M
+
+   	./uaputl.exe sys_cfg_mcbc_data_rate 0
+		Set AP MCBC data rate to auto
+
+	./uaputl.exe sys_cfg_mcbc_data_rate
+		Get AP MCBC data rate
+
+sys_cfg_pkt_fwd_ctl
+-------------------
+    "./uaputl.exe sys_cfg_pkt_fwd_ctl [PKT_FWD_CTRL]"
+
+    This command is used to set or get the packet forwarding control
+    settings.
+
+    where PKT_FWD_CTRL is:
+        bit 0 -- Packet forwarding handled by Host (0) or Firmware (1)
+        bit 1 -- Intra-BSS broadcast packets are allowed (0) or denied (1)
+        bit 2 -- Intra-BSS unicast packets are allowed (0) or denied (1)
+        bit 3 -- Inter-BSS unicast packets are allowed (0) or denied (1)
+        empty - Get current packet forwarding setting
+
+    Example:
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 1
+		Set AP packet forwarding control in firmware to allow all packets
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 6
+		Set AP packet forwarding control in Host, only allow Inter-BSS unicast packets forwarding.
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 8
+		Set AP packet forwarding control in Host, only allow Intra-BSS packets forwarding.
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl 0
+		Set AP packet forwarding control in Host, allow Intra-BSS packets and
+	            Inter-BSS unicast packets forwarding.
+
+	./uaputl.exe sys_cfg_pkt_fwd_ctl
+		Get AP packet forwarding control
+
+sys_cfg_sta_ageout_timer
+------------------------
+    "./uaputl.exe sys_cfg_sta_ageout_timer [STA_AGEOUT_TIMER]"
+
+    This command is used to set or get the STA ageout value.
+
+    Value of 0 will mean that stations will never be aged out.
+
+    Minimum value for this is 100. Maximum allowed setting should be 864000.
+
+    If no arguments are given, this command returns the current STA ageout
+    value.
+
+    Ageout timer value is represented in units of 100 ms.
+
+    Example:
+	./uaputl.exe sys_cfg_sta_ageout_timer 1800
+		Set AP STA ageout time to 180000 ms
+
+	./uaputl.exe sys_cfg_sta_ageout_timer
+		Get AP STA ageout time
+
+sys_cfg_ps_sta_ageout_timer
+---------------------------
+	"./uaputl.exe sys_cfg_ps_sta_ageout_timer [PS_STA_AGEOUT_TIMER]"
+
+	This command is used to set or get the PS STA ageout value.
+
+	Value of 0 will mean that stations will never be aged out.
+
+	Minimum value for this is 100. Maximum allowed setting should be 864000.
+
+	If no arguments are given, this command returns the current	PS STA ageout
+	value.
+
+	Ageout timer value is represented in units of 100 ms.
+
+	Example:
+	./uaputl.exe sys_cfg_ps_sta_ageout_timer 1800
+		Set AP PS STA ageout time to 180000 ms
+
+	./uaputl.exe sys_cfg_ps_sta_ageout_timer
+		Get AP PS STA ageout time
+
+sys_cfg_auth
+------------
+    "./uaputl.exe sys_cfg_auth [AUTHMODE]"
+
+    This command is used to set or get the AP authentication mode.
+
+    The supported options are:
+        AUTHMODE :     0 - Open authentication
+                       1 - Shared key authentication
+                       255 - Auto (Open and Shared key) authentication
+    empty - Get current authentication mode
+
+    Example:
+	./uaputl.exe sys_cfg_auth 0
+		Set AP authentication mode to Open.
+
+	./uaputl.exe sys_cfg_auth
+		Get AP authentication mode.
+
+sys_cfg_protocol
+----------------
+    "./uaputl.exe sys_cfg_protocol [PROTOCOL] [AKM_SUITE]"
+
+    This command is used to set or get the encryption protocol.
+
+    The supported options are:
+	PROTOCOL:
+			1		 No RSN
+			2		WEP Static
+			8		  WPA
+			32		  WPA2
+			40		 WPA, WPA2 Mixed Mode
+    empty - Get current encryption protocol
+
+    AKM_SUITE:
+            bit 0   KEY_MGMT_EAP
+            bit 1   KEY_MGMT_PSK
+            bit 2   KEY_MGMT_NONE
+            bit 8   KEY_MGMT_PSK_SHA256
+
+    Example:
+	./uaputl.exe sys_cfg_protocol 2
+		Set AP encryption protocol to static WEP.
+
+	./uaputl.exe sys_cfg_protocol
+		Get AP encryption protocol.
+
+    ./uaputl.exe sys_cfg_protocol 32 0x102
+        Set AP encryption protocol to WPA2 and AKM SUITE to PSK and PSK SHA256
+
+    ./uaputl.exe sys_cfg_protocol 40 0x100
+        Set AP encryption protocol to WPA+WPA2 and AKM SUITE to PSK SHA256
+
+sys_cfg_pmf
+-----------
+    "./uaputl.exe sys_cfg_pmf [MFPC] [MFPR]"
+
+    This command is used to set or get the PMF settings.
+
+    The supported options are:
+        MFPC:       0 - Mgmt frame protection not capable
+                    1 - Mgmt frame protection capable
+
+        MFPR:       0 - Mgmt frame protection not required
+                    1 - Mgmt frame protection required
+                    x - don't care if MFPC = 0
+
+    Example:
+    ./uaputl.exe sys_cfg_pmf 1 1
+        Set AP's PMF params to Mgmt frames protection capable and required.
+
+    ./uaputl.exe sys_cfg_pmf
+        Get AP's PMF params settings.
+
+sys_cfg_wep_key
+---------------
+    "./uaputl.exe sys_cfg_wep_key [INDEX ISDEFAULT Key_0]
+                                  [INDEX ISDEFAULT Key_1]
+                                  [INDEX ISDEFAULT Key_2]
+                                  [INDEX ISDEFAULT Key_3]
+                                  [INDEX]"
+
+    This command is used to set or get the WEP key settings.
+
+    The supported options are:
+        INDEX:       0 - KeyIndex is 0
+                     1 - KeyIndex is 1
+                     2 - KeyIndex is 2
+                     3 - KeyIndex is 3
+	ISDEFAULT:   0: KeyIndex is not the default
+		     1: KeyIndex is the default transmit key
+
+        KEY_* :      Key value.
+        empty - Get current WEP key settings for all the keys
+        INDEX - Only INDEX will get the key setting for the particular
+                KeyIndex.
+
+    Example:
+	./uaputl.exe sys_cfg_wep_key 0 1 55555
+		Set AP's default transmit key to "55555", key index is 0.
+
+    ./uaputl.exe sys_cfg_wep_key 0 1 12345678901234567890123456
+        Set AP's default transmit key to "12345678901234567890123456", key index is 0.
+
+	./uaputl.exe sys_cfg_wep_key
+		Get AP all the WEP keys settings.
+
+	./uaputl.exe sys_cfg_wep_key 1
+		Get WEP key setting for the KeyIndex = 1.
+
+sys_cfg_cipher
+--------------
+    "./uaputl.exe sys_cfg_cipher [PAIRWISE_CIPHER GROUP_CIPHER]"
+
+    This command is used to set or get the key types for the pairwise and group key.
+
+    The supported options are:
+	PAIRWISE_CIPHER:
+			0		  None
+			4		  TKIP
+			8		 AES CCMP
+			12		 AES CCMP + TKIP
+        GROUP_CIPHER:
+			0		  None
+			4		  TKIP
+			8		 AES CCMP
+    	empty - Get current key types
+
+	Valid combinations of [PAIRWISE_CIPHER GROUP_CIPHER] are:
+		[0 0], [4 4], [8 8], [12 4].
+
+    Example:
+	./uaputl.exe sys_cfg_cipher 4 4
+		Set AP's pairwise and group key's type to TKIP.
+
+	./uaputl.exe sys_cfg_cipher
+		Get AP's key types for the pairwise and group key.
+
+sys_cfg_pwk_cipher
+------------------
+    "./uaputl.exe sys_cfg_pwk_cipher [<PROTOCOL>] [PAIRWISE_CIPHER]"
+
+    This command is used to set or get protocol and corresponding pairwise cipher settings.
+
+    The supported options are:
+        PROTOCOL:
+                        0                None
+                        8                 WPA
+                        32                WPA2
+        PAIRWISE_CIPHER:
+                        0                 None
+                        4                 TKIP
+                        8                AES CCMP
+                        12               AES CCMP + TKIP
+        WPA/TKIP cipher cannot be used when uAP operates in 802.11n mode.
+        If only PROTOCOL is provided, pairwise cipher for that protocol is displayed.
+        empty - Get protocol and corresponding pairwise cipher settings.
+
+    Example:
+        ./uaputl.exe sys_cfg_pwk_cipher 8 4
+                Set AP's pairwise cipher to TKIP for WPA protocol.
+
+        ./uaputl.exe sys_cfg_pwk_cipher 32
+                Get AP's pairwise cipher for WPA2 protocol.
+
+        ./uaputl.exe sys_cfg_pwk_cipher
+                Get AP's protocol and corresponding pairwise cipher settings.
+
+sys_cfg_gwk_cipher
+------------------
+    "./uaputl.exe sys_cfg_gwk_cipher [GROUP_CIPHER]"
+
+    This command is used to set or get group cipher.
+
+    The supported options are:
+        GROUP_CIPHER:
+                        0                 None
+                        4                 TKIP
+                        8                AES CCMP
+        empty - Get group cipher settings.
+
+    Example:
+        ./uaputl.exe sys_cfg_gwk_cipher 8
+                Set AP's group cipher to AES CCMP.
+
+        ./uaputl.exe sys_cfg_gwk_cipher
+                Get AP's group cipher settings.
+
+sys_cfg_group_rekey_timer
+-------------------------
+    "./uaputl.exe sys_cfg_group_rekey_timer [GROUP_REKEY_TIMER]"
+
+    This command is used to set or get the AP group re-key time interval, in seconds.
+
+    The supported options are:
+        GROUP_REKEY_TIMER is represented in seconds. This is only applicable
+        		 if the protocol is WPA or WPA2. Value of 0 will disable group re-key.
+
+        empty - Get current group rekey timer
+
+    Example:
+	./uaputl.exe sys_cfg_group_rekey_timer 1800
+		Set AP's group re-key time interval to 1800 s
+
+	./uaputl.exe sys_cfg_group_rekey_timer
+		Get AP's group re-key time interval.
+
+sys_cfg_wpa_passphrase
+----------------------
+    "./uaputl.exe sys_cfg_wpa_passphrase [PASSPHRASE]"
+
+    This command is used to set or get the WPA or WPA2 passphrase.
+
+    If no arguments are given, this command returns the current WPA or WPA2
+    passphrase.
+    While setting, the maximum length of the passphrase can be 64 characters.
+
+    Example:
+	./uaputl.exe sys_cfg_wpa_passphrase 1234567890
+		Set AP's WPA or WPA2 passphrase to "1234567890"
+
+	./uaputl.exe sys_cfg_wpa_passphrase
+		Get AP's WPA or WPA2 passphrase.
+
+sys_cfg_max_sta_num
+-------------------
+    "./uaputl.exe sys_cfg_max_sta_num [STA_NUM]"
+
+    This command is used to set or get the maximum number of stations allowed to connect to uAP.
+
+    If no arguments are given, this command returns the configured maximum number of stations
+		allowed to connect to uAP and maximum number of stations supported.
+
+    Example:
+	./uaputl.exe sys_cfg_max_sta_num 2
+		Set AP's maximum station number to 2
+
+	./uaputl.exe sys_cfg_max_sta_num
+		Get AP's maximum station number configured and maximum station number supported.
+
+sys_cfg_retry_limit
+-------------------
+    "./uaputl.exe sys_cfg_retry_limit [RETRY_LIMIT]"
+
+    This command is used to set or get the retry limit to use for packet transmissions.
+
+    The maximum retry_limit allowed is 14.
+
+    If no arguments are given, this command returns the current retry limit value.
+
+    Example:
+	./uaputl.exe sys_cfg_retry_limit 2
+		Set AP's retry limit value to 2
+
+	./uaputl.exe sys_cfg_retry_limit
+		Get AP's retry limit value
+
+sys_cfg_sticky_tim_config
+-------------------------
+    "./uaputl.exe sys_cfg_sticky_tim_config [ENABLE] [<DURATION> <STICKY_BIT_MASK>]"
+
+    This command is used to set or get sticky TIM configuration.
+
+    ENABLE is used to enable or disable sticky TIM feature.
+    Following are the valid values of ENABLE
+    0- disable SticktyTIM
+    1- enable StickyTIM  (Both DURATION in beacons and STICKY_BIT_MASK must be provided)
+    2- enable StickyTIM  (enable sticky TIM without changing previous values of
+       DURATION and STICKY_BIT_MASK)
+
+    When bit 0 of STICKY_BIT_MASK is set, TIM bit is made sticky and when
+    cleared, normal TIM bit updates resume.
+    When bit 1 of STICKY_BIT_MASK is set, MoreData bit is made sticky and when
+    cleared, normal MoreData bit updates resume.
+    STICKY_BIT_MASK = 0 is NOT a valid configuration value.
+
+    If no argument is given, this command returns current sticky TIM configuration.
+
+    Example:
+    ./uaputl.exe sys_cfg_sticky_tim_config
+                Get sticky TIM configuration.
+
+    ./uaputl.exe sys_cfg_sticky_tim_config 0
+                Disable sticky TIM feature.
+
+    ./uaputl.exe sys_cfg_sticky_tim_config 1 30 1
+                Enable sticky TIM feature with DURATION of 30 beacons and
+                STICKY_BIT_MASK set to 1.
+
+sys_cfg_sticky_tim_sta_mac_addr
+-------------------------------
+    "./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr [CONTROL] [STA_MAC_ADDRESS]"
+
+    This command is used to set or get sticky TIM control parameter for associated station.
+
+    CONTROL when set to 1, sticky TIM bit for that station is activated.
+    When set to 0, sticky TIM bit for that station is deactivated.
+
+    If no argument is given, it returns sticky TIM configuration for all associated stations.
+    If only STA_MAC_ADDRESS is provided, it returns sticky TIM configartion for that station.
+
+    Example:
+    ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr
+            Get sticky TIM configuration for all associated stations.
+
+    ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr 00:50:43:20:11:22
+            Get control parameter for station 00:50:43:20:11:22.
+
+    ./uaputl.exe sys_cfg_sticky_tim_sta_mac_addr 1 00:50:43:20:11:22
+            Set control parameter for station with MAC address 00:50:43:20:11:22 to 1.
+
+    Note:TIM bit for an associated STA is made sticky only if both below mentioned
+         conditions are satisfied
+         1.Enable = 1 or 2 in most recently received sys_cfg_sticky_tim_config command, and
+         2.Control = 1 in most recently received sys_cfg_sticky_tim_sta_mac_addr
+           with this station MAC address.
+
+sys_cfg_2040_coex
+-------------------------------
+    "./uaputl.exe sys_cfg_2040_coex [ENABLE]"
+
+    This command is used to set or get 20/40 BSS coexistence configuration.
+
+    ENABLE when set to 0, disables 20/40 coex.
+    When set to 1, enables 20/40 coex.
+
+    If no argument is given, it returns 20/40 BSS coex configuration.
+
+    Example:
+    ./uaputl.exe sys_cfg_2040_coex
+            Get 20/40 BSS coexistence configuration.
+
+    ./uaputl.exe sys_cfg_2040_coex 0
+            Disable 20/40 BSS coexistence.
+
+    ./uaputl.exe sys_cfg_2040_coex 1
+            Enable 20/40 BSS coexistence.
+
+    Note:20/40 BSS coex configuration can be set only before starting BSS.
+
+sys_cfg_eapol_pwk_hsk
+---------------------
+    "./uaputl.exe sys_cfg_eapol_pwk_hsk [<TIMEOUT> <RETRIES>]"
+
+	This command is used to set or get pairwise handshake update timeout and
+	number of retries.
+
+	Both TIMEOUT and number of RETRIES should be provided for a 'set'.
+
+	If no arguments are given, this command returns timeout value and number
+	of
+	retries for pairwise key.
+
+	Example:
+	./uaputl.exe sys_cfg_eapol_pwk_hsk 50 2
+		Set AP's pairwise key timeout to 50ms and number of retries to 2.
+
+	./uaputl.exe sys_cfg_eapol_pwk_hsk
+		Get AP's pairwise key timeout and number of retries.
+
+sys_cfg_eapol_gwk_hsk
+---------------------
+	"./uaputl.exe sys_cfg_eapol_gwk_hsk [<TIMEOUT> <RETRIES>]"
+
+	This command is used to set or get groupwise handshake update timeout and
+	number of retries.
+
+	Both TIMEOUT and number of RETRIES should be provided for a	'set'.
+
+	If no arguments are given, this command returns timeout	value and number
+	of retries for groupwise key.
+
+	Example:
+	./uaputl.exe sys_cfg_eapol_gwk_hsk 50 2
+	Set AP's groupwise key timeout to 50ms and number of retries to 2.
+
+	./uaputl.exe sys_cfg_eapol_gwk_hsk
+	Get AP's groupwise key timeout and number of retries.
+
+sta_filter_table
+----------------
+    "./uaputl.exe sta_filter_table <FILTERMODE> [<MACADDRESS_LIST>]"
+
+    This command is used to get or set the client station MAC address
+    filter table.
+
+    The supported options are:
+    FILTERMODE : 0 - Disable filter table
+                 1 - Allow mac address specified in the allowed list
+                 2 - Block MAC addresses specified in the  banned list
+    MACADDRESS_LIST is the list of MAC addresses to be acted upon. Each
+    MAC address must be separated with a space. Maximum of 16 MAC addresses
+    are supported.
+
+    empty - Get current client station MAC address filter table.
+
+    Example:
+	./uaputl.exe sta_filter_table 0
+		Disable filter table
+
+	./uaputl.exe sta_filter_table 1 00:50:43:20:aa:bb
+		Set AP's filter mode to allow, only MAC address "00:50:43:ab:bb" will be allowed.
+
+	./uaputl.exe sta_filter_table
+		Get AP's filter table settings.
+
+regrdwr
+-------
+     "./uaputl.exe regrdwr <TYPE> <OFFSET> [value]"
+
+     These commands are used to read the MAC, BBP and RF registers from the card.
+     TYPE can take 3 values, 1 - read/write MAC register
+                             2 - read/write BBP register
+                             3 - read/write RF  register
+
+     OFFSET specifies the offset location that is to be read.
+     This parameter can be specified either in decimal or in hexadecimal (by preceding the number with a "0x").
+
+     value if specified, then that value will be written to that offset in the specified register. Value should be
+     specified in hexadecimal.
+
+     Example:
+	./uaputl.exe regrdwr 1 0xa123
+		read MAC register 0xa123
+
+	./uaputl.exe regrdwr 1 0xa123 0xaa
+		write 0xaa to MAC register 0xa123
+
+        ./uaputl.exe regrdwr 2 0x0123
+		read BBP register 0x0123
+
+	./uaputl.exe regrdwr 2 0x0123 0xaa
+		write 0xaa to BBP register 0x0123
+
+        ./uaputl.exe regrdwr 3 0x0123
+		read RF register 0x0123
+
+	./uaputl.exe regrdwr 3 0x0123 0xaa
+		write 0xaa to RF register 0x0123
+
+memaccess
+---------
+ 	"./uaputl.exe memaccess <ADDR> [value]"
+	This commands is used to read/write to a memory address
+
+	ADDR specifies the address of the location that is to be read/write
+	This parameter can be specified either in decimal or in hexadecimal (by preceding the number with a "0x").
+
+	value if specified, then that value will be written to that address in the specified register.
+
+	Example:
+		./uaputl.exe memaccess 0xc00153e4
+			read contents of memory location 0xc00153e4
+
+
+		./uaputl.exe memaccess 0xc00153e4 0xaabbccdd
+			write value 0xaabbccdd to  memory location 0xc00153e4
+
+rdeeprom
+--------
+    "./uaputl.exe rdeeprom <offset> <bytecount>"
+
+    This command is used to read bytes from offset location on
+    EEPROM
+
+    offset: 0,4,8,..., multiple of 4
+    bytecount: 4-20, multiple of 4
+
+   	Example:
+    ./uaputl.exe rdeeprom 200 12
+        read 12 bytes from offset 200 ON EEPROM
+
+cfg_data
+--------
+ 	"./uaputl.exe cfg_data <type> [*.conf]"
+
+    This command is used to set/get the configuration data to/from the firmware.
+
+    type: 2 -- cal data
+
+   	Example:
+        ./uaputl.exe cfg_data 2 cal_data.conf
+            read cal_data from cal_data.conf and download to firmware.
+        ./uaputl.exe cfg_data 2
+            read cal_data from firmware
+
+sys_cfg_80211d
+--------------
+    "./uaputl.exe sys_cfg_80211d [state STATE] [country COUNTRY]"
+    This command is used to set/get 802.11D specific parameters.
+    If no parameters are provided, this command returns state, country and
+    domain information.
+
+    Allowed values for state are 0 for disable and 1 for enable.
+    COUNTRY is a two letter string input (derived from ISO 3166 code;
+    http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
+    )
+
+    Countries are mapped with specific domain in file "80211d_domain.conf". In
+    order to set customize band setting, user can modify 80211d_domain.conf
+    file.
+
+    Example:
+    ./uaputl.exe sys_cfg_80211d state 0
+        To-disable
+
+    ./uaputl.exe sys_cfg_80211d state 1
+        To-enable
+
+    ./uaputl.exe sys_cfg_80211d country IN
+        for using country as INDIA
+
+    ./uaputl.exe sys_cfg_80211d state 1 country US
+        for enabling and setting country in single command.
+
+uap_stats
+---------
+    "./uaputl.exe uap_stats"
+    This command is used to get uAP statistics.
+
+    Example:
+    ./uaputl.exe uap_stats
+
+pscfg
+---------
+    "./uaputl.exe pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE]
+
+    This command is used to set or get the AP's power mode and power save params.
+
+    The supported options are:
+        MODE :     0 - disable power mode
+                   2 - enable inactivity based power save mode
+
+        PS PARAMS:
+            CTRL:  0 - disable protection frame Tx before PS
+                   1 - enable protection frame Tx before PS
+            INACTTO: Inactivity timeout in microseconds, default value is 200000 us
+            MIN_SLEEP: Minimum sleep duration in microseconds, default value 17000 us
+            MAX_SLEEP: Maximum sleep duration in microseconds, default value 17000 us
+			The value of MIN_SLEEP should be >= 5000 us.
+			The value of MAX_SLEEP should be <= beacon interval(when ctrl: 0).
+			The value of MAX_SLEEP should be <= 32000 us(when ctrl: 1).
+
+            MIN_AWAKE: Minimum awake duration in microseconds, default value is 2000 us
+            MAX_AWAKE: Maximum awake duration in microseconds, default value is 2000 us
+			The value of MIN_AWAKE should be >= 2000 us.
+            MIN_AWAKE,MAX_AWAKE only valid when MODE is set to inactivity based power save mode.
+
+
+	empty - Get current power mode and power save params.
+
+    Example:
+	./uaputl.exe pscfg 0
+		Disable AP's power mode.
+
+   	./uaputl.exe pscfg 2
+		Enable inactivity based power save mode.
+
+   	./uaputl.exe pscfg 2 1 400000 20000 20000 10000 10000
+		Enable inactivity based power save mode, enable protection, set inactivity timeout 400000 us
+        set minimum sleep duration to 20000 us, maximum sleep duration to 20000 us
+        and set minimum awake duration to 10000us, maximum awake duration to 10000 us
+
+	./uaputl.exe pscfg
+		Get current AP's power mode and power save params.
+
+hscfg
+-----
+    ./uaputl.exe hscfg [condition [[GPIO# [gap]]]]
+	This command is used to configure the host sleep parameters.
+
+	This command takes one (condition), two (condition and GPIO#) or three
+	(condition, GPIO# and gap) parameters for set. If no parameter provided,
+	get is performed.
+
+	where Condition is:
+		bit 0 = 1   -- broadcast data
+		bit 1 = 1   -- unicast data
+		bit 2 = 1   -- mac event
+		bit 3 = 1   -- multicast data
+		bit 6 = 1  --  Wakeup when mgmt frame received.
+
+	The host sleep mode will be cancelled if condition is set to 0xffff.
+	The default is 0x7.
+
+	where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid
+	GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO will be used instead).
+	The default is 0xff.
+
+	where Gap is the gap in milliseconds between wakeup signal and wakeup event or 0xff
+	for special setting (host acknowledge required) when GPIO is used to wakeup host.
+	The default is 200.
+
+	Examples:
+		./uaputl.exe hscfg              : Get current host sleep mode
+		./uaputl.exe hscfg 0xffff       : Cancel host sleep mode
+		./uaputl.exe hscfg 3            : Broadcast and unicast data
+		                                  Use GPIO and gap set previously
+		./uaputl.exe hscfg 2 3          : Unicast data
+		                                  Use GPIO 3 and gap set previously
+		./uaputl.exe hscfg 2 1 0xa0     : Unicast data
+		                                  Use GPIO 1 and gap 160 ms
+		./uaputl.exe hscfg 2 0xff       : Unicast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap set previously
+		./uaputl.exe hscfg 4 3 0xff     : MAC event
+		                                  Use GPIO 3
+		                                  Special host sleep mode
+		./uaputl.exe hscfg 1 0xff 0xff  : Broadcast data
+		                                  Use interface (e.g. SDIO)
+		                                  Use gap 255ms
+
+hssetpara
+---------
+    ./uaputl.exe hssetpara condition [[GPIO# [gap]]]
+    This command is used to configure the host sleep parameters.
+
+    Note:
+    1) The usages of parameters are the same as "hscfg" command.
+    2) The parameters will be saved in the driver and be used when host suspends.
+
+sta_deauth_ext
+--------------
+    "./uaputl.exe sta_deauth_ext <STA_MAC_ADDRESS><REASON_CODE>"
+
+    This command is used to de-authenticate a client station with specific reason code.
+
+    Example:
+        ./uaputl.exe sta_deauth_ext 00:50:43:20:34:58  4
+            deauth station 00:50:43:20:34:58 with IEEE reason code 4 (Disassociated due to inactivity)
+
+sys_cfg_custom_ie
+-----------------
+    "./uaputl.exe sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]"
+
+    This command is used to set or get custom IEs for management frames.
+
+    The supported options are:
+        INDEX:       0 - IE Index is 0
+                     1 - IE Index is 1
+                     2 - IE Index is 2
+                     MAX IE Index depends on device memory.
+
+               	    -1 - Append/Delete IE automatically
+                         Delete will delete the IE from the matching IE buffer
+                         Append will append the IE to the buffer with the same mask
+        MASK :       Management subtype mask value as per bit definitions
+	                   :  Bit 0 - Association request.
+	                   :  Bit 1 - Association response.
+	                   :  Bit 2 - Reassociation request.
+	                   :  Bit 3 - Reassociation response.
+	                   :  Bit 4 - Probe request.
+	                   :  Bit 5 - Probe response.
+	                   :  Bit 8 - Beacon.
+        MASK :       MASK = 0 to clear the mask and the IE buffer
+
+        IEBuffer:    IE buffer to set in hexadecimal bytes.
+	                  The Buffer should not be space separated.
+	                  ( Maximum length = 256 bytes )
+        empty - Get IE buffer, subtype mask settings for all the indices [0-3].
+        INDEX - Only INDEX will get the IE buffer configured for the particular
+                Index.
+
+    Example:
+	./uaputl.exe sys_cfg_custom_ie
+		Get IE buffer, subtype mask settings for all indices.
+
+	./uaputl.exe sys_cfg_custom_ie 1
+		Get IE buffer and subtype mask WEP key setting for the Index = 1.
+
+	./uaputl.exe sys_cfg_custom_ie 2 0
+		Clear IE buffer and mask value for Index = 2.
+
+	./uaputl.exe sys_cfg_custom_ie 3 0x101 0xdd051234567890
+		Set IE buffer and mask value for Index = 3.
+
+	./uaputl.exe sys_cfg_custom_ie -1 0x101 0xdd051234567890
+		Append the specified IEBuffer at index with mask value of 0x101
+
+	./uaputl.exe sys_cfg_custom_ie -1 0 0xdd051234567890
+		Delete the specified IEBuffer from all the IEs.
+
+	./uaputl.exe sys_cfg_custom_ie 2 0 0xdd051234567890
+		Delete the specified IEBuffer from the IEs at index 2.
+
+coex_config
+-----------
+    "./uaputl.exe coex_config [CONFIG_FILE]"
+    This command is used to set or get the BT coex configuration settings.
+
+    The supported options are:
+        CONFIG_FILE is file contain all the BT coex settings.
+        empty - Get current BT coex settings
+
+    Example:
+	./uaputl.exe coex_config
+		Get current BT coex settings.
+
+	./uaputl.exe coex_config uapcoex.conf
+		Load BT coex configuration settings from uapcoex.conf file and set.
+
+sys_cfg_wmm
+-----------
+    "./uaputl.exe sys_cfg_wmm [qosinfo=<qosinfo>]
+                              [0]
+                              [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+                              [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+                              [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+                              [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]"
+
+    This command can be used set/get beacon WMM parameters
+
+    The supported option are:
+        qosinfo: qos information. User can set only MSB. Valid values are 0x80 and 0x00.
+        Lower 4 bits are managed by FW. Hence, value read for qosinfo may have
+        lower 4 bits non-zero.
+
+        AC_BE: 0
+        AC_BK: 1
+        AC_VI: 2
+        AC_V0: 3
+        AIFSN: AIFSN value
+        ECW_MAX: ECW max
+        ECW_MIN: ECW min
+        TX_OP: TXOP Limit
+        empty - Get current WMM parameters
+        When all the parameter are 0, wmm will be disabled.
+
+        Example:
+        ./uaputl.exe sys_cfg_wmm 0 3 10 4 0
+           Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_wmm 1 7 10 4 0
+           Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_wmm 2 2 4 3 94
+           Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+
+        ./uaputl.exe sys_cfg_wmm 3 2 3 2 47
+           Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_wmm
+            Get current wmm parameters
+
+        ./uaputl.exe sys_cfg_wmm 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_wmm qosinfo=0x80 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Enable wmm PS mode.
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_wmm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        ./uaputl.exe sys_cfg_wmm 0
+            Disable wmm
+
+sys_cfg_ap_wmm
+-----------
+    "./uaputl.exe sys_cfg_ap wmm [0]
+                                 [AC_BE AIFSN ECW_MAX ECW_MIN TX_OP]
+                                 [AC_BK AIFSN ECW_MAX ECW_MIN TX_OP]
+                                 [AC_VI AIFSN ECW_MAX ECW_MIN TX_OP]
+                                 [AC_VO AIFSN ECW_MAX ECW_MIN TX_OP]"
+
+    This command can be used set/get AP WMM parameters
+
+    The supported option are:
+        AC_BE: 0
+        AC_BK: 1
+        AC_VI: 2
+        AC_V0: 3
+        AIFSN: AIFSN value
+        ECW_MAX: ECW max
+        ECW_MIN: ECW min
+        TX_OP: TXOP Limit
+        empty - Get current AP WMM parameters
+        When all the parameter are 0, AP wmm will be disabled.
+
+        Example:
+        ./uaputl.exe sys_cfg_ap_wmm 0 3 10 4 0
+           Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_ap_wmm 1 7 10 4 0
+           Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+
+        ./uaputl.exe sys_cfg_ap_wmm 2 2 4 3 94
+           Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+
+        ./uaputl.exe sys_cfg_ap_wmm 3 2 3 2 47
+           Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_ap_wmm
+            Get current AP wmm parameters
+
+        ./uaputl.exe sys_cfg_ap_wmm 0 3 10 4 0 1 7 10 4 0 2 2 4 3 94 3 2 3 2 47
+            Set AC_BE with AIFSN 3, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_BK with AIFSN 7, ECW_MAX 10, ECW_MIN 4 and TXOP 0
+            Set AC_VI with AIFSN 2, ECW_MAX 4, ECW_MIN 3 and TXOP 94
+            Set AC_VO with AIFSN 2, ECW_MAX 3, ECW_MIN 2 and TXOP 47
+
+        ./uaputl.exe sys_cfg_ap_wmm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+        ./uaputl.exe sys_cfg_ap_wmm 0
+            Disable AP wmm
+
+addbapara
+---------
+    "./uaputl.exe addbapara [timeout txwinsize rxwinsize txamsdu rxamsdu]"
+	This command can be used to update the default ADDBA parameters.
+
+	The supported options are:
+	    timeout - This is the block ack timeout for ADDBA request.
+		    0 : Disable (recommended for throughput test)
+		    1 - 65535 : Block Ack Timeout in TU
+	    txwinsize - Buffer size for ADDBA request. (32 is default value)
+	    rxwinsize - Buffer size for ADDBA response. (16 is default value)
+	    txamsdu - amsdu support for ADDBA request. (1 is default value)
+		    0 : Disable amsdu in ADDBA request.
+		    1 - Enable amsdu in ADDBA request.
+	    rxamsdu - amsdu support for ADDBA response. (1 is default value)
+		    0 : Disable amsdu in ADDBA response.
+		    1 - Enable amsdu in ADDBA response.
+        empty - Get current ADDBA parameters.
+
+	Current window size limit for Tx as well as Rx is 1023.
+
+	Example:
+	./uaputl.exe addbapara
+        Get the current addba params
+	./uaputl.exe addbaparam 1000 64 8 0 0
+        This will change the ADDBA timeout to (1000 * 1024) us,	txwinsize to 64 and rxwinsize to 8
+        and disable AMSDU in ADDBA request/response.
+
+	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 txamdsdu/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.
+
+sys_cfg_11n
+-----------
+    "./uaputl.exe sys_cfg_11n [ENABLE] [HTCAP] [AMPDU] [TXBFCAP] [HT_MCS_CAP]"
+    This command can be used set/get 802.11n parameters.
+
+    The supported option are:
+        ENABLE: 0 - disable 802.11n in uap
+                1 - enable 802.11n in uap
+		Note: If 802.11n is disabled, 802.11ac MUST be disabled at the same time
+        HTCAP: HT Capabilities info (default value is 0x111c)
+               Bit 15-13: Reserved set to 0
+               Bit 12: DSS/CCK mode in 40MHz enable/disable
+               Bit 11-10: Reserved set to 0
+               Bit 9-8: Reserved set to 0x01
+               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
+        AMPDU: A-MPDU Parameter (default value is 0x03)
+               Bit 7-5: Reserved set to 0
+               Bit 4-2: Minimum MPDU Start spacing
+                        Set to 0 for no restriction
+                        Set to 1 for 1/4 us
+                        Set to 2 for 1/2 us
+                        Set to 3 for 1 us
+                        Set to 4 for 2 us
+                        Set to 5 for 4 us
+                        Set to 6 for 8 us
+                        Set to 7 for 16 us
+               Bit 1-0: Max A-MPDU length
+        TXBFCAP: TX Beamforming capabilities
+               Bit 0    : Implicit TX BF receiving capable
+               Bit 1    : RX staggered sounding capable
+               Bit 2    : TX staggered sounding capable
+               Bit 3    : RX NDP capable
+               Bit 4    : TX NDP capable
+               Bit 5    : Implicit TX BF capable
+               Bit 6-7  : Calibration
+                       0: - not supported
+                       1: - STA can respond to a calibration request using
+                            the CSI Report, but cannot initiate calibration
+                       2: - reserved
+                       3: - STA can both initiate and respond to a calibration request
+               Bit 8    : Explicit CSI TX BF capable
+               Bit 9    : Explicit non-compressed steering capable
+               Bit 10   : Explicit compressed steering capable
+               Bit 11-12: Explicit TX BF CSI feedback
+                       0: - not supported
+                       1: - delayed feedback
+                       2: - immediate feedback
+                       3: - delayed and immediate feedback
+               Bit 13-14: Explicit non-compressed BF feedback capable
+                       0: - not supported
+                       1: - delayed feedback
+                       2: - immediate feedback
+                       3: - delayed and immediate feedback
+               Bit 15-16: Explicit compressed BF feedback capable
+                       0: - not supported
+                       1: - delayed feedback
+                       2: - immediate feedback
+                       3: - delayed and immediate feedback
+               Bit 17-18: Minimal grouping
+                       0: - no grouping (STA supports groups of 1)
+                       1: - groups of 1, 2
+                       2: - groups of 1, 4
+                       3: - groups of 1, 2, 4
+               Bit 19-20: CSI number of beamformer antennas supported
+                       0: - single TX antenna sounding
+                       1: - 2 TX antenna sounding
+                       2: - 3 TX antenna sounding
+                       3: - 4 TX antenna sounding
+               Bit 21-22: Non-compressed steering number of beamformer antennas supported
+                       0: - single TX antenna sounding
+                       1: - 2 TX antenna sounding
+                       2: - 3 TX antenna sounding
+                       3: - 4 TX antenna sounding
+               Bit 23-24: Compressed steering number of beamformer antennas supported
+                       0: - single TX antenna sounding
+                       1: - 2 TX antenna sounding
+                       2: - 3 TX antenna sounding
+                       3: - 4 TX antenna sounding
+               Bit 25-26: CSI max number of rows beamformer supported
+                       0: - single row of CSI
+                       1: - 2 rows of CSI
+                       2: - 3 rows of CSI
+                       3: - 4 rows of CSI
+               Bit 27-28: Channel estimation capability
+                       0: - 1 space time stream
+                       1: - 2 space time streams
+                       2: - 3 space time streams
+                       3: - 4 space time streams
+               Bit 29-31: Reserved
+        HT_MCS_MAP: MCS rate bitmap
+               Bit 0-7   : MCS_SET_0
+               Bit 15-8  : MCS_SET_1
+        empty - Get current 802.11n parameters.
+
+        Example:
+        ./uaputl.exe sys_cfg_11n 1 0x117e 3
+            enable 802.11n, and set HT Capabilities info to 0x117e, and A-MPDU Parameter to 0x03
+        ./uaputl.exe sys_cfg_11n 1 0x117e 3 0xFFFFFFFF
+            enable 802.11n, and set HT Capabilities info to 0x117e, A-MPDU
+            Parameter to 0x03 and TX Beamforming capabilities to 0xFFFFFFFF
+        ./uaputl.exe sys_cfg_11n 1 0x117e 3 0xFFFFFFFF 0x00100023
+            enable 802.11n, and set HT Capabilities info to 0x117e, A-MPDU
+            Parameter to 0x03, TX Beamforming capabilities to 0xFFFFFFFF and
+            MCS rate bitmap to 0x00100023.
+        ./uaputl.exe sys_cfg_11n 0
+            disable 802.11n in uap
+        ./uaputl.exe sys_cfg_11n
+            Get current 802.11n parameters
+
+aggrpriotbl
+-----------
+        "./uaputl.exe aggrpriotbl <m0> <n0> <m1> <n1> ... <m7> <n7>"
+        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)
+
+        The supported option are:
+            <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.
+
+        empty - Get current priority table for AMPDU/AMSDU traffic.
+
+        Example:
+        ./uaputl.exe 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
+
+	    ./uaputl.exe 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.
+
+	    ./uaputl.exe 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 issued in disconnected state.
+
+addbareject
+-----------
+        "./uaputl.exe addbareject <m0> <m1> ... <m7>"
+        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.
+
+        The supported option are:
+            <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.
+        empty - Get current addbareject table for all the TIDs.
+
+        Example:
+        ./uaputl.exe addbareject
+            This command will get the current table.
+	        [0 0 0 0 0 0 1 1]. ADDBA would be accepted for all TIDs except for TID [6,7].
+	        This is the default state.
+
+        ./uaputl.exe 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]
+
+	    ./uaputl.exe 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 issued in disconnected state.
+
+sys_cfg_tdls_ext_cap
+--------------------
+
+    "./uaputl.exe sys_cfg_tdls_ext_cap [CONFIG_FILE]"
+
+    This command is used to set/get TDLS extended capability settings.
+
+    If CONFIG_FILE is provided, a SET is performed , else a GET is performed.
+
+    Examples:
+        ./uaputl.exe sys_cfg_tdls_ext_cap config/tdls_ext_cap.conf
+        Set TDLS extended capability parameters in the config file.
+        ./uaputl.exe sys_cfg_tdls_ext_cap
+        Get TDLS extended capability parameters.
+
+    "./uaputl.exe skip_cac [<MODE>]"
+
+    This command is used to set/get SKIP_CAC feature. If enabled then next BSS
+    start would skip the channel availability check (CAC). The mode will be
+    disabled automatically once BSS_START is performed.
+
+    MODE : 0 - Disable skip CAC mode
+	   1 - Enable skip CAC mode
+
+    eg.,
+	./uaputl.exe skip_cac ==> GET current configured mode
+	./uaputl.exe skip_cac 1 ==> enables skip_cac mode
+	./uaputl.exe skip_cac 0 ==> disable skip_cac mode
+
+httxbfcfg
+---------
+	"./uaputl.exe httxbfcfg <ACTION> [ACT_DATA]"
+
+	This command is used to configure the TX beamforming options.
+
+	The supported options are:
+		ACTION: 0 - Control global parameters for beamforming
+                1 - Performs NDP Sounding for PEER
+		        2 - TX BF interval in milliseconds
+		        3 - Enable/Disable beamforming/sounding for the indicated peer.
+		        4 - TX BF SNR Threshold for peer
+		ACT_DATA: Specific data for the above actions
+                  For ACTION 0 - Beamforming enable/disable, sounding enable/disable,
+                                 FB type, snr_threshold, sounding interval, Beamformig mode
+		          For ACTION 1 - PEER MAC and status
+		          For ACTION 2 - TX BF interval
+		          For ACTION 3 - PEER MAC
+		          For ACTION 4 - PEER MAC and SNR
+		          empty - Get action specific settings
+
+	Examples:
+		./uaputl.exe httxbfcfg 0                          : Get current global configuration parameter
+		./uaputl.exe httxbfcfg 2 00:50:43:20:BF:64        : Get the TX BF periodicity for a given peer
+		./uaputl.exe httxbfcfg 3                          : Get the list of MAC addresses that have
+		                                                      beamforming and/or sounding enabled
+		./uaputl.exe httxbfcfg 4                          : Get the list of PEER MAC, SNR tuples
+		                                                      programmed into the firmware.
+		./uaputl.exe httxbfcfg 0 0 0 3 10 500 5           : Disable beamforming, sounding, set FB type
+		                                                      to 3, snr threshold to 10, sounding interval
+		                                                      to 500 ms and beamforming mode to 5
+		./uaputl.exe httxbfcfg 1 00:50:43:20:BF:64        : Perform NDP Trigger sounding to peer
+		                                                      00:50:43:20:BF:64
+		./uaputl.exe httxbfcfg 2 00:50:43:20:BF:64 500    : Set TX BF periodicity for peer 00:50:43:20:BF:64
+		                                                      to 500 milliseconds
+		./uaputl.exe httxbfcfg 3 00:50:43:20:BF:43 1 0 3  : Enable beamforming, disable sounding and set
+		                                                      FB type to 3 for peer 00:50:43:20:BF:43
+		./uaputl.exe httxbfcfg 4 00:50:43:20:BF:24 43     : Set TX BF SNR threshold to peer
+
+
+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-10: Reserved set to 0
+        Bit 9-8: Rx STBC set to 0x01
+        BIT9 BIT8  Description
+        0    0     No spatial streams
+        0    1     One spatial streams supported
+        1    0     Reserved
+        1    1     Reserved
+		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:
+		./uaputl.exe -i uapX httxcfg
+		This will display HT Tx configuration for 2.4G and 5G band.
+
+		./uaputl.exe -i uapX httxcfg 0x62
+		This will enable 20/40 and Short GI but will disable Green field for 2.4G and 5G band.
+
+		./uaputl.exe -i uapX 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.
+
+htstreamcfg
+	This command is used to set/get HT stream configuration.
+	The setting only takes effect in next association.
+
+	Usage:
+		./uaputl.exe -i uapX htstreamcfg [n]
+
+	where <n>
+		0x11: HT stream 1x1 mode
+		0x22: HT stream 2x2 mode
+
+	Examples:
+		./uaputl.exe -i uapX htstreamcfg        : Get current setting
+		./uaputl.exe -i uapX htstreamcfg 0x11   : Set HT stream 1x1 mode
+		./uaputl.exe -i uapX htstreamcfg 0x22   : Set HT stream 2x2 mode
+
+deepsleep
+---------
+    "./uaputl.exe deepsleep [MODE] [IDLE_TIME]"
+    This command is used to set/get auto deep sleep mode.
+
+    The supported option are:
+        [MODE]: Enable/disable auto deep sleep mode (1/0)
+        [IDLE_TIME]: Idle time in milliseconds after which firmware will put the device
+                    in deep sleep mode. Default value is 100 ms.
+        empty - Get current deep sleep mode.
+
+    Example:
+    ./uaputl.exe deepsleep          : Display auto deep sleep mode
+    ./uaputl.exe deepsleep 1        : Enable auto deep sleep mode, idle time unchanged
+    ./uaputl.exe deepsleep 0        : Disable auto deep sleep mode
+    ./uaputl.exe deepsleep 1 500    : Enable auto deep sleep mode with idle time 500 ms
+
+    Note:
+            Deepsleep must be disabled before changing idle time.
+
+sdcmd52rw
+	This command is used to read/write a controller register in
+	Secure Digital I/O Interfaces.
+
+	Usage:
+    "./uaputl.exe sdcmd52rw <function number> <register address> [value]"
+
+	For SDIO MMC driver, only function 0 and 1 access is allowed. And there
+	is a limitation for function 0 write, only vendor specific CCCR registers
+	(0xf0 -0xff) are permiited.
+
+	Examples:
+    ./uaputl.exe sdcmd52rw 1 3          : Issue cmd52 to read function 1, register 3.
+    ./uaputl.exe sdcmd52rw 1 1 0x3f     : Issue cmd52 to write function 1, register 1
+                                          with value 0x3f.
+
+txpwrlimit_cfg_get
+txpwrlimit_2g_cfg_set
+txpwrlimit_5g_cfg_set
+------------------
+    This command is used to set/get the configuration data of Tx power limitation.
+    Note: The configuration set should be issued when no STA is connected.
+
+    Examples:
+        ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_cfg_get
+        ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_2g_cfg_set
+        ./uaputl.exe hostcmd config/txpwrlimit_cfg.conf txpwrlimit_5g_cfg_set
+
+rxpktcoal_cfg
+-------------
+   "./uaputl.exe rxpktcoal_cfg [PKT-THRESHOLD] [TIMEOUT]"
+
+	This is used to get/set RX packet coalescing paramters
+
+    The supported option are:
+        [PKT-THRESHOLD]: count after which packets would be sent to host. Valid values 1-7
+        [TIMEOUT]: timeout in ms after which packets would be sent to host. Valid values 1-4
+        Coalescing is disabled if both or either of packet_thershold and delay is zero
+
+        RX packet coalescing parameters can be changed only when device is in
+        idle state i.e. all interfaces are disconnected.
+
+    Example:
+    ./uaputl.exe rxpktcoal_cfg      : Display RX packet coalescing settings
+    ./uaputl.exe rxpktcoal_cfg 5 1  : Enable RX packet coalescing: packet count 5, delay 1.
+    ./uaputl.exe rxpktcoal_cfg 0 0  : Disable RX packet coalescing.
+
+tx_data_pause
+-------------
+  "./uaputl.exe tx_data_pause [ENABLE][TX_BUF_CNT]"
+
+    This command is used to set/get tx data pause settings.
+
+    The supported option are:
+        [ENABLE]: Enable/disable pause tx events from firmware to host.
+        [TX_BUF_CNT]: Max number of TX buffers allowed for all PS clients
+        empty - Get current tx data pause settings
+
+    Example:
+    ./uaputl.exe tx_data_pause      : Display tx data pause settings
+    ./uaputl.exe tx_data_pause 1    : Enable pause tx event, max tx buffer number unchanged.
+    ./uaputl.exe tx_data_pause 0    : Disable pasue tx event, max tx buffer number unchanged.
+    ./uaputl.exe tx_data_pause 1 15 : Enable pause tx event, with max tx buffer number 15.
+
+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
+		3: configuration of VHT capabilities (uAP only)
+	Note: For the UAP, only 3 is supported for txrx.
+
+	where [l] is <bwcfg>
+	<bwcfg> - This parameter specifies the bandwidth (BW) configuration
+		  applied to the vhtcfg.
+	If <txrx> is 3 (For uAP),
+		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.
+
+	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.
+
+	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:
+		./uaputl.exe -i uapX vhtcfg 2 3            : Get current VHT configuration in 5GHz for the uAP.
+		./uaputl.exe -i uapX 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.
+		./uaputl.exe -i uapX 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.
+
+dfstesting
+----------
+  "./uaputl.exe dfstesting [<user_cac_pd> <user_nop_pd> <no_chan_change> <fixed_chan_num>]"
+
+    This command is used to set/get DFS testing settings.
+
+    The supported option are:
+        <user_cac_pd>: user-configured Channel Availability Check in msec
+                       0 = disable, use default period (60000)
+                       1-65535 = enable with that period
+        <user_nop_pd>: user-configured Non-Occupancy Period in sec
+                       0 = disable, use default period (1800)
+                       1-65535 = enable with that period
+        <no_chan_change>: enable/disable no channel change on radar
+                          0 = disable, 1 = enable (overrides below)
+        <fixed_chan_num>: user-configured channel to change to on radar
+                          0 = disable, 1-255 = enable with that channel
+                          (channel validity for region, etc. is not checked)
+                          (only takes effect if no_chan_change = 0)
+
+    Example:
+    ./uaputl.exe dfstesting             : Get current dfstesting settings
+    ./uaputl.exe dfstesting 2000 0 0 0  : user_cac=2sec, others disabled/default
+    ./uaputl.exe dfstesting 0 0 1 0     : only no_chan_change enabled
+    ./uaputl.exe dfstesting 0 120 0 64  : user_nop=2min, force chan 64 on radar
+
+cscount
+---------------
+
+  "./uaputl.exe cscount [<channel_switch_count>]"
+
+    This command is used to configure the number of beacons AP sends with channel switch IE, before channel change due to
+    radar detection. If not configured, <channel_switch_count> is set to 5 by default.
+
+    The supported options are:
+        <channel_switch_count>: user configured channel switch count
+                                5-20 = configure with that value
+
+   Example:
+   ./uaputl.exe cscount         : Get user configured channel switch count value
+   ./uaputl.exe cscount 10      : Set channel switch count to 10
+
+
+mgmtframectrl
+-------------
+  "./uaputl.exe mgmtframectrl [MASK]"
+
+    This command is used to set/get management frame control mask.
+
+    where the parameter [MASK] is the bit mask of management frame reception.
+        Following are the bit definitions.
+        Bit 0 : Association Request
+        Bit 1 : Association Response
+        Bit 2 : Re-Association Request
+        Bit 3 : Re-Association Response
+        Bit 4 : Probe Request
+        Bit 5 : Probe Response
+        Bit 8 : Beacon Frames
+
+    Example:
+    ./uaputl.exe mgmtframectrl 0x101
+    Set management frame control mask to 0x101.
+
+restrict_client_mode
+--------------------
+	"./uaputl.exe restrict_client_mode [<ENABLE> [MODE_CONFIG]]"
+
+	This command is used to set/get the mode in which the ex-Stations can connect to the uAP.
+	If no arguments are given, this command returns the current configuration.
+	By default this feature will be disabled.
+	[ENABLE]:
+		1: Enable the feature.
+		0: Disable the feature.
+	[MODE_CONFIG]: config mode.
+		Bit 0:	B only Mode.
+		Bit 1:	A only Mode.
+		Bit 2:	G only Mode.
+		Bit 3:	N only Mode.
+		Bit 4:	AC only Mode.
+
+	Example:
+	./uaputl.exe restrict_client_mode 1 0x8.
+	Only N mode clients will be able to connect. Association will fail for other clients.
+
+	./uaputl.exe restrict_client_mode 0.
+	This feature is disabled.
+
+	Note:
+	The set operation should be performed before bss is started.
+	User should make sure that the mode advertized by uAP in beacons
+	(i.e. combination of supported/extended rates IE and capability IEs)
+	is superset of the mode allowed for ex-STA associations using this TLV.
+
+uap_oper_ctrl
+-------------
+	"./uaputl.exe uap_oper_ctrl [control] [chanopt] [bandcfg] [channel]"
+
+	This command is used to set/get uAP operation control when in-STA disconnected with ext-AP.
+	If no arguments are given, this command returns the current configuration.
+
+	The supported options are:
+		<control> : 0  default, do nothing
+				   2  uAP stops and restart automatically
+		<chanopt> Specify which channel should be used when uap restarts automatically
+				   1: uap restarts on default 2.4G/channel 6
+				   2: uap restart on band/channel configured by driver previously
+				   3: uap restart on band/channel configured by parameter bandcfg/channel
+		<bandcfg> This parameter specifies the bandwidth when chanopt is 3
+				   0: 20Mhz
+				   2: 40Mhz
+				   3: 80Mhz
+		<channel> This parameter specifies the channel will be used when chanopt is 3
+
+		Example:
+		./uaputl.exe uap_oper_ctrl  2 1
+		uap stops and restart automatically when in-STA disconnects with ext-AP,
+		and restart on default 2.4G/channel 6.
+
+		./uaputl.exe uap_oper_ctrl  2 2
+		uap stops and restart automatically when in-STA disconnects with ext-AP,
+		and restart on band/channel configured by driver previously.
+
+		./uaputl.exe uap_oper_ctrl  2 3 2 36
+		uap stops and restart automatically when in-STA disconnects with ext-AP,
+		and restart on channel 36, bandwidth 40.
+
+		./uaputl.exe uap_oper_ctrl  0
+		when in-STA disconnects with ext-AP, uap will stay on current operation channel.
+
+		./uaputl.exe uap_oper_ctrl
+		Get current uap operation control setting.
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANEVENT
+
+NAME
+mlanevent.exe
+
+This tool can be used to listen for and obtain events from the uAP driver
+through the netlink layer.
+
+----------------
+Supported events
+----------------
+STA_DEAUTH
+STA_ASSOC
+BSS_START
+BSS_IDLE
+BSS_ACTIVE
+
+-----------------
+Details of events
+-----------------
+
+STA_DEAUTH
+----------
+    For this event, the following information is shown:
+        + Deauthenticated STA MAC address.
+        + Reason for deauthentication.
+
+STA_ASSOC
+---------
+    For this event, the following information is shown:
+        + STA MAC address.
+
+BSS_START
+---------
+    For this event, the following information is shown:
+        + AP MAC address.
+
+BSS_IDLE
+--------
+    For this event, there is no associated information.
+
+BSS_ACTIVE
+----------
+    For this event, there is no associated information.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  IWPRIV
+
+NAME
+	This manual describes the usage of private commands used in Marvell MLAN
+	Linux UAP Driver.
+
+	To use parameters as hex format, a '0x' must precede it for the parameters to
+	be parsed properly.
+
+SYNOPSIS
+	iwpriv <uapX> <command> [sub-command] ...
+
+	iwpriv uapX version
+	iwpriv uapX verext
+	iwpriv uapX start
+	iwpriv uapX stop
+	iwpriv uapX bssstart
+	iwpriv uapX bssstop
+	iwpriv uapX fwreload <path>
+	iwpriv uapX apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,[SEC,][KEY,]
+	                   [CHANNEL,][PREAMBLE,][MAX_SCB,][END]"
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell MLAN
+	card via the Linux device driver.
+
+	The uapX parameter specifies the network device that is to be used to
+	perform this command on. It could be uap0, uap1 etc.
+
+version
+	This is used to get the current version of the driver and the firmware.
+
+verext
+	Retrieve and display an extended version string from the firmware
+
+	Usage:
+		iwpriv uapX verext [#]
+
+	where [#] is an optional argument to retrieve a specific version string,
+	omission of the argument retrieves the 0 indexed string.
+
+start
+	Start the uAP driver.
+
+	Usage:
+		iwpriv uapX start
+
+stop
+	Stop the uAP driver.
+
+	Usage:
+		iwpriv uapX stop
+
+bssstart
+	Start the AP mode, so that uAP will start transmitting beacon.
+
+	Usage:
+		iwpriv uapX bssstart
+
+bssstop
+	Stop the AP mode and disconnect all stations. uAP will stop
+	transmitting beacon as well.
+
+	Usage:
+		iwpriv uapX bssstop
+
+fwreload
+	Reload the firmware. Here string "FW_PATH=" in the path
+	argument is mandatory part.
+
+	Usage:
+		iwpriv uapX fwreload <path>
+
+apcfg
+	This command is used to set the AP configurations. Here string
+	"ASCII_CMD=AP_CFG" is minimum requirement in the ASCII string.
+	Note: BSS will be stopped then restarted if BSS is already started
+	when the command is received.
+
+	Usage:
+		iwpriv uapX apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,[SEC=sec,]
+			[KEY=key,][CHANNEL=channel,][MAX_SCB=max_scb,][END]"
+
+	Where the parameters are:
+		SSID:       Set SSID to be used in beacon and probe response
+		[SEC]:      Security modes - open, wep128, wpa-psk or wpa2-psk
+		            11n will be auto disabled in wep128 and wpa-psk mode
+		[KEY]:      Encrypted key for wep128, wpa-psk or wpa2-psk, minimum 8 chars
+		[CHANNEL]:  Channel to be selected
+		[MAX_SCB]:  Maximum STA number
+		[END]:      Optional termination in ASCII string
+
+	Examples:
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP"
+                                        : Set AP SSID to "TEST_uAP"
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,SEC=open"
+                                        : Set AP SSID to "TEST_uAP" and
+                                          security mode is disabled
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,SEC=WPA2-PSK,KEY=ecbe5facdbfe234a"
+                                        : Set AP SSID to "TEST_uAP" and security mode
+                                          to WPA2-SPK and encrypted key ecbe5facdbfe234a
+		iwpriv uap0 apcfg "ASCII_CMD=AP_CFG,SSID=TEST_uAP,CHANNEL=8"
+                                        : Set AP SSID to "TEST_uAP" and
+                                          set the AP channel to 8
+
+===============================================================================
diff --git a/wlan_sd8997/README_WIFIDIRECT b/wlan_sd8997/README_WIFIDIRECT
new file mode 100644
index 0000000..b56602a
--- /dev/null
+++ b/wlan_sd8997/README_WIFIDIRECT
@@ -0,0 +1,448 @@
+
+===============================================================================
+
+        S E T U P  I N S T R U C T I O N S F O R  *WifiDirect*
+
+Driver,FW release:
+
+1. Make sure, bg_scan.conf,uaputl.conf has SSID starting with "DIRECT-"
+2. Download uAP configuration and BG scan configuration.
+3. This version of wifidirectutl breaks the backward compatibility and will work
+with following releases -
+    8797 >= 14.xx.16.p15
+         >= 14.xx.11.p138
+    8766 >= 14.xx.11.p138
+    8787 >= 14.xx.9.p89
+
+    However, In case one needs to run the utility in backward compatibility mode
+    he can do so by running following command before running the utility -
+
+    # export WIFIDIR_USE_FIXED_IE_INDICES=1
+
+    To disable backward comaptibility mode run following command -
+
+    # export WIFIDIR_USE_FIXED_IE_INDICES=0
+
+WPSWIFIDIRECT release:
+
+1. Modify the wifidirect.conf file to specify the correct HW addresses of
+   devices. The DUT mac address and peer mac address needs to be correctly
+   entered.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  WIFIDIRECTUTL
+
+NAME
+	wifidirectutl
+
+This tool can be used to configure WifiDirect parameters.
+
+------------------
+Supported Commands
+------------------
+wifidirect_mode [MODE]
+wifidirect_config [*.conf]
+wifidirect_params_config [*.conf]
+wifidirect_action_frame <*.conf> | [<PeerAddr> <Category> <OuiSubtype> <DialogToken>]
+wifidirect_discovery_request <*.conf>
+wifidirect_discovery_response <*.conf>
+
+wifidirect_cfg_discovery_period [<MinDiscPeriod> <MaxDiscPeriod>]
+wifidirect_cfg_intent [IntentValue]
+wifidirect_cfg_capability [<DeviceCapability> <GroupCapability>]
+wifidirect_cfg_noa <enable|disable> <index> [<counttype> <duration> <interval>]
+wifidirect_cfg_opp_ps <enable|disable> [<CTWindow>]
+wifidirect_cfg_invitation_list [mac_addr]
+wifidirect_cfg_listen_channel [ListenChannel]
+wifidirect_cfg_op_channel [OperatingChannel]
+wifidirect_cfg_persistent_group_record [index] [role]
+           [<groupbss> <deviceId> <ssid> <psk>] [peermac1] [peermac2]
+wifidirect_cfg_persistent_group_invoke [index] | <cancel>
+wifidirect_cfg_presence_req_params [<type> <duration> <interval>]
+wifidirect_cfg_ext_listen_time [<duration> <interval>]
+wifidirect_cfg_provisioning_params [<action> <configMethods> <devicePassword>]
+wifidirect_cfg_wps_params [<action>]
+
+wifidirect_mode [mode]
+----------
+    "./wifidirectutl <iface> wifidirect_mode [mode]"
+
+    This command is used to setup various modes for wifidirect device.
+    The mode 2 can be used only when wifidirect is started using mode 1.
+    The mode 3 should not be used for uAP.
+
+    The supported options are:
+        mode :     0 - stop wifidirect mode
+                   1 - start wifidirect mode
+                   2 - start wifidirect group owner mode
+                   3 - start wifidirect client mode
+                   4 - start wifidirect find phase
+                   5 - stop wifidirect find phase
+        empty - Get current wifidirect mode
+
+    Example:
+        ./wifidirectutl <iface> wifidirect_mode 0
+                Stop wifidirect mode.
+
+        ./wifidirectutl <iface> wifidirect_mode 1
+                Start wifidirect mode.
+
+        ./wifidirectutl <iface> wifidirect_mode
+                Get current WIFIDIRECT start/stop mode.
+
+wifidirect_config
+----------
+    "./wifidirectutl <iface> wifidirect_config [*.conf]"
+
+    This command is used to set/get the wifidirect configuration.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_config wifidirect.conf
+            Read configuration from wifidirect.conf and apply it.
+        ./wifidirectutl <iface> wifidirect_config
+            Read existing wifidirect configuration and display it.
+
+wifidirect_params_config
+----------
+    "./wifidirectutl <iface> wifidirect_params_config [*.conf]"
+
+    This command is used to set/get the wifidirect parameters configuration.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_params_config wifidirect.conf
+            Read parameter configuration from wifidirect.conf and apply it.
+        ./wifidirectutl <iface> wifidirect_params_config
+            Read existing wifidirect parameters's configuration and display it.
+
+wifidirect_action_frame
+----------
+    "./wifidirectutl <iface> wifidirect_action_frame <*.conf> | <PeerAddr> <Category> <OUISubtype> <DialogToken>"
+
+    This command is used to send action frames as specified in config file or on command line.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_action_frame wifidirect.conf
+            Read action_frame from wifidirect.conf and send to peer.
+        ./wifidirectutl <iface> wifidirect_action_frame <PeerAddr> <Category> <OUISubtype> <DialogToken>
+            Read action frame parameters from command line and send to peer.
+
+wifidirect_discovery_request
+----------
+    "./wifidirectutl <iface> wifidirect_discovery_request <*.conf>"
+
+    This command is used to send wifidirect discovery request packet.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_discovery_request wifidirect.conf
+            Read discovery packet from wifidirect.conf and send to peer.
+
+wifidirect_discovery_response
+----------
+    "./wifidirectutl <iface> wifidirect_discovery_response <*.conf>"
+
+    This command is used to send wifidirect discovery response packet.
+
+        Example:
+        ./wifidirectutl <iface> wifidirect_discovery_response wifidirect.conf
+            Read discovery packet from wifidirect.conf and send to peer.
+
+wifidirect_cfg_discovery_period
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_discovery_period [<MinDiscPeriod> <MaxDiscPeriod>]"
+
+	This command is used to set or get minimum and maximum discovery period.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_discovery_period 10 20
+		Set minimum discovery interval to 10 and maximum discovery
+		interval to	20.
+
+		./wifidirectutl <iface> wifidirect_cfg_discovery_period
+		Get minimum and maximum discovery interval.
+
+wifidirect_cfg_intent
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_intent [IntentValue]"
+
+	This command is used to set or get intent value.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_intent 12
+		Set intent value to 12.
+
+		./wifidirectutl <iface> wifidirect_cfg_intent
+		Get Group Owner Intent.
+
+wifidirect_cfg_capability
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_capability [<DeviceCapability> <GroupCapability>]"
+
+	This command is used to set or get device capability and group capability.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_capability 10 20
+		Set Device capability to 10 and group capability to 20
+
+		./wifidirectutl <iface> wifidirect_cfg_capability
+		Get Device capability and group capability.
+
+wifidirect_cfg_noa
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_noa <enable|disable> <index> [<counttype> <duration> <interval>]"
+
+	This command is used to set or get NoA parameters like count_type, duration and
+	interval in ms when NoA is enabled. Valid value of index is [0, 1].
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_noa enable 0 10 50 100
+		Enable NoA and set count to 10, duration to 50ms and interval to 100 ms
+            for index 0.
+
+		./wifidirectutl <iface> wifidirect_cfg_noa disable 1
+		Disable NoA at index 1.
+
+		./wifidirectutl <iface> wifidirect_cfg_noa
+		Get NoA settings.
+
+wifidirect_cfg_opp_ps
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_opp_ps <enable|disable> [<CTWindow>]"
+
+	This command is used to set or get Opportunistic power save and CT window.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_opp_ps enable 50
+		Set OppPS and CTwindow value to 50.
+
+		./wifidirectutl <iface> wifidirect_cfg_opp_ps disable
+		Disable OppPS.
+
+		./wifidirectutl <iface> wifidirect_cfg_opp_ps
+		Get OppPS and CT window.
+
+wifidirect_cfg_invitation_list
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_invitation_list [mac_addr]"
+
+	This command is used to set or get invitation list of peers.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_invitation_list 00:50:43:20:23:34
+		Set 00:50:43:20:23:34 in invitation list of peers.
+
+		./wifidirectutl <iface> wifidirect_cfg_invitation_list
+		Get Invitation list of peers.
+
+wifidirect_cfg_listen_channel
+----------
+	"./wifidirectutl <iface> wifidirect_cfg_listen_channel [ListenChannel]"
+
+	This command is used to set or get Listen channel.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_listen_channel 11
+		Set Listen channel to 11.
+
+		./wifidirectutl <iface> wifidirect_cfg_listen_channel
+		Get Listen channel.
+
+wifidirect_cfg_op_channel
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_op_channel [OperatingChannel]"
+
+		This command is used to set or get Operating channel.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_op_channel 11
+		Set Operating channel to 11.
+
+		./wifidirectutl <iface> wifidirect_cfg_op_channel
+		Get Operating channel.
+
+wifidirect_cfg_persistent_group_record
+----------
+		"./wifidirectutl <iface> [index] [role]
+                 [<groupbss> <deviceId> <ssid> <psk>] [peermac1] [peermac2]"
+
+		This command is used to set or get the persistent group record
+        maintained in the device. Valid index is from 0 to 3. The role should be
+        0 for client, 1 for group-owner.
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record 0 1
+        00:50:43:12:24:36 00:50:43:13:26:39 "DIRECT-" "1234567890"
+        00:50:43:20:c2:d0
+		Set persistent group record with index 0, role as group owner, bssId and
+        device Id, ssid="DIRECT-", passphrase="1234567890", and peer mac address.
+        The passphrase get converted to PSK.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record 1 1
+        00:50:43:12:24:36 00:50:43:13:26:39 "DIRECT-" "1234567890"
+        0x1234567890123456789012345678901234567890123456789012345678901234
+		Set persistent group record with index 1, role as group owner, bssId and
+        device Id, ssid="DIRECT-", passphrase="1234567890", and peer mac address.
+        The passphrase get converted to PSK.
+        PSK is specified with "0x" prefix and 32 bytes (64 characters).
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record 1
+		Get persistent group record with index 1.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_record
+		Get persistent group record for all indices.
+
+wifidirect_cfg_persistent_group_invoke
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_persistent_group_invoke [index] | <cancel>"
+
+		This command is used to invoke a particular persistent group record
+        from the list. Valid index is from 0 to 3.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_invoke 2
+		Invoke persistent group record with index 1.
+
+		./wifidirectutl <iface> wifidirect_cfg_persistent_group_invoke cancel
+		Cancel invokation of persistent groups.
+
+wifidirect_cfg_presence_req_params
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_presence_req_params [<type> <duration> <interval>]"
+
+		This command is used to set/get presence request parameters. Type should
+        be 1 for preferred values and 2 for acceptable values.
+
+		./wifidirectutl <iface> wifidirect_cfg_presence_req_params 1 50 100
+		Set duration to 50ms and interval to 100ms.
+
+		./wifidirectutl <iface> wifidirect_cfg_presence_req_params
+		Get presence request parameters.
+
+wifidirect_cfg_ext_listen_time
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_ext_listen_time [<duration> <interval>]"
+
+		This command is used to set/get extended listen timing parameters.
+
+		./wifidirectutl <iface> wifidirect_cfg_ext_listen_time 1200 1300
+		Set availability period to 1200ms and availability interval to 1300 ms.
+
+		./wifidirectutl <iface> wifidirect_cfg_ext_listen_time
+		Get extended listen timing parameters.
+
+wifidirect_cfg_provisioning_params
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_provisioning_params [<action> <configMethod> <devicePassword>]"
+
+		This command is used to set/get provisioning protocol parameters. Action should
+        be 1 for request parameters and 2 for response parameters.
+
+		./wifidirectutl <iface> wifidirect_cfg_provisioning_params 1 0x80 0x04
+		Set config method to 0x86 and device password to 0x04.
+
+		./wifidirectutl <iface> wifidirect_cfg_provisioning_params
+		Get Provision protocol parameters.
+
+wifidirect_cfg_wps_params
+----------
+		"./wifidirectutl <iface> wifidirect_cfg_wps_params [<action>]"
+
+		This command is used to set WPS action. action can be "pin" (pin entered),
+        "pbc"(button pressed) or "none".
+
+		Example:
+		./wifidirectutl <iface> wifidirect_cfg_wps_params pin
+		Indicates pin operation
+
+		./wifidirectutl <iface> wifidirect_cfg_wps_params none
+		Indicates no operation
+
+===============================================================================
+        U S E R  M A N U A L  F O R  WIFIDISPLAY
+
+wifidisplay_mode
+-----------
+            "./wifidirectutl <iface> wifidisplay_mode [<action>]"
+            This command is used to enable or disable wifi-display. The possible values are either 1 or 0.
+		Example:
+		./wifidirectutl <iface> wifidisplay_mode 1
+		Indicates enable wifi_display
+
+		./wifidirectutl <iface> wifidisplay_mode 0
+		Indicates disable wifi_display
+
+wifidisplay_config
+-----------
+            "./wifidirectutl <iface> wifidisplay_config [*.conf]"
+
+            This command is used to set/get the wifidisplay configuration.
+
+             Example:
+             ./wifidirectutl <iface> wifidisplay_config wifidisplay.conf
+             Read configuration from wifidisplay.conf and apply it.
+             ./wifidirectutl <iface> wifidisplay_config
+             Read existing wifidisplay configuration and display it.
+
+wifidisplay_update_devinfo
+----------
+            "./wifidirectutl <iface> wifidisplay_update_devinfo [value]"
+
+            This command is used to set the device information of wifidisplay device information subelement.
+            This command will overwrite the new device information with user defined value.
+
+             Example:
+             ./wifidirectutl <iface> wifidisplay_update_devinfo 10
+             Update device information programmed with new value 10 by overwritting existing value.
+
+wifidisplay_discovery_request
+----------
+            "./wifidirectutl <iface> wifidisplay_discovery_request [*.config]"
+
+            This command is used to send wifi display service discovery request.
+
+            Example:
+            ./wifidirectutl <iface> wifidisplay_discovery_request wifidisplay.conf
+            Read discovery packet from wifidisplay.conf and send to peer.
+
+wifidisplay_discovery_response
+----------
+           "./wifidirectutl <iface> wifidisplay_discovery_response <*.conf>"
+
+           This command is used to send wifidisplay discovery response packet.
+
+           Example:
+           ./wifidirectutl <iface> wifidisplay_discovery_response wifidisplay.conf
+           Read discovery packet from wifidisplay.conf and send to peer.
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANEVENT
+
+NAME
+mlanevent.exe
+
+This tool can be used to listen for and obtain events from the driver
+through the netlink layer. This is only used for display/debugging purpose.
+
+----------------
+Supported events
+----------------
+WIFIDIRECT_GENERIC_EVENT
+WIFIDIRECT_SERVICE_DISCOVERY
+
+-----------------
+Details of events
+-----------------
+
+WIFIDIRECT_GENERIC_EVENT
+-----------------
+    For this event, the following information is shown:
+        + Event length.
+        + Event Type indicating Negociation, Invitation, Discoverability,
+		Provision discovery related Request or Response.
+        + Event SubType indicating Client or Group owner role.
+        + Peer MAC address.
+        + Associated WIFIDIRECT IE elements.
+
+WIFIDIRECT_SERVICE_DISCOVERY
+---------------------
+    For this event, the following information is shown:
+        + Peer MAC address.
+        + Service discovery packet details.
diff --git a/wlan_sd8997/gpl-2.0.txt b/wlan_sd8997/gpl-2.0.txt
new file mode 100644
index 0000000..2c62266
--- /dev/null
+++ b/wlan_sd8997/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_sd8997/mlan/mlan.h b/wlan_sd8997/mlan/mlan.h
new file mode 100644
index 0000000..ac63d72
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan.h
@@ -0,0 +1,41 @@
+/** @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.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+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_sd8997/mlan/mlan_11ac.c b/wlan_sd8997/mlan/mlan_11ac.c
new file mode 100644
index 0000000..a72fb6d
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11ac.c
@@ -0,0 +1,1391 @@
+/** @file mlan_11ac.c
+ *
+ *  @brief This file defines the private and adapter data
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *  (C) Copyright 2011-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+
+#define NO_NSS_SUPPORT 0x3
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+t_u16 wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u8 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(IN mlan_private *pmpriv,
+			 IN t_u8 band, IN t_u32 pri_chan, IN 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;
+			}
+		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;
+			}
+		case 100:
+		case 104:
+		case 108:
+		case 112:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 106;
+				break;
+			}
+		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;
+			}
+		case 132:
+		case 136:
+		case 140:
+		case 144:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 138;
+				break;
+			}
+		case 149:
+		case 153:
+		case 157:
+		case 161:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 155;
+				break;
+			}
+		case 165:
+		case 169:
+		case 173:
+		case 177:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 171;
+				break;
+			}
+		case 184:
+		case 188:
+		case 192:
+		case 196:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 190;
+				break;
+			}
+
+		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 number of nss which supports VHT mcs
+ *
+ *  @param mcs_map_set  VHT mcs map
+ *
+ *  @return             Number of supported nss
+ */
+static t_u8
+wlan_get_nss_num_vht_mcs(t_u16 mcs_map_set)
+{
+	t_u8 nss, nss_num = 0;
+	for (nss = 1; nss <= 8; nss++) {
+		if (GET_VHTNSSMCS(mcs_map_set, nss) != NO_NSS_SUPPORT)
+			nss_num++;
+	}
+	PRINTM(MCMND, "Supported nss:%d\n", nss_num);
+	return nss_num;
+}
+
+/**
+ *  @brief This function fills the cap info
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_fill_cap_info(mlan_private *priv, VHT_capa_t *vht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11ac_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_bg;
+
+	vht_cap->vht_cap_info = usr_dot_11ac_dev_cap;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Set/get 11ac configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_11ac_ioctl_vhtcfg(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_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;
+
+	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) {
+			/* 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 ((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 ((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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+				  IN 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(pmadapter, cfg->param.supported_mcs_set, mcs_set, NUM_MCS_SUPP);
+
+#endif
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function prints the 802.11ac device capability
+ *
+ *  @param pmadapter     A pointer to mlan_adapter structure
+ *  @param cap           Capability value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_dot11acdevcap(pmlan_adapter pmadapter, t_u32 cap)
+{
+	ENTER();
+
+	switch (GET_VHTCAP_MAXMPDULEN(cap)) {
+	case 0x0:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MSDU length = 3895 octets\n");
+		break;
+	case 0x1:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MSDU length = 7991 octets\n");
+		break;
+	case 0x2:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MSDU length = 11454 octets\n");
+		break;
+	default:
+		PRINTM(MINFO, "Unsupport value\n");
+		break;
+	}
+
+	PRINTM(MINFO, "GET_HW_SPEC: HTC-VHT %s\n",
+	       (ISSUPP_11ACVHTHTCVHT(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: VHT TXOP PS %s\n",
+	       (ISSUPP_11ACVHTTXOPPS(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: MU RX beamformee %s\n",
+	       (ISSUPP_11ACMURXBEAMFORMEE(cap) ? "supported" :
+		"not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: MU TX beamformee %s\n",
+	       (ISSUPP_11ACMUTXBEAMFORMEE(cap) ? "supported" :
+		"not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: SU RX Beamformee %s\n",
+	       (ISSUPP_11ACSUBEAMFORMEE(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: SU TX Beamformer %s\n",
+	       (ISSUPP_11ACSUBEAMFORMER(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n",
+	       (ISSUPP_11ACRXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n",
+	       (ISSUPP_11ACTXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 160MHz BW\n",
+	       (ISSUPP_11ACSGI160(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 80MHz BW\n",
+	       (ISSUPP_11ACSGI80(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: LDPC coding %s\n",
+	       (ISSUPP_11ACLDPC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160/80+80 MHz %s\n",
+	       (ISSUPP_11ACBW8080(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160 MHz %s\n",
+	       (ISSUPP_11ACBW160(cap) ? "supported" : "not supported"));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function prints the 802.11ac device MCS
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param support   Support value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_dot11acmcssupport(pmlan_adapter pmadapter, t_u32 support)
+{
+	ENTER();
+
+	PRINTM(MINFO, "GET_HW_SPEC: MCSs for %2dx%2d MIMO\n",
+	       GET_DEVRXMCSMAP(support), GET_DEVTXMCSMAP(support));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function converts the 2-bit MCS map to the highest long GI
+ *  VHT PPDU data rate
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param bands        Supported bands
+ *  @param mcs_map      2-bit MCS map
+ *
+ *  @return             the max data rate for long GI
+ */
+t_u16
+wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u8 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
+ *  @return             N/A
+ */
+void
+wlan_fill_vht_cap_tlv(mlan_private *priv,
+		      MrvlIETypes_VHTCap_t *pvht_cap, t_u8 bands, t_u8 flag)
+{
+	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;
+
+	ENTER();
+
+	/* Fill VHT cap info */
+	wlan_fill_cap_info(priv, &pvht_cap->vht_cap, bands);
+	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);
+	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));
+	}
+	/* 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 ((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_u8 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 append the 802_11AC 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;
+	MrvlIETypes_VHTOprat_t *pvht_op;
+	t_u8 supp_chwd_set;
+	t_u32 usr_vht_cap_info;
+	int ret_len = 0;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (pbss_desc->bss_band & BAND_A)
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_bg;
+
+	/* 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(pmadapter,
+		       (t_u8 *)pvht_cap + sizeof(MrvlIEtypesHeader_t),
+		       (t_u8 *)pbss_desc->pvht_cap + sizeof(IEEEtypes_Header_t),
+		       pvht_cap->header.len);
+
+		wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pbss_desc->bss_band,
+				      MTRUE);
+
+		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;
+	}
+
+	/* VHT Operation IE */
+	if (pbss_desc->pvht_oprat) {
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+			pvht_op = (MrvlIETypes_VHTOprat_t *)*ppbuffer;
+			memset(pmadapter, pvht_op, 0,
+			       sizeof(MrvlIETypes_VHTOprat_t));
+			pvht_op->header.type = wlan_cpu_to_le16(VHT_OPERATION);
+			pvht_op->header.len = sizeof(MrvlIETypes_VHTOprat_t) -
+				sizeof(MrvlIEtypesHeader_t);
+			memcpy(pmadapter,
+			       (t_u8 *)pvht_op + sizeof(MrvlIEtypesHeader_t),
+			       (t_u8 *)pbss_desc->pvht_oprat +
+			       sizeof(IEEEtypes_Header_t), pvht_op->header.len);
+
+			/* negotiate the channel width and central freq */
+			/* and keep the central freq as the peer suggests */
+			supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
+			if (supp_chwd_set == VHT_CAP_CHWD_80MHZ)
+				pvht_op->chan_width = MIN(VHT_OPER_CHWD_80MHZ,
+							  pbss_desc->
+							  pvht_oprat->
+							  chan_width);
+			else if (supp_chwd_set == VHT_CAP_CHWD_160MHZ)
+				pvht_op->chan_width = MIN(VHT_OPER_CHWD_160MHZ,
+							  pbss_desc->
+							  pvht_oprat->
+							  chan_width);
+			else if (supp_chwd_set == VHT_CAP_CHWD_80_80MHZ)
+				pvht_op->chan_width =
+					MIN(VHT_OPER_CHWD_80_80MHZ,
+					    pbss_desc->pvht_oprat->chan_width);
+			else
+				pvht_op->chan_width = VHT_OPER_CHWD_20_40MHZ;
+	    /** current region don't allow bandwidth 80 */
+			if (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_80MHZ)
+				pvht_op->chan_width = VHT_OPER_CHWD_20_40MHZ;
+			HEXDUMP("VHT_OPERATION IE", (t_u8 *)pvht_op,
+				sizeof(MrvlIETypes_VHTOprat_t));
+			*ppbuffer += sizeof(MrvlIETypes_VHTOprat_t);
+			ret_len += sizeof(MrvlIETypes_VHTOprat_t);
+			pvht_op->header.len =
+				wlan_cpu_to_le16(pvht_op->header.len);
+		}
+	}
+	/* 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);
+
+		mcs_map_user =
+			GET_DEVRXMCSMAP(pmpriv->usr_dot_11ac_mcs_support);
+		nss = wlan_get_nss_num_vht_mcs(mcs_map_user);
+		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(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *cmd,
+		  IN t_u16 cmd_action, IN 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;
+	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(pmadapter, &vhtcfg->vht_supp_mcs_set[0],
+	       &vht_cfg->vht_rx_mcs, sizeof(t_u32));
+	vht_cfg->vht_tx_mcs = wlan_cpu_to_le32(vht_cfg->vht_tx_mcs);
+	memcpy(pmadapter, &vhtcfg->vht_supp_mcs_set[4],
+	       &vht_cfg->vht_tx_mcs, sizeof(t_u32));
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of 11ac 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_11ac_cfg(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *resp, IN 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(pmadapter, &cfg->param.vht_cfg.vht_rx_mcs,
+		       &vhtcfg->vht_supp_mcs_set[0], sizeof(t_u32));
+		cfg->param.vht_cfg.vht_rx_mcs =
+			wlan_le32_to_cpu(cfg->param.vht_cfg.vht_rx_mcs);
+		memcpy(pmadapter, &cfg->param.vht_cfg.vht_tx_mcs,
+		       &vhtcfg->vht_supp_mcs_set[4], 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_u8 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_sd8997/mlan/mlan_11ac.h b/wlan_sd8997/mlan/mlan_11ac.h
new file mode 100644
index 0000000..f34c118
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11ac.h
@@ -0,0 +1,63 @@
+/** @file mlan_11ac.h
+ *
+ *  @brief This file defines the private and adapter data
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *  (C) Copyright 2011-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+#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_u8 bands,
+				     t_u16 mcs_map);
+void wlan_fill_vht_cap_tlv(mlan_private *priv, MrvlIETypes_VHTCap_t *pvht_cap,
+			   t_u8 bands, t_u8 flag);
+void wlan_fill_vht_cap_ie(mlan_private *priv, IEEEtypes_VHTCap_t *pvht_cap,
+			  t_u8 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_u8 bss_band);
+
+mlan_status wlan_cmd_11ac_cfg(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_11ac_cfg(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN mlan_ioctl_req *pioctl_buf);
+
+#endif /* _MLAN_11AC_H_ */
diff --git a/wlan_sd8997/mlan/mlan_11d.c b/wlan_sd8997/mlan/mlan_11d.c
new file mode 100644
index 0000000..051cc7e
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11d.c
@@ -0,0 +1,1610 @@
+/** @file mlan_11d.c
+ *
+ *  @brief This file contains functions for 802.11D.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+/********************************************************
+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 */
+};
+
+/** Universal region code */
+#define UNIVERSAL_REGION_CODE   0xff
+#endif
+
+/** Default Tx power */
+#define TX_PWR_DEFAULT  10
+
+/* Following two structures define the supported channels */
+/** Channels for 802.11b/g */
+static chan_freq_power_t channel_freq_power_UN_BG[] = {
+	{1, 2412, TX_PWR_DEFAULT},
+	{2, 2417, TX_PWR_DEFAULT},
+	{3, 2422, TX_PWR_DEFAULT},
+	{4, 2427, TX_PWR_DEFAULT},
+	{5, 2432, TX_PWR_DEFAULT},
+	{6, 2437, TX_PWR_DEFAULT},
+	{7, 2442, TX_PWR_DEFAULT},
+	{8, 2447, TX_PWR_DEFAULT},
+	{9, 2452, TX_PWR_DEFAULT},
+	{10, 2457, TX_PWR_DEFAULT},
+	{11, 2462, TX_PWR_DEFAULT},
+	{12, 2467, TX_PWR_DEFAULT},
+	{13, 2472, TX_PWR_DEFAULT},
+	{14, 2484, TX_PWR_DEFAULT}
+};
+
+/** Channels for 802.11a/j */
+static chan_freq_power_t channel_freq_power_UN_AJ[] = {
+	{8, 5040, TX_PWR_DEFAULT},
+	{12, 5060, TX_PWR_DEFAULT},
+	{16, 5080, TX_PWR_DEFAULT},
+	{34, 5170, TX_PWR_DEFAULT},
+	{38, 5190, TX_PWR_DEFAULT},
+	{42, 5210, TX_PWR_DEFAULT},
+	{46, 5230, TX_PWR_DEFAULT},
+	{36, 5180, TX_PWR_DEFAULT},
+	{40, 5200, TX_PWR_DEFAULT},
+	{44, 5220, TX_PWR_DEFAULT},
+	{48, 5240, TX_PWR_DEFAULT},
+	{52, 5260, TX_PWR_DEFAULT},
+	{56, 5280, TX_PWR_DEFAULT},
+	{60, 5300, TX_PWR_DEFAULT},
+	{64, 5320, TX_PWR_DEFAULT},
+	{100, 5500, TX_PWR_DEFAULT},
+	{104, 5520, TX_PWR_DEFAULT},
+	{108, 5540, TX_PWR_DEFAULT},
+	{112, 5560, TX_PWR_DEFAULT},
+	{116, 5580, TX_PWR_DEFAULT},
+	{120, 5600, TX_PWR_DEFAULT},
+	{124, 5620, TX_PWR_DEFAULT},
+	{128, 5640, TX_PWR_DEFAULT},
+	{132, 5660, TX_PWR_DEFAULT},
+	{136, 5680, TX_PWR_DEFAULT},
+	{140, 5700, TX_PWR_DEFAULT},
+	{149, 5745, TX_PWR_DEFAULT},
+	{153, 5765, TX_PWR_DEFAULT},
+	{157, 5785, TX_PWR_DEFAULT},
+	{161, 5805, TX_PWR_DEFAULT},
+	{165, 5825, TX_PWR_DEFAULT},
+/*  {240, 4920, TX_PWR_DEFAULT},
+    {244, 4940, TX_PWR_DEFAULT},
+    {248, 4960, TX_PWR_DEFAULT},
+    {252, 4980, TX_PWR_DEFAULT},
+channels for 11J JP 10M channel gap */
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function converts integer code to region string
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param code         Region code
+ *
+ *  @return             Region string
+ */
+static t_u8 *
+wlan_11d_code_2_region(pmlan_adapter pmadapter, t_u8 code)
+{
+	t_u8 i;
+
+	ENTER();
+
+	/* Look for code in mapping table */
+	for (i = 0; i < NELEMENTS(region_code_mapping); i++) {
+		if (region_code_mapping[i].code == code) {
+			LEAVE();
+			return region_code_mapping[i].region;
+		}
+	}
+
+	LEAVE();
+	/* Default is US */
+	return region_code_mapping[0].region;
+}
+
+/**
+ *  @brief This function Checks if channel txpwr is learned from AP/IBSS
+ *
+ *  @param pmadapter            A pointer to mlan_adapter structure
+ *  @param band                 Band number
+ *  @param chan                 Channel number
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     MTRUE or MFALSE
+ */
+static t_u8
+wlan_11d_channel_known(pmlan_adapter pmadapter,
+		       t_u8 band,
+		       t_u8 chan, parsed_region_chan_11d_t *parsed_region_chan)
+{
+	chan_power_11d_t *pchan_pwr = parsed_region_chan->chan_pwr;
+	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+	t_u8 i = 0;
+	t_u8 ret = MFALSE;
+	mlan_private *pmpriv;
+
+	ENTER();
+
+	HEXDUMP("11D: parsed_region_chan", (t_u8 *)pchan_pwr,
+		sizeof(chan_power_11d_t) * no_of_chan);
+
+	/* Search channel */
+	for (i = 0; i < no_of_chan; i++) {
+		if (chan == pchan_pwr[i].chan && band == pchan_pwr[i].band) {
+			PRINTM(MINFO, "11D: Found channel:%d (band:%d)\n", chan,
+			       band);
+			ret = MTRUE;
+
+			if (band & BAND_A) {
+				/* If chan is a DFS channel, we need to see an AP on it */
+				pmpriv = wlan_get_priv(pmadapter,
+						       MLAN_BSS_ROLE_STA);
+				if (pmpriv &&
+				    wlan_11h_radar_detect_required(pmpriv,
+								   chan)) {
+					PRINTM(MINFO,
+					       "11H: DFS channel %d, and ap_seen=%d\n",
+					       chan, pchan_pwr[i].ap_seen);
+					ret = pchan_pwr[i].ap_seen;
+				}
+			}
+
+			LEAVE();
+			return ret;
+		}
+	}
+
+	PRINTM(MINFO, "11D: Could not find channel:%d (band:%d)\n", chan, band);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function generates parsed_region_chan from Domain Info
+ *           learned from AP/IBSS
+ *
+ *  @param pmadapter            Pointer to mlan_adapter structure
+ *  @param region_chan          Pointer to region_chan_t
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     N/A
+ */
+static t_void
+wlan_11d_generate_parsed_region_chan(pmlan_adapter pmadapter,
+				     region_chan_t *region_chan,
+				     parsed_region_chan_11d_t
+				     *parsed_region_chan)
+{
+	chan_freq_power_t *cfp;
+	t_u8 i;
+
+	ENTER();
+
+	/* Region channel must be provided */
+	if (!region_chan) {
+		PRINTM(MWARN, "11D: region_chan is MNULL\n");
+		LEAVE();
+		return;
+	}
+
+	/* Get channel-frequency-power trio */
+	cfp = region_chan->pcfp;
+	if (!cfp) {
+		PRINTM(MWARN, "11D: cfp equal MNULL\n");
+		LEAVE();
+		return;
+	}
+
+	/* Set channel, band and power */
+	for (i = 0; i < region_chan->num_cfp; i++, cfp++) {
+		parsed_region_chan->chan_pwr[i].chan = (t_u8)cfp->channel;
+		parsed_region_chan->chan_pwr[i].band = region_chan->band;
+		parsed_region_chan->chan_pwr[i].pwr = (t_u8)cfp->max_tx_power;
+		PRINTM(MINFO, "11D: Chan[%d] Band[%d] Pwr[%d]\n",
+		       parsed_region_chan->chan_pwr[i].chan,
+		       parsed_region_chan->chan_pwr[i].band,
+		       parsed_region_chan->chan_pwr[i].pwr);
+	}
+	parsed_region_chan->no_of_chan = region_chan->num_cfp;
+
+	PRINTM(MINFO, "11D: no_of_chan[%d]\n", parsed_region_chan->no_of_chan);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function generates domain_info from parsed_region_chan
+ *
+ *  @param pmadapter            Pointer to mlan_adapter structure
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11d_generate_domain_info(pmlan_adapter pmadapter,
+			      parsed_region_chan_11d_t *parsed_region_chan)
+{
+	t_u8 no_of_sub_band = 0;
+	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+	t_u8 no_of_parsed_chan = 0;
+	t_u8 first_chan = 0, next_chan = 0, max_pwr = 0;
+	t_u8 i, flag = MFALSE;
+	wlan_802_11d_domain_reg_t *domain_info = &pmadapter->domain_reg;
+
+	ENTER();
+
+	/* Should be only place that clear domain_reg (besides init) */
+	memset(pmadapter, domain_info, 0, sizeof(wlan_802_11d_domain_reg_t));
+
+	/* Set country code */
+	memcpy(pmadapter, domain_info->country_code,
+	       wlan_11d_code_2_region(pmadapter, (t_u8)pmadapter->region_code),
+	       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(pmadapter, parsed_region_chan,
+		       &region_chan, 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(pmadapter, pdomain->country_code, country_code,
+	       COUNTRY_CODE_LEN);
+	pdomain->band = band;
+	pdomain->no_of_sub_band = num_sub_band;
+	memcpy(pmadapter, pdomain->sub_band, sub_band_list,
+	       MIN(MRVDRV_MAX_SUBBAND_802_11D,
+		   num_sub_band) * 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) ? 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;
+
+	ENTER();
+
+	PRINTM(MINFO, "11D: number of sub-band=0x%x\n", no_of_sub_band);
+
+	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(pmadapter, domain->country_code,
+	       pmadapter->domain_reg.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(pmadapter, domain->sub_band,
+		       pmadapter->domain_reg.sub_band,
+		       MIN(MRVDRV_MAX_SUBBAND_802_11D,
+			   no_of_sub_band) * 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(pmadapter, &region_chan,
+		       &pmadapter->parsed_region_chan,
+		       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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			 IN 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;
+	}
+	cfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+	domain_info = &cfg_11d->param.domain_info;
+	memcpy(pmadapter, pmadapter->country_code, domain_info->country_code,
+	       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_bg && cfp_a && (cfp_bg == cfp_a))
+		pmadapter->region_code = cfp_a;
+	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_bg && cfp_a && (cfp_bg == cfp_a))
+			pmadapter->region_code = cfp_a;
+		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(pmadapter, pmadapter->country_code, pdomain_tlv->country_code,
+	       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_sd8997/mlan/mlan_11h.c b/wlan_sd8997/mlan/mlan_11h.c
new file mode 100644
index 0000000..2de0d26
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11h.c
@@ -0,0 +1,4101 @@
+/** @file mlan_11h.c
+ *
+ *  @brief This file contains functions for 802.11H.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/*************************************************************
+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 = 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 Marvell
+ *         proprietary format
+ *
+ *  @param pmadapter Pointer to mlan_adapter
+ *  @param pout_buf Output parameter: Buffer to output Marvell formatted IE
+ *  @param pin_ie   Pointer to IEEE IE to be converted to Marvell 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 Marvell 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(pmadapter, ptmp_buf, &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(pmadapter, ptmp_buf, pin_ie + 2, 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(adapter, pdfs->dfs_owner, priv->curr_addr,
+	       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;
+		}
+	}
+
+	/*
+	 * 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(priv->adapter, &pcmd_ptr->params.tpc_req, pinfo_buf,
+	       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(priv->adapter, &pcmd_ptr->params.chan_sw_ann, pch_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)
+{
+	const 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;
+
+	/*
+	 * 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;
+
+	ENTER();
+	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(priv->adapter, &pcmd_ptr->params.chan_rpt_req, pchan_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);
+	}
+
+	/* 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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, &sup_chan_ie, 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(adapter, dfs_elem.dfs_owner,
+		       p11h_bss_info->ibss_dfs.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, OUT 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(IN 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 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(IN mlan_adapter *pmadapter,
+				  OUT mlan_ioctl_req **ppioctl_req,
+				  IN t_bool is_adding_ie)
+{
+	mlan_ioctl_req *pioctl_req = MNULL;
+	mlan_ds_misc_cfg *pds_misc_cfg = MNULL;
+	custom_ie *pcust_chansw_ie = MNULL;
+	IEEEtypes_ChanSwitchAnn_t *pchansw_ie = MNULL;
+	mlan_status ret;
+	IEEEtypes_Header_t *pChanSwWrap_ie = MNULL;
+	IEEEtypes_WideBWChanSwitch_t *pbwchansw_ie = MNULL;
+	IEEEtypes_VhtTpcEnvelope_t *pvhttpcEnv_ie = MNULL;
+	t_u8 index;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	if (pmadapter == MNULL || ppioctl_req == MNULL) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* allocate buffer for mlan_ioctl_req and mlan_ds_misc_cfg */
+	/* FYI - will be freed as part of cmd_response handler */
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(mlan_ioctl_req) +
+					       sizeof(mlan_ds_misc_cfg),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pioctl_req);
+	if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+		PRINTM(MERROR, "%s(): Could not allocate ioctl req\n",
+		       __func__);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pds_misc_cfg = (mlan_ds_misc_cfg *)((t_u8 *)pioctl_req +
+					    sizeof(mlan_ioctl_req));
+
+	/* prepare mlan_ioctl_req */
+	memset(pmadapter, pioctl_req, 0x00, sizeof(mlan_ioctl_req));
+	pioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	pioctl_req->action = MLAN_ACT_SET;
+	pioctl_req->pbuf = (t_u8 *)pds_misc_cfg;
+	pioctl_req->buf_len = sizeof(mlan_ds_misc_cfg);
+
+	/* prepare mlan_ds_misc_cfg */
+	memset(pmadapter, pds_misc_cfg, 0x00, sizeof(mlan_ds_misc_cfg));
+	pds_misc_cfg->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	pds_misc_cfg->param.cust_ie.type = TLV_TYPE_MGMT_IE;
+	pds_misc_cfg->param.cust_ie.len = (sizeof(custom_ie) - MAX_IE_SIZE);
+
+	/* configure custom_ie api settings */
+	pcust_chansw_ie =
+		(custom_ie *)&pds_misc_cfg->param.cust_ie.ie_data_list[0];
+	pcust_chansw_ie->ie_index = 0xffff;	/* Auto index */
+	pcust_chansw_ie->ie_length = sizeof(IEEEtypes_ChanSwitchAnn_t);
+	pcust_chansw_ie->mgmt_subtype_mask = (is_adding_ie)
+		? MBIT(8) | MBIT(5)	/* add IE for BEACON | PROBE_RSP */
+		: 0;		/* remove IE */
+
+	/* prepare CHAN_SW IE inside ioctl */
+	pchansw_ie = (IEEEtypes_ChanSwitchAnn_t *)pcust_chansw_ie->ie_buffer;
+	pchansw_ie->element_id = CHANNEL_SWITCH_ANN;
+	pchansw_ie->len =
+		sizeof(IEEEtypes_ChanSwitchAnn_t) - sizeof(IEEEtypes_Header_t);
+	pchansw_ie->chan_switch_mode = 1;	/* STA should not transmit */
+	pchansw_ie->new_channel_num = pmadapter->state_rdh.new_channel;
+
+	pchansw_ie->chan_switch_count = pmadapter->dfs_cs_count;
+	PRINTM(MCMD_D, "New Channel = %d Channel switch count = %d\n",
+	       pmadapter->state_rdh.new_channel, pchansw_ie->chan_switch_count);
+
+	for (index = 0; index < pmadapter->state_rdh.priv_list_count; index++) {
+		pmpriv = pmadapter->state_rdh.priv_list[index];
+		/*find the first AP interface */
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+			if (pmpriv->is_11ac_enabled) {
+
+				pChanSwWrap_ie =
+					(IEEEtypes_Header_t *)((t_u8 *)
+							       pchansw_ie +
+							       sizeof
+							       (IEEEtypes_ChanSwitchAnn_t));
+				pChanSwWrap_ie->element_id = EXT_POWER_CONSTR;
+				/*will have multiple sub IEs */
+				pChanSwWrap_ie->len = 0;
+
+				/* prepare the Wide Bandwidth Channel Switch IE
+				 * Channel Switch IE */
+				pbwchansw_ie =
+					(IEEEtypes_WideBWChanSwitch_t
+					 *)((t_u8 *)pChanSwWrap_ie +
+					    sizeof(IEEEtypes_Header_t));
+				pbwchansw_ie->ieee_hdr.element_id =
+					BW_CHANNEL_SWITCH;
+				pbwchansw_ie->ieee_hdr.len =
+					sizeof(IEEEtypes_WideBWChanSwitch_t) -
+					sizeof(IEEEtypes_Header_t);
+				/*fix 80MHZ now */
+				pbwchansw_ie->new_channel_width =
+					VHT_OPER_CHWD_80MHZ;
+				pbwchansw_ie->new_channel_center_freq0 =
+					wlan_11h_get_channel_freq_idx
+					(pmadapter->state_rdh.new_channel);
+				pbwchansw_ie->new_channel_center_freq1 =
+					wlan_11h_get_channel_freq_idx
+					(pmadapter->state_rdh.new_channel);
+				pChanSwWrap_ie->len +=
+					sizeof(IEEEtypes_WideBWChanSwitch_t);
+
+				/*prepare the VHT Transmit Power Envelope IE */
+				pvhttpcEnv_ie =
+					(IEEEtypes_VhtTpcEnvelope_t *)((t_u8 *)
+								       pChanSwWrap_ie
+								       +
+								       sizeof
+								       (IEEEtypes_Header_t)
+								       +
+								       sizeof
+								       (IEEEtypes_WideBWChanSwitch_t));
+				pvhttpcEnv_ie->ieee_hdr.element_id =
+					VHT_TX_POWER_ENV;
+				pvhttpcEnv_ie->ieee_hdr.len =
+					sizeof(IEEEtypes_VhtTpcEnvelope_t) -
+					sizeof(IEEEtypes_Header_t);
+				/* Local Max TX Power Count= 3,
+				 * Local TX Power Unit Inter=EIP(0) */
+				pvhttpcEnv_ie->tpc_info = 3;
+				pvhttpcEnv_ie->local_max_tp_20mhz = 0xff;
+				pvhttpcEnv_ie->local_max_tp_40mhz = 0xff;
+				pvhttpcEnv_ie->local_max_tp_80mhz = 0xff;
+				pChanSwWrap_ie->len +=
+					sizeof(IEEEtypes_VhtTpcEnvelope_t);
+
+				pcust_chansw_ie->ie_length +=
+					sizeof(IEEEtypes_WideBWChanSwitch_t)
+					+ sizeof(IEEEtypes_VhtTpcEnvelope_t)
+					+ sizeof(IEEEtypes_Header_t);
+
+				PRINTM(MINFO,
+				       "Append Wide Bandwidth Channel Switch IE\n");
+				break;
+			}
+		}
+	}
+
+	pds_misc_cfg->param.cust_ie.len += pcust_chansw_ie->ie_length;
+	DBG_HEXDUMP(MCMD_D, "11h: custom_ie containing CHAN_SW IE",
+		    (t_u8 *)pcust_chansw_ie, pds_misc_cfg->param.cust_ie.len);
+
+	/* assign output pointer before returning */
+	*ppioctl_req = pioctl_req;
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef UAP_SUPPORT
+/** Bits 2,3 of band config define the band width */
+#define UAP_BAND_WIDTH_MASK 0x0C
+
+/**
+ *  @brief Check if start channel 165 is allowed to operate in
+ *  previous uAP channel's band config
+ *
+ *  @param start_chn     Random Start channel choosen after radar detection
+ *  @param uap_band_cfg  Private driver uAP band configuration information structure
+ *
+ *  @return MFALSE if the channel is not allowed in given band
+ */
+static t_bool
+wlan_11h_is_band_valid(t_u8 start_chn, Band_Config_t uap_band_cfg)
+{
+
+	/* if band width is not 20MHZ (either 40 or 80MHz)
+	 * return MFALSE, 165 is not allowed in bands other than 20MHZ
+	 */
+	if (start_chn == 165 && (uap_band_cfg.chanWidth != CHAN_BW_20MHZ)) {
+		return MFALSE;
+	}
+	return MTRUE;
+}
+
+/**
+ *  @brief Retrieve a randomly selected starting channel if needed for 11h
+ *
+ *  If 11h is enabled and 5GHz band is selected in band_config
+ *    return a random channel in A band, else one from BG band.
+ *
+ *  @param priv          Private driver information structure
+ *  @param uap_band_cfg  Private driver information structure
+ *
+ *  @return      Starting channel
+ */
+static t_u8
+wlan_11h_get_uap_start_channel(mlan_private *priv, Band_Config_t uap_band_cfg)
+{
+	t_u8 start_chn;
+	mlan_adapter *adapter = priv->adapter;
+	t_u32 region;
+	t_u32 rand_entry;
+	region_chan_t *chn_tbl;
+	t_u8 rand_tries = 0;
+
+	/*TODO:  right now mostly a copy of wlan_11h_get_adhoc_start_channel.
+	 *       Improve to be more specfic to UAP, e.g.
+	 *       1. take into account COUNTRY_CODE -> region_code
+	 *       2. check domain_info for value channels
+	 */
+	ENTER();
+
+	/*
+	 * Set start_chn to the Default.
+	 * Used if 11h is disabled or the band
+	 * does not require 11h support.
+	 */
+	start_chn = DEFAULT_AD_HOC_CHANNEL;
+
+	/*
+	 * Check that we are looking for a channel in the A Band
+	 */
+	if (uap_band_cfg.chanBand == BAND_5GHZ) {
+		/*
+		 * Set default to the A Band default.
+		 * Used if random selection fails
+		 * or if 11h is not enabled
+		 */
+		start_chn = DEFAULT_AD_HOC_CHANNEL_A;
+
+		/*
+		 * Check that 11h is enabled in the driver
+		 */
+		if (wlan_11h_is_enabled(priv)) {
+			/*
+			 * Search the region_channel tables for a channel table
+			 * that is marked for the A Band.
+			 */
+			for (region = 0; (region < MAX_REGION_CHANNEL_NUM);
+			     region++) {
+				chn_tbl = &adapter->region_channel[region];
+
+				/* Check if table is valid and marked for A Band */
+				if (chn_tbl->valid
+				    && chn_tbl->region == adapter->region_code
+				    && chn_tbl->band & BAND_A) {
+					/*
+					 * Set the start channel.  Get a random
+					 * number and use it to pick an entry
+					 * in the table between 0 and the number
+					 * of channels in the table (NumCFP).
+					 */
+					rand_entry =
+						wlan_11h_get_random_num(adapter)
+						% chn_tbl->num_cfp;
+					start_chn =
+						(t_u8)chn_tbl->pcfp[rand_entry].
+						channel;
+					/* Loop until a non-dfs channel is found with compatible band
+					 * bounded by chn_tbl->num_cfp entries in the channel table
+					 */
+					while ((wlan_11h_is_channel_under_nop
+						(adapter, start_chn) ||
+						((adapter->state_rdh.stage ==
+						  RDH_GET_INFO_CHANNEL) &&
+						 wlan_11h_radar_detect_required
+						 (priv, start_chn)) ||
+						!(wlan_11h_is_band_valid
+						  (start_chn, uap_band_cfg))) &&
+					       (++rand_tries <
+						chn_tbl->num_cfp)) {
+						rand_entry++;
+						rand_entry =
+							rand_entry %
+							chn_tbl->num_cfp;
+						start_chn =
+							(t_u8)chn_tbl->
+							pcfp[rand_entry].
+							channel;
+						PRINTM(MINFO,
+						       "start chan=%d rand_entry=%d\n",
+						       start_chn, rand_entry);
+					}
+
+					if (rand_tries == chn_tbl->num_cfp) {
+						PRINTM(MERROR,
+						       "Failed to get UAP start channel\n");
+						start_chn = 0;
+					}
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMD_D, "11h: UAP Get Start Channel %d\n", start_chn);
+	LEAVE();
+	return start_chn;
+}
+#endif /* UAP_SUPPORT */
+
+#ifdef DEBUG_LEVEL1
+static const char *DFS_TS_REPR_STRINGS[] = { "",
+	"NOP_start",
+	"CAC_completed"
+};
+#endif
+
+/**
+ *  @brief Search for a dfs timestamp in the list with desired channel.
+ *
+ *  Assumes there will only be one timestamp per channel in the list.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param channel    Channel number
+ *
+ *  @return           Pointer to timestamp if found, or MNULL
+ */
+static wlan_dfs_timestamp_t *
+wlan_11h_find_dfs_timestamp(mlan_adapter *pmadapter, t_u8 channel)
+{
+	wlan_dfs_timestamp_t *pts = MNULL, *pts_found = MNULL;
+
+	ENTER();
+	pts = (wlan_dfs_timestamp_t *)util_peek_list(pmadapter->pmoal_handle,
+						     &pmadapter->state_dfs.
+						     dfs_ts_head, MNULL, MNULL);
+
+	while (pts &&
+	       pts !=
+	       (wlan_dfs_timestamp_t *)&pmadapter->state_dfs.dfs_ts_head) {
+		PRINTM(MINFO,
+		       "dfs_timestamp(@ %p) - chan=%d, repr=%d(%s),"
+		       " time(sec.usec)=%lu.%06lu\n", pts, pts->channel,
+		       pts->represents, DFS_TS_REPR_STRINGS[pts->represents],
+		       pts->ts_sec, pts->ts_usec);
+
+		if (pts->channel == channel) {
+			pts_found = pts;
+			break;
+		}
+		pts = pts->pnext;
+	}
+
+	LEAVE();
+	return pts_found;
+}
+
+/**
+ *  @brief Removes dfs timestamp from list.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param pdfs_ts    Pointer to dfs_timestamp to remove
+ */
+static t_void
+wlan_11h_remove_dfs_timestamp(mlan_adapter *pmadapter,
+			      wlan_dfs_timestamp_t *pdfs_ts)
+{
+	ENTER();
+	/* dequeue and delete timestamp */
+	util_unlink_list(pmadapter->pmoal_handle,
+			 &pmadapter->state_dfs.dfs_ts_head,
+			 (pmlan_linked_list)pdfs_ts, MNULL, MNULL);
+	pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pdfs_ts);
+	LEAVE();
+}
+
+/**
+ *  @brief Add a dfs timestamp to the list
+ *
+ *  Assumes there will only be one timestamp per channel in the list,
+ *  and that timestamp modes (represents) are mutually exclusive.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param repr       Timestamp 'represents' value (see _dfs_timestamp_repr_e)
+ *  @param channel    Channel number
+ *
+ *  @return           Pointer to timestamp if found, or MNULL
+ */
+static mlan_status
+wlan_11h_add_dfs_timestamp(mlan_adapter *pmadapter, t_u8 repr, t_u8 channel)
+{
+	wlan_dfs_timestamp_t *pdfs_ts = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	pdfs_ts = wlan_11h_find_dfs_timestamp(pmadapter, channel);
+
+	if (!pdfs_ts) {
+		/* need to allocate new timestamp */
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       sizeof
+						       (wlan_dfs_timestamp_t),
+						       MLAN_MEM_DEF,
+						       (t_u8 **)&pdfs_ts);
+		if ((ret != MLAN_STATUS_SUCCESS) || !pdfs_ts) {
+			PRINTM(MERROR, "%s(): Could not allocate dfs_ts\n",
+			       __func__);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		memset(pmadapter, (t_u8 *)pdfs_ts, 0,
+		       sizeof(wlan_dfs_timestamp_t));
+
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &pmadapter->state_dfs.dfs_ts_head,
+				       (pmlan_linked_list)pdfs_ts, MNULL,
+				       MNULL);
+		pdfs_ts->channel = channel;
+	}
+	/* (else, use existing timestamp for channel; see assumptions above) */
+
+	/* update params */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pdfs_ts->ts_sec,
+						  &pdfs_ts->ts_usec);
+	pdfs_ts->represents = repr;
+
+	PRINTM(MCMD_D, "11h: add/update dfs_timestamp - chan=%d, repr=%d(%s),"
+	       " time(sec.usec)=%lu.%06lu\n", pdfs_ts->channel,
+	       pdfs_ts->represents, DFS_TS_REPR_STRINGS[pdfs_ts->represents],
+	       pdfs_ts->ts_sec, pdfs_ts->ts_usec);
+
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global functions
+********************************************************/
+
+/**
+ *  @brief Return whether the device has activated master radar detection.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return
+ *    - MTRUE if master radar detection is enabled in firmware
+ *    - MFALSE otherwise
+ */
+t_bool
+wlan_11h_is_master_radar_det_active(mlan_private *priv)
+{
+	ENTER();
+	LEAVE();
+	return priv->adapter->state_11h.is_master_radar_det_active;
+}
+
+/**
+ *  @brief Configure master radar detection.
+ *  Call wlan_11h_check_update_radar_det_state() afterwards
+ *    to push this to firmware.
+ *
+ *  @param priv  Private driver information structure
+ *  @param enable Whether to enable or disable master radar detection
+ *
+ *  @return  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ *  @sa wlan_11h_check_update_radar_det_state
+ */
+mlan_status
+wlan_11h_config_master_radar_det(mlan_private *priv, t_bool enable)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	/* Force disable master radar detection on in-AP interfaces */
+	if (priv->adapter->dfs_repeater)
+		enable = MFALSE;
+
+	ENTER();
+	if (wlan_11h_is_dfs_master(priv) &&
+	    priv->adapter->init_para.dfs_master_radar_det_en) {
+		priv->adapter->state_11h.master_radar_det_enable_pending =
+			enable;
+		ret = MLAN_STATUS_SUCCESS;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Configure slave radar detection.
+ *  Call wlan_11h_check_update_radar_det_state() afterwards
+ *    to push this to firmware.
+ *
+ *  @param priv  Private driver information structure
+ *  @param enable Whether to enable or disable slave radar detection
+ *
+ *  @return  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ *  @sa wlan_11h_check_update_radar_det_state
+ */
+mlan_status
+wlan_11h_config_slave_radar_det(mlan_private *priv, t_bool enable)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	/* Force disable radar detection on STA interfaces */
+	if (priv->adapter->dfs_repeater)
+		enable = MFALSE;
+
+	ENTER();
+	if (wlan_11h_is_dfs_slave(priv) &&
+	    priv->adapter->init_para.dfs_slave_radar_det_en) {
+		priv->adapter->state_11h.slave_radar_det_enable_pending =
+			enable;
+		ret = MLAN_STATUS_SUCCESS;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Checks all interfaces and determines if radar_detect flag states
+ *         have/should be changed.  If so, sends SNMP_MIB 11H command to FW.
+ *         Call this function on any interface enable/disable/channel change.
+ *
+ *  @param pmpriv  Pointer to mlan_private structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS (update or not)
+ *              or MLAN_STATUS_FAILURE (cmd failure)
+ *
+ *  @sa    wlan_11h_check_radar_det_state
+ */
+mlan_status
+wlan_11h_check_update_radar_det_state(mlan_private *pmpriv)
+{
+	t_u32 new_radar_det_state = 0;
+	t_u32 mib_11h = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (wlan_11h_check_radar_det_state(pmpriv->adapter,
+					   &new_radar_det_state)) {
+		PRINTM(MCMD_D, "%s: radar_det_state being updated.\n",
+		       __func__);
+
+		mib_11h |= new_radar_det_state;
+		/* keep priv's existing 11h state */
+		if (pmpriv->intf_state_11h.is_11h_active)
+			mib_11h |= ENABLE_11H_MASK;
+
+		/* Send cmd to FW to enable/disable 11h function in firmware */
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET,
+				       Dot11H_i, MNULL, &mib_11h);
+		if (ret)
+			ret = MLAN_STATUS_FAILURE;
+	}
+
+	/* updated state sent OR no change, thus no longer pending */
+	pmpriv->adapter->state_11h.master_radar_det_enable_pending = MFALSE;
+	pmpriv->adapter->state_11h.slave_radar_det_enable_pending = MFALSE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Query 11h firmware enabled state.
+ *
+ *  Return whether the firmware currently has 11h extensions enabled
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return
+ *    - MTRUE if 11h has been activated in the firmware
+ *    - MFALSE otherwise
+ *
+ *  @sa wlan_11h_activate
+ */
+t_bool
+wlan_11h_is_active(mlan_private *priv)
+{
+	ENTER();
+	LEAVE();
+	return priv->intf_state_11h.is_11h_active;
+}
+
+/**
+ *  @brief Enable the transmit interface and record the state.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_11h_tx_enable(mlan_private *priv)
+{
+	ENTER();
+	if (priv->intf_state_11h.tx_disabled) {
+		if (priv->media_connected == MTRUE) {
+			wlan_recv_event(priv, MLAN_EVENT_ID_FW_START_TX, MNULL);
+			priv->intf_state_11h.tx_disabled = MFALSE;
+		}
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief Disable the transmit interface and record the state.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_11h_tx_disable(mlan_private *priv)
+{
+	ENTER();
+	if (!priv->intf_state_11h.tx_disabled) {
+		if (priv->media_connected == MTRUE) {
+			priv->intf_state_11h.tx_disabled = MTRUE;
+			wlan_recv_event(priv, MLAN_EVENT_ID_FW_STOP_TX, MNULL);
+		}
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief Enable or Disable the 11h extensions in the firmware
+ *
+ *  @param priv         Private driver information structure
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param flag         Enable 11h if MTRUE, disable otherwise
+ *
+ *  @return      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_activate(mlan_private *priv, t_void *pioctl_buf, t_bool flag)
+{
+	t_u32 enable = flag & ENABLE_11H_MASK;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	/* add bits for master/slave radar detect into enable. */
+	enable |= wlan_11h_get_current_radar_detect_flags(priv->adapter);
+
+	/* Whenever repeater mode is on make sure
+	 * we do not enable master or slave radar det mode.
+	 * HW will not detect radar in dfs_repeater mode.
+	 */
+	if (priv->adapter->dfs_repeater) {
+		enable &= ~(MASTER_RADAR_DET_MASK | SLAVE_RADAR_DET_MASK);
+	}
+
+	/*
+	 * Send cmd to FW to enable/disable 11h function in firmware
+	 */
+	ret = wlan_prepare_cmd(priv,
+			       HostCmd_CMD_802_11_SNMP_MIB,
+			       HostCmd_ACT_GEN_SET,
+			       Dot11H_i, (t_void *)pioctl_buf, &enable);
+	if (ret)
+		ret = MLAN_STATUS_FAILURE;
+	else
+		/* Set boolean flag in driver 11h state */
+		priv->intf_state_11h.is_11h_active = flag;
+
+	PRINTM(MINFO, "11h: %s\n", flag ? "Activate" : "Deactivate");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Initialize the 11h parameters and enable 11h when starting an IBSS
+ *
+ *  @param adapter mlan_adapter structure
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_11h_init(mlan_adapter *adapter)
+{
+	wlan_11h_device_state_t *pstate_11h = &adapter->state_11h;
+	IEEEtypes_Quiet_t *pquiet = &adapter->state_11h.quiet_ie;
+	wlan_dfs_device_state_t *pstate_dfs = &adapter->state_dfs;
+	wlan_radar_det_hndlg_state_t *pstate_rdh = &adapter->state_rdh;
+#ifdef DFS_TESTING_SUPPORT
+	wlan_dfs_testing_settings_t *pdfs_test = &adapter->dfs_test_params;
+#endif
+
+	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;
+
+#ifdef DFS_TESTING_SUPPORT
+	/* 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;
+#endif
+
+	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)
+	    || (adapter->adhoc_start_band & BAND_AN)
+		) {
+		/*
+		 * 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;
+}
+
+/**
+ *  @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;
+			}
+		}
+#ifdef DFS_TESTING_SUPPORT
+		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;
+		}
+#endif
+
+		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)
+		|| (adapter->adhoc_start_band & BAND_AN)
+	    )
+		) {
+		if (!wlan_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_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(priv->adapter, priv->adapter->curr_cmd->pdata_buf,
+		       &resp->params.tpc_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_cancel_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(pmadapter, &p11h_bss_info->power_constraint, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->power_capability, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->tpc_report, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->chan_switch_ann, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->quiet, pelement,
+		       MIN((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(pmadapter, &p11h_bss_info->ibss_dfs, pelement,
+		       MIN((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;
+
+	ENTER();
+	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(priv->adapter, deauth_param.mac_addr,
+	       &priv->curr_bss_params.bss_descriptor.mac_address,
+	       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;
+}
+
+#ifdef DFS_TESTING_SUPPORT
+/**
+ *  @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;
+	} 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;
+	}
+
+	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) {
+		ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+		ch_nop_info = &ds_11hcfg->param.ch_nop_info;
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+		if (pioctl_req->action == MLAN_ACT_GET) {
+			ch_nop_info->chan_under_nop =
+				wlan_11h_is_channel_under_nop(pmadapter,
+							      ch_nop_info->
+							      curr_chan);
+			if (ch_nop_info->chan_under_nop) {
+				wlan_11h_switch_non_dfs_chan(pmpriv,
+							     &ch_nop_info->
+							     new_chan.channel);
+				if (ch_nop_info->chan_width == CHAN_BW_80MHZ ||
+				    ch_nop_info->chan_width == CHAN_BW_40MHZ)
+					wlan_11h_update_bandcfg(&ch_nop_info->
+								new_chan.
+								bandcfg,
+								ch_nop_info->
+								new_chan.
+								channel);
+				if (ch_nop_info->chan_width == CHAN_BW_80MHZ)
+					ch_nop_info->new_chan.center_chan =
+						wlan_get_center_freq_idx(pmpriv,
+									 BAND_AAC,
+									 ch_nop_info->
+									 new_chan.
+									 channel,
+									 ch_nop_info->
+									 chan_width);
+			}
+		}
+		ret = MLAN_STATUS_SUCCESS;
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif /* DFS_TESTING_SUPPORT */
+
+/**
+ *  @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 cancel 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_cancel_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);
+#ifdef DFS_TESTING_SUPPORT
+		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
+#endif
+		{
+			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)
+{
+	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;
+
+	ENTER();
+	pchan_rpt_rsp = (HostCmd_DS_CHAN_RPT_RSP *)&pevent->event_buf;
+	DBG_HEXDUMP(MCMD_D, "11h: Event ChanRptReady (HostCmd_DS_CHAN_RPT_RSP)",
+		    (t_u8 *)pchan_rpt_rsp, pevent->event_len);
+
+	if (wlan_le32_to_cpu(pchan_rpt_rsp->cmd_result) ==
+	    MLAN_CMD_RESULT_SUCCESS) {
+		pbuffer = (t_u8 *)&pchan_rpt_rsp->tlv_buffer;
+		evt_len = pevent->event_len;
+		evt_len -=
+			sizeof(HostCmd_DS_CHAN_RPT_RSP) -
+			sizeof(pchan_rpt_rsp->tlv_buffer);
+
+		while (evt_len >= sizeof(MrvlIEtypesHeader_t)) {
+			ptlv = (MrvlIEtypes_Data_t *)pbuffer;
+			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+
+			switch (wlan_le16_to_cpu(ptlv->header.type)) {
+			case TLV_TYPE_CHANRPT_11H_BASIC:
+				pmeas_rpt_basic =
+					(MeasRptBasicMap_t *)&ptlv->data;
+				if (pmeas_rpt_basic->radar) {
+					pstate_dfs->dfs_radar_found = MTRUE;
+					PRINTM(MMSG,
+					       "RADAR Detected on channel %d!\n",
+					       pstate_dfs->dfs_check_channel);
+					/* add channel to NOP list */
+					wlan_11h_add_dfs_timestamp(priv->
+								   adapter,
+								   DFS_TS_REPR_NOP_START,
+								   pstate_dfs->
+								   dfs_check_channel);
+				}
+				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;
+	}
+
+	/* Update DFS structure. */
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &sec,
+						      &usec);
+	pstate_dfs->dfs_report_time_sec = sec;
+	pstate_dfs->dfs_check_pending = MFALSE;
+	pstate_dfs->dfs_check_priv = MNULL;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 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;
+}
+
+/**
+ *  @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);
+		}
+	}
+}
+
+/**
+ *  @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(IN Band_Config_t *uap_band_cfg, IN t_u8 new_channel)
+{
+	t_u8 chan_offset;
+	ENTER();
+
+	/* Update the channel offset for 20MHz, 40MHz and 80MHz
+	 * Clear the channel bandwidth for 20MHz
+	 * since channel switch could be happening from 40/80MHz to 20MHz
+	 */
+	chan_offset = wlan_get_second_channel_offset(new_channel);
+	uap_band_cfg->chan2Offset = chan_offset;
+
+	if (!chan_offset) {	/* 40MHz/80MHz */
+		PRINTM(MCMD_D, "20MHz channel, clear channel bandwidth\n");
+		uap_band_cfg->chanWidth = CHAN_BW_20MHZ;
+	}
+	LEAVE();
+}
+
+/**
+ * @brief Get priv current index -- this is used to enter correct rdh_state during radar handling
+ *
+ * @param pmpriv           Pointer to mlan_private
+ * @param pstate_rdh       Pointer to radar detected state handler
+ *
+ * @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_get_priv_curr_idx(mlan_private *pmpriv,
+			   wlan_radar_det_hndlg_state_t *pstate_rdh)
+{
+	t_bool found = MFALSE;
+	ENTER();
+
+	PRINTM(MINFO, "%s:pmpriv =%p\n", __func__, pmpriv);
+	while ((++pstate_rdh->priv_curr_idx) < pstate_rdh->priv_list_count) {
+		if (pmpriv == pstate_rdh->priv_list[pstate_rdh->priv_curr_idx]) {
+			PRINTM(MINFO, "found matching priv: priv_idx=%d\n",
+			       pstate_rdh->priv_curr_idx);
+			found = MTRUE;
+			break;
+		}
+	}
+	return (found == MTRUE) ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Driver handling for 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 TO NEXT STAGE */
+
+	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 TO NEXT STAGE */
+
+	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
+		}
+#ifdef DFS_TESTING_SUPPORT
+		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;
+		}
+#endif
+		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 TO NEXT STAGE */
+
+	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 TO NEXT STAGE */
+
+	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 - firmware will accept on any interface, and apply to all */
+		if (pstate_rdh->priv_curr_idx == RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
+			mlan_ioctl_req *pioctl_req = MNULL;
+
+			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 */
+			}
+
+			PRINTM(MMSG,
+			       "11h: Radar Detected - adding CHAN_SW IE to interfaces.\n");
+			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 */
+			}
+
+			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 TO NEXT STAGE */
+
+	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 - firmware will accept on any interface,
+		   and apply to all */
+		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");
+
+			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 */
+			}
+
+			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 */
+			}
+
+			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 TO NEXT STAGE */
+
+	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;
+
+#ifdef DFS_TESTING_SUPPORT
+		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 */
+		}
+#endif
+		/* FALL THROUGH TO NEXT STAGE */
+
+	case RDH_SET_NEW_CHANNEL:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n",
+		       __func__, pstate_rdh->stage,
+		       rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+		/* only set new channel for UAP intfs */
+		while ((++pstate_rdh->priv_curr_idx) <
+		       pstate_rdh->priv_list_count) {
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+
+				pmpriv->uap_state_chan_cb.pioctl_req_curr =
+					MNULL;
+				pmpriv->uap_state_chan_cb.get_chan_callback =
+					wlan_11h_radar_detected_callback;
+
+				/* DFS only in 5GHz */
+				wlan_11h_update_bandcfg(&pstate_rdh->
+							uap_band_cfg,
+							pstate_rdh->
+							new_channel);
+				PRINTM(MCMD_D,
+				       "RDH_SET_NEW_CHANNEL: uAP band config = 0x%x channel=%d\n",
+				       pstate_rdh->uap_band_cfg,
+				       pstate_rdh->new_channel);
+
+				ret = wlan_uap_set_channel(pmpriv,
+							   pstate_rdh->
+							   uap_band_cfg,
+							   pstate_rdh->
+							   new_channel);
+				break;	/* leads to exit case */
+			}
+#endif
+		}
+
+		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
+		    ret == MLAN_STATUS_FAILURE)
+			break;	/* EXIT CASE (for UAP) */
+		/* else */
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_RESTART_INTFS;
+		/* FALL THROUGH TO NEXT STAGE */
+
+	case RDH_RESTART_INTFS:
+#ifdef DFS_TESTING_SUPPORT
+rdh_restart_intfs:
+#endif
+		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 TO NEXT STAGE */
+
+	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;
+			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 */
+			}
+
+			pmpriv = pstate_rdh->priv_list[0];
+			pstate_rdh->priv_curr_idx = 0;
+			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: 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];
+
+	ENTER();
+	switch (pmadapter->event_cause & EVENT_ID_MASK) {
+	case EVENT_RADAR_DETECTED:
+		/* find active intf:  prefer dfs_master over dfs_slave */
+		if (wlan_get_privs_by_two_cond(pmadapter,
+					       wlan_11h_is_master_active_on_dfs_chan,
+					       wlan_11h_is_dfs_master,
+					       MTRUE, priv_list)) {
+			pmpriv = priv_list[0];
+			PRINTM(MINFO, "%s: found dfs_master priv=%p\n",
+			       __func__, pmpriv);
+		} else if (wlan_get_privs_by_two_cond(pmadapter,
+						      wlan_11h_is_slave_active_on_dfs_chan,
+						      wlan_11h_is_dfs_slave,
+						      MTRUE, priv_list)) {
+			pmpriv = priv_list[0];
+			PRINTM(MINFO, "%s: found dfs_slave priv=%p\n",
+			       __func__, pmpriv);
+		} else if (pmadapter->state_dfs.dfs_check_pending) {
+			pmpriv = (mlan_private *)(pmadapter->state_dfs.
+						  dfs_check_priv);
+			PRINTM(MINFO, "%s: found dfs priv=%p\n", __func__,
+			       pmpriv);
+		}
+
+		/* update event_cause if we found an appropriate priv */
+		if (pmpriv) {
+			pmlan_buffer pmevbuf = pmadapter->pmlan_buffer_event;
+			t_u32 new_event_cause =
+				pmadapter->event_cause & EVENT_ID_MASK;
+			new_event_cause |=
+				((GET_BSS_NUM(pmpriv) & 0xff) << 16) |
+				((pmpriv->bss_type & 0xff) << 24);
+			PRINTM(MINFO, "%s: priv - bss_num=%d, bss_type=%d\n",
+			       __func__, GET_BSS_NUM(pmpriv), pmpriv->bss_type);
+			memcpy(pmadapter, pmevbuf->pbuf + pmevbuf->data_offset,
+			       &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();
+
+#ifdef DFS_TESTING_SUPPORT
+	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;
+	}
+#endif
+
+	/*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;
+}
diff --git a/wlan_sd8997/mlan/mlan_11h.h b/wlan_sd8997/mlan/mlan_11h.h
new file mode 100644
index 0000000..d059439
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11h.h
@@ -0,0 +1,194 @@
+/** @file mlan_11h.h
+ *
+ *  @brief This header file contains data structures and
+ *  function declarations of 802.11h
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/*************************************************************
+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);
+
+#ifdef DFS_TESTING_SUPPORT
+/** 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);
+#endif
+
+extern mlan_status
+
+wlan_11h_ioctl_dfs_cancel_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);
+
+/** 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);
+
+/** 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);
+
+/** Handler for RADAR_DETECTED */
+extern mlan_status wlan_11h_radar_detected_handling(mlan_adapter *pmadapter,
+						    mlan_private *priv);
+/** 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(IN Band_Config_t *uap_band_cfg,
+				    IN 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_sd8997/mlan/mlan_11n.c b/wlan_sd8997/mlan/mlan_11n.c
new file mode 100644
index 0000000..b00bbb7
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11n.c
@@ -0,0 +1,3276 @@
+/** @file mlan_11n.c
+ *
+ *  @brief This file contains functions for 11n handling.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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(IN pmlan_adapter pmadapter,
+			       IN 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_SET) {
+		if (cfg->param.tx_buf_size == 0xffff) {
+			PRINTM(MIOCTL, "Send reconfigure tx buf to FW\n");
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_RECONFIGURE_TX_BUFF,
+					       HostCmd_ACT_GEN_SET, 0,
+					       (t_void *)pioctl_req,
+					       &cfg->param.tx_buf_size);
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = MLAN_STATUS_PENDING;
+			LEAVE();
+			return ret;
+		}
+	}
+	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(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_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(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_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(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_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(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_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(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_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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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(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_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(IN pmlan_adapter pmadapter,
+			    IN 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(pmadapter, cfg->param.addba_reject, pmpriv->addba_reject,
+		       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(IN pmlan_adapter pmadapter,
+				IN 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 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(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_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(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_11n_cfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_REJECT_ADDBA_REQ,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &cfg->param.reject_addba_req);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will send DELBA to entries in the priv's
+ *          Tx BA stream table
+ *
+ *  @param priv                 A pointer to mlan_private
+ *  @param tid                  TID
+ *
+ *  @return		 N/A
+ */
+static void
+wlan_send_delba_txbastream_tbl(pmlan_private priv, t_u8 tid)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	TxBAStreamTbl *tx_ba_stream_tbl_ptr;
+
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	tx_ba_stream_tbl_ptr =
+		(TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+						&priv->tx_ba_stream_tbl_ptr,
+						MNULL, MNULL);
+	if (!tx_ba_stream_tbl_ptr) {
+		wlan_release_ralist_lock(priv);
+		LEAVE();
+		return;
+	}
+
+	while (tx_ba_stream_tbl_ptr !=
+	       (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (tx_ba_stream_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) {
+			if (tid == tx_ba_stream_tbl_ptr->tid) {
+				PRINTM(MIOCTL,
+				       "Tx:Send delba to tid=%d, " MACSTR "\n",
+				       tid, MAC2STR(tx_ba_stream_tbl_ptr->ra));
+				wlan_release_ralist_lock(priv);
+				wlan_send_delba(priv, MNULL,
+						tx_ba_stream_tbl_ptr->tid,
+						tx_ba_stream_tbl_ptr->ra, 1);
+				LEAVE();
+				return;
+			}
+		}
+		tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext;
+	}
+	wlan_release_ralist_lock(priv);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief update station list for the new aggr_prio_tbl setting
+ *
+ *  @param priv 	A pointer to mlan_private structure
+ *
+ *
+ *  @return		N/A
+ */
+void
+wlan_update_all_stations_ampdu(mlan_private *priv)
+{
+	sta_node *sta_ptr;
+	mlan_adapter *pmadapter = priv->adapter;
+	int i = 0;
+
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	sta_ptr = (sta_node *)util_peek_list(pmadapter->pmoal_handle,
+					     &priv->sta_list, MNULL, MNULL);
+	if (!sta_ptr) {
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		LEAVE();
+		return;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			if (sta_ptr->is_11n_enabled)
+				sta_ptr->ampdu_sta[i] =
+					priv->aggr_prio_tbl[i].ampdu_user;
+		}
+		sta_ptr = sta_ptr->pnext;
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Set/get aggr_prio_tbl
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_aggr_prio_tbl(IN pmlan_adapter pmadapter,
+			     IN 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(IN pmlan_adapter pmadapter,
+				 IN 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(pmadapter, cfg->param.supported_mcs_set, mcs_set, NUM_MCS_FIELD);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function checks if the given pointer is valid entry of
+ *         Tx BA Stream table
+ *
+ *  @param priv         Pointer to mlan_private
+ *  @param ptxtblptr    Pointer to tx ba stream entry
+ *
+ *  @return             MTRUE or MFALSE
+ */
+static int
+wlan_is_txbastreamptr_valid(mlan_private *priv, TxBAStreamTbl *ptxtblptr)
+{
+	TxBAStreamTbl *ptx_tbl;
+
+	ENTER();
+
+	ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						  &priv->tx_ba_stream_tbl_ptr,
+						  MNULL, MNULL);
+	if (!ptx_tbl) {
+		LEAVE();
+		return MFALSE;
+	}
+
+	while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (ptx_tbl == ptxtblptr) {
+			LEAVE();
+			return MTRUE;
+		}
+		ptx_tbl = ptx_tbl->pnext;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief This function will return the pointer to a entry in BA Stream
+ *          table which matches the ba_status requested
+ *
+ *  @param priv         A pointer to mlan_private
+ *  @param ba_status    Current status of the BA stream
+ *
+ *  @return             A pointer to first entry matching status in BA stream
+ *                      NULL if not found
+ */
+static TxBAStreamTbl *
+wlan_11n_get_txbastream_status(mlan_private *priv, baStatus_e ba_status)
+{
+	TxBAStreamTbl *ptx_tbl;
+
+	ENTER();
+
+	ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						  &priv->tx_ba_stream_tbl_ptr,
+						  MNULL, MNULL);
+	if (!ptx_tbl) {
+		LEAVE();
+		return MNULL;
+	}
+
+	while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (ptx_tbl->ba_status == ba_status) {
+			LEAVE();
+			return ptx_tbl;
+		}
+		ptx_tbl = ptx_tbl->pnext;
+	}
+
+	LEAVE();
+	return MNULL;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function fills the cap info
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_fill_cap_info(mlan_private *priv, HTCap_t *ht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11n_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+	if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+		SETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+	else
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+
+	if (ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
+		SETHT_GREENFIELD(ht_cap->ht_cap_info);
+	else
+		RESETHT_GREENFIELD(ht_cap->ht_cap_info);
+
+	if (ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
+		SETHT_SHORTGI20(ht_cap->ht_cap_info);
+	else
+		RESETHT_SHORTGI20(ht_cap->ht_cap_info);
+
+	if (ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
+		SETHT_SHORTGI40(ht_cap->ht_cap_info);
+	else
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+	if (ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
+		SETHT_RXSTBC(ht_cap->ht_cap_info, 1);
+	else
+		RESETHT_RXSTBC(ht_cap->ht_cap_info);
+
+	if (ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
+		SETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+	else
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+
+	/** if current channel only allow 20Mhz, we should cler 40Mhz support */
+	if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	    priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+	}
+	/* No user config for LDPC coding capability yet */
+	if (ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
+		SETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+	else
+		RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+
+	/* No user config for TX STBC yet */
+	if (ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
+		SETHT_TXSTBC(ht_cap->ht_cap_info);
+	else
+		RESETHT_TXSTBC(ht_cap->ht_cap_info);
+
+	/* No user config for Delayed BACK yet */
+	RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+
+	/* Need change to support 8k AMSDU receive */
+	RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+	/* SM power save */
+	if (ISSUPP_MIMOPS(priv->adapter->hw_dot_11n_dev_cap))
+		RESETHT_SM_POWERSAVE(ht_cap->ht_cap_info);	/* Enable HT SMPS */
+	else
+		SETHT_STATIC_SMPS(ht_cap->ht_cap_info);	/* Disable HT SMPS */
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function clear the bit in cap info which we don't support
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_reset_cap_info(mlan_private *priv, HTCap_t *ht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11n_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+	if (!ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
+		RESETHT_GREENFIELD(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
+		RESETHT_SHORTGI20(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+	if (!ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
+		RESETHT_RXSTBC(ht_cap->ht_cap_info);
+
+	if (!ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+
+	/** if current channel only allow 20Mhz, we should cler 40Mhz support */
+	if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	    priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+	}
+	/* No user config for LDPC coding capability yet */
+	if (!ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
+		RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+
+	/* No user config for TX STBC yet */
+	if (!ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
+		RESETHT_TXSTBC(ht_cap->ht_cap_info);
+
+	/* No user config for Delayed BACK yet */
+	RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+
+	/* Need change to support 8k AMSDU receive */
+	RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+	/* SM power save */
+	if (!ISSUPP_MIMOPS(priv->adapter->hw_dot_11n_dev_cap))
+		SETHT_STATIC_SMPS(ht_cap->ht_cap_info);	/* Disable HT SMPS */
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function fills the HT cap tlv
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *  @param fill         A flag for fill the htcap info
+ *
+ *  @return             N/A
+ */
+void
+wlan_fill_ht_cap_tlv(mlan_private *priv,
+		     MrvlIETypes_HTCap_t *pht_cap, t_u8 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);
+	/* 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_u8 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);
+	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 (priv->bss_mode == MLAN_BSS_MODE_IBSS)
+				disable_station_ampdu(priv, tid,
+						      padd_ba_rsp->
+						      peer_mac_addr);
+			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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *cmd,
+		 IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *cmd,
+		   IN t_u16 cmd_action, IN 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;
+	mlan_tx_sounding_cfg_args *mlan_tx_sounding_cfg = MNULL;
+	tx_sounding_cfg_args_t *tx_sounding_cfg = MNULL;
+
+	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(pmadapter, txbfcfg->body.bf_periodicity.peer_mac,
+		       txbf->body.bf_periodicity[0].peer_mac,
+		       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(pmadapter, txbfcfg->body.bf_sound_args.peer_mac,
+			       txbf->body.bf_sound[0].peer_mac,
+			       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(pmadapter, txbfcfg->body.tx_bf_peer.peer_mac,
+			       txbf->body.tx_bf_peer[0].peer_mac,
+			       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(pmadapter, txbfcfg->body.bf_snr.peer_mac,
+			       txbf->body.bf_snr[0].peer_mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			txbfcfg->body.bf_snr.snr = txbf->body.bf_snr[0].snr;
+			break;
+		case TX_SOUNDING_CFG:
+			mlan_tx_sounding_cfg = &txbf->body.tx_sounding_cfg;
+			tx_sounding_cfg = &txbfcfg->body.tx_sounding_cfg;
+			tx_sounding_cfg->tx_sounding_enbl =
+				mlan_tx_sounding_cfg->tx_sounding_enbl;
+			tx_sounding_cfg->sounding_type =
+				mlan_tx_sounding_cfg->sounding_type;
+			tx_sounding_cfg->sounding_interval =
+				wlan_cpu_to_le16(mlan_tx_sounding_cfg->
+						 sounding_interval);
+			break;
+		default:
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	switch (txbf->bf_action) {
+	case TX_SOUNDING_CFG:
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(tx_sounding_cfg_args_t) + 4 +
+					 S_DS_GEN);
+		break;
+	default:
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_TX_BF_CFG) +
+					 S_DS_GEN);
+	}
+
+	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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *resp, IN 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;
+	mlan_tx_sounding_cfg_args *mlan_tx_sounding_cfg = MNULL;
+	tx_sounding_cfg_args_t *tx_sounding_cfg = MNULL;
+
+	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(pmadapter, txbf->body.bf_sound[0].peer_mac,
+			       txbfcfg->body.bf_sound_args.peer_mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			txbf->body.bf_sound[0].status =
+				txbfcfg->body.bf_sound_args.status;
+			break;
+		case SET_GET_BF_PERIODICITY:
+			memcpy(pmadapter, txbf->body.bf_periodicity->peer_mac,
+			       txbfcfg->body.bf_periodicity.peer_mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			txbf->body.bf_periodicity->interval =
+				wlan_le16_to_cpu(txbfcfg->body.bf_periodicity.
+						 interval);
+			break;
+		case TX_BF_FOR_PEER_ENBL:
+			txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+			tx_bf_peer =
+				(bf_peer_args *)((t_u8 *)&txbfcfg->body +
+						 sizeof(t_u8));
+			for (i = 0; i < txbf->no_of_peers; i++) {
+				memcpy(pmadapter,
+				       txbf->body.tx_bf_peer[i].peer_mac,
+				       (t_u8 *)tx_bf_peer->peer_mac,
+				       MLAN_MAC_ADDR_LENGTH);
+				txbf->body.tx_bf_peer[i].bf_enbl =
+					tx_bf_peer->bf_enbl;
+				txbf->body.tx_bf_peer[i].sounding_enbl =
+					tx_bf_peer->sounding_enbl;
+				txbf->body.tx_bf_peer[i].fb_type =
+					tx_bf_peer->fb_type;
+				tx_bf_peer++;
+			}
+			break;
+		case SET_SNR_THR_PEER:
+			txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+			bf_snr = (bf_snr_thr_t *)((t_u8 *)&txbfcfg->body +
+						  sizeof(t_u8));
+			for (i = 0; i < txbf->no_of_peers; i++) {
+				memcpy(pmadapter, txbf->body.bf_snr[i].peer_mac,
+				       (t_u8 *)bf_snr->peer_mac,
+				       MLAN_MAC_ADDR_LENGTH);
+				txbf->body.bf_snr[i].snr = bf_snr->snr;
+				bf_snr++;
+			}
+			break;
+		case TX_SOUNDING_CFG:
+			mlan_tx_sounding_cfg = &txbf->body.tx_sounding_cfg;
+			tx_sounding_cfg = &txbfcfg->body.tx_sounding_cfg;
+			mlan_tx_sounding_cfg->tx_sounding_enbl =
+				tx_sounding_cfg->tx_sounding_enbl;
+			mlan_tx_sounding_cfg->sounding_type =
+				tx_sounding_cfg->sounding_type;
+			mlan_tx_sounding_cfg->sounding_interval =
+				wlan_le16_to_cpu(tx_sounding_cfg->
+						 sounding_interval);
+			break;
+		default:
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get second channel offset
+ *
+ * @param chan            channel num
+ * @return                second channel offset
+ */
+t_u8
+wlan_get_second_channel_offset(int chan)
+{
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+
+	switch (chan) {
+	case 36:
+	case 44:
+	case 52:
+	case 60:
+	case 100:
+	case 108:
+	case 116:
+	case 124:
+	case 132:
+	case 140:
+	case 149:
+	case 157:
+		chan2Offset = SEC_CHAN_ABOVE;
+		break;
+	case 40:
+	case 48:
+	case 56:
+	case 64:
+	case 104:
+	case 112:
+	case 120:
+	case 128:
+	case 136:
+	case 144:
+	case 153:
+	case 161:
+		chan2Offset = SEC_CHAN_BELOW;
+		break;
+	case 165:
+		/* Special Case: 20Mhz-only Channel */
+		chan2Offset = SEC_CHAN_NONE;
+		break;
+	}
+	return chan2Offset;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief validate the channel offset for Infra/Ad-hoc band configuration
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param band         band
+ *  @param chan         primary channel
+ *  @param chan_bw      channel bandwidth
+ *
+ *  @return             channel offset (NO_SEC_CHANNEL, SEC_CHANNEL_ABOVE,
+ *                                      SEC_CHANNEL_BELOW)
+ */
+t_u8
+wlan_validate_chan_offset(IN mlan_private *pmpriv,
+			  IN t_u8 band, IN t_u32 chan, IN t_u8 chan_bw)
+{
+	t_u8 chan_offset;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+
+	if (chan_bw == CHANNEL_BW_40MHZ_ABOVE)
+		chan_offset = SEC_CHAN_ABOVE;
+	else if (chan_bw == CHANNEL_BW_40MHZ_BELOW)
+		chan_offset = SEC_CHAN_BELOW;
+	else
+		chan_offset = SEC_CHAN_NONE;
+
+	/* validation */
+	if (chan_offset != SEC_CHAN_NONE) {
+		if (band & BAND_GN) {
+			if ((chan == 1) || (chan == 2) || (chan == 3) ||
+			    (chan == 4))
+				chan_offset = SEC_CHAN_ABOVE;
+			else if ((chan == 10) || (chan == 11) ||
+				 (chan == 12) || (chan == 13))
+				chan_offset = SEC_CHAN_BELOW;
+
+			/* check if channel 12 is supported in the region */
+			if (!wlan_find_cfp_by_band_and_channel
+			    (pmadapter, band, 12))
+				if ((chan == 8) || (chan == 9))
+					chan_offset = SEC_CHAN_BELOW;
+		} else if (band & BAND_AN)
+			chan_offset = wlan_get_second_channel_offset(chan);
+	}
+	return chan_offset;
+}
+
+/**
+ *  @brief This function check if ht40 is allowed in current region
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc    A pointer to BSSDescriptor_t structure
+ *
+ *  @return MTRUE/MFALSE
+ */
+static int
+wlan_check_chan_width_ht40_by_region(IN mlan_private *pmpriv,
+				     IN 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))
+		return MFALSE;
+	if ((chan_offset == SEC_CHAN_BELOW) &&
+	    (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS))
+		return MFALSE;
+
+	num_cfp = pmadapter->region_channel[0].num_cfp;
+
+	if ((pbss_desc->bss_band & (BAND_B | BAND_G)) &&
+	    pmadapter->region_channel && 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(IN mlan_private *pmpriv,
+			IN BSSDescriptor_t *pbss_desc, OUT t_u8 **ppbuffer)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	MrvlIETypes_HTCap_t *pht_cap;
+	MrvlIETypes_HTInfo_t *pht_info;
+	MrvlIEtypes_ChanListParamSet_t *pchan_list;
+	MrvlIETypes_2040BSSCo_t *p2040_bss_co;
+	MrvlIETypes_ExtCap_t *pext_cap;
+	t_u32 usr_dot_11n_dev_cap, orig_usr_dot_11n_dev_cap = 0;
+	t_u32 usr_vht_cap_info;
+	t_u8 usr_dot_11ac_bw;
+	int ret_len = 0;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+
+	if (pbss_desc->bss_band & BAND_A)
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
+
+	if (pbss_desc->bss_band & BAND_A)
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_vht_cap_info = pmpriv->usr_dot_11ac_dev_cap_bg;
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+		usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
+	else
+		usr_dot_11ac_bw = pmpriv->usr_dot_11ac_bw;
+	if ((pbss_desc->bss_band & (BAND_B | BAND_G)) &&
+	    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(pmadapter, (t_u8 *)pht_cap + sizeof(MrvlIEtypesHeader_t),
+		       (t_u8 *)pbss_desc->pht_cap + sizeof(IEEEtypes_Header_t),
+		       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);
+
+		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) {
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+			pht_info = (MrvlIETypes_HTInfo_t *)*ppbuffer;
+			memset(pmadapter, pht_info, 0,
+			       sizeof(MrvlIETypes_HTInfo_t));
+			pht_info->header.type = wlan_cpu_to_le16(HT_OPERATION);
+			pht_info->header.len = sizeof(HTInfo_t);
+
+			memcpy(pmadapter,
+			       (t_u8 *)pht_info + sizeof(MrvlIEtypesHeader_t),
+			       (t_u8 *)pbss_desc->pht_info +
+			       sizeof(IEEEtypes_Header_t),
+			       pht_info->header.len);
+
+			if (!ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+				RESET_CHANWIDTH40(pht_info->ht_info.field2);
+
+			*ppbuffer += sizeof(MrvlIETypes_HTInfo_t);
+			ret_len += sizeof(MrvlIETypes_HTInfo_t);
+			pht_info->header.len =
+				wlan_cpu_to_le16(pht_info->header.len);
+		}
+
+		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(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);
+
+		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(pmadapter,
+		       (t_u8 *)pext_cap + sizeof(MrvlIEtypesHeader_t),
+		       (t_u8 *)&pmpriv->ext_cap, sizeof(ExtCap_t));
+		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, 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(IN pmlan_adapter pmadapter, IN 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;
+	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(pmadapter, new_node->ra, ra, 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(priv->adapter, &add_ba_req.peer_mac_addr, peer_mac,
+	       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(priv->adapter, &delba.peer_mac_addr, peer_mac,
+	       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();
+	rx_reorder_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_reorder_tbl_ptr) {
+		LEAVE();
+		return count;
+	}
+	while (rx_reorder_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		ptbl->tid = (t_u16)rx_reorder_tbl_ptr->tid;
+		memcpy(priv->adapter, ptbl->ta, rx_reorder_tbl_ptr->ta,
+		       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;
+	}
+	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(priv->adapter, ptbl->ra, ptxtbl->ra,
+		       MLAN_MAC_ADDR_LENGTH);
+		ptbl->amsdu = ptxtbl->amsdu;
+		ptxtbl = ptxtbl->pnext;
+		ptbl++;
+		count++;
+		if (count >= bastream_max)
+			break;
+	}
+	wlan_release_ralist_lock(priv);
+	LEAVE();
+	return count;
+}
+
+/**
+ *  @brief This function check if 11AC is allowed in bandcfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param bss_band     bss band
+ *
+ *  @return 0--not allowed, other value allowed
+ */
+t_u8
+wlan_11n_bandconfig_allowed(mlan_private *pmpriv, t_u8 bss_band)
+{
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+		if (bss_band & BAND_G)
+			return (pmpriv->adapter->adhoc_start_band & BAND_GN);
+		else if (bss_band & BAND_A)
+			return (pmpriv->adapter->adhoc_start_band & BAND_AN);
+	} else {
+		if (bss_band & BAND_G)
+			return (pmpriv->config_bands & BAND_GN);
+		else if (bss_band & BAND_A)
+			return (pmpriv->config_bands & BAND_AN);
+	}
+	return 0;
+}
+
+/**
+ *  @brief This function cleans up txbastream_tbl for specific station
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ra       RA to find in txbastream_tbl
+ *  @return         N/A
+ */
+void
+wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra)
+{
+	TxBAStreamTbl *ptx_tbl = MNULL;
+	t_u8 i;
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		ptx_tbl = wlan_11n_get_txbastream_tbl(priv, i, ra, MFALSE);
+		if (ptx_tbl)
+			wlan_11n_delete_txbastream_tbl_entry(priv, ptx_tbl);
+	}
+	wlan_release_ralist_lock(priv);
+	LEAVE();
+	return;
+}
+
+void
+wlan_update_11n_cap(mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	pmpriv->usr_dev_mcs_support = pmadapter->hw_dev_mcs_support;
+	pmpriv->usr_dot_11n_dev_cap_bg =
+		pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_BG;
+	pmpriv->usr_dot_11n_dev_cap_a =
+		pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_A;
+}
diff --git a/wlan_sd8997/mlan/mlan_11n.h b/wlan_sd8997/mlan/mlan_11n.h
new file mode 100644
index 0000000..20d5196
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11n.h
@@ -0,0 +1,396 @@
+/** @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.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf);
+/** Prepare 11ncfg command */
+mlan_status wlan_cmd_11n_cfg(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action,
+			     IN t_void *pdata_buf);
+/** Prepare reject addba requst command */
+mlan_status wlan_cmd_reject_addba_req(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_u16 cmd_action,
+				      IN t_void *pdata_buf);
+/** Handle the command response of rejecting addba request */
+mlan_status wlan_ret_reject_addba_req(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+/** Prepare TX BF configuration command */
+mlan_status wlan_cmd_tx_bf_cfg(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action, IN t_void *pdata_buf);
+/** Handle the command response TX BF configuration */
+mlan_status wlan_ret_tx_bf_cfg(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *resp,
+			       IN 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(IN mlan_private *pmpriv,
+			    IN BSSDescriptor_t *pbss_desc, OUT t_u8 **ppbuffer);
+/** wlan fill HT cap tlv */
+void wlan_fill_ht_cap_tlv(mlan_private *priv, MrvlIETypes_HTCap_t *pht_cap,
+			  t_u8 band, t_u8 fill);
+/** wlan fill HT cap IE */
+void wlan_fill_ht_cap_ie(mlan_private *priv, IEEEtypes_HTCap_t *pht_cap,
+			 t_u8 bands);
+#endif /* STA_SUPPORT */
+/** Miscellaneous configuration handler */
+mlan_status wlan_11n_cfg_ioctl(IN pmlan_adapter pmadapter,
+			       IN 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(IN mlan_private *pmpriv,
+			       IN t_u8 band, IN t_u32 chan, IN t_u8 chan_bw);
+/** get channel offset */
+t_u8 wlan_get_second_channel_offset(int chan);
+
+void wlan_update_11n_cap(mlan_private *pmpriv);
+
+/** clean up txbastream_tbl */
+void wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra);
+/**
+ *  @brief This function checks whether a station has 11N enabled or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param mac      station mac address
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+is_station_11n_enabled(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		return (sta_ptr->is_11n_enabled) ? MTRUE : MFALSE;
+	return MFALSE;
+}
+
+/**
+ *  @brief This function get station max amsdu size
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param mac      station mac address
+ *  @return         max amsdu size statio supported
+ */
+static INLINE t_u16
+get_station_max_amsdu_size(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		return sta_ptr->max_amsdu;
+	return 0;
+}
+
+/**
+ *  @brief This function checks whether a station allows AMPDU or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ptr      A pointer to RA list table
+ *  @param tid      TID value for ptr
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+is_station_ampdu_allowed(mlan_private *priv, raListTbl *ptr, int tid)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+	if (sta_ptr) {
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			if (priv->sec_info.wapi_enabled &&
+			    !sta_ptr->wapi_key_on)
+				return MFALSE;
+		}
+		return (sta_ptr->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED)
+			? MTRUE : MFALSE;
+	}
+	return MFALSE;
+}
+
+/**
+ *  @brief This function disable station ampdu for specific tid
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param tid     tid index
+ *  @param ra      station mac address
+ *  @return        N/A
+ */
+static INLINE void
+disable_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ra);
+	if (sta_ptr)
+		sta_ptr->ampdu_sta[tid] = BA_STREAM_NOT_ALLOWED;
+	return;
+}
+
+/**
+ *  @brief This function reset station ampdu for specific id to user setting.
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param tid     tid index
+ *  @param ra      station mac address
+ *  @return        N/A
+ */
+static INLINE void
+reset_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ra);
+	if (sta_ptr)
+		sta_ptr->ampdu_sta[tid] = priv->aggr_prio_tbl[tid].ampdu_user;
+	return;
+}
+
+/**
+ *  @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)
+{
+#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;
+	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->bss_mode == MLAN_BSS_MODE_IBSS)
+		return is_station_ampdu_allowed(priv, ptr, tid);
+	return (priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED)
+		? MTRUE : MFALSE;
+}
+
+/**
+ *  @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;
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+		if (sta_ptr) {
+			if (priv->sec_info.wapi_enabled &&
+			    !sta_ptr->wapi_key_on)
+				return MFALSE;
+		}
+	}
+#endif /* UAP_SUPPORT */
+#define TXRATE_BITMAP_INDEX_MCS0_7 2
+	return ((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)
+		&&((priv->is_data_rate_auto)
+		   || !((priv->bitmap_rates[TXRATE_BITMAP_INDEX_MCS0_7]) &
+			0x03))) ? 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(priv->adapter, ra, ptx_tbl->ra,
+			       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 */
+#ifdef STA_SUPPORT
+	if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
+		if ((!(ra[0] & 0x01)) && (priv->adapter->adhoc_11n_enabled))
+			ret = is_station_11n_enabled(priv, ra);
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+#endif /* !_MLAN_11N_H_ */
diff --git a/wlan_sd8997/mlan/mlan_11n_aggr.c b/wlan_sd8997/mlan/mlan_11n_aggr.c
new file mode 100644
index 0000000..e783598
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11n_aggr.c
@@ -0,0 +1,597 @@
+/** @file mlan_11n_aggr.c
+ *
+ *  @brief This file contains functions for 11n Aggregation.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.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(pmadapter, amsdu_buf, data, (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(pmadapter, amsdu_buf + amsdu_buf_offset, &snap, LLC_SNAP_LEN);
+	amsdu_buf_offset += LLC_SNAP_LEN;
+
+	memcpy(pmadapter, amsdu_buf + amsdu_buf_offset, data + 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 };
+
+	ENTER();
+
+	data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+	total_pkt_len = pmbuf->data_len;
+
+	/* Sanity test */
+	if (total_pkt_len > max_rx_data_size) {
+		PRINTM(MERROR, "Total packet length greater than tx buffer"
+		       " size %d\n", total_pkt_len);
+		goto done;
+	}
+
+	pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len);
+
+	while (total_pkt_len >= hdr_len) {
+		prx_pkt = (RxPacketHdr_t *)data;
+		/* Length will be in network format, change it to host */
+		pkt_len = mlan_ntohs((*(t_u16 *)(data + (2 *
+							 MLAN_MAC_ADDR_LENGTH))));
+		if (pkt_len > total_pkt_len) {
+			PRINTM(MERROR,
+			       "Error in packet length: total_pkt_len = %d, pkt_len = %d\n",
+			       total_pkt_len, pkt_len);
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+
+		pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
+			(4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;
+
+		total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);
+
+		if (memcmp(pmadapter, &prx_pkt->rfc1042_hdr,
+			   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
+			memmove(pmadapter, data + LLC_SNAP_LEN, data, (2 *
+								       MLAN_MAC_ADDR_LENGTH));
+			data += LLC_SNAP_LEN;
+			pkt_len += sizeof(Eth803Hdr_t) - LLC_SNAP_LEN;
+		} else {
+			*(t_u16 *)(data + (2 * MLAN_MAC_ADDR_LENGTH))
+				= (t_u16)0;
+			pkt_len += sizeof(Eth803Hdr_t);
+		}
+		daggr_mbuf =
+			wlan_alloc_mlan_buffer(pmadapter,
+					       pkt_len + MLAN_NET_IP_ALIGN, 0,
+					       MOAL_ALLOC_MLAN_BUFFER);
+		if (daggr_mbuf == MNULL) {
+			PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		daggr_mbuf->data_offset += MLAN_NET_IP_ALIGN;
+		daggr_mbuf->bss_index = pmbuf->bss_index;
+		daggr_mbuf->buf_type = pmbuf->buf_type;
+		daggr_mbuf->data_len = pkt_len;
+		daggr_mbuf->in_ts_sec = pmbuf->in_ts_sec;
+		daggr_mbuf->in_ts_usec = pmbuf->in_ts_usec;
+		daggr_mbuf->pparent = pmbuf;
+		daggr_mbuf->priority = pmbuf->priority;
+		memcpy(pmadapter, daggr_mbuf->pbuf + daggr_mbuf->data_offset,
+		       data, pkt_len);
+
+#ifdef UAP_SUPPORT
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			ret = wlan_uap_recv_packet(priv, daggr_mbuf);
+		} else {
+#endif /* UAP_SUPPORT */
+		/** send EAPOL from AMSDU pkt to firmware */
+			if (priv->sec_info.ewpa_enabled &&
+			    (!memcmp
+			     (pmadapter,
+			      daggr_mbuf->pbuf + daggr_mbuf->data_offset +
+			      MLAN_ETHER_PKT_TYPE_OFFSET, eapol_type,
+			      sizeof(eapol_type)))) {
+				ret = wlan_prepare_cmd(priv,
+						       HostCmd_CMD_802_11_EAPOL_PKT,
+						       0, 0, MNULL, daggr_mbuf);
+				if (ret == MLAN_STATUS_SUCCESS)
+					wlan_recv_event(priv,
+							MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+							MNULL);
+				wlan_free_mlan_buffer(pmadapter, daggr_mbuf);
+				data += pkt_len + pad;
+				continue;
+			}
+	/**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;
+		case MLAN_STATUS_SUCCESS:
+			wlan_recv_packet_complete(pmadapter, daggr_mbuf, ret);
+			break;
+		default:
+			break;
+		}
+
+		data += pkt_len + pad;
+	}
+
+done:
+	priv->msdu_in_rx_amsdu_cnt += pmbuf->use_count;
+	priv->amsdu_rx_cnt++;
+    /** we should free the aggr buffer after deaggr */
+	wlan_free_mlan_buffer(pmadapter, pmbuf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Aggregate multiple packets into one single AMSDU packet
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param pra_list Pointer to the RA List table containing the pointers
+ *                  to packets.
+ *  @param headroom Any interface specific headroom that may be need. TxPD
+ *                  will be formed leaving this headroom.
+ *  @param ptrindex Pointer index
+ *
+ *  @return     Final packet size or MLAN_STATUS_FAILURE
+ */
+int
+wlan_11n_aggregate_pkt(mlan_private *priv, raListTbl *pra_list,
+		       int headroom, int ptrindex)
+{
+	int pkt_size = 0;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_buffer *pmbuf_aggr, *pmbuf_src;
+	t_u8 *data;
+	int pad = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	mlan_tx_param tx_param;
+#ifdef STA_SUPPORT
+	TxPD *ptx_pd = MNULL;
+#endif
+	t_u32 max_amsdu_size = MIN(pra_list->max_amsdu, pmadapter->tx_buf_size);
+	ENTER();
+
+	PRINTM(MDAT_D, "Handling Aggr packet\n");
+
+	pmbuf_src =
+		(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+					     &pra_list->buf_head, MNULL, MNULL);
+	if (pmbuf_src) {
+		pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter,
+						    pmadapter->tx_buf_size, 0,
+						    MOAL_MALLOC_BUFFER);
+		if (!pmbuf_aggr) {
+			PRINTM(MERROR, "Error allocating mlan_buffer\n");
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		data = pmbuf_aggr->pbuf + headroom;
+		pmbuf_aggr->bss_index = pmbuf_src->bss_index;
+		pmbuf_aggr->buf_type = pmbuf_src->buf_type;
+		pmbuf_aggr->priority = pmbuf_src->priority;
+		pmbuf_aggr->pbuf = data;
+		pmbuf_aggr->data_offset = 0;
+		pmbuf_aggr->in_ts_sec = pmbuf_src->in_ts_sec;
+		pmbuf_aggr->in_ts_usec = pmbuf_src->in_ts_usec;
+		if (pmbuf_src->flags & MLAN_BUF_FLAG_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);
+
+		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);
+
+		pkt_size += wlan_11n_form_amsdu_pkt(pmadapter,
+						    (data + pkt_size),
+						    pmbuf_src->pbuf +
+						    pmbuf_src->data_offset,
+						    pmbuf_src->data_len, &pad);
+
+		DBG_HEXDUMP(MDAT_D, "pmbuf_src", pmbuf_src,
+			    sizeof(mlan_buffer));
+		wlan_write_data_complete(pmadapter, pmbuf_src,
+					 MLAN_STATUS_SUCCESS);
+
+		pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+						    priv->wmm.ra_list_spinlock);
+
+		if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		pmbuf_src =
+			(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &pra_list->buf_head, MNULL,
+						     MNULL);
+		priv->msdu_in_tx_amsdu_cnt++;
+	}
+
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+
+	/* Last AMSDU packet does not need padding */
+	pkt_size -= pad;
+	pmbuf_aggr->data_len = pkt_size;
+	wlan_11n_update_pktlen_amsdu_txpd(priv, pmbuf_aggr);
+	pmbuf_aggr->data_len += headroom;
+	pmbuf_aggr->pbuf = data - headroom;
+	tx_param.next_pkt_len = ((pmbuf_src) ?
+				 pmbuf_src->data_len + sizeof(TxPD) : 0);
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA,
+				     pmbuf_aggr, &tx_param);
+	switch (ret) {
+	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;
+			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:
+		pmadapter->data_sent = MFALSE;
+		PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
+		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_sd8997/mlan/mlan_11n_aggr.h b/wlan_sd8997/mlan/mlan_11n_aggr.h
new file mode 100644
index 0000000..a8ae115
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11n_aggr.h
@@ -0,0 +1,42 @@
+/** @file mlan_11n_aggr.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of 11n aggregation functionalities
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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_sd8997/mlan/mlan_11n_rxreorder.c b/wlan_sd8997/mlan/mlan_11n_rxreorder.c
new file mode 100644
index 0000000..5d9c089
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11n_rxreorder.c
@@ -0,0 +1,1632 @@
+/** @file mlan_11n_rxreorder.c
+ *
+ *  @brief This file contains the handling of RxReordering in wlan
+ *  driver.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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;
+	}
+	if (rx_reor_tbl_ptr &&
+	    wlan_is_rsn_replay_attack((mlan_private *)priv, payload,
+				      rx_reor_tbl_ptr)) {
+		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) {
+		wlan_11n_dispatch_pkt_until_start_win(priv,
+						      rx_reor_tbl_ptr, seq_num);
+	} else {
+		PRINTM(MDAT_D, "%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");
+			LEAVE();
+			return;
+		}
+
+		util_init_list((pmlan_linked_list)new_node);
+		new_node->tid = tid;
+		memcpy(pmadapter, new_node->ta, ta, MLAN_MAC_ADDR_LENGTH);
+		new_node->start_win = seq_num;
+		new_node->pkt_count = 0;
+		if (queuing_ra_based(priv)) {
+			/* TODO for adhoc */
+			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];
+			}
+			if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
+				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;
+
+		if (pmadapter->callbacks.
+		    moal_malloc(pmadapter->pmoal_handle,
+				sizeof(t_void *) * 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);
+			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;
+		new_node->ba_status = BA_STREAM_SETUP_INPROGRESS;
+
+		pmadapter->callbacks.moal_init_timer(pmadapter->pmoal_handle,
+						     &new_node->
+						     timer_context.timer,
+						     wlan_flush_data,
+						     &new_node->timer_context);
+
+		for (i = 0; i < win_size; ++i)
+			new_node->rx_reorder_ptr[i] = MNULL;
+
+		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);
+	}
+
+	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(priv->adapter, padd_ba_req, pdata_buf,
+	       sizeof(HostCmd_DS_11N_ADDBA_REQ));
+	padd_ba_req->block_ack_param_set =
+		wlan_cpu_to_le16(padd_ba_req->block_ack_param_set);
+	padd_ba_req->block_ack_tmo =
+		wlan_cpu_to_le16(padd_ba_req->block_ack_tmo);
+	padd_ba_req->ssn = wlan_cpu_to_le16(padd_ba_req->ssn);
+	padd_ba_req->add_req_result = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+  *  @brief This function check if AMPDU Rx allowed
+  *
+  *  @param priv        A pointer to mlan_private structure
+  *  @param tid         TID
+  *
+  *  @return            MTRUE/MFALSE
+  */
+t_u8
+wlan_is_addba_reject(mlan_private *priv, t_u8 tid)
+{
+#ifdef STA_SUPPORT
+	if (priv->bss_mode == MLAN_BSS_MODE_IBSS)
+		return priv->ibss_addba_reject[tid];
+#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(priv->adapter, padd_ba_rsp->peer_mac_addr,
+	       pevt_addba_req->peer_mac_addr, 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
+	    || ((priv->bss_mode == MLAN_BSS_MODE_IBSS)
+		&& !wlan_is_11n_enabled(priv, pevt_addba_req->peer_mac_addr))
+	    || ((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(priv->adapter, pdel_ba, pdata_buf, 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;
+}
+
+/**
+ *  @bref This function check PN numbers to detect replay counter attack
+ *  @param pmpriv                pointer to mlan_private
+ *  @param payload               pointer to mlan_buffer
+ *  @param rx_reor_tbl_ptr       pointer to RxReorderTbl
+ *
+ *  @return                      MTRUE/MFALSE
+ */
+t_u8
+wlan_is_rsn_replay_attack(mlan_private *pmpriv, t_void *payload,
+			  RxReorderTbl *rx_reor_tbl_ptr)
+{
+	RxPD *prx_pd = MNULL;
+	pmlan_buffer pmbuf = MNULL;
+
+	ENTER();
+
+	pmbuf = (pmlan_buffer)payload;
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+
+	if (!(prx_pd->flags & RXPD_FLAG_PN_CHECK_SUPPORT)) {
+		LEAVE();
+		return MFALSE;
+	}
+
+	if ((prx_pd->hi_rx_count32 == rx_reor_tbl_ptr->hi_curr_rx_count32 &&
+	     prx_pd->lo_rx_count16 <= rx_reor_tbl_ptr->lo_curr_rx_count16)
+	    || (rx_reor_tbl_ptr->hi_curr_rx_count32 != 0xffffffff &&
+		prx_pd->hi_rx_count32 < rx_reor_tbl_ptr->hi_curr_rx_count32)) {
+		PRINTM(MERROR,
+		       "Drop packet because of invalid PN value. Last PN:0x%x 0x%x,New PN:0x%x 0x%x\n",
+		       rx_reor_tbl_ptr->hi_curr_rx_count32,
+		       rx_reor_tbl_ptr->lo_curr_rx_count16,
+		       prx_pd->hi_rx_count32, prx_pd->lo_rx_count16);
+		LEAVE();
+		return MTRUE;
+	}
+
+	rx_reor_tbl_ptr->lo_curr_rx_count16 = prx_pd->lo_rx_count16;
+	rx_reor_tbl_ptr->hi_curr_rx_count32 = prx_pd->hi_rx_count32;
+
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @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;
+				ra_list->ba_packet_threshold =
+					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(MERROR, "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(priv->adapter, delba.peer_mac_addr, event->peer_mac_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	delba.del_ba_param_set |= (t_u16)event->tid << DELBA_TID_POS;
+	delba.del_ba_param_set |=
+		(t_u16)event->origninator << DELBA_INITIATOR_POS;
+	delba.reason_code = REASON_CODE_STA_TIMEOUT;
+	wlan_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, MNULL, &delba);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function cleans up reorder tbl
+ *
+ *  @param priv     A pointer to mlan_private
+ *
+ *  @return         N/A
+ */
+void
+wlan_11n_cleanup_reorder_tbl(mlan_private *priv)
+{
+	RxReorderTbl *del_tbl_ptr;
+
+	ENTER();
+
+	while ((del_tbl_ptr = (RxReorderTbl *)
+		util_peek_list(priv->adapter->pmoal_handle,
+			       &priv->rx_reorder_tbl_ptr,
+			       priv->adapter->callbacks.moal_spin_lock,
+			       priv->adapter->callbacks.moal_spin_unlock))) {
+		wlan_11n_delete_rxreorder_tbl_entry(priv, del_tbl_ptr);
+	}
+
+	util_init_list((pmlan_linked_list)&priv->rx_reorder_tbl_ptr);
+
+	memset(priv->adapter, priv->rx_seq, 0xff, sizeof(priv->rx_seq));
+	LEAVE();
+}
+
+/**
+ *  @brief This function handle the rxba_sync event
+ *
+ *  @param priv       A pointer to mlan_private
+ *  @param event_buf  A pointer to event buf
+ *  @param len        event_buf length
+ *  @return           N/A
+ */
+void
+wlan_11n_rxba_sync_event(mlan_private *priv, t_u8 *event_buf, t_u16 len)
+{
+	MrvlIEtypes_RxBaSync_t *tlv_rxba = (MrvlIEtypes_RxBaSync_t *)event_buf;
+	t_u16 tlv_type, tlv_len;
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+	t_u8 i, j;
+	t_u16 seq_num = 0;
+	int tlv_buf_left = len;
+	ENTER();
+
+	DBG_HEXDUMP(MEVT_D, "RXBA_SYNC_EVT", event_buf, len);
+	while (tlv_buf_left >= sizeof(MrvlIEtypes_RxBaSync_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv_rxba->header.type);
+		tlv_len = wlan_le16_to_cpu(tlv_rxba->header.len);
+		if (tlv_type != TLV_TYPE_RXBA_SYNC) {
+			PRINTM(MERROR, "Wrong TLV id=0x%x\n", tlv_type);
+			goto done;
+		}
+		tlv_rxba->seq_num = wlan_le16_to_cpu(tlv_rxba->seq_num);
+		tlv_rxba->bitmap_len = wlan_le16_to_cpu(tlv_rxba->bitmap_len);
+		PRINTM(MEVENT, MACSTR " tid=%d seq_num=%d bitmap_len=%d\n",
+		       MAC2STR(tlv_rxba->mac), tlv_rxba->tid, tlv_rxba->seq_num,
+		       tlv_rxba->bitmap_len);
+		rx_reor_tbl_ptr =
+			wlan_11n_get_rxreorder_tbl(priv, tlv_rxba->tid,
+						   tlv_rxba->mac);
+		if (!rx_reor_tbl_ptr) {
+			PRINTM(MEVENT, "Can not find rx_reorder_tbl\n");
+			goto done;
+		}
+		if (rx_reor_tbl_ptr->force_no_drop) {
+			PRINTM(MEVENT, "Ignore RXBA_SYNC_EVT in resume\n");
+			goto done;
+		}
+		for (i = 0; i < tlv_rxba->bitmap_len; i++) {
+			for (j = 0; j < 8; j++) {
+				if (tlv_rxba->bitmap[i] & (1 << j)) {
+					seq_num =
+						(tlv_rxba->seq_num + i * 8 +
+						 j) & (MAX_TID_VALUE - 1);
+					PRINTM(MEVENT,
+					       "Fw dropped packet, seq=%d start_win=%d, win_size=%d\n",
+					       seq_num,
+					       rx_reor_tbl_ptr->start_win,
+					       rx_reor_tbl_ptr->win_size);
+					if (MLAN_STATUS_SUCCESS !=
+					    mlan_11n_rxreorder_pkt(priv,
+								   seq_num,
+								   tlv_rxba->
+								   tid,
+								   tlv_rxba->
+								   mac, 0,
+								   (t_void *)
+								   RX_PKT_DROPPED_IN_FW))
+					{
+						PRINTM(MERROR,
+						       "Fail to handle dropped packet, seq=%d\n",
+						       seq_num);
+					}
+				}
+			}
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv_rxba =
+			(MrvlIEtypes_RxBaSync_t *)((t_u8 *)tlv_rxba + tlv_len +
+						   sizeof(MrvlIEtypesHeader_t));
+	}
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function cleans up reorder tbl for specific station
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ta       ta to find in reordering table
+ *  @return         N/A
+ */
+void
+wlan_cleanup_reorder_tbl(mlan_private *priv, t_u8 *ta)
+{
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+	t_u8 i;
+	ENTER();
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, i, ta);
+		if (rx_reor_tbl_ptr)
+			wlan_11n_delete_rxreorder_tbl_entry(priv,
+							    rx_reor_tbl_ptr);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function will set force_no_drop flag in rxreorder_tbl.
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param flag    MTRUE/MFALSE
+ *
+ *  @return        N/A
+ */
+void
+wlan_set_rxreorder_tbl_no_drop_flag(mlan_private *priv, t_u8 flag)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		rx_reor_tbl_ptr->force_no_drop = flag;
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param flag         MTRUE/MFALSE
+ *  @return             N/A
+ */
+void
+wlan_update_rxreorder_tbl(pmlan_adapter pmadapter, t_u8 flag)
+{
+	t_u8 i;
+	pmlan_private priv = MNULL;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			wlan_set_rxreorder_tbl_no_drop_flag(priv, flag);
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief This function will flush the data  in rxreorder_tbl.
+ *  	   which has flush_data flag on.
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return        N/A
+ */
+void
+wlan_flush_priv_rxreorder_tbl(mlan_private *priv)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		if (rx_reor_tbl_ptr->flush_data) {
+			rx_reor_tbl_ptr->flush_data = MFALSE;
+			wlan_start_flush_data(priv, rx_reor_tbl_ptr);
+		}
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @return             N/A
+ */
+void
+wlan_flush_rxreorder_tbl(pmlan_adapter pmadapter)
+{
+	t_u8 i;
+	pmlan_private priv = MNULL;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			wlan_flush_priv_rxreorder_tbl(priv);
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_win_size based on coex flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param coex_flag    coex flag
+ *
+ *  @return             N/A
+ */
+void
+wlan_update_ampdu_rxwinsize(pmlan_adapter pmadapter, t_u8 coex_flag)
+{
+	t_u8 i;
+	t_u32 rx_win_size = 0;
+	pmlan_private priv = MNULL;
+
+	ENTER();
+	if (!pmadapter->coex_rx_winsize) {
+		LEAVE();
+		return;
+	}
+	PRINTM(MEVENT, "Update rxwinsize %d\n", coex_flag);
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			rx_win_size = priv->add_ba_param.rx_win_size;
+			if (coex_flag == MTRUE) {
+#ifdef STA_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_STA)
+					priv->add_ba_param.rx_win_size =
+						MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+					priv->add_ba_param.rx_win_size =
+						MLAN_WFD_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+				if (priv->bss_type == MLAN_BSS_TYPE_NAN)
+					priv->add_ba_param.rx_win_size =
+						MLAN_NAN_COEX_AMPDU_DEF_RXWINSIZE;
+#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 This function updates ampdu rx_win_size
+ *
+ *  @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_sd8997/mlan/mlan_11n_rxreorder.h b/wlan_sd8997/mlan/mlan_11n_rxreorder.h
new file mode 100644
index 0000000..f2394cc
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_11n_rxreorder.h
@@ -0,0 +1,109 @@
+/** @file mlan_11n_rxreorder.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of 11n RxReordering functionalities
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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
+t_u8 wlan_is_rsn_replay_attack(mlan_private *pmpriv, t_void *payload,
+			       RxReorderTbl *rx_reor_tbl_ptr);
+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_sd8997/mlan/mlan_cfp.c b/wlan_sd8997/mlan/mlan_cfp.c
new file mode 100644
index 0000000..404dc23
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_cfp.c
@@ -0,0 +1,3104 @@
+/**
+ * @file mlan_cfp.c
+ *
+ *  @brief This file contains WLAN client mode channel, frequency and power
+ *  related code
+ *
+ *  (C) Copyright 2009-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/*************************************************************
+Change Log:
+    04/16/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_join.h"
+#include "mlan_main.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/** 100mW */
+#define WLAN_TX_PWR_DEFAULT     20
+/** 100mW */
+#define WLAN_TX_PWR_00_DEFAULT      20
+/** 100mW */
+#define WLAN_TX_PWR_US_DEFAULT      20
+/** 100mW */
+#define WLAN_TX_PWR_JP_BG_DEFAULT   20
+/** 200mW */
+#define WLAN_TX_PWR_JP_A_DEFAULT    23
+/** 100mW */
+#define WLAN_TX_PWR_FR_100MW        20
+/** 10mW */
+#define WLAN_TX_PWR_FR_10MW         10
+/** 100mW */
+#define WLAN_TX_PWR_EMEA_DEFAULT    20
+/** 2000mW */
+#define WLAN_TX_PWR_CN_2000MW       33
+/** 200mW */
+#define WLAN_TX_PWR_200MW   23
+/** 1000mW */
+#define WLAN_TX_PWR_1000MW   30
+/** 30mW */
+#define WLAN_TX_PWR_SP_30MW   14
+/** 60mW */
+#define WLAN_TX_PWR_SP_60MW   17
+/** 25mW */
+#define WLAN_TX_PWR_25MW   14
+/** 250mW */
+#define WLAN_TX_PWR_250MW   24
+
+/** Region code mapping */
+typedef struct _country_code_mapping {
+    /** Region */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+    /** Code for B/G CFP table */
+	t_u8 cfp_code_bg;
+    /** Code for A CFP table */
+	t_u8 cfp_code_a;
+} country_code_mapping_t;
+
+#define EU_CFP_CODE_BG  0x30
+#define EU_CFP_CODE_A   0x30
+
+/** Region code mapping table */
+static country_code_mapping_t country_code_mapping[] = {
+	{"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    */
+};
+
+/** 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"
+};
+
+/**
+ * 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: USA FCC/Canada IC */
+static chan_freq_power_t channel_freq_power_US_BG[] = {
+	{1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Europe ETSI/China */
+static chan_freq_power_t channel_freq_power_EU_BG[] = {
+	{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
+	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPNFE_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE}
+};
+
+/** Band : 'B/G', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR_BG[] = {
+	{1, 2412, WLAN_TX_PWR_1000MW, MFALSE},
+	{2, 2417, WLAN_TX_PWR_1000MW, MFALSE},
+	{3, 2422, WLAN_TX_PWR_1000MW, MFALSE},
+	{4, 2427, WLAN_TX_PWR_1000MW, MFALSE},
+	{5, 2432, WLAN_TX_PWR_1000MW, MFALSE},
+	{6, 2437, WLAN_TX_PWR_1000MW, MFALSE},
+	{7, 2442, WLAN_TX_PWR_1000MW, MFALSE},
+	{8, 2447, WLAN_TX_PWR_1000MW, MFALSE},
+	{9, 2452, WLAN_TX_PWR_1000MW, MFALSE},
+	{10, 2457, WLAN_TX_PWR_1000MW, MFALSE},
+	{11, 2462, WLAN_TX_PWR_1000MW, MFALSE},
+	{12, 2467, WLAN_TX_PWR_1000MW, MFALSE},
+	{13, 2472, WLAN_TX_PWR_1000MW, MFALSE},
+};
+
+/** Band : 'B/G', Region: Special */
+static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
+	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
+};
+
+/**
+ * The 2.4GHz CFP tables
+ */
+static cfp_table_t cfp_table_BG[] = {
+	{
+	 0x01,			/* Brazil */
+	 channel_freq_power_BR_BG,
+	 NELEMENTS(channel_freq_power_BR_BG),
+	 },
+	{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 FCC */
+
+/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
+/** Band: 'A', Region: USA FCC */
+static chan_freq_power_t channel_freq_power_A[] = {
+	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Region: Canada IC */
+static chan_freq_power_t channel_freq_power_CAN_A[] = {
+	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Region: Europe ETSI */
+static chan_freq_power_t channel_freq_power_EU_A[] = {
+	{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
+	{165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE}
+};
+
+/** Band: 'A', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN_A[] = {
+	{36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE}
+};
+
+/** Band: 'A', Region: China */
+static chan_freq_power_t channel_freq_power_CN_A[] = {
+	{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
+	{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
+	{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
+	{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
+	{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
+	{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
+	{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
+	{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
+	{149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE},
+	{165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE}
+};
+
+/** Band: 'A', NULL */
+static chan_freq_power_t channel_freq_power_NULL_A[] = {
+};
+
+/** Band: 'A', Region: Spain/Austria/Brazil */
+static chan_freq_power_t channel_freq_power_SPN2_A[] = {
+	{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
+	{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
+	{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
+	{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
+	{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
+	{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
+	{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
+	{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR1_A[] = {
+	{100, 5500, WLAN_TX_PWR_250MW, MTRUE},
+	{104, 5520, WLAN_TX_PWR_250MW, MTRUE},
+	{108, 5540, WLAN_TX_PWR_250MW, MTRUE},
+	{112, 5560, WLAN_TX_PWR_250MW, MTRUE},
+	{116, 5580, WLAN_TX_PWR_250MW, MTRUE},
+	{120, 5600, WLAN_TX_PWR_250MW, MTRUE},
+	{124, 5620, WLAN_TX_PWR_250MW, MTRUE},
+	{128, 5640, WLAN_TX_PWR_250MW, MTRUE},
+	{132, 5660, WLAN_TX_PWR_250MW, MTRUE},
+	{136, 5680, WLAN_TX_PWR_250MW, MTRUE},
+	{140, 5700, WLAN_TX_PWR_250MW, MTRUE},
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR2_A[] = {
+	{149, 5745, WLAN_TX_PWR_1000MW, MFALSE},
+	{153, 5765, WLAN_TX_PWR_1000MW, MFALSE},
+	{157, 5785, WLAN_TX_PWR_1000MW, MFALSE},
+	{161, 5805, WLAN_TX_PWR_1000MW, MFALSE},
+	{165, 5825, WLAN_TX_PWR_1000MW, MFALSE}
+};
+
+/** Band: 'A', Region: Russia */
+static chan_freq_power_t channel_freq_power_RU_A[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{132, 5660, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{136, 5680, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{140, 5700, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+};
+
+/** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+};
+
+/** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
+static chan_freq_power_t channel_freq_power_lower_middle_band[] = {
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE},
+};
+
+/** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
+static chan_freq_power_t channel_freq_power_upper_middle_band[] = {
+	{100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE},
+	{140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE},
+};
+
+/** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_high_band[] = {
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
+ * High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_high_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
+};
+
+/** Band: 'A', Code: 6, Low band (5150-5250 MHz) and
+ * mid low (5260-5320) and High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_middle_high_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
+};
+
+/**
+ * The 5GHz CFP tables
+ */
+static cfp_table_t cfp_table_A[] = {
+	{0x1,			/* Low band (5150-5250 MHz) channels */
+	 channel_freq_power_low_band,
+	 NELEMENTS(channel_freq_power_low_band)
+	 },
+	{0x2,			/* Lower middle band (5250-5350 MHz) channels */
+	 channel_freq_power_lower_middle_band,
+	 NELEMENTS(channel_freq_power_lower_middle_band)
+	 },
+	{0x3,			/* Upper middle band (5470-5725 MHz) channels */
+	 channel_freq_power_upper_middle_band,
+	 NELEMENTS(channel_freq_power_upper_middle_band)
+	 },
+	{0x4,			/* High band (5725-5850 MHz) channels */
+	 channel_freq_power_high_band,
+	 NELEMENTS(channel_freq_power_high_band)
+	 },
+	{0x5,			/* Low band (5150-5250 MHz) and
+				   High band (5725-5850 MHz) channels */
+	 channel_freq_power_low_high_band,
+	 NELEMENTS(channel_freq_power_low_high_band)
+	 },
+	{0x6,			/* Low band (5150-5250 MHz)
+				   Mid band (5260-5320) and
+				   High band (5725-5850 MHz) channels */
+	 channel_freq_power_low_middle_high_band,
+	 NELEMENTS(channel_freq_power_low_middle_high_band)
+	 },
+	{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),
+	 },
+	{0x10,			/* US FCC */
+	 channel_freq_power_A,
+	 NELEMENTS(channel_freq_power_A),
+	 },
+	{0x20,			/* CANADA IC */
+	 channel_freq_power_CAN_A,
+	 NELEMENTS(channel_freq_power_CAN_A),
+	 },
+	{0x30,			/* EU */
+	 channel_freq_power_EU_A,
+	 NELEMENTS(channel_freq_power_EU_A),
+	 },
+	{0x40,			/* JAPAN */
+	 channel_freq_power_JPN_A,
+	 NELEMENTS(channel_freq_power_JPN_A),
+	 },
+	{0x41,			/* JAPAN */
+	 channel_freq_power_JPN_A,
+	 NELEMENTS(channel_freq_power_JPN_A),
+	 },
+	{0x50,			/* China */
+	 channel_freq_power_CN_A,
+	 NELEMENTS(channel_freq_power_CN_A),
+	 },
+	{0xfe,			/* JAPAN */
+	 channel_freq_power_NULL_A,
+	 NELEMENTS(channel_freq_power_NULL_A),
+	 },
+	{0xff,			/* Special */
+	 channel_freq_power_JPN_A,
+	 NELEMENTS(channel_freq_power_JPN_A),
+	 },
+/* Add new region here */
+};
+
+/** Number of the CFP tables for 5GHz */
+#define MLAN_CFP_TABLE_SIZE_A   (NELEMENTS(cfp_table_A))
+
+enum {
+	RATEID_DBPSK1Mbps,	//(0)
+	RATEID_DQPSK2Mbps,	//(1)
+	RATEID_CCK5_5Mbps,	//(2)
+	RATEID_CCK11Mbps,	//(3)
+	RATEID_CCK22Mbps,	//(4)
+	RATEID_OFDM6Mbps,	//(5)
+	RATEID_OFDM9Mbps,	//(6)
+	RATEID_OFDM12Mbps,	//(7)
+	RATEID_OFDM18Mbps,	//(8)
+	RATEID_OFDM24Mbps,	//(9)
+	RATEID_OFDM36Mbps,	//(10)
+	RATEID_OFDM48Mbps,	//(11)
+	RATEID_OFDM54Mbps,	//(12)
+	RATEID_OFDM72Mbps,	//(13)
+};
+
+static const t_u8 rateUnit_500Kbps[] = {
+	(10 / 5),		/* 1Mbps */
+	(20 / 5),		/* 2Mbps */
+
+	(55 / 5),		/* 5.5Mbps */
+	(110 / 5),		/* 11Mbps */
+	(10 / 5),		/* 22Mbps, intentionally set to 1Mbps because it's not available */
+
+	(60 / 5),		/* 6Mbps */
+	(90 / 5),		/* 9Mbps */
+	(120 / 5),		/* 12Mbps */
+	(180 / 5),		/* 18Mbps */
+	(240 / 5),		/* 24Mbps */
+	(360 / 5),		/* 36Mbps */
+	(480 / 5),		/* 48Mbps */
+	(540 / 5),		/* 54Mbps */
+	(60 / 5),		/* 72Mbps  intentionally set to 6Mbps because it's not available */
+};
+
+typedef struct _rate_map {
+    /** Rate, in 0.5Mbps */
+	t_u32 rate;
+    /** Mrvl rate id, refer to RATEID_XXX in FW */
+	t_u32 id;
+    /** nss: 0-nss1, 1-nss2 */
+	t_u8 nss;
+} rate_map;
+
+/** If user configure to 1x1 or we found peer device only support 1x1,
+ * then we need skip the nss1 part when map to Mrvl rate.
+ */
+const rate_map rate_map_table_2x2[] = {
+	/* LG <--> Mrvl rate idx */
+	{2, 0, 0},		//RATEID_DBPSK1Mbps
+	{4, 1, 0},		//RATEID_DQPSK2Mbps
+	{11, 2, 0},		//RATEID_CCK5_5Mbps
+	{22, 3, 0},		//RATEID_CCK11Mbps
+	{44, 4, 0},		//RATEID_CCK22Mbps
+	{12, 5, 0},		//RATEID_OFDM6Mbps
+	{18, 6, 0},		//RATEID_OFDM9Mbps
+	{24, 7, 0},		//RATEID_OFDM12Mbps
+	{36, 8, 0},		//RATEID_OFDM18Mbps
+	{48, 9, 0},		//RATEID_OFDM24Mbps
+	{72, 10, 0},		//RATEID_OFDM36Mbps
+	{96, 11, 0},		//RATEID_OFDM48Mbps
+	{108, 12, 0},		//RATEID_OFDM54Mbps
+	{144, 13, 0},		//RATEID_OFDM72Mbps
+
+	/* HT bw20 <--> Mrvl rate idx - nss2 */
+	{26, 22, 1},		//RATEID_MCS8_13Mbps
+	{52, 23, 1},		//RATEID_MCS9_26Mbps
+	{78, 24, 1},		//RATEID_MCS10_39Mbps
+	{104, 25, 1},		//RATEID_MCS11_52Mbps
+	{156, 26, 1},		//RATEID_MCS12_78Mbps
+	{208, 27, 1},		//RATEID_MCS13_104Mbps
+	{234, 28, 1},		//RATEID_MCS14_117Mbps
+	{260, 29, 1},		//RATEID_MCS15_130Mbps
+	/* HT bw20 <--> Mrvl rate idx - nss1 */
+	{13, 14, 0},		//RATEID_MCS0_6d5Mbps
+	{26, 15, 0},		//RATEID_MCS1_13Mbps
+	{39, 16, 0},		//RATEID_MCS2_19d5Mbps
+	{52, 17, 0},		//RATEID_MCS3_26Mbps
+	{78, 18, 0},		//RATEID_MCS4_39Mbps
+	{104, 19, 0},		//RATEID_MCS5_52Mbps
+	{117, 20, 0},		//RATEID_MCS6_58d5Mbps
+	{130, 21, 0},		//RATEID_MCS7_65Mbps
+
+	/* HT bw40<--> Mrvl rate idx - nss2 */
+	{54, 39, 1},		//RATEID_MCS8BW40_27Mbps
+	{108, 40, 1},		//RATEID_MCS9BW40_54Mbps
+	{162, 41, 1},		//RATEID_MCS10BW40_81Mbps
+	{216, 42, 1},		//RATEID_MCS11BW40_108Mbps
+	{324, 43, 1},		//RATEID_MCS12BW40_162Mbps
+	{432, 44, 1},		//RATEID_MCS13BW40_216Mbps
+	{486, 45, 1},		//RATEID_MCS14BW40_243Mbps
+	{540, 46, 1},		//RATEID_MCS15BW40_270Mbps
+	/* HT bw40<--> Mrvl rate idx - nss1 */
+	{12, 30, 0},		//RATEID_MCS32BW40_6Mbps
+	{27, 31, 0},		//RATEID_MCS0BW40_13d5Mbps
+	{54, 32, 0},		//RATEID_MCS1BW40_27Mbps
+	{81, 33, 0},		//RATEID_MCS2BW40_40d5Mbps
+	{108, 34, 0},		//RATEID_MCS3BW40_54Mbps
+	{162, 35, 0},		//RATEID_MCS4BW40_81Mbps
+	{216, 36, 0},		//RATEID_MCS5BW40_108Mbps
+	{243, 37, 0},		//RATEID_MCS6BW40_121d5Mbps
+	{270, 38, 0},		//RATEID_MCS7BW40_135Mbps
+
+	/* VHT bw20<--> Mrvl rate idx - nss2 */
+	{26, 57, 1},		//RATEID_VHT_MCS0_2SS_BW20   13    Mbps
+	{52, 58, 1},		//RATEID_VHT_MCS1_2SS_BW20   26    Mbps
+	{78, 59, 1},		//RATEID_VHT_MCS2_2SS_BW20   39    Mbps
+	{104, 60, 1},		//RATEID_VHT_MCS3_2SS_BW20   52    Mbps
+	{156, 61, 1},		//RATEID_VHT_MCS4_2SS_BW20   78    Mbps
+	{208, 62, 1},		//RATEID_VHT_MCS5_2SS_BW20   104   Mbps
+	{234, 63, 1},		//RATEID_VHT_MCS6_2SS_BW20   117   Mbps
+	{260, 64, 1},		//RATEID_VHT_MCS7_2SS_BW20   130   Mbps
+	{312, 65, 1},		//RATEID_VHT_MCS8_2SS_BW20   156   Mbps
+	{0, 66, 1},		//RATEID_VHT_MCS9_2SS_BW20   173.3 Mbps(INVALID)
+	/* VHT bw20<--> Mrvl rate idx - nss1 */
+	{13, 47, 0},		//RATEID_VHT_MCS0_1SS_BW20   6.5  Mbps
+	{26, 48, 0},		//RATEID_VHT_MCS1_1SS_BW20   13   Mbps
+	{39, 49, 0},		//RATEID_VHT_MCS2_1SS_BW20   19.5 Mbps
+	{52, 50, 0},		//RATEID_VHT_MCS3_1SS_BW20   26   Mbps
+	{78, 51, 0},		//RATEID_VHT_MCS4_1SS_BW20   39   Mbps
+	{104, 52, 0},		//RATEID_VHT_MCS5_1SS_BW20   52   Mbps
+	{117, 53, 0},		//RATEID_VHT_MCS6_1SS_BW20   58.5 Mbps
+	{130, 54, 0},		//RATEID_VHT_MCS7_1SS_BW20   65   Mbps
+	{156, 55, 0},		//RATEID_VHT_MCS8_1SS_BW20   78   Mbps
+	{0, 56, 0},		//RATEID_VHT_MCS9_1SS_BW20   86.7 Mbps(INVALID)
+
+	/* VHT bw40<--> Mrvl rate idx - nss2 */
+	{54, 77, 1},		//RATEID_VHT_MCS0_2SS_BW40   27  Mbps
+	{108, 78, 1},		//RATEID_VHT_MCS1_2SS_BW40   54  Mbps
+	{162, 79, 1},		//RATEID_VHT_MCS2_2SS_BW40   81  Mbps
+	{216, 80, 1},		//RATEID_VHT_MCS3_2SS_BW40   108 Mbps
+	{324, 81, 1},		//RATEID_VHT_MCS4_2SS_BW40   162 Mbps
+	{432, 82, 1},		//RATEID_VHT_MCS5_2SS_BW40   216 Mbps
+	{486, 83, 1},		//RATEID_VHT_MCS6_2SS_BW40   243 Mbps
+	{540, 84, 1},		//RATEID_VHT_MCS7_2SS_BW40   270 Mbps
+	{648, 85, 1},		//RATEID_VHT_MCS8_2SS_BW40   324 Mbps
+	{720, 86, 1},		//RATEID_VHT_MCS9_2SS_BW40   360 Mbps
+	/* VHT bw40<--> Mrvl rate idx - nss1 */
+	{27, 67, 0},		//RATEID_VHT_MCS0_1SS_BW40   13.5  Mbps
+	{54, 68, 0},		//RATEID_VHT_MCS1_1SS_BW40   27    Mbps
+	{81, 69, 0},		//RATEID_VHT_MCS2_1SS_BW40   40.5  Mbps
+	{108, 70, 0},		//RATEID_VHT_MCS3_1SS_BW40   54    Mbps
+	{162, 71, 0},		//RATEID_VHT_MCS4_1SS_BW40   81    Mbps
+	{216, 72, 0},		//RATEID_VHT_MCS5_1SS_BW40   108   Mbps
+	{243, 73, 0},		//RATEID_VHT_MCS6_1SS_BW40   121.5 Mbps
+	{270, 74, 0},		//RATEID_VHT_MCS7_1SS_BW40   135   Mbps
+	{324, 75, 0},		//RATEID_VHT_MCS8_1SS_BW40   162   Mbps
+	{360, 76, 0},		//RATEID_VHT_MCS9_1SS_BW40   180   Mbps
+
+	/* VHT bw80<--> Mrvl rate idx - nss2 */
+	{117, 97, 1},		//RATEID_VHT_MCS0_2SS_BW80   58.5  Mbps
+	{234, 98, 1},		//RATEID_VHT_MCS1_2SS_BW80   117   Mbps
+	{350, 99, 1},		//RATEID_VHT_MCS2_2SS_BW80   175   Mbps
+	{468, 100, 1},		//RATEID_VHT_MCS3_2SS_BW80   234   Mbps
+	{702, 101, 1},		//RATEID_VHT_MCS4_2SS_BW80   351   Mbps
+	{936, 102, 1},		//RATEID_VHT_MCS5_2SS_BW80   468   Mbps
+	{1053, 103, 1},		//RATEID_VHT_MCS6_2SS_BW80   526.5 Mbps
+	{1170, 104, 1},		//RATEID_VHT_MCS7_2SS_BW80   585   Mbps
+	{1404, 105, 1},		//RATEID_VHT_MCS8_2SS_BW80   702   Mbps
+	{1560, 106, 1},		//RATEID_VHT_MCS9_2SS_BW80   780   Mbps
+	/* VHT bw80<--> Mrvl rate idx - nss1 */
+	{58, 87, 0},		//RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3x2 could correspond to 58
+	{59, 87, 0},		//RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3*2 could correspond to 59 too
+	{117, 88, 0},		//RATEID_VHT_MCS1_1SS_BW80   58.5  Mbps
+	{175, 89, 0},		//RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could correspond to 175
+	{176, 89, 0},		//RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could correspond to 176 too
+	{234, 90, 0},		//RATEID_VHT_MCS3_1SS_BW80   117   Mbps
+	{351, 91, 0},		//RATEID_VHT_MCS4_1SS_BW80   175.5 Mbps
+	{468, 92, 0},		//RATEID_VHT_MCS5_1SS_BW80   234   Mbps
+	{526, 93, 0},		//RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could correspond to 526
+	{527, 93, 0},		//RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could correspond to 527 too
+	{585, 94, 0},		//RATEID_VHT_MCS7_1SS_BW80   292.5 Mbps
+	{702, 95, 0},		//RATEID_VHT_MCS8_1SS_BW80   351   Mbps
+	{780, 96, 0},		//RATEID_VHT_MCS9_1SS_BW80   390   Mbps
+};
+
+/** rate_map_table_1x1 is based on rate_map_table_2x2 and remove nss2 part.
+ * For the chip who only support 1x1, Mrvl rate idx define is different with 2x2 in FW
+ * We need redefine a bitrate to Mrvl rate idx table for 1x1 chip.
+  */
+const rate_map rate_map_table_1x1[] = {
+	/* LG <--> Mrvl rate idx */
+	{2, 0, 0},		//RATEID_DBPSK1Mbps
+	{4, 1, 0},		//RATEID_DQPSK2Mbps
+	{11, 2, 0},		//RATEID_CCK5_5Mbps
+	{22, 3, 0},		//RATEID_CCK11Mbps
+	{44, 4, 0},		//RATEID_CCK22Mbps
+	{12, 5, 0},		//RATEID_OFDM6Mbps
+	{18, 6, 0},		//RATEID_OFDM9Mbps
+	{24, 7, 0},		//RATEID_OFDM12Mbps
+	{36, 8, 0},		//RATEID_OFDM18Mbps
+	{48, 9, 0},		//RATEID_OFDM24Mbps
+	{72, 10, 0},		//RATEID_OFDM36Mbps
+	{96, 11, 0},		//RATEID_OFDM48Mbps
+	{108, 12, 0},		//RATEID_OFDM54Mbps
+	{144, 13, 0},		//RATEID_OFDM72Mbps
+
+	/* HT bw20 <--> Mrvl rate idx */
+	{13, 14, 0},		//RATEID_MCS0_6d5Mbps
+	{26, 15, 0},		//RATEID_MCS1_13Mbps
+	{39, 16, 0},		//RATEID_MCS2_19d5Mbps
+	{52, 17, 0},		//RATEID_MCS3_26Mbps
+	{78, 18, 0},		//RATEID_MCS4_39Mbps
+	{104, 19, 0},		//RATEID_MCS5_52Mbps
+	{117, 20, 0},		//RATEID_MCS6_58d5Mbps
+	{130, 21, 0},		//RATEID_MCS7_65Mbps
+
+	/* HT bw40<--> Mrvl rate idx */
+	{12, 22, 0},		//RATEID_MCS32BW40_6Mbps,   for 1x1 start from 22
+	{27, 23, 0},		//RATEID_MCS0BW40_13d5Mbps
+	{54, 24, 0},		//RATEID_MCS1BW40_27Mbps
+	{81, 25, 0},		//RATEID_MCS2BW40_40d5Mbps
+	{108, 26, 0},		//RATEID_MCS3BW40_54Mbps
+	{162, 27, 0},		//RATEID_MCS4BW40_81Mbps
+	{216, 28, 0},		//RATEID_MCS5BW40_108Mbps
+	{243, 29, 0},		//RATEID_MCS6BW40_121d5Mbps
+	{270, 30, 0},		//RATEID_MCS7BW40_135Mbps
+
+	/* VHT bw20<--> Mrvl rate idx */
+	{13, 31, 0},		//RATEID_VHT_MCS0_1SS_BW20   6.5  Mbps
+	{26, 32, 0},		//RATEID_VHT_MCS1_1SS_BW20   13   Mbps
+	{39, 33, 0},		//RATEID_VHT_MCS2_1SS_BW20   19.5 Mbps
+	{52, 34, 0},		//RATEID_VHT_MCS3_1SS_BW20   26   Mbps
+	{78, 35, 0},		//RATEID_VHT_MCS4_1SS_BW20   39   Mbps
+	{104, 36, 0},		//RATEID_VHT_MCS5_1SS_BW20   52   Mbps
+	{117, 37, 0},		//RATEID_VHT_MCS6_1SS_BW20   58.5 Mbps
+	{130, 38, 0},		//RATEID_VHT_MCS7_1SS_BW20   65   Mbps
+	{156, 39, 0},		//RATEID_VHT_MCS8_1SS_BW20   78   Mbps
+	{0, 40, 0},		//RATEID_VHT_MCS9_1SS_BW20   86.7 Mbps(INVALID)
+
+	/* VHT bw40<--> Mrvl rate idx */
+	{27, 41, 0},		//RATEID_VHT_MCS0_1SS_BW40   13.5  Mbps
+	{54, 42, 0},		//RATEID_VHT_MCS1_1SS_BW40   27    Mbps
+	{81, 43, 0},		//RATEID_VHT_MCS2_1SS_BW40   40.5  Mbps
+	{108, 44, 0},		//RATEID_VHT_MCS3_1SS_BW40   54    Mbps
+	{162, 45, 0},		//RATEID_VHT_MCS4_1SS_BW40   81    Mbps
+	{216, 46, 0},		//RATEID_VHT_MCS5_1SS_BW40   108   Mbps
+	{243, 47, 0},		//RATEID_VHT_MCS6_1SS_BW40   121.5 Mbps
+	{270, 48, 0},		//RATEID_VHT_MCS7_1SS_BW40   135   Mbps
+	{324, 49, 0},		//RATEID_VHT_MCS8_1SS_BW40   162   Mbps
+	{360, 50, 0},		//RATEID_VHT_MCS9_1SS_BW40   180   Mbps
+
+	/* VHT bw80<--> Mrvl rate idx */
+	{58, 51, 0},		//RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3x2 could correspond to 58
+	{59, 51, 0},		//RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3x2 could correspond to 59 too
+	{117, 52, 0},		//RATEID_VHT_MCS1_1SS_BW80   58.5  Mbps
+	{175, 53, 0},		//RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could correspond to 175
+	{176, 53, 0},		//RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could correspond to 176 too
+	{234, 54, 0},		//RATEID_VHT_MCS3_1SS_BW80   117   Mbps
+	{351, 55, 0},		//RATEID_VHT_MCS4_1SS_BW80   175.5 Mbps
+	{468, 56, 0},		//RATEID_VHT_MCS5_1SS_BW80   234   Mbps
+	{526, 57, 0},		//RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could correspond to 526
+	{527, 57, 0},		//RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could correspond to 527 too
+	{585, 58, 0},		//RATEID_VHT_MCS7_1SS_BW80   292.5 Mbps
+	{702, 59, 0},		//RATEID_VHT_MCS8_1SS_BW80   351   Mbps
+	{780, 60, 0},		//RATEID_VHT_MCS9_1SS_BW80   390   Mbps
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+/**
+ * The table to keep region code
+ */
+t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = {
+	0x10, 0x20, 0x30, 0x40, 0x41, 0x50, 0xfe, 0xff
+};
+
+/** The table to keep CFP code for BG */
+t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG] = { };
+
+/** The table to keep CFP code for A */
+t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = { 0x1, 0x2, 0x3, 0x4, 0x5 };
+
+/**
+ * The rates supported for ad-hoc B mode
+ */
+t_u8 AdhocRates_B[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
+
+/**
+ * The rates supported for ad-hoc G mode
+ */
+t_u8 AdhocRates_G[G_SUPPORTED_RATES] = {
+	0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported for ad-hoc BG mode
+ */
+t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = {
+	0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
+	0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in A mode for ad-hoc
+ */
+t_u8 AdhocRates_A[A_SUPPORTED_RATES] = {
+	0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in A mode (used for BAND_A)
+ */
+t_u8 SupportedRates_A[A_SUPPORTED_RATES] = {
+	0x0c, 0x12, 0x18, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported by the card
+ */
+t_u16 WlanDataRates[WLAN_SUPPORTED_RATES_EXT] = {
+	0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
+	0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,
+	0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75,
+	0x82, 0x0C, 0x1B, 0x36, 0x51, 0x6C, 0xA2,
+	0xD8, 0xF3, 0x10E, 0x00
+};
+
+/**
+ * The rates supported in B mode
+ */
+t_u8 SupportedRates_B[B_SUPPORTED_RATES] = {
+	0x02, 0x04, 0x0b, 0x16, 0x00
+};
+
+/**
+ * The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_G[G_SUPPORTED_RATES] = {
+	0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = {
+	0x02, 0x04, 0x0b, 0x0c, 0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
+	0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in N mode
+ */
+t_u8 SupportedRates_N[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
+
+/********************************************************
+			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 = FW_CFP_TABLE_MAX_ROWS_BG;
+				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 = FW_CFP_TABLE_MAX_ROWS_A;
+				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();
+
+	/* first clear dest dynamic blacklisted entries */
+	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();
+
+	/* Look for code in mapping table */
+	for (i = 0; i < NELEMENTS(country_code_mapping); i++) {
+		if (!memcmp(pmadapter, country_code_mapping[i].country_code,
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			*cfp_bg = country_code_mapping[i].cfp_code_bg;
+			*cfp_a = country_code_mapping[i].cfp_code_a;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	/* If still not found, look for code in EU country code table */
+	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+		if (!memcmp(pmadapter, eu_country_code_table[i],
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			*cfp_bg = EU_CFP_CODE_BG;
+			*cfp_a = EU_CFP_CODE_A;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function finds if given country code is in EU table
+ *
+ *  @param pmadapter        A pointer to mlan_adapter structure
+ *  @param country_code     Country string
+ *
+ *  @return                 MTRUE or MFALSE
+ */
+t_bool
+wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
+{
+
+	t_u8 i;
+
+	ENTER();
+
+	/* Look for code in EU country code table */
+	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+		if (!memcmp(pmadapter, eu_country_code_table[i],
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			LEAVE();
+			return MTRUE;
+		}
+	}
+
+	LEAVE();
+	return MFALSE;
+}
+
+#define BAND_MASK_5G        0x03
+#define ANTENNA_OFFSET      2
+/**
+ *   @brief This function adjust the antenna index
+ *
+ *   V16_FW_API: Bit0: ant A, Bit 1:ant B, Bit0 & Bit 1: A+B
+ *   8887: case1: 0 - 2.4G ant A,  1- 2.4G antB, 2-- 5G ant C
+ *   case2: 0 - 2.4G ant A,  1- 2.4G antB, 0x80- 5G antA, 0x81-5G ant B
+ *   @param priv 	 A pointer to mlan_private structure
+ *   @param prx_pd   A pointer to the RxPD structure
+ *
+ *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+t_u8
+wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd)
+{
+	t_u8 antenna = prx_pd->antenna;
+	if (prx_pd->antenna == 0xff)
+		return 0;
+	if ((antenna & MBIT(0)) && (antenna & MBIT(1)))
+		antenna = 2;
+	else if (antenna & MBIT(1))
+		antenna = 1;
+	else if (antenna & MBIT(0))
+		antenna = 0;
+
+	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_u8
+wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info)
+{
+	t_u8 rate_index = 0;
+	t_u8 bw = 0;
+	t_u8 nss = 0;
+	t_bool sgi_enable = 0;
+
+#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) {
+		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);
+	}
+	return rate_index;
+}
+
+#ifdef STA_SUPPORT
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief convert ht_info to rate_info
+ *
+ *  @param ht_info      ht info
+ *
+ *  @return             rate info
+ */
+t_u8
+wlan_convert_v14_rate_ht_info(t_u8 ht_info)
+{
+	t_u8 rate_info = 0;
+	rate_info = ht_info & 0x01;
+	/* band */
+	rate_info |= (ht_info & MBIT(1)) << 1;
+	/* short GI */
+	rate_info |= (ht_info & MBIT(2)) << 2;
+	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
+ *
+ *  @return                 Data rate or 0
+ */
+t_u32
+wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 tx_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 bw = 0;
+	t_u8 gi = 0;
+	ENTER();
+
+	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_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_u8 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:
+			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:
+			case BAND_B:	/* Matching BAND_B/G */
+			case BAND_G:
+			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, "wlan_get_cfp_by_band_and_channel(): cannot find "
+		       "cfp by band %d & channel %d\n", 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:
+			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:
+			case BAND_B:
+			case BAND_G:
+			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,
+		       "wlan_find_cfp_by_band_and_freq(): cannot find cfp by "
+		       "band %d & freq %d\n", 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_u8 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:
+			PRINTM(MINFO, "Infra band=%d SupportedRates_G\n",
+			       config_bands);
+			k = wlan_copy_rates(rates, k, SupportedRates_G,
+					    sizeof(SupportedRates_G));
+			break;
+		case BAND_B | BAND_G:
+		case BAND_A | BAND_B | BAND_G:
+		case BAND_A | BAND_B:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC | BAND_GAC:
+		case BAND_B | BAND_G | BAND_GN:
+		case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+			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:
+			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:
+			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:
+		case BAND_G | BAND_GN:
+		case BAND_G | BAND_GN | BAND_GAC:
+			PRINTM(MINFO, "Band: Adhoc G only\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_G,
+					    sizeof(AdhocRates_G));
+			break;
+		case BAND_B | BAND_G:
+		case BAND_B | BAND_G | BAND_GN:
+		case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+			PRINTM(MINFO, "Band: Adhoc BG\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_BG,
+					    sizeof(AdhocRates_BG));
+			break;
+		case BAND_A:
+		case BAND_AN:
+		case BAND_A | BAND_AN:
+		case BAND_A | BAND_AN | BAND_AAC:
+			PRINTM(MINFO, "Band: Adhoc A\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_A,
+					    sizeof(AdhocRates_A));
+			break;
+		}
+	}
+
+	LEAVE();
+	return k;
+}
+
+#define COUNTRY_ID_US 0
+#define COUNTRY_ID_JP 1
+#define COUNTRY_ID_CN 2
+#define COUNTRY_ID_EU 3
+typedef struct _oper_bw_chan {
+	/*non-global operating class */
+	t_u8 oper_class;
+	/*global operating class */
+	t_u8 global_oper_class;
+	/*bandwidth 0-20M 1-40M 2-80M 3-160M */
+	t_u8 bandwidth;
+	/*channel list */
+	t_u8 channel_list[13];
+} oper_bw_chan;
+
+/** oper class table for US*/
+static oper_bw_chan oper_bw_chan_us[] = {
+    /** non-Global oper class, global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 124, 0, {149, 153, 157, 161}},
+	{4, 121, 0,
+	 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144}},
+	{5, 125, 0, {149, 153, 157, 161, 165}},
+	{12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
+	{22, 116, 1, {36, 44}},
+	{23, 119, 1, {52, 60}},
+	{24, 122, 1, {100, 108, 116, 124, 132, 140}},
+	{25, 126, 1, {149, 157}},
+	{26, 126, 1, {149, 157}},
+	{27, 117, 1, {40, 48}},
+	{28, 120, 1, {56, 64}},
+	{29, 123, 1, {104, 112, 120, 128, 136, 144}},
+	{30, 127, 1, {153, 161}},
+	{31, 127, 1, {153, 161}},
+	{32, 83, 1, {1, 2, 3, 4, 5, 6, 7}},
+	{33, 84, 1, {5, 6, 7, 8, 9, 10, 11}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for EU*/
+static oper_bw_chan oper_bw_chan_eu[] = {
+    /** non-global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{5, 116, 1, {36, 44}},
+	{6, 119, 1, {52, 60}},
+	{7, 122, 1, {100, 108, 116, 124, 132}},
+	{8, 117, 1, {40, 48}},
+	{9, 120, 1, {56, 64}},
+	{10, 123, 1, {104, 112, 120, 128, 136}},
+	{11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{17, 125, 0, {149, 153, 157, 161, 165, 169}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for Japan*/
+static oper_bw_chan oper_bw_chan_jp[] = {
+    /** non-Global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48}},
+	{30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{31, 82, 0, {14}},
+	{32, 118, 0, {52, 56, 60, 64}},
+	{33, 118, 0, {52, 56, 60, 64}},
+	{34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{36, 116, 1, {36, 44}},
+	{37, 119, 1, {52, 60}},
+	{38, 119, 1, {52, 60}},
+	{39, 122, 1, {100, 108, 116, 124, 132}},
+	{40, 122, 1, {100, 108, 116, 124, 132}},
+	{41, 117, 1, {40, 48}},
+	{42, 120, 1, {56, 64}},
+	{43, 120, 1, {56, 64}},
+	{44, 123, 1, {104, 112, 120, 128, 136}},
+	{45, 123, 1, {104, 112, 120, 128, 136}},
+	{56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for China*/
+static oper_bw_chan oper_bw_chan_cn[] = {
+    /** non-Global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 125, 0, {149, 153, 157, 161, 165}},
+	{4, 116, 1, {36, 44}},
+	{5, 119, 1, {52, 60}},
+	{6, 126, 1, {149, 157}},
+	{7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/**
+ *  @brief Get non-global operaing class table according to country
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param arraysize          A pointer to table size
+ *
+ *  @return                   A pointer to oper_bw_chan
+ */
+oper_bw_chan *
+wlan_get_nonglobal_operclass_table(mlan_private *pmpriv, int *arraysize)
+{
+	t_u8 country_code[][COUNTRY_CODE_LEN] = { "US", "JP", "CN" };
+	int country_id = 0;
+	oper_bw_chan *poper_bw_chan = MNULL;
+
+	ENTER();
+
+	for (country_id = 0; country_id < 3; country_id++)
+		if (!memcmp
+		    (pmpriv->adapter, pmpriv->adapter->country_code,
+		     country_code[country_id], COUNTRY_CODE_LEN - 1))
+			break;
+	if (country_id >= 3)
+		country_id = COUNTRY_ID_US;	/*Set default to US */
+	if (wlan_is_etsi_country
+	    (pmpriv->adapter, pmpriv->adapter->country_code))
+		country_id = COUNTRY_ID_EU;
+				    /** Country in EU */
+
+	switch (country_id) {
+	case COUNTRY_ID_US:
+		poper_bw_chan = oper_bw_chan_us;
+		*arraysize = sizeof(oper_bw_chan_us);
+		break;
+	case COUNTRY_ID_JP:
+		poper_bw_chan = oper_bw_chan_jp;
+		*arraysize = sizeof(oper_bw_chan_jp);
+		break;
+	case COUNTRY_ID_CN:
+		poper_bw_chan = oper_bw_chan_cn;
+		*arraysize = sizeof(oper_bw_chan_cn);
+		break;
+	case COUNTRY_ID_EU:
+		poper_bw_chan = oper_bw_chan_eu;
+		*arraysize = sizeof(oper_bw_chan_eu);
+		break;
+	default:
+		PRINTM(MERROR, "Country not support!\n");
+		break;
+	}
+
+	LEAVE();
+	return poper_bw_chan;
+}
+
+/**
+ *  @brief Check validation of given channel and oper class
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param channel            Channel number
+ *  @param oper_class         operating class
+ *
+ *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
+				t_u8 oper_class)
+{
+	int arraysize = 0, i = 0, channum = 0;
+	oper_bw_chan *poper_bw_chan = MNULL;
+	t_u8 center_freq_idx = 0;
+	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
+
+	ENTER();
+
+	for (i = 0; i < sizeof(center_freqs); i++) {
+		if (channel == center_freqs[i]) {
+			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	if (oper_class <= 0 || oper_class > 130) {
+		PRINTM(MERROR, "Invalid operating class!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (oper_class >= 128) {
+		center_freq_idx =
+			wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
+						 CHANNEL_BW_80MHZ);
+		channel = center_freq_idx;
+	}
+	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+	if (!poper_bw_chan) {
+		PRINTM(MCMND, "Operating class table do not find!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
+		if (poper_bw_chan[i].oper_class == oper_class ||
+		    poper_bw_chan[i].global_oper_class == oper_class) {
+			for (channum = 0;
+			     channum < sizeof(poper_bw_chan[i].channel_list);
+			     channum++) {
+				if (poper_bw_chan[i].channel_list[channum] &&
+				    poper_bw_chan[i].channel_list[channum] ==
+				    channel) {
+					LEAVE();
+					return MLAN_STATUS_SUCCESS;
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMND, "Operating class %d do not match channel %d!\n",
+	       oper_class, channel);
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Get current operating class from channel and bandwidth
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param channel            Channel number
+ *  @param bw                 Bandwidth
+ *  @param oper_class         A pointer to current operating class
+ *
+ *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel, t_u8 bw,
+			 t_u8 *oper_class)
+{
+	oper_bw_chan *poper_bw_chan = MNULL;
+	t_u8 center_freq_idx = 0;
+	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
+	int i = 0, arraysize = 0, channum = 0;
+
+	ENTER();
+
+	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+	if (!poper_bw_chan) {
+		PRINTM(MCMND, "Operating class table do not find!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	for (i = 0; i < sizeof(center_freqs); i++) {
+		if (channel == center_freqs[i]) {
+			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	if (bw == BW_80MHZ) {
+		center_freq_idx =
+			wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
+						 CHANNEL_BW_80MHZ);
+		channel = center_freq_idx;
+	}
+
+	for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
+		if (poper_bw_chan[i].bandwidth == bw) {
+			for (channum = 0;
+			     channum < sizeof(poper_bw_chan[i].channel_list);
+			     channum++) {
+				if (poper_bw_chan[i].channel_list[channum] &&
+				    poper_bw_chan[i].channel_list[channum] ==
+				    channel) {
+					*oper_class =
+						poper_bw_chan[i].oper_class;
+					return MLAN_STATUS_SUCCESS;
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMND, "Operating class not find!\n");
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Add Supported operating classes IE
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param pptlv_out          A pointer to TLV to fill in
+ *  @param curr_oper_class    Current operating class
+ *
+ *  @return                   Length
+ */
+int
+wlan_add_supported_oper_class_ie(IN mlan_private *pmpriv, OUT 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(pmpriv->adapter, &poper_class->oper_class, oper_class_us,
+		       sizeof(oper_class_us));
+	} else if (country_id == COUNTRY_ID_JP) {
+		poper_class->header.len = sizeof(oper_class_jp);
+		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_jp,
+		       sizeof(oper_class_jp));
+	} else if (country_id == COUNTRY_ID_CN) {
+		poper_class->header.len = sizeof(oper_class_cn);
+		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_cn,
+		       sizeof(oper_class_cn));
+	} else if (country_id == COUNTRY_ID_EU) {
+		poper_class->header.len = sizeof(oper_class_eu);
+		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_eu,
+		       sizeof(oper_class_eu));
+	}
+	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];
+
+	ENTER();
+
+	memcpy(pmadapter, region_chan_old, pmadapter->region_channel,
+	       sizeof(pmadapter->region_channel));
+	memset(pmadapter, pmadapter->region_channel, 0,
+	       sizeof(pmadapter->region_channel));
+
+	if (band & (BAND_B | BAND_G | BAND_GN)) {
+		cfp = wlan_get_region_cfp_table(pmadapter, region,
+						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)
+			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
+					      region_chan_old[j].pcfp,
+					      region_chan_old[j].num_cfp);
+		else
+			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
+		i++;
+	}
+	if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+		cfp = wlan_get_region_cfp_table(pmadapter, region, 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
+			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 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 & MARVELL_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
+	sta_node *sta_ptr = MNULL;
+#endif
+
+	ENTER();
+
+	if (priv->adapter->hw_dev_mcs_support == HT_STREAM_MODE_2X2) {
+		rate_tbl = rate_map_table_2x2;
+		cnt = sizeof(rate_map_table_2x2) / sizeof(rate_map);
+	}
+#ifdef UAP_SUPPORT
+	if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
+		if (!dst_mac) {
+			LEAVE();
+			return mrvlRATEID;
+		}
+		sta_ptr =
+			(sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+						   &priv->sta_list,
+						   priv->adapter->callbacks.
+						   moal_spin_lock,
+						   priv->adapter->callbacks.
+						   moal_spin_unlock);
+		if (!sta_ptr) {
+			LEAVE();
+			return mrvlRATEID;
+		}
+		while (sta_ptr != (sta_node *)&priv->sta_list) {
+			if (memcmp
+			    (priv->adapter, dst_mac, sta_ptr->mac_addr,
+			     MLAN_MAC_ADDR_LENGTH)) {
+				htcap = &(sta_ptr->HTcap);
+				break;
+			}
+			sta_ptr = sta_ptr->pnext;
+		}
+	}
+#endif
+#ifdef STA_SUPPORT
+	if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+		htcap = priv->curr_bss_params.bss_descriptor.pht_cap;
+	}
+#endif
+	if (htcap) {
+		/* If user configure tx to 2x2 and peer device rx is 2x2 */
+		if (tx_mcs_supp >= 2 && htcap->ht_cap.supported_mcs_set[1])
+			skip_nss2 = MFALSE;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		if (rate_tbl[i].nss && skip_nss2)
+			continue;
+		if (rate_tbl[i].rate == IeeeMacRate) {
+			mrvlRATEID = rate_tbl[i].id;
+			break;
+		}
+	}
+
+	return mrvlRATEID;
+}
+
+/**
+ *  @brief Convert rateid in MRVL format to IEEE format
+ *
+ *  @param IeeeMacRate  Rate in terms of MRVL format
+ *
+ *  @return
+ *    Rate ID in terms of IEEE format
+ */
+t_u8
+wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)
+{
+	return rateUnit_500Kbps[rate];
+}
+
+/**
+ *  @brief	Update CFP tables and power tables from FW
+ *
+ *  @param priv		Private driver information structure
+ *  @param buf		Pointer to the buffer holding TLV data
+ *					from 0x242 command response.
+ *  @param buf_left	bufsize
+ *
+ *  @return
+ *    None
+ */
+void
+wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	MrvlIEtypesHeader_t *head;
+	t_u16 tlv;
+	t_u16 tlv_buf_len;
+	t_u16 tlv_buf_left;
+	t_u16 i;
+	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;
+	}
+	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(pmadapter, pmadapter->otp_region, data,
+			       sizeof(otp_region_info_t));
+			data += sizeof(otp_region_info_t);
+			/* Get pre-defined cfp tables corresponding to the region code
+			 * in OTP
+			 */
+			for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
+				if (cfp_table_BG[i].code ==
+				    pmadapter->otp_region->region_code) {
+					max_tx_pwr_bg =
+						(cfp_table_BG[i].cfp)->
+						max_tx_power;
+					break;
+				}
+			}
+			for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
+				if (cfp_table_A[i].code ==
+				    pmadapter->otp_region->region_code) {
+					max_tx_pwr_a =
+						(cfp_table_A[i].cfp)->
+						max_tx_power;
+					break;
+				}
+			}
+			/* Update the region code and the country code in pmadapter */
+			pmadapter->region_code =
+				pmadapter->otp_region->region_code;
+			pmadapter->country_code[0] =
+				pmadapter->otp_region->country_code[0];
+			pmadapter->country_code[1] =
+				pmadapter->otp_region->country_code[1];
+			pmadapter->country_code[2] = '\0';
+			pmadapter->domain_reg.country_code[0] =
+				pmadapter->otp_region->country_code[0];
+			pmadapter->domain_reg.country_code[1] =
+				pmadapter->otp_region->country_code[1];
+			pmadapter->domain_reg.country_code[2] = '\0';
+			pmadapter->cfp_code_bg =
+				pmadapter->otp_region->region_code;
+			pmadapter->cfp_code_a =
+				pmadapter->otp_region->region_code;
+			break;
+		case TLV_TYPE_CHAN_ATTR_CFG:
+			/* Skip adding fw cfp tables if they already exist or
+			 * if this TLV has no set data
+			 */
+			if (*data == 0)
+				break;
+			if (pmadapter->cfp_otp_bg || pmadapter->cfp_otp_a) {
+				break;
+			}
+
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       FW_CFP_TABLE_MAX_ROWS_BG *
+					       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 < FW_CFP_TABLE_MAX_ROWS_BG; 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 & MARVELL_CHANNEL_DFS)
+					(pmadapter->cfp_otp_bg +
+					 i)->passive_scan_or_radar_detect =
+			MTRUE;
+				data++;
+			}
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       FW_CFP_TABLE_MAX_ROWS_A *
+					       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 < FW_CFP_TABLE_MAX_ROWS_A; 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 & MARVELL_CHANNEL_DFS)
+					(pmadapter->cfp_otp_a +
+					 i)->passive_scan_or_radar_detect =
+			 MTRUE;
+				data++;
+			}
+			break;
+		case TLV_TYPE_POWER_TABLE:
+			/* Skip adding fw power tables if this TLV has no data or
+			 * if they already exists but force reg rule is set in the otp
+			 */
+			if (*data == 0)
+				break;
+			if (pmadapter->otp_region &&
+			    pmadapter->otp_region->force_reg &&
+			    pmadapter->tx_power_table_bg)
+				break;
+
+			/* Save the tlv data in power tables for band BG and A */
+			tmp = data;
+			i = 0;
+			while ((i < FW_CFP_TABLE_MAX_ROWS_BG *
+				FW_CFP_TABLE_MAX_COLS_BG)
+			       && (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 falied!\n");
+					break;
+				}
+			}
+			memcpy(pmadapter, pmadapter->tx_power_table_bg, data,
+			       i);
+			pmadapter->tx_power_table_bg_size = i;
+			data += i;
+			i = 0;
+			while ((i <
+				FW_CFP_TABLE_MAX_ROWS_A *
+				FW_CFP_TABLE_MAX_COLS_A)
+			       && (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(pmadapter, pmadapter->tx_power_table_a, data, i);
+			pmadapter->tx_power_table_a_size = i;
+			break;
+		default:
+			break;
+		}
+		tlv_buf += (sizeof(*head) + tlv_buf_len);
+		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
+	}
+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->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->tx_power_table_a_size = 0;
+	LEAVE();
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter, IN 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_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);
+
+	/* Get cfp table and its size corresponding to the region code */
+	cfp_bg = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
+					   BAND_G | BAND_B, &cfp_no_bg);
+	size += cfp_no_bg * sizeof(chan_freq_power_t);
+	cfp_a = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
+					  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(pmadapter, req_buf, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, &pmadapter->region_code,
+	       sizeof(pmadapter->region_code));
+	len += sizeof(pmadapter->region_code);
+	memcpy(pmadapter, req_buf + len, &pmadapter->country_code,
+	       sizeof(pmadapter->country_code));
+	len += sizeof(pmadapter->country_code);
+	if (pmadapter->otp_region) {
+		memcpy(pmadapter, req_buf + len,
+		       &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(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, cfp_bg, size);
+	len += size;
+	if (!cfp_a)
+		goto out;
+	size = cfp_no_a * sizeof(chan_freq_power_t);
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, cfp_a, 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(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+
+	/* No. of rows */
+	size = FW_CFP_TABLE_MAX_ROWS_BG;
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+
+	/* No. of cols */
+	size = pmadapter->tx_power_table_bg_size / FW_CFP_TABLE_MAX_ROWS_BG;
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, pmadapter->tx_power_table_bg,
+	       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(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+
+	/* No. of rows */
+	size = FW_CFP_TABLE_MAX_ROWS_A;
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+
+	/* No. of cols */
+	size = pmadapter->tx_power_table_a_size / FW_CFP_TABLE_MAX_ROWS_A;
+	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
+	len += sizeof(size);
+	memcpy(pmadapter, req_buf + len, pmadapter->tx_power_table_a,
+	       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_sd8997/mlan/mlan_cmdevt.c b/wlan_sd8997/mlan/mlan_cmdevt.c
new file mode 100644
index 0000000..3beeee0
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_cmdevt.c
@@ -0,0 +1,7485 @@
+/**
+ * @file mlan_cmdevt.c
+ *
+ *  @brief This file contains the handling of CMD/EVENT in MLAN
+ *
+ *  (C) Copyright 2009-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/*************************************************************
+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_11h.h"
+#include "mlan_sdio.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(IN mlan_private *pmpriv, IN cmd_ctrl_node *pcmd_node)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (pcmd_node == MNULL)
+		goto done;
+	pcmd_node->cmd_flag |= CMD_F_SCAN;
+
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &pmadapter->scan_pending_q,
+			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief Internal function used to flush the scan pending queue
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+void
+wlan_check_scan_queue(IN 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
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param reason        Reason code
+ *
+ *  @return     N/A
+ */
+t_void
+wlan_dump_info(mlan_adapter *pmadapter, t_u8 reason)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	t_u8 i;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	t_u8 j;
+	t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+#endif
+	t_u16 cmd_id, cmd_act;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	PRINTM(MERROR, "------------Dump info-----------\n", reason);
+	switch (reason) {
+	case REASON_CODE_NO_CMD_NODE:
+		pmadapter->dbg.num_no_cmd_node++;
+		PRINTM(MERROR, "No Free command node\n");
+		break;
+	case REASON_CODE_CMD_TIMEOUT:
+		PRINTM(MERROR, "Commmand Timeout\n");
+		break;
+	case REASON_CODE_CMD_TO_CARD_FAILURE:
+		PRINTM(MERROR, "Command to card failure\n");
+		break;
+	case REASON_CODE_EXT_SCAN_TIMEOUT:
+		PRINTM(MERROR, "EXT_SCAN_STATUS event Timeout\n");
+		break;
+	default:
+		break;
+	}
+	if ((reason == REASON_CODE_NO_CMD_NODE) &&
+	    (pmadapter->dbg.num_no_cmd_node > 1)) {
+		if (pmadapter->dbg.num_no_cmd_node >= 5)
+			wlan_recv_event(wlan_get_priv
+					(pmadapter, MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+		LEAVE();
+		return;
+	}
+	wlan_dump_pending_commands(pmadapter);
+	if (reason != REASON_CODE_CMD_TIMEOUT) {
+		if (!pmadapter->curr_cmd) {
+			PRINTM(MERROR, "CurCmd Empty\n");
+		} else {
+			pcmd_node = pmadapter->curr_cmd;
+			cmd_id = pmadapter->dbg.last_cmd_id[pmadapter->dbg.
+							    last_cmd_index];
+			cmd_act =
+				pmadapter->dbg.last_cmd_act[pmadapter->dbg.
+							    last_cmd_index];
+			PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
+			PRINTM(MERROR,
+			       "Current cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n",
+			       sec, usec, cmd_id, cmd_act);
+			if (pcmd_node->cmdbuf) {
+				t_u8 *pcmd_buf;
+				pcmd_buf =
+					pcmd_node->cmdbuf->pbuf +
+					pcmd_node->cmdbuf->data_offset +
+					INTF_HEADER_LEN;
+				for (i = 0; i < 16; i++)
+					PRINTM(MERROR, "%02x ", *pcmd_buf++);
+				PRINTM(MERROR, "\n");
+			}
+			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, "dbg.num_cmd_timeout = %d\n",
+	       pmadapter->dbg.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);
+	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);
+	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, "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\n",
+	       pmadapter->pm_wakeup_card_req, pmadapter->pm_wakeup_fw_try);
+	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, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
+	       pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port);
+	PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
+	       pmadapter->mp_wr_bitmap, pmadapter->curr_wr_port);
+	PRINTM(MERROR, "mp_invalid_update=%d\n", pmadapter->mp_invalid_update);
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n",
+	       pmadapter->last_recv_wr_bitmap, pmadapter->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->last_mp_wr_bitmap[i],
+		       pmadapter->last_mp_wr_ports[i],
+		       pmadapter->last_mp_wr_len[i],
+		       pmadapter->last_curr_wr_port[i]);
+		for (j = 0; j < mp_aggr_pkt_limit; j++) {
+			PRINTM(MERROR, "0x%02x ",
+			       pmadapter->last_mp_wr_info[i *
+							  mp_aggr_pkt_limit +
+							  j]);
+		}
+		PRINTM(MERROR, "\n");
+	}
+#endif
+	for (i = 0; i < pmadapter->priv_num; ++i) {
+		if (pmadapter->priv[i])
+			wlan_dump_ralist(pmadapter->priv[i]);
+	}
+	if (reason != REASON_CODE_CMD_TIMEOUT) {
+		if ((pmadapter->dbg.num_no_cmd_node >= 5)
+		    || (pmadapter->pm_wakeup_card_req &&
+			pmadapter->pm_wakeup_fw_try)
+		    || (reason == REASON_CODE_EXT_SCAN_TIMEOUT)
+			) {
+			if (pmpriv)
+				wlan_recv_event(pmpriv,
+						MLAN_EVENT_ID_DRV_DBG_DUMP,
+						MNULL);
+			else
+				wlan_recv_event(wlan_get_priv
+						(pmadapter, MLAN_BSS_ROLE_ANY),
+						MLAN_EVENT_ID_DRV_DBG_DUMP,
+						MNULL);
+		}
+	}
+	PRINTM(MERROR, "-------- Dump info End---------\n", reason);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function convert a given character to hex
+ *
+ *  @param chr        Character to be converted
+ *
+ *  @return           The converted hex if chr is a valid hex, else 0
+ */
+static t_u32
+wlan_hexval(t_u8 chr)
+{
+	if (chr >= '0' && chr <= '9')
+		return chr - '0';
+	if (chr >= 'A' && chr <= 'F')
+		return chr - 'A' + 10;
+	if (chr >= 'a' && chr <= 'f')
+		return chr - 'a' + 10;
+
+	return 0;
+}
+
+/**
+ *  @brief This function convert a given string to hex
+ *
+ *  @param a            A pointer to string to be converted
+ *
+ *  @return             The converted hex value if param a is a valid hex, else 0
+ */
+int
+wlan_atox(t_u8 *a)
+{
+	int i = 0;
+
+	ENTER();
+
+	while (wlan_isxdigit(*a))
+		i = i * 16 + wlan_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief This function parse cal data from ASCII to hex
+ *
+ *  @param src          A pointer to source data
+ *  @param len          Source data length
+ *  @param dst          A pointer to a buf to store the parsed data
+ *
+ *  @return             The parsed hex data length
+ */
+static t_u32
+wlan_parse_cal_cfg(t_u8 *src, t_size len, t_u8 *dst)
+{
+	t_u8 *ptr;
+	t_u8 *dptr;
+
+	ENTER();
+	ptr = src;
+	dptr = dst;
+
+	while (ptr - src < len) {
+		if (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) {
+			ptr++;
+			continue;
+		}
+
+		if (wlan_isxdigit(*ptr)) {
+			*dptr++ = wlan_atox(ptr);
+			ptr += 2;
+		} else {
+			ptr++;
+		}
+	}
+	LEAVE();
+	return dptr - dst;
+}
+
+/**
+ *  @brief This function finds first occurrence of a char in a string
+ *
+ *  @param s            A pointer to the string to be searched
+ *  @param c            The character to search for
+ *
+ *  @return             Location of the first occurrence of the char
+ *                      if found, else NULL
+ */
+t_u8 *
+wlan_strchr(t_u8 *s, int c)
+{
+	t_u8 *pos = s;
+	while (*pos != '\0') {
+		if (*pos == (t_u8)c)
+			return pos;
+		pos++;
+	}
+	return MNULL;
+}
+
+#define CFG_TYPE_HOSTCMD        0
+#define CFG_TYPE_DPDFILE          1
+
+/**
+ *    @brief WOAL parse ASCII format raw data to hex format
+ *
+ *    @param pmpriv       MOAL handle
+ *    @param cfg_type     Conf file type
+ *    @param data         Source data
+ *    @param size         data length
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+wlan_process_hostcmd_cfg(IN pmlan_private pmpriv, IN t_u16 cfg_type,
+			 IN t_u8 *data, IN 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 = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+	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, MLAN_SIZE_OF_CMD_BUFFER);
+			ptr = buf;
+			start_raw = MFALSE;
+			pos++;
+			continue;
+		}
+
+		if (start_raw == MFALSE) {
+			intf_s = wlan_strchr(pos, '=');
+			if (intf_s)
+				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) {
+					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_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             N/A
+ */
+static void
+wlan_init_cmd_node(IN pmlan_private pmpriv,
+		   IN cmd_ctrl_node *pcmd_node,
+		   IN t_u32 cmd_oid,
+		   IN t_void *pioctl_buf, IN t_void *pdata_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (pcmd_node == MNULL) {
+		LEAVE();
+		return;
+	}
+	pcmd_node->priv = pmpriv;
+	pcmd_node->cmd_oid = cmd_oid;
+	pcmd_node->pioctl_buf = pioctl_buf;
+	pcmd_node->pdata_buf = pdata_buf;
+
+	pcmd_node->cmdbuf = pcmd_node->pmbuf;
+
+	/* 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;
+	pcmd_node->cmdbuf->data_offset += INTF_HEADER_LEN;
+
+	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_oid = 0;
+	pcmd_node->cmd_flag = 0;
+	pcmd_node->pioctl_buf = MNULL;
+	pcmd_node->pdata_buf = MNULL;
+
+	if (pcmd_node->respbuf) {
+		wlan_free_mlan_buffer(pmadapter, pcmd_node->respbuf);
+		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(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *resp, IN 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(pmpriv->adapter, misc->param.hostcmd.cmd, (void *)resp,
+		       size);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function sends host command to firmware.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_host_cmd(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_cmd *pcmd_ptr = (mlan_ds_misc_cmd *)pdata_buf;
+
+	ENTER();
+
+	/* Copy the HOST command to command buffer */
+	memcpy(pmpriv->adapter, (void *)cmd, pcmd_ptr->cmd,
+	       MIN(MRVDRV_SIZE_OF_CMD_BUFFER, pcmd_ptr->len));
+	PRINTM(MINFO, "Host command size = %d\n", pcmd_ptr->len);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN mlan_private *pmpriv, IN 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 DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+
+	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);
+	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);
+
+	if (pcmd->command == HostCmd_CMD_HOST_CLOCK_CFG) {
+		HostCmd_DS_HOST_CLOCK_CFG *host_clock =
+			(HostCmd_DS_HOST_CLOCK_CFG *) & pcmd->params.
+			host_clock_cfg;
+		pmadapter->callbacks.moal_get_host_time_ns(&pmadapter->d1);
+		PRINTM(MINFO, "WIFI_TS: d1: %llu\n", pmadapter->d1);
+		/* Overwrite the time to be given to FW */
+		host_clock->time = wlan_cpu_to_le64(pmadapter->d1);
+	}
+
+	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\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));
+	DBG_HEXDUMP(MCMD_D, "DNLD_CMD", (t_u8 *)pcmd, cmd_size);
+
+	/* Send the command to lower layer */
+
+	pcmd_node->cmdbuf->data_offset -= INTF_HEADER_LEN;
+	pcmd_node->cmdbuf->data_len += INTF_HEADER_LEN;
+	/* Extra header for SDIO is added here */
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_CMD,
+				     pcmd_node->cmdbuf, MNULL);
+
+	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,
+			      MRVDRV_TIMER_10S * 2);
+
+	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;
+	t_u16 cmd_len = 0;
+	opt_sleep_confirm_buffer *sleep_cfm_buf =
+		(opt_sleep_confirm_buffer *)(pmadapter->psleep_cfm->pbuf +
+					     pmadapter->psleep_cfm->
+					     data_offset);
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	if (!pmpriv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	cmd_len = sizeof(OPT_Confirm_Sleep);
+	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 */
+
+	pmadapter->psleep_cfm->data_len = cmd_len + INTF_HEADER_LEN;
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_CMD,
+				     pmadapter->psleep_cfm, MNULL);
+
+	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 */
+
+#define NUM_SC_PER_LINE         16
+		if (++i % NUM_SC_PER_LINE == 0)
+			PRINTM(MEVENT, "+\n");
+		else
+			PRINTM(MEVENT, "+");
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Event handler
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param event_id Event ID
+ *  @param pmevent  Event buffer
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_recv_event(pmlan_private priv, mlan_event_id event_id, t_void *pmevent)
+{
+	pmlan_callbacks pcb = MNULL;
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pcb = &priv->adapter->callbacks;
+
+	if (pmevent)
+		/* The caller has provided the event. */
+		pcb->moal_recv_event(priv->adapter->pmoal_handle,
+				     (pmlan_event)pmevent);
+	else {
+		mlan_event mevent;
+
+		memset(priv->adapter, &mevent, 0, sizeof(mlan_event));
+		mevent.bss_index = priv->bss_index;
+		mevent.event_id = event_id;
+		mevent.event_len = 0;
+
+		pcb->moal_recv_event(priv->adapter->pmoal_handle, &mevent);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function allocates the command buffer and links
+ *          it to command free queue.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_alloc_cmd_buffer(IN 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);
+
+	/* 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;
+		}
+	}
+	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(IN 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++) {
+		if (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;
+		}
+		if (pcmd_array[i].respbuf) {
+			wlan_free_mlan_buffer(pmadapter, pcmd_array[i].respbuf);
+			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(pmadapter, (t_u8 *)&eventcause,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       sizeof(eventcause));
+		} else {
+			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(pmadapter,
+		       pmbuf->pbuf + pmbuf->data_offset,
+		       (t_u8 *)&eventcause, sizeof(eventcause));
+	}
+
+	if (MTRUE
+	    && (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE)
+		) {
+		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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	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(IN 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(IN 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(IN mlan_private *pmpriv,
+		 IN t_u16 cmd_no,
+		 IN t_u16 cmd_action,
+		 IN t_u32 cmd_oid, IN t_void *pioctl_buf, IN 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)
+			) {
+			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_oid, pioctl_buf, pdata_buf);
+
+	if (pcmd_node->cmdbuf == MNULL) {
+		PRINTM(MERROR, "PREP_CMD: No free cmd buf\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_ptr =
+		(HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+				       pcmd_node->cmdbuf->data_offset);
+	cmd_ptr->command = cmd_no;
+	cmd_ptr->result = 0;
+
+	/* Prepare command */
+	if (cmd_no)
+		ret = pmpriv->ops.prepare_cmd(pmpriv, cmd_no, cmd_action,
+					      cmd_oid, pioctl_buf, pdata_buf,
+					      cmd_ptr);
+	else {
+		ret = wlan_cmd_host_cmd(pmpriv, cmd_ptr, pdata_buf);
+		pcmd_node->cmd_flag |= CMD_F_HOSTCMD;
+	}
+
+	/* Return error, since the command preparation failed */
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "PREP_CMD: Command 0x%x preparation failed\n",
+		       cmd_no);
+		pcmd_node->pioctl_buf = MNULL;
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+		wlan_request_cmd_lock(pmadapter);
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+		wlan_release_cmd_lock(pmadapter);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	/* Send command */
+#ifdef STA_SUPPORT
+	if (cmd_no == HostCmd_CMD_802_11_SCAN
+	    || cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
+		if (cmd_no == HostCmd_CMD_802_11_SCAN_EXT &&
+		    pmadapter->ext_scan && pmadapter->ext_scan_enh
+		    && pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MFALSE);
+		} else
+			wlan_queue_scan_cmd(pmpriv, pcmd_node);
+	} else {
+#endif
+		if ((cmd_no == HostCmd_CMD_802_11_HS_CFG_ENH) &&
+		    (cmd_action == HostCmd_ACT_GEN_SET) &&
+		    (pmadapter->hs_cfg.conditions == HOST_SLEEP_CFG_CANCEL))
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MFALSE);
+		else
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MTRUE);
+#ifdef STA_SUPPORT
+	}
+#endif
+	wlan_release_cmd_lock(pmadapter);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function inserts command node to cmd_free_q
+ *              after cleaning it.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_insert_cmd_to_free_q(IN mlan_adapter *pmadapter,
+			  IN 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(IN mlan_adapter *pmadapter,
+			     IN cmd_ctrl_node *pcmd_node, IN 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();
+
+	/* 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;
+	}
+
+	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;
+	}
+
+	pmadapter->num_cmd_timeout = 0;
+
+	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);
+	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);
+	}
+	orig_cmdresp_no = wlan_le16_to_cpu(resp->command);
+	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;
+
+	if (resp->command == HostCmd_CMD_HOST_CLOCK_CFG) {
+		/* d2 needs to be fast - is there a way to avoid callback? */
+		pcb->moal_get_host_time_ns(&pmadapter->d2);
+		PRINTM(MINFO, "WIFI_TS: RTT for Host_CLOCK_CFG= %d ns\n",
+		       pmadapter->d2 - pmadapter->d1);
+	}
+
+	/* 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) {
+#if defined(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;
+		}
+	}
+
+	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) {
+
+#if defined(STA_SUPPORT)
+			if (pmadapter->pwarm_reset_ioctl_req) {
+				/* warm reset complete */
+				pmadapter->hw_status = WlanHardwareStatusReady;
+				pcb->moal_ioctl_complete(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 pwarm_reset_ioctl_req,
+							 MLAN_STATUS_SUCCESS);
+				pmadapter->pwarm_reset_ioctl_req = MNULL;
+				goto done;
+			}
+#endif
+			pmadapter->hw_status = WlanHardwareStatusInitdone;
+		} else {
+			/* Issue init commands for the next interface */
+			ret = pmpriv_next->ops.init_cmd(pmpriv_next, MFALSE);
+		}
+	} else if ((pmadapter->hw_status == WlanHardwareStatusGetHwSpec) &&
+		   (HostCmd_CMD_GET_HW_SPEC == cmdresp_no)) {
+		pmadapter->hw_status = WlanHardwareStatusGetHwSpecdone;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the timeout of command sending.
+ *          It will re-send the same command again.
+ *
+ *  @param function_context   A pointer to function_context
+ *  @return                   N/A
+ */
+t_void
+wlan_cmd_timeout_func(t_void *function_context)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)function_context;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	t_u8 i;
+	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++;
+	pmadapter->dbg.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 (pcmd_node->cmdbuf) {
+		t_u8 *pcmd_buf;
+		pcmd_buf =
+			pcmd_node->cmdbuf->pbuf +
+			pcmd_node->cmdbuf->data_offset + INTF_HEADER_LEN;
+		for (i = 0; i < 16; i++)
+			PRINTM(MERROR, "%02x ", *pcmd_buf++);
+		PRINTM(MERROR, "\n");
+	}
+
+	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(IN pmlan_adapter pmadapter)
+{
+
+	cmd_ctrl_node *pcmd_node = MNULL;
+
+	ENTER();
+
+	wlan_request_cmd_lock(pmadapter);
+	while ((pcmd_node =
+		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						&pmadapter->scan_pending_q,
+						MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->scan_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		pcmd_node->pioctl_buf = MNULL;
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+
+	pmadapter->scan_processing = MFALSE;
+	wlan_release_cmd_lock(pmadapter);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Cancel pending SCAN ioctl cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param pioctl_req   A pointer to pmlan_ioctl_req
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	pmlan_private priv = MNULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	PRINTM(MIOCTL, "Cancel scan command\n");
+	wlan_request_cmd_lock(pmadapter);
+	/* IOCTL will be completed, avoid calling IOCTL complete again from EVENT/CMDRESP */
+	if (pmadapter->pscan_ioctl_req) {
+		pioctl_buf = pmadapter->pscan_ioctl_req;
+		priv = pmadapter->priv[pioctl_buf->bss_index];
+		pmadapter->pscan_ioctl_req = MNULL;
+		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+					 MLAN_STATUS_FAILURE);
+	}
+
+	if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
+		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
+		if (pioctl_buf->req_id == MLAN_IOCTL_SCAN) {
+			PRINTM(MIOCTL, "wlan_cancel_scan: current command\n");
+			pcmd_node = pmadapter->curr_cmd;
+			pcmd_node->pioctl_buf = MNULL;
+			pcmd_node->cmd_flag |= CMD_F_CANCELED;
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+		}
+	}
+	while ((pcmd_node = wlan_get_pending_scan_cmd(pmadapter)) != MNULL) {
+		PRINTM(MIOCTL,
+		       "wlan_cancel_scan: find scan command in cmd_pending_q\n");
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+	wlan_release_cmd_lock(pmadapter);
+	if (pmadapter->scan_processing &&
+	    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+		if (priv) {
+			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
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter)
+{
+	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;
+		pmadapter->curr_cmd = 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);
+	}
+
+	/* Cancel all pending command */
+	while ((pcmd_node =
+		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						&pmadapter->cmd_pending_q,
+						MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		if (pcmd_node->pioctl_buf) {
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+			pcmd_node->pioctl_buf = MNULL;
+		}
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+	wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	if (pmadapter->scan_processing &&
+	    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+		if (priv) {
+			wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN_EXT,
+					 HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+			wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+					MNULL);
+		}
+	} else
+		/* Cancel all pending scan command */
+		wlan_flush_scan_queue(pmadapter);
+#endif
+	LEAVE();
+}
+
+/**
+ *  @brief Cancel specific bss's pending ioctl cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param bss_index    BSS index
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+	t_u8 flash_scan = MFALSE;
+#endif
+#ifdef STA_SUPPORT
+	pmlan_private priv = MNULL;
+#endif
+	ENTER();
+
+	PRINTM(MIOCTL, "MOAL Cancel BSS IOCTL: bss_index=%d\n", (int)bss_index);
+	wlan_request_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	if (pmadapter->pscan_ioctl_req &&
+	    (pmadapter->pscan_ioctl_req->bss_index == bss_index)) {
+		/* IOCTL will be completed, avoid calling IOCTL complete again from EVENT/CMDRESP */
+		flash_scan = MTRUE;
+		pioctl_buf = pmadapter->pscan_ioctl_req;
+		priv = pmadapter->priv[pioctl_buf->bss_index];
+		pmadapter->pscan_ioctl_req = MNULL;
+		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+					 MLAN_STATUS_FAILURE);
+	}
+#endif
+	if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
+		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
+		if (pioctl_buf->bss_index == bss_index) {
+			pcmd_node = pmadapter->curr_cmd;
+			pcmd_node->pioctl_buf = MNULL;
+			pcmd_node->cmd_flag |= CMD_F_CANCELED;
+#ifdef STA_SUPPORT
+			if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
+				flash_scan = MTRUE;
+#endif
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+		}
+	}
+	while ((pcmd_node =
+		wlan_get_bss_pending_ioctl_cmd(pmadapter,
+					       bss_index)) != MNULL) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+		pcmd_node->pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+		if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
+			flash_scan = MTRUE;
+#endif
+		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+					 MLAN_STATUS_FAILURE);
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+	wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	if (flash_scan) {
+		if (pmadapter->scan_processing &&
+		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+			if (priv) {
+				wlan_prepare_cmd(priv,
+						 HostCmd_CMD_802_11_SCAN_EXT,
+						 HostCmd_ACT_GEN_SET, 0, MNULL,
+						 MNULL);
+				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) {
+				wlan_prepare_cmd(priv,
+						 HostCmd_CMD_802_11_SCAN_EXT,
+						 HostCmd_ACT_GEN_SET, 0, MNULL,
+						 MNULL);
+				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(IN pmlan_private pmpriv,
+			IN mlan_wifi_rate * pmlan_rate, OUT 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) * 5;
+		PRINTM(MCMND, "bitrate(in 100kbps)=%d\n", prate->bitrate);
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares command of ftm config session 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 cmd_oid      OID: CONFIG or CANCEL
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_ftm_config_session_params(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *cmd,
+					  IN t_u16 cmd_action,
+					  IN t_u32 cmd_oid,
+					  IN t_void *pdata_buf)
+{
+	HostCmd_DS_FTM_CONFIG_SESSION_PARAMS *ftm_config =
+		&cmd->params.ftm_config;
+	t_u8 *tlv = MNULL;
+	mlan_rtt_config_params *rtt_params = MNULL;
+	MrvlIEtypes_RTTRangeRequest_t *tlv_rtt_rr = MNULL;
+	mlan_rtt_cancel_params *rtt_cancel = MNULL;
+	MrvlIEtypes_RTTRangeCancel_t *tlv_rtt_rc = MNULL;
+	t_u32 i = 0;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_FTM_CONFIG_SESSION_PARAMS);
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_FTM_CONFIG_SESSION_PARAMS);
+
+	ftm_config->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+	tlv = ftm_config->tlv_buffer;
+
+	if (cmd_oid == OID_RTT_REQUEST) {
+		rtt_params = (mlan_rtt_config_params *) pdata_buf;
+		for (i = 0; i < rtt_params->rtt_config_num; i++) {
+			tlv_rtt_rr = (MrvlIEtypes_RTTRangeRequest_t *) tlv;
+			tlv_rtt_rr->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_RTT_RANGE_REQUEST);
+			tlv_rtt_rr->header.len =
+				wlan_cpu_to_le16((sizeof(*tlv_rtt_rr)
+						  -
+						  sizeof(MrvlIEtypesHeader_t)));
+			memcpy(pmpriv->adapter, tlv_rtt_rr->addr,
+			       rtt_params->rtt_config[i].addr,
+			       sizeof(tlv_rtt_rr->addr));
+			tlv_rtt_rr->type = rtt_params->rtt_config[i].type;
+			tlv_rtt_rr->peer = rtt_params->rtt_config[i].peer;
+			tlv_rtt_rr->channel = rtt_params->rtt_config[i].channel;
+			tlv_rtt_rr->bandcfg = rtt_params->rtt_config[i].bandcfg;
+			tlv_rtt_rr->burst_period =
+				rtt_params->rtt_config[i].burst_period;
+			tlv_rtt_rr->num_burst =
+				rtt_params->rtt_config[i].num_burst;
+			tlv_rtt_rr->num_frames_per_burst =
+				rtt_params->rtt_config[i].num_frames_per_burst;
+			tlv_rtt_rr->num_retries_per_rtt_frame =
+				rtt_params->rtt_config[i].
+				num_retries_per_rtt_frame;
+			tlv_rtt_rr->num_retries_per_ftmr =
+				rtt_params->rtt_config[i].num_retries_per_ftmr;
+			tlv_rtt_rr->LCI_request =
+				rtt_params->rtt_config[i].LCI_request;
+			tlv_rtt_rr->LCR_request =
+				rtt_params->rtt_config[i].LCR_request;
+			tlv_rtt_rr->burst_duration =
+				rtt_params->rtt_config[i].burst_duration;
+			tlv_rtt_rr->preamble =
+				rtt_params->rtt_config[i].preamble;
+			tlv_rtt_rr->bw = rtt_params->rtt_config[i].bw;
+			cmd->size += sizeof(*tlv_rtt_rr);
+			tlv += sizeof(*tlv_rtt_rr);
+		}
+	} else if (cmd_oid == OID_RTT_CANCEL) {
+		rtt_cancel = (mlan_rtt_cancel_params *) pdata_buf;
+		for (i = 0; i < rtt_cancel->rtt_cancel_num; i++) {
+			tlv_rtt_rc = (MrvlIEtypes_RTTRangeCancel_t *) tlv;
+			tlv_rtt_rc->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_RTT_RANGE_CANCEL);
+			tlv_rtt_rc->header.len =
+				wlan_cpu_to_le16(sizeof(*tlv_rtt_rc)
+						 - sizeof(MrvlIEtypesHeader_t));
+			memcpy(pmpriv->adapter, tlv_rtt_rc->addr,
+			       rtt_cancel->rtt_cancel[i],
+			       sizeof(tlv_rtt_rc->addr));
+			cmd->size += sizeof(*tlv_rtt_rc);
+			tlv += sizeof(*tlv_rtt_rc);
+		}
+	} else {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of ftm config session 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
+ */
+mlan_status
+wlan_ret_802_11_ftm_config_session_params(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  IN mlan_ioctl_req *pioctl_buf)
+{
+	ENTER();
+
+	PRINTM(MCMND, "ftm config successfully\n");
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function transform Event_WLS_FTM_t to wifi_rtt_result in mlan_event.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param event_ftm  A pointer to Event_WLS_FTM_t
+ *  @param event_ftm_len   length of event_ftm
+ *  @param pevent       A pointer to mlan_event
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_fill_hal_rtt_results(IN pmlan_private pmpriv,
+			  IN Event_WLS_FTM_t * event_ftm,
+			  IN t_u32 event_ftm_len, OUT mlan_event *pevent)
+{
+    /** For input buffer Event_WLS_FTM_t */
+	t_u8 *tlv = event_ftm->u.rtt_results.tlv_buffer;
+	int event_left_len = event_ftm_len - (tlv - (t_u8 *)event_ftm);
+	MrvlIEtypes_RTTResult_t *tlv_rtt_result = MNULL;
+	t_u16 tlv_rtt_result_len = 0;
+	IEEEtypes_Header_t *tlv_ie = MNULL;
+	int tlv_ie_len = 0;
+	int tlv_left_len = 0;
+	t_u8 *tlv_pos = MNULL;
+    /** For output buffer mlan_event */
+	t_u8 *pos = pevent->event_buf;
+	wifi_rtt_result_element *rtt_result_elem = MNULL;
+	wifi_rtt_result *rtt_result = MNULL;
+	t_u32 i = 0;
+
+	ENTER();
+	PRINTM(MCMND,
+	       "wlan_fill_hal_rtt_results event_ftm_len=%d event_left_len=%d event_ftm=%p tlv=%p\n",
+	       event_ftm_len, event_left_len, event_ftm, tlv);
+
+	pevent->event_id = MLAN_EVENT_ID_DRV_RTT_RESULT;
+
+    /** Event format for moal is: [complete(u8)] + [multiple number of rtt result(len(u16) + body)] */
+
+    /** [complete(u8)] */
+	*pos = event_ftm->u.rtt_results.complete;
+	pos += sizeof(event_ftm->u.rtt_results.complete);
+
+    /** multiple number of rtt result(wifi_rtt_result_element) */
+    /** Fill rtt results, 1 tlv at least contain 1 MrvlIEtypes_RTTResult_t */
+	while (event_left_len >= sizeof(MrvlIEtypes_RTTResult_t)) {
+		PRINTM(MCMND, "[%d] event_left_len=%d tlv=%p\n", i,
+		       event_left_len, tlv);
+		tlv_rtt_result = (MrvlIEtypes_RTTResult_t *) tlv;
+		tlv_rtt_result_len =
+			wlan_le16_to_cpu(tlv_rtt_result->header.len);
+
+		rtt_result_elem = (wifi_rtt_result_element *) pos;
+		pos += sizeof(*rtt_result_elem);
+
+		rtt_result = (wifi_rtt_result *) (rtt_result_elem->data);
+		memcpy(pmpriv->adapter, rtt_result->addr, tlv_rtt_result->addr,
+		       sizeof(rtt_result->addr));
+		rtt_result->burst_num =
+			wlan_le32_to_cpu(tlv_rtt_result->burst_num);
+		rtt_result->measurement_number =
+			wlan_le32_to_cpu(tlv_rtt_result->measurement_number);
+		rtt_result->success_number =
+			wlan_le32_to_cpu(tlv_rtt_result->success_number);
+		rtt_result->number_per_burst_peer =
+			tlv_rtt_result->number_per_burst_peer;
+		rtt_result->status = tlv_rtt_result->status;
+		rtt_result->retry_after_duration =
+			tlv_rtt_result->retry_after_duration;
+		rtt_result->type = tlv_rtt_result->type;
+		rtt_result->rssi = wlan_le32_to_cpu(tlv_rtt_result->rssi);
+		rtt_result->rssi_spread =
+			wlan_le32_to_cpu(tlv_rtt_result->rssi_spread);
+		wlan_fill_hal_wifi_rate(pmpriv, &tlv_rtt_result->tx_rate,
+					&rtt_result->tx_rate);
+		wlan_fill_hal_wifi_rate(pmpriv, &tlv_rtt_result->rx_rate,
+					&rtt_result->rx_rate);
+		rtt_result->rtt = wlan_le64_to_cpu(tlv_rtt_result->rtt);
+		rtt_result->rtt_sd = wlan_le64_to_cpu(tlv_rtt_result->rtt_sd);
+		rtt_result->rtt_spread =
+			wlan_le64_to_cpu(tlv_rtt_result->rtt_spread);
+		rtt_result->distance_mm =
+			wlan_le32_to_cpu(tlv_rtt_result->distance_mm);
+		rtt_result->distance_sd_mm =
+			wlan_le32_to_cpu(tlv_rtt_result->distance_sd_mm);
+		rtt_result->distance_spread_mm =
+			wlan_le32_to_cpu(tlv_rtt_result->distance_spread_mm);
+		rtt_result->ts = wlan_le64_to_cpu(tlv_rtt_result->ts);
+		rtt_result->burst_duration =
+			wlan_le32_to_cpu(tlv_rtt_result->burst_duration);
+		rtt_result->negotiated_burst_num =
+			wlan_le32_to_cpu(tlv_rtt_result->negotiated_burst_num);
+		pos += sizeof(*rtt_result);
+
+		tlv_ie = (IEEEtypes_Header_t *)(tlv_rtt_result->tlv_buffer);
+		tlv_pos = (t_u8 *)tlv_ie;
+		tlv_left_len =
+			tlv_rtt_result_len - (sizeof(*tlv_rtt_result) -
+					      sizeof(tlv_rtt_result->header));
+		PRINTM(MCMND, "tlv_ie=%p tlv_left_len=%d\n", tlv_ie,
+		       tlv_left_len);
+	/** Get the standard IEEEIE: MEASUREMENT_REPORT for LCI/LCR*/
+		while ((tlv_left_len > 0) && (tlv_left_len > sizeof(*tlv_ie))) {
+			tlv_ie_len = tlv_ie->len;
+			PRINTM(MCMND,
+			       "[-] tlv_ie=%p tlv_ie_len=%d   tlv_left_len=%d  jump=%d\n",
+			       tlv_ie, tlv_ie_len, tlv_left_len,
+			       sizeof(*tlv_ie) + tlv_ie_len);
+			if ((tlv_ie_len > 0) &&
+			    (tlv_ie->element_id == MEASUREMENT_REPORT)) {
+				PRINTM(MCMND, "LCI/LCR IE: id=%d len=%d\n",
+				       tlv_ie->element_id, tlv_ie->len);
+				memcpy(pmpriv->adapter, pos, (t_u8 *)tlv_ie,
+				       sizeof(*tlv_ie) + tlv_ie_len);
+				pos += sizeof(*tlv_ie) + tlv_ie_len;
+			}
+			tlv_left_len -= sizeof(*tlv_ie) + tlv_ie_len;
+			tlv_pos += sizeof(*tlv_ie) + tlv_ie_len;
+			tlv_ie = (IEEEtypes_Header_t *)tlv_pos;
+			PRINTM(MCMND,
+			       "[+] tlv_ie=%p tlv_ie_len=%d   tlv_left_len=%d \n",
+			       tlv_ie, tlv_ie_len, tlv_left_len);
+		}
+
+		rtt_result_elem->len = pos - rtt_result_elem->data;
+
+		tlv += tlv_rtt_result_len + sizeof(tlv_rtt_result->header);
+		event_left_len -=
+			tlv_rtt_result_len + sizeof(tlv_rtt_result->header);
+		i++;
+	}
+
+    /** event_len include the mlan_event header and payload */
+	pevent->event_len = pos - pevent->event_buf;
+	PRINTM(MCMND, "pevent->event_len=%d \n", pevent->event_len);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of ftm config responder.
+ *
+ *  @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_ftm_config_responder(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *cmd,
+				     IN t_u16 cmd_action,
+				     IN t_u32 cmd_oid, IN t_void *pdata_buf)
+{
+	mlan_rtt_responder *rtt_rsp_cfg = (mlan_rtt_responder *) pdata_buf;
+	HostCmd_DS_FTM_CONFIG_RESPONDER *responder =
+		&cmd->params.ftm_rtt_responder;
+	t_u8 *tlv = responder->tlv_buffer;
+	MrvlIEtypes_RTTResponderEnCfg_t *tlv_rsp_en = MNULL;
+	MrvlIEtypes_RTTLCICfg_t *tlv_lci = MNULL;
+	MrvlIEtypes_RTTLCRCfg_t *tlv_lcr = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_FTM_CONFIG_RESPONDER);
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_FTM_CONFIG_RESPONDER);
+
+	switch (rtt_rsp_cfg->action) {
+	case RTT_GET_RESPONDER_INFO:
+		responder->action =
+			wlan_cpu_to_le16(HostCmd_ACT_RTT_GET_RSP_INFO);
+		break;
+	case RTT_SET_RESPONDER_ENABLE:
+		tlv_rsp_en = (MrvlIEtypes_RTTResponderEnCfg_t *) tlv;
+		responder->action =
+			wlan_cpu_to_le16(HostCmd_ACT_RTT_SET_RSP_EN);
+		tlv_rsp_en->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_RTT_RESPONDER_EN_CFG);
+		tlv_rsp_en->header.len = wlan_cpu_to_le16(sizeof(*tlv_rsp_en)
+							  -
+							  sizeof
+							  (MrvlIEtypesHeader_t));
+		tlv_rsp_en->channel = rtt_rsp_cfg->u.encfg.channel;
+		tlv_rsp_en->bandcfg = rtt_rsp_cfg->u.encfg.bandcfg;
+		tlv_rsp_en->max_duration_seconds =
+			wlan_cpu_to_le32(rtt_rsp_cfg->u.encfg.max_dur_sec);
+		cmd->size += sizeof(*tlv_rsp_en);
+		break;
+	case RTT_SET_RESPONDER_DISABLE:
+		responder->action =
+			wlan_cpu_to_le16(HostCmd_ACT_RTT_SET_RSP_DIS);
+		break;
+	case RTT_SET_RESPONDER_LCI:
+		tlv_lci = (MrvlIEtypes_RTTLCICfg_t *) tlv;
+		responder->action =
+			wlan_cpu_to_le16(HostCmd_ACT_RTT_SET_RSP_LCI);
+		tlv_lci->header.type = wlan_cpu_to_le16(TLV_TYPE_RTT_LCI_CFG);
+		tlv_lci->header.len = wlan_cpu_to_le16(sizeof(*tlv_lci)
+						       -
+						       sizeof
+						       (MrvlIEtypesHeader_t));
+		tlv_lci->latitude =
+			wlan_cpu_to_le64(rtt_rsp_cfg->u.lci.latitude);
+		tlv_lci->longitude =
+			wlan_cpu_to_le64(rtt_rsp_cfg->u.lci.longitude);
+		tlv_lci->altitude =
+			wlan_cpu_to_le32(rtt_rsp_cfg->u.lci.altitude);
+		tlv_lci->latitude_unc = rtt_rsp_cfg->u.lci.latitude_unc;
+		tlv_lci->longitude_unc = rtt_rsp_cfg->u.lci.longitude_unc;
+		tlv_lci->altitude_unc = rtt_rsp_cfg->u.lci.altitude_unc;
+		tlv_lci->motion_pattern = rtt_rsp_cfg->u.lci.motion_pattern;
+		tlv_lci->floor = wlan_cpu_to_le32(rtt_rsp_cfg->u.lci.floor);
+		tlv_lci->height_above_floor =
+			wlan_cpu_to_le32(rtt_rsp_cfg->u.lci.height_above_floor);
+		tlv_lci->height_unc =
+			wlan_cpu_to_le32(rtt_rsp_cfg->u.lci.height_unc);
+		cmd->size += sizeof(*tlv_lci);
+		break;
+	case RTT_SET_RESPONDER_LCR:
+		tlv_lcr = (MrvlIEtypes_RTTLCRCfg_t *) tlv;
+		responder->action =
+			wlan_cpu_to_le16(HostCmd_ACT_RTT_SET_RSP_LCR);
+		tlv_lcr->header.type = wlan_cpu_to_le16(TLV_TYPE_RTT_LCR_CFG);
+		tlv_lcr->header.len = wlan_cpu_to_le16(sizeof(*tlv_lcr)
+						       -
+						       sizeof
+						       (MrvlIEtypesHeader_t));
+		memcpy(pmpriv->adapter, tlv_lcr->country_code,
+		       rtt_rsp_cfg->u.lcr.country_code,
+		       sizeof(tlv_lcr->country_code));
+		tlv_lcr->length = wlan_cpu_to_le32(rtt_rsp_cfg->u.lcr.length);
+		memcpy(pmpriv->adapter, tlv_lcr->civic_info,
+		       rtt_rsp_cfg->u.lcr.civic_info,
+		       sizeof(tlv_lcr->civic_info));
+		cmd->size += sizeof(*tlv_lcr);
+		break;
+	default:
+		PRINTM(MERROR,
+		       "wlan_cmd_802_11_ftm_config_responder: action not found\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+		break;
+	}
+
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of ftm config responder
+ *
+ *  @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_ftm_config_responder(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *resp,
+				     IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)(pioctl_buf->pbuf);
+	mlan_rtt_responder *rtt_rsp_cfg = &(misc->param.rtt_rsp_cfg);
+	HostCmd_DS_FTM_CONFIG_RESPONDER *responder = MNULL;
+	t_u32 cmdrsp_len = wlan_le16_to_cpu(resp->size);
+	int left_len = 0;
+	t_u8 *tlv = MNULL;
+	MrvlIEtypes_RTTResponderInfo_t *tlv_rsp_info = MNULL;
+
+	ENTER();
+
+	PRINTM(MCMND, "ftm config responder successfully cmdrsp_len=%d\n",
+	       cmdrsp_len);
+
+	if ((cmdrsp_len < S_DS_GEN) ||
+	    (cmdrsp_len - S_DS_GEN < sizeof(HostCmd_DS_FTM_CONFIG_RESPONDER)))
+		goto done;
+
+	responder = &resp->params.ftm_rtt_responder;
+	left_len = cmdrsp_len - (S_DS_GEN + sizeof(*responder));
+	PRINTM(MCMND, "left_len=%d\n", left_len);
+
+	tlv = responder->tlv_buffer;
+	while ((left_len > 0) && (left_len > sizeof(MrvlIEtypesHeader_t))) {
+		PRINTM(MCMND, "left_len=%d tlv: type=0x%x len=%d\n", left_len,
+		       ((MrvlIEtypesHeader_t *)tlv)->type,
+		       ((MrvlIEtypesHeader_t *)tlv)->len);
+		if (((MrvlIEtypesHeader_t *)tlv)->type ==
+		    TLV_TYPE_RTT_RESPONDER_INFO) {
+			if (((MrvlIEtypesHeader_t *)tlv)->len >=
+			    (sizeof(MrvlIEtypes_RTTResponderInfo_t) -
+			     sizeof(MrvlIEtypesHeader_t))) {
+				tlv_rsp_info =
+					(MrvlIEtypes_RTTResponderInfo_t *) tlv;
+				PRINTM(MCMND, "rtt_rsp_cfg->action=0x%x\n",
+				       rtt_rsp_cfg->action);
+				if (rtt_rsp_cfg->action ==
+				    RTT_GET_RESPONDER_INFO ||
+				    rtt_rsp_cfg->action ==
+				    RTT_SET_RESPONDER_ENABLE) {
+					rtt_rsp_cfg->u.info.channel =
+						tlv_rsp_info->channel;
+					rtt_rsp_cfg->u.info.bandcfg =
+						tlv_rsp_info->bandcfg;
+					rtt_rsp_cfg->u.info.preamble =
+						tlv_rsp_info->preamble;
+					PRINTM(MCMND,
+					       "set to rtt_rsp_cfg channel=%d bandcfg=%d %d %d %d preamble=%d\n",
+					       rtt_rsp_cfg->u.info.channel,
+					       rtt_rsp_cfg->u.info.bandcfg.
+					       chanBand,
+					       rtt_rsp_cfg->u.info.bandcfg.
+					       chanWidth,
+					       rtt_rsp_cfg->u.info.bandcfg.
+					       chan2Offset,
+					       rtt_rsp_cfg->u.info.bandcfg.
+					       chan2Offset,
+					       rtt_rsp_cfg->u.info.preamble);
+					break;
+				}
+			}
+		}
+		left_len -=
+			((MrvlIEtypesHeader_t *)tlv)->len +
+			sizeof(MrvlIEtypesHeader_t);
+		tlv += ((MrvlIEtypesHeader_t *)tlv)->len +
+			sizeof(MrvlIEtypesHeader_t);
+	}
+
+done:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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(pmpriv->adapter, info->param.ver_ext.version_str,
+		       ver_ext->version_str, sizeof(char) * 128);
+	}
+	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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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 && !IS_CARD_RX_RCVD(pmadapter)) {
+		wlan_dnld_sleep_confirm_cmd(pmadapter);
+	} else {
+		PRINTM(MCMND, "Delay Sleep Confirm (%s%s%s)\n",
+		       (pmadapter->cmd_sent) ? "D" : "",
+		       (pmadapter->curr_cmd) ? "C" : "",
+		       (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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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();
+
+	if (wlan_le16_to_cpu(phs_cfg->action) == HS_ACTIVATE) {
+		/* 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);
+		wlan_host_sleep_activated_event(pmpriv, MTRUE);
+		goto done;
+	} else {
+		phs_cfg->params.hs_config.conditions =
+			wlan_le32_to_cpu(phs_cfg->params.hs_config.conditions);
+		PRINTM(MCMND,
+		       "CMD_RESP: HS_CFG cmd reply result=%#x,"
+		       " conditions=0x%x gpio=0x%x gap=0x%x\n", resp->result,
+		       phs_cfg->params.hs_config.conditions,
+		       phs_cfg->params.hs_config.gpio,
+		       phs_cfg->params.hs_config.gap);
+	}
+	if (phs_cfg->params.hs_config.conditions != HOST_SLEEP_CFG_CANCEL) {
+		pmadapter->is_hs_configured = 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)
+		wlan_pm_wakeup_card(pmadapter);
+	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;
+
+	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);
+
+	/* 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 (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(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,
+			IN HostCmd_DS_COMMAND *cmd,
+			IN t_u16 cmd_action,
+			IN t_u16 ps_bitmap, IN 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->adhoc_wake_period =
+				wlan_cpu_to_le16(pmadapter->adhoc_awake_period);
+			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(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *resp,
+			IN 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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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->is_data_rate_auto) {
+		pmpriv->data_rate = wlan_index_to_data_rate(pmadapter,
+							    pmpriv->tx_rate,
+							    pmpriv->
+							    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)
+					/* 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);
+			}
+		} else if (rate->sub_command == MLAN_OID_GET_DATA_RATE) {
+			/* Tx rate info */
+			if ((pmpriv->tx_rate_info & 0x3) ==
+			    MLAN_RATE_FORMAT_VHT) {
+				/* VHT rate */
+				rate->param.data_rate.tx_rate_format =
+					MLAN_RATE_FORMAT_VHT;
+				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_nss =
+					(pmpriv->tx_rate) >> 4;
+				rate->param.data_rate.tx_mcs_index =
+					(pmpriv->tx_rate) & 0xF;
+				rate->param.data_rate.tx_data_rate =
+					wlan_index_to_data_rate(pmadapter,
+								pmpriv->tx_rate,
+								pmpriv->
+								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);
+			} 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) {
+				/* VHT rate */
+				rate->param.data_rate.rx_rate_format =
+					MLAN_RATE_FORMAT_VHT;
+				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_nss =
+					(pmpriv->rxpd_rate) >> 4;
+				rate->param.data_rate.rx_mcs_index =
+					(pmpriv->rxpd_rate) & 0xF;
+				rate->param.data_rate.rx_data_rate =
+					wlan_index_to_data_rate(pmadapter,
+								pmpriv->
+								rxpd_rate,
+								pmpriv->
+								rxpd_rate_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);
+			} 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 fw_wakeup_method.
+ *
+ * @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_fw_wakeup_method(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *cmd,
+				 IN t_u16 cmd_action, IN t_u16 *pdata_buf)
+{
+	HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &cmd->params.fwwakeupmethod;
+	mlan_fw_wakeup_params *fw_wakeup_params = MNULL;
+	MrvlIEtypes_WakeupSourceGPIO_t *tlv =
+		(MrvlIEtypes_WakeupSourceGPIO_t *) ((t_u8 *)fwwm +
+						    sizeof
+						    (HostCmd_DS_802_11_FW_WAKEUP_METHOD));
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_FW_WAKE_METHOD);
+	cmd->size = sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) + S_DS_GEN;
+	fwwm->action = wlan_cpu_to_le16(cmd_action);
+	switch (cmd_action) {
+	case HostCmd_ACT_GEN_SET:
+		fw_wakeup_params = (mlan_fw_wakeup_params *) pdata_buf;
+		fwwm->method = wlan_cpu_to_le16(fw_wakeup_params->method);
+
+		if (fw_wakeup_params->method == WAKEUP_FW_THRU_GPIO) {
+			cmd->size += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
+			tlv->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_HS_WAKEUP_SOURCE_GPIO);
+			tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_WakeupSourceGPIO_t)
+						 - sizeof(MrvlIEtypesHeader_t));
+			tlv->ind_gpio = (t_u8)fw_wakeup_params->gpio_pin;
+		}
+
+		break;
+	case HostCmd_ACT_GEN_GET:
+	default:
+		fwwm->method = wlan_cpu_to_le16(WAKEUP_FW_UNCHANGED);
+		break;
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of fw_wakeup_method
+ *
+ *  @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_fw_wakeup_method(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &resp->params.fwwakeupmethod;
+	t_u16 action;
+	MrvlIEtypes_WakeupSourceGPIO_t *gpio_tlv =
+		(MrvlIEtypes_WakeupSourceGPIO_t *) ((t_u8 *)fwwm +
+						    sizeof
+						    (HostCmd_DS_802_11_FW_WAKEUP_METHOD));
+	mlan_ds_pm_cfg *pmcfg = MNULL;
+
+	ENTER();
+
+	action = wlan_le16_to_cpu(fwwm->action);
+
+	pmpriv->adapter->fw_wakeup_method = wlan_le16_to_cpu(fwwm->method);
+	pmpriv->adapter->fw_wakeup_gpio_pin = 0;
+
+	if ((resp->size -
+	     (sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) + S_DS_GEN))
+	    == sizeof(MrvlIEtypes_WakeupSourceGPIO_t)) {
+		pmpriv->adapter->fw_wakeup_gpio_pin = gpio_tlv->ind_gpio;
+	}
+	PRINTM(MCMND, "FW wakeup method=%d, gpio=%d\n",
+	       pmpriv->adapter->fw_wakeup_method,
+	       pmpriv->adapter->fw_wakeup_gpio_pin);
+
+	if (pioctl_buf) {
+		pmcfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+		pmcfg->param.fw_wakeup_params.method =
+			pmpriv->adapter->fw_wakeup_method;
+		pmcfg->param.fw_wakeup_params.gpio_pin =
+			pmpriv->adapter->fw_wakeup_gpio_pin;
+	}
+	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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN 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 *) ((t_u8 *)rbstcx +
+							sizeof
+							(HostCmd_DS_802_11_ROBUSTCOEX));
+
+	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;
+}
+
+/**
+ *  @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
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN t_void *pdata_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;
+	t_u16 *pbitmap_rates = (t_u16 *)pdata_buf;
+
+	t_u32 i;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
+
+	rate_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	rate_scope = (MrvlRateScope_t *)((t_u8 *)rate_cfg +
+					 sizeof(HostCmd_DS_TX_RATE_CFG));
+	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]);
+	} 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]);
+	}
+
+	rate_drop = (MrvlRateDropPattern_t *)((t_u8 *)rate_scope +
+					      sizeof(MrvlRateScope_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) +
+				     sizeof(MrvlRateScope_t) +
+				     sizeof(MrvlRateDropPattern_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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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;
+
+	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 *)((t_u8 *)prate_cfg) + sizeof(HostCmd_DS_TX_RATE_CFG);
+	if (tlv_buf) {
+		tlv_buf_len = *(t_u16 *)(tlv_buf + sizeof(t_u16));
+		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]);
+			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;
+	}
+
+	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;
+			}
+			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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	/*
+	 * This should be issued in the very first to config
+	 *   SDIO_GPIO interrupt mode.
+	 */
+	if (wlan_set_sdio_gpio_int(priv) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	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;
+	}
+    /** Cal data dnld cmd prepare */
+	if ((pmadapter->pcal_data) && (pmadapter->cal_data_len > 0)) {
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
+				       HostCmd_ACT_GEN_SET, OID_TYPE_CAL, MNULL,
+				       MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		pmadapter->pcal_data = MNULL;
+		pmadapter->cal_data_len = 0;
+	}
+	/* Get FW region and cfp tables */
+	if (pmadapter->init_para.fw_region) {
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
+				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	/*
+	 * Get HW spec
+	 */
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function issues adapter specific commands
+ *          to initialize firmware
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_adapter_init_cmd(IN 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
+
+	/* Get fw wakeup method */
+	if (pmpriv) {
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_802_11_FW_WAKE_METHOD,
+				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Reconfigure tx buf size */
+	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
+
+#if defined(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;
+		}
+	}
+	if (pmadapter->init_para.drcs_chantime_mode) {
+		mlan_ds_drcs_cfg drcs_init_cfg[2];
+		drcs_init_cfg[0].chan_idx = 0x1;
+		drcs_init_cfg[0].chantime =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 8);
+		/* switchtime use default value in fw */
+		drcs_init_cfg[0].switchtime = 10;
+		drcs_init_cfg[0].undozetime = 5;
+		drcs_init_cfg[0].mode =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode);
+		drcs_init_cfg[1].chan_idx = 0x2;
+		drcs_init_cfg[1].chantime =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 24);
+		/* switchtime use default value in fw */
+		drcs_init_cfg[1].switchtime = 10;
+		drcs_init_cfg[1].undozetime = 5;
+		drcs_init_cfg[1].mode =
+			(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 16);
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DRCS_CONFIG,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       (t_void *)drcs_init_cfg);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef RX_PACKET_COALESCE
+/**
+ *  @brief This function prepares command of rx_pkt_coalesce_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_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			     const IN HostCmd_DS_COMMAND *resp,
+			     OUT 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 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_handle_event_multi_chan_info(IN pmlan_private pmpriv, pmlan_buffer pevent)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	t_u32 interfaces = 0;
+	MrvlIEtypes_multi_chan_info_t *pmulti_chan_info = MNULL;
+	MrvlIEtypes_multi_chan_group_info_t *pmulti_chan_grp_info = MNULL;
+	int tlv_buf_left = pevent->data_len - sizeof(mlan_event_id);
+	t_u16 tlv_type, tlv_len;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private intf_priv = MNULL;
+	int num_intf = 0, bss_type = 0, bss_num = 0;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+
+	ENTER();
+
+	PRINTM(MEVENT, "multi channel event\n");
+	pmulti_chan_info =
+		(MrvlIEtypes_multi_chan_info_t *)(pevent->pbuf +
+						  pevent->data_offset +
+						  sizeof(mlan_event_id));
+	if (tlv_buf_left < sizeof(MrvlIEtypes_multi_chan_info_t) ||
+	    wlan_le16_to_cpu(pmulti_chan_info->header.type) !=
+	    TLV_TYPE_MULTI_CHAN_INFO) {
+		PRINTM(MERROR, "Invalid multi channel event\n");
+		goto done;
+	}
+
+	pmadapter->mc_status = wlan_le16_to_cpu(pmulti_chan_info->status);
+	PRINTM(MEVENT, "mc_status=%d\n", pmadapter->mc_status);
+	tlv_buf_left -= sizeof(MrvlIEtypes_multi_chan_info_t);
+	tlv = (MrvlIEtypesHeader_t *)pmulti_chan_info->tlv_buffer;
+
+	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_MULTI_CHAN_GROUP_INFO_TLV_ID) {
+			PRINTM(MERROR, "wrong tlv type:0x%x\n", tlv_type);
+			break;
+		}
+		pmulti_chan_grp_info =
+			(MrvlIEtypes_multi_chan_group_info_t *)tlv;
+		PRINTM(MEVENT, "mc_info: groupid=%d chan=%d, numintf=%d\n",
+		       pmulti_chan_grp_info->chan_group_id,
+		       pmulti_chan_grp_info->chan_band_info.chan_num,
+		       pmulti_chan_grp_info->num_intf);
+		num_intf = pmulti_chan_grp_info->num_intf;
+		for (interfaces = 0; interfaces < num_intf; interfaces++) {
+			bss_type =
+				pmulti_chan_grp_info->
+				bss_type_numlist[interfaces] >> 4;
+			bss_num =
+				pmulti_chan_grp_info->
+				bss_type_numlist[interfaces] & BSS_NUM_MASK;
+			PRINTM(MEVENT, "intf%d: bss_type=%d bss_num=%d\n",
+			       interfaces, bss_type, bss_num);
+			intf_priv =
+				wlan_get_priv_by_id(pmadapter, bss_num,
+						    bss_type);
+			if (intf_priv) {
+			} else {
+				PRINTM(MERROR,
+				       "Invalid bss_type, bss_num in multi_channel event\n");
+			}
+		}
+
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares the command MULTI_CHAN_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          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_multi_chan_cfg(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *cmd,
+			IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_multi_chan_cfg *multi_chan_cfg =
+		(mlan_ds_multi_chan_cfg *)pdata_buf;
+	HostCmd_DS_MULTI_CHAN_CFG *pmchan_cfg =
+		(HostCmd_DS_MULTI_CHAN_CFG *)&cmd->params.multi_chan_cfg;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_CONFIG);
+	pmchan_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		pmchan_cfg->buffer_weight = multi_chan_cfg->buffer_weight;
+		pmchan_cfg->channel_time =
+			wlan_cpu_to_le32(multi_chan_cfg->channel_time);
+		PRINTM(MCMND,
+		       "Set multi-channel: buffer_weight=%d channel_time=%d\n",
+		       multi_chan_cfg->buffer_weight,
+		       multi_chan_cfg->channel_time);
+		cmd->size =
+			wlan_cpu_to_le16(S_DS_GEN +
+					 sizeof(HostCmd_DS_MULTI_CHAN_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 MULTI_CHAN_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_multi_chan_cfg(IN pmlan_private pmpriv,
+			const IN HostCmd_DS_COMMAND *resp,
+			OUT mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_MULTI_CHAN_CFG *presp_cfg =
+		&resp->params.multi_chan_cfg;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		pcfg->param.multi_chan_cfg.channel_time =
+			wlan_le32_to_cpu(presp_cfg->channel_time);
+		pcfg->param.multi_chan_cfg.buffer_weight =
+			presp_cfg->buffer_weight;
+		pcfg->param.multi_chan_cfg.tlv_len =
+			resp->size - (sizeof(HostCmd_DS_GEN) +
+				      sizeof(HostCmd_DS_MULTI_CHAN_CFG));
+		PRINTM(MCMND,
+		       "Get multi-channel: buffer_weight=%d channel_time=%d tlv_len=%d\n",
+		       pcfg->param.multi_chan_cfg.buffer_weight,
+		       pcfg->param.multi_chan_cfg.channel_time,
+		       pcfg->param.multi_chan_cfg.tlv_len);
+		memcpy(pmpriv->adapter, pcfg->param.multi_chan_cfg.tlv_buf,
+		       presp_cfg->tlv_buf, pcfg->param.multi_chan_cfg.tlv_len);
+		pioctl_buf->buf_len =
+			sizeof(mlan_ds_multi_chan_cfg) +
+			pcfg->param.multi_chan_cfg.tlv_len;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command MULTI_CHAN_POLICY
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          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_multi_chan_policy(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	t_u16 policy = 0;
+	HostCmd_DS_MULTI_CHAN_POLICY *pmulti_chan_policy =
+		(HostCmd_DS_MULTI_CHAN_POLICY *)&cmd->params.multi_chan_policy;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_POLICY);
+	pmulti_chan_policy->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size =
+		wlan_cpu_to_le16(S_DS_GEN +
+				 sizeof(HostCmd_DS_MULTI_CHAN_POLICY));
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		policy = *((t_u16 *)pdata_buf);
+		pmulti_chan_policy->policy = wlan_cpu_to_le16(policy);
+		PRINTM(MCMND, "Set multi-channel policy: %d\n", policy);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of MULTI_CHAN_POLICY
+ *
+ *  @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_multi_chan_policy(IN pmlan_private pmpriv,
+			   const IN HostCmd_DS_COMMAND *resp,
+			   OUT mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_MULTI_CHAN_POLICY *presp_cfg =
+		&resp->params.multi_chan_policy;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		pcfg->param.multi_chan_policy =
+			wlan_le16_to_cpu(presp_cfg->policy);
+
+		if (pioctl_buf->action == HostCmd_ACT_GEN_SET) {
+			if (pcfg->param.multi_chan_policy)
+				pmpriv->adapter->mc_policy = MTRUE;
+			else
+				pmpriv->adapter->mc_policy = MFALSE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command DRCD_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          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_drcs_cfg(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *cmd,
+		  IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_drcs_cfg *drcs_cfg = (mlan_ds_drcs_cfg *) pdata_buf;
+	HostCmd_DS_DRCS_CFG *pdrcs_cfg =
+		(HostCmd_DS_DRCS_CFG *) & cmd->params.drcs_cfg;
+	MrvlTypes_DrcsTimeSlice_t *channel_time_slicing =
+		&pdrcs_cfg->time_slicing;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DRCS_CONFIG);
+	pdrcs_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		channel_time_slicing->header.type =
+			wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
+		channel_time_slicing->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlTypes_DrcsTimeSlice_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		channel_time_slicing->chan_idx =
+			wlan_cpu_to_le16(drcs_cfg->chan_idx);
+		channel_time_slicing->chantime = drcs_cfg->chantime;
+		channel_time_slicing->switchtime = drcs_cfg->switchtime;
+		channel_time_slicing->undozetime = drcs_cfg->undozetime;
+		channel_time_slicing->mode = drcs_cfg->mode;
+		PRINTM(MCMND,
+		       "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+		       channel_time_slicing->chan_idx,
+		       channel_time_slicing->chantime,
+		       channel_time_slicing->switchtime,
+		       channel_time_slicing->undozetime,
+		       channel_time_slicing->mode);
+		cmd->size =
+			wlan_cpu_to_le16(S_DS_GEN +
+					 sizeof(HostCmd_DS_DRCS_CFG));
+		/* Set two channels different parameters */
+		if (0x3 != channel_time_slicing->chan_idx) {
+			drcs_cfg++;
+			channel_time_slicing = pdrcs_cfg->drcs_buf;
+			channel_time_slicing->header.type =
+				wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
+			channel_time_slicing->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlTypes_DrcsTimeSlice_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			channel_time_slicing->chan_idx =
+				wlan_cpu_to_le16(drcs_cfg->chan_idx);
+			channel_time_slicing->chantime = drcs_cfg->chantime;
+			channel_time_slicing->switchtime = drcs_cfg->switchtime;
+			channel_time_slicing->undozetime = drcs_cfg->undozetime;
+			channel_time_slicing->mode = drcs_cfg->mode;
+			PRINTM(MCMND,
+			       "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+			       channel_time_slicing->chan_idx,
+			       channel_time_slicing->chantime,
+			       channel_time_slicing->switchtime,
+			       channel_time_slicing->undozetime,
+			       channel_time_slicing->mode);
+			cmd->size +=
+				wlan_cpu_to_le16(sizeof
+						 (MrvlTypes_DrcsTimeSlice_t));
+		}
+	} 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 DRCS_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_drcs_cfg(IN pmlan_private pmpriv,
+		  const IN HostCmd_DS_COMMAND *resp,
+		  OUT mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_DRCS_CFG *presp_cfg = &resp->params.drcs_cfg;
+	const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing =
+		&presp_cfg->time_slicing;
+	const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing1 = MNULL;
+	mlan_ds_drcs_cfg *drcs_cfg1 = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		if (wlan_le16_to_cpu(channel_time_slicing->header.type) !=
+		    MRVL_DRCS_TIME_SLICE_TLV_ID ||
+		    wlan_le16_to_cpu(channel_time_slicing->header.len) !=
+		    sizeof(MrvlTypes_DrcsTimeSlice_t) -
+		    sizeof(MrvlIEtypesHeader_t)) {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pcfg->param.drcs_cfg[0].chan_idx =
+			wlan_le16_to_cpu(channel_time_slicing->chan_idx);
+		pcfg->param.drcs_cfg[0].chantime =
+			channel_time_slicing->chantime;
+		pcfg->param.drcs_cfg[0].switchtime =
+			channel_time_slicing->switchtime;
+		pcfg->param.drcs_cfg[0].undozetime =
+			channel_time_slicing->undozetime;
+		pcfg->param.drcs_cfg[0].mode = channel_time_slicing->mode;
+		PRINTM(MCMND,
+		       "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+		       pcfg->param.drcs_cfg[0].chan_idx,
+		       channel_time_slicing->chantime,
+		       channel_time_slicing->switchtime,
+		       channel_time_slicing->undozetime,
+		       channel_time_slicing->mode);
+		pioctl_buf->buf_len = sizeof(mlan_ds_drcs_cfg);
+		/*Channel for chan_idx 1 and 2 have different parameters */
+		if (0x3 != pcfg->param.drcs_cfg[0].chan_idx) {
+			channel_time_slicing1 = presp_cfg->drcs_buf;
+			if (wlan_le16_to_cpu(channel_time_slicing1->header.type)
+			    != MRVL_DRCS_TIME_SLICE_TLV_ID ||
+			    wlan_le16_to_cpu(channel_time_slicing1->header.
+					     len) !=
+			    sizeof(MrvlTypes_DrcsTimeSlice_t) -
+			    sizeof(MrvlIEtypesHeader_t)) {
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+			drcs_cfg1 =
+				(mlan_ds_drcs_cfg *) & pcfg->param.drcs_cfg[1];
+			drcs_cfg1->chan_idx =
+				wlan_le16_to_cpu(channel_time_slicing1->
+						 chan_idx);
+			drcs_cfg1->chantime = channel_time_slicing1->chantime;
+			drcs_cfg1->switchtime =
+				channel_time_slicing1->switchtime;
+			drcs_cfg1->undozetime =
+				channel_time_slicing1->undozetime;
+			drcs_cfg1->mode = channel_time_slicing1->mode;
+			PRINTM(MCMND,
+			       "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
+			       drcs_cfg1->chan_idx, drcs_cfg1->chantime,
+			       drcs_cfg1->switchtime, drcs_cfg1->undozetime,
+			       drcs_cfg1->mode);
+			pioctl_buf->buf_len += sizeof(mlan_ds_drcs_cfg);
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv, IN 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(pmpriv->adapter, hw_spec->permanent_addr, pmpriv->curr_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN HostCmd_DS_COMMAND *pcmd,
+			  IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &resp->params.sdio_rx_aggr;
+
+	pmadapter->sdio_rx_aggr_enable = cfg->enable;
+	pmadapter->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->sdio_rx_block_size);
+	if (!pmadapter->sdio_rx_block_size)
+		pmadapter->sdio_rx_aggr_enable = MFALSE;
+	if (pmadapter->sdio_rx_aggr_enable) {
+		pmadapter->max_sp_rx_size = SDIO_CMD53_MAX_SIZE;
+		wlan_re_alloc_sdio_rx_mpa_buffer(pmadapter);
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *pcmd,
+		  IN t_u16 cmd_action, IN t_u32 cmd_oid, IN 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;
+	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));
+	} else {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	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);
+
+done:
+	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;
+
+	ENTER();
+
+	if (resp->result != HostCmd_RESULT_OK) {
+		PRINTM(MERROR, "CFG data cmd resp failed\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *pcmd,
+		     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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;
+
+	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;
+			}
+		}
+		if ((pmadapter->fw_bands & BAND_AN)
+			) {
+			pmadapter->adhoc_start_band = BAND_A | BAND_AN;
+			pmadapter->adhoc_11n_enabled = MTRUE;
+		} else
+			pmadapter->adhoc_start_band = BAND_A;
+		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
+	} else if ((pmadapter->fw_bands & BAND_GN)
+		) {
+		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+		pmadapter->adhoc_11n_enabled = MTRUE;
+	} 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 */
+
+	PRINTM(MCMND, "fw_band=0x%x, config_band=0x%x adhoc_band=0x%x\n",
+	       pmadapter->fw_bands, pmadapter->config_bands,
+	       pmadapter->adhoc_start_band);
+	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 (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 =
+					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);
+	pmadapter->mp_end_port = wlan_le16_to_cpu(hw_spec->mp_end_port);
+
+	for (i = 1; i <= (unsigned)(MAX_PORT - pmadapter->mp_end_port); i++)
+		pmadapter->mp_data_port_mask &= ~(1 << (MAX_PORT - i));
+
+	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;
+
+	if ((pmadapter->fw_cap_info & SDIO_SP_RX_AGGR_ENABLE) &&
+	    pmadapter->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->sdio_rx_aggr_enable = MFALSE;
+		PRINTM(MCMND, "FW: SDIO rx aggr disabled 0x%x\n",
+		       pmadapter->fw_cap_info);
+	}
+
+	if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+				 pmadapter->fw_bands)) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#ifdef STA_SUPPORT
+	if (wlan_11d_set_universaltable(pmpriv, pmadapter->fw_bands)) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#endif /* STA_SUPPORT */
+	if (pmadapter->fw_cap_info & FW_CAPINFO_ECSA) {
+		t_u8 ecsa_enable = MTRUE;
+		pmadapter->ecsa_enable = MTRUE;
+		PRINTM(MCMND, "pmadapter->ecsa_enable=%d\n",
+		       pmadapter->ecsa_enable);
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET, ECSAEnable_i, MNULL,
+				       &ecsa_enable);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (pmadapter->fw_cap_info & FW_CAPINFO_GET_LOG) {
+		pmadapter->getlog_enable = MTRUE;
+		PRINTM(MCMND, "pmadapter->getlog_enable=%d\n",
+		       pmadapter->getlog_enable);
+	}
+
+	left_len = resp->size - sizeof(HostCmd_DS_GET_HW_SPEC) - S_DS_GEN;
+	tlv = (MrvlIEtypesHeader_t *)((t_u8 *)hw_spec +
+				      sizeof(HostCmd_DS_GET_HW_SPEC));
+	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		switch (tlv_type) {
+		case TLV_TYPE_FW_VER_INFO:
+			api_rev = (MrvlIEtypes_fw_ver_info_t *) tlv;
+			api_id = wlan_le16_to_cpu(api_rev->api_id);
+			switch (api_id) {
+			case FW_API_VER_ID:
+				pmadapter->fw_ver = api_rev->major_ver;
+				pmadapter->fw_min_ver = api_rev->minor_ver;
+				PRINTM(MCMND, "fw ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			case UAP_FW_API_VER_ID:
+				pmadapter->uap_fw_ver = api_rev->major_ver;
+				PRINTM(MCMND, "uap fw ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			case CHANRPT_API_VER_ID:
+				pmadapter->chanrpt_param_bandcfg =
+					api_rev->minor_ver;
+				PRINTM(MCMND, "chanrpt api ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			default:
+				break;
+			}
+			break;
+		case TLV_TYPE_MAX_CONN:
+			tlv_max_conn = (MrvlIEtypes_Max_Conn_t *) tlv;
+			PRINTM(MMSG, "max_p2p_conn = %d, max_sta_conn = %d\n",
+			       tlv_max_conn->max_p2p_conn,
+			       tlv_max_conn->max_sta_conn);
+			if (tlv_max_conn->max_p2p_conn &&
+			    tlv_max_conn->max_sta_conn)
+				pmadapter->max_sta_conn =
+					MIN(tlv_max_conn->max_sta_conn,
+					    tlv_max_conn->max_p2p_conn);
+			else if (tlv_max_conn->max_sta_conn)
+				pmadapter->max_sta_conn =
+					tlv_max_conn->max_sta_conn;
+			else if (tlv_max_conn->max_p2p_conn)
+				pmadapter->max_sta_conn =
+					tlv_max_conn->max_p2p_conn;
+			else
+				pmadapter->max_sta_conn = 0;
+			break;
+		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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN 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(pmpriv->adapter, &radio_ctl, pdata_buf, sizeof(t_u32));
+	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(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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 +
+			sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG);
+		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 +
+			sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG);
+		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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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 *)((t_u8 *)p2p_config +
+						      sizeof
+						      (HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG));
+			tlv_buf_left =
+				resp->size -
+				(sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG) +
+				 S_DS_GEN);
+			while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+				tlv_type = wlan_le16_to_cpu(tlv->type);
+				tlv_len = wlan_le16_to_cpu(tlv->len);
+				if (tlv_buf_left <
+				    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+					PRINTM(MERROR,
+					       "Error processing p2p param config TLVs, bytes left < TLV length\n");
+					break;
+				}
+				switch (tlv_type) {
+				case TLV_TYPE_WIFI_DIRECT_NOA:
+					pnoa_tlv =
+						(MrvlIEtypes_NoA_setting_t *)
+						tlv;
+					cfg->param.p2p_config.flags |=
+						WIFI_DIRECT_NOA;
+					cfg->param.p2p_config.noa_enable =
+						pnoa_tlv->enable;
+					cfg->param.p2p_config.index =
+						wlan_le16_to_cpu(pnoa_tlv->
+								 index);
+					cfg->param.p2p_config.noa_count =
+						pnoa_tlv->noa_count;
+					cfg->param.p2p_config.noa_duration =
+						wlan_le32_to_cpu(pnoa_tlv->
+								 noa_duration);
+					cfg->param.p2p_config.noa_interval =
+						wlan_le32_to_cpu(pnoa_tlv->
+								 noa_interval);
+					PRINTM(MCMND,
+					       "Get NOA: enable=%d index=%d, count=%d, duration=%d interval=%d\n",
+					       cfg->param.p2p_config.noa_enable,
+					       cfg->param.p2p_config.index,
+					       cfg->param.p2p_config.noa_count,
+					       (int)cfg->param.p2p_config.
+					       noa_duration,
+					       (int)cfg->param.p2p_config.
+					       noa_interval);
+					break;
+				case TLV_TYPE_WIFI_DIRECT_OPP_PS:
+					popp_ps_tlv =
+						(MrvlIEtypes_OPP_PS_setting_t *)
+						tlv;
+					cfg->param.p2p_config.flags |=
+						WIFI_DIRECT_OPP_PS;
+					cfg->param.p2p_config.opp_ps_enable =
+						(popp_ps_tlv->
+						 enable & 0x80) >> 7;
+					cfg->param.p2p_config.ct_window =
+						popp_ps_tlv->enable & 0x7f;
+					PRINTM(MCMND,
+					       "Get OPP_PS: enable=%d ct_win=%d\n",
+					       cfg->param.p2p_config.
+					       opp_ps_enable,
+					       cfg->param.p2p_config.ct_window);
+					break;
+				default:
+					break;
+				}
+				tlv_buf_left -=
+					tlv_len + sizeof(MrvlIEtypesHeader_t);
+				tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv +
+							      tlv_len +
+							      sizeof
+							      (MrvlIEtypesHeader_t));
+			}
+			pioctl_buf->data_read_written =
+				sizeof(mlan_ds_wifi_direct_config);
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function prepares command of mimo switch configuration.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_mimo_switch(pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_ANTENNA);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_ANTENNA) +
+				 S_DS_GEN);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		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->action_tx = wlan_cpu_to_le16(HostCmd_ACT_GET_TX);
+		pantenna->action_rx = wlan_cpu_to_le16(HostCmd_ACT_GET_RX);
+	}
+	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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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);
+	mlan_ds_radio_cfg *radio = MNULL;
+
+	ENTER();
+
+	PRINTM(MINFO, "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 (pioctl_buf) {
+		radio = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
+		radio->param.ant_cfg.tx_antenna = tx_ant_mode;
+		radio->param.ant_cfg.rx_antenna = rx_ant_mode;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of reg_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 or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_reg_access(IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_reg_rw *reg_rw;
+
+	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);
+			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;
+			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;
+			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;
+		}
+	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,
+		    IN HostCmd_DS_COMMAND *resp, IN 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(pmadapter, &eeprom->value,
+					       &cmd_eeprom->value,
+					       MIN(MAX_EEPROM_DATA,
+						   eeprom->byte_count));
+					HEXDUMP("EEPROM",
+						(char *)&eeprom->value,
+						MIN(MAX_EEPROM_DATA,
+						    eeprom->byte_count));
+				}
+				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(IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_ds_mem_rw *mem_rw = MNULL;
+	HostCmd_DS_MEM_ACCESS *mem = (HostCmd_DS_MEM_ACCESS *)&resp->params.mem;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
+		mem_rw = &reg_mem->param.mem_rw;
+
+		mem_rw->addr = wlan_le32_to_cpu(mem->addr);
+		mem_rw->value = wlan_le32_to_cpu(mem->value);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+*
+*  @brief This function handles coex events generated by firmware
+*
+*  @param priv A pointer to mlan_private structure
+*  @param pevent   A pointer to event buf
+*
+*  @return     N/A
+*/
+void
+wlan_bt_coex_wlan_param_update_event(pmlan_private priv, pmlan_buffer pevent)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	MrvlIETypes_BtCoexAggrWinSize_t *pCoexWinsize = MNULL;
+	MrvlIEtypes_BtCoexScanTime_t *pScantlv = MNULL;
+	t_s32 len = pevent->data_len - sizeof(t_u32);
+	t_u8 *pCurrent_ptr = pevent->pbuf + pevent->data_offset + sizeof(t_u32);
+	t_u16 tlv_type, tlv_len;
+
+	ENTER();
+
+	while (len >= sizeof(MrvlIEtypesHeader_t)) {
+		tlv = (MrvlIEtypesHeader_t *)pCurrent_ptr;
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		if ((tlv_len + sizeof(MrvlIEtypesHeader_t)) > len)
+			break;
+		switch (tlv_type) {
+		case TLV_BTCOEX_WL_AGGR_WINSIZE:
+			pCoexWinsize = (MrvlIETypes_BtCoexAggrWinSize_t *) tlv;
+			pmadapter->coex_win_size = pCoexWinsize->coex_win_size;
+			pmadapter->coex_tx_win_size = pCoexWinsize->tx_win_size;
+			pmadapter->coex_rx_win_size = pCoexWinsize->rx_win_size;
+			wlan_coex_ampdu_rxwinsize(pmadapter);
+			wlan_update_ampdu_txwinsize(pmadapter);
+			break;
+		case TLV_BTCOEX_WL_SCANTIME:
+			pScantlv = (MrvlIEtypes_BtCoexScanTime_t *) tlv;
+			pmadapter->coex_scan = pScantlv->coex_scan;
+			pmadapter->coex_min_scan_time =
+				wlan_le16_to_cpu(pScantlv->min_scan_time);
+			pmadapter->coex_max_scan_time =
+				wlan_le16_to_cpu(pScantlv->max_scan_time);
+			break;
+		default:
+			break;
+		}
+		len -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		pCurrent_ptr += tlv_len + sizeof(MrvlIEtypesHeader_t);
+	}
+	PRINTM(MEVENT,
+	       "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
+	       pmadapter->coex_scan, pmadapter->coex_min_scan_time,
+	       pmadapter->coex_win_size, pmadapter->coex_tx_win_size,
+	       pmadapter->coex_rx_win_size);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares command of supplicant pmk
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_802_11_supplicant_pmk(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+	MrvlIEtypes_Passphrase_t *ppassphrase_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 zero[MLAN_MAX_KEY_LENGTH] = { 0 };
+	MrvlIEtypes_fw_roam_enable_t *proam_tlv = MNULL;
+	MrvlIEtypes_keyParams_t *key_tlv = MNULL;
+	int length = 0;
+	t_u8 userset_passphrase = 0;
+
+	ENTER();
+	if (sec->multi_passphrase)
+		psk = (mlan_ds_passphrase *)&sec->param.
+			roam_passphrase[userset_passphrase];
+	else
+		psk = (mlan_ds_passphrase *)&sec->param.passphrase;
+	if (cmd_action == HostCmd_ACT_GEN_REMOVE) {
+		cmd->size =
+			sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1;
+		proam_tlv = (MrvlIEtypes_fw_roam_enable_t *) ptlv_buffer;
+		proam_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_ROAM);
+		proam_tlv->header.len =
+			sizeof(MrvlIEtypes_fw_roam_enable_t) -
+			sizeof(MrvlIEtypesHeader_t);
+		proam_tlv->roam_enable = MTRUE;
+		ptlv_buffer +=
+			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+		cmd->size +=
+			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+		proam_tlv->header.len = wlan_cpu_to_le16(proam_tlv->header.len);
+
+		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;
+	}
+
+	/*
+	 * 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=marvell
+	 *  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=mrvl/: 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=marvell
+	 */
+
+	/* -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(pmpriv->adapter, pbssid_tlv->bssid, (t_u8 *)&psk->bssid,
+		       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(pmpriv->adapter, ppmk_tlv->pmk, psk->psk.pmk.pmk,
+		       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 (memcmp
+		    (pmpriv->adapter, psk->psk.pmk.pmk_r0, zero,
+		     MLAN_MAX_KEY_LENGTH)) {
+			ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
+			ppmk_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_PMK_R0);
+			ppmk_tlv->header.len = MLAN_MAX_KEY_LENGTH;
+			memcpy(pmpriv->adapter, ppmk_tlv->pmk,
+			       psk->psk.pmk.pmk_r0, 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);
+		}
+		if (memcmp
+		    (pmpriv->adapter, psk->psk.pmk.pmk_r0_name, zero,
+		     MLAN_MAX_PMKR0_NAME_LENGTH)) {
+			ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
+			ppmk_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_PMK_R0_NAME);
+			ppmk_tlv->header.len = MLAN_MAX_PMKR0_NAME_LENGTH;
+			memcpy(pmpriv->adapter, ppmk_tlv->pmk,
+			       psk->psk.pmk.pmk_r0_name,
+			       MLAN_MAX_PMKR0_NAME_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);
+		}
+	}
+	if (pmpriv->adapter->fw_roaming &&
+	    (pmpriv->adapter->userset_passphrase ||
+	     (psk && psk->psk_type == MLAN_PSK_PMK))) {
+		proam_tlv = (MrvlIEtypes_fw_roam_enable_t *) ptlv_buffer;
+		proam_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_ROAM);
+		proam_tlv->header.len =
+			sizeof(MrvlIEtypes_fw_roam_enable_t) -
+			sizeof(MrvlIEtypesHeader_t);
+		proam_tlv->roam_enable = MTRUE;
+		proam_tlv->userset_passphrase =
+			pmpriv->adapter->userset_passphrase;
+		ptlv_buffer +=
+			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+		cmd->size +=
+			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+		proam_tlv->header.len = wlan_cpu_to_le16(proam_tlv->header.len);
+	}
+	do {
+		if (pmpriv->adapter->userset_passphrase &&
+		    sec->multi_passphrase) {
+			key_tlv = (MrvlIEtypes_keyParams_t *) ptlv_buffer;
+			key_tlv->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_ROAM_OFFLOAD_USER_SET_PMK);
+			ptlv_buffer += sizeof(MrvlIEtypesHeader_t);
+			cmd->size += sizeof(MrvlIEtypesHeader_t);
+			length = cmd->size;
+		}
+		if (psk && 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(pmpriv->adapter, (t_u8 *)pssid_tlv->ssid,
+			       (t_u8 *)psk->ssid.ssid, MIN(MLAN_MAX_SSID_LENGTH,
+							   psk->ssid.ssid_len));
+			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->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(pmpriv->adapter, ppassphrase_tlv->passphrase,
+			       psk->psk.passphrase.passphrase,
+			       MIN(MLAN_MAX_PASSPHRASE_LENGTH,
+				   psk->psk.passphrase.passphrase_len));
+			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 (key_tlv)
+			key_tlv->header.len =
+				wlan_cpu_to_le16(cmd->size - length);
+		userset_passphrase++;
+		psk = (mlan_ds_passphrase *)&sec->param.
+			roam_passphrase[userset_passphrase];
+	} while (psk && sec->multi_passphrase &&
+		 userset_passphrase < pmpriv->adapter->userset_passphrase);
+	pmpriv->adapter->userset_passphrase = 0;
+	if ((cmd_action == HostCmd_ACT_GEN_SET) &&
+	    ((ssid_flag || bssid_flag) && (!pmk_flag && !passphrase_flag))) {
+		PRINTM(MERROR,
+		       "Invalid case,ssid/bssid present without pmk or passphrase\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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *resp,
+			       IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_SUPPLICANT_PMK *supplicant_pmk_resp =
+		&resp->params.esupplicant_psk;
+	mlan_ds_sec_cfg sec_buf;
+	mlan_ds_sec_cfg *sec = MNULL;
+	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+	MrvlIEtypes_Passphrase_t *passphrase_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)
+			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))
+					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(pmpriv->adapter,
+					       sec->param.passphrase.ssid.ssid,
+					       pssid_tlv->ssid,
+					       MIN(MLAN_MAX_SSID_LENGTH,
+						   pssid_tlv->header.len));
+					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(pmpriv->adapter,
+					       &sec->param.passphrase.bssid,
+					       pbssid_tlv->bssid,
+					       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(pmpriv->adapter,
+					       sec->param.passphrase.psk.
+					       passphrase.passphrase,
+					       passphrase_tlv->passphrase,
+					       MIN(MLAN_MAX_PASSPHRASE_LENGTH,
+						   passphrase_tlv->header.len));
+					tlv_buf +=
+						passphrase_tlv->header.len +
+						sizeof(MrvlIEtypesHeader_t);
+					tlv_buf_len -=
+						(passphrase_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(pmpriv->adapter,
+					       sec->param.passphrase.psk.pmk.
+					       pmk, ppmk_tlv->pmk,
+					       MIN(MLAN_MAX_KEY_LENGTH,
+						   ppmk_tlv->header.len));
+					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;
+		}
+	}
+
+	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(IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action, IN 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,
+		 IN HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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 prepares command of sending host_clock_cfg.
+ *
+ *  @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_host_clock_cfg(IN HostCmd_DS_COMMAND *cmd,
+			IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_host_clock *hostclk = (mlan_ds_host_clock *) pdata_buf;
+	HostCmd_DS_HOST_CLOCK_CFG *host_clock =
+		(HostCmd_DS_HOST_CLOCK_CFG *) & cmd->params.host_clock_cfg;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HOST_CLOCK_CFG);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_HOST_CLOCK_CFG) + S_DS_GEN);
+
+	host_clock->action = wlan_cpu_to_le16(cmd_action);
+	host_clock->time = wlan_cpu_to_le64(hostclk->time);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of host_clock_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_host_clock_cfg(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *resp,
+			IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *cfg = MNULL;
+	mlan_ds_host_clock *hostclk = MNULL;
+	HostCmd_DS_HOST_CLOCK_CFG *host_clock =
+		(HostCmd_DS_HOST_CLOCK_CFG *) & resp->params.host_clock_cfg;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u64 cmd_rtt;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		hostclk = &cfg->param.host_clock;
+
+		hostclk->time = wlan_le64_to_cpu(host_clock->time);
+		hostclk->fw_time = wlan_le64_to_cpu(host_clock->time);
+		cmd_rtt = (pmadapter->d2 - pmadapter->d1) / 2;
+		PRINTM(MINFO, "HW time: %ld, Host Time: %ld, RTT: %ld\n",
+		       host_clock->hw_time, hostclk->time, cmd_rtt);
+		hostclk->fw_time = wlan_le64_to_cpu(host_clock->hw_time) /*- cmd_rtt*/ ;	// Not adjusting cmd_rtt gave better results with 802.1as
+		hostclk->host_bbu_clk_delta = hostclk->time - hostclk->fw_time;
+		pmadapter->host_bbu_clk_delta = hostclk->host_bbu_clk_delta;
+
+		/* Indicate ioctl complete */
+		pioctl_buf->data_read_written =
+			sizeof(mlan_ds_misc_cfg) + MLAN_SUB_COMMAND_SIZE;
+	}
+
+	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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN mlan_ioctl_req *pioctl_buf)
+{
+	t_u16 action;
+	t_u16 tlv, tlv_buf_len, tlv_buf_left;
+	MrvlIEtypesHeader_t *head;
+	HostCmd_DS_CHAN_REGION_CFG *reg = MNULL;
+	t_u8 *tlv_buf = MNULL;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	reg = (HostCmd_DS_CHAN_REGION_CFG *) & resp->params.reg_cfg;
+	if (!reg) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	action = wlan_le16_to_cpu(reg->action);
+	if (action != HostCmd_ACT_GEN_GET) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	tlv_buf = (t_u8 *)reg + sizeof(*reg);
+	tlv_buf_left = wlan_le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
+
+	/* Add FW cfp tables and region info */
+	wlan_add_fw_cfp_tables(pmpriv, tlv_buf, tlv_buf_left);
+
+	if (!pioctl_buf)
+		goto done;
+
+	if (!pioctl_buf->pbuf) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+	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;
+
+		switch (tlv) {
+		case TLV_TYPE_CHAN_ATTR_CFG:
+			DBG_HEXDUMP(MCMD_D, "CHAN:",
+				    (t_u8 *)head + sizeof(*head), tlv_buf_left);
+			if (tlv_buf_len >
+			    misc_cfg->param.custom_reg_domain.cfg_len) {
+				tlv_buf_len =
+					misc_cfg->param.custom_reg_domain.
+					cfg_len;
+			}
+			misc_cfg->param.custom_reg_domain.cfg_len = tlv_buf_len;
+			memcpy(pmpriv->adapter,
+			       misc_cfg->param.custom_reg_domain.cfg_buf,
+			       (t_u8 *)head + sizeof(*head), tlv_buf_len);
+			pioctl_buf->data_read_written = tlv_buf_len;
+			break;
+		}
+
+		tlv_buf += (sizeof(*head) + tlv_buf_len);
+		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends fw dump event command to firmware.
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param cmd            HostCmd_DS_COMMAND structure
+ *  @param cmd_action     the action: GET or SET
+ *  @param pdata_buf      A void pointer to information buffer
+ *  @return               N/A
+ */
+mlan_status
+wlan_cmd_fw_dump_event(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *cmd,
+			       IN t_u16 cmd_action,
+			       IN 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 *)((t_u8 *)plink_stat +
+				      sizeof(HostCmd_DS_802_11_LINK_STATISTIC));
+	DBG_HEXDUMP(MCMD_D, "tlv:", (void *)tlv, 1024);
+	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		switch (tlv_type) {
+		case TLV_TYPE_LL_STAT_IFACE:
+			fw_ifaceStat =
+				(mlan_wifi_iface_stat *) ((t_u8 *)tlv +
+							  sizeof
+							  (MrvlIEtypesHeader_t));
+			break;
+		case TLV_TYPE_LL_STAT_RADIO:
+			fw_radioStat =
+				(mlan_wifi_radio_stat *) ((t_u8 *)tlv +
+							  sizeof
+							  (MrvlIEtypesHeader_t));
+			num_radio = MAX_RADIO;
+			break;
+		default:
+			break;
+		}
+		left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+	if (!fw_ifaceStat || !fw_radioStat) {
+		PRINTM(MERROR, "!fw_ifaceStat || !fw_radioStat\n");
+		return;
+	}
+
+	*((t_u32 *)link_statistic) = num_radio;
+	link_statistic += sizeof(num_radio);
+
+	/* Fill radio stats array */
+	for (i = 0; i < num_radio; i++) {
+		radio_stat = (wifi_radio_stat *) link_statistic;
+		link_statistic += sizeof(wifi_radio_stat);
+
+		radio_stat->radio = wlan_le32_to_cpu(fw_radioStat[i].radio);
+
+		radio_stat->on_time = wlan_le32_to_cpu(fw_radioStat[i].on_time);
+		radio_stat->tx_time = wlan_le32_to_cpu(fw_radioStat[i].tx_time);
+		radio_stat->reserved0 =
+			wlan_le32_to_cpu(fw_radioStat[i].reserved0);
+		radio_stat->rx_time = wlan_le32_to_cpu(fw_radioStat[i].rx_time);
+		radio_stat->on_time_scan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_scan);
+		radio_stat->on_time_nbd =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_nbd);
+		radio_stat->on_time_gscan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_gscan);
+		radio_stat->on_time_roam_scan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_roam_scan);
+		radio_stat->on_time_pno_scan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_pno_scan);
+		radio_stat->on_time_hs20 =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_hs20);
+
+		radio_stat->num_channels =
+			wlan_le32_to_cpu(fw_radioStat[i].num_channels);
+		for (chan_idx = 0; chan_idx < radio_stat->num_channels;
+		     chan_idx++) {
+			if (radio_stat->num_channels > MAX_NUM_CHAN) {
+				radio_stat->num_channels =
+					wlan_le32_to_cpu(MAX_NUM_CHAN);
+				PRINTM(MERROR,
+				       "%s : radio_stat->num_channels=%d\n",
+				       __func__, radio_stat->num_channels);
+				break;
+			}
+			radio_stat->channels[chan_idx].channel.width =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].channel.
+						 width);
+			radio_stat->channels[chan_idx].channel.center_freq =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].channel.
+						 center_freq);
+			radio_stat->channels[chan_idx].channel.center_freq0 =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].channel.
+						 center_freq0);
+			radio_stat->channels[chan_idx].channel.center_freq1 =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].channel.
+						 center_freq1);
+
+			radio_stat->channels[chan_idx].on_time =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].on_time);
+			radio_stat->channels[chan_idx].cca_busy_time =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].
+						 cca_busy_time);
+		}
+	}
+
+	/* Fill iface stats */
+	iface_stat = (wifi_iface_stat *) link_statistic;
+
+	/* get wifi_interface_link_layer_info in driver, not in firmware */
+	if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+		iface_stat->info.mode = WIFI_INTERFACE_STA;
+		if (priv->media_connected)
+			iface_stat->info.state = WIFI_ASSOCIATING;
+		else
+			iface_stat->info.state = WIFI_DISCONNECTED;
+		iface_stat->info.roaming = WIFI_ROAMING_IDLE;
+		iface_stat->info.capabilities = WIFI_CAPABILITY_QOS;
+		memcpy(priv->adapter, iface_stat->info.ssid,
+		       priv->curr_bss_params.bss_descriptor.ssid.ssid,
+		       MLAN_MAX_SSID_LENGTH);
+		memcpy(priv->adapter, iface_stat->info.bssid,
+		       priv->curr_bss_params.bss_descriptor.mac_address,
+		       MLAN_MAC_ADDR_LENGTH);
+	} else {
+		iface_stat->info.mode = WIFI_INTERFACE_SOFTAP;
+		iface_stat->info.capabilities = WIFI_CAPABILITY_QOS;
+	}
+	memcpy(priv->adapter, iface_stat->info.mac_addr, priv->curr_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+	memcpy(priv->adapter, iface_stat->info.ap_country_str,
+	       priv->adapter->country_code, COUNTRY_CODE_LEN);
+	memcpy(priv->adapter, iface_stat->info.country_str,
+	       priv->adapter->country_code, 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(priv->adapter,
+		       iface_stat->peer_info[peerIdx].peer_mac_address,
+		       fw_ifaceStat->peer_info[peerIdx].peer_mac_address, 6);
+		iface_stat->peer_info[peerIdx].capabilities =
+			wlan_le32_to_cpu(fw_ifaceStat->peer_info[peerIdx].
+					 capabilities);
+		iface_stat->peer_info[peerIdx].num_rate =
+			wlan_le32_to_cpu(fw_ifaceStat->peer_info[peerIdx].
+					 num_rate);
+
+		PRINTM(MINFO,
+		       "bitrate  tx_mpdu  rx_mpdu  mpdu_lost retries retries_short retries_long\n");
+		for (rate_idx = 0;
+		     rate_idx < iface_stat->peer_info[peerIdx].num_rate;
+		     rate_idx++) {
+			wlan_fill_hal_wifi_rate(priv,
+						&fw_ifaceStat->
+						peer_info[peerIdx].
+						rate_stats[rate_idx].rate,
+						&iface_stat->peer_info[peerIdx].
+						rate_stats[rate_idx].rate);
+
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				tx_mpdu =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].tx_mpdu);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				rx_mpdu =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].rx_mpdu);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				mpdu_lost =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].
+						 mpdu_lost);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				retries =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].retries);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				retries_short =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].
+						 retries_short);
+			iface_stat->peer_info[peerIdx].rate_stats[rate_idx].
+				retries_long =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx].
+						 rate_stats[rate_idx].
+						 retries_long);
+			PRINTM(MCMND,
+			       "0x%x  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x\n",
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].rate.bitrate,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].tx_mpdu,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].rx_mpdu,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].mpdu_lost,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].retries,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].retries_short,
+			       iface_stat->peer_info[peerIdx].
+			       rate_stats[rate_idx].retries_long);
+		}
+	}
+}
+
+/**
+ *  @brief This function handles the command response of get_link_statistic
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_get_link_statistic(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *resp, IN 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;
+}
diff --git a/wlan_sd8997/mlan/mlan_decl.h b/wlan_sd8997/mlan/mlan_decl.h
new file mode 100644
index 0000000..4ac8ad2
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_decl.h
@@ -0,0 +1,2066 @@
+/** @file mlan_decl.h
+ *
+ *  @brief This file declares the generic data structures and APIs.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+Change log:
+    11/07/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_DECL_H_
+#define _MLAN_DECL_H_
+
+/** MLAN release version */
+#define MLAN_RELEASE_VERSION		 "C536"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef signed char t_s8;
+/** Unsigned char (1-byte) */
+typedef unsigned char t_u8;
+/** Signed short (2-bytes) */
+typedef short t_s16;
+/** Unsigned short (2-bytes) */
+typedef unsigned short t_u16;
+/** Signed long (4-bytes) */
+typedef int t_s32;
+/** Unsigned long (4-bytes) */
+typedef unsigned int t_u32;
+/** Signed long long 8-bytes) */
+typedef long long t_s64;
+/** Unsigned long long 8-bytes) */
+typedef unsigned long long t_u64;
+/** Void pointer (4-bytes) */
+typedef void t_void;
+/** 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)
+
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM         (16)
+
+/** NET IP alignment */
+#define MLAN_NET_IP_ALIGN        2
+
+/** DMA alignment */
+/* SDIO3.0 Inrevium Adapter require 32 bit DMA alignment */
+#define DMA_ALIGNMENT            32
+
+/** max size of TxPD */
+#define MAX_TXPD_SIZE            32
+
+/** Minimum data header length */
+#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT+MAX_TXPD_SIZE)
+
+/** rx data header length */
+#define MLAN_RX_HEADER_LEN       MLAN_MIN_DATA_HEADER_LEN
+
+/** This is current limit on Maximum Tx AMPDU allowed */
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED          16
+#define MLAN_MAX_TX_BASTREAM_DEFAULT            2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED     16
+
+#ifdef STA_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_STA_AMPDU_DEF_TXWINSIZE       64
+/** Default Win size attached during ADDBA response */
+#define MLAN_STA_AMPDU_DEF_RXWINSIZE       64
+/** RX winsize for COEX */
+#define MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE  16
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_UAP_AMPDU_DEF_TXWINSIZE       48
+/** Default Win size attached during ADDBA response */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE       32
+/** 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
+
+/** NAN use the same window size for tx/rx */
+#define MLAN_NAN_AMPDU_DEF_TXRXWINSIZE     16
+/** RX winsize for COEX */
+#define MLAN_NAN_COEX_AMPDU_DEF_RXWINSIZE  16
+
+/** 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 7 */
+#define MLAN_RATE_INDEX_MCS7    7
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9    9
+/** 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 */
+#define MLAN_RX_DATA_BUF_SIZE     (4 * 1024)
+/** Size of rx command buffer */
+#define MLAN_RX_CMD_BUF_SIZE      (2 * 1024)
+
+#define MLAN_USB_RX_DATA_BUF_SIZE       MLAN_RX_DATA_BUF_SIZE
+
+/** 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
+
+/** 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           (4 * 1024)
+/** SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT       (16)
+
+/** SDIO IO Port mask */
+#define MLAN_SDIO_IO_PORT_MASK		0xfffff
+/** SDIO Block/Byte mode mask */
+#define MLAN_SDIO_BYTE_MODE_MASK	0x80000000
+
+/** Max retry number of IO write */
+#define MAX_WRITE_IOMEM_RETRY		2
+
+/** 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)
+
+/** 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 NET_MONITOR */
+#define MLAN_BUF_FLAG_NET_MONITOR        MBIT(11)
+
+/** Buffer flag for NULL data packet */
+#define MLAN_BUF_FLAG_NULL_PKT        MBIT(12)
+
+#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 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,
+	MLAN_STATUS_COMPLETE,
+} 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,
+	MLAN_BUF_TYPE_SPA_DATA,
+} mlan_buf_type;
+
+/** 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_NAN = 4,
+	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 bit mask */
+#define BSS_ROLE_BIT_MASK    MBIT(0)
+
+/** Get BSS role */
+#define GET_BSS_ROLE(priv)   ((priv)->bss_role & BSS_ROLE_BIT_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_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,
+	/* 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_FW_ROAM_OFFLOAD_RESULT = 0x80000023,
+	MLAN_EVENT_ID_NAN_STARTED = 0x80000024,
+	MLAN_EVENT_ID_DRV_RTT_RESULT = 0x80000025,
+	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;
+
+/** Data Structures */
+/** mlan_image data structure */
+typedef struct _mlan_fw_image {
+    /** Helper image buffer pointer */
+	t_u8 *phelper_buf;
+    /** Helper image length */
+	t_u32 helper_len;
+    /** 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;
+
+#define OID_TYPE_CAL    0x2
+#define OID_TYPE_DPD    0xa
+
+/** 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 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,
+};
+
+/** 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;
+
+/** 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[0];
+} mlan_event, *pmlan_event;
+
+/** 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;
+
+/** mix rate information structure */
+typedef MLAN_PACK_START struct _mix_rate_info {
+    /**  bit0: LGI: gi=0, SGI: gi= 1 */
+    /**  bit1-2: 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3  */
+    /**  bit3-4: LG: format=0, HT: format=1, VHT: format=2 */
+    /**  bit5: LDPC: 0-not support,  1-support */
+    /**  bit6-7:reserved */
+	t_u8 rate_info;
+    /** MCS index */
+	t_u8 mcs_index;
+    /** bitrate, in 500Kbps */
+	t_u16 bitrate;
+} MLAN_PACK_END mix_rate_info, *pmix_rate_info;
+
+/** rxpd extra information structure */
+typedef MLAN_PACK_START struct _rxpd_extra_info {
+    /** flags */
+	t_u8 flags;
+    /** channel.flags */
+	t_u16 channel_flags;
+    /** mcs.known */
+	t_u8 mcs_known;
+    /** mcs.flags */
+	t_u8 mcs_flags;
+    /** vht sig1 */
+	t_u32 vht_sig1;
+    /** vht sig2 */
+	t_u32 vht_sig2;
+} MLAN_PACK_END rxpd_extra_info, *prxpd_extra_info;
+
+/** rdaio tap information structure */
+typedef MLAN_PACK_START struct _radiotap_info {
+    /** Rate Info */
+	mix_rate_info rate_info;
+    /** SNR */
+	t_s8 snr;
+    /** Noise Floor */
+	t_s8 nf;
+    /** band config */
+	t_u8 band_config;
+    /** chan number */
+	t_u8 chan_num;
+    /** antenna */
+	t_u8 antenna;
+    /** extra rxpd info from FW */
+	rxpd_extra_info extra_info;
+} MLAN_PACK_END radiotap_info, *pradiotap_info;
+
+/** 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;
+    /** Offset to data */
+	t_u32 data_offset;
+    /** Data length */
+	t_u32 data_len;
+    /** Buffer type: data, cmd, event etc. */
+	mlan_buf_type buf_type;
+
+    /** Fields below are valid for data packet only */
+    /** QoS priority */
+	t_u32 priority;
+    /** Time stamp when packet is received (seconds) */
+	t_u32 in_ts_sec;
+    /** Time stamp when packet is received (micro seconds) */
+	t_u32 in_ts_usec;
+    /** Time stamp when packet is processed (seconds) */
+	t_u32 out_ts_sec;
+    /** Time stamp when packet is processed (micro seconds) */
+	t_u32 out_ts_usec;
+    /** tx_seq_num */
+	t_u32 tx_seq_num;
+
+    /** Fields below are valid for MLAN module only */
+    /** Pointer to parent mlan_buffer */
+	struct _mlan_buffer *pparent;
+    /** Use count for this buffer */
+	t_u32 use_count;
+	union {
+		pkt_txctrl tx_info;
+		pkt_rxinfo rx_info;
+	} u;
+} mlan_buffer, *pmlan_buffer;
+
+/** mlan_fw_info data structure */
+typedef struct _mlan_hw_info {
+    /** Firmware capabilities */
+	t_u32 fw_cap;
+} mlan_hw_info, *pmlan_hw_info;
+
+/** mlan_bss_attr data structure */
+typedef struct _mlan_bss_attr {
+    /** BSS type */
+	t_u32 bss_type;
+    /** Data frame type: Ethernet II, 802.11, etc. */
+	t_u32 frame_type;
+    /** The BSS is active (non-0) or not (0). */
+	t_u32 active;
+    /** BSS Priority */
+	t_u32 bss_priority;
+    /** BSS number */
+	t_u32 bss_num;
+    /** The BSS is virtual */
+	t_u32 bss_virtual;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+/** bss tbl data structure */
+typedef struct _mlan_bss_tbl {
+    /** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+} mlan_bss_tbl, *pmlan_bss_tbl;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** Type enumeration for the command result */
+typedef MLAN_PACK_START enum _mlan_cmd_result_e {
+	MLAN_CMD_RESULT_SUCCESS = 0,
+	MLAN_CMD_RESULT_FAILURE = 1,
+	MLAN_CMD_RESULT_TIMEOUT = 2,
+	MLAN_CMD_RESULT_INVALID_DATA = 3
+} MLAN_PACK_END mlan_cmd_result_e;
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} MLAN_PACK_END mlan_wmm_ac_e;
+
+/** Type enumeration for the action field in the Queue Config command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e {
+	MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_config_action_e;
+
+/** Type enumeration for the action field in the queue stats command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e {
+	MLAN_WMM_STATS_ACTION_START = 0,
+	MLAN_WMM_STATS_ACTION_STOP = 1,
+	MLAN_WMM_STATS_ACTION_GET_CLR = 2,
+	MLAN_WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_stats_action_e;
+
+/**
+ *  @brief IOCTL structure for a Traffic stream status.
+ *
+ */
+typedef MLAN_PACK_START struct {
+    /** TSID: Range: 0->7 */
+	t_u8 tid;
+    /** TSID specified is valid */
+	t_u8 valid;
+    /** AC TSID is active on */
+	t_u8 access_category;
+    /** UP specified for the TSID */
+	t_u8 user_priority;
+    /** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 psb;
+    /** Upstream(0), Downlink(1), Bidirectional(3) */
+	t_u8 flow_dir;
+    /** Medium time granted for the TSID */
+	t_u16 medium_time;
+} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t,
+/** Type definition of mlan_ds_wmm_ts_status for MLAN_OID_WMM_CFG_TS_STATUS */
+mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status;
+
+/** Max Ie length */
+#define MAX_IE_SIZE             256
+
+/** custom IE */
+typedef MLAN_PACK_START struct _custom_ie {
+    /** IE Index */
+	t_u16 ie_index;
+    /** Mgmt Subtype Mask */
+	t_u16 mgmt_subtype_mask;
+    /** IE Length */
+	t_u16 ie_length;
+    /** IE buffer */
+	t_u8 ie_buffer[MAX_IE_SIZE];
+} MLAN_PACK_END custom_ie;
+
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW         4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX               26
+
+/** custom IE info */
+typedef MLAN_PACK_START struct _custom_ie_info {
+    /** size of buffer */
+	t_u16 buf_size;
+    /** no of buffers of buf_size */
+	t_u16 buf_count;
+} MLAN_PACK_END custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** No of tuples */
+	t_u16 count;
+    /** custom IE info tuples */
+	custom_ie_info info[MAX_MGMT_IE_INDEX];
+} MLAN_PACK_END tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef MLAN_PACK_START struct _tlvbuf_custom_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** IE data */
+	custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW];
+    /** Max mgmt IE TLV */
+	tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+/** 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[0];
+} 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[0];
+		} 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[0];
+		} 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[0];
+		} 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;
+
+#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 {
+	WIFI_DISCONNECTED = 0,
+	WIFI_AUTHENTICATING = 1,
+	WIFI_ASSOCIATING = 2,
+	WIFI_ASSOCIATED = 3,
+    /** if done by firmware/driver */
+	WIFI_EAPOL_STARTED = 4,
+    /** if done by firmware/driver */
+	WIFI_EAPOL_COMPLETED = 5,
+} wifi_connection_state;
+/** roam state */
+typedef enum {
+	WIFI_ROAMING_IDLE = 0,
+	WIFI_ROAMING_ACTIVE = 1,
+} wifi_roam_state;
+/** interface mode */
+typedef enum {
+	WIFI_INTERFACE_STA = 0,
+	WIFI_INTERFACE_SOFTAP = 1,
+	WIFI_INTERFACE_IBSS = 2,
+	WIFI_INTERFACE_P2P_CLIENT = 3,
+	WIFI_INTERFACE_P2P_GO = 4,
+	WIFI_INTERFACE_NAN = 5,
+	WIFI_INTERFACE_MESH = 6,
+} wifi_interface_mode;
+
+/** set for QOS association */
+#define WIFI_CAPABILITY_QOS          0x00000001
+/** set for protected association (802.11 beacon frame control protected bit set) */
+#define WIFI_CAPABILITY_PROTECTED    0x00000002
+/** set if 802.11 Extended Capabilities element interworking bit is set */
+#define WIFI_CAPABILITY_INTERWORKING 0x00000004
+/** set for HS20 association */
+#define WIFI_CAPABILITY_HS20         0x00000008
+/** set is 802.11 Extended Capabilities element UTF-8 SSID bit is set */
+#define WIFI_CAPABILITY_SSID_UTF8    0x00000010
+/** set is 802.11 Country Element is present */
+#define WIFI_CAPABILITY_COUNTRY      0x00000020
+
+/** link layer status */
+typedef struct {
+    /** interface mode */
+	wifi_interface_mode mode;
+    /** interface mac address (self) */
+	t_u8 mac_addr[6];
+    /** connection state (valid for STA, CLI only) */
+	wifi_connection_state state;
+    /** roaming state */
+	wifi_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];
+} wifi_interface_link_layer_info;
+
+typedef wifi_interface_link_layer_info *wifi_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;
+
+/** 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 */
+	wifi_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) */
+
+/** =========== Define Copied from HAL START =========== */
+/** Ranging status */
+typedef enum {
+	RTT_STATUS_SUCCESS = 0,
+    /** general failure status */
+	RTT_STATUS_FAILURE = 1,
+    /** target STA does not respond to request */
+	RTT_STATUS_FAIL_NO_RSP = 2,
+    /** request rejected. Applies to 2-sided RTT only */
+	RTT_STATUS_FAIL_REJECTED = 3,
+	RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4,
+    /** timing measurement times out */
+	RTT_STATUS_FAIL_TM_TIMEOUT = 5,
+    /** Target on different channel, cannot range */
+	RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6,
+    /** ranging not supported */
+	RTT_STATUS_FAIL_NO_CAPABILITY = 7,
+    /** request aborted for unknown reason */
+	RTT_STATUS_ABORTED = 8,
+    /** Invalid T1-T4 timestamp */
+	RTT_STATUS_FAIL_INVALID_TS = 9,
+    /** 11mc protocol failed */
+	RTT_STATUS_FAIL_PROTOCOL = 10,
+    /** request could not be scheduled */
+	RTT_STATUS_FAIL_SCHEDULE = 11,
+    /** responder cannot collaborate at time of request */
+	RTT_STATUS_FAIL_BUSY_TRY_LATER = 12,
+    /** bad request args */
+	RTT_STATUS_INVALID_REQ = 13,
+    /** WiFi not enabled */
+	RTT_STATUS_NO_WIFI = 14,
+    /** Responder overrides param info, cannot range with new params */
+	RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15
+} wifi_rtt_status;
+
+/** RTT peer type */
+typedef enum {
+	RTT_PEER_AP = 0x1,
+	RTT_PEER_STA = 0x2,
+	RTT_PEER_P2P_GO = 0x3,
+	RTT_PEER_P2P_CLIENT = 0x4,
+	RTT_PEER_NAN = 0x5
+} rtt_peer_type;
+
+/** RTT Measurement Bandwidth */
+typedef enum {
+	WIFI_RTT_BW_5 = 0x01,
+	WIFI_RTT_BW_10 = 0x02,
+	WIFI_RTT_BW_20 = 0x04,
+	WIFI_RTT_BW_40 = 0x08,
+	WIFI_RTT_BW_80 = 0x10,
+	WIFI_RTT_BW_160 = 0x20
+} wifi_rtt_bw;
+
+/** RTT Type */
+typedef enum {
+	RTT_TYPE_1_SIDED = 0x1,
+	RTT_TYPE_2_SIDED = 0x2,
+} wifi_rtt_type;
+
+/** RTT configuration */
+typedef struct {
+    /** peer device mac address */
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+    /** 1-sided or 2-sided RTT */
+	wifi_rtt_type type;
+    /** optional - peer device hint (STA, P2P, AP) */
+	rtt_peer_type peer;
+    /** Required for STA-AP mode, optional for P2P, NBD etc. */
+	wifi_channel_info channel;
+    /** Time interval between bursts (units: 100 ms).
+      * Applies to 1-sided and 2-sided RTT multi-burst requests.
+      * Range: 0-31, 0: no preference by initiator (2-sided RTT) */
+	t_u32 burst_period;
+    /** Total number of RTT bursts to be executed. It will be
+      * specified in the same way as the parameter "Number of
+      * Burst Exponent" found in the FTM frame format. It
+      * applies to both: 1-sided RTT and 2-sided RTT. Valid
+      * values are 0 to 15 as defined in 802.11mc std.
+      * 0 means single shot
+      * The implication of this parameter on the maximum
+      * number of RTT results is the following:
+      * for 1-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst)
+      * for 2-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst - 1) */
+	t_u32 num_burst;
+    /** num of frames per burst. Minimum value = 1, Maximum value = 31
+      * For 2-sided this equals the number of FTM frames to be attempted in a single burst.
+      * This also equals the number of FTM frames that the initiator will request that the responder send
+      * in a single frame. */
+	t_u32 num_frames_per_burst;
+    /** number of retries for a failed RTT frame. Applies
+      * to 1-sided RTT only. Minimum value = 0, Maximum value = 3 */
+	t_u32 num_retries_per_rtt_frame;
+
+    /** following fields are only valid for 2-side RTT */
+    /** Maximum number of retries that the initiator can retry an FTMR frame.
+      * Minimum value = 0, Maximum value = 3 */
+	t_u32 num_retries_per_ftmr;
+    /** 1: request LCI, 0: do not request LCI */
+	t_u8 LCI_request;
+    /** 1: request LCR, 0: do not request LCR */
+	t_u8 LCR_request;
+    /** Applies to 1-sided and 2-sided RTT. Valid values will
+      * be 2-11 and 15 as specified by the 802.11mc std for
+      * the FTM parameter burst duration. In a multi-burst
+      * request, if responder overrides with larger value,
+      * the initiator will return failure. In a single-burst
+      * request if responder overrides with larger value,
+      * the initiator will sent TMR_STOP to terminate RTT
+      * at the end of the burst_duration it requested. */
+	t_u32 burst_duration;
+    /** RTT preamble to be used in the RTT frames */
+	wifi_preamble preamble;
+    /** RTT BW to be used in the RTT frames */
+	wifi_rtt_bw bw;
+} wifi_rtt_config;
+
+/** Format of information elements found in the beacon */
+typedef struct {
+    /** element identifier */
+	t_u8 id;
+    /** number of bytes to follow */
+	t_u8 len;
+	t_u8 data[];
+} wifi_information_element;
+
+/** RTT results */
+typedef struct {
+    /** device mac address */
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+    /** burst number in a multi-burst request */
+	t_u32 burst_num;
+    /** Total RTT measurement frames attempted */
+	t_u32 measurement_number;
+    /** Total successful RTT measurement frames */
+	t_u32 success_number;
+    /** Maximum number of "FTM frames per burst" supported by
+      * the responder STA. Applies to 2-sided RTT only.
+      * If reponder overrides with larger value:
+      * - for single-burst request initiator will truncate the
+      * larger value and send a TMR_STOP after receiving as
+      * many frames as originally requested.
+      * - for multi-burst request, initiator will return
+      * failure right away */
+	t_u8 number_per_burst_peer;
+    /** ranging status */
+	wifi_rtt_status status;
+    /** When status == RTT_STATUS_FAIL_BUSY_TRY_LATER,
+      * this will be the time provided by the responder as to
+      * when the request can be tried again. Applies to 2-sided
+      * RTT only. In sec, 1-31sec. */
+	t_u8 retry_after_duration;
+    /** RTT type */
+	wifi_rtt_type type;
+    /** average rssi in 0.5 dB steps e.g. 143 implies -71.5 dB */
+	int rssi;
+    /** rssi spread in 0.5 dB steps e.g. 5 implies 2.5 dB spread (optional) */
+	int rssi_spread;
+    /** 1-sided RTT: TX rate of RTT frame.
+      * 2-sided RTT: TX rate of initiator's Ack in response to FTM frame. */
+	wifi_rate tx_rate;
+    /** 1-sided RTT: TX rate of Ack from other side.
+      * 2-sided RTT: TX rate of FTM frame coming from responder. */
+	wifi_rate rx_rate;
+    /** round trip time in picoseconds */
+	t_s64 rtt;
+    /** rtt standard deviation in picoseconds */
+	t_s64 rtt_sd;
+    /** difference between max and min rtt times recorded in picoseconds */
+	t_s64 rtt_spread;
+    /** distance in mm (optional) */
+	int distance_mm;
+    /** standard deviation in mm (optional) */
+	int distance_sd_mm;
+    /** difference between max and min distance recorded in mm (optional) */
+	int distance_spread_mm;
+    /** time of the measurement (in microseconds since boot) */
+	t_s64 ts;
+    /** in ms, actual time taken by the FW to finish one burst
+      * measurement. Applies to 1-sided and 2-sided RTT. */
+	int burst_duration;
+    /** Number of bursts allowed by the responder. Applies
+      * to 2-sided RTT only. */
+	int negotiated_burst_num;
+    /** for 11mc only */
+	wifi_information_element *LCI;
+    /** for 11mc only */
+	wifi_information_element *LCR;
+} wifi_rtt_result;
+
+/** Preamble definition for bit mask used in wifi_rtt_capabilities */
+#define PREAMBLE_LEGACY 0x1
+#define PREAMBLE_HT     0x2
+#define PREAMBLE_VHT    0x4
+
+/** BW definition for bit mask used in wifi_rtt_capabilities */
+#define BW_5_SUPPORT   0x1
+#define BW_10_SUPPORT  0x2
+#define BW_20_SUPPORT  0x4
+#define BW_40_SUPPORT  0x8
+#define BW_80_SUPPORT  0x10
+#define BW_160_SUPPORT 0x20
+
+/** RTT Capabilities */
+typedef struct {
+    /** if 1-sided rtt data collection is supported */
+	t_u8 rtt_one_sided_supported;
+    /** if ftm rtt data collection is supported */
+	t_u8 rtt_ftm_supported;
+    /** if initiator supports LCI request. Applies to 2-sided RTT */
+	t_u8 lci_support;
+    /** if initiator supports LCR request. Applies to 2-sided RTT */
+	t_u8 lcr_support;
+    /** bit mask indicates what preamble is supported by initiator */
+	t_u8 preamble_support;
+    /** bit mask indicates what BW is supported by initiator */
+	t_u8 bw_support;
+    /** if 11mc responder mode is supported */
+	t_u8 responder_supported;
+    /** draft 11mc spec version supported by chip. For instance,
+      * version 4.0 should be 40 and version 4.3 should be 43 etc. */
+	t_u8 mc_version;
+} wifi_rtt_capabilities;
+
+/** API for setting LCI/LCR information to be provided to a requestor */
+typedef enum {
+    /** Not expected to change location */
+	WIFI_MOTION_NOT_EXPECTED = 0,
+    /** Expected to change location */
+	WIFI_MOTION_EXPECTED = 1,
+    /** Movement pattern unknown */
+	WIFI_MOTION_UNKNOWN = 2,
+} wifi_motion_pattern;
+
+/** LCI information */
+typedef struct {
+    /** latitude in degrees * 2^25 , 2's complement */
+	long latitude;
+    /** latitude in degrees * 2^25 , 2's complement */
+	long longitude;
+    /** Altitude in units of 1/256 m */
+	int altitude;
+    /** As defined in Section 2.3.2 of IETF RFC 6225 */
+	t_u8 latitude_unc;
+    /** As defined in Section 2.3.2 of IETF RFC 6225 */
+	t_u8 longitude_unc;
+    /** As defined in Section 2.4.5 from IETF RFC 6225: */
+	t_u8 altitude_unc;
+    /** Following element for configuring the Z subelement */
+	wifi_motion_pattern motion_pattern;
+    /** floor in units of 1/16th of floor. 0x80000000 if unknown. */
+	int floor;
+    /** in units of 1/64 m */
+	int height_above_floor;
+    /** in units of 1/64 m. 0 if unknown */
+	int height_unc;
+} wifi_lci_information;
+
+/** LCR information */
+typedef struct {
+    /** country code */
+	char country_code[2];
+    /** length of the info field */
+	int length;
+    /** Civic info to be copied in FTM frame */
+	char civic_info[256];
+} wifi_lcr_information;
+
+/**
+ * RTT Responder information
+ */
+typedef struct {
+	wifi_channel_info channel;
+	wifi_preamble preamble;
+} wifi_rtt_responder;
+
+/** =========== Define Copied from HAL END =========== */
+
+#define MAX_RTT_CONFIG_NUM 10
+
+/** RTT config params */
+typedef struct wifi_rtt_config_params {
+	t_u8 rtt_config_num;
+	wifi_rtt_config rtt_config[MAX_RTT_CONFIG_NUM];
+} wifi_rtt_config_params_t;
+
+#define OID_RTT_REQUEST  0
+#define OID_RTT_CANCEL   1
+
+/** Pass RTT result element between mlan and moal */
+typedef struct {
+    /** element identifier  */
+	t_u16 id;
+    /** number of bytes to follow  */
+	t_u16 len;
+    /** data: fill with one wifi_rtt_result  */
+	t_u8 data[0];
+} wifi_rtt_result_element;
+
+#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) (IN t_void *pmoal_handle,
+					 IN t_u32 offset,
+					 IN t_u32 len, OUT t_u8 *pbuf);
+    /** moal_get_hw_spec_complete */
+	mlan_status (*moal_get_hw_spec_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status,
+						  IN mlan_hw_info * phw,
+						  IN pmlan_bss_tbl ptbl);
+    /** moal_init_fw_complete */
+	mlan_status (*moal_init_fw_complete) (IN t_void *pmoal_handle,
+					      IN mlan_status status);
+    /** moal_shutdown_fw_complete */
+	mlan_status (*moal_shutdown_fw_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status);
+    /** moal_send_packet_complete */
+	mlan_status (*moal_send_packet_complete) (IN t_void *pmoal_handle,
+						  IN pmlan_buffer pmbuf,
+						  IN mlan_status status);
+    /** moal_recv_complete */
+	mlan_status (*moal_recv_complete) (IN t_void *pmoal_handle,
+					   IN pmlan_buffer pmbuf,
+					   IN t_u32 port,
+					   IN mlan_status status);
+    /** moal_recv_packet */
+	mlan_status (*moal_recv_packet) (IN t_void *pmoal_handle,
+					 IN pmlan_buffer pmbuf);
+    /** moal_recv_event */
+	mlan_status (*moal_recv_event) (IN t_void *pmoal_handle,
+					IN pmlan_event pmevent);
+    /** moal_ioctl_complete */
+	mlan_status (*moal_ioctl_complete) (IN t_void *pmoal_handle,
+					    IN pmlan_ioctl_req pioctl_req,
+					    IN mlan_status status);
+
+    /** moal_alloc_mlan_buffer */
+	mlan_status (*moal_alloc_mlan_buffer) (IN t_void *pmoal_handle,
+					       IN t_u32 size,
+					       OUT pmlan_buffer *pmbuf);
+    /** moal_free_mlan_buffer */
+	mlan_status (*moal_free_mlan_buffer) (IN t_void *pmoal_handle,
+					      IN pmlan_buffer pmbuf);
+
+    /** moal_write_reg */
+	mlan_status (*moal_write_reg) (IN t_void *pmoal_handle,
+				       IN t_u32 reg, IN t_u32 data);
+    /** moal_read_reg */
+	mlan_status (*moal_read_reg) (IN t_void *pmoal_handle,
+				      IN t_u32 reg, OUT t_u32 *data);
+    /** moal_write_data_sync */
+	mlan_status (*moal_write_data_sync) (IN t_void *pmoal_handle,
+					     IN pmlan_buffer pmbuf,
+					     IN t_u32 port, IN t_u32 timeout);
+    /** moal_read_data_sync */
+	mlan_status (*moal_read_data_sync) (IN t_void *pmoal_handle,
+					    IN OUT pmlan_buffer pmbuf,
+					    IN t_u32 port, IN t_u32 timeout);
+    /** moal_malloc */
+	mlan_status (*moal_malloc) (IN t_void *pmoal_handle,
+				    IN t_u32 size,
+				    IN t_u32 flag, OUT t_u8 **ppbuf);
+    /** moal_mfree */
+	mlan_status (*moal_mfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_vmalloc */
+	mlan_status (*moal_vmalloc) (IN t_void *pmoal_handle,
+				     IN t_u32 size, OUT t_u8 **ppbuf);
+    /** moal_vfree */
+	mlan_status (*moal_vfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_memset */
+	t_void *(*moal_memset) (IN t_void *pmoal_handle,
+				IN t_void *pmem, IN t_u8 byte, IN t_u32 num);
+    /** moal_memcpy */
+	t_void *(*moal_memcpy) (IN t_void *pmoal_handle,
+				IN t_void *pdest,
+				IN const t_void *psrc, IN t_u32 num);
+    /** moal_memmove */
+	t_void *(*moal_memmove) (IN t_void *pmoal_handle,
+				 IN t_void *pdest,
+				 IN const t_void *psrc, IN t_u32 num);
+    /** moal_memcmp */
+	t_s32 (*moal_memcmp) (IN t_void *pmoal_handle,
+			      IN const t_void *pmem1,
+			      IN const t_void *pmem2, IN t_u32 num);
+    /** moal_udelay */
+	t_void (*moal_udelay) (IN t_void *pmoal_handle, IN t_u32 udelay);
+    /** moal_get_system_time */
+	mlan_status (*moal_get_system_time) (IN t_void *pmoal_handle,
+					     OUT t_u32 *psec, OUT t_u32 *pusec);
+    /** moal_init_timer*/
+	mlan_status (*moal_init_timer) (IN t_void *pmoal_handle,
+					OUT t_void **pptimer,
+					IN t_void (*callback) (t_void
+							       *pcontext),
+					IN t_void *pcontext);
+    /** moal_free_timer */
+	mlan_status (*moal_free_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_start_timer*/
+	mlan_status (*moal_start_timer) (IN t_void *pmoal_handle,
+					 IN t_void *ptimer,
+					 IN t_u8 periodic, IN t_u32 msec);
+    /** moal_stop_timer*/
+	mlan_status (*moal_stop_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_init_lock */
+	mlan_status (*moal_init_lock) (IN t_void *pmoal_handle,
+				       OUT t_void **pplock);
+    /** moal_free_lock */
+	mlan_status (*moal_free_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_lock */
+	mlan_status (*moal_spin_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_unlock */
+	mlan_status (*moal_spin_unlock) (IN t_void *pmoal_handle,
+					 IN t_void *plock);
+    /** moal_print */
+	t_void (*moal_print) (IN t_void *pmoal_handle,
+			      IN t_u32 level, IN char *pformat, IN ...
+		);
+    /** moal_print_netintf */
+	t_void (*moal_print_netintf) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index, IN t_u32 level);
+    /** moal_assert */
+	t_void (*moal_assert) (IN t_void *pmoal_handle, IN t_u32 cond);
+    /** moal_hist_data_add */
+	t_void (*moal_hist_data_add) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index,
+				      IN t_u8 rx_rate,
+				      IN t_s8 snr,
+				      IN t_s8 nflr, IN t_u8 antenna);
+	t_void (*moal_updata_peer_signal) (IN t_void *pmoal_handle,
+					   IN t_u32 bss_index,
+					   IN t_u8 *peer_addr,
+					   IN t_s8 snr, IN t_s8 nflr);
+	mlan_status (*moal_get_host_time_ns) (OUT t_u64 *time);
+	t_u64 (*moal_do_div) (IN t_u64 num, IN t_u32 base);
+} 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
+
+/** 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
+
+/** 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
+
+/** 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
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#ifdef DEBUG_LEVEL1
+    /** Driver debug bit masks */
+	t_u32 drvdbg;
+#endif
+    /** allocate fixed buffer size for scan beacon buffer*/
+	t_u32 fixed_beacon_buffer;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** SDIO MPA Rx */
+	t_u32 mpa_rx_cfg;
+#endif
+	/** SDIO Single port rx aggr */
+	t_u8 sdio_rx_aggr_enable;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/* 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
+    /** 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;
+    /** Host sleep wakeup interval */
+	t_u32 hs_wake_interval;
+    /** GPIO to indicate wakeup source */
+	t_u8 indication_gpio;
+    /** channel time and mode for DRCS*/
+	t_u32 drcs_chantime_mode;
+	t_bool fw_region;
+} mlan_device, *pmlan_device;
+
+/** MLAN API function prototype */
+#define MLAN_API
+
+/** Registration */
+MLAN_API mlan_status mlan_register(IN pmlan_device pmdevice,
+				   OUT t_void **ppmlan_adapter);
+
+/** Un-registration */
+MLAN_API mlan_status mlan_unregister(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Downloading */
+MLAN_API mlan_status mlan_dnld_fw(IN t_void *pmlan_adapter,
+				  IN pmlan_fw_image pmfw);
+
+/** Custom data pass API */
+MLAN_API mlan_status mlan_set_init_param(IN t_void *pmlan_adapter,
+					 IN pmlan_init_param pparam);
+
+/** Firmware Initialization */
+MLAN_API mlan_status mlan_init_fw(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Shutdown */
+MLAN_API mlan_status mlan_shutdown_fw(IN t_void *pmlan_adapter
+	);
+
+/** Main Process */
+MLAN_API mlan_status mlan_main_process(IN t_void *pmlan_adapter
+	);
+
+/** Rx process */
+mlan_status mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts);
+
+/** Packet Transmission */
+MLAN_API mlan_status mlan_send_packet(IN t_void *pmlan_adapter,
+				      IN pmlan_buffer pmbuf);
+
+/** Packet Reception complete callback */
+MLAN_API mlan_status mlan_recv_packet_complete(IN t_void *pmlan_adapter,
+					       IN pmlan_buffer pmbuf,
+					       IN mlan_status status);
+
+/** interrupt handler */
+MLAN_API mlan_status mlan_interrupt(IN t_void *pmlan_adapter);
+
+#if defined(SYSKT)
+/** GPIO IRQ callback function */
+MLAN_API t_void mlan_hs_callback(IN t_void *pctx);
+#endif /* SYSKT_MULTI || SYSKT */
+
+MLAN_API t_void mlan_pm_wakeup_card(IN t_void *pmlan_adapter);
+
+MLAN_API t_u8 mlan_is_main_process_running(IN t_void *adapter);
+
+/** mlan ioctl */
+MLAN_API mlan_status mlan_ioctl(IN t_void *pmlan_adapter,
+				IN pmlan_ioctl_req pioctl_req);
+/** mlan select wmm queue */
+MLAN_API t_u8 mlan_select_wmm_queue(IN t_void *pmlan_adapter,
+				    IN t_u8 bss_num, IN t_u8 tid);
+#endif /* !_MLAN_DECL_H_ */
diff --git a/wlan_sd8997/mlan/mlan_fw.h b/wlan_sd8997/mlan/mlan_fw.h
new file mode 100644
index 0000000..320298f
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_fw.h
@@ -0,0 +1,7065 @@
+/** @file mlan_fw.h
+ *
+ *  @brief This file contains firmware specific defines.
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/27/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_FW_H_
+#define _MLAN_FW_H_
+
+/** Interface header length */
+#define INTF_HEADER_LEN     4
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** 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];
+
+/** Firmware wakeup method : Unchanged */
+#define WAKEUP_FW_UNCHANGED                     0
+/** Firmware wakeup method : Through interface */
+#define WAKEUP_FW_THRU_INTERFACE                1
+/** Firmware wakeup method : Through GPIO*/
+#define WAKEUP_FW_THRU_GPIO                     2
+/** Default value of GPIO */
+#define DEF_WAKEUP_FW_GPIO                      0
+
+/** Default auto deep sleep mode */
+#define DEFAULT_AUTO_DS_MODE                  MTRUE
+/** Default power save mode */
+#define DEFAULT_PS_MODE                 Wlan802_11PowerModePSP
+
+#define EVENT_NAN_GENERIC 0x00000075
+#define NAN_EVT_SUBTYPE_SD_EVENT 0
+#define NAN_EVT_SUBTYPE_NAN_STARTED 1
+#define NAN_EVT_SUBTYPE_SDF_TX_DONE 2
+
+#define EVENT_WLS_FTM_COMPLETE 0x00000086
+
+#define WLS_SUB_EVENT_FTM_COMPLETE          0
+#define WLS_SUB_EVENT_RADIO_RECEIVED        1
+#define WLS_SUB_EVENT_RADIO_RPT_RECEIVED    2
+#define WLS_SUB_EVENT_ANQP_RESP_RECEIVED    3
+#define WLS_SUB_EVENT_RTT_RESULTS           4
+
+/** 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_ID;
+
+/** Key Info flag for multicast key */
+#define KEY_INFO_MCAST_KEY      0x01
+/** Key Info flag for unicast key */
+#define KEY_INFO_UCAST_KEY      0x02
+
+/** KEY_INFO_WEP*/
+typedef enum _KEY_INFO_WEP {
+	KEY_INFO_WEP_MCAST = 0x01,
+	KEY_INFO_WEP_UNICAST = 0x02,
+	KEY_INFO_WEP_ENABLED = 0x04
+} KEY_INFO_WEP;
+
+/** KEY_INFO_TKIP */
+typedef enum _KEY_INFO_TKIP {
+	KEY_INFO_TKIP_MCAST = 0x01,
+	KEY_INFO_TKIP_UNICAST = 0x02,
+	KEY_INFO_TKIP_ENABLED = 0x04
+} KEY_INFO_TKIP;
+
+/** KEY_INFO_AES*/
+typedef enum _KEY_INFO_AES {
+	KEY_INFO_AES_MCAST = 0x01,
+	KEY_INFO_AES_UNICAST = 0x02,
+	KEY_INFO_AES_ENABLED = 0x04,
+	KEY_INFO_AES_MCAST_IGTK = 0x400,
+} KEY_INFO_AES;
+
+/** WPA AES key length */
+#define WPA_AES_KEY_LEN                 16
+/** WPA TKIP key length */
+#define WPA_TKIP_KEY_LEN                32
+/** WPA AES IGTK key length */
+#define CMAC_AES_KEY_LEN                16
+/** IGTK key length */
+#define WPA_IGTK_KEY_LEN                16
+
+/** WAPI key length */
+#define WAPI_KEY_LEN            50
+/** KEY_INFO_WAPI*/
+typedef enum _KEY_INFO_WAPI {
+	KEY_INFO_WAPI_MCAST = 0x01,
+	KEY_INFO_WAPI_UNICAST = 0x02,
+	KEY_INFO_WAPI_ENABLED = 0x04
+} KEY_INFO_WAPI;
+
+/** Maximum ethernet frame length sans FCS */
+#define MV_ETH_FRAME_LEN   1514
+
+/** 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
+
+/** This is for firmware specific length */
+#define EXTRA_LEN	36
+
+/** 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)
+
+/* Macros in interface module */
+/** Firmware ready */
+#define FIRMWARE_READY          0xfedc
+
+/** Number of firmware blocks to transfer */
+#define FIRMWARE_TRANSFER_NBLOCK	2
+
+/** 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
+
+/** TLV  type ID definition */
+#define PROPRIETARY_TLV_BASE_ID                 0x0100
+
+/** 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
+
+/** 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 : Passphrase */
+#define TLV_TYPE_PASSPHRASE         (PROPRIETARY_TLV_BASE_ID + 0x3c)	/* 0x013c */
+
+/** 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 : ENABLE ROAM IE */
+#define TLV_TYPE_ROAM                (PROPRIETARY_TLV_BASE_ID + 245)
+/** TLV type : AP LIST IE */
+#define TLV_TYPE_APLIST              (PROPRIETARY_TLV_BASE_ID + 246)
+/** TLV type : PMK */
+#define TLV_TYPE_PMK_R0             (PROPRIETARY_TLV_BASE_ID + 247)
+/** TLV type : PMK */
+#define TLV_TYPE_PMK_R0_NAME        (PROPRIETARY_TLV_BASE_ID + 248)
+/** TLV type : TRIGGER CONDITION*/
+#define TLV_TYPE_ROM_TRIGGER        (PROPRIETARY_TLV_BASE_ID + 264)
+/** TLV type : RETRY_COUNT*/
+#define TLV_TYPE_ROM_RETRY_COUNT    (PROPRIETARY_TLV_BASE_ID + 265)
+/** TLV type : BGSCAN SETTING*/
+#define TLV_TYPE_ROM_BGSCAN         (PROPRIETARY_TLV_BASE_ID + 266)
+/** TLV type : PARA RSSI*/
+#define TLV_TYPE_ROM_PARA_RSSI      (PROPRIETARY_TLV_BASE_ID + 267)
+/** TLV type : BSSID blacklist*/
+#define TLV_TYPE_BLACKLIST_BSSID    (PROPRIETARY_TLV_BASE_ID + 0x11d)
+/** TLV type : BAND & RSSI*/
+#define TLV_TYPE_BAND_RSSI          (PROPRIETARY_TLV_BASE_ID + 0x11e)
+/** TLV type : ESS scan*/
+#define TLV_TYPE_ENERGYEFFICIENTSCAN	(PROPRIETARY_TLV_BASE_ID + 0xda)
+/** TLV type : KEY params*/
+#define TLV_TYPE_ROAM_OFFLOAD_USER_SET_PMK  	(PROPRIETARY_TLV_BASE_ID + 291)
+
+/** 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: robustcoex mode */
+#define TLV_TYPE_ROBUSTCOEX           (PROPRIETARY_TLV_BASE_ID + 0x11B)	/* 0x021B */
+
+/** 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 : 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)
+
+#define TLV_TYPE_LL_STAT_IFACE                     (PROPRIETARY_TLV_BASE_ID + 300)
+#define TLV_TYPE_LL_STAT_RADIO                     (PROPRIETARY_TLV_BASE_ID + 301)
+
+/** 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
+/** Test if adhoc 11n is enabled */
+#define IS_11N_ADHOC_ENABLED(priv) ((priv->bss_mode == MLAN_BSS_MODE_IBSS) && pmadapter->adhoc_11n_enabled)
+#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)
+/** Find out if we are the initiator or not */
+#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) & \
+			MBIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS)
+
+/** 4K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_4K        4096
+/** 8K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_8K        8192
+/** 12K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_12K        12288
+/** Max Rx AMPDU Size */
+#define MAX_RX_AMPDU_SIZE_64K   0x03
+/** Non green field station */
+#define NON_GREENFIELD_STAS     0x04
+
+/** Greenfield support */
+#define HWSPEC_GREENFIELD_SUPP   MBIT(29)
+/** RX STBC support */
+#define HWSPEC_RXSTBC_SUPP   MBIT(26)
+/** ShortGI @ 40Mhz support */
+#define HWSPEC_SHORTGI40_SUPP    MBIT(24)
+/** ShortGI @ 20Mhz support */
+#define HWSPEC_SHORTGI20_SUPP    MBIT(23)
+/** RX LDPC support */
+#define HWSPEC_LDPC_SUPP         MBIT(22)
+/** Channel width 40Mhz support */
+#define HWSPEC_CHANBW40_SUPP     MBIT(17)
+/** 40Mhz intolarent enable */
+#define CAPINFO_40MHZ_INTOLARENT MBIT(8)
+
+/** Default 11n capability mask for 2.4GHz */
+#define DEFAULT_11N_CAP_MASK_BG (HWSPEC_SHORTGI20_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+/** Default 11n capability mask for 5GHz */
+#define DEFAULT_11N_CAP_MASK_A  (HWSPEC_CHANBW40_SUPP | HWSPEC_SHORTGI20_SUPP | \
+		HWSPEC_SHORTGI40_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+
+/** Default 11n TX BF capability **/
+#define DEFAULT_11N_TX_BF_CAP   0x19E74618
+
+/** Bits to ignore in hw_dev_cap as these bits are set in get_hw_spec */
+#define IGN_HW_DEV_CAP      (CAPINFO_40MHZ_INTOLARENT)
+
+/** HW_SPEC FwCapInfo */
+#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & MBIT(11))
+
+/** HW_SPEC Dot11nDevCap : MAX AMSDU supported */
+#define ISSUPP_MAXAMSDU(Dot11nDevCap) (Dot11nDevCap & MBIT(31))
+/** HW_SPEC Dot11nDevCap : Beamforming support */
+#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & MBIT(30))
+/** HW_SPEC Dot11nDevCap : Green field support */
+#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & MBIT(29))
+/** HW_SPEC Dot11nDevCap : AMPDU support */
+#define ISSUPP_AMPDU(Dot11nDevCap) (Dot11nDevCap & MBIT(28))
+/** HW_SPEC Dot11nDevCap : MIMO PS support  */
+#define ISSUPP_MIMOPS(Dot11nDevCap) (Dot11nDevCap & MBIT(27))
+/** HW_SPEC Dot11nDevCap : Rx STBC support */
+#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & MBIT(26))
+/** HW_SPEC Dot11nDevCap : Tx STBC support */
+#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & MBIT(25))
+/** HW_SPEC Dot11nDevCap : Short GI @ 40Mhz support */
+#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24))
+/** HW_SPEC Dot11nDevCap : Reset Short GI @ 40Mhz support */
+#define RESETSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(24))
+/** HW_SPEC Dot11nDevCap : Short GI @ 20Mhz support */
+#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & MBIT(23))
+/** HW_SPEC Dot11nDevCap : Rx LDPC support */
+#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & MBIT(22))
+/** HW_SPEC Dot11nDevCap : Number of TX BA streams supported */
+#define ISSUPP_GETTXBASTREAM(Dot11nDevCap) ((Dot11nDevCap >> 18) & 0xF)
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 40Mhz  support */
+#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 20Mhz  support */
+#define ISSUPP_CHANWIDTH20(Dot11nDevCap) (Dot11nDevCap & MBIT(16))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 10Mhz  support */
+#define ISSUPP_CHANWIDTH10(Dot11nDevCap) (Dot11nDevCap & MBIT(15))
+/** Dot11nUsrCap : 40Mhz intolarance enabled */
+#define ISENABLED_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap & MBIT(8))
+/** Dot11nUsrCap : Reset 40Mhz intolarance enabled */
+#define RESET_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(8))
+/** HW_SPEC Dot11nDevCap : Rx AntennaD support */
+#define ISSUPP_RXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(7))
+/** HW_SPEC Dot11nDevCap : Rx AntennaC support */
+#define ISSUPP_RXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(6))
+/** HW_SPEC Dot11nDevCap : Rx AntennaB support */
+#define ISSUPP_RXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(5))
+/** HW_SPEC Dot11nDevCap : Rx AntennaA support */
+#define ISSUPP_RXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(4))
+/** HW_SPEC Dot11nDevCap : Tx AntennaD support */
+#define ISSUPP_TXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(3))
+/** HW_SPEC Dot11nDevCap : Tx AntennaC support */
+#define ISSUPP_TXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(2))
+/** HW_SPEC Dot11nDevCap : Tx AntennaB support */
+#define ISSUPP_TXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(1))
+/** HW_SPEC Dot11nDevCap : Tx AntennaA support */
+#define ISSUPP_TXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(0))
+
+/** HW_SPEC Dot11nDevCap : Set support of channel bw @ 40Mhz */
+#define SETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap |= MBIT(17))
+/** HW_SPEC Dot11nDevCap : Reset support of channel bw @ 40Mhz */
+#define RESETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(17))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_TXMCSSUPP(DevMCSSupported) (DevMCSSupported >> 4)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
+
+/** GET HTCapInfo : Supported Channel BW */
+#define GETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo & MBIT(1))
+/** GET HTCapInfo : Support for Greenfield */
+#define GETHT_GREENFIELD(HTCapInfo) (HTCapInfo & MBIT(4))
+/** GET HTCapInfo : Support for Short GI @ 20Mhz */
+#define GETHT_SHORTGI20(HTCapInfo) (HTCapInfo & MBIT(5))
+/** GET HTCapInfo : Support for Short GI @ 40Mhz */
+#define GETHT_SHORTGI40(HTCapInfo) (HTCapInfo & MBIT(6))
+/** GET HTCapInfo : Support for Tx STBC */
+#define GETHT_TXSTBC(HTCapInfo) (HTCapInfo & MBIT(7))
+
+/** GET HTCapInfo : Support for Rx STBC */
+#define GETHT_RXSTBC(HTCapInfo) ((HTCapInfo >> 8) & 0x03)
+/** GET HTCapInfo : Support for Delayed ACK */
+#define GETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo & MBIT(10))
+/** GET HTCapInfo : Support for Max AMSDU */
+#define GETHT_MAXAMSDU(HTCapInfo) (HTCapInfo & MBIT(11))
+
+/** SET HTCapInfo : Set support for LDPC coding capability */
+#define SETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo |= MBIT(0))
+/** SET HTCapInfo : Set support for Channel BW */
+#define SETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo |= MBIT(1))
+/** SET HTCapInfo : Set support for Greenfield */
+#define SETHT_GREENFIELD(HTCapInfo) (HTCapInfo |= MBIT(4))
+/** SET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define SETHT_SHORTGI20(HTCapInfo) (HTCapInfo |= MBIT(5))
+/** SET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define SETHT_SHORTGI40(HTCapInfo) (HTCapInfo |= MBIT(6))
+/** SET HTCapInfo : Set support for Tx STBC */
+#define SETHT_TXSTBC(HTCapInfo) (HTCapInfo |= MBIT(7))
+/** SET HTCapInfo : Set support for Rx STBC */
+#define SETHT_RXSTBC(HTCapInfo, value) (HTCapInfo |= (value << 8))
+/** SET HTCapInfo : Set support for delayed block ack */
+#define SETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo |= MBIT(10))
+/** SET HTCapInfo : Set support for Max size AMSDU */
+#define SETHT_MAXAMSDU(HTCapInfo) (HTCapInfo |= MBIT(11))
+/** SET HTCapInfo : Set support for DSSS/CCK Rates @ 40Mhz */
+#define SETHT_DSSSCCK40(HTCapInfo) (HTCapInfo |= MBIT(12))
+/** SET HTCapInfo : Enable 40Mhz Intolarence */
+#define SETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo |= MBIT(14))
+/** SET HTCapInfo : Disable Static SM power save */
+#define SETHT_STATIC_SMPS(HTCapInfo) ((HTCapInfo) |= (MBIT(2) | MBIT(3)))
+
+/** RESET HTCapInfo : Set support for LDPC coding capability */
+#define RESETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo &= ~MBIT(0))
+/** RESET HTCapInfo : Set support for Channel BW */
+#define RESETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo &= ~MBIT(1))
+/** RESET HTCapInfo : Set support for Greenfield */
+#define RESETHT_GREENFIELD(HTCapInfo) (HTCapInfo &= ~MBIT(4))
+/** RESET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define RESETHT_SHORTGI20(HTCapInfo) (HTCapInfo &= ~MBIT(5))
+/** RESET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define RESETHT_SHORTGI40(HTCapInfo) (HTCapInfo &= ~MBIT(6))
+/** RESET HTCapInfo : Set support for Tx STBC */
+#define RESETHT_TXSTBC(HTCapInfo) (HTCapInfo &= ~MBIT(7))
+/** RESET HTCapInfo : Set support for Rx STBC */
+#define RESETHT_RXSTBC(HTCapInfo) (HTCapInfo &= ~(0x03 << 8))
+/** RESET HTCapInfo : Set support for delayed block ack */
+#define RESETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo &= ~MBIT(10))
+/** RESET HTCapInfo : Set support for Max size AMSDU */
+#define RESETHT_MAXAMSDU(HTCapInfo) (HTCapInfo &= ~MBIT(11))
+/** RESET HTCapInfo : Disable 40Mhz Intolarence */
+#define RESETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo &= ~MBIT(14))
+/** RESET HTCapInfo: Enable SM power save */
+#define RESETHT_SM_POWERSAVE(HTCapInfo) ((HTCapInfo) &= ~(MBIT(2) | MBIT(3)))
+/** RESET HTExtCap : Clear RD Responder bit */
+#define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~MBIT(11))
+/** SET MCS32 */
+#define SETHT_MCS32(x) (x[4] |= 1)
+/** Set mcs set defined bit */
+#define SETHT_MCS_SET_DEFINED(x) (x[12] |= 1)
+/** Set the highest Rx data rate */
+#define SETHT_RX_HIGHEST_DT_SUPP(x, y) ((*(t_u16 *) (x + 10)) = y)
+/** AMPDU factor size */
+#define AMPDU_FACTOR_64K	0x03
+/** Set AMPDU size in A-MPDU paramter field */
+#define SETAMPDU_SIZE(x, y) do { \
+	x = x & ~0x03; \
+	x |= y & 0x03; \
+} while (0) \
+/** Set AMPDU spacing in A-MPDU paramter field */
+#define SETAMPDU_SPACING(x, y) do { \
+	x = x & ~0x1c; \
+	x |= (y & 0x07) << 2; \
+} while (0) \
+
+/** RadioType : Support for Band A */
+#define ISSUPP_BANDA(FwCapInfo) (FwCapInfo & MBIT(10))
+/** RadioType : Support for 40Mhz channel BW */
+#define ISALLOWED_CHANWIDTH40(Field2) (Field2 & MBIT(2))
+/** RadioType : Set support 40Mhz channel */
+#define SET_CHANWIDTH40(Field2) (Field2 |= MBIT(2))
+/** RadioType : Reset support 40Mhz channel */
+#define RESET_CHANWIDTH40(Field2) (Field2 &= ~(MBIT(0) | MBIT(1) | MBIT(2)))
+/** RadioType : Get secondary channel */
+#define GET_SECONDARYCHAN(Field2) (Field2 & (MBIT(0) | MBIT(1)))
+
+/** ExtCap : Support for FILS */
+#define ISSUPP_EXTCAP_FILS(ext_cap) (ext_cap.FILS)
+/** ExtCap : Set support FILS */
+#define SET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 1)
+/** ExtCap : Reset support FILS */
+#define RESET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 0)
+
+/** ExtCap : Support for TDLS */
+#define ISSUPP_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport)
+/** ExtCap : Set support TDLS */
+#define SET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 1)
+/** ExtCap : Reset support TDLS */
+#define RESET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 0)
+/** ExtCap : Support for TDLS UAPSD */
+#define ISSUPP_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport)
+/** ExtCap : Set support TDLS UAPSD */
+#define SET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 1)
+/** ExtCap : Reset support TDLS UAPSD */
+#define RESET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 0)
+/** ExtCap : Support for TDLS CHANNEL SWITCH */
+#define ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching)
+/** ExtCap : Set support TDLS CHANNEL SWITCH */
+#define SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching = 1)
+/** ExtCap : Reset support TDLS CHANNEL SWITCH */
+#define RESET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching = 0)
+
+/** ExtCap : 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 : Set FTMI bit(bit 71) */
+#define SET_EXTCAP_FTMI(ext_cap) (ext_cap.FTMI = 1)
+#define SET_EXTCAP_INTERNETWORKING(ext_cap) (ext_cap.Interworking = 1)
+/** LLC/SNAP header len   */
+#define LLC_SNAP_LEN    8
+
+/** bandwidth following HTCAP */
+#define BW_FOLLOW_HTCAP             0
+/** bandwidth following VHTCAP */
+#define BW_FOLLOW_VHTCAP            1
+
+/** HW_SPEC FwCapInfo */
+#define HWSPEC_11ACSGI80_SUPP       MBIT(5)
+#define HWSPEC_11ACRXSTBC_SUPP      MBIT(8)
+
+#define ISSUPP_11ACENABLED(FwCapInfo) (FwCapInfo & (MBIT(12)|MBIT(13)))
+
+#define ISSUPP_11AC2GENABLED(FwCapInfo) (FwCapInfo & MBIT(12))
+#define ISSUPP_11AC5GENABLED(FwCapInfo) (FwCapInfo & MBIT(13))
+
+/** HW_SPEC Dot11acDevCap : HTC-VHT supported */
+#define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & MBIT(22))
+/** HW_SPEC Dot11acDevCap : VHT TXOP PS support */
+#define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & MBIT(21))
+/** HW_SPEC Dot11acDevCap : MU RX beamformee support */
+#define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(20))
+/** HW_SPEC Dot11acDevCap : MU TX beamformee support */
+#define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(19))
+/** HW_SPEC Dot11acDevCap : SU Beamformee support */
+#define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(12))
+/** HW_SPEC Dot11acDevCap : SU Beamformer support */
+#define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & MBIT(11))
+/** HW_SPEC Dot11acDevCap : Rx STBC support */
+#define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(8))
+/** HW_SPEC Dot11acDevCap : Tx STBC support */
+#define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(7))
+/** HW_SPEC Dot11acDevCap : Short GI support for 160MHz BW */
+#define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & MBIT(6))
+/** HW_SPEC Dot11acDevCap : Short GI support for 80MHz BW */
+#define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & MBIT(5))
+/** HW_SPEC Dot11acDevCap : LDPC coding support */
+#define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & MBIT(4))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160/80+80 MHz support */
+#define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & MBIT(3))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160 MHz support */
+#define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & MBIT(2))
+
+/** Set VHT Cap Info: Max MPDU length */
+#define SET_VHTCAP_MAXMPDULEN(VHTCapInfo, value) (VHTCapInfo |= (value & 0x03))
+/** SET VHT CapInfo:  Supported Channel Width SET (2 bits)*/
+#define SET_VHTCAP_CHWDSET(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x3) << 2))
+/** SET VHT CapInfo:  Rx STBC (3 bits) */
+#define SET_VHTCAP_RXSTBC(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 8))
+/** SET VHT CapInfo:  Commpressed Steering Num of BFer Ant Supported (3 bits) */
+#define SET_VHTCAP_SNBFERANT(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 13))
+/** SET VHT CapInfo:  Num of Sounding Dimensions (3 bits) */
+#define SET_VHTCAP_NUMSNDDM(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 16))
+/** SET VHT CapInfo:  Max AMPDU Length Exponent (3 bits) */
+#define SET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x7) << 23))
+/** SET VHT CapInfo:  VHT Link Adaptation Capable (2 bits) */
+#define SET_VHTCAP_LINKADPCAP(VHTCapInfo, value) (VHTCapInfo |= ((value & 0x3) << 26))
+
+/** HW_SPEC Dot11acDevCap : ReSet VHT Link Adapation Capable */
+#define RESET_11ACVHTLINKCAPA(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x03))
+/** HW_SPEC Dot11acDevCap : ReSet Maximum AMPDU Length Exponent */
+#define RESET_11ACAMPDULENEXP(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x07))
+/** HW_SPEC Dot11acDevCap : ReSet support of HTC-VHT */
+#define RESET_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(22))
+/** HW_SPEC Dot11acDevCap : ReSet support of VHT TXOP PS */
+#define RESET_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(21))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU RX beamformee */
+#define RESET_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(20))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU TX beamformee */
+#define RESET_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(19))
+/** HW_SPEC Dot11acDevCap : ReSet Number of Sounding Dimensions */
+#define RESET_11ACSOUNDINGNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 16))
+/** HW_SPEC Dot11acDevCap : ReSet Compressed Steering Number
+  * of Beamformer Antenna */
+#define RESET_11ACBFANTNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 13))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformee */
+#define RESET_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(12))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformer */
+#define RESET_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(11))
+/** HW_SPEC Dot11acDevCap : ReSet support of Rx STBC */
+#define RESET_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 8))
+/** HW_SPEC Dot11acDevCap : ReSet support of Tx STBC */
+#define RESET_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(7))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 160MHz BW */
+#define RESET_11ACSGI160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(6))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 80MHz BW */
+#define RESET_11ACSGI80(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(5))
+/** HW_SPEC Dot11acDevCap : ReSet support of LDPC coding */
+#define RESET_11ACLDPC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(4))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+  * Channel BW 20/40/80/160/80+80 MHz */
+#define RESET_11ACBW8080(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(3))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+  * Channel BW 20/40/80/160 MHz */
+#define RESET_11ACBW160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(2))
+/** HW_SPEC Dot11acDevCap : ReSet Max MPDU length */
+#define RESET_11ACMAXMPDULEN(Dot11acDevCap) (Dot11acDevCap &= ~(0x03))
+
+/** Default 11ac capability mask for 2.4GHz */
+#define DEFAULT_11AC_CAP_MASK_BG (HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** Default 11ac capability mask for 5GHz */
+#define DEFAULT_11AC_CAP_MASK_A  (HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** GET VHT CapInfo : MAX MPDU Length */
+#define GET_VHTCAP_MAXMPDULEN(VHTCapInfo) (VHTCapInfo & 0x3)
+/** GET VHT CapInfo:  Supported Channel Width SET (2 bits)*/
+#define GET_VHTCAP_CHWDSET(VHTCapInfo)    ((VHTCapInfo >> 2) & 0x3)
+/** GET VHT CapInfo:  Rx STBC (3 bits) */
+#define GET_VHTCAP_RXSTBC(VHTCapInfo)     ((VHTCapInfo >> 8) & 0x7)
+/** GET VHT CapInfo:  Compressed Steering Num of BFer Ant Supported (3 bits) */
+#define GET_VHTCAP_SNBFERANT(VHTCapInfo)  ((VHTCapInfo >> 13) & 0x7)
+/** GET VHT CapInfo:  Num of Sounding Dimensions (3 bits) */
+#define GET_VHTCAP_NUMSNDDM(VHTCapInfo)   ((VHTCapInfo >> 16) & 0x7)
+/** GET VHT CapInfo:  Max AMPDU Length Exponent (3 bits) */
+#define GET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo)   ((VHTCapInfo >> 23) & 0x7)
+/** GET VHT CapInfo:  VHT Link Adaptation Capable (2 bits) */
+#define GET_VHTCAP_LINKADPCAP(VHTCapInfo)  ((VHTCapInfo >> 26) & 0x3)
+/**SET OPERATING MODE:Channel Width:80M*/
+#define SET_OPER_MODE_80M(oper_mode)  (oper_mode = (oper_mode & ~MBIT(0))| MBIT(1))
+/**SET OPERATING MODE:Channel Width:40M*/
+#define SET_OPER_MODE_40M(oper_mode)  (oper_mode = (oper_mode & ~MBIT(1))| MBIT(0))
+/**SET OPERATING MODE:Channel Width:20M*/
+#define SET_OPER_MODE_20M(oper_mode)  (oper_mode &= ~(0x03))
+#define IS_OPER_MODE_20M(oper_mode) (((oper_mode) & (MBIT(0) | MBIT(1))) == 0)
+/**SET OPERATING MODE:Rx NSS:2*/
+#define SET_OPER_MODE_2NSS(oper_mode)  (oper_mode = (oper_mode &~(MBIT(5)|MBIT(6)))| MBIT(4))
+/**SET OPERATING MODE:Rx NSS:1*/
+#define SET_OPER_MODE_1NSS(oper_mode)  (oper_mode &= ~(MBIT(4)|MBIT(5)|MBIT(6)))
+
+#define GET_VHTMCS(MCSMapSet)         (MCSMapSet & 0xFFFF)
+#define GET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2*(nss-1)))&0x3)
+#define RET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2*(nss-1)))&0x3)
+#define SET_VHTNSSMCS(MCSMapSet, nss, value) \
+            (MCSMapSet |= (value & 0x3) << (2 * (nss - 1)))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_DEVTXMCSMAP(DevMCSMap)      (DevMCSMap >> 16)
+#define GET_DEVNSSTXMCS(DevMCSMap, nss) ((DevMCSMap >> (2*(nss-1)+16))&0x3)
+#define SET_DEVNSSTXMCS(DevMCSMap, nss, value) \
+            (DevMCSMap |= (value & 0x3) << (2 * (nss - 1) + 16))
+#define RESET_DEVTXMCSMAP(DevMCSMap)    (DevMCSMap &= 0xFFFF)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_DEVRXMCSMAP(DevMCSMap)      (DevMCSMap & 0xFFFF)
+#define GET_DEVNSSRXMCS(DevMCSMap, nss) ((DevMCSMap >> (2*(nss-1)))&0x3)
+#define SET_DEVNSSRXMCS(DevMCSMap, nss, value) \
+            (DevMCSMap |= (value & 0x3) << (2 * (nss - 1)))
+#define RESET_DEVRXMCSMAP(DevMCSMap)    (DevMCSMap &= 0xFFFF0000)
+
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_DROP_PATTERN  (PROPRIETARY_TLV_BASE_ID + 0x51)	/* 0x0151 */
+/** TLV type : Rate drop pattern */
+#define TLV_TYPE_RATE_DROP_CONTROL  (PROPRIETARY_TLV_BASE_ID + 0x52)	/* 0x0152 */
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_SCOPE         (PROPRIETARY_TLV_BASE_ID + 0x53)	/* 0x0153 */
+
+/** TLV type : Power group */
+#define TLV_TYPE_POWER_GROUP        (PROPRIETARY_TLV_BASE_ID + 0x54)	/* 0x0154 */
+
+/** Modulation class for DSSS Rates */
+#define MOD_CLASS_HR_DSSS       0x03
+/** Modulation class for OFDM Rates */
+#define MOD_CLASS_OFDM          0x07
+/** Modulation class for HT Rates */
+#define MOD_CLASS_HT            0x08
+/** Modulation class for VHT Rates */
+#define MOD_CLASS_VHT           0x09
+/** HT bandwidth 20 MHz */
+#define HT_BW_20    0
+/** HT bandwidth 40 MHz */
+#define HT_BW_40    1
+/** HT bandwidth 80 MHz */
+#define HT_BW_80    2
+
+/** TLV type : 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 : 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 : 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
+
+/** Host Command ID : 802.11 K Feature Control */
+#define HostCmd_CMD_OFFLOAD_FEATURE_CONTROL     0x00fd
+/** Host Command ID : 802.11 K Get  Neighbor AP list*/
+#define HostCmd_CMD_802_11K_GET_NLIST     0x0231
+
+/** 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 firmware wakeup method */
+#define HostCmd_CMD_802_11_FW_WAKE_METHOD     0x0074
+/** 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 : 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
+
+/** Host Command ID : SDIO GPIO interrupt configuration */
+#define HostCmd_CMD_SDIO_GPIO_INT_CONFIG      0x0088
+
+#ifdef MFG_CMD_SUPPORT
+/** Host Command ID : Mfg command */
+#define HostCmd_CMD_MFG_COMMAND               0x0089
+#endif
+/** 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
+/** Host Command ID : ROAMING OFFLOAD TO FW*/
+#define HostCmd_CMD_ROAM_OFFLOAD              0x0245
+
+/** Host Command ID: Multi chan config */
+#define HostCmd_CMD_MULTI_CHAN_CONFIG                0x011e
+/** Host Command ID: Multi chan policy */
+#define HostCmd_CMD_MULTI_CHAN_POLICY                0x0121
+/** TLV ID for multi chan info */
+#define TLV_TYPE_MULTI_CHAN_INFO             (PROPRIETARY_TLV_BASE_ID + 0xb7)
+/** TLV ID for multi chan group info */
+#define TLV_TYPE_MULTI_CHAN_GROUP_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0xb8)
+/** TLV ID for DRCS TimeSlice */
+#define MRVL_DRCS_TIME_SLICE_TLV_ID  (PROPRIETARY_TLV_BASE_ID + 263)
+/** Host Command ID: DRCS config */
+#define HostCmd_CMD_DRCS_CONFIG                     0x024a
+
+#ifdef RX_PACKET_COALESCE
+/** TLV ID for RX pkt coalesce config */
+#define TLV_TYPE_RX_PKT_COAL_CONFIG           (PROPRIETARY_TLV_BASE_ID + 0xC9)
+#endif
+
+/** Host Command ID : Channel report request */
+#define HostCmd_CMD_CHAN_REPORT_REQUEST              0x00dd
+
+/** Host Command ID: SUPPLICANT_PMK */
+#define HostCmd_CMD_SUPPLICANT_PMK            0x00c4
+/** Host Command ID: SUPPLICANT_PROFILE */
+#define HostCmd_CMD_SUPPLICANT_PROFILE        0x00c5
+
+/** Host Command ID : Add Block Ack Request */
+#define HostCmd_CMD_11N_ADDBA_REQ             0x00ce
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_CFG                   0x00cd
+/** Host Command ID : Add Block Ack Response */
+#define HostCmd_CMD_11N_ADDBA_RSP             0x00cf
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_DELBA                 0x00d0
+/** Host Command ID: Configure Tx Buf size */
+#define HostCmd_CMD_RECONFIGURE_TX_BUFF       0x00d9
+/** Host Command ID: AMSDU Aggr Ctrl */
+#define HostCmd_CMD_AMSDU_AGGR_CTRL           0x00df
+/** Host Command ID: 11AC config */
+#define HostCmd_CMD_11AC_CFG                   0x0112
+/** Host Command ID: Configure TX Beamforming capability */
+#define HostCmd_CMD_TX_BF_CFG                 0x0104
+
+/** Host Command ID : 802.11 TX power configuration */
+#define HostCmd_CMD_TXPWR_CFG                 0x00d1
+
+/** Host Command ID : Soft Reset */
+#define  HostCmd_CMD_SOFT_RESET               0x00d5
+
+/** Host Command ID : 802.11 b/g/n rate configration */
+#define HostCmd_CMD_TX_RATE_CFG               0x00d6
+
+/** Host Command ID : Enhanced PS mode */
+#define HostCmd_CMD_802_11_PS_MODE_ENH        0x00e4
+
+/** Host command action : Host sleep configuration */
+#define HostCmd_CMD_802_11_HS_CFG_ENH         0x00e5
+
+/** Host Command ID : CAU register access */
+#define HostCmd_CMD_CAU_REG_ACCESS            0x00ed
+
+/** Host Command ID : mgmt IE list */
+#define  HostCmd_CMD_MGMT_IE_LIST             0x00f2
+
+/** Host Command ID : TDLS configuration */
+#define  HostCmd_CMD_TDLS_CONFIG              0x0100
+/** Host Command ID : TDLS operation */
+#define HostCmd_CMD_TDLS_OPERATION          0x0122
+
+/** 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)
+
+/* 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 bit23 for firmware roaming*/
+#define FW_ROAMING_SUPPORT    MBIT(23)
+
+/** 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)
+
+#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
+
+/** 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: 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: 802.11 Network Monitor */
+#define HostCmd_CMD_802_11_NET_MONITOR         0x0102
+
+/** Host Command ID: Tx data pause */
+#define HostCmd_CMD_CFG_TX_DATA_PAUSE           0x0103
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** Host Command ID: P2P PARAMS CONFIG */
+#define HOST_CMD_P2P_PARAMS_CONFIG              0x00ea
+/** Host Command ID: WIFI_DIRECT_MODE_CONFIG */
+#define HOST_CMD_WIFI_DIRECT_MODE_CONFIG    0x00eb
+#endif
+
+/** Host Command ID: Remain On Channel */
+#define HostCmd_CMD_802_11_REMAIN_ON_CHANNEL     0x010d
+
+#define HostCmd_CMD_COALESCE_CFG                 0x010a
+
+/** Host Command ID: GTK REKEY OFFLOAD CFG */
+#define HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG       0x010f
+
+/** Host Command ID : OTP user data */
+#define HostCmd_CMD_OTP_READ_USER_DATA          0x0114
+
+/** Host Command ID: HS wakeup reason */
+#define HostCmd_CMD_HS_WAKEUP_REASON         0x0116
+
+/** Host Command ID: reject addba request */
+#define HostCmd_CMD_REJECT_ADDBA_REQ         0x0119
+
+#define HostCmd_CMD_FW_DUMP_EVENT            0x0125
+
+/** Host Command ID : Target device access */
+#define HostCmd_CMD_TARGET_ACCESS            0x012a
+
+/** Host Command ID: DFS repeater mode */
+#define HostCmd_DFS_REPEATER_MODE	0x012b
+
+/** Host Command ID: Get sensor temp*/
+#define HostCmd_DS_GET_SENSOR_TEMP	0x0227
+
+/** Host Command ID : Configure ADHOC_OVER_IP parameters */
+#define HostCmd_CMD_WMM_PARAM_CONFIG                0x023a
+
+#ifdef STA_SUPPORT
+/** Host Command ID :  set/get sta configure */
+#define HostCmd_CMD_STA_CONFIGURE            0x023f
+#endif
+
+/** Host Command ID : GPIO independent reset configure */
+#define HostCmd_CMD_INDEPENDENT_RESET_CFG    0x0243
+
+#define HostCmd_CMD_HOST_CLOCK_CFG          0x0246
+
+/** Channel usability flags */
+#define MARVELL_CHANNEL_DISABLED		MBIT(7)
+#define MARVELL_CHANNEL_NOHT160			MBIT(4)
+#define MARVELL_CHANNEL_NOHT80			MBIT(3)
+#define MARVELL_CHANNEL_NOHT40			MBIT(2)
+#define MARVELL_CHANNEL_DFS				MBIT(1)
+#define MARVELL_CHANNEL_PASSIVE			MBIT(0)
+
+#define HostCmd_CMD_CHAN_REGION_CFG			0x0242
+/* OTP Region info */
+typedef MLAN_PACK_START struct _otp_region_info {
+	t_u8 country_code[2];
+	t_u8 region_code;
+	t_u8 environment;
+	t_u16 force_reg:1;
+	t_u16 reserved:15;
+} MLAN_PACK_END otp_region_info_t;
+
+#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_FTM_CONFIG_SESSION_PARAMS     0x024d
+#define HostCmd_CMD_FTM_SESSION_CTRL              0x024e
+#define HostCmd_CMD_FTM_FEATURE_CTRL              0x024f
+#define HostCmd_CMD_WLS_REQ_FTM_RANGE             0x0250
+
+#define HostCmd_CMD_FTM_CONFIG_RESPONDER     0x0255
+#define HostCmd_ACT_RTT_GET_RSP_INFO 0x0000
+#define HostCmd_ACT_RTT_SET_RSP_EN 0x0001
+#define HostCmd_ACT_RTT_SET_RSP_DIS 0x0002
+#define HostCmd_ACT_RTT_SET_RSP_LCI 0x0003
+#define HostCmd_ACT_RTT_SET_RSP_LCR 0x0004
+
+#define HostCmd_CMD_ACS     0x025a
+
+/** 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 : 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        30
+/** Size of command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+
+/** 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
+
+/** 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
+
+/** 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
+
+#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: Multi Chan Info*/
+#define EVENT_MULTI_CHAN_INFO               0x0000006a
+
+/** Event ID: Tx status */
+#define EVENT_TX_STATUS_REPORT               0x00000074
+
+#define EVENT_BT_COEX_WLAN_PARA_CHANGE	 0x00000076
+
+#define EVENT_ROAM_OFFLOAD     0x00000083
+
+#define EVENT_NLIST_REPORT     0x00000079
+
+#define EVENT_EXCEED_MAX_P2P_CONN     0x00000089
+
+#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             1
+/** 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;
+
+/** tdls ie data structure */
+typedef MLAN_PACK_START struct _ie_data {
+    /** IE Length */
+	t_u16 ie_length;
+    /** IE pointer */
+	t_u8 ie_ptr[0];
+} 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 structure for generic events from NAN FW */
+typedef MLAN_PACK_START struct _event_nan_generic {
+    /** NAN Event SubType */
+	t_u16 event_sub_type;
+} MLAN_PACK_END event_nan_generic;
+
+#define RXPD_FLAG_EXTRA_HEADER             (1 << 1)
+#define RXPD_FLAG_PN_CHECK_SUPPORT             (1 << 2)
+
+/** 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*/
+/** MrvlIEtypesHeader_t */
+typedef MLAN_PACK_START struct _MrvlIEtypesHeader {
+    /** Header type */
+	t_u16 type;
+    /** Header length */
+	t_u16 len;
+} MLAN_PACK_END MrvlIEtypesHeader_t;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Data_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Data */
+	t_u8 data[1];
+} MLAN_PACK_END MrvlIEtypes_Data_t;
+
+/*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] Reserved */
+	t_u8 rate_info;
+   /** Reserved */
+	t_u8 reserved[3];
+    /** TDLS flags, bit 0: 0=InfraLink, 1=DirectLink,
+      *  bit 1: extra info for radio tap,
+      *  bit 2: PN check support*/
+	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;
+    /** PN number high 32 bits*/
+	t_u32 hi_rx_count32;
+    /** PN number low 16 bits*/
+	t_u16 lo_rx_count16;
+    /** Reserved */
+	t_u8 reserved3[2];
+} 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[0]; */
+} 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
+/** TxPD descriptor */
+typedef MLAN_PACK_START struct _UapTxPD {
+	/** 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 UapTxPD, *PUapTxPD;
+
+/** RxPD Descriptor */
+typedef MLAN_PACK_START struct _UapRxPD {
+    /** BSS Type */
+	t_u8 bss_type;
+    /** BSS number*/
+	t_u8 bss_num;
+    /** Rx packet length */
+	t_u16 rx_pkt_length;
+    /** Rx packet offset */
+	t_u16 rx_pkt_offset;
+    /** Rx packet type */
+	t_u16 rx_pkt_type;
+    /** Sequence nunmber */
+	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] Reserved */
+	t_u8 rate_info;
+    /** Reserved */
+	t_u8 reserved1[3];
+    /** TDLS flags, bit 0: 0=InfraLink, 1=DirectLink */
+	t_u8 flags;
+    /** For SD8887 ntenna 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;
+    /** PN number high 32 bits*/
+	t_u32 hi_rx_count32;
+    /** PN number low 16 bits*/
+	t_u16 lo_rx_count16;
+    /** Reserved */
+	t_u8 reserved3[2];
+} MLAN_PACK_END UapRxPD, *PUapRxPD;
+
+/** 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[0]; */
+} 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[0]; */
+} 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_6_7:2;
+    /** 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;
+    /** Reserved */
+	t_u8 reserved_6_7:2;
+#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;
+
+/** 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_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 tlv */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ChannelStats_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** channel statictics */
+	ChanStatistics_t chanStat[0];
+} MLAN_PACK_END MrvlIEtypes_ChannelStats_t;
+
+/** MrvlIETypes_ActionFrame_t */
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header;
+				  /**< Header */
+
+    /** Source Address */
+	t_u8 srcAddr[MLAN_MAC_ADDR_LENGTH];
+    /** Destination Address */
+	t_u8 dstAddr[MLAN_MAC_ADDR_LENGTH];
+
+    /** IEEEtypes Action frame structure */
+	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[0];
+} MLAN_PACK_END MrvlIEtypes_RsnParamSet_t;
+
+/** 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;
+
+/** 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;
+	} 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)
+
+/** 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;
+
+/* 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 new power save command */
+typedef MLAN_PACK_START struct _HostCmd_DS_PS_MODE_ENH {
+    /** Action */
+	t_u16 action;
+    /** Data speciifc to action */
+	/* For IEEE power save data will be as
+	 * UINT16 mode (0x01 - firmware to automatically choose PS_POLL or NULL mode, 0x02 - PS_POLL, 0x03 - NULL mode )
+	 * UINT16 NullpacketInterval
+	 * UINT16 NumDtims
+	 * UINT16 BeaconMissInterval
+	 * UINT16 locallisteninterval
+	 * UINT16 adhocawakeperiod */
+
+	/* For auto deep sleep */
+	/* UINT16 Deep sleep inactivity timeout */
+
+	/* For PS sleep confirm
+	 * UINT16 responeCtrl - 0x00 - reponse from fw not needed, 0x01 - response from fw is needed */
+
+	union {
+    /** PS param definition */
+		ps_param opt_ps;
+    /** Auto ds param definition */
+		auto_ds_param auto_ds;
+    /** Sleep comfirm param definition */
+		sleep_confirm_param sleep_cfm;
+    /** bitmap for get PS info and Disable PS mode */
+		t_u16 ps_bitmap;
+    /** auto ps param */
+		auto_ps_param auto_ps;
+	} params;
+} MLAN_PACK_END HostCmd_DS_802_11_PS_MODE_ENH;
+
+/** FW VERSION tlv */
+#define TLV_TYPE_FW_VER_INFO        (PROPRIETARY_TLV_BASE_ID + 0xC7)	/* 0x1C7 */
+
+/** MrvlIEtypes_fw_ver_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_ver_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** API id */
+	t_u16 api_id;
+    /** major version */
+	t_u8 major_ver;
+    /** minor version */
+	t_u8 minor_ver;
+} MLAN_PACK_END MrvlIEtypes_fw_ver_info_t;
+
+/** API ID */
+enum API_VER_ID {
+	KEY_API_VER_ID = 1,
+	FW_API_VER_ID = 2,
+	UAP_FW_API_VER_ID = 3,
+	CHANRPT_API_VER_ID = 4,
+};
+
+/** FW AP V15 */
+#define HOST_API_VERSION_V15  15
+/** FW minor version 1 */
+#define FW_MINOR_VERSION_1    1
+
+/** 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;
+
+/* HostCmd_DS_SDIO_SP_RX_AGGR_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SDIO_SP_RX_AGGR_CFG {
+    /** Action */
+	t_u8 action;
+    /** Enable */
+	t_u8 enable;
+    /** Sdio block size */
+	t_u16 sdio_block_size;
+} MLAN_PACK_END HostCmd_DS_SDIO_SP_RX_AGGR_CFG;
+
+/**  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[0];
+} 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_802_11_NET_MONITOR */
+typedef MLAN_PACK_START struct _HostCmd_802_11_DS_NET_MONITOR {
+    /** Action */
+	t_u16 action;
+    /** Enable/disable net monitor */
+	t_u16 enable_net_mon;
+    /** set net monitor filer flag */
+	t_u16 filter_flag;
+    /** Channel to monitor */
+	MrvlIEtypes_ChanBandListParamSet_t monitor_chan;
+} MLAN_PACK_END HostCmd_DS_802_11_NET_MONITOR;
+
+/** 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;
+
+/** 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;
+
+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;
+} 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 {
+    /** wifi radio (if multiple radio supported) */
+	t_u32 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 */
+	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[0];
+} 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[0]; */
+} 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[0]; */
+} 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[0];
+} MLAN_PACK_END HostCmd_DS_802_11_LINK_STATISTIC;
+
+/**_HostCmd_TX_RATE_QUERY */
+typedef MLAN_PACK_START struct _HostCmd_TX_RATE_QUERY {
+    /** Tx rate */
+	t_u8 tx_rate;
+    /** Tx Rate Info:
+     * [Bit 0-1] tx rate formate: LG = 0, HT = 1, VHT = 2
+     * [Bit 2-3] HT/VHT Bandwidth: BW20 = 0, BW40 = 1, BW80 = 2, BW160 = 3
+     * [Bit 4]   HT/VHT Guard Interval: LGI = 0, SGI = 1 */
+	t_u8 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_FW_WAKE_METHOD */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_FW_WAKEUP_METHOD {
+    /** Action */
+	t_u16 action;
+    /** Method */
+	t_u16 method;
+} MLAN_PACK_END HostCmd_DS_802_11_FW_WAKEUP_METHOD;
+
+/** HostCmd_CMD_802_11_ROBUSTCOEX */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_ROBUSTCOEX {
+    /** Action */
+	t_u16 action;
+    /** RSVD */
+	t_u16 rsvd;
+} MLAN_PACK_END HostCmd_DS_802_11_ROBUSTCOEX;
+
+/** 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
+
+/**  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];
+    /** VHT MCS rate bitmap */
+	t_u16 vht_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[0]; */
+} MLAN_PACK_END MrvlRateDropPattern_t;
+
+/** HostCmd_DS_TX_RATE_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TX_RATE_CFG {
+    /** Action */
+	t_u16 action;
+    /** Reserved */
+	t_u16 reserved_1;
+	/* MrvlRateScope_t RateScope;
+	 * MrvlRateDropPattern_t RateDrop; */
+} 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[0] */
+} 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;
+
+#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
+     */
+} MLAN_PACK_END HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG;
+#endif
+
+/** Coalesce filter field parameter */
+MLAN_PACK_START struct coalesce_filt_field_param {
+    /** Operation */
+	t_u8 operation;
+    /** Operation length */
+	t_u8 operand_len;
+    /** Offset */
+	t_u16 offset;
+    /** Operand byte stream */
+	t_u8 operand_byte_stream[4];
+} MLAN_PACK_END;
+
+/** Coalesce receive filter rule */
+MLAN_PACK_START struct coalesce_receive_filt_rule {
+    /** header */
+	MrvlIEtypesHeader_t header;
+    /** Number of fields */
+	t_u8 num_of_fields;
+    /** packet type */
+	t_u8 pkt_type;
+    /** maximum coalescing delay */
+	t_u16 max_coalescing_delay;
+	struct coalesce_filt_field_param params[0];
+} MLAN_PACK_END;
+
+/** HostCmd_DS_COALESCE_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_COALESCE_CONFIG {
+    /** Action 0-GET, 1-SET */
+	t_u16 action;
+    /** Number of rules */
+	t_u16 num_of_rules;
+	struct coalesce_receive_filt_rule rule[0];
+} 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[0];
+} 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_802_11K_GET_NLIST */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11K_GET_NLIST {
+	/** Action */
+	t_u16 action;
+	/** Dialog token */
+	t_u8 dialog_token;
+} MLAN_PACK_END HostCmd_DS_802_11K_GET_NLIST;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** host_OffloadFeatureStdControl_t*/
+typedef MLAN_PACK_START struct {
+	t_u8 dot11k_tsm:1;
+	t_u8 dot11k_lm:1;
+	t_u8 dot11k_nbor_support:1;
+	t_u8 dot11k_rm:1;
+	t_u8 dot11h_rm:1;
+	t_u8 wmm_ac_tpsec_modify:1;
+	t_u8 wmm_ac_dynamic_ps:1;
+	t_u8 client_radar_detect:1;
+
+	t_u8 reserved:3;
+	t_u8 rbc:1;
+	t_u8 dot11v_bss_trans:1;
+	t_u8 vowifi_probe_tpc_rpt:1;
+	t_u8 pmf_required:1;
+	t_u8 pmf_capable:1;
+} MLAN_PACK_END host_OffloadFeatureStdControl_t;
+#else
+/** host_OffloadFeatureStdControl_t */
+typedef MLAN_PACK_START struct {
+	t_u8 client_radar_detect:1;
+	t_u8 wmm_ac_dynamic_ps:1;
+	t_u8 wmm_ac_tpsec_modify:1;
+	t_u8 dot11h_rm:1;
+	t_u8 dot11k_rm:1;
+	t_u8 dot11k_nbor_support:1;
+	t_u8 dot11k_lm:1;
+	t_u8 dot11k_tsm:1;
+
+	t_u8 pmf_capable:1;
+	t_u8 pmf_required:1;
+	t_u8 vowifi_probe_tpc_rpt:1;
+	t_u8 dot11v_bss_trans:1;
+	t_u8 rbc:1;
+	t_u8 reserved:3;
+} MLAN_PACK_END host_OffloadFeatureStdControl_t;
+#endif
+
+/** END HostCmd_OFFLOAD_FEATURE_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_OFFLOAD_FEATURE_CTRL {
+	t_u8 featureSelect;
+	union {
+		host_OffloadFeatureStdControl_t std;
+		t_u8 empty;
+	} control;
+} MLAN_PACK_END HostCmd_OFFLOAD_FEATURE_CTRL;
+/** 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_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 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;
+
+/** 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 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;
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_VHTOprat_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+
+    /** Channel width */
+	t_u8 chan_width;
+    /** Channel center frequency 1 */
+	t_u8 chan_center_freq_1;
+    /** Channel center frequency 2 */
+	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;
+
+    /** Maximum tx power */
+	t_u8 max_tx_power;
+    /** Channel center frequency */
+	t_u8 chan_center_freq;
+    /** Channel width */
+	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;
+
+    /** MIMO Capability count */
+	t_u8 MU_MIMO_capa_count;
+    /** Stream under utilization */
+	t_u8 stream_underutilization;
+    /** VHT40 util */
+	t_u8 VHT40_util;
+    /** VHT80 util */
+	t_u8 VHT80_util;
+    /** VHT160 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;
+
+    /** AP quiet mode */
+	t_u8 AP_quiet_mode;
+    /** Quiet count */
+	t_u8 quiet_count;
+    /** Quiet period */
+	t_u8 quiet_period;
+    /** Quiet duration */
+	t_u16 quiet_dur;
+    /** Quiet offset */
+	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;
+
+    /** New Channel width */
+	t_u8 new_chan_width;
+    /** New Channel center frequency 1 */
+	t_u8 new_chan_center_freq_1;
+    /** New channel center frequency 2 */
+	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;
+
+/** tx sounding cfg args */
+typedef MLAN_PACK_START struct _tx_sounding_cfg_args {
+    /** enable/disable tx sounding */
+	t_u8 tx_sounding_enbl;
+    /** Sounding Type */
+	t_u8 sounding_type;
+    /** Sounding interval in milliseconds */
+	t_u16 sounding_interval;
+} MLAN_PACK_END tx_sounding_cfg_args_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;
+		tx_sounding_cfg_args_t tx_sounding_cfg;
+	} 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;
+
+/* 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;
+
+/* 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;
+
+/** 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)
+/** 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_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;
+
+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;
+
+struct timestamps {
+	/** t2 time */
+	t_u32 t2;
+	/** t2 error */
+	t_u8 t2_err;
+	/** t3 time */
+	t_u32 t3;
+	/** t3 error */
+	t_u8 t3_err;
+	/** ingress time */
+	t_u64 ingress_time;
+} __attribute__ ((packed));
+
+/** HostCmd_DS_HOST_CLOCK_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_HOST_CLOCK_CFG {
+    /** Action */
+	t_u16 action;
+    /** host time nano secs value */
+	t_u64 time;
+    /** HW time in nano sec value */
+	t_u64 hw_time;
+} MLAN_PACK_END HostCmd_DS_HOST_CLOCK_CFG;
+
+/** HostCmd_DS_ACS */
+typedef MLAN_PACK_START struct _HostCmd_DS_ACS {
+    /** Best channel */
+	t_u8 best_ch;
+    /** TLV buffer */
+    /** MrvlIEtypes_ChanListParamSet_t TLV (0x0101) in cmd */
+    /** MrvlIEtypes_ScanChanGap_t TLV (0x01c5) in cmd */
+    /** MrvlIEtypes_ChannelStats_t TLV (0x01c6) in cmd resp */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END HostCmd_DS_ACS;
+
+/** 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 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_sta_ageout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sta_ageout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** station age out timer */
+	t_u32 sta_ageout_timer;
+} MLAN_PACK_END MrvlIEtypes_sta_ageout_t;
+
+/** MrvlIEtypes_rts_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rts_threshold_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** rts threshold */
+	t_u16 rts_threshold;
+} MLAN_PACK_END MrvlIEtypes_rts_threshold_t;
+
+/** MrvlIEtypes_frag_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_frag_threshold_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** frag threshold */
+	t_u16 frag_threshold;
+} MLAN_PACK_END MrvlIEtypes_frag_threshold_t;
+
+/** MrvlIEtypes_retry_limit_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_retry_limit_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** retry limit */
+	t_u8 retry_limit;
+} MLAN_PACK_END MrvlIEtypes_retry_limit_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_timeout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** pairwise update timeout in milliseconds */
+	t_u32 pairwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_retries_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** pairwise handshake retries */
+	t_u32 pwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_retries_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_timeout_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** groupwise update timeout in milliseconds */
+	t_u32 groupwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_retries_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** groupwise handshake retries */
+	t_u32 gwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_retries_t;
+
+/** MrvlIEtypes_mgmt_ie_passthru_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mgmt_ie_passthru_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** mgmt IE mask value */
+	t_u32 mgmt_ie_mask;
+} MLAN_PACK_END MrvlIEtypes_mgmt_ie_passthru_t;
+
+/** MrvlIEtypes_mac_filter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mac_filter_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Filter mode */
+	t_u8 filter_mode;
+    /** Number of STA MACs */
+	t_u8 count;
+    /** STA MAC addresses buffer */
+	t_u8 mac_address[1];
+} MLAN_PACK_END MrvlIEtypes_mac_filter_t;
+
+/** MrvlIEtypes_auth_type_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_auth_type_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Authentication type */
+	t_u8 auth_type;
+} MLAN_PACK_END MrvlIEtypes_auth_type_t;
+
+/** MrvlIEtypes_encrypt_protocol_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_encrypt_protocol_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** encryption protocol */
+	t_u16 protocol;
+} MLAN_PACK_END MrvlIEtypes_encrypt_protocol_t;
+
+/** MrvlIEtypes_pwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_pwk_cipher_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** protocol */
+	t_u16 protocol;
+    /** pairwise cipher */
+	t_u8 pairwise_cipher;
+    /** reserved */
+	t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_pwk_cipher_t;
+
+/** MrvlIEtypes_gwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_gwk_cipher_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** group cipher */
+	t_u8 group_cipher;
+    /** reserved */
+	t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_gwk_cipher_t;
+
+/** MrvlIEtypes_akmp_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_akmp_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** key management */
+	t_u16 key_mgmt;
+    /** key management operation */
+	t_u16 key_mgmt_operation;
+} MLAN_PACK_END MrvlIEtypes_akmp_t;
+
+/** MrvlIEtypes_passphrase_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_passphrase_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** passphrase */
+	t_u8 passphrase[1];
+} MLAN_PACK_END MrvlIEtypes_passphrase_t;
+
+/** MrvlIEtypes_rsn_replay_prot_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rsn_replay_prot_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** rsn replay proection */
+	t_u8 rsn_replay_prot;
+} MLAN_PACK_END MrvlIEtypes_rsn_replay_prot_t;
+
+/** MrvlIEtypes_group_rekey_time_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_group_rekey_time_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** group key rekey time */
+	t_u32 gk_rekey_time;
+} MLAN_PACK_END MrvlIEtypes_group_rekey_time_t;
+
+/** MrvlIEtypes_wep_key_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wep_key_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** key index */
+	t_u8 key_index;
+    /** is default */
+	t_u8 is_default;
+    /** key data */
+	t_u8 key[1];
+} MLAN_PACK_END MrvlIEtypes_wep_key_t;
+
+/** MrvlIEtypes_bss_status_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_bss_status_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** BSS status, READ only */
+	t_u16 bss_status;
+} MLAN_PACK_END MrvlIEtypes_bss_status_t;
+
+/** MrvlIEtypes_preamble_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_preamble_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** preamble type, READ only */
+	t_u8 preamble_type;
+} MLAN_PACK_END MrvlIEtypes_preamble_t;
+
+/** MrvlIEtypes_wmm_parameter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wmm_parameter_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** WMM parameter */
+	WmmParameter_t wmm_para;
+} MLAN_PACK_END MrvlIEtypes_wmm_parameter_t;
+
+/** SNMP_MIB_UAP_INDEX */
+typedef enum _SNMP_MIB_UAP_INDEX {
+	tkip_mic_failures = 0x0b,
+	ccmp_decrypt_errors = 0x0c,
+	wep_undecryptable_count = 0x0d,
+	wep_icv_error_count = 0x0e,
+	decrypt_failure_count = 0xf,
+	dot11_failed_count = 0x12,
+	dot11_retry_count = 0x13,
+	dot11_multi_retry_count = 0x14,
+	dot11_frame_dup_count = 0x15,
+	dot11_rts_success_count = 0x16,
+	dot11_rts_failure_count = 0x17,
+	dot11_ack_failure_count = 0x18,
+	dot11_rx_fragment_count = 0x19,
+	dot11_mcast_rx_frame_count = 0x1a,
+	dot11_fcs_error_count = 0x1b,
+	dot11_tx_frame_count = 0x1c,
+	dot11_rsna_tkip_cm_invoked = 0x1d,
+	dot11_rsna_4way_hshk_failures = 0x1e,
+	dot11_mcast_tx_count = 0x1f,
+} SNMP_MIB_UAP_INDEX;
+
+/** MrvlIEtypes_snmp_oid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_snmp_oid_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** data */
+	t_u32 data;
+} MLAN_PACK_END MrvlIEtypes_snmp_oid_t;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_CONFIG {
+	/** CMD Action GET/SET*/
+	t_u16 action;
+	/** Tlv buffer */
+	t_u8 tlv_buffer[1];
+} MLAN_PACK_END HostCmd_DS_SYS_CONFIG;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_INFO {
+    /** sys info */
+	t_u8 sys_info[64];
+} MLAN_PACK_END HostCmd_DS_SYS_INFO;
+
+/** HostCmd_DS_STA_DEAUTH */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_DEAUTH {
+    /** mac address */
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+    /** reason code */
+	t_u16 reason;
+} MLAN_PACK_END HostCmd_DS_STA_DEAUTH;
+
+/** HostCmd_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 mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+} 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[0]; */
+} 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 */
+
+/** 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;
+
+/** 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;
+
+/**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[0];
+} 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
+
+typedef MLAN_PACK_START struct _MrvlTypes_DrcsTimeSlice_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Channel Index*/
+	t_u16 chan_idx;
+	/** Channel time (in TU) for chan_idx*/
+	t_u8 chantime;
+	/** Channel swith time (in TU) for chan_idx*/
+	t_u8 switchtime;
+	/** Undoze time (in TU) for chan_idx*/
+	t_u8 undozetime;
+	/** Rx traffic control scheme when channel switch*/
+	/** only valid for GC/STA interface*/
+	t_u8 mode;
+} MLAN_PACK_END MrvlTypes_DrcsTimeSlice_t;
+typedef MLAN_PACK_START struct _HostCmd_DS_MULTI_CHAN_CFG {
+	/** Action */
+	t_u16 action;
+	/** Channel time */
+	t_u32 channel_time;
+	/** Buffer weight */
+	t_u8 buffer_weight;
+	/** TLV buffer */
+	t_u8 tlv_buf[0];
+	/* t_u8 *tlv_buf; */
+} MLAN_PACK_END HostCmd_DS_MULTI_CHAN_CFG;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_DRCS_CFG {
+	/** Action */
+	t_u16 action;
+	/** TLV buffer */
+	MrvlTypes_DrcsTimeSlice_t time_slicing;
+	/** TLV buffer */
+	MrvlTypes_DrcsTimeSlice_t drcs_buf[0];
+	/* t_u8 *tlv_buf; */
+} MLAN_PACK_END HostCmd_DS_DRCS_CFG;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_MULTI_CHAN_POLICY {
+	/** Action */
+	t_u16 action;
+	/** Multi-channel Policy */
+	t_u16 policy;
+} MLAN_PACK_END HostCmd_DS_MULTI_CHAN_POLICY;
+
+/** Channel band info */
+typedef MLAN_PACK_START struct _ChannelBandInfo {
+	/* band config */
+	Band_Config_t bandcfg;
+    /** channel num for specificed band */
+	t_u8 chan_num;
+} MLAN_PACK_END ChannelBandInfo;
+
+/** MrvlIETypes_mutli_chan_group_info_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_mutli_chan_group_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** channel group id */
+	t_u8 chan_group_id;
+    /** buffer weight for this channel group */
+	t_u8 chan_buff_weight;
+    /** channel number and band information */
+	ChannelBandInfo chan_band_info;
+    /** Max channel time (us) */
+	t_u32 channel_time;
+    /** Reserved */
+	t_u32 reserved;
+	MLAN_PACK_START union {
+		t_u8 sdio_func_num;
+		t_u8 usb_epnum;
+	} MLAN_PACK_END hid_num;
+    /** interface number in this group */
+	t_u8 num_intf;
+    /** bss_type list */
+	t_u8 bss_type_numlist[0];
+} MLAN_PACK_END MrvlIEtypes_multi_chan_group_info_t;
+
+/** MrvlIEtypes_multi_chan_info_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_mutli_chan_info_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** multi channel operation status */
+	t_u16 status;
+    /** Tlv buffer */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END MrvlIEtypes_multi_chan_info_t;
+
+/** TLV buffer : firmware roam keys */
+typedef MLAN_PACK_START struct _MrvlIEtypes_keyParams_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Tlv buffer */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END MrvlIEtypes_keyParams_t;
+/** TLV buffer : firmware roam enable */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_roam_enable_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Enable */
+	t_u8 roam_enable;
+    /** User set passphrase*/
+	t_u8 userset_passphrase;
+} MLAN_PACK_END MrvlIEtypes_fw_roam_enable_t;
+/** HostCmd_DS_ROAM_OFFLOAD */
+typedef MLAN_PACK_START struct _HostCmd_DS_ROAM_OFFLOAD {
+	/** Action */
+	t_u16 action;
+	/** tlv */
+	t_u8 tlv[0];
+} MLAN_PACK_END HostCmd_DS_ROAM_OFFLOAD;
+/** HostCmd_DS_ROAM_OFFLOAD_APLIST */
+typedef MLAN_PACK_START struct _MrvlIEtypes_roam_aplist_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** AP mac addrs**/
+	t_u8 ap_mac[][MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_roam_aplist_t;
+/** MrvlIEtypes_fw_roam_trigger_condition_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_roam_trigger_condition_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Roam offload trigger condition**/
+	t_u16 trigger_condition;
+} MLAN_PACK_END MrvlIEtypes_fw_roam_trigger_condition_t;
+/** MrvlIEtypes_fw_roam_retry_count_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_roam_retry_count_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Roam offload retry count**/
+	t_u16 retry_count;
+} MLAN_PACK_END MrvlIEtypes_fw_roam_retry_count_t;
+/** MrvlIEtypes_fw_roam_bgscan_setting_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_roam_bgscan_setting_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Bss type of BG scan during fw roam**/
+	t_u8 bss_type;
+    /** Number of channels scanned during each scan**/
+	t_u8 channels_perscan;
+    /** Interval between consecutive scans**/
+	t_u32 scan_interval;
+    /** Condition to trigger report to host**/
+	t_u32 report_condition;
+} MLAN_PACK_END MrvlIEtypes_fw_roam_bgscan_setting_t;
+/** MrvlIEtypes_para_rssi_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_para_rssi_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Max value of RSSI threshold**/
+	t_u8 max_rssi;
+    /** Min value of RSSI threshold**/
+	t_u8 min_rssi;
+    /** Adjusting step value of RSSI threshold**/
+	t_u8 step_rssi;
+} MLAN_PACK_END MrvlIEtypes_para_rssi_t;
+/** MrvlIEtypes_band_rssi_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_band_rssi_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** BAND and RSSI gap*/
+	mlan_ds_misc_band_rssi band_rssi;
+} MLAN_PACK_END MrvlIEtypes_band_rssi_t;
+/** MrvlIEtypes_ees_param_set_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ees_param_set_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** ees params*/
+	mlan_ds_misc_ees_cfg ees_cfg;
+} MLAN_PACK_END MrvlIEtypes_ees_param_set_t;
+/** MrvlIEtypes_roam_blacklist_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_roam_blacklist_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+	/* Black list(BSSID list) */
+	mlan_ds_misc_roam_offload_aplist blacklist;
+} MLAN_PACK_END MrvlIEtypes_roam_blacklist_t;
+/** MrvlIEtypes_beacon_miss_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_beacon_miss_threshold_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+	/* Beacon miss threshold */
+	t_u8 bcn_miss_threshold;
+} MLAN_PACK_END MrvlIEtypes_beacon_miss_threshold_t;
+/** MrvlIEtypes_pre_beacon_miss_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_pre_beacon_miss_threshold_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+	/* Pre-Beacon miss threshold */
+	t_u8 pre_bcn_miss_threshold;
+} MLAN_PACK_END MrvlIEtypes_pre_beacon_miss_threshold_t;
+
+/** 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;
+
+/** 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*/
+
+/* DFS Repeater Mode */
+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 Marvell extended TLV
+ */
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header;
+				/**< Marvell 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;
+
+/**
+ * @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;
+
+/** Marvell channel descriptor */
+typedef MLAN_PACK_START struct {
+	t_u16 startFreq;		/**< Start Frequency */
+	Band_Config_t bandcfg;		/**< bandcfg */
+	t_u8 chanNum;			/**< channel no */
+
+} MLAN_PACK_END MrvlChannelDesc_t;
+
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t Header;  /**< Header */
+
+	MeasRptBasicMap_t map;	     /**< IEEE 802.11h basic meas report */
+} MLAN_PACK_END MrvlIEtypes_ChanRpt11hBasic_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;
+
+/** HostCmd_DS_SENSOR_TEMP structure */
+typedef MLAN_PACK_START struct _HostCmd_DS_SENSOR_TEMP {
+	/** Temperature */
+	t_u32 temperature;
+} MLAN_PACK_END HostCmd_DS_SENSOR_TEMP;
+
+#ifdef STA_SUPPORT
+/** HostCmd_DS_STA_CONFIGURE structure */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_CONFIGURE {
+    /** Action Set or get */
+	t_u16 action;
+    /** Tlv buffer */
+	t_u8 tlv_buffer[0];
+    /**MrvlIEtypes_channel_band_t band_channel; */
+} MLAN_PACK_END HostCmd_DS_STA_CONFIGURE;
+#endif
+
+/** 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;
+
+/** TLV for RTT Range Request */
+#define TLV_TYPE_RTT_RANGE_REQUEST (PROPRIETARY_TLV_BASE_ID + 0x125)	/* 0x0100 + 0x125 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RTTRangeRequest_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Peer device MAC address */
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+    /** 1-sided or 2-sided RTT */
+	t_u8 type;
+    /** peer device hint (STA, P2P, AP) */
+	t_u8 peer;
+    /** channel number */
+	t_u8 channel;
+    /** Band Config */
+	Band_Config_t bandcfg;
+    /** Time interval between bursts (units: 100 ms) */
+	t_u8 burst_period;
+    /** Total number of RTT bursts to be executed. */
+	t_u8 num_burst;
+    /** num of frames per burst. */
+	t_u8 num_frames_per_burst;
+    /** number of retries for a failed RTT frame. */
+	t_u8 num_retries_per_rtt_frame;
+    /** Maximum number of retries that the initiator can retry an FTMR frame. */
+	t_u8 num_retries_per_ftmr;
+    /** LCI request */
+	t_u8 LCI_request;
+    /** LCR request */
+	t_u8 LCR_request;
+    /** burst duration */
+	t_u8 burst_duration;
+    /** RTT preamble to be used in the RTT frames */
+	t_u8 preamble;
+    /** RTT BW to be used in the RTT frames */
+	t_u8 bw;
+} MLAN_PACK_END MrvlIEtypes_RTTRangeRequest_t;
+
+/** TLV for RTT Range Cancel */
+#define TLV_TYPE_RTT_RANGE_CANCEL (PROPRIETARY_TLV_BASE_ID + 0x126)	/* 0x0100 + 0x126 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RTTRangeCancel_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Peer device MAC address */
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_RTTRangeCancel_t;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_FTM_CONFIG_SESSION_PARAMS {
+    /** Action */
+	t_u16 action;
+    /** TLV buffer */
+    /** MrvlIEtypes_RTTRangeRequest_t */
+    /** MrvlIEtypes_RTTRangeCancel_t */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END HostCmd_DS_FTM_CONFIG_SESSION_PARAMS;
+
+typedef MLAN_PACK_START struct _WLS_Sub_Event_RTTResults_t {
+    /** complete */
+	t_u8 complete;
+    /** tlv buffer */
+    /** MrvlIEtypes_RTTResult_t */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END WLS_SUB_EVENT_RTTResults_t;
+
+/** TLV for RTT Result */
+#define TLV_TYPE_RTT_RESULT (PROPRIETARY_TLV_BASE_ID + 0x127)	/* 0x0100 + 0x127 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RTTResult_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** Peer device MAC address */
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+    /** burst number in a multi-burst request */
+	t_u32 burst_num;
+    /** Total RTT measurement frames attempted */
+	t_u32 measurement_number;
+    /** Total successful RTT measurement frames */
+	t_u32 success_number;
+    /** Maximum number of "FTM frames per burst" supported by the responder STA. */
+	t_u8 number_per_burst_peer;
+    /** ranging status */
+	t_u8 status;
+    /** The time provided by the responder when the request can be tried again. */
+	t_u8 retry_after_duration;
+    /** RTT type */
+	t_u8 type;
+    /** average rssi in 0.5 dB steps e.g. 143 implies -71.5 dB */
+	t_s32 rssi;
+    /** rssi spread in 0.5 dB steps e.g. 5 implies 2.5 dB spread (optional) */
+	t_s32 rssi_spread;
+    /** TX rate */
+	mlan_wifi_rate tx_rate;
+    /** RX rate */
+	mlan_wifi_rate rx_rate;
+    /** round trip time in picoseconds */
+	t_s64 rtt;
+    /** rtt standard deviation in picoseconds */
+	t_s64 rtt_sd;
+    /** difference between max and min rtt times recorded in picoseconds */
+	t_s64 rtt_spread;
+    /** distance in mm (optional) */
+	t_s32 distance_mm;
+    /** standard deviation in mm (optional) */
+	t_s32 distance_sd_mm;
+    /** difference between max and min distance recorded in mm (optional) */
+	t_s32 distance_spread_mm;
+    /** time of the measurement (in microseconds since boot) */
+	t_s64 ts;
+    /** in ms, actual time taken by the FW to finish one burst */
+	t_s32 burst_duration;
+    /** Number of bursts allowed by the responder. */
+	t_s32 negotiated_burst_num;
+    /** tlv buffer */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END MrvlIEtypes_RTTResult_t;
+
+/** TLV for IEEEI IE */
+typedef MLAN_PACK_START struct _MrvlIEtypes_IEEEIE_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** data */
+	t_u8 data[0];
+} MLAN_PACK_END MrvlIEtypes_IEEEIE_t;
+
+/** auto link switch network info */
+typedef MLAN_PACK_START struct _Event_WLS_FTM_t {
+    /** Event ID */
+	t_u16 event_id;
+    /** BSS index number for multiple BSS support */
+	t_u8 bss_index;
+    /** BSS type */
+	t_u8 bss_type;
+    /** sub event id */
+	t_u8 sub_event_id;
+	union {
+	/** RTT Results Sub Event */
+		WLS_SUB_EVENT_RTTResults_t rtt_results;
+	} u;
+} MLAN_PACK_END Event_WLS_FTM_t;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_FTM_CONFIG_RESPONDER {
+    /** Action */
+	t_u16 action;
+    /** TLV buffer */
+    /** MrvlIEtypes_RTTResponderInfo_t */
+    /** MrvlIEtypes_RTTResponderEnCfg_t */
+	t_u8 tlv_buffer[0];
+} MLAN_PACK_END HostCmd_DS_FTM_CONFIG_RESPONDER;
+
+/** TLV for RTTResponderInfo */
+#define TLV_TYPE_RTT_RESPONDER_INFO (PROPRIETARY_TLV_BASE_ID + 0x128)	/* 0x0100 + 0x128 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RTTResponderInfo_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** channel */
+	t_u8 channel;
+    /** bandcfg */
+	Band_Config_t bandcfg;
+    /** bandcfg */
+	t_u8 preamble;
+} MLAN_PACK_END MrvlIEtypes_RTTResponderInfo_t;
+
+/** TLV for RTTResponderEnCfg */
+#define TLV_TYPE_RTT_RESPONDER_EN_CFG (PROPRIETARY_TLV_BASE_ID + 0x129)	/* 0x0100 + 0x129 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RTTResponderEnCfg_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** channel */
+	t_u8 channel;
+    /** bandcfg */
+	Band_Config_t bandcfg;
+    /** bandcfg */
+	t_u32 max_duration_seconds;
+} MLAN_PACK_END MrvlIEtypes_RTTResponderEnCfg_t;
+
+/** TLV for RTTLCICfg */
+#define TLV_TYPE_RTT_LCI_CFG (PROPRIETARY_TLV_BASE_ID + 0x12A)	/* 0x0100 + 0x12A */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RTTLCICfg_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** latitude */
+	t_u64 latitude;
+    /** longitude */
+	t_u64 longitude;
+    /** altitude */
+	t_u32 altitude;
+    /** latitude_unc */
+	t_u8 latitude_unc;
+    /** longitude_unc */
+	t_u8 longitude_unc;
+    /** altitude_unc */
+	t_u8 altitude_unc;
+    /** motion_pattern */
+	t_u8 motion_pattern;
+    /** floor */
+	t_u32 floor;
+    /** height_above_floor */
+	t_u32 height_above_floor;
+    /** height_unc */
+	t_u32 height_unc;
+} MLAN_PACK_END MrvlIEtypes_RTTLCICfg_t;
+
+/** TLV for RTTLCRCfg */
+#define TLV_TYPE_RTT_LCR_CFG (PROPRIETARY_TLV_BASE_ID + 0x12B)	/* 0x0100 + 0x12B */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RTTLCRCfg_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** country_code */
+	char country_code[2];
+    /** length of the info field */
+	t_u32 length;
+    /** Civic info to be copied in FTM frame */
+	char civic_info[256];
+} MLAN_PACK_END MrvlIEtypes_RTTLCRCfg_t;
+
+/** 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;
+		HostCmd_DS_SDIO_SP_RX_AGGR_CFG sdio_rx_aggr;
+	/** 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;
+	/** 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;
+		HostCmd_DS_802_11_FW_WAKEUP_METHOD fwwakeupmethod;
+	/** 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;
+		/** 11K GET NLIST */
+		HostCmd_DS_802_11K_GET_NLIST get_nlist;
+		/** OFFLOAD FEATURE CTRL */
+		HostCmd_OFFLOAD_FEATURE_CTRL fctrl;
+		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;
+
+	/** 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_UAP_OPER_CTRL uap_oper_ctrl;
+#endif				/* UAP_SUPPORT */
+
+       /** Sleep period command */
+		HostCmd_DS_802_11_SLEEP_PERIOD sleep_pd;
+       /** Sleep params command */
+		HostCmd_DS_802_11_SLEEP_PARAMS sleep_param;
+
+       /** SDIO GPIO interrupt config command */
+		HostCmd_DS_SDIO_GPIO_INT_CONFIG sdio_gpio_int;
+		HostCmd_DS_SDIO_PULL_CTRL sdio_pull_ctl;
+		HostCmd_DS_SET_BSS_MODE bss_mode;
+		HostCmd_DS_802_11_NET_MONITOR net_mon;
+		HostCmd_DS_CMD_TX_DATA_PAUSE tx_data_pause;
+		HostCmd_DS_REMAIN_ON_CHANNEL remain_on_chan;
+#ifdef WIFI_DIRECT_SUPPORT
+		HostCmd_DS_WIFI_DIRECT_MODE wifi_direct_mode;
+		HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG p2p_params_config;
+#endif
+		HostCmd_DS_COALESCE_CONFIG coalesce_config;
+		HostCmd_DS_HS_WAKEUP_REASON hs_wakeup_reason;
+		HostCmd_DS_MULTI_CHAN_CFG multi_chan_cfg;
+		HostCmd_DS_MULTI_CHAN_POLICY multi_chan_policy;
+		HostCmd_DS_DRCS_CFG drcs_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_MIMO_SWITCH mimo_switch;
+#ifdef STA_SUPPORT
+		HostCmd_DS_STA_CONFIGURE sta_cfg;
+#endif
+    /** GPIO Independent reset configure */
+		HostCmd_DS_INDEPENDENT_RESET_CFG ind_rst_cfg;
+		HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT ps_inact_tmo;
+		HostCmd_DS_ROAM_OFFLOAD roam_offload;
+		HostCmd_DS_HOST_CLOCK_CFG host_clock_cfg;
+		HostCmd_DS_ACS acs;
+		HostCmd_DS_CHAN_REGION_CFG reg_cfg;
+		HostCmd_DS_FTM_CONFIG_SESSION_PARAMS ftm_config;
+		HostCmd_DS_FTM_CONFIG_RESPONDER ftm_rtt_responder;
+		HostCmd_DS_DYN_BW dyn_bw;
+		HostCmd_DS_802_11_ROBUSTCOEX robustcoexparams;
+    /** boot sleep configure */
+		HostCmd_DS_BOOT_SLEEP boot_sleep;
+	} params;
+} MLAN_PACK_END HostCmd_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_u8 hdr[4];
+#ifdef SPI_SUPPORT
+    /** Header for interface */
+	t_u16 hdr;
+#endif
+    /** 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;
+
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+#endif /* !_MLAN_FW_H_ */
diff --git a/wlan_sd8997/mlan/mlan_ieee.h b/wlan_sd8997/mlan/mlan_ieee.h
new file mode 100644
index 0000000..0a9f4ad
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_ieee.h
@@ -0,0 +1,1960 @@
+/** @file mlan_ieee.h
+ *
+ *  @brief This file contains IEEE information element related
+ *  definitions used in MLAN and MOAL module.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+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
+
+/** 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,
+	MEASUREMENT_REQUEST = 38,
+	MEASUREMENT_REPORT = 39,
+	REGULATORY_CLASS = 59,
+	HT_CAPABILITY = 45,
+	QOS_INFO = 46,
+	HT_OPERATION = 61,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	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_IE = VENDOR_SPECIFIC_221,
+	RSN_IE = 48,
+	VS_IE = VENDOR_SPECIFIC_221,
+	WAPI_IE = 68,
+} 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;
+
+#define MEASURE_TYPE_CLI 8
+#define MEASURE_TYPE_LOCATION_CIVIC 9
+
+/** Measurement Report IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MeasurementReport_t {
+    /** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+    /** Measurement Token */
+	t_u8 ms_token;
+    /** Measurement Report Mode */
+	t_u8 ms_rp_mode;
+    /** Measurement Type, value in MEASURE_TYPE_XXX */
+	t_u8 ms_type;
+    /** variable */
+	t_u8 variable[0];
+} MLAN_PACK_END IEEEtypes_MeasurementReport_t;
+
+/** Report */
+typedef MLAN_PACK_START struct _IEEEtypes_Report_t {
+    /** Subelement ID */
+	t_u8 subelement_id;
+    /** length */
+	t_u8 length;
+    /** variable */
+	t_u8 variable[0];
+} MLAN_PACK_END IEEEtypes_Report_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;
+
+/** 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[0];
+} MLAN_PACK_END IEEEtypes_Auth_framebody;
+
+/*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[0];
+} 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[0];
+} MLAN_PACK_END IEEEtypes_Ft_action_request;
+
+/*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_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_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_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
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN    4
+/** AKM Suite length */
+#define AKM_SUITE_LEN    4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT    7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT    6
+/** PMF ORing mask */
+#define PMF_MASK    0x00c0
+#endif
+
+/** wpa_suite_t */
+typedef MLAN_PACK_START struct _wpa_suite_t {
+    /** OUI */
+	t_u8 oui[3];
+    /** tyep */
+	t_u8 type;
+} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t;
+
+/** wpa_suite_ucast_t */
+typedef MLAN_PACK_START struct {
+	/* count */
+	t_u16 count;
+    /** wpa_suite list */
+	wpa_suite list[1];
+} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+
+/** IEEEtypes_Rsn_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t {
+    /** Rsn : Element ID */
+	t_u8 element_id;
+    /** Rsn : Length */
+	t_u8 len;
+    /** Rsn : version */
+	t_u16 version;
+    /** Rsn : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Rsn : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t;
+
+/** IEEEtypes_Wpa_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t {
+    /** Wpa : Element ID */
+	t_u8 element_id;
+    /** Wpa : Length */
+	t_u8 len;
+    /** Wpa : oui */
+	t_u8 oui[4];
+    /** version */
+	t_u16 version;
+    /** Wpa : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Wpa : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Reserved */
+	t_u8 reserved:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aifsn */
+	t_u8 aifsn:4;
+#else
+    /** Aifsn */
+	t_u8 aifsn:4;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn;   /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;		    /**< Ecw */
+	t_u16 tx_op_limit;		      /**< Tx op limit */
+} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t {
+
+    /**
+     * WMM Info IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [7]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [0]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+
+} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t {
+    /**
+     * WMM Parameter IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [24]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [1]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+    /** Reserved */
+	t_u8 reserved;
+
+    /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/** Enumerator for TSPEC direction */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e {
+
+	TSPEC_DIR_UPLINK = 0,
+	TSPEC_DIR_DOWNLINK = 1,
+	/* 2 is a reserved value */
+	TSPEC_DIR_BIDIRECT = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e;
+
+/** Enumerator for TSPEC PSB */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e {
+
+	TSPEC_PSB_LEGACY = 0,
+	TSPEC_PSB_TRIG = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e;
+
+/** Enumerator for TSPEC Ack Policy */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e {
+
+	TSPEC_ACKPOLICY_NORMAL = 0,
+	TSPEC_ACKPOLICY_NOACK = 1,
+	/* 2 is reserved */
+	TSPEC_ACKPOLICY_BLOCKACK = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e;
+
+/** Enumerator for TSPEC Trafffice type */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e {
+
+	TSPEC_TRAFFIC_APERIODIC = 0,
+	TSPEC_TRAFFIC_PERIODIC = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e;
+
+/** Data structure of WMM TSPEC information */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+	t_u8 Schedule:1;
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 AccessPolicy1:1;	/* ! */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+#else
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 AccessPolicy1:1;	/* ! */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 Schedule:1;
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t;
+
+/** Data structure of WMM TSPEC Nominal Size */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+	t_u16 Size:15;		/* ! Nominal size in octets */
+#else
+	t_u16 Size:15;		/* ! Nominal size in octets */
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t;
+
+/** Data structure of WMM TSPEC SBWA */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Whole:3;		/* ! Whole portion */
+	t_u16 Fractional:13;	/* ! Fractional portion */
+#else
+	t_u16 Fractional:13;	/* ! Fractional portion */
+	t_u16 Whole:3;		/* ! Whole portion */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA;
+
+/** Data structure of WMM TSPEC Body */
+typedef MLAN_PACK_START struct {
+
+    /** TS Information */
+	IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo;
+    /** NomMSDU size */
+	IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize;
+    /** MAximum MSDU size */
+	t_u16 MaximumMSDUSize;
+    /** Minimum Service Interval */
+	t_u32 MinServiceInterval;
+    /** Maximum Service Interval */
+	t_u32 MaxServiceInterval;
+    /** Inactivity Interval */
+	t_u32 InactivityInterval;
+    /** Suspension Interval */
+	t_u32 SuspensionInterval;
+    /** Service Start Time */
+	t_u32 ServiceStartTime;
+    /** Minimum Data Rate */
+	t_u32 MinimumDataRate;
+    /** Mean Data Rate */
+	t_u32 MeanDataRate;
+    /** Peak Data Rate */
+	t_u32 PeakDataRate;
+    /** Maximum Burst Size */
+	t_u32 MaxBurstSize;
+    /** Delay Bound */
+	t_u32 DelayBound;
+    /** Minimum Phy Rate */
+	t_u32 MinPHYRate;
+    /** Surplus BA Allowance */
+	IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance;
+    /** Medium Time */
+	t_u16 MediumTime;
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t;
+
+/** Data structure of WMM TSPEC all elements */
+typedef MLAN_PACK_START struct {
+    /** Element ID */
+	t_u8 ElementId;
+    /** Length */
+	t_u8 Len;
+    /** Oui Type */
+	t_u8 OuiType[4];	/* 00:50:f2:02 */
+    /** Ouisubtype */
+	t_u8 OuiSubType;	/* 01 */
+    /** Version */
+	t_u8 Version;
+
+    /** TspecBody */
+	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 {
+
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+    /** Action */
+	IEEEtypes_WMM_Tspec_Action_e action;
+    /** Dialog Token */
+	t_u8 dialogToken;
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t;
+
+/** WMM TSPEC AddTS request structure */
+typedef MLAN_PACK_START struct {
+
+    /** Tspec action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Status Code */
+	t_u8 statusCode;
+    /** tspecIE */
+	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 {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Reason Code */
+	t_u8 reasonCode;
+    /** tspecIE */
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t;
+
+/** union of WMM TSPEC structures */
+typedef MLAN_PACK_START union {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+
+    /** add TS request */
+	IEEEtypes_Action_WMM_AddTsReq_t addTsReq;
+    /** add TS response */
+	IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp;
+    /** Delete TS */
+	IEEEtypes_Action_WMM_DelTs_t delTs;
+
+} MLAN_PACK_END IEEEtypes_Action_WMMAC_t;
+
+/** union of WMM TSPEC & Action category */
+typedef MLAN_PACK_START union {
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+
+    /** wmmAc */
+	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;
+
+/** 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;
+    /** Channel width */
+	t_u8 chan_width;
+    /** Channel center frequency 1 */
+	t_u8 chan_center_freq_1;
+    /** Channel center frequency 2 */
+	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;
+    /** maximum tx power */
+	t_u8 max_tx_power;
+    /** channel center frequency */
+	t_u8 chan_center_freq;
+    /** channel width */
+	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;
+    /** MIMO capability count */
+	t_u8 MU_MIMO_capa_count;
+    /** stream under utilization */
+	t_u8 stream_underutilization;
+    /** VHT 40 util */
+	t_u8 VHT40_util;
+    /** VHT 80 util */
+	t_u8 VHT80_util;
+    /** VHT 160 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;
+    /** AP quiet mode */
+	t_u8 AP_quiet_mode;
+    /** Quiet count */
+	t_u8 quiet_count;
+    /** Quiet period */
+	t_u8 quiet_period;
+    /** Quiet duration */
+	t_u16 quiet_dur;
+    /** Quiet offset */
+	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;
+    /** New channel width */
+	t_u8 new_chan_width;
+    /** New channel center frequency 1 */
+	t_u8 new_chan_center_freq_1;
+    /** New channel center frequency 2 */
+	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;
+
+/** default channel switch count */
+#define DEF_CHAN_SWITCH_COUNT       5
+
+/*  IEEE Channel Switch Announcement Element (7.3.2.20) */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a chan switch element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;	/**< IEEE Element ID = 37 */
+	t_u8 len;		/**< Element length after id and len */
+	t_u8 chan_switch_mode;	/**< STA should not transmit any frames if 1 */
+	t_u8 new_channel_num;	/**< Channel # that AP/IBSS is moving to */
+	t_u8 chan_switch_count;	/**< # of TBTTs before channel switch */
+
+} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t;
+
+/** data structure for extended channel switch */
+typedef MLAN_PACK_START struct {
+   /** IEEE element ID = 60 */
+	t_u8 element_id;
+    /** Element length after id and len, set to 4 */
+	t_u8 len;
+    /** STA should not transmit any frames if 1 */
+	t_u8 chan_switch_mode;
+    /** Operate class # that AP/IBSS is moving to */
+	t_u8 new_oper_class;
+    /** Channel # that AP/IBSS is moving to */
+	t_u8 new_channel_num;
+    /** of TBTTs before channel switch */
+	t_u8 chan_switch_count;
+} MLAN_PACK_END IEEEtypes_ExtChanSwitchAnn_t;
+
+/*  IEEE Wide Bandwidth Channel Switch Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a wide bandwidth chan
+ *    switch element.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 194*/
+	IEEEtypes_Header_t ieee_hdr;
+    /** New channel width */
+	t_u8 new_channel_width;
+    /** New channel center frequency 0*/
+	t_u8 new_channel_center_freq0;
+    /** New channel center frequency 1*/
+	t_u8 new_channel_center_freq1;
+} MLAN_PACK_END IEEEtypes_WideBWChanSwitch_t;
+
+/*  IEEE VHT Transmit Power Envelope Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise the max
+ *    TX power in sepeate bandwidth and as a sub element of Channel Switch
+ *    Wrapper IE.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 195*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 tpc_info;		/**< Transmit Power Information>*/
+	t_u8 local_max_tp_20mhz;/**< Local Maximum Transmit Power for 20 MHZ>*/
+	t_u8 local_max_tp_40mhz;/**< Local Maximum Transmit Power for 40 MHZ>*/
+	t_u8 local_max_tp_80mhz;/**< Local Maximum Transmit Power for 80 MHZ>*/
+} MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t;
+
+/** 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 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
+
+/** 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;
+
+/** 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];
+} 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
+
+/**
+ *  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;
+	t_u8 random_mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END wlan_bgscan_cfg;
+#endif /* STA_SUPPORT */
+
+/** 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;
+} MLAN_PACK_END ChanStatistics_t;
+
+#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 */
+	t_u32 channel;
+
+    /** Freq */
+	t_u32 freq;
+
+    /** Beacon period */
+	t_u16 beacon_period;
+
+    /** ATIM window */
+	t_u32 atim_window;
+
+    /** ERP flags */
+	t_u8 erp_flags;
+
+    /** Type of network in use */
+	WLAN_802_11_NETWORK_TYPE network_type_use;
+
+    /** Network infrastructure mode */
+	t_u32 bss_mode;
+
+    /** Network supported rates */
+	WLAN_802_11_RATES supported_rates;
+
+    /** Supported data rates */
+	t_u8 data_rates[WLAN_SUPPORTED_RATES];
+
+    /** Current channel bandwidth
+     *  0 : 20MHZ
+     *  1 : 40MHZ
+     *  2 : 80MHZ
+     *  3 : 160MHZ
+     */
+	t_u8 curr_bandwidth;
+
+    /** Network band.
+     * BAND_B(0x01): 'b' band
+     * BAND_G(0x02): 'g' band
+     * BAND_A(0X04): 'a' band
+     */
+	t_u16 bss_band;
+
+    /** TSF timestamp from the current firmware TSF */
+	t_u64 network_tsf;
+
+    /** TSF value included in the beacon/probe response */
+	t_u8 time_stamp[8];
+
+    /** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+
+    /** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+
+    /** Capability information */
+	IEEEtypes_CapInfo_t cap_info;
+
+    /** WMM IE */
+	IEEEtypes_WmmParameter_t wmm_ie;
+
+    /** 802.11h BSS information */
+	wlan_11h_bss_info_t wlan_11h_bss_info;
+
+    /** Indicate disabling 11n when associate with AP */
+	t_u8 disable_11n;
+    /** 802.11n BSS information */
+    /** HT Capabilities IE */
+	IEEEtypes_HTCap_t *pht_cap;
+    /** HT Capabilities Offset */
+	t_u16 ht_cap_offset;
+    /** HT Information IE */
+	IEEEtypes_HTInfo_t *pht_info;
+    /** HT Information Offset */
+	t_u16 ht_info_offset;
+    /** 20/40 BSS Coexistence IE */
+	IEEEtypes_2040BSSCo_t *pbss_co_2040;
+    /** 20/40 BSS Coexistence Offset */
+	t_u16 bss_co_2040_offset;
+    /** Extended Capabilities IE */
+	IEEEtypes_ExtCap_t *pext_cap;
+    /** Extended Capabilities Offset */
+	t_u16 ext_cap_offset;
+    /** Overlapping BSS Scan Parameters IE */
+	IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param;
+    /** Overlapping BSS Scan Parameters Offset */
+	t_u16 overlap_bss_offset;
+
+    /** VHT Capabilities IE */
+	IEEEtypes_VHTCap_t *pvht_cap;
+    /** VHT Capabilities IE offset */
+	t_u16 vht_cap_offset;
+    /** VHT Operations IE */
+	IEEEtypes_VHTOprat_t *pvht_oprat;
+    /** VHT Operations IE offset */
+	t_u16 vht_oprat_offset;
+    /** VHT Transmit Power Envelope IE */
+	IEEEtypes_VHTtxpower_t *pvht_txpower;
+    /** VHT Transmit Power Envelope IE offset */
+	t_u16 vht_txpower_offset;
+    /** Extended Power Constraint IE */
+	IEEEtypes_ExtPwerCons_t *pext_pwer;
+    /** Extended Power Constraint IE offset */
+	t_u16 ext_pwer_offset;
+    /** Extended BSS Load IE  */
+	IEEEtypes_ExtBSSload_t *pext_bssload;
+    /** Extended BSS Load IE offset */
+	t_u16 ext_bssload_offset;
+    /** Quiet Channel IE */
+	IEEEtypes_QuietChan_t *pquiet_chan;
+    /** Quiet Channel IE offset */
+	t_u16 quiet_chan_offset;
+    /** Operating Mode Notification IE */
+	IEEEtypes_OperModeNtf_t *poper_mode;
+    /** Operating Mode Notification IE offset */
+	t_u16 oper_mode_offset;
+
+#ifdef STA_SUPPORT
+    /** Country information set */
+	IEEEtypes_CountryInfoFullSet_t country_info;
+#endif				/* STA_SUPPORT */
+
+    /** WPA IE */
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+    /** WPA IE offset in the beacon buffer */
+	t_u16 wpa_offset;
+    /** RSN IE */
+	IEEEtypes_Generic_t *prsn_ie;
+    /** RSN IE offset in the beacon buffer */
+	t_u16 rsn_offset;
+#ifdef STA_SUPPORT
+    /** WAPI IE */
+	IEEEtypes_Generic_t *pwapi_ie;
+    /** WAPI IE offset in the beacon buffer */
+	t_u16 wapi_offset;
+#endif
+	/* Mobility domain IE */
+	IEEEtypes_MobilityDomain_t *pmd_ie;
+	/** Mobility domain IE offset in the beacon buffer */
+	t_u16 md_offset;
+
+    /** Pointer to the returned scan response */
+	t_u8 *pbeacon_buf;
+    /** Length of the stored scan response */
+	t_u32 beacon_buf_size;
+    /** Max allocated size for updated scan response */
+	t_u32 beacon_buf_size_max;
+
+} BSSDescriptor_t, *pBSSDescriptor_t;
+
+/**
+ *  Type definitions for TCLAS element
+ */
+#define TCLAS_CLASSIFIER_TYPE_4      4
+
+/**
+ *  IEEE TCLAS Classifier Type 4
+ *
+ *  Type definition for Classifier Type 4 in TCLAS element
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_IPv4_t {
+    /** Version */
+	t_u8 version;
+    /** Source IP address */
+	t_u8 source_ip_addr[4];
+    /** Dest IP address */
+	t_u8 dest_ip_addr[4];
+    /** Source port */
+	t_u8 source_port[2];
+    /** Dest port */
+	t_u8 dest_port[2];
+    /** DSCP value */
+	t_u8 dscp;
+    /** Protocol value */
+	t_u8 protocol;
+    /** Reserved */
+	t_u8 reserved;
+} MLAN_PACK_END IEEEtypes_TCLAS_IPv4_t;
+
+/**
+ *  IEEE TCLAS base
+ *
+ *  Type definition for common parameters for every
+ *    classifier type
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_Base_t {
+    /** Element id */
+	t_u8 element_id;
+    /** Element len */
+	t_u8 element_len;
+    /** User priority */
+	t_u8 user_priority;
+    /** Classifier type */
+	t_u8 classifier_type;
+    /** Classifier mask */
+	t_u8 classifier_mask;
+} MLAN_PACK_END IEEEtypes_TCLAS_Base_t;
+
+/**
+ *  IEEE TCLAS element
+ *
+ *  Type definition for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_t {
+    /** Base structure for TCLAS */
+	IEEEtypes_TCLAS_Base_t tclas_base;
+
+	union MLAN_PACK_START {
+	/** Classifier type 4 */
+		IEEEtypes_TCLAS_IPv4_t ipv4;
+	} MLAN_PACK_END classifier;
+} MLAN_PACK_END IEEEtypes_TCLAS_t;
+
+/**
+ *  TCLAS element TLV
+ *
+ *  Structure that defines TLV for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _tclasElemen_tlv {
+    /** Type */
+	t_u16 type;
+    /** Length of TLV */
+	t_u16 len;
+    /** Tclas Ie */
+	IEEEtypes_TCLAS_t tclas_ie;
+} MLAN_PACK_END tclas_element_tlv_t;
+
+#endif /* !_MLAN_IEEE_H_ */
diff --git a/wlan_sd8997/mlan/mlan_init.c b/wlan_sd8997/mlan/mlan_init.c
new file mode 100644
index 0000000..66730bb
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_init.c
@@ -0,0 +1,1658 @@
+/** @file mlan_init.c
+ *
+ *  @brief This file contains the initialization for FW
+ *  and HW.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/13/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_init.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11h.h"
+#include "mlan_meas.h"
+#include "mlan_sdio.h"
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+#include "hostsa_init.h"
+#endif
+
+/********************************************************
+			Global Variables
+********************************************************/
+extern mlan_operations *mlan_ops[];
+/*******************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief This function adds a BSS priority table
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_add_bsspriotbl(pmlan_private priv)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_bssprio_node *pbssprio = MNULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	status = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						  sizeof(mlan_bssprio_node),
+						  MLAN_MEM_DEF,
+						  (t_u8 **)&pbssprio);
+	if (status) {
+		PRINTM(MERROR, "Failed to allocate bsspriotbl\n");
+		LEAVE();
+		return status;
+	}
+
+	pbssprio->priv = priv;
+
+	util_init_list((pmlan_linked_list)pbssprio);
+
+	if (!pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur)
+		pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur
+			= pbssprio;
+
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &pmadapter->bssprio_tbl[priv->bss_priority].
+			       bssprio_head, (pmlan_linked_list)pbssprio,
+			       pmadapter->callbacks.moal_spin_lock,
+			       pmadapter->callbacks.moal_spin_unlock);
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function deletes the BSS priority table
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         N/A
+ */
+static t_void
+wlan_delete_bsspriotbl(pmlan_private priv)
+{
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_bssprio_node *pbssprio_node = MNULL, *ptmp_node = MNULL, **ppcur =
+		MNULL;
+	pmlan_list_head phead;
+
+	ENTER();
+
+	for (i = 0; i < pmadapter->priv_num; ++i) {
+		phead = &pmadapter->bssprio_tbl[i].bssprio_head;
+		ppcur = &pmadapter->bssprio_tbl[i].bssprio_cur;
+		PRINTM(MINFO,
+		       "Delete BSS priority table, index = %d, i = %d, phead = %p, pcur = %p\n",
+		       priv->bss_index, i, phead, *ppcur);
+		if (*ppcur) {
+			pbssprio_node =
+				(mlan_bssprio_node *)util_peek_list(pmadapter->
+								    pmoal_handle,
+								    phead,
+								    pmadapter->
+								    callbacks.
+								    moal_spin_lock,
+								    pmadapter->
+								    callbacks.
+								    moal_spin_unlock);
+			while (pbssprio_node &&
+			       ((pmlan_list_head)pbssprio_node != phead)) {
+				ptmp_node = pbssprio_node->pnext;
+				if (pbssprio_node->priv == priv) {
+					PRINTM(MINFO,
+					       "Delete node, pnode = %p, pnext = %p\n",
+					       pbssprio_node, ptmp_node);
+					util_unlink_list(pmadapter->
+							 pmoal_handle, phead,
+							 (pmlan_linked_list)
+							 pbssprio_node,
+							 pmadapter->callbacks.
+							 moal_spin_lock,
+							 pmadapter->callbacks.
+							 moal_spin_unlock);
+					pmadapter->callbacks.
+						moal_mfree(pmadapter->
+							   pmoal_handle,
+							   (t_u8 *)
+							   pbssprio_node);
+				}
+				pbssprio_node = ptmp_node;
+			}
+			*ppcur = (mlan_bssprio_node *)phead;
+		}
+	}
+
+	LEAVE();
+}
+
+/********************************************************
+			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
+	t_u32 max_mp_regs = MAX_MP_REGS;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	t_u32 mp_tx_aggr_buf_size = SDIO_MP_TX_AGGR_DEF_BUF_SIZE;
+	t_u32 mp_rx_aggr_buf_size = SDIO_MP_RX_AGGR_DEF_BUF_SIZE;
+#endif
+
+	ENTER();
+
+#ifdef STA_SUPPORT
+	/* Allocate buffer to store the BSSID list */
+	buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST;
+	if (pmadapter->callbacks.moal_vmalloc &&
+	    pmadapter->callbacks.moal_vfree)
+		ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle,
+							buf_size,
+							(t_u8 **)
+							&ptemp_scan_table);
+	else
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       buf_size, MLAN_MEM_DEF,
+						       (t_u8 **)
+						       &ptemp_scan_table);
+	if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) {
+		PRINTM(MERROR, "Failed to allocate scan table\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->pscan_table = ptemp_scan_table;
+
+	if (pmadapter->fixed_beacon_buffer)
+		beacon_buffer_size = MAX_SCAN_BEACON_BUFFER;
+	else
+		beacon_buffer_size = DEFAULT_SCAN_BEACON_BUFFER;
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       beacon_buffer_size, MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->bcn_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->bcn_buf) {
+		PRINTM(MERROR, "Failed to allocate bcn buf\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->bcn_buf_size = beacon_buffer_size;
+
+	pmadapter->num_in_chan_stats = sizeof(chan_2g);
+	pmadapter->num_in_chan_stats += sizeof(chan_5g);
+	buf_size = sizeof(ChanStatistics_t) * pmadapter->num_in_chan_stats;
+	if (pmadapter->callbacks.moal_vmalloc &&
+	    pmadapter->callbacks.moal_vfree)
+		ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle,
+							buf_size,
+							(t_u8 **)&pmadapter->
+							pchan_stats);
+	else
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       buf_size, MLAN_MEM_DEF,
+						       (t_u8 **)&pmadapter->
+						       pchan_stats);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pchan_stats) {
+		PRINTM(MERROR, "Failed to allocate channel statistics\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+#endif
+
+	/* Allocate command buffer */
+	ret = wlan_alloc_cmd_buffer(pmadapter);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to allocate command buffer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       max_mp_regs + DMA_ALIGNMENT,
+					       MLAN_MEM_DEF | MLAN_MEM_DMA,
+					       (t_u8 **)&pmadapter->
+					       mp_regs_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mp_regs_buf) {
+		PRINTM(MERROR, "Failed to allocate mp_regs_buf\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->mp_regs =
+		(t_u8 *)ALIGN_ADDR(pmadapter->mp_regs_buf, DMA_ALIGNMENT);
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       SDIO_CMD53_MAX_SIZE +
+					       DMA_ALIGNMENT,
+					       MLAN_MEM_DEF | MLAN_MEM_DMA,
+					       (t_u8 **)&pmadapter->rx_buffer);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->rx_buffer) {
+		PRINTM(MERROR, "Failed to allocate receive buffer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->rx_buf =
+		(t_u8 *)ALIGN_ADDR(pmadapter->rx_buffer, DMA_ALIGNMENT);
+#endif
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	pmadapter->max_sp_tx_size = MAX_SUPPORT_AMSDU_SIZE;
+	pmadapter->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->mpa_buf_size =
+			SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT *
+			MLAN_SDIO_BLOCK_SIZE;
+		if (pmadapter->callbacks.moal_vmalloc &&
+		    pmadapter->callbacks.moal_vfree)
+			ret = pmadapter->callbacks.moal_vmalloc(pmadapter->
+								pmoal_handle,
+								pmadapter->
+								mpa_buf_size,
+								(t_u8 **)
+								&pmadapter->
+								mpa_buf);
+		else
+			ret = pmadapter->callbacks.moal_malloc(pmadapter->
+							       pmoal_handle,
+							       pmadapter->
+							       mpa_buf_size,
+							       MLAN_MEM_DEF,
+							       (t_u8 **)
+							       &pmadapter->
+							       mpa_buf);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->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);
+
+	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;
+
+	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->adhoc_aes_enabled = 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);
+	priv->enable_11k = MFALSE;
+
+#ifdef UAP_SUPPORT
+	priv->uap_bss_started = MFALSE;
+	priv->uap_host_based = MFALSE;
+	memset(pmadapter, &priv->uap_state_chan_cb, 0,
+	       sizeof(priv->uap_state_chan_cb));
+#endif
+#if defined(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->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+	priv->atim_window = 0;
+	priv->adhoc_state = ADHOC_IDLE;
+	priv->tx_power_level = 0;
+	priv->max_tx_power_level = 0;
+	priv->min_tx_power_level = 0;
+	priv->tx_rate = 0;
+	priv->rxpd_rate_info = 0;
+	priv->rx_pkt_info = MFALSE;
+	/* refer to V15 CMD_TX_RATE_QUERY */
+	priv->rxpd_vhtinfo = 0;
+	priv->rxpd_rate = 0;
+	priv->rate_bitmap = 0;
+	priv->data_rssi_last = 0;
+	priv->data_rssi_avg = 0;
+	priv->data_nf_avg = 0;
+	priv->data_nf_last = 0;
+	priv->bcn_rssi_last = 0;
+	priv->bcn_rssi_avg = 0;
+	priv->bcn_nf_avg = 0;
+	priv->bcn_nf_last = 0;
+
+	priv->sec_info.ewpa_enabled = MFALSE;
+	priv->sec_info.wpa_enabled = MFALSE;
+	priv->sec_info.wpa2_enabled = MFALSE;
+	memset(pmadapter, &priv->wpa_ie, 0, sizeof(priv->wpa_ie));
+	memset(pmadapter, &priv->aes_key, 0, sizeof(priv->aes_key));
+	priv->wpa_ie_len = 0;
+	priv->wpa_is_gtk_set = MFALSE;
+#if defined(STA_SUPPORT)
+	priv->pmfcfg.mfpc = 0;
+	priv->pmfcfg.mfpr = 0;
+#endif
+	priv->sec_info.wapi_enabled = MFALSE;
+	priv->wapi_ie_len = 0;
+	priv->sec_info.wapi_key_on = MFALSE;
+
+	memset(pmadapter, &priv->wps, 0, sizeof(priv->wps));
+	memset(pmadapter, &priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
+	priv->gen_ie_buf_len = 0;
+#endif /* STA_SUPPORT */
+	priv->wmm_required = MTRUE;
+	priv->wmm_enabled = MFALSE;
+	priv->wmm_qosinfo = 0;
+	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;
+	priv->tdls_idle_time = TDLS_IDLE_TIMEOUT;
+	priv->txaggrctrl = MTRUE;
+#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(priv->adapter, &priv->def_ext_cap, &priv->ext_cap,
+	       sizeof(priv->ext_cap));
+#endif /* STA_SUPPORT */
+
+	for (i = 0; i < MAX_NUM_TID; i++)
+		priv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+	priv->addba_reject[6] = ADDBA_RSP_STATUS_REJECT;
+	priv->addba_reject[7] = ADDBA_RSP_STATUS_REJECT;
+	memcpy(priv->adapter, priv->ibss_addba_reject, priv->addba_reject,
+	       sizeof(priv->addba_reject));
+	priv->max_amsdu = 0;
+#ifdef STA_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+		priv->add_ba_param.tx_win_size = MLAN_STA_AMPDU_DEF_TXWINSIZE;
+		priv->add_ba_param.rx_win_size = MLAN_STA_AMPDU_DEF_RXWINSIZE;
+	}
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+		priv->add_ba_param.tx_win_size = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+		priv->add_ba_param.rx_win_size = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+	}
+#endif
+#ifdef UAP_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		priv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+		priv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE;
+		priv->aggr_prio_tbl[6].ampdu_user =
+			priv->aggr_prio_tbl[7].ampdu_user =
+			BA_STREAM_NOT_ALLOWED;
+	}
+#endif
+	priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
+
+	priv->port_ctrl_mode = MTRUE;
+
+	priv->port_open = MFALSE;
+
+	priv->intf_hr_len = INTF_HEADER_LEN;
+	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;
+
+	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
+
+	pmadapter->int_mode = pmadapter->init_para.int_mode;
+	pmadapter->gpio_pin = pmadapter->init_para.gpio_pin;
+
+#if defined(STA_SUPPORT)
+	pmadapter->pwarm_reset_ioctl_req = MNULL;
+#endif
+	pmadapter->cmd_sent = MFALSE;
+	pmadapter->data_sent = MTRUE;
+	pmadapter->mp_rd_bitmap = 0;
+	pmadapter->mp_wr_bitmap = 0;
+	pmadapter->curr_rd_port = 0;
+	pmadapter->curr_wr_port = 0;
+	pmadapter->mp_data_port_mask = DATA_PORT_MASK;
+	pmadapter->mp_invalid_update = 0;
+	memset(pmadapter, pmadapter->mp_update, 0,
+	       sizeof(pmadapter->mp_update));
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	pmadapter->mpa_tx.buf_len = 0;
+	pmadapter->mpa_tx.pkt_cnt = 0;
+	pmadapter->mpa_tx.start_port = 0;
+
+	if (!pmadapter->init_para.mpa_tx_cfg)
+		pmadapter->mpa_tx.enabled = MFALSE;
+	else if (pmadapter->init_para.mpa_tx_cfg == MLAN_INIT_PARA_DISABLED)
+		pmadapter->mpa_tx.enabled = MFALSE;
+	else
+		pmadapter->mpa_tx.enabled = MTRUE;
+	pmadapter->mpa_tx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	pmadapter->mpa_rx.buf_len = 0;
+	pmadapter->mpa_rx.pkt_cnt = 0;
+	pmadapter->mpa_rx.start_port = 0;
+
+	if (!pmadapter->init_para.mpa_rx_cfg)
+		pmadapter->mpa_rx.enabled = MFALSE;
+	else if (pmadapter->init_para.mpa_rx_cfg == MLAN_INIT_PARA_DISABLED)
+		pmadapter->mpa_rx.enabled = MFALSE;
+	else
+		pmadapter->mpa_rx.enabled = MTRUE;
+	pmadapter->mpa_rx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+	pmadapter->rx_pkts_queued = 0;
+	pmadapter->cmd_resp_received = MFALSE;
+	pmadapter->event_received = MFALSE;
+	pmadapter->data_received = MFALSE;
+
+	pmadapter->cmd_timer_is_set = MFALSE;
+
+	/* PnP and power profile */
+	pmadapter->surprise_removed = MFALSE;
+
+	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;
+
+	pmadapter->num_in_scan_table = 0;
+	memset(pmadapter, pmadapter->pscan_table, 0,
+	       (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
+	pmadapter->active_scan_triggered = MFALSE;
+	pmadapter->ext_scan = MTRUE;
+	pmadapter->scan_probes = DEFAULT_PROBES;
+
+	memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size);
+	pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+
+	pmadapter->radio_on = RADIO_ON;
+	if (!pmadapter->multiple_dtim)
+		pmadapter->multiple_dtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
+
+	pmadapter->local_listen_interval = 0;	/* default value in firmware will be used */
+#endif /* STA_SUPPORT */
+	pmadapter->fw_wakeup_method = WAKEUP_FW_UNCHANGED;
+	pmadapter->fw_wakeup_gpio_pin = DEF_WAKEUP_FW_GPIO;
+
+	pmadapter->is_deep_sleep = MFALSE;
+	pmadapter->idle_time = DEEP_SLEEP_IDLE_TIME;
+	if (!pmadapter->init_para.auto_ds)
+		pmadapter->init_auto_ds = DEFAULT_AUTO_DS_MODE;
+	else if (pmadapter->init_para.auto_ds == MLAN_INIT_PARA_DISABLED)
+		pmadapter->init_auto_ds = MFALSE;
+	else
+		pmadapter->init_auto_ds = MTRUE;
+
+	pmadapter->delay_null_pkt = MFALSE;
+	pmadapter->delay_to_ps = DELAY_TO_PS_DEFAULT;
+	pmadapter->enhanced_ps_mode = PS_MODE_AUTO;
+
+	pmadapter->gen_null_pkt = MFALSE;	/* Disable NULL Pkt generation-default */
+	pmadapter->pps_uapsd_mode = MFALSE;	/* Disable pps/uapsd mode -default */
+
+	pmadapter->pm_wakeup_card_req = MFALSE;
+
+	pmadapter->pm_wakeup_fw_try = MFALSE;
+
+	if (!pmadapter->init_para.max_tx_buf)
+		pmadapter->max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K;
+	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;
+
+	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->adhoc_11n_enabled = MFALSE;
+	pmadapter->tdls_status = TDLS_NOT_SETUP;
+#endif /* STA_SUPPORT */
+
+	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);
+	}
+	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->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(pmadapter, pmadapter->country_code, MRVDRV_DEFAULT_COUNTRY_CODE,
+	       COUNTRY_CODE_LEN);
+	pmadapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
+	pmadapter->adhoc_awake_period = 0;
+#ifdef STA_SUPPORT
+	memset(pmadapter, &pmadapter->arp_filter, 0,
+	       sizeof(pmadapter->arp_filter));
+	pmadapter->arp_filter_size = 0;
+#endif /* STA_SUPPORT */
+
+	pmadapter->mc_status = MFALSE;
+
+	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(IN 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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pmlan_lock)
+	    != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pint_lock)
+	    != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	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;
+	}
+
+	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(IN 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 (pmadapter->pint_lock)
+		pcb->moal_free_lock(pmadapter->pmoal_handle,
+				    pmadapter->pint_lock);
+	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);
+
+	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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	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;
+	}
+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(IN pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	if (pmadapter->pmlan_cmd_timer)
+		pcb->moal_free_timer(pmadapter->pmoal_handle,
+				     pmadapter->pmlan_cmd_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(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	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
+	}
+#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;
+	}
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode == MTRUE) {
+		pmadapter->hw_status = WlanHardwareStatusInitializing;
+		ret = wlan_get_hw_spec_complete(pmadapter);
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function udpate hw spec info to each interface
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+void
+wlan_update_hw_spec(IN 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;
+			}
+		}
+		if ((pmadapter->fw_bands & BAND_AN)
+			) {
+			pmadapter->adhoc_start_band = BAND_A | BAND_AN;
+			pmadapter->adhoc_11n_enabled = MTRUE;
+		} else
+			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_GN)
+		) {
+		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i])
+				pmadapter->priv[i]->adhoc_channel =
+					DEFAULT_AD_HOC_CHANNEL;
+		}
+		pmadapter->adhoc_11n_enabled = MTRUE;
+	} 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 =
+					DEFAULT_11N_TX_BF_CAP;
+		}
+	}
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i])
+			wlan_update_11ac_cap(pmadapter->priv[i]);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief  This function initializes firmware for interface
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_init_priv_fw(IN 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;
+	} 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;
+	ENTER();
+
+	if (!pmadapter) {
+		PRINTM(MERROR, "The adapter is NULL\n");
+		LEAVE();
+		return;
+	}
+
+	wlan_cancel_all_pending_cmd(pmadapter);
+	/* 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;
+	}
+	wlan_free_fw_cfp_tables(pmadapter);
+#ifdef STA_SUPPORT
+	PRINTM(MINFO, "Free ScanTable\n");
+	if (pmadapter->pscan_table) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pscan_table);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pscan_table);
+		pmadapter->pscan_table = MNULL;
+	}
+	if (pmadapter->pchan_stats) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pchan_stats);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pchan_stats);
+		pmadapter->pchan_stats = MNULL;
+	}
+	if (pmadapter->bcn_buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->bcn_buf);
+		pmadapter->bcn_buf = MNULL;
+	}
+#endif
+
+	wlan_11h_cleanup(pmadapter);
+
+	if (pmadapter->mp_regs_buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mp_regs_buf);
+		pmadapter->mp_regs_buf = MNULL;
+		pmadapter->mp_regs = MNULL;
+	}
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+	if (pmadapter->rx_buffer) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->rx_buffer);
+		pmadapter->rx_buffer = MNULL;
+		pmadapter->rx_buf = MNULL;
+	}
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	wlan_free_sdio_mpa_buffers(pmadapter);
+#ifdef DEBUG_LEVEL1
+	if (pmadapter->mpa_buf) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->mpa_buf);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->mpa_buf);
+		pmadapter->mpa_buf = MNULL;
+		pmadapter->mpa_buf_size = 0;
+	}
+#endif
+#endif
+	wlan_free_mlan_buffer(pmadapter, pmadapter->psleep_cfm);
+	pmadapter->psleep_cfm = MNULL;
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function frees the structure of priv
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *
+ *  @return         N/A
+ */
+t_void
+wlan_free_priv(mlan_private *pmpriv)
+{
+	ENTER();
+	wlan_clean_txrx(pmpriv);
+	wlan_delete_bsspriotbl(pmpriv);
+
+#ifdef STA_SUPPORT
+	wlan_free_curr_bcn(pmpriv);
+#endif /* STA_SUPPORT */
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	hostsa_cleanup(pmpriv);
+#endif /*EMBEDDED AUTHENTICATOR */
+
+	wlan_delete_station_list(pmpriv);
+	LEAVE();
+}
+
+/**
+ *  @brief This function init interface based on pmadapter's bss_attr table
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+mlan_status
+wlan_init_interface(IN 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(pmadapter,
+					       &pmadapter->priv[i]->ops,
+					       mlan_ops[j],
+					       sizeof(mlan_operations));
+				}
+			}
+		}
+	}
+	/*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(IN pmlan_adapter pmadapter)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_hw_info info;
+	mlan_bss_tbl bss_tbl;
+
+	ENTER();
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode != MTRUE) {
+#endif
+		/* Check if hardware is ready */
+		if (pmadapter->hw_status != WlanHardwareStatusInitializing)
+			status = MLAN_STATUS_FAILURE;
+		else {
+			memset(pmadapter, &info, 0, sizeof(info));
+			info.fw_cap = pmadapter->fw_cap_info;
+			memset(pmadapter, &bss_tbl, 0, sizeof(bss_tbl));
+			memcpy(pmadapter, bss_tbl.bss_attr, pmadapter->bss_attr,
+			       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(pmadapter, pmadapter->bss_attr, bss_tbl.bss_attr,
+			       sizeof(mlan_bss_tbl));
+#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(IN pmlan_adapter pmadapter)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	/* Check if hardware is ready */
+	if (pmadapter->hw_status != WlanHardwareStatusReady)
+		status = MLAN_STATUS_FAILURE;
+
+	/* Reconfigure wmm parameter */
+	if (status == MLAN_STATUS_SUCCESS) {
+		wlan_prepare_cmd(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA),
+				 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(IN 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_sd8997/mlan/mlan_init.h b/wlan_sd8997/mlan/mlan_init.h
new file mode 100644
index 0000000..4cbe939
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_init.h
@@ -0,0 +1,96 @@
+/** @file mlan_init.h
+ *
+ *  @brief This file defines the FW initialization data
+ *  structures.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+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	620
+/** 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 CMD7 */
+#define FW_CMD_7                0x00000007
+
+/** 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;
+} MLAN_PACK_END FWSyncHeader;
+
+#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); \
+	}
+#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_sd8997/mlan/mlan_ioctl.h b/wlan_sd8997/mlan/mlan_ioctl.h
new file mode 100644
index 0000000..2097488
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_ioctl.h
@@ -0,0 +1,4751 @@
+/** @file mlan_ioctl.h
+ *
+ *  @brief This file declares the IOCTL data structures and APIs.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+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_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
+
+	/* 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,
+
+	/* 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,
+
+	/* 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_FW_WAKEUP_METHOD = 0x00090007,
+	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,
+
+	/* 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,
+#if defined(DFS_TESTING_SUPPORT)
+	MLAN_OID_11H_DFS_TESTING = 0x00110003,
+#endif
+	MLAN_OID_11H_CHAN_REPORT_REQUEST = 0x00110004,
+	MLAN_OID_11H_CHAN_SWITCH_COUNT = 0x00110005,
+#ifdef DFS_TESTING_SUPPORT
+	MLAN_OID_11H_CHAN_NOP_INFO = 0x00110006,
+#endif
+
+	/* 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,
+
+	MLAN_IOCTL_11K_CFG = 0x00130000,
+	MLAN_OID_11K_CFG_ENABLE = 0x00130001,
+	MLAN_OID_11K_GET_NLIST = 0x00130002,
+
+	/* 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,
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	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_COALESCING_STATUS = 0x0020000E,
+	MLAN_OID_MISC_CUSTOM_IE = 0x0020000F,
+	MLAN_OID_MISC_TDLS_CONFIG = 0x00200010,
+	MLAN_OID_MISC_NET_MONITOR = 0x00200011,
+	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_OTP_USER_DATA = 0x0020001D,
+	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
+	MLAN_OID_MISC_MULTI_CHAN_CFG = 0x00200023,
+	MLAN_OID_MISC_MULTI_CHAN_POLICY = 0x00200024,
+#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_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_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_ROAM_OFFLOAD = 0x00200042,
+	MLAN_OID_MISC_ROAM_OFFLOAD_APLIST = 0x00200043,
+	MLAN_OID_MISC_GET_TSF = 0x00200045,
+	MLAN_OID_MISC_GET_CHAN_REGION_CFG = 0x00200046,
+	MLAN_OID_MISC_OPER_CLASS_CHECK = 0x00200049,
+	MLAN_OID_MISC_DRCS_CFG = 0x00200050,
+
+	MLAN_OID_MISC_CWMODE_CTRL = 0x00200051,
+	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_CORRELATED_TIME = 0x00200058,
+	MLAN_OID_MISC_CONFIG_RTT = 0x00200059,
+	MLAN_OID_MISC_CANCEL_RTT = 0x0020005A,
+	MLAN_OID_MISC_RTT_RESPONDER_CFG = 0x0020005B,
+	MLAN_OID_MISC_CFP_INFO = 0x00200060,
+	MLAN_OID_MISC_BOOT_SLEEP = 0x00200061,
+	MLAN_OID_MISC_ACS = 0x00200063,
+};
+
+/** 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
+};
+
+/** 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
+};
+
+/** Max number of supported rates */
+#define MLAN_SUPPORTED_RATES	32
+
+/** 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
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES      4
+
+/** Default number of probes to send on each channel */
+#define DEFAULT_PROBES  4
+
+/** MAX BG channel */
+#define MAX_BG_CHANNEL 14
+
+/**
+ *  @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;
+    /** 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;
+
+/** tx status event structure */
+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;
+	/** t1 time stamp */
+	t_u64 t1_tstamp;
+	/** t4 time stamp */
+	t_u64 t4_tstamp;
+	/** t1 error */
+	t_u64 t1_error;
+	/** t4 error */
+	t_u64 t4_error;
+	/** egress time */
+	t_u64 egress_time;
+} 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[0]; */
+} 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;
+    /** Ext_scan:  0 disable, 1: enable, 2: enhance scan*/
+	t_u32 ext_scan;
+} 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 PMK R0 NAME key length */
+#define MLAN_MAX_PMKR0_NAME_LENGTH      16
+
+/** 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)
+
+/** mlan_ssid_bssid  data structure for
+ *  MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS
+ */
+typedef struct _mlan_ssid_bssid {
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+    /** index in BSSID list, start from 1 */
+	t_u32 idx;
+    /** Receive signal strength in dBm */
+	t_s32 rssi;
+    /**channel*/
+	t_u16 channel;
+    /**mobility domain value*/
+	t_u16 ft_md;
+    /**ft capability*/
+	t_u8 ft_cap;
+    /**band*/
+	t_u16 bss_band;
+	t_u32 channel_flags;
+} mlan_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
+/** 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   10
+/** 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  300
+/** 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           16
+
+/* 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
+
+/** 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
+
+/** 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;
+
+/** 5G band */
+#define BAND_CONFIG_5G        0x01
+/** 2.4 G band */
+#define BAND_CONFIG_2G        0x00
+/** 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;
+
+} mlan_uap_bss_param;
+
+/** mlan_uap_scan_channels */
+typedef struct _mlan_uap_scan_channels {
+    /** flag for remove nop channel*/
+	t_u8 remove_nop_channel;
+	/** num of removed channel */
+	t_u8 num_remvoed_channel;
+    /** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+    /** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+} mlan_uap_scan_channels;
+
+/** mlan_uap_oper_ctrl */
+typedef struct _mlan_uap_oper_ctrl {
+    /** control value
+      *  0: do nothing,
+      *  2: uap stops and restarts automaticaly
+     */
+	t_u16 ctrl_value;
+    /** channel opt
+      *  1: uap restart on default 2.4G/channel 6
+      *  2: uap restart on the band/channel configured by driver previously
+      *  3: uap restart on the band/channel specified by band_cfg and channel
+	*/
+	t_u16 chan_opt;
+    /** band cfg   0
+      *  0: 20Mhz  2: 40 Mhz  3: 80Mhz
+     */
+	t_u8 band_cfg;
+    /** channel */
+	t_u8 channel;
+} mlan_uap_oper_ctrl;
+
+#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 uap flag for MLAN_OID_BSS_START */
+		t_u8 host_based;
+	/** BSS param for AP mode for MLAN_OID_UAP_BSS_CONFIG */
+		mlan_uap_bss_param bss_config;
+	/** AP Wmm parameters for MLAN_OID_UAP_CFG_WMM_PARAM */
+		wmm_parameter_t ap_wmm_para;
+	/** ap scan channels for MLAN_OID_UAP_SCAN_CHANNELS*/
+		mlan_uap_scan_channels ap_scan_channels;
+	/** ap channel for MLAN_OID_UAP_CHANNEL*/
+		chan_band_info ap_channel;
+	/** ap operation control for MLAN_OID_UAP_OPER_CTRL*/
+		mlan_uap_oper_ctrl ap_oper_ctrl;
+#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
+	} param;
+} mlan_ds_bss, *pmlan_ds_bss;
+
+/** Type definition of mlan_ds_custom_reg_domain */
+typedef struct _mlan_ds_custom_reg_domain {
+	t_u8 cfg_len;
+	t_u8 cfg_buf[0];
+} 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,
+};
+
+/** 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;
+    /** Ad-hoc channel bandwidth */
+	t_u32 adhoc_chan_bandwidth;
+    /** 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
+
+/** filt field param structure */
+struct filt_field_param {
+	/** Operation */
+	t_u8 operation;
+	/** Operand len */
+	t_u8 operand_len;
+	/** offset */
+	t_u16 offset;
+	/** Operand byte stream */
+	t_u8 operand_byte_stream[COALESCE_MAX_BYTESEQ];
+};
+
+/** coalesce rule structure */
+struct coalesce_rule {
+	/** max coalescing delay */
+	t_u16 max_coalescing_delay;
+	/** number of fields */
+	t_u8 num_of_fields;
+	/** packet type */
+	t_u8 pkt_type;
+	struct filt_field_param params[COALESCE_MAX_FILTERS];
+};
+
+/** coalesce configuration structure */
+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
+};
+
+/** Get stats org structure */
+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;
+} mlan_ds_get_stats, *pmlan_ds_get_stats;
+
+/** Type definition of mlan_ds_get_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_get_correlated_time {
+   /** System time */
+	t_u64 sys_time;
+   /** FW time */
+	t_u64 hw_time;
+} mlan_ds_get_correlated_time, *pmlan_ds_get_correlated_time;
+
+/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_uap_stats {
+    /** tkip mic failures */
+	t_u32 tkip_mic_failures;
+    /** ccmp decrypt errors */
+	t_u32 ccmp_decrypt_errors;
+    /** wep undecryptable count */
+	t_u32 wep_undecryptable_count;
+    /** wep icv error count */
+	t_u32 wep_icv_error_count;
+    /** decrypt failure count */
+	t_u32 decrypt_failure_count;
+    /** dot11 multicast tx count */
+	t_u32 mcast_tx_count;
+    /** dot11 failed count */
+	t_u32 failed_count;
+    /** dot11 retry count */
+	t_u32 retry_count;
+    /** dot11 multi retry count */
+	t_u32 multi_retry_count;
+    /** dot11 frame duplicate count */
+	t_u32 frame_dup_count;
+    /** dot11 rts success count */
+	t_u32 rts_success_count;
+    /** dot11 rts failure count */
+	t_u32 rts_failure_count;
+    /** dot11 ack failure count */
+	t_u32 ack_failure_count;
+    /** dot11 rx ragment count */
+	t_u32 rx_fragment_count;
+    /** dot11 mcast rx frame count */
+	t_u32 mcast_rx_frame_count;
+    /** dot11 fcs error count */
+	t_u32 fcs_error_count;
+    /** dot11 tx frame count */
+	t_u32 tx_frame_count;
+    /** dot11 rsna tkip cm invoked */
+	t_u32 rsna_tkip_cm_invoked;
+    /** dot11 rsna 4way handshake failures */
+	t_u32 rsna_4way_hshk_failures;
+} mlan_ds_uap_stats, *pmlan_ds_uap_stats;
+
+/** Mask of last beacon RSSI */
+#define BCN_RSSI_LAST_MASK              0x00000001
+/** Mask of average beacon RSSI */
+#define BCN_RSSI_AVG_MASK               0x00000002
+/** Mask of last data RSSI */
+#define DATA_RSSI_LAST_MASK             0x00000004
+/** Mask of average data RSSI */
+#define DATA_RSSI_AVG_MASK              0x00000008
+/** Mask of last beacon SNR */
+#define BCN_SNR_LAST_MASK               0x00000010
+/** Mask of average beacon SNR */
+#define BCN_SNR_AVG_MASK                0x00000020
+/** Mask of last data SNR */
+#define DATA_SNR_LAST_MASK              0x00000040
+/** Mask of average data SNR */
+#define DATA_SNR_AVG_MASK               0x00000080
+/** Mask of last beacon NF */
+#define BCN_NF_LAST_MASK                0x00000100
+/** Mask of average beacon NF */
+#define BCN_NF_AVG_MASK                 0x00000200
+/** Mask of last data NF */
+#define DATA_NF_LAST_MASK               0x00000400
+/** Mask of average data NF */
+#define DATA_NF_AVG_MASK                0x00000800
+/** Mask of all RSSI_INFO */
+#define ALL_RSSI_INFO_MASK              0x00000fff
+#define MAX_PATH_NUM                    3
+/** path A */
+#define PATH_A							0x01
+/** path B */
+#define PATH_B							0x02
+/** path AB */
+#define PATH_AB							0x03
+/** ALL the path */
+#define PATH_ALL						0
+/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */
+typedef struct _mlan_ds_get_signal {
+    /** Selector of get operation */
+	/*
+	 * Bit0:  Last Beacon RSSI,  Bit1:  Average Beacon RSSI,
+	 * Bit2:  Last Data RSSI,    Bit3:  Average Data RSSI,
+	 * Bit4:  Last Beacon SNR,   Bit5:  Average Beacon SNR,
+	 * Bit6:  Last Data SNR,     Bit7:  Average Data SNR,
+	 * Bit8:  Last Beacon NF,    Bit9:  Average Beacon NF,
+	 * Bit10: Last Data NF,      Bit11: Average Data NF
+	 *
+	 * Bit0: PATH A
+	 * Bit1: PATH B
+	 */
+	t_u16 selector;
+
+    /** RSSI */
+    /** RSSI of last beacon */
+	t_s16 bcn_rssi_last;
+    /** RSSI of beacon average */
+	t_s16 bcn_rssi_avg;
+    /** RSSI of last data packet */
+	t_s16 data_rssi_last;
+    /** RSSI of data packet average */
+	t_s16 data_rssi_avg;
+
+    /** SNR */
+    /** SNR of last beacon */
+	t_s16 bcn_snr_last;
+    /** SNR of beacon average */
+	t_s16 bcn_snr_avg;
+    /** SNR of last data packet */
+	t_s16 data_snr_last;
+    /** SNR of data packet average */
+	t_s16 data_snr_avg;
+
+    /** NF */
+    /** NF of last beacon */
+	t_s16 bcn_nf_last;
+    /** NF of beacon average */
+	t_s16 bcn_nf_avg;
+    /** NF of last data packet */
+	t_s16 data_nf_last;
+    /** NF of data packet average */
+	t_s16 data_nf_avg;
+} mlan_ds_get_signal, *pmlan_ds_get_signal;
+
+/** bit for 2.4 G antenna diversity */
+#define ANT_DIVERSITY_2G   MBIT(3)
+/** bit for 5 G antenna diversity */
+#define ANT_DIVERSITY_5G   MBIT(7)
+
+/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */
+typedef struct _mlan_fw_info {
+    /** Firmware version */
+	t_u32 fw_ver;
+    /** MAC address */
+	mlan_802_11_mac_addr mac_addr;
+    /** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+    /** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+    /** user's MCS setting */
+	t_u8 usr_dev_mcs_support;
+    /** 802.11ac device capabilities */
+	t_u32 hw_dot_11ac_dev_cap;
+    /** 802.11ac device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11ac_dev_cap_bg;
+    /** 802.11ac device Capabilities for 5GHz */
+	t_u32 usr_dot_11ac_dev_cap_a;
+    /** 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_u8 fw_bands;
+	/** region code */
+	t_u16 region_code;
+    /** 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;
+    /** FW support roaming offload */
+	t_u8 fw_roaming_support;
+} mlan_fw_info, *pmlan_fw_info;
+
+/** Version string buffer length */
+#define MLAN_MAX_VER_STR_LEN    128
+
+/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */
+typedef struct _mlan_ver_ext {
+    /** Selected version string */
+	t_u32 version_str_sel;
+    /** Version string */
+	char version_str[MLAN_MAX_VER_STR_LEN];
+} mlan_ver_ext, *pmlan_ver_ext;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+    /** Extended Capabilities value */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit77: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 MaxAMSDU:2;	/* bit 63-bit 64 */
+	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 MaxAMSDU:2;	/* bit 63-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 rsvdBit77:1;	/* bit 77 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#endif
+
+/** ExtCap : TDLS prohibited */
+#define IS_EXTCAP_TDLS_PROHIBITED(ext_cap) (ext_cap.TDLSProhibited)
+/** ExtCap : TDLS channel switch prohibited */
+#define IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ext_cap) (ext_cap.TDLSChlSwitchProhib)
+
+/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */
+typedef struct _mlan_bss_info {
+    /** BSS mode */
+	t_u32 bss_mode;
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** Table index */
+	t_u32 scan_table_idx;
+    /** Channel */
+	t_u32 bss_chan;
+    /** Band */
+	t_u8 bss_band;
+    /** Region code */
+	t_u32 region_code;
+    /** Connection status */
+	t_u32 media_connected;
+    /** Radio on */
+	t_u32 radio_on;
+    /** Max power level in dBm */
+	t_s32 max_power_level;
+    /** Min power level in dBm */
+	t_s32 min_power_level;
+    /** Adhoc state */
+	t_u32 adhoc_state;
+    /** NF of last beacon */
+	t_s32 bcn_nf_last;
+    /** wep status */
+	t_u32 wep_status;
+    /** scan block status */
+	t_u8 scan_block;
+     /** Host Sleep configured flag */
+	t_u32 is_hs_configured;
+    /** Deep Sleep flag */
+	t_u32 is_deep_sleep;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+#ifdef STA_SUPPORT
+    /** Capability Info */
+	t_u16 capability_info;
+    /** Beacon Interval */
+	t_u16 beacon_interval;
+    /** Listen Interval */
+	t_u16 listen_interval;
+    /** Association Id  */
+	t_u16 assoc_id;
+    /** AP/Peer supported rates */
+	t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES];
+    /** extend capability for AP */
+	ExtCap_t ext_cap;
+#endif				/* STA_SUPPORT */
+    /** Mobility Domain ID */
+	t_u16 mdid;
+    /** FT Capability policy */
+	t_u8 ft_cap;
+    /** 11h active */
+	t_bool is_11h_active;
+    /** dfs check channel */
+	t_u8 dfs_check_channel;
+} mlan_bss_info, *pmlan_bss_info;
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID     8
+
+/** Max RX Win size */
+#define MAX_RX_WINSIZE  64
+
+/** rx_reorder_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** TA */
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+    /** Start window */
+	t_u32 start_win;
+    /** Window size */
+	t_u32 win_size;
+    /** amsdu flag */
+	t_u8 amsdu;
+    /** buffer status */
+	t_u32 buffer[MAX_RX_WINSIZE];
+} rx_reorder_tbl;
+
+/** tx_ba_stream_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** RA */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+    /** amsdu flag */
+	t_u8 amsdu;
+} tx_ba_stream_tbl;
+
+/** Debug command number */
+#define DBG_CMD_NUM	10
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** 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;
+
+/** 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;
+    /** Corresponds to is_hs_configured member of mlan_adapter */
+	t_u8 is_hs_configured;
+    /** Corresponds to hs_activated member of mlan_adapter */
+	t_u8 hs_activated;
+    /** Corresponds to pps_uapsd_mode member of mlan_adapter */
+	t_u16 pps_uapsd_mode;
+    /** Corresponds to sleep_period.period member of mlan_adapter */
+	t_u16 sleep_pd;
+    /** Corresponds to wmm_qosinfo member of mlan_private */
+	t_u8 qos_cfg;
+    /** Corresponds to tx_lock_flag member of mlan_adapter */
+	t_u8 tx_lock_flag;
+    /** Corresponds to port_open member of mlan_private */
+	t_u8 port_open;
+    /** bypass pkt count */
+	t_u16 bypass_pkt_count;
+    /** Corresponds to scan_processing member of mlan_adapter */
+	t_u32 scan_processing;
+    /** Corresponds to mlan_processing member of mlan_adapter */
+	t_u32 mlan_processing;
+    /** Corresponds to main_lock_flag member of mlan_adapter */
+	t_u32 main_lock_flag;
+    /** Corresponds to main_process_cnt member of mlan_adapter */
+	t_u32 main_process_cnt;
+	/** Corresponds to delay_task_flag member of mlan_adapter */
+	t_u32 delay_task_flag;
+    /** mlan_rx_processing */
+	t_u32 mlan_rx_processing;
+    /** rx pkts queued */
+	t_u32 rx_pkts_queued;
+    /** Number of host to card command failures */
+	t_u32 num_cmd_host_to_card_failure;
+    /** Number of host to card sleep confirm failures */
+	t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+    /** Number of host to card Tx failures */
+	t_u32 num_tx_host_to_card_failure;
+    /** Number of allocate buffer failure */
+	t_u32 num_alloc_buffer_failure;
+	/** Number of pkt dropped */
+	t_u32 num_pkt_dropped;
+    /** 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 * 2];
+	/** Invalid port update count */
+	t_u32 mp_invalid_update;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** Number of packets tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT];
+    /** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+    /** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+	/** last recv wr_bitmap */
+	t_u32 last_recv_wr_bitmap;
+    /** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+    /** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+	/** last len for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+    /** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+    /** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT];
+    /** 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;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** Number of packets rx aggr */
+	t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_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 Tx timeouts */
+	t_u32 num_tx_timeout;
+    /** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+    /** Number of command timeouts */
+	t_u32 dbg_num_cmd_timeout;
+    /** Timeout command ID */
+	t_u16 timeout_cmd_id;
+    /** Timeout command action */
+	t_u16 timeout_cmd_act;
+    /** List of last command IDs */
+	t_u16 last_cmd_id[DBG_CMD_NUM];
+    /** List of last command actions */
+	t_u16 last_cmd_act[DBG_CMD_NUM];
+    /** Last command index */
+	t_u16 last_cmd_index;
+    /** List of last command response IDs */
+	t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+    /** Last command response index */
+	t_u16 last_cmd_resp_index;
+    /** List of last events */
+	t_u16 last_event[DBG_CMD_NUM];
+    /** Last event index */
+	t_u16 last_event_index;
+    /** Number of no free command node */
+	t_u16 num_no_cmd_node;
+    /** pending command id */
+	t_u16 pending_cmd;
+    /** time stamp for dnld last cmd */
+	t_u32 dnld_cmd_in_secs;
+    /** Corresponds to data_sent member of mlan_adapter */
+	t_u8 data_sent;
+    /** Corresponds to cmd_sent member of mlan_adapter */
+	t_u8 cmd_sent;
+    /** SDIO multiple port read bitmap */
+	t_u32 mp_rd_bitmap;
+    /** SDIO multiple port write bitmap */
+	t_u32 mp_wr_bitmap;
+    /** Current available port for read */
+	t_u8 curr_rd_port;
+    /** Current available port for write */
+	t_u8 curr_wr_port;
+    /** 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
+    /** mlan_adapter pointer */
+	t_void *mlan_adapter;
+    /** mlan_adapter_size */
+	t_u32 mlan_adapter_size;
+    /** mlan_priv vector */
+	t_void *mlan_priv[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_size */
+	t_u32 mlan_priv_size[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_num */
+	t_u8 mlan_priv_num;
+} mlan_debug_info, *pmlan_debug_info;
+
+#ifdef UAP_SUPPORT
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS         MAX_STA_COUNT
+
+/** station info */
+typedef struct _sta_info {
+    /** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+    /** station bandmode */
+	t_u8 bandmode;
+} sta_info;
+
+/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */
+typedef struct _mlan_ds_sta_list {
+    /** station count */
+	t_u16 sta_count;
+    /** station list */
+	sta_info info[MAX_NUM_CLIENTS];
+} mlan_ds_sta_list, *pmlan_ds_sta_list;
+#endif
+
+/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */
+typedef struct _mlan_ds_get_info {
+    /** Sub-command */
+	t_u32 sub_command;
+
+    /** Status information parameter */
+	union {
+	/** Signal information for MLAN_OID_GET_SIGNAL */
+		mlan_ds_get_signal signal;
+		/** Signal path id for MLAN_OID_GET_SIGNAL_EXT */
+		t_u16 path_id;
+	/** Signal information for MLAN_OID_GET_SIGNAL_EXT */
+		mlan_ds_get_signal signal_ext[MAX_PATH_NUM];
+	/** Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_get_stats stats;
+	/** Statistics information for MLAN_OID_LINK_STATS*/
+		t_u8 link_statistic[1];
+	/** Firmware information for MLAN_OID_GET_FW_INFO */
+		mlan_fw_info fw_info;
+	/** Extended version information for MLAN_OID_GET_VER_EXT */
+		mlan_ver_ext ver_ext;
+	/** BSS information for MLAN_OID_GET_BSS_INFO */
+		mlan_bss_info bss_info;
+	/** Debug information for MLAN_OID_GET_DEBUG_INFO */
+		t_u8 debug_info[1];
+#ifdef UAP_SUPPORT
+	/** UAP Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_uap_stats ustats;
+	/** UAP station list for MLAN_OID_UAP_STA_LIST */
+		mlan_ds_sta_list sta_list;
+#endif
+	} param;
+} mlan_ds_get_info, *pmlan_ds_get_info;
+
+/*-----------------------------------------------------------------*/
+/** Security Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for authentication mode */
+enum _mlan_auth_mode {
+	MLAN_AUTH_MODE_OPEN = 0x00,
+	MLAN_AUTH_MODE_SHARED = 0x01,
+	MLAN_AUTH_MODE_FT = 0x02,
+	MLAN_AUTH_MODE_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_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,
+};
+
+/** Enumeration for PSK */
+enum _mlan_psk_type {
+	MLAN_PSK_PASSPHRASE = 1,
+	MLAN_PSK_PMK,
+	MLAN_PSK_CLEAR,
+	MLAN_PSK_QUERY,
+};
+
+/** 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
+/** 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
+/** 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 defnition of mlan_pmk_t */
+typedef struct _mlan_pmk_t {
+    /** PMK */
+	t_u8 pmk[MLAN_MAX_KEY_LENGTH];
+	t_u8 pmk_r0[MLAN_MAX_KEY_LENGTH];
+	t_u8 pmk_r0_name[MLAN_MAX_PMKR0_NAME_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;
+	/** 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;
+
+/* Security SSID MAX number support by firmware*/
+#define MAX_SEC_SSID_NUM 6
+
+/** Type definition of mlan_ds_sec_cfg for MLAN_IOCTL_SEC_CFG */
+typedef struct _mlan_ds_sec_cfg {
+    /** Sub-command */
+	t_u32 sub_command;
+    /** Flag to extend some structures to support multiple values.
+     ** For example, mlan_ds_passphrase can only contain one value,
+     ** if need use mlan_ds_passphrase[N], just set this flag and
+     ** use mlan_ds_passphrase[] instead to avoid modify
+     ** more already exist code.
+     */
+	t_u8 multi_passphrase;
+    /** 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;
+		mlan_ds_passphrase roam_passphrase[MAX_SEC_SSID_NUM];
+	} param;
+} mlan_ds_sec_cfg, *pmlan_ds_sec_cfg;
+
+/*-----------------------------------------------------------------*/
+/** 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_AUTO = 0xFF,
+};
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE   18
+
+/** 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;
+} 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;
+	} param;
+} mlan_ds_power_cfg, *pmlan_ds_power_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 adhoc awake period */
+#define MIN_ADHOC_AWAKE_PD      0
+/** Maximum adhoc awake period */
+#define MAX_ADHOC_AWAKE_PD      31
+/** Special adhoc awake period */
+#define SPECIAL_ADHOC_AWAKE_PD  255
+
+/** 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;
+    /** Adhoc awake period */
+	t_u32 adhoc_awake_period;
+    /** 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_fw_wakeup_params for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+typedef struct _mlan_fw_wakeup_params {
+    /** FW wakeup method */
+	t_u16 method;
+    /** GPIO pin NO.*/
+	t_u8 gpio_pin;
+} mlan_fw_wakeup_params, *pmlan_fw_wakeup_params;
+
+/** 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;
+	/** FW wakeup method for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+		mlan_fw_wakeup_params fw_wakeup_params;
+	/** 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;
+
+/** tx sounding cfg args */
+typedef struct _mlan_tx_sounding_cfg_args {
+    /** enable/disable tx sounding */
+	t_u8 tx_sounding_enbl;
+    /** Sounding Type */
+	t_u8 sounding_type;
+    /** Sounding interval in milliseconds */
+	t_u16 sounding_interval;
+} mlan_tx_sounding_cfg_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];
+		mlan_tx_sounding_cfg_args tx_sounding_cfg;
+	} 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;
+	} 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;
+
+/** 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;
+
+typedef struct _mlan_ds_11k_cfg {
+    /** Sub-command */
+	t_u32 sub_command;
+	union {
+		t_u32 enable_11k;
+	} param;
+} mlan_ds_11k_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,
+};
+
+/** 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 */
+/*-----------------------------------------------------------------*/
+#if defined(DFS_TESTING_SUPPORT)
+/** 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;
+} 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;
+#endif
+
+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;
+
+/** 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;
+#if defined(DFS_TESTING_SUPPORT)
+	/** 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;
+#endif
+		mlan_ds_11h_chan_rep_req chan_rpt_req;
+		t_s8 cs_count;
+	} param;
+} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Miscellaneous Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** CMD buffer size */
+#define MLAN_SIZE_OF_CMD_BUFFER 2048
+
+/** 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;
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** 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[MLAN_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;
+
+/** 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;
+
+/** Enumeration for function init/shutdown */
+enum _mlan_func_cmd {
+	MLAN_FUNC_INIT = 1,
+	MLAN_FUNC_SHUTDOWN,
+};
+
+/** Enumeration for Coalescing status */
+enum _mlan_coal_status {
+	MLAN_MISC_COALESCING_ENABLE = 1,
+	MLAN_MISC_COALESCING_DISABLE = 0
+};
+
+/* Net monitor filters: */
+/* management frame */
+#define MLAN_NETMON_MANAGEMENT    MBIT(0)
+/* control frame */
+#define MLAN_NETMON_CONTROL       MBIT(1)
+/* data frame */
+#define MLAN_NETMON_DATA          MBIT(2)
+/* only unicast frame (no promiscuous) */
+#define MLAN_NETMON_NOPROM        MBIT(3)
+/* decrypted frame */
+#define MLAN_NETMON_DECRYPTED     MBIT(4)
+
+typedef struct _mlan_ds_misc_net_monitor {
+    /** Enable/disable network monitor */
+	t_u32 enable_net_mon;
+    /** Set net monitor filer flag */
+	t_u32 filter_flag;
+   /** Radio type */
+	t_u32 band;
+    /** Channel */
+	t_u32 channel;
+    /** Secondary channel bandwidth */
+	t_u32 chan_bandwidth;
+} mlan_ds_misc_net_monitor;
+
+/** 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;
+
+/** 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;
+
+/* 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_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;
+
+/** Type definition of mlan_ds_host_clock  */
+typedef struct _mlan_ds_host_clock {
+    /** host time in secs */
+	t_u64 time;
+	/** fw time */
+	t_u64 fw_time;
+    /** host-bbu clock delta */
+	t_u64 host_bbu_clk_delta;
+} mlan_ds_host_clock;
+
+/** 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;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** flag for NOA */
+#define WIFI_DIRECT_NOA         1
+/** flag for OPP_PS */
+#define WIFI_DIRECT_OPP_PS      2
+/** Type definition of mlan_ds_wifi_direct_config
+ *  for MLAN_OID_MISC_WIFI_DIRECT_CONFIG
+ */
+typedef struct _mlan_ds_wifi_direct_config {
+    /** flags for NOA/OPP_PS */
+	t_u8 flags;
+     /** NoA enable/disable */
+	t_u8 noa_enable;
+    /** index */
+	t_u16 index;
+    /** NoA count */
+	t_u8 noa_count;
+    /** NoA duration */
+	t_u32 noa_duration;
+    /** NoA interval */
+	t_u32 noa_interval;
+    /** opp ps enable/disable */
+	t_u8 opp_ps_enable;
+    /** CT window value */
+	t_u8 ct_window;
+} mlan_ds_wifi_direct_config;
+#endif
+
+#if defined(STA_SUPPORT)
+/** mlan_ds_misc_pmfcfg structure */
+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
+
+/** mlan_ds_multi_chan_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_multi_chan_cfg {
+    /** Channel Time */
+	t_u32 channel_time;
+    /** Buffer Weight */
+	t_u8 buffer_weight;
+    /** tlv len */
+	t_u16 tlv_len;
+    /** TLV buffer */
+	t_u8 tlv_buf[0];
+} MLAN_PACK_END mlan_ds_multi_chan_cfg;
+
+/** mlan_ds_drcs_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_drcs_cfg {
+    /** Channel Index*/
+	t_u16 chan_idx;
+    /** Channel time (in TU) for chan_idx */
+	t_u8 chantime;
+    /** Channel swith time (in TU) for chan_idx */
+	t_u8 switchtime;
+    /** Undoze time (in TU) for chan_idx */
+	t_u8 undozetime;
+    /** Rx traffic control scheme when channel switch*/
+    /** only valid for GC/STA interface*/
+	t_u8 mode;
+} MLAN_PACK_END mlan_ds_drcs_cfg;
+
+#define MAX_SSID_NUM 16
+#define MAX_AP_LIST 8
+#define RETRY_UNLIMITED_TIME 0xFF
+
+#define FW_ROAM_ENABLE                        MBIT(0)
+#define FW_ROAM_TRIGGER_COND                  MBIT(1)
+#define FW_ROAM_BSSID                         MBIT(2)
+#define FW_ROAM_SSID                          MBIT(3)
+#define FW_ROAM_RETRY_COUNT                   MBIT(4)
+#define FW_ROAM_RSSI_PARA                     MBIT(5)
+#define FW_ROAM_BAND_RSSI                     MBIT(6)
+#define FW_ROAM_BGSCAN_PARAM                  MBIT(7)
+#define FW_ROAM_EES_PARAM                     MBIT(8)
+#define FW_ROAM_BCN_MISS_THRESHOLD            MBIT(9)
+#define FW_ROAM_PRE_BCN_MISS_THRESHOLD        MBIT(10)
+#define FW_ROAM_BLACKLIST                     MBIT(11)
+#define FW_ROAM_REPEAT_CNT                    MBIT(12)
+
+/*Roam offload configuration for auto reconnection when suspend and resume*/
+typedef enum _roam_offload_config_mode {
+	ROAM_OFFLOAD_ENABLE = 1,
+	ROAM_OFFLOAD_SUSPEND_CFG,
+	ROAM_OFFLOAD_RESUME_CFG,
+	ROAM_OFFLOAD_PARAM_CFG,
+} roam_offload_config_mode;
+
+typedef enum _roam_offload_set_mode {
+	ROAM_OFFLOAD_DISABLE = 0,
+	ROAM_OFFLOAD_WITH_APLIST,
+	ROAM_OFFLOAD_WITHOUT_APLIST,
+	ROAM_OFFLOAD_WITH_BSSID,
+	ROAM_OFFLOAD_WITH_SSID,
+	AUTO_RECONNECT,
+} roam_offload_set_mode;
+
+typedef enum _roam_offload_trigger_mode {
+	NO_TRIGGER = 0x00,
+	RSSI_LOW_TRIGGER = 0x01,
+	PRE_BEACON_LOST_TRIGGER = 0x02,
+	LINK_LOST_TRIGGER = 0x04,
+	DEAUTH_WITH_EXT_AP_TRIGGER = 0x08,
+} roam_offload_trigger_mode;
+
+/** mlan_ds_misc_ees_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_ees_cfg {
+	/* EES mode */
+	t_u16 ees_mode;
+	/* EES report condition */
+	t_u16 ees_rpt_condition;
+	/* High scan period(milliseconds) */
+	t_u16 high_scan_period;
+	/* High scan count */
+	t_u16 high_scan_count;
+	/* Middle scan period(milliseconds) */
+	t_u16 mid_scan_period;
+	/* Middle scan count */
+	t_u16 mid_scan_count;
+	/* Low scan period(milliseconds) */
+	t_u16 low_scan_period;
+	/* Low scan count */
+	t_u16 low_scan_count;
+} MLAN_PACK_END mlan_ds_misc_ees_cfg;
+
+/** mlan_ds_misc_bgscan_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_bgscan_cfg {
+	/* BSS Type  0x1-bss independent, 0x2-bss infrastructure, 0x3-bss any */
+	t_u8 bss_type;
+	/* Number of channels scanned for each scan */
+	t_u8 channels_per_scan;
+	/* Interval between consective scans */
+	t_u32 scan_interval;
+	/* Conditons to trigger report to host */
+	t_u32 bg_rpt_condition;
+} MLAN_PACK_END mlan_ds_misc_bgscan_cfg;
+
+/** mlan_ds_misc_band_rssi structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_band_rssi {
+	/* RSSI hysteresis */
+	t_u8 rssi_hysteresis;
+	/*  Preferred channel band for fw roaming
+	 *  0:2.4G band; 1: 5G band; 2:4G band; 0xFF:band not set(invalid)
+	 */
+	t_u8 band_preferred;
+} MLAN_PACK_END mlan_ds_misc_band_rssi;
+
+/** mlan_ds_misc_ssid_list structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_ssid_list {
+	/* SSID number */
+	t_u8 ssid_num;
+	/* SSID for fw roaming/auto_reconnect */
+	mlan_802_11_ssid ssids[MAX_SSID_NUM];
+} MLAN_PACK_END mlan_ds_misc_ssid_list;
+
+/** mlan_ds_misc_roam_offload_aplist structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_roam_offload_aplist {
+    /** Number of AP**/
+	t_u8 ap_num;
+    /** AP mac addrs**/
+	t_u8 ap_mac[MAX_AP_LIST][MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END mlan_ds_misc_roam_offload_aplist;
+
+/** _mlan_ds_misc_roam_offload_para_rssi structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_roam_offload_para_rssi {
+    /** Setting flag**/
+	t_u8 set_flag;
+    /** Max value of RSSI threshold**/
+	t_u8 max_rssi;
+    /** Min value of RSSI threshold**/
+	t_u8 min_rssi;
+    /** Adjusting step value of RSSI threshold**/
+	t_u8 step_rssi;
+} MLAN_PACK_END mlan_ds_misc_roam_offload_para_rssi;
+
+/** mlan_ds_misc_roam_offload structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_roam_offload {
+    /** Enable roam offload**/
+	t_u8 enable;
+    /** User set passphrase**/
+	t_u8 userset_passphrase;
+	/* Condition to trigger roaming
+	 * Bit0 : RSSI low trigger
+	 * Bit1 : Pre-beacon lost trigger
+	 * Bit2 : Link Lost trigger
+	 * Bit3 : Deauth by ext-AP trigger
+	 * Bit4 ~ Bit15 : Reserved
+	 * value 0 : no trigger
+	 * value 0xff : invalid
+	 */
+	t_u16 trigger_condition;
+    /** AP list**/
+	mlan_ds_misc_roam_offload_aplist aplist;
+	/*Roam offload configuration mode for auto connection when suspend and resume */
+	roam_offload_config_mode config_mode;
+    /** Retry count**/
+	t_u8 retry_count;
+    /** RSSI para**/
+	mlan_ds_misc_roam_offload_para_rssi para_rssi;
+    /** BSSID of reconnection**/
+	mlan_802_11_mac_addr bssid_reconnect;
+	/* SSID List(White list) */
+	mlan_ds_misc_ssid_list ssid_list;
+	/* Black list(BSSID list) */
+	mlan_ds_misc_roam_offload_aplist black_list;
+	/* BAND and RSSI_HYSTERESIS set flag */
+	t_u8 band_rssi_flag;
+	mlan_ds_misc_band_rssi band_rssi;
+
+	/* BGSCAN params set flag */
+	t_u8 bgscan_set_flag;
+	mlan_ds_misc_bgscan_cfg bgscan_cfg;
+
+	/* EES mode params set flag */
+	t_u8 ees_param_set_flag;
+	mlan_ds_misc_ees_cfg ees_cfg;
+
+	/* Beacon miss threshold */
+	t_u8 bcn_miss_threshold;
+
+	/* Beacon miss threshold */
+	t_u8 pre_bcn_miss_threshold;
+
+	/* Scan repeat count */
+	t_u16 repeat_count;
+} MLAN_PACK_END mlan_ds_misc_roam_offload;
+
+/**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
+
+/** mlan_ds_misc_dfs_repeater structure */
+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
+
+/** Temperature Sensor structure */
+typedef struct _mlan_ds_sensor_temp {
+    /** Temperature */
+	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;
+
+/** mlan_ds_cw_mode_ctrl structure */
+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[0];
+} 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;
+
+/** RTT configuration */
+typedef struct _mlan_rtt_config {
+    /** peer device mac address */
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+    /** 1-sided or 2-sided RTT */
+	t_u8 type;
+    /** optional - peer device hint (STA, P2P, AP) */
+	t_u8 peer;
+    /** Required for STA-AP mode, optional for P2P, NBD etc. */
+	t_u8 channel;
+    /** Required for STA-AP mode, optional for P2P, NBD etc. */
+	Band_Config_t bandcfg;
+    /** Time interval between bursts (units: 100 ms).
+      * Applies to 1-sided and 2-sided RTT multi-burst requests.
+      * Range: 0-31, 0: no preference by initiator (2-sided RTT) */
+	t_u8 burst_period;
+    /** Total number of RTT bursts to be executed. It will be
+      * specified in the same way as the parameter "Number of
+      * Burst Exponent" found in the FTM frame format. It
+      * applies to both: 1-sided RTT and 2-sided RTT. Valid
+      * values are 0 to 15 as defined in 802.11mc std.
+      * 0 means single shot
+      * The implication of this parameter on the maximum
+      * number of RTT results is the following:
+      * for 1-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst)
+      * for 2-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst - 1) */
+	t_u8 num_burst;
+    /** num of frames per burst.
+      * Minimum value = 1, Maximum value = 31
+      * For 2-sided this equals the number of FTM frames
+      * to be attempted in a single burst. This also
+      * equals the number of FTM frames that the
+      * initiator will request that the responder send
+      * in a single frame. */
+	t_u8 num_frames_per_burst;
+    /** number of retries for a failed RTT frame. Applies
+      * to 1-sided RTT only. Minimum value = 0, Maximum value = 3 */
+	t_u8 num_retries_per_rtt_frame;
+
+    /** following fields are only valid for 2-side RTT */
+    /** Maximum number of retries that the initiator can
+      * retry an FTMR frame.
+      * Minimum value = 0, Maximum value = 3 */
+	t_u8 num_retries_per_ftmr;
+    /** 1: request LCI, 0: do not request LCI */
+	t_u8 LCI_request;
+    /** 1: request LCR, 0: do not request LCR */
+	t_u8 LCR_request;
+    /** Applies to 1-sided and 2-sided RTT. Valid values will
+      * be 2-11 and 15 as specified by the 802.11mc std for
+      * the FTM parameter burst duration. In a multi-burst
+      * request, if responder overrides with larger value,
+      * the initiator will return failure. In a single-burst
+      * request if responder overrides with larger value,
+      * the initiator will sent TMR_STOP to terminate RTT
+      * at the end of the burst_duration it requested. */
+	t_u8 burst_duration;
+    /** RTT preamble to be used in the RTT frames */
+	t_u8 preamble;
+    /** RTT BW to be used in the RTT frames */
+	t_u8 bw;
+} mlan_rtt_config, *pmlan_rtt_config;
+
+/** RTT config params */
+typedef struct _mlan_rtt_config_params {
+	t_u8 rtt_config_num;
+	mlan_rtt_config rtt_config[MAX_RTT_CONFIG_NUM];
+} mlan_rtt_config_params;
+
+/** RTT cancel params */
+typedef struct _mlan_rtt_cancel_params {
+	t_u8 rtt_cancel_num;
+	t_u8 rtt_cancel[MAX_RTT_CONFIG_NUM][MLAN_MAC_ADDR_LENGTH];
+} mlan_rtt_cancel_params;
+
+/** RTT responder info */
+typedef struct _rtt_responder_info {
+	t_u8 channel;
+	Band_Config_t bandcfg;
+	t_u8 preamble;
+} rtt_responder_info;
+
+/** RTT responder enable configure */
+typedef struct _rtt_responder_encfg {
+	t_u8 channel;
+	Band_Config_t bandcfg;
+	t_u32 max_dur_sec;
+} rtt_responder_encfg;
+
+/** Define for mlan_rtt_responder.action */
+#define RTT_GET_RESPONDER_INFO       0
+#define RTT_SET_RESPONDER_ENABLE   1
+#define RTT_SET_RESPONDER_DISABLE  2
+#define RTT_SET_RESPONDER_LCI           3
+#define RTT_SET_RESPONDER_LCR          4
+
+/** RTT responder configure for MLAN_OID_MISC_RTT_RESPONDER_CFG */
+typedef struct _mlan_rtt_responder {
+	t_u8 action;
+	union {
+		rtt_responder_info info;
+		rtt_responder_encfg encfg;
+		wifi_lci_information lci;
+		wifi_lcr_information lcr;
+	} u;
+} mlan_rtt_responder;
+
+/** channel statictics */
+typedef struct _ChStat_t {
+    /** channle number */
+	t_u8 chan_num;
+    /** total network */
+	t_u16 total_networks;
+    /** busy duration */
+	t_u16 cca_busy_duration;
+} ChStat_t, *pChStat_t;
+
+#define MAX_CH_STATS    MAX_BG_CHANNEL
+/** Type definition of mlan_acs_scan */
+typedef struct _mlan_ds_misc_acs {
+    /** Best Channel Number */
+	t_u8 best_ch;
+    /** Scan channel gap */
+	t_u16 scan_chan_gap;
+    /** Channel Statistics Number */
+	t_u8 ch_stats_num;
+    /** Channel Statistics */
+	ChStat_t ch_stats[MAX_CH_STATS];
+} mlan_ds_misc_acs, *pmlan_ds_misc_acs;
+
+/** 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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;
+	/** Coalescing status for MLAN_OID_MISC_COALESCING_STATUS */
+		t_u16 coalescing_status;
+	/** 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;
+	/** Net monitor for MLAN_OID_MISC_NET_MONITOR */
+		mlan_ds_misc_net_monitor net_mon;
+	/** Tx data pause for MLAN_OID_MISC_TX_DATAPAUSE */
+		mlan_ds_misc_tx_datapause tx_datapause;
+	/** IP address configuration */
+		mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
+	/** MAC control for MLAN_OID_MISC_MAC_CONTROL */
+		t_u32 mac_ctrl;
+	/** MEF configuration for MLAN_OID_MISC_MEF_CFG */
+		mlan_ds_misc_mef_cfg mef_cfg;
+	/** CFP code for MLAN_OID_MISC_CFP_CODE */
+		mlan_ds_misc_cfp_code cfp_code;
+	/** Country code for MLAN_OID_MISC_COUNTRY_CODE */
+		mlan_ds_misc_country_code country_code;
+	/** Thermal reading for MLAN_OID_MISC_THERMAL */
+		t_u32 thermal;
+	/** Mgmt subtype mask for MLAN_OID_MISC_RX_MGMT_IND */
+		t_u32 mgmt_subtype_mask;
+	/** subscribe event for MLAN_OID_MISC_SUBSCRIBE_EVENT */
+		mlan_ds_subscribe_evt subscribe_event;
+#ifdef DEBUG_LEVEL1
+	/** Driver debug bit masks */
+		t_u32 drvdbg;
+#endif
+#ifdef STA_SUPPORT
+		ExtCap_t ext_cap;
+#endif
+		mlan_ds_misc_otp_user_data otp_user_data;
+	/** Tx control */
+		t_u32 tx_control;
+#if defined(STA_SUPPORT)
+		mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+	/** Multi-channel config for MLAN_OID_MISC_MULTI_CHAN_CFG */
+		mlan_ds_multi_chan_cfg multi_chan_cfg;
+	/** Multi-channel policy for MLAN_OID_MISC_MULTI_CHAN_POLICY */
+		t_u16 multi_chan_policy;
+	/** channel drcs time slicing config for MLAN_OID_MISC_DRCS_CFG */
+		mlan_ds_drcs_cfg drcs_cfg[2];
+#ifdef WIFI_DIRECT_SUPPORT
+		mlan_ds_wifi_direct_config p2p_config;
+#endif
+		mlan_ds_coalesce_cfg coalesce_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;
+	/** Sensor temperature */
+		mlan_ds_sensor_temp sensor_temp;
+	/** GTK rekey data */
+		mlan_ds_misc_gtk_rekey_data gtk_rekey;
+	/** Bandwidth Channel operation */
+		mlan_ds_bw_chan_oper bw_chan_oper;
+    /** Independent Reset Configuration */
+		mlan_ds_ind_rst_cfg ind_rst_cfg;
+    /** Roam offload */
+		mlan_ds_misc_roam_offload roam_offload;
+    /** misc tsf */
+		t_u64 misc_tsf;
+    /** Custom regulatory domain */
+		mlan_ds_custom_reg_domain custom_reg_domain;
+    /** cwmmode */
+		mlan_ds_cw_mode_ctrl cwmode;
+   /**  Tx/Rx per-packet control */
+		t_u8 txrx_pkt_ctrl;
+		mlan_ds_misc_robustcoex_params robustcoexparams;
+    /** config RTT for MLAN_OID_MISC_CONFIG_RTT */
+		mlan_rtt_config_params rtt_params;
+    /** cancel RTT for MLAN_OID_MISC_CANCEL_RTT */
+		mlan_rtt_cancel_params rtt_cancel;
+    /** config RTT responder for MLAN_OID_MISC_RTT_RESPONDER_CFG */
+		mlan_rtt_responder rtt_rsp_cfg;
+		mlan_ds_host_clock host_clock;
+    /** boot sleep enable or disable */
+		t_u16 boot_sleep;
+    /** ACS */
+		mlan_ds_misc_acs acs;
+	} param;
+} mlan_ds_misc_cfg, *pmlan_ds_misc_cfg;
+
+/** 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_sd8997/mlan/mlan_join.c b/wlan_sd8997/mlan/mlan_join.c
new file mode 100644
index 0000000..9d8eb1b
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_join.c
@@ -0,0 +1,2549 @@
+/** @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.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ *  @sa mlan_join.h
+ */
+
+/******************************************************
+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_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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, priv->gen_ie_buf,
+		       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(MrvlIEtypesHeader_t));
+		memcpy(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, ie,
+		       ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_t));
+
+		/* Increment the return size and the return buffer pointer param */
+		*ppbuffer += ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_t);
+		ret_len += ie->ieee_hdr.len + sizeof(MrvlIEtypesHeader_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(pmriv->adapter, *ppbuffer, &tsf_tlv, 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(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val));
+	*ppbuffer += sizeof(tsf_val);
+
+	memcpy(pmriv->adapter, &tsf_val, pbss_desc->time_stamp,
+	       sizeof(tsf_val));
+
+	PRINTM(MINFO, "ASSOC: TSF offset calc: %016llx - %016llx\n",
+	       tsf_val, pbss_desc->network_tsf);
+
+	memcpy(pmriv->adapter, *ppbuffer, &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(IN mlan_private *pmpriv,
+		      IN t_u8 *rate1,
+		      IN t_u32 rate1_size, IN t_u8 *rate2, IN 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(pmpriv->adapter, tmp, rate1, 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(IN mlan_private *pmpriv,
+			      IN BSSDescriptor_t *pbss_desc,
+			      OUT t_u8 *pout_rates, OUT t_u32 *pout_rates_size)
+{
+	t_u8 card_rates[WLAN_SUPPORTED_RATES];
+	t_u32 card_rates_size = 0;
+	ENTER();
+	/* Copy AP supported rates */
+	memcpy(pmpriv->adapter, pout_rates, pbss_desc->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(IN mlan_private *pmpriv,
+			   IN 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(pmpriv->adapter, &new_tsf_base, 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(priv->adapter, *ppbuffer, &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(priv->adapter, *ppbuffer, priv->wapi_ie,
+		       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;
+}
+
+/********************************************************
+				Global Functions
+********************************************************/
+/**
+ *  @brief This function updates RSN IE in the association request.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @param ptlv_rsn_ie       A pointer to rsn_ie TLV
+ */
+int
+wlan_update_rsn_ie(mlan_private *pmpriv, MrvlIEtypes_RsnParamSet_t *ptlv_rsn_ie)
+{
+	t_u16 *prsn_cap;
+	t_u16 *ptr;
+	t_u16 *akm_suite_count_ptr;
+	t_u16 pmf_mask = 0x00;
+	t_u8 *temp;
+	t_u16 pairwise_cipher_count = 0;
+	t_u16 akm_suite_count = 0;
+	t_u16 temp_akm_suite_count = 0;
+	int found = 0;
+	t_u8 sha_256_oui[4] = { 0x00, 0x0f, 0xac, 0x06 };
+	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 (!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(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)),
+			       sha_256_oui, 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 PMF is required by AP, just leave the same value with AP */
+	if (!(*prsn_cap & (0x1 << MFPR_BIT)))
+		*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 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(IN mlan_private *pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_ASSOCIATE *passo = &cmd->params.associate;
+	BSSDescriptor_t *pbss_desc;
+	MrvlIEtypes_SsIdParamSet_t *pssid_tlv;
+	MrvlIEtypes_PhyParamSet_t *pphy_tlv;
+	MrvlIEtypes_SsParamSet_t *pss_tlv;
+	MrvlIEtypes_RatesParamSet_t *prates_tlv;
+	MrvlIEtypes_AuthType_t *pauth_tlv;
+	MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv = MNULL;
+	MrvlIEtypes_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;
+
+	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;
+
+	memcpy(pmadapter, passo->peer_sta_addr,
+	       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(pmadapter, pssid_tlv->ssid, pbss_desc->ssid.ssid,
+	       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(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));
+	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(pmadapter, &pmpriv->curr_bss_params.data_rates, rates,
+	       rates_size);
+
+	/* 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(pmadapter, prates_tlv->rates, rates, 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
+			pauth_tlv->auth_type =
+				wlan_cpu_to_le16(MLAN_AUTH_MODE_OPEN);
+		pos += sizeof(pauth_tlv->header) + pauth_tlv->header.len;
+		pauth_tlv->header.len = wlan_cpu_to_le16(pauth_tlv->header.len);
+	}
+
+	if (IS_SUPPORT_MULTI_BANDS(pmadapter)
+	    && (pbss_desc->bss_band & pmpriv->config_bands)
+	    && !(ISSUPP_11NENABLED(pmadapter->fw_cap_info)
+		 && (!pbss_desc->disable_11n)
+		 && (pmpriv->config_bands & BAND_GN
+		     || pmpriv->config_bands & BAND_AN)
+		 && (pbss_desc->pht_cap)
+	    )
+		) {
+		/* Append a channel TLV for the channel the attempted AP was found on */
+		pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
+		pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		pchan_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
+
+		memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
+		       sizeof(ChanScanParamSet_t));
+		pchan_tlv->chan_scan_param[0].chan_number =
+			(pbss_desc->phy_param_set.ds_param_set.current_chan);
+		PRINTM(MINFO, "Assoc: TLV Chan = %d\n",
+		       pchan_tlv->chan_scan_param[0].chan_number);
+
+		pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
+			wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
+
+		PRINTM(MINFO, "Assoc: TLV Bandcfg = %x\n",
+		       pchan_tlv->chan_scan_param[0].bandcfg);
+		pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+	}
+	if (!pmpriv->wps.session_enable) {
+		if ((pmpriv->sec_info.wpa_enabled
+		     || pmpriv->sec_info.wpa2_enabled)) {
+			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+			/* WPA_IE or RSN_IE */
+			prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
+			prsn_ie_tlv->header.type =
+				prsn_ie_tlv->header.type & 0x00FF;
+			prsn_ie_tlv->header.type =
+				wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+			prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
+			prsn_ie_tlv->header.len =
+				prsn_ie_tlv->header.len & 0x00FF;
+			if (prsn_ie_tlv->header.len <=
+			    (sizeof(pmpriv->wpa_ie) - 2))
+				memcpy(pmadapter, prsn_ie_tlv->rsn_ie,
+				       &pmpriv->wpa_ie[2],
+				       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);
+		}
+#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(pmadapter, prsn_ie_tlv->rsn_ie,
+					       &((*(pbss_desc->pwpa_ie)).
+						 vend_hdr.oui[0]),
+					       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(pmadapter, prsn_ie_tlv->rsn_ie,
+					       &((*(pbss_desc->prsn_ie)).
+						 data[0])
+					       , 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);
+	if (pmpriv->adapter->ecsa_enable) {
+		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);
+
+	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);
+
+	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 (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(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+	       sizeof(passo->cap_info));
+
+	if (pmpriv->config_bands == BAND_B)
+		SHORT_SLOT_TIME_DISABLED(tmp_cap);
+
+	/* set SpectrumMgmt(BIT8) and RadioMeasurement(BIT12) if 11K is enabled */
+	if (pmpriv->enable_11k) {
+		SPECTRUM_MGMT_ENABLED(tmp_cap);
+		RADIO_MEASUREMENT_ENABLED(tmp_cap);
+	}
+
+	RADIO_MEASUREMENT_ENABLED(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(pmadapter, &passo->cap_info, &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(IN mlan_private *pmpriv,
+			  IN HostCmd_DS_COMMAND *resp, IN 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;
+	ENTER();
+
+	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(pmpriv->adapter, cur_mac,
+		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		       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(pmpriv->adapter, pmpriv->assoc_rsp_buf, &resp->params,
+	       pmpriv->assoc_rsp_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++;
+		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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+		       &passoc_rsp->status_code, 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(pmpriv->adapter, &pmpriv->ext_cap, &pmpriv->def_ext_cap,
+	       sizeof(pmpriv->ext_cap));
+	/* Make a copy of current BSSID descriptor */
+	memcpy(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+	       pbss_desc, 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->amsdu_rx_cnt = 0;
+	pmpriv->amsdu_tx_cnt = 0;
+	pmpriv->msdu_in_rx_amsdu_cnt = 0;
+	pmpriv->msdu_in_tx_amsdu_cnt = 0;
+	pmpriv->rxpd_rate = 0;
+	pmpriv->rxpd_rate_info = 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++;
+
+	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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+	       (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+	       MLAN_MAC_ADDR_LENGTH);
+
+	/* 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
+#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
+#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(pmpriv->adapter, (t_u8 *)assoc_succ->bssid,
+	       pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH);
+	memcpy(pmpriv->adapter, (t_u8 *)assoc_succ->oui, pbss_desc->mac_address,
+	       MLAN_MAC_ADDR_LENGTH / 2);
+	memcpy(pmpriv->adapter, (t_u8 *)assoc_succ->ssid, pbss_desc->ssid.ssid,
+	       pbss_desc->ssid.ssid_len);
+	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(IN mlan_private *pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd, IN 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;
+	MrvlIETypes_HTCap_t *pht_cap;
+	MrvlIETypes_HTInfo_t *pht_info;
+	t_u32 rx_mcs_supp = 0;
+	MrvlIETypes_VHTCap_t *pvht_cap = MNULL;
+	MrvlIETypes_VHTOprat_t *pvht_op = MNULL;
+	t_u16 mcs_map_user = 0;
+	/* 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(pmadapter, padhoc_start->ssid,
+	       ((mlan_802_11_ssid *)pdata_buf)->ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len));
+
+	PRINTM(MINFO, "ADHOC_S_CMD: SSID = %s\n", padhoc_start->ssid);
+
+	memset(pmadapter, pbss_desc->ssid.ssid, 0, MLAN_MAX_SSID_LENGTH);
+	memcpy(pmadapter, pbss_desc->ssid.ssid,
+	       ((mlan_802_11_ssid *)pdata_buf)->ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len));
+
+	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(pmadapter, &pbss_desc->phy_param_set,
+	       &padhoc_start->phy_param_set, 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(pmadapter, &pbss_desc->ss_param_set,
+	       &padhoc_start->ss_param_set, 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->adhoc_aes_enabled
+	    || 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(pmadapter, &pmpriv->curr_bss_params.data_rates,
+	       &padhoc_start->DataRate, pmpriv->curr_bss_params.num_of_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);
+		if (pmadapter->adhoc_start_band & BAND_GN
+		    || pmadapter->adhoc_start_band & BAND_AN
+		    || pmadapter->adhoc_start_band & BAND_GAC
+		    || pmadapter->adhoc_start_band & BAND_AAC) {
+			if (pmadapter->chan_bandwidth == CHANNEL_BW_40MHZ_ABOVE) {
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chan2Offset = SEC_CHAN_ABOVE;
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chanWidth = CHAN_BW_40MHZ;
+			} else if (pmadapter->chan_bandwidth ==
+				   CHANNEL_BW_40MHZ_BELOW) {
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chan2Offset = SEC_CHAN_BELOW;
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chanWidth = CHAN_BW_40MHZ;
+			} else if (pmadapter->chan_bandwidth ==
+				   CHANNEL_BW_80MHZ) {
+				pchan_tlv->chan_scan_param[0].bandcfg.
+					chanWidth = CHAN_BW_80MHZ;
+			}
+		}
+		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(pmadapter, pmpriv->wpa_ie, wpa_ie, sizeof(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(pmadapter, prsn_ie_tlv->rsn_ie,
+			       &pmpriv->wpa_ie[2], 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);
+	}
+
+	if (pmadapter->adhoc_11n_enabled == MTRUE) {
+		{
+			pht_cap = (MrvlIETypes_HTCap_t *)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);
+			rx_mcs_supp =
+				GET_RXMCSSUPP(pmpriv->usr_dev_mcs_support);
+			/* Set MCS for 1x1/2x2 */
+			memset(pmadapter,
+			       (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
+			       rx_mcs_supp);
+			wlan_fill_ht_cap_tlv(pmpriv, pht_cap,
+					     pmpriv->curr_bss_params.band,
+					     MTRUE);
+			HEXDUMP("ADHOC_START: HT_CAPABILITIES IE",
+				(t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
+			pos += sizeof(MrvlIETypes_HTCap_t);
+			cmd_append_size += sizeof(MrvlIETypes_HTCap_t);
+			pht_cap->header.len =
+				wlan_cpu_to_le16(pht_cap->header.len);
+		}
+		{
+			pht_info = (MrvlIETypes_HTInfo_t *)pos;
+			memset(pmadapter, pht_info, 0,
+			       sizeof(MrvlIETypes_HTInfo_t));
+			pht_info->header.type = wlan_cpu_to_le16(HT_OPERATION);
+			pht_info->header.len = sizeof(HTInfo_t);
+			pht_info->ht_info.pri_chan =
+				(t_u8)pmpriv->curr_bss_params.bss_descriptor.
+				channel;
+			if ((pmadapter->chan_bandwidth ==
+			     CHANNEL_BW_40MHZ_ABOVE) ||
+			    (pmadapter->chan_bandwidth ==
+			     CHANNEL_BW_40MHZ_BELOW)) {
+				pht_info->ht_info.field2 =
+					pmadapter->chan_bandwidth;
+				SET_CHANWIDTH40(pht_info->ht_info.field2);
+			}
+			if (pmadapter->chan_bandwidth == CHANNEL_BW_80MHZ) {
+				pht_info->ht_info.field2 =
+					wlan_get_second_channel_offset
+					(pht_info->ht_info.pri_chan);
+				pht_info->ht_info.field2 |= MBIT(2);
+			}
+			pht_info->ht_info.field3 =
+				wlan_cpu_to_le16(NON_GREENFIELD_STAS);
+			pht_info->ht_info.basic_mcs_set[0] = 0xff;
+			HEXDUMP("ADHOC_START: HT_INFORMATION IE",
+				(t_u8 *)pht_info, sizeof(MrvlIETypes_HTInfo_t));
+			pos += sizeof(MrvlIETypes_HTInfo_t);
+			cmd_append_size += sizeof(MrvlIETypes_HTInfo_t);
+			pht_info->header.len =
+				wlan_cpu_to_le16(pht_info->header.len);
+		}
+		if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info)
+		    && (pmadapter->adhoc_start_band & BAND_GAC
+			|| pmadapter->adhoc_start_band & BAND_AAC)) {
+			/* VHT Capabilities IE */
+			pvht_cap = (MrvlIETypes_VHTCap_t *)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);
+			/* rx MCS Map */
+			mcs_map_user =
+				GET_DEVRXMCSMAP(pmpriv->
+						usr_dot_11ac_mcs_support);
+			pvht_cap->vht_cap.mcs_sets.rx_mcs_map =
+				wlan_cpu_to_le16(mcs_map_user);
+			/* rx highest rate */
+			pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+				wlan_convert_mcsmap_to_maxrate(pmpriv,
+							       pmadapter->
+							       adhoc_start_band,
+							       mcs_map_user);
+			pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+				wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.
+						 rx_max_rate);
+			/* tx MCS map */
+			mcs_map_user =
+				GET_DEVTXMCSMAP(pmpriv->
+						usr_dot_11ac_mcs_support);
+			pvht_cap->vht_cap.mcs_sets.tx_mcs_map =
+				wlan_cpu_to_le16(mcs_map_user);
+			/* tx highest rate */
+			pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+				wlan_convert_mcsmap_to_maxrate(pmpriv,
+							       pmadapter->
+							       adhoc_start_band,
+							       mcs_map_user);
+			pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+				wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.
+						 tx_max_rate);
+
+			wlan_fill_vht_cap_tlv(pmpriv, pvht_cap,
+					      pmadapter->adhoc_start_band,
+					      MTRUE);
+			HEXDUMP("VHT_CAPABILITIES IE", (t_u8 *)pvht_cap,
+				sizeof(MrvlIETypes_VHTCap_t));
+			pos += sizeof(MrvlIETypes_VHTCap_t);
+			cmd_append_size += sizeof(MrvlIETypes_VHTCap_t);
+			pvht_cap->header.len =
+				wlan_cpu_to_le16(pvht_cap->header.len);
+			/* VHT Operation IE */
+			pvht_op = (MrvlIETypes_VHTOprat_t *)pos;
+			memset(pmadapter, pvht_op, 0,
+			       sizeof(MrvlIETypes_VHTOprat_t));
+			pvht_op->header.type = wlan_cpu_to_le16(VHT_OPERATION);
+			pvht_op->header.len = sizeof(MrvlIETypes_VHTOprat_t) -
+				sizeof(MrvlIEtypesHeader_t);
+			if (pmadapter->chan_bandwidth == CHANNEL_BW_80MHZ) {
+				pvht_op->chan_width = VHT_OPER_CHWD_80MHZ;
+				/* central frequency */
+				pvht_op->chan_center_freq_1 =
+					wlan_get_center_freq_idx(pmpriv,
+								 pmadapter->
+								 adhoc_start_band,
+								 pmpriv->
+								 adhoc_channel,
+								 pmadapter->
+								 chan_bandwidth);
+			}
+			/* basic MCS (rx MCS Map) */
+			pvht_op->basic_MCS_map =
+				GET_DEVRXMCSMAP(pmpriv->
+						usr_dot_11ac_mcs_support);
+			pvht_op->basic_MCS_map =
+				wlan_cpu_to_le16(pvht_op->basic_MCS_map);
+
+			HEXDUMP("VHT_OPERATION IE", (t_u8 *)pvht_op,
+				sizeof(MrvlIETypes_VHTOprat_t));
+			pos += sizeof(MrvlIETypes_VHTOprat_t);
+			cmd_append_size += sizeof(MrvlIETypes_VHTOprat_t);
+			pvht_op->header.len =
+				wlan_cpu_to_le16(pvht_op->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(pmadapter, &tmp_cap, &padhoc_start->cap, sizeof(t_u16));
+
+	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(pmadapter, &padhoc_start->cap, &tmp_cap, sizeof(t_u16));
+
+	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(IN mlan_private *pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd, IN 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(pmadapter, &padhoc_join->bss_descriptor.bssid,
+	       &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH);
+
+	memcpy(pmadapter, &padhoc_join->bss_descriptor.ssid,
+	       &pbss_desc->ssid.ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH, pbss_desc->ssid.ssid_len));
+
+	memcpy(pmadapter, &padhoc_join->bss_descriptor.phy_param_set,
+	       &pbss_desc->phy_param_set, 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(pmadapter, &padhoc_join->bss_descriptor.ss_param_set,
+	       &pbss_desc->ss_param_set, sizeof(IEEEtypes_SsParamSet_t));
+	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(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+	       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(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
+	       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(pmadapter, padhoc_join->bss_descriptor.data_rates,
+	       pbss_desc->supported_rates, rates_size);
+
+	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(pmadapter, &pmpriv->curr_bss_params.data_rates,
+	       pbss_desc->supported_rates, rates_size);
+
+	/* 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->adhoc_aes_enabled
+	    || 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(pmadapter, prsn_ie_tlv->rsn_ie,
+			       &pmpriv->wpa_ie[2], 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(pmadapter, prsn_ie_tlv->rsn_ie,
+				       &((*(pbss_desc->pwpa_ie)).vend_hdr.
+					 oui[0]), 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(pmadapter, prsn_ie_tlv->rsn_ie,
+				       &((*(pbss_desc->prsn_ie)).data[0])
+				       , 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 (ISSUPP_11NENABLED(pmadapter->fw_cap_info)
+	    && wlan_11n_bandconfig_allowed(pmpriv, pbss_desc->bss_band)
+		)
+		cmd_append_size +=
+			wlan_cmd_append_11n_tlv(pmpriv, pbss_desc, &pos);
+	if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info)
+	    && wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
+		cmd_append_size +=
+			wlan_cmd_append_11ac_tlv(pmpriv, pbss_desc, &pos);
+
+	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(pmadapter, &tmp_cap, &padhoc_join->bss_descriptor.cap,
+	       sizeof(IEEEtypes_CapInfo_t));
+	tmp_cap = wlan_cpu_to_le16(tmp_cap);
+
+	memcpy(pmadapter, &padhoc_join->bss_descriptor.cap,
+	       &tmp_cap, 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(IN mlan_private *pmpriv,
+		       IN HostCmd_DS_COMMAND *resp, IN 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(pmpriv->adapter, pbss_desc->mac_address,
+		       padhoc_start_result->bssid, 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(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+		       pbss_desc, sizeof(BSSDescriptor_t));
+
+		pmpriv->adhoc_state = ADHOC_JOINED;
+	}
+
+    /** process wmm ie */
+	if (ie_len >= sizeof(IEEEtypes_VendorHeader_t)) {
+		if ((pwmm_param_ie->vend_hdr.element_id == VENDOR_SPECIFIC_221)
+		    && !memcmp(pmadapter, pwmm_param_ie->vend_hdr.oui, wmm_oui,
+			       sizeof(wmm_oui)) &&
+		    (pwmm_param_ie->vend_hdr.len + 2 == ie_len)) {
+			DBG_HEXDUMP(MCMD_D, "WMM Param", (t_u8 *)pwmm_param_ie,
+				    ie_len);
+			memcpy(pmpriv->adapter,
+			       (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.
+			       wmm_ie, pwmm_param_ie,
+			       MIN(sizeof(IEEEtypes_WmmParameter_t),
+				   (pwmm_param_ie->vend_hdr.len + 2)));
+			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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+	       (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+	       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(IN mlan_private *pmpriv,
+	       IN t_void *pioctl_buf, IN 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(pmpriv->adapter, &current_bssid,
+	       &pmpriv->curr_bss_params.bss_descriptor.mac_address,
+	       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(IN mlan_private *pmpriv,
+		 IN t_void *pioctl_buf, IN 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(pmpriv->adapter, &pmpriv->adhoc_last_start_ssid,
+		       padhoc_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(IN mlan_private *pmpriv,
+		IN t_void *pioctl_buf, IN 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(IN mlan_private *pmpriv,
+		IN mlan_ioctl_req *pioctl_req,
+		IN 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(pmpriv->adapter, &local_param, deauth_param,
+		       sizeof(*deauth_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(pmpriv->adapter, local_param.mac_addr,
+				       (t_u8 *)&pmpriv->curr_bss_params.
+				       bss_descriptor.mac_address,
+				       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(IN 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_sd8997/mlan/mlan_join.h b/wlan_sd8997/mlan/mlan_join.h
new file mode 100644
index 0000000..a202f9f
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_join.h
@@ -0,0 +1,47 @@
+/** @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
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ *  @sa mlan_join.c
+ */
+
+/******************************************************
+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_sd8997/mlan/mlan_main.h b/wlan_sd8997/mlan/mlan_main.h
new file mode 100644
index 0000000..8ab03a7
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_main.h
@@ -0,0 +1,3735 @@
+/** @file mlan_main.h
+ *
+ *  @brief This file defines the private and adapter data
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/13/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_MAIN_H_
+#define _MLAN_MAIN_H_
+
+#ifdef DEBUG_LEVEL1
+extern t_void (*print_callback) (IN t_void *pmoal_handle,
+				 IN t_u32 level, IN char *pformat, IN ...
+	);
+
+extern mlan_status (*get_sys_time_callback) (IN t_void *pmoal_handle,
+					     OUT t_u32 *psec, OUT t_u32 *pusec);
+
+extern t_u32 mlan_drvdbg;
+
+/* Reason Code 3: STA is leaving (or has left) IBSS or ESS */
+#define DEF_DEAUTH_REASON_CODE (0x3)
+
+#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 */
+
+/** 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))
+
+#ifdef memcmp
+#undef memcmp
+#endif
+/** Memcmp routine */
+#define memcmp(adapter, s1, s2, len) \
+	(adapter->callbacks.moal_memcmp(adapter->pmoal_handle, s1, s2, len))
+
+/** Find number of elements */
+#ifndef NELEMENTS
+#define NELEMENTS(x)    (sizeof(x)/sizeof(x[0]))
+#endif
+
+/** SWAP: swap t_u8 */
+#define SWAP_U8(a, b)	{t_u8 t; t = a; a = b; b = t; }
+
+/** SWAP: swap t_u8 */
+#define SWAP_U16(a, b)	{t_u16 t; t = a; a = b; b = t; }
+
+/** MLAN MNULL pointer */
+#define MNULL                           (0)
+
+/** 16 bits byte swap */
+#define swap_byte_16(x) \
+((t_u16)((((t_u16)(x) & 0x00ffU) << 8) | \
+		 (((t_u16)(x) & 0xff00U) >> 8)))
+
+/** 32 bits byte swap */
+#define swap_byte_32(x) \
+((t_u32)((((t_u32)(x) & 0x000000ffUL) << 24) | \
+	 (((t_u32)(x) & 0x0000ff00UL) <<  8) | \
+	 (((t_u32)(x) & 0x00ff0000UL) >>  8) | \
+	 (((t_u32)(x) & 0xff000000UL) >> 24)))
+
+/** 64 bits byte swap */
+#define swap_byte_64(x) \
+((t_u64)((t_u64)(((t_u64)(x) & 0x00000000000000ffULL) << 56) | \
+	     (t_u64)(((t_u64)(x) & 0x000000000000ff00ULL) << 40) | \
+	     (t_u64)(((t_u64)(x) & 0x0000000000ff0000ULL) << 24) | \
+	     (t_u64)(((t_u64)(x) & 0x00000000ff000000ULL) <<  8) | \
+	     (t_u64)(((t_u64)(x) & 0x000000ff00000000ULL) >>  8) | \
+	     (t_u64)(((t_u64)(x) & 0x0000ff0000000000ULL) >> 24) | \
+	     (t_u64)(((t_u64)(x) & 0x00ff000000000000ULL) >> 40) | \
+	     (t_u64)(((t_u64)(x) & 0xff00000000000000ULL) >> 56)))
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert ulong n/w to host */
+#define mlan_ntohl(x) x
+/** Convert host ulong to n/w */
+#define mlan_htonl(x) x
+/** Convert n/w to host */
+#define mlan_ntohs(x)  x
+/** Convert host to n/w */
+#define mlan_htons(x)  x
+/** Convert from 16 bit little endian format to CPU format */
+#define wlan_le16_to_cpu(x) swap_byte_16(x)
+/** Convert from 32 bit little endian format to CPU format */
+#define wlan_le32_to_cpu(x) swap_byte_32(x)
+/** Convert from 64 bit little endian format to CPU format */
+#define wlan_le64_to_cpu(x) swap_byte_64(x)
+/** Convert to 16 bit little endian format from CPU format */
+#define wlan_cpu_to_le16(x) swap_byte_16(x)
+/** Convert to 32 bit little endian format from CPU format */
+#define wlan_cpu_to_le32(x) swap_byte_32(x)
+/** Convert to 64 bit little endian format from CPU format */
+#define wlan_cpu_to_le64(x) swap_byte_64(x)
+
+/** Convert TxPD to little endian format from CPU format */
+#define endian_convert_TxPD(x)                                          \
+	{                                                                   \
+	    (x)->tx_pkt_length = wlan_cpu_to_le16((x)->tx_pkt_length);      \
+	    (x)->tx_pkt_offset = wlan_cpu_to_le16((x)->tx_pkt_offset);      \
+	    (x)->tx_pkt_type   = wlan_cpu_to_le16((x)->tx_pkt_type);        \
+	    (x)->tx_control    = wlan_cpu_to_le32((x)->tx_control);         \
+        (x)->tx_control_1  = wlan_cpu_to_le32((x)->tx_control_1);         \
+	}
+/** Convert RxPD from little endian format to CPU format */
+#define endian_convert_RxPD(x)                                          \
+	{                                                                   \
+	    (x)->rx_pkt_length = wlan_le16_to_cpu((x)->rx_pkt_length);      \
+	    (x)->rx_pkt_offset = wlan_le16_to_cpu((x)->rx_pkt_offset);      \
+	    (x)->rx_pkt_type   = wlan_le16_to_cpu((x)->rx_pkt_type);        \
+	    (x)->seq_num       = wlan_le16_to_cpu((x)->seq_num);            \
+        (x)->rx_info       = wlan_le32_to_cpu((x)->rx_info);            \
+	    (x)->hi_rx_count32 = wlan_le32_to_cpu((x)->hi_rx_count32);      \
+	    (x)->lo_rx_count16 = wlan_le16_to_cpu((x)->lo_rx_count16);      \
+	}
+/** Convert RxPD extra header from little endian format to CPU format */
+#define endian_convert_RxPD_extra_header(x)                                          \
+	{                                                                   \
+	    (x)->channel_flags = wlan_le16_to_cpu((x)->channel_flags);      \
+	    (x)->vht_sig1 = wlan_le32_to_cpu((x)->vht_sig1);		\
+	    (x)->vht_sig2 = wlan_le32_to_cpu((x)->vht_sig2);		\
+	}
+#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)
+/** Convert RxPD extra header from little endian format to CPU format */
+#define endian_convert_RxPD_extra_header(x)  do {} while (0)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** Global moal_assert_callback */
+extern t_void (*assert_callback) (IN t_void *pmoal_handle, IN 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)
+
+/** Upload size */
+#define WLAN_UPLD_SIZE                  (2312)
+
+/** Maximum event buffer size */
+#define MAX_EVENT_SIZE                  2048
+
+#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
+/** 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          8
+
+/** 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         100
+/** low rx pending packets */
+#define LOW_RX_PENDING          80
+
+/** Default region code */
+#define MRVDRV_DEFAULT_REGION_CODE      0x10
+
+/** Default country code */
+#define MRVDRV_DEFAULT_COUNTRY_CODE      "US"
+
+/** Japan country code */
+#define COUNTRY_CODE_JP_40	        0x40
+/** Japan special country code */
+#define COUNTRY_CODE_JP_FF	        0xFF
+
+/** Default factor for calculating beacon average */
+#define DEFAULT_BCN_AVG_FACTOR          8
+/** Default factor for calculating data average */
+#define DEFAULT_DATA_AVG_FACTOR         8
+
+/** The first valid channel for use */
+#define FIRST_VALID_CHANNEL          0xff
+/** Default Ad-Hoc channel */
+#define DEFAULT_AD_HOC_CHANNEL       6
+/** Default Ad-Hoc channel A */
+#define DEFAULT_AD_HOC_CHANNEL_A     36
+
+/** Number of WEP keys */
+#define MRVL_NUM_WEP_KEY                (4)
+
+/** Default multiple DTIM */
+#define MRVDRV_DEFAULT_MULTIPLE_DTIM        1
+
+/** Default beacon missing timeout */
+#define DEFAULT_BCN_MISS_TIMEOUT            10
+
+/** Maximum buffer space for beacons retrieved from scan responses */
+#define MAX_SCAN_BEACON_BUFFER          49152
+/** Default buffer space for beacons retrieved from scan responses */
+#define DEFAULT_SCAN_BEACON_BUFFER      4096
+
+/**
+ * @brief Buffer pad space for newly allocated beacons/probe responses
+ *
+ * Beacons are typically 6 bytes longer than an equivalent probe response.
+ *  For each scan response stored, allocate an extra byte pad at the end to
+ *  allow easy expansion to store a beacon in the same memory a probe response
+ *  previously contained
+ */
+#define SCAN_BEACON_ENTRY_PAD          6
+
+/** Scan time specified in the channel TLV
+ *  for each channel for passive scans
+ */
+#define MRVDRV_PASSIVE_SCAN_CHAN_TIME       200
+
+/** Scan time specified in the channel TLV
+ *  for each channel for active scans
+ */
+#define MRVDRV_ACTIVE_SCAN_CHAN_TIME        200
+
+/** Scan time specified in the channel TLV
+ *  for each channel for specific scans
+ */
+#define MRVDRV_SPECIFIC_SCAN_CHAN_TIME      110
+
+/**
+ * Max total scan time in milliseconds
+ * The total scan time should be less than scan command timeout value (20s)
+ */
+#define MRVDRV_MAX_TOTAL_SCAN_TIME     (MRVDRV_TIMER_10S * 2 - MRVDRV_TIMER_1S)
+
+/** Offset for GTK as it has version to skip past for GTK */
+#define RSN_GTK_OUI_OFFSET 2
+
+/** If OUI is not found */
+#define MLAN_OUI_NOT_PRESENT 0
+/** If OUI is found */
+#define MLAN_OUI_PRESENT 1
+
+/** Is cmd_resp, event or data packet received? */
+#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \
+	adapter->event_received || \
+	adapter->data_received)
+/** Type command */
+#define MLAN_TYPE_CMD			1
+/** Type data */
+#define MLAN_TYPE_DATA			0
+/** Type event */
+#define MLAN_TYPE_EVENT			3
+
+/** 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 */
+#define MAX_MP_REGS			196
+/** Maximum port */
+#define MAX_PORT			32
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** Multi port TX aggregation buffer size */
+#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE        (65280)	/* 64K - 256 */
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+/** Multi port RX aggregation buffer size */
+#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE        (65280)	/* 64K - 256 */
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+/** High threshold at which to start drop packets */
+#define  RX_HIGH_THRESHOLD           1024
+/** Low threshold to allow Rx BA */
+#define  RX_LOW_THRESHOLD            128
+
+/** 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 Tx timeouts */
+	t_u32 num_tx_timeout;
+    /** 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;
+} 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;
+
+/** 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;
+} 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];
+} 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
+
+/** CFP dynamic (non-const) elements */
+typedef struct _cfp_dyn_t {
+	/** extra flags to specify channel usability
+	 *  bit 7 : if set, channel is disabled
+	 *  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_u8 flags;
+    /** TRUE: Channel is blacklisted (do not use) */
+	t_bool blacklist;
+} cfp_dyn_t;
+
+/** Chan-Freq-TxPower mapping table*/
+typedef struct _chan_freq_power_t {
+    /** Channel Number */
+	t_u16 channel;
+    /** Frequency of this Channel */
+	t_u32 freq;
+    /** Max allowed Tx power level */
+	t_u16 max_tx_power;
+    /** TRUE:radar detect required for BAND A or passive scan for BAND B/G;
+      * FALSE:radar detect not required for BAND A or active scan for BAND B/G*/
+	t_bool passive_scan_or_radar_detect;
+    /** Elements associated to cfp that change at run-time */
+	cfp_dyn_t dynamic;
+} chan_freq_power_t;
+
+/** 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) (IN t_void *priv, IN t_u8 first_bss);
+    /** ioctl handler */
+	mlan_status (*ioctl) (t_void *adapter, pmlan_ioctl_req pioctl_req);
+    /** cmd handler */
+	mlan_status (*prepare_cmd) (IN t_void *priv,
+				    IN t_u16 cmd_no,
+				    IN t_u16 cmd_action,
+				    IN t_u32 cmd_oid,
+				    IN t_void *pioctl_buf,
+				    IN t_void *pdata_buf, IN t_void *pcmd_buf);
+    /** cmdresp handler */
+	mlan_status (*process_cmdresp) (IN t_void *priv,
+					IN t_u16 cmdresp_no,
+					IN t_void *pcmd_buf, IN t_void *pioctl);
+    /** rx handler */
+	mlan_status (*process_rx_packet) (IN t_void *adapter,
+					  IN pmlan_buffer pmbuf);
+    /** event handler */
+	mlan_status (*process_event) (IN t_void *priv);
+    /** txpd handler */
+	t_void *(*process_txpd) (IN t_void *priv, IN pmlan_buffer pmbuf);
+    /** BSS role */
+	mlan_bss_role bss_role;
+} mlan_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;
+    /** rxpd_htinfo */
+	t_u8 rxpd_rate_info;
+    /** max amsdu size */
+	t_u16 max_amsdu;
+    /** 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 */
+#ifdef UAP_SUPPORT
+    /** UAP 11ac flag */
+	t_u8 is_11ac_enabled;
+#endif				/* UAP_SUPPORT */
+    /** 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;
+    /**  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;
+    /** Rate bitmap */
+	t_u16 rate_bitmap;
+    /** 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;
+    /** 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_u8 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;
+	/** 11k flag */
+	t_u8 enable_11k;
+#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;
+	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;
+    /** 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;
+    /** Advanced Encryption Standard */
+	t_u8 adhoc_aes_enabled;
+    /** 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;
+    /** Current Beacon buffer */
+	t_u8 *pcurr_bcn_buf;
+    /** Current Beacon size */
+	t_u32 curr_bcn_size;
+    /** Current Beacon buffer lock */
+	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];
+#ifdef STA_SUPPORT
+    /** Extended capabilities */
+	ExtCap_t ext_cap;
+    /** Default extended capabilities */
+	ExtCap_t def_ext_cap;
+#endif
+    /** interface header len */
+	t_u8 intf_hr_len;
+    /** 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];
+    /** 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;
+
+/** 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;
+    /** PN number high 32 bits*/
+	t_u32 hi_curr_rx_count32;
+    /** PN number low 16 bits*/
+	t_u16 lo_curr_rx_count16;
+};
+
+/** 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 OID for sub-command use */
+	t_u32 cmd_oid;
+    /** 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;
+    /** pre_allocated mlan_buffer for cmd */
+	mlan_buffer *pmbuf;
+};
+
+/** 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;
+
+/** 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;
+    /** tdls status */
+	tdlsStatus_e status;
+    /** SNR */
+	t_s8 snr;
+    /** Noise Floor */
+	t_s8 nf;
+    /** flag for host based tdls */
+	t_u8 external_tdls;
+    /** peer capability */
+	t_u16 capability;
+    /** 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_u8 bandmode;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+    /** cm connection info */
+	t_void *cm_connectioninfo;
+#endif
+};
+
+/** 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;
+
+#ifdef DFS_TESTING_SUPPORT
+/** 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;
+} wlan_dfs_testing_settings_t;
+#endif /* DFS_SUPPORT_TESTING */
+
+/**
+ * @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;
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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++;
+}
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** 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];
+	/** multiport rx aggregation mbuf array */
+	pmlan_buffer mbuf_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT];
+} sdio_mpa_tx;
+#endif
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+/** 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];
+	/** multiport rx aggregation pkt len array */
+	t_u32 len_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT];
+
+	/** 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 /* SDIO_MULTI_PORT_RX_AGGR */
+
+/** mlan_init_para structure */
+typedef struct _mlan_init_para {
+#ifdef MFG_CMD_SUPPORT
+    /** MFG mode */
+	t_u32 mfg_mode;
+#endif
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** 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;
+	t_u32 drcs_chantime_mode;
+	t_bool fw_region;
+} mlan_init_para, *pmlan_init_para;
+
+/** 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;
+    /** more_rx_task_flag */
+	t_u32 more_rx_task_flag;
+    /** rx_proc_lock for main_rx_process */
+	t_void *prx_proc_lock;
+    /** 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 */
+	t_u8 flush_data;
+    /** IO port */
+	t_u32 ioport;
+
+    /** STATUS variables */
+	WLAN_HARDWARE_STATUS hw_status;
+    /** PnP SUPPORT */
+	t_u8 surprise_removed;
+
+    /** ECSA support */
+	t_u8 ecsa_enable;
+
+    /** Get log support */
+	t_u8 getlog_enable;
+
+    /** Radio on flag */
+	t_u16 radio_on;
+
+    /** Firmware release number */
+	t_u32 fw_release_number;
+    /** firmware version */
+	t_u8 fw_ver;
+    /** firmware minor version */
+	t_u8 fw_min_ver;
+    /** uap firmware version */
+	t_u8 uap_fw_ver;
+    /** mac address retrun from get_hw_spec */
+	t_u8 permanent_addr[MLAN_MAC_ADDR_LENGTH];
+    /** Number of antenna used */
+	t_u16 number_of_antenna;
+    /** antenna info */
+	t_u8 antinfo;
+    /** Firmware capability information */
+	t_u32 fw_cap_info;
+    /** pint_lock for interrupt handling */
+	t_void *pint_lock;
+    /** Interrupt status */
+	t_u8 sdio_ireg;
+    /** 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 * 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/* see blk_queue_max_segment_size */
+	t_u32 max_seg_size;
+	/* see blk_queue_max_segments */
+	t_u16 max_segs;
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	/** 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];
+    /** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+    /** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+    /** last wr_bitmap from FW */
+	t_u32 last_recv_wr_bitmap;
+    /** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+    /** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+    /** last length for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+    /** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT];
+    /** 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;
+#endif				/* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	/** 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];
+#endif				/* SDIO_MULTI_PORT_RX_AGGR */
+
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+
+    /** Event cause */
+	t_u32 event_cause;
+    /** Event buffer */
+	pmlan_buffer pmlan_buffer_event;
+    /** Upload length */
+	t_u32 upld_len;
+    /** Upload buffer*/
+	t_u8 upld_buf[WLAN_UPLD_SIZE];
+    /** Data sent:
+     *       TRUE - Data is sent to fw, no Tx Done received
+     *       FALSE - Tx done received for previous Tx
+     */
+	t_u8 data_sent;
+    /** CMD sent:
+     *       TRUE - CMD is sent to fw, no CMD Done received
+     *       FALSE - CMD done received for previous CMD
+     */
+	t_u8 cmd_sent;
+    /** CMD Response received:
+     *       TRUE - CMD is response is received from fw, and yet to process
+     *       FALSE - No cmd response to process
+     */
+	t_u8 cmd_resp_received;
+    /** Event received:
+     *       TRUE - Event received from fw, and yet to process
+     *       FALSE - No events to process
+     */
+	t_u8 event_received;
+
+    /** Data received:
+     *       TRUE - Data received from fw
+     *       FALSE - No Data received
+     */
+	t_u8 data_received;
+
+    /** Command-related variables */
+    /** Command sequence number */
+	t_u16 seq_num;
+    /** Command controller nodes */
+	cmd_ctrl_node *cmd_pool;
+    /** Current Command */
+	cmd_ctrl_node *curr_cmd;
+    /** mlan_lock for command */
+	t_void *pmlan_cmd_lock;
+    /** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+    /** Last init fw command id */
+	t_u16 last_init_cmd;
+    /** Command timer */
+	t_void *pmlan_cmd_timer;
+    /** Command timer set flag */
+	t_u8 cmd_timer_is_set;
+    /** time stamp for command dnld */
+	t_u32 dnld_cmd_in_secs;
+
+    /** Command Queues */
+    /** Free command buffers */
+	mlan_list_head cmd_free_q;
+    /** Pending command buffers */
+	mlan_list_head cmd_pending_q;
+    /** Command queue for scanning */
+	mlan_list_head scan_pending_q;
+    /** ioctl pending queue */
+	mlan_list_head ioctl_pending_q;
+    /** pending_ioctl flag */
+	t_u8 pending_ioctl;
+    /** mlan_processing */
+	t_u32 scan_processing;
+    /** firmware support for roaming*/
+	t_u8 fw_roaming;
+    /** User set passphrase*/
+	t_u8 userset_passphrase;
+    /** 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 */
+	wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+#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;
+#ifdef DFS_TESTING_SUPPORT
+    /** User configured settings for DFS testing */
+	wlan_dfs_testing_settings_t dfs_test_params;
+#endif
+    /** 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;
+    /** Scan block flag */
+	t_u8 scan_block;
+    /** Extended scan or legacy scan */
+	t_u8 ext_scan;
+	t_u16 bcn_buf_size;
+    /** Beacon buffer */
+	t_u8 *bcn_buf;
+    /** Pointer to valid beacon buffer end */
+	t_u8 *pbcn_buf_end;
+    /** allocate fixed scan beacon buffer size*/
+	t_u32 fixed_beacon_buffer;
+
+    /** F/W supported bands */
+	t_u8 fw_bands;
+    /** User selected band to start adhoc network */
+	t_u8 adhoc_start_band;
+    /** User selected bands */
+	t_u8 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;
+	/** Multi channel status */
+	t_u8 mc_status;
+
+    /** 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;
+
+    /** 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;
+
+    /** AdHoc awake period */
+	t_u16 adhoc_awake_period;
+
+    /** Firmware wakeup method */
+	t_u16 fw_wakeup_method;
+    /** Firmware wakeup GPIO pin */
+	t_u8 fw_wakeup_gpio_pin;
+    /** 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;
+
+    /** 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;
+    /** 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
+    /** Enable 11n support for adhoc start */
+	t_u8 adhoc_11n_enabled;
+    /** 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;
+
+    /** 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;
+    /** management frame wakeup filter config */
+	mlan_mgmt_frame_wakeup mgmt_filter[MAX_MGMT_FRAME_FILTER];
+
+    /** Bypass TX queue pkt count  */
+	t_u16 bypass_pkt_count;
+#if defined(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;
+    /** NetMon enabled */
+	t_u32 enable_net_mon;
+
+    /** Control coex RX window size configuration */
+	t_u8 coex_rx_winsize;
+    /** DFS repeater */
+	t_bool dfs_repeater;
+    /** DFSr channel */
+	t_u32 dfsr_channel;
+    /** multi channel policy */
+	t_bool mc_policy;
+	/** flag for sdio rx aggr */
+	t_bool sdio_rx_aggr_enable;
+	/** fw rx block size */
+	t_u16 sdio_rx_block_size;
+    /**channel param band config */
+	t_u8 chanrpt_param_bandcfg;
+	/** d1 time */
+	t_u64 d1;
+	 /** d2 time */
+	t_u64 d2;
+     /** host bbu clock delta */
+	t_u64 host_bbu_clk_delta;
+    /** maximum station 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;
+	chan_freq_power_t *cfp_otp_a;
+	t_u8 *tx_power_table_a;
+	t_u32 tx_power_table_a_size;
+} mlan_adapter, *pmlan_adapter;
+
+/** Ethernet packet type for EAPOL */
+#define MLAN_ETHER_PKT_TYPE_EAPOL	(0x888E)
+/** 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_cmd_net_monitor(IN HostCmd_DS_COMMAND *cmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_net_monitor(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_net_monitor(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+
+void wlan_rxpdinfo_to_radiotapinfo(pmlan_private priv,
+				   RxPD *prx_pd, radiotap_info * prt_info);
+
+mlan_status wlan_init_lock_list(IN pmlan_adapter pmadapter);
+mlan_status wlan_init_priv_lock_list(IN pmlan_adapter pmadapter,
+				     t_u8 start_index);
+t_void wlan_free_lock_list(IN pmlan_adapter pmadapter);
+mlan_status wlan_init_timer(IN pmlan_adapter pmadapter);
+t_void wlan_free_timer(IN pmlan_adapter pmadapter);
+
+/* Function prototype */
+/** Download firmware */
+mlan_status wlan_dnld_fw(IN pmlan_adapter pmadapter, IN pmlan_fw_image pmfw);
+
+/** Initialize firmware */
+mlan_status wlan_init_fw(IN pmlan_adapter pmadapter);
+
+/** get hw spec complete */
+mlan_status wlan_get_hw_spec_complete(IN pmlan_adapter pmadapter);
+
+/** Initialize firmware complete */
+mlan_status wlan_init_fw_complete(IN pmlan_adapter pmadapter);
+
+/** Shutdown firmware complete */
+mlan_status wlan_shutdown_fw_complete(IN 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(IN pmlan_adapter pmadapter);
+
+/** Initialize mlan_private structure */
+mlan_status wlan_init_priv(IN pmlan_private priv);
+
+/** Process event */
+mlan_status wlan_process_event(pmlan_adapter pmadapter);
+
+/** Prepare command */
+mlan_status wlan_prepare_cmd(IN pmlan_private priv,
+			     IN t_u16 cmd_no,
+			     IN t_u16 cmd_action,
+			     IN t_u32 cmd_oid,
+			     IN t_void *pioctl_buf, IN t_void *pdata_buf);
+
+/** cmd timeout handler */
+t_void wlan_cmd_timeout_func(t_void *function_context);
+/** process host cmd */
+mlan_status wlan_misc_ioctl_host_cmd(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req);
+/** process init/shutdown cmd*/
+mlan_status wlan_misc_ioctl_init_shutdown(IN pmlan_adapter pmadapter,
+					  IN pmlan_ioctl_req pioctl_req);
+/** process debug info */
+mlan_status wlan_get_info_debug_info(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req);
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/** Set/Get BSS role */
+mlan_status wlan_bss_ioctl_bss_role(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_get_correlated_time(IN pmlan_adapter pmadapter,
+					  IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_set_ewpa_mode(mlan_private *priv, mlan_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(IN mlan_adapter *pmadapter);
+/** Free command buffer */
+mlan_status wlan_free_cmd_buffer(IN mlan_adapter *pmadapter);
+/** Request command lock */
+t_void wlan_request_cmd_lock(mlan_adapter *pmadapter);
+/** Release command lock */
+t_void wlan_release_cmd_lock(mlan_adapter *pmadapter);
+#ifdef STA_SUPPORT
+/** Flush the scan pending queue */
+t_void wlan_flush_scan_queue(pmlan_adapter pmadapter);
+mlan_status wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+					 pmlan_ioctl_req pioctl_req);
+#endif
+/**Cancel pending command */
+t_void wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter);
+/**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(IN mlan_adapter *pmadapter,
+				 IN cmd_ctrl_node *pcmd_node);
+
+/** Insert command to pending queue */
+t_void wlan_insert_cmd_to_pending_q(IN mlan_adapter *pmadapter,
+				    IN cmd_ctrl_node *pcmd_node,
+				    IN 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);
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+mlan_status wlan_alloc_sdio_mpa_buffers(IN mlan_adapter *pmadapter,
+					t_u32 mpa_tx_buf_size,
+					t_u32 mpa_rx_buf_size);
+
+mlan_status wlan_free_sdio_mpa_buffers(IN mlan_adapter *pmadapter);
+#endif
+
+/** Process write data complete */
+mlan_status wlan_write_data_complete(pmlan_adapter pmlan_adapter,
+				     pmlan_buffer pmbuf, mlan_status status);
+/** 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)
+
+/** 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,
+				    IN HostCmd_DS_COMMAND *cmd,
+				    IN t_u16 cmd_action,
+				    IN t_u16 ps_bitmap, IN t_void *pdata_buf);
+/** handle command resp for enhanced power save mode */
+mlan_status wlan_ret_enh_power_mode(IN pmlan_private pmpriv,
+				    IN HostCmd_DS_COMMAND *resp,
+				    IN mlan_ioctl_req *pioctl_buf);
+
+/** handle commnand for cfg data */
+mlan_status wlan_cmd_cfg_data(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *pcmd,
+			      IN t_u16 cmd_action,
+			      IN t_u32 cmd_oid, IN t_void *pdata_buf);
+/** handle command resp for cfg data */
+mlan_status wlan_ret_cfg_data(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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);
+
+mlan_status wlan_pm_reset_card(pmlan_adapter adapter);
+mlan_status wlan_pm_wakeup_card(pmlan_adapter pmadapter);
+
+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);
+
+#ifdef WIFI_DIRECT_SUPPORT
+mlan_status wlan_bss_ioctl_wifi_direct_mode(IN pmlan_adapter pmadapter,
+					    IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_wifi_direct_mode(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_u16 cmd_action,
+				      IN t_void *pdata_buf);
+mlan_status wlan_ret_wifi_direct_mode(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_p2p_params_config(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+mlan_status wlan_ret_p2p_params_config(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *resp,
+				       IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_p2p_config(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req);
+#endif
+/** get ralist info */
+int wlan_get_ralist_info(mlan_private *priv, ralist_info *buf);
+/** dump ralist */
+void wlan_dump_ralist(mlan_private *priv);
+
+/** get pm info */
+mlan_status wlan_get_pm_info(IN pmlan_adapter pmadapter,
+			     IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_bss_ioctl_bss_remove(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_radio_ioctl_mimo_switch_cfg(IN pmlan_adapter pmadapter,
+					     IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_802_11_mimo_switch(pmlan_private pmpriv,
+					IN HostCmd_DS_COMMAND *cmd,
+					IN t_void *pdata_buf);
+
+mlan_status wlan_misc_per_pkt_cfg(IN pmlan_adapter pmadapter,
+				  IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_config_mgmt_filter(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_get_hs_wakeup_reason(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_hs_wakeup_reason(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_void *pdata_buf);
+
+mlan_status wlan_ret_hs_wakeup_reason(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_radio_ioctl_radio_ctl(IN pmlan_adapter pmadapter,
+				       IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_radio_ioctl_remain_chan_cfg(IN pmlan_adapter pmadapter,
+					     IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_remain_on_channel(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+mlan_status wlan_ret_remain_on_channel(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *resp,
+				       IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_radio_ioctl_ant_cfg(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *cmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_cfg(IN pmlan_adapter pmadapter,
+				IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_get_data_rate(IN pmlan_adapter pmadapter,
+					  IN 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(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN mlan_ioctl_req *pioctl_buf);
+/** Sends HS_WAKEUP event to applications */
+t_void wlan_host_sleep_wakeup_event(pmlan_private priv);
+
+mlan_status wlan_cmd_802_11_fw_wakeup_method(IN pmlan_private pmpriv,
+					     IN HostCmd_DS_COMMAND *cmd,
+					     IN t_u16 cmd_action,
+					     IN t_u16 *pdata_buf);
+mlan_status wlan_ret_fw_wakeup_method(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_fw_wakeup_method(IN pmlan_adapter pmadapter,
+				  IN pmlan_ioctl_req pioctl_req);
+
+/** Prepares command of robustcoex */
+mlan_status wlan_cmd_robustcoex(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_u16 *pdata_buf);
+/** Set Robustcoex gpiocfg */
+mlan_status wlan_misc_robustcoex(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req);
+
+/** send get hw spec command to firmware */
+mlan_status wlan_adapter_get_hw_spec(IN pmlan_adapter pmadapter);
+/** send adapter specific init cmd to firmware */
+mlan_status wlan_adapter_init_cmd(IN pmlan_adapter pmadapter);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status wlan_cmd_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
+					 IN HostCmd_DS_COMMAND *cmd,
+					 IN t_u16 cmd_action,
+					 IN t_void *pdata_buf);
+mlan_status wlan_ret_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
+					 const IN HostCmd_DS_COMMAND *resp,
+					 OUT mlan_ioctl_req *pioctl_buf);
+#endif
+mlan_status wlan_handle_event_multi_chan_info(IN pmlan_private pmpriv,
+					      pmlan_buffer pevent);
+
+#ifdef STA_SUPPORT
+/** warm reset */
+mlan_status wlan_misc_ioctl_warm_reset(IN pmlan_adapter pmadapter,
+				       IN 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(IN t_void *priv,
+				     IN t_u16 cmd_no,
+				     IN t_u16 cmd_action,
+				     IN t_u32 cmd_oid,
+				     IN t_void *pioctl_buf,
+				     IN t_void *pdata_buf, IN t_void *pcmd_buf);
+
+/** cmdresp handler for station mode */
+mlan_status wlan_ops_sta_process_cmdresp(IN t_void *priv,
+					 IN t_u16 cmdresp_no,
+					 IN t_void *pcmd_buf,
+					 IN t_void *pioctl);
+
+/** rx handler for station mode */
+mlan_status wlan_ops_sta_process_rx_packet(IN t_void *adapter,
+					   IN pmlan_buffer pmbuf);
+
+/** event handler for station mode */
+mlan_status wlan_ops_sta_process_event(IN t_void *priv);
+
+/** fill txpd for station mode */
+t_void *wlan_ops_sta_process_txpd(IN t_void *priv, IN pmlan_buffer pmbuf);
+
+/** send init cmd to firmware for station mode */
+mlan_status wlan_ops_sta_init_cmd(IN t_void *priv, IN t_u8 first_bss);
+
+/** Flush the scan table */
+mlan_status wlan_flush_scan_table(IN pmlan_adapter pmadapter);
+
+/** Scan for networks */
+mlan_status wlan_scan_networks(IN mlan_private *pmpriv,
+			       IN t_void *pioctl_buf,
+			       IN wlan_user_scan_cfg *puser_scan_in);
+
+/** Scan for specific SSID */
+mlan_status wlan_scan_specific_ssid(IN mlan_private *pmpriv,
+				    IN t_void *pioctl_buf,
+				    IN mlan_802_11_ssid *preq_ssid);
+
+/** Scan command handler */
+mlan_status wlan_cmd_802_11_scan(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *pcmd,
+				 IN t_void *pdata_buf);
+
+/** Handler for scan command response */
+mlan_status wlan_ret_802_11_scan(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN t_void *pioctl_buf);
+
+/** Extended scan command handler */
+mlan_status wlan_cmd_802_11_scan_ext(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *pcmd,
+				     IN t_void *pdata_buf);
+/** Handler for extended scan command response */
+mlan_status wlan_ret_802_11_scan_ext(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *resp,
+				     IN t_void *pioctl_buf);
+/** Handler event for extended scan report */
+mlan_status wlan_handle_event_ext_scan_report(IN mlan_private *pmpriv,
+					      IN mlan_buffer *pmbuf);
+mlan_status wlan_handle_event_ext_scan_status(IN mlan_private *pmpriv,
+					      IN mlan_buffer *pmbuf);
+
+/** check network compatibility */
+t_s32 wlan_is_network_compatible(IN mlan_private *pmpriv,
+				 IN t_u32 index, IN t_u32 mode);
+
+/** Find an SSID in a list */
+t_s32 wlan_find_ssid_in_list(IN pmlan_private pmpriv,
+			     IN mlan_802_11_ssid *ssid,
+			     IN t_u8 *bssid, IN t_u32 mode);
+
+/** Find a BSSID in a list */
+t_s32 wlan_find_bssid_in_list(IN mlan_private *pmpriv,
+			      IN t_u8 *bssid, IN t_u32 mode);
+
+/** Find best network */
+mlan_status wlan_find_best_network(IN mlan_private *pmpriv,
+				   OUT mlan_ssid_bssid *preq_ssid_bssid);
+
+/** Compare two SSIDs */
+t_s32 wlan_ssid_cmp(IN pmlan_adapter pmadapter,
+		    IN mlan_802_11_ssid *ssid1, IN mlan_802_11_ssid *ssid2);
+
+/** Associate */
+mlan_status wlan_associate(IN mlan_private *pmpriv,
+			   IN t_void *pioctl_buf, IN BSSDescriptor_t *pBSSDesc);
+
+/** Associate command handler */
+mlan_status wlan_cmd_802_11_associate(IN mlan_private *pmpriv,
+				      IN HostCmd_DS_COMMAND *cmd,
+				      IN t_void *pdata_buf);
+
+/** Handler for association command response */
+mlan_status wlan_ret_802_11_associate(IN mlan_private *pmpriv,
+				      IN HostCmd_DS_COMMAND *resp,
+				      IN t_void *pioctl_buf);
+
+/** Reset connected state */
+t_void wlan_reset_connect_state(IN pmlan_private priv, IN 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(IN t_u8 band);
+/** convert radio_type to band */
+t_u8 radio_type_to_band(t_u8 chanBand);
+
+/** Disconnect */
+mlan_status wlan_disconnect(IN mlan_private *pmpriv,
+			    IN mlan_ioctl_req *pioctl_req,
+			    IN mlan_deauth_param *deauth_param);
+
+/** Ad-Hoc start */
+mlan_status wlan_adhoc_start(IN mlan_private *pmpriv,
+			     IN t_void *pioctl_buf,
+			     IN mlan_802_11_ssid *padhoc_ssid);
+
+/** Ad-Hoc join */
+mlan_status wlan_adhoc_join(IN mlan_private *pmpriv,
+			    IN t_void *pioctl_buf,
+			    IN BSSDescriptor_t *pBSSDesc);
+
+/** Ad-Hoc start command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_start(IN mlan_private *pmpriv,
+					 IN HostCmd_DS_COMMAND *cmd,
+					 IN t_void *pdata_buf);
+
+/** Ad-Hoc command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_join(IN mlan_private *pmpriv,
+					IN HostCmd_DS_COMMAND *cmd,
+					IN t_void *pdata_buf);
+
+/** Handler for Ad-Hoc commands */
+mlan_status wlan_ret_802_11_ad_hoc(IN mlan_private *pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN t_void *pioctl_buf);
+
+/** Handler for bgscan query commands */
+mlan_status wlan_cmd_802_11_bg_scan_query(IN mlan_private *pmpriv,
+					  IN HostCmd_DS_COMMAND *pcmd,
+					  IN t_void *pdata_buf);
+/** Handler for bgscan config command */
+mlan_status wlan_cmd_bgscan_config(IN mlan_private *pmpriv,
+				   IN HostCmd_DS_COMMAND *pcmd,
+				   IN t_void *pdata_buf);
+/** Hander for bgscan config command response */
+mlan_status wlan_ret_bgscan_config(IN mlan_private *pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_802_11_bgscan_query(IN mlan_private *pmpriv,
+					 IN HostCmd_DS_COMMAND *resp,
+					 IN 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(IN mlan_private *pmpriv);
+/*  Free a beacon buffer of the current bss descriptor */
+t_void wlan_free_curr_bcn(IN mlan_private *pmpriv);
+
+#endif /* STA_SUPPORT */
+
+/* Rate related functions */
+t_u8 wlan_convert_v14_rate_ht_info(t_u8 ht_info);
+/** Convert index into data rate */
+t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index,
+			      t_u8 rate_info);
+/** Get active data rates */
+t_u32 wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
+				 t_u8 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_u8 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);
+
+/* 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 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 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(IN pmlan_adapter pmadapter,
+				     IN mlan_ioctl_req *pioctl_req);
+
+/** This function converts region string to CFP table code */
+mlan_status wlan_misc_country_2_cfp_table_code(IN pmlan_adapter pmadapter,
+					       IN t_u8 *country_code,
+					       OUT t_u8 *cfp_bg,
+					       OUT 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 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_void 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(IN mlan_private *priv,
+				       IN 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(IN mlan_private *priv, IN pmlan_buffer pmbuf);
+#endif /* UAP_SUPPORT */
+
+mlan_status wlan_misc_ioctl_coalescing_status(IN pmlan_adapter pmadapter,
+					      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req,
+					   IN t_bool send_ioctl);
+
+mlan_status wlan_cmd_get_hw_spec(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *pcmd);
+mlan_status wlan_ret_get_hw_spec(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN t_void *pioctl_buf);
+mlan_status wlan_cmd_sdio_rx_aggr_cfg(IN HostCmd_DS_COMMAND *pcmd,
+				      IN t_u16 cmd_action,
+				      IN t_void *pdata_buf);
+mlan_status wlan_ret_sdio_rx_aggr_cfg(IN pmlan_private pmpriv,
+				      IN HostCmd_DS_COMMAND *resp);
+
+mlan_status wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_mac_control(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *pcmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_mac_control(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_cw_mode_ctrl(IN pmlan_private pmpriv,
+				  IN HostCmd_DS_COMMAND *cmd,
+				  IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_cw_mode_ctrl(IN pmlan_private pmpriv,
+				  IN HostCmd_DS_COMMAND *resp,
+				  IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_radio_control(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *cmd,
+					  IN t_u16 cmd_action,
+					  IN t_void *pdata_buf);
+mlan_status wlan_ret_802_11_radio_control(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_rf_antenna(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+mlan_status wlan_ret_802_11_rf_antenna(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *resp,
+				       IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_ret_reg_access(mlan_adapter *pmadapter,
+				t_u16 type,
+				IN HostCmd_DS_COMMAND *resp,
+				IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_mem_access(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *resp,
+				IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_reg_mem_ioctl_reg_rw(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_read_eeprom(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_mem_rw(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_reg_access(IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_cmd_mem_access(IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_void *pdata_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(IN pmlan_adapter pmadapter,
+					IN 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(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status
+
+wlan_misc_ioctl_tdls_get_ies(IN pmlan_adapter pmadapter,
+			     IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_tdls_idle_time(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req);
+
+t_void wlan_tdls_config(IN pmlan_private pmpriv, IN t_u8 enable);
+mlan_status wlan_misc_ioctl_tdls_cs_channel(IN pmlan_adapter pmadapter,
+					    IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_config_rtt(IN pmlan_adapter pmadapter,
+			    IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cancel_rtt(IN pmlan_adapter pmadapter,
+			    IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_rtt_responder_cfg(IN pmlan_adapter pmadapter,
+				   IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_802_11_ftm_config_session_params(IN pmlan_private pmpriv,
+						      IN HostCmd_DS_COMMAND
+						      *cmd, IN t_u16 cmd_action,
+						      IN t_u32 cmd_oid,
+						      IN t_void *pdata_buf);
+mlan_status wlan_ret_802_11_ftm_config_session_params(IN pmlan_private pmpriv,
+						      IN HostCmd_DS_COMMAND
+						      *resp,
+						      IN mlan_ioctl_req
+						      *pioctl_buf);
+mlan_status wlan_fill_hal_rtt_results(IN pmlan_private pmpriv,
+				      IN Event_WLS_FTM_t * event_ftm,
+				      IN t_u32 event_ftm_len,
+				      OUT mlan_event *pevent);
+mlan_status wlan_cmd_802_11_ftm_config_responder(IN pmlan_private pmpriv,
+						 IN HostCmd_DS_COMMAND *cmd,
+						 IN t_u16 cmd_action,
+						 IN t_u32 cmd_oid,
+						 IN t_void *pdata_buf);
+mlan_status wlan_ret_802_11_ftm_config_responder(IN pmlan_private pmpriv,
+						 IN HostCmd_DS_COMMAND *resp,
+						 IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_get_info_ver_ext(IN pmlan_adapter pmadapter,
+				  IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_ioctl_link_statistic(IN mlan_private *pmpriv,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_802_11_link_statistic(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *cmd,
+					   IN t_u16 cmd_action,
+					   IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_ret_get_link_statistic(IN pmlan_private pmpriv,
+					IN HostCmd_DS_COMMAND *resp,
+					IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_reg_rx_mgmt_ind(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req);
+
+#ifdef DEBUG_LEVEL1
+mlan_status wlan_set_drvdbg(IN pmlan_adapter pmadapter,
+			    IN pmlan_ioctl_req pioctl_req);
+#endif
+
+#ifdef STA_SUPPORT
+mlan_status wlan_misc_ext_capa_cfg(IN pmlan_adapter pmadapter,
+				   IN pmlan_ioctl_req pioctl_req);
+
+t_u32 wlan_is_ext_capa_support(IN mlan_private *pmpriv);
+#endif
+
+#ifdef STA_SUPPORT
+void wlan_add_ext_capa_info_ie(IN mlan_private *pmpriv, OUT t_u8 **pptlv_out);
+#endif
+
+mlan_status wlan_cmd_boot_sleep(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_boot_sleep(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *resp,
+				IN mlan_ioctl_req *pioctl_buf);
+
+#define BW_20MHZ  0
+#define BW_40MHZ  1
+#define BW_80MHZ  2
+#define BW_160MHZ 3
+int wlan_add_supported_oper_class_ie(IN mlan_private *pmpriv,
+				     OUT 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(IN pmlan_adapter pmadapter,
+						 IN mlan_ioctl_req *pioctl_req);
+mlan_status wlan_misc_ioctl_oper_class(IN pmlan_adapter pmadapter,
+				       IN mlan_ioctl_req *pioctl_req);
+
+t_u8 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(IN pmlan_adapter pmadapter,
+				    IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_txcontrol(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_region(IN pmlan_adapter pmadapter,
+				   IN pmlan_ioctl_req pioctl_req);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status
+
+wlan_misc_ioctl_rx_pkt_coalesce_config(IN pmlan_adapter pmadapter,
+				       IN pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_ioctl_multi_chan_config(IN pmlan_adapter pmadapter,
+					      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_multi_chan_cfg(IN pmlan_private pmpriv,
+				    IN HostCmd_DS_COMMAND *cmd,
+				    IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_multi_chan_cfg(IN pmlan_private pmpriv,
+				    const IN HostCmd_DS_COMMAND *resp,
+				    OUT mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_multi_chan_policy(IN pmlan_adapter pmadapter,
+					      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_multi_chan_policy(IN pmlan_private pmpriv,
+				       IN HostCmd_DS_COMMAND *cmd,
+				       IN t_u16 cmd_action,
+				       IN t_void *pdata_buf);
+
+mlan_status wlan_ret_multi_chan_policy(IN pmlan_private pmpriv,
+				       const IN HostCmd_DS_COMMAND *resp,
+				       OUT mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_drcs_config(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_drcs_cfg(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *cmd,
+			      IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_ret_drcs_cfg(IN pmlan_private pmpriv,
+			      const IN HostCmd_DS_COMMAND *resp,
+			      OUT mlan_ioctl_req *pioctl_buf);
+
+void wlan_bt_coex_wlan_param_update_event(pmlan_private priv,
+					  pmlan_buffer pevent);
+
+mlan_status wlan_misc_ioctl_dfs_repeater_cfg(IN pmlan_adapter pmadapter,
+					     IN pmlan_ioctl_req pioctl_req);
+
+t_bool wlan_check_interface_active(mlan_adapter *pmadapter);
+
+mlan_status wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,
+					 IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_pmic_configure(IN pmlan_adapter pmadapter,
+					   IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_cwmode_ctrl(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_ind_rst_cfg(IN pmlan_adapter pmadapter,
+					IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_ind_rst_cfg(IN HostCmd_DS_COMMAND *cmd,
+				 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_ind_rst_cfg(IN pmlan_private pmpriv,
+				 IN HostCmd_DS_COMMAND *resp,
+				 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_supplicant_pmk(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *cmd,
+					   IN t_u16 cmd_action,
+					   IN t_void *pdata_buf);
+
+mlan_status wlan_ret_802_11_supplicant_pmk(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *resp,
+					   IN mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_sec_ioctl_passphrase(IN pmlan_adapter pmadapter,
+				      IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_get_tsf(IN pmlan_adapter pmadapter,
+				    IN 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(IN pmlan_adapter pmadapter,
+				   IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_get_cfpinfo(IN pmlan_adapter pmadapter,
+			     IN pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_acs(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_acs(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_acs(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_get_tsf(pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action);
+mlan_status wlan_ret_get_tsf(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf);
+
+t_u8 wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie);
+
+mlan_status wlan_clear_fw_roaming_pmk(IN pmlan_private pmpriv);
+
+mlan_status wlan_cmd_ps_inactivity_timeout(IN pmlan_private pmpriv,
+					   IN HostCmd_DS_COMMAND *cmd,
+					   IN t_u16 cmd_action,
+					   IN t_void *pdata_buf);
+
+mlan_status wlan_cmd_host_clock_cfg(IN HostCmd_DS_COMMAND *cmd,
+				    IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_ret_host_clock_cfg(IN pmlan_private pmpriv,
+				    IN HostCmd_DS_COMMAND *resp,
+				    IN mlan_ioctl_req *pioctl_buf);
+
+t_u8 wlan_ieee_rateid_to_mrvl_rateid(IN mlan_private *priv,
+				     IN t_u16 IeeeMacRate, IN t_u8 *dst_mac);
+t_u8 wlan_mrvl_rateid_to_ieee_rateid(IN t_u8 rate);
+
+t_u8 wlan_get_center_freq_idx(IN mlan_private *pmpriv,
+			      IN t_u8 band, IN t_u32 pri_chan, IN t_u8 chan_bw);
+
+mlan_status wlan_ret_chan_region_cfg(IN pmlan_private pmpriv,
+				     IN HostCmd_DS_COMMAND *resp,
+				     IN mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_fw_dump_event(IN pmlan_adapter pmadapter,
+					  IN mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_fw_dump_event(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *cmd,
+				   IN t_u16 cmd_action, IN t_void *pdata_buf);
+
+mlan_status wlan_misc_bootsleep(IN pmlan_adapter pmadapter,
+				IN pmlan_ioctl_req pioctl_req);
+
+/**
+ *  @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) (IN pmlan_private pmpriv),
+		     t_bool (*check_cond) (IN 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) (IN pmlan_private pmpriv),
+		      t_bool (*check_cond) (IN 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) (IN 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) (IN pmlan_private pmpriv),
+			   t_bool (*check_cond_2) (IN 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_sd8997/mlan/mlan_meas.c b/wlan_sd8997/mlan/mlan_meas.c
new file mode 100644
index 0000000..9199336
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_meas.c
@@ -0,0 +1,469 @@
+/**
+ * @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
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/*************************************************************
+Change Log:
+    03/24/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_ioctl.h"
+#include "mlan_meas.h"
+
+/** Default measurement duration when not provided by the application */
+#define WLAN_MEAS_DEFAULT_MEAS_DURATION    1000U	/* TUs */
+
+#ifdef DEBUG_LEVEL2
+/** String descriptions of the different measurement enums.  Debug display */
+static const char *meas_type_str[WLAN_MEAS_NUM_TYPES] = {
+	"basic",
+};
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief Retrieve the measurement string representation of a meas_type enum
+ *  Used for debug display only
+ *
+ *  @param meas_type Measurement type enumeration input for string lookup
+ *
+ *  @return         Constant string representing measurement type
+ */
+static const char *
+wlan_meas_get_meas_type_str(MeasType_t meas_type)
+{
+	if (meas_type <= WLAN_MEAS_11H_MAX_TYPE)
+		return meas_type_str[meas_type];
+
+	return "Invld";
+}
+#endif
+
+/**
+ *  @brief Debug print display of the input measurement request
+ *
+ *  @param pmeas_req  Pointer to the measurement request to display
+ *
+ *  @return          N/A
+ */
+static
+	void
+wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req)
+{
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+
+	PRINTM(MINFO, "Meas: Req: mac_addr: " MACSTR "\n",
+	       MAC2STR(pmeas_req->mac_addr));
+
+	PRINTM(MINFO, "Meas: Req:  dlgTkn: %d\n", pmeas_req->dialog_token);
+	PRINTM(MINFO, "Meas: Req:    mode: dm[%c] rpt[%c] req[%c]\n",
+	       pmeas_req->req_mode.duration_mandatory ? 'X' : ' ',
+	       pmeas_req->req_mode.report ? 'X' : ' ',
+	       pmeas_req->req_mode.request ? 'X' : ' ');
+	PRINTM(MINFO, "Meas: Req:        : en[%c] par[%c]\n",
+	       pmeas_req->req_mode.enable ? 'X' : ' ',
+	       pmeas_req->req_mode.parallel ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+	PRINTM(MINFO, "Meas: Req: measTyp: %s\n",
+	       wlan_meas_get_meas_type_str(pmeas_req->meas_type));
+#endif
+
+	switch (pmeas_req->meas_type) {
+	case WLAN_MEAS_BASIC:
+		/* Lazy cheat, fields of bas, cca, rpi union match on the request */
+		PRINTM(MINFO, "Meas: Req: chan: %u\n",
+		       pmeas_req->req.basic.channel);
+		PRINTM(MINFO, "Meas: Req: strt: %llu\n",
+		       wlan_le64_to_cpu(pmeas_req->req.basic.start_time));
+		PRINTM(MINFO, "Meas: Req:  dur: %u\n",
+		       wlan_le16_to_cpu(pmeas_req->req.basic.duration));
+		break;
+	default:
+		PRINTM(MINFO, "Meas: Req: <unhandled>\n");
+		break;
+	}
+
+	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+	LEAVE();
+}
+
+/**
+ *  @brief Debug print display of the input measurement report
+ *
+ *  @param pmeas_rpt  Pointer to measurement report to display
+ *
+ *  @return          N/A
+ */
+static
+	void
+wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
+{
+	MeasType_t type;
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+	PRINTM(MINFO, "Meas: Rpt: mac_addr: " MACSTR "\n",
+	       MAC2STR(pmeas_rpt->mac_addr));
+
+	PRINTM(MINFO, "Meas: Rpt:  dlgTkn: %d\n", pmeas_rpt->dialog_token);
+
+	PRINTM(MINFO, "Meas: Rpt: rptMode: (%x): Rfs[%c] ICp[%c] Lt[%c]\n",
+	       *(t_u8 *)&pmeas_rpt->rpt_mode,
+	       pmeas_rpt->rpt_mode.refused ? 'X' : ' ',
+	       pmeas_rpt->rpt_mode.incapable ? 'X' : ' ',
+	       pmeas_rpt->rpt_mode.late ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+	PRINTM(MINFO, "Meas: Rpt: measTyp: %s\n",
+	       wlan_meas_get_meas_type_str(pmeas_rpt->meas_type));
+#endif
+
+	type = wlan_le32_to_cpu(pmeas_rpt->meas_type);
+	switch (type) {
+	case WLAN_MEAS_BASIC:
+		PRINTM(MINFO, "Meas: Rpt: chan: %u\n",
+		       pmeas_rpt->rpt.basic.channel);
+		PRINTM(MINFO, "Meas: Rpt: strt: %llu\n",
+		       wlan_le64_to_cpu(pmeas_rpt->rpt.basic.start_time));
+		PRINTM(MINFO, "Meas: Rpt:  dur: %u\n",
+		       wlan_le16_to_cpu(pmeas_rpt->rpt.basic.duration));
+		PRINTM(MINFO, "Meas: Rpt:  bas: (%x): unmsd[%c], radar[%c]\n",
+		       *(t_u8 *)&(pmeas_rpt->rpt.basic.map),
+		       pmeas_rpt->rpt.basic.map.unmeasured ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.radar ? 'X' : ' ');
+		PRINTM(MINFO, "Meas: Rpt:  bas: unidSig[%c] ofdm[%c] bss[%c]\n",
+		       pmeas_rpt->rpt.basic.map.unidentified_sig ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.ofdm_preamble ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.bss ? 'X' : ' ');
+		break;
+	default:
+		PRINTM(MINFO, "Meas: Rpt: <unhandled>\n");
+		break;
+	}
+
+	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+	LEAVE();
+}
+
+/**
+ *  @brief Retrieve a measurement report from the firmware
+ *
+ *  Callback from command processing when a measurement report is received
+ *    from the firmware.  Perform the following when a report is received:
+ *
+ *   -# Debug displays the report if compiled with the appropriate flags
+ *   -# If we are pending on a specific measurement report token, and it
+ *      matches the received report's token, store the report and wake up
+ *      any pending threads
+ *
+ *  @param pmpriv Private driver information structure
+ *  @param resp HostCmd_DS_COMMAND struct returned from the firmware command
+ *              passing a HostCmd_DS_MEASUREMENT_REPORT structure.
+ *
+ *  @return     MLAN_STATUS_SUCCESS
+ */
+static int
+wlan_meas_cmdresp_get_report(mlan_private *pmpriv,
+			     const HostCmd_DS_COMMAND *resp)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt = &resp->params.meas_rpt;
+
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Rpt: %#x-%u, Seq=%u, Ret=%u\n",
+	       resp->command, resp->size, resp->seq_num, resp->result);
+
+	/* Debug displays the measurement report */
+	wlan_meas_dump_meas_rpt(pmeas_rpt);
+
+	/*
+	 * Check if we are pending on a measurement report and it matches
+	 *  the dialog token of the received report:
+	 */
+	if (pmadapter->state_meas.meas_rpt_pend_on
+	    && pmadapter->state_meas.meas_rpt_pend_on ==
+	    pmeas_rpt->dialog_token) {
+		PRINTM(MINFO, "Meas: Rpt: RCV'd Pend on meas #%d\n",
+		       pmadapter->state_meas.meas_rpt_pend_on);
+
+		/* Clear the pending report indicator */
+		pmadapter->state_meas.meas_rpt_pend_on = 0;
+
+		/* Copy the received report into the measurement state for retrieval */
+		memcpy(pmadapter, &pmadapter->state_meas.meas_rpt_returned,
+		       pmeas_rpt,
+		       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(pmpriv->adapter, &pcmd_ptr->params.meas_req, pmeas_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(pmpriv->adapter, pcmd_ptr->params.meas_rpt.mac_addr,
+	       pmpriv->curr_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_sd8997/mlan/mlan_meas.h b/wlan_sd8997/mlan/mlan_meas.h
new file mode 100644
index 0000000..805500b
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_meas.h
@@ -0,0 +1,60 @@
+/**
+ *  @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
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/*************************************************************
+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(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);
+
+/* 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_sd8997/mlan/mlan_misc.c b/wlan_sd8997/mlan/mlan_misc.c
new file mode 100644
index 0000000..73feecf
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_misc.c
@@ -0,0 +1,5650 @@
+/**
+ * @file mlan_misc.c
+ *
+ *  @brief This file include Miscellaneous functions for MLAN module
+ *
+ *  (C) Copyright 2009-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/*************************************************************
+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_sdio.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+extern mlan_operations *mlan_ops[];
+#endif
+extern t_u8 ac_to_tid[4][2];
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/** 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(IN pmlan_private pmpriv, IN 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(IN pmlan_private pmpriv,
+			      IN pmlan_ioctl_req pioctl_req,
+			      IN t_u16 mask,
+			      IN custom_ie *ie_data, OUT 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(IN pmlan_private pmpriv,
+			      IN pmlan_ioctl_req pioctl_req,
+			      IN custom_ie *ie_data, IN 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(pmpriv->adapter, del_ie, ie_data->ie_buffer,
+	       MIN(MAX_IE_SIZE, ie_data->ie_length));
+	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)
+			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(pmpriv->adapter, ie,
+				       pmpriv->mgmt_ie[index].ie_buffer, cnt);
+				if (pmpriv->mgmt_ie[index].ie_length >
+				    (cnt + del_len))
+					memcpy(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)));
+				memset(pmpriv->adapter,
+				       &pmpriv->mgmt_ie[index].ie_buffer, 0,
+				       sizeof(pmpriv->mgmt_ie[index].
+					      ie_buffer));
+				memcpy(pmpriv->adapter,
+				       &pmpriv->mgmt_ie[index].ie_buffer, ie,
+				       pmpriv->mgmt_ie[index].ie_length -
+				       del_len);
+				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 Get correlated 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_get_correlated_time(IN pmlan_adapter pmadapter,
+			      IN pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_host_clock *host_clock = 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;
+	}
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	host_clock = &misc->param.host_clock;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_HOST_CLOCK_CFG,
+			       HostCmd_ACT_GEN_GET,
+			       0, (t_void *)pioctl_req, (t_void *)host_clock);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief     Do ACS
+ *
+ *  @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_acs(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_misc_acs *acs = MNULL;
+
+	ENTER();
+
+	if (pioctl_req != MNULL) {
+		misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+		acs = &misc->param.acs;
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	} else {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_ACS,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, (t_void *)acs);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(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;
+
+	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(IN pmlan_adapter pmadapter,
+			      IN 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(IN pmlan_adapter pmadapter,
+			 IN 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->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_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->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_tx_timeout = pmadapter->dbg.num_tx_timeout;
+		debug_info->num_cmd_timeout = pmadapter->num_cmd_timeout;
+		debug_info->dbg_num_cmd_timeout =
+			pmadapter->dbg.num_cmd_timeout;
+		debug_info->timeout_cmd_id = pmadapter->dbg.timeout_cmd_id;
+		debug_info->timeout_cmd_act = pmadapter->dbg.timeout_cmd_act;
+		memcpy(pmadapter, debug_info->last_cmd_id,
+		       pmadapter->dbg.last_cmd_id,
+		       sizeof(pmadapter->dbg.last_cmd_id));
+		memcpy(pmadapter, debug_info->last_cmd_act,
+		       pmadapter->dbg.last_cmd_act,
+		       sizeof(pmadapter->dbg.last_cmd_act));
+		debug_info->last_cmd_index = pmadapter->dbg.last_cmd_index;
+		memcpy(pmadapter, debug_info->last_cmd_resp_id,
+		       pmadapter->dbg.last_cmd_resp_id,
+		       sizeof(pmadapter->dbg.last_cmd_resp_id));
+		debug_info->last_cmd_resp_index =
+			pmadapter->dbg.last_cmd_resp_index;
+		memcpy(pmadapter, debug_info->last_event,
+		       pmadapter->dbg.last_event,
+		       sizeof(pmadapter->dbg.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;
+		debug_info->mp_rd_bitmap = pmadapter->mp_rd_bitmap;
+		debug_info->mp_wr_bitmap = pmadapter->mp_wr_bitmap;
+		debug_info->curr_rd_port = pmadapter->curr_rd_port;
+		debug_info->curr_wr_port = pmadapter->curr_wr_port;
+		debug_info->mp_invalid_update = pmadapter->mp_invalid_update;
+		debug_info->num_of_irq = pmadapter->num_of_irq;
+		memcpy(pmadapter, debug_info->mp_update, pmadapter->mp_update,
+		       sizeof(pmadapter->mp_update));
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+		memcpy(pmadapter, debug_info->mpa_tx_count,
+		       pmadapter->mpa_tx_count,
+		       sizeof(pmadapter->mpa_tx_count));
+		debug_info->mpa_sent_last_pkt = pmadapter->mpa_sent_last_pkt;
+		debug_info->mpa_sent_no_ports = pmadapter->mpa_sent_no_ports;
+		debug_info->last_recv_wr_bitmap =
+			pmadapter->last_recv_wr_bitmap;
+		debug_info->last_mp_index = pmadapter->last_mp_index;
+		memcpy(pmadapter, debug_info->last_mp_wr_bitmap,
+		       pmadapter->last_mp_wr_bitmap,
+		       sizeof(pmadapter->last_mp_wr_bitmap));
+		memcpy(pmadapter, debug_info->last_mp_wr_ports,
+		       pmadapter->last_mp_wr_ports,
+		       sizeof(pmadapter->last_mp_wr_ports));
+		memcpy(pmadapter, debug_info->last_mp_wr_len,
+		       pmadapter->last_mp_wr_len,
+		       sizeof(pmadapter->last_mp_wr_len));
+		memcpy(pmadapter, debug_info->last_mp_wr_info,
+		       pmadapter->last_mp_wr_info,
+		       sizeof(pmadapter->last_mp_wr_info));
+		memcpy(pmadapter, debug_info->last_curr_wr_port,
+		       pmadapter->last_curr_wr_port,
+		       sizeof(pmadapter->last_curr_wr_port));
+		debug_info->mpa_buf = pmadapter->mpa_buf;
+		debug_info->mpa_buf_size = pmadapter->mpa_buf_size;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+		debug_info->sdio_rx_aggr = pmadapter->sdio_rx_aggr_enable;
+		memcpy(pmadapter, debug_info->mpa_rx_count,
+		       pmadapter->mpa_rx_count,
+		       sizeof(pmadapter->mpa_rx_count));
+#endif
+		debug_info->data_sent = pmadapter->data_sent;
+		debug_info->cmd_sent = pmadapter->cmd_sent;
+		debug_info->cmd_resp_received = pmadapter->cmd_resp_received;
+		debug_info->tx_pkts_queued =
+			util_scalar_read(pmadapter->pmoal_handle,
+					 &pmpriv->wmm.tx_pkts_queued, MNULL,
+					 MNULL);
+#ifdef UAP_SUPPORT
+		debug_info->num_bridge_pkts =
+			util_scalar_read(pmadapter->pmoal_handle,
+					 &pmadapter->pending_bridge_pkts,
+					 pmadapter->callbacks.moal_spin_lock,
+					 pmadapter->callbacks.moal_spin_unlock);
+		debug_info->num_drop_pkts = pmpriv->num_drop_pkts;
+#endif
+		debug_info->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(IN pmlan_adapter pmadapter,
+			    IN 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 function wakes up the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pm_wakeup_card(IN pmlan_adapter pmadapter)
+{
+	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 (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
+		/* GPIO_PORT_TO_LOW(); */
+	} else
+		ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+					  HOST_TO_CARD_EVENT_REG,
+					  HOST_POWER_UP);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function resets the PM setting of the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pm_reset_card(IN pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
+		/* GPIO_PORT_TO_HIGH(); */
+	} else
+		ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+					  HOST_TO_CARD_EVENT_REG, 0);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter, IN 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 Get/Set the firmware wakeup method
+ *
+ *  @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_fw_wakeup_method(IN pmlan_adapter pmadapter, IN 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_pm_cfg *pmcfg = (mlan_ds_pm_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_FW_WAKE_METHOD,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &pmcfg->param.fw_wakeup_params);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter, IN 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 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();
+
+	/* make sure that the data length is at least SDIO block size */
+	data_len =
+		(data_len + MLAN_SDIO_BLOCK_SIZE -
+		 1) / MLAN_SDIO_BLOCK_SIZE * MLAN_SDIO_BLOCK_SIZE;
+
+	/* 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;
+		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 Send coalescing status 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_coalescing_status(IN pmlan_adapter pmadapter,
+				  IN 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;
+
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc->param.coalescing_status);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			IN 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;
+#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);
+
+		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(pmadapter, &pmpriv->ops, mlan_ops[j],
+				       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(IN pmlan_adapter pmadapter,
+			       IN pmlan_ioctl_req pioctl_req,
+			       IN 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(pmadapter,
+							       (t_u8 *)ie_data +
+							       len, &i,
+							       sizeof(ie_data->
+								      ie_index));
+							len += sizeof(ie_data->
+								      ie_index);
+							memcpy(pmadapter,
+							       (t_u8 *)ie_data +
+							       len,
+							       &pmpriv->
+							       mgmt_ie[i].
+							       mgmt_subtype_mask,
+							       sizeof(ie_data->
+								      mgmt_subtype_mask));
+							len += sizeof(ie_data->
+								      mgmt_subtype_mask);
+							memcpy(pmadapter,
+							       (t_u8 *)ie_data +
+							       len,
+							       &pmpriv->
+							       mgmt_ie[i].
+							       ie_length,
+							       sizeof(ie_data->
+								      ie_length));
+							len += sizeof(ie_data->
+								      ie_length);
+							if (pmpriv->mgmt_ie[i].
+							    ie_length) {
+								memcpy(pmadapter, (t_u8 *)ie_data + len, &pmpriv->mgmt_ie[i].ie_buffer, 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) {
+						ret = MLAN_STATUS_SUCCESS;
+						goto done;
+					}
+					tmp_ie = (t_u8 *)&pmpriv->
+						mgmt_ie[index].ie_buffer;
+					memcpy(pmadapter,
+					       tmp_ie +
+					       pmpriv->mgmt_ie[index].ie_length,
+					       &ie_data->ie_buffer,
+					       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(pmadapter, &ie_data->ie_buffer,
+					       &pmpriv->mgmt_ie[index].
+					       ie_buffer,
+					       pmpriv->mgmt_ie[index].
+					       ie_length);
+					misc->param.cust_ie.len +=
+						pmpriv->mgmt_ie[index].
+						ie_length +
+						MLAN_CUSTOM_IE_HDR_SIZE;
+				}
+			} else {
+				if (index >= pmadapter->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(pmadapter, (t_u8 *)ie_data,
+					       &pmpriv->mgmt_ie[index],
+					       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(pmadapter,
+					       &pmpriv->mgmt_ie[index], ie_data,
+					       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(IN pmlan_adapter pmadapter,
+			  IN 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:
+		cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
+		break;
+	case MLAN_REG_BBP:
+		cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
+		break;
+	case MLAN_REG_RF:
+		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;
+	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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_MEM_ACCESS,
+			       cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&reg_mem->param.mem_rw);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will check if station list is empty
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return	   MFALSE/MTRUE
+ */
+t_u8
+wlan_is_station_list_empty(mlan_private *priv)
+{
+	ENTER();
+	if (!(util_peek_list(priv->adapter->pmoal_handle,
+			     &priv->sta_list,
+			     priv->adapter->callbacks.moal_spin_lock,
+			     priv->adapter->callbacks.moal_spin_unlock))) {
+		LEAVE();
+		return MTRUE;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief This function will return the pointer to station entry in station list
+ *          table which matches the give mac address
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     mac address to find in station list table
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+sta_node *
+wlan_get_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr;
+
+	ENTER();
+
+	if (!mac) {
+		LEAVE();
+		return MNULL;
+	}
+	sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+					     &priv->sta_list,
+					     priv->adapter->callbacks.
+					     moal_spin_lock,
+					     priv->adapter->callbacks.
+					     moal_spin_unlock);
+
+	while (sta_ptr && (sta_ptr != (sta_node *)&priv->sta_list)) {
+		if (!memcmp
+		    (priv->adapter, sta_ptr->mac_addr, mac,
+		     MLAN_MAC_ADDR_LENGTH)) {
+			LEAVE();
+			return sta_ptr;
+		}
+		sta_ptr = sta_ptr->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function will add a pointer to station entry in station list
+ *          table with the give mac address, if it does not exist already
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     mac address to find in station list table
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+sta_node *
+wlan_add_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	mlan_adapter *pmadapter = priv->adapter;
+
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		goto done;
+	if (priv->adapter->callbacks.
+	    moal_malloc(priv->adapter->pmoal_handle, sizeof(sta_node),
+			MLAN_MEM_DEF, (t_u8 **)&sta_ptr)) {
+		PRINTM(MERROR, "Failed to allocate memory for station node\n");
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		LEAVE();
+		return MNULL;
+	}
+	memset(priv->adapter, sta_ptr, 0, sizeof(sta_node));
+	memcpy(priv->adapter, sta_ptr->mac_addr, mac, MLAN_MAC_ADDR_LENGTH);
+	util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->sta_list,
+			       (pmlan_linked_list)sta_ptr,
+			       priv->adapter->callbacks.moal_spin_lock,
+			       priv->adapter->callbacks.moal_spin_unlock);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+	if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+	    IsAuthenticatorEnabled(priv->psapriv))
+		authenticator_init_client(priv->psapriv,
+					  &sta_ptr->cm_connectioninfo, mac);
+#endif
+done:
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return sta_ptr;
+}
+
+/**
+ *  @brief This function will delete a station entry from station list
+ *
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     station's mac address
+ *
+ *  @return	   N/A
+ */
+t_void
+wlan_delete_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	mlan_adapter *pmadapter = priv->adapter;
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr) {
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+		    IsAuthenticatorEnabled(priv->psapriv))
+			authenticator_free_client(priv->psapriv,
+						  sta_ptr->cm_connectioninfo);
+#endif
+		util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list,
+				 (pmlan_linked_list)sta_ptr,
+				 priv->adapter->callbacks.moal_spin_lock,
+				 priv->adapter->callbacks.moal_spin_unlock);
+		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
+						    (t_u8 *)sta_ptr);
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Clean up wapi station list
+ *
+ *  @param priv  Pointer to the mlan_private driver data struct
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_delete_station_list(pmlan_private priv)
+{
+	sta_node *sta_ptr;
+
+	ENTER();
+	while ((sta_ptr =
+		(sta_node *)util_dequeue_list(priv->adapter->pmoal_handle,
+					      &priv->sta_list,
+					      priv->adapter->callbacks.
+					      moal_spin_lock,
+					      priv->adapter->callbacks.
+					      moal_spin_unlock))) {
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+		    IsAuthenticatorEnabled(priv->psapriv))
+			authenticator_free_client(priv->psapriv,
+						  sta_ptr->cm_connectioninfo);
+#endif
+		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
+						    (t_u8 *)sta_ptr);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief 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(priv->adapter, peer_info->mac_addr,
+			       sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH);
+			memcpy(priv->adapter, peer_info->ht_cap,
+			       &sta_ptr->HTcap, sizeof(IEEEtypes_HTCap_t));
+			memcpy(priv->adapter, peer_info->ext_cap,
+			       &sta_ptr->ExtCap, sizeof(IEEEtypes_ExtCap_t));
+			memcpy(priv->adapter, peer_info->vht_cap,
+			       &sta_ptr->vht_cap, sizeof(IEEEtypes_VHTCap_t));
+			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(IN pmlan_adapter pmadapter,
+			    IN 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(pmpriv->adapter, (t_u8 *)tdls_evt->peer_mac_addr,
+			       tdls_all_cfg->u.tdls_tear_down.peer_mac_addr,
+			       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)pMrvlTlv->header.len;
+				memset(pmadapter, pmpriv->chan_supp, 0,
+				       sizeof(pmpriv->chan_supp));
+				memcpy(pmadapter, pmpriv->chan_supp,
+				       pMrvlTlv->data, MIN(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)pMrvlTlv->header.len;
+				memset(pmadapter, pmpriv->supp_regulatory_class,
+				       0,
+				       sizeof(pmpriv->supp_regulatory_class));
+				memcpy(pmadapter, pmpriv->supp_regulatory_class,
+				       pMrvlTlv->data, MIN(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	        N/A
+ */
+t_void
+wlan_tdls_config(IN pmlan_private pmpriv, IN 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	        N/A
+ */
+t_void
+wlan_tdls_cs_param_config(IN 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	         N/A
+ */
+t_void
+wlan_tdls_cs_start(IN pmlan_private pmpriv,
+		   IN t_u8 *peer_mac_addr, IN 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(pmpriv->adapter, tdls_config, &misc->param.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(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(pmpriv->adapter,
+		       tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr,
+		       peer_mac_addr, 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->
+							       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();
+}
+
+/**
+ *  @brief stop tdls channel switch
+ *
+ *  @param pmpriv	A pointer to mlan_private structure
+ *  @param peer_mac_addr 	A pointer to peer mac address
+ *  @return	                N/A
+ */
+t_void
+wlan_tdls_cs_stop(IN pmlan_private pmpriv, IN 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(pmpriv->adapter,
+	       tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
+	       peer_mac_addr, 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();
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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(pmpriv->adapter,
+				       (t_u8 *)tdls_evt->peer_mac_addr,
+				       ptdls_oper->peer_mac,
+				       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
+ */
+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(pmadapter, (t_u8 *)ext_cap,
+		       (t_u8 *)pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t),
+		       pbss_desc->pext_cap->ieee_hdr.len);
+	}
+	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(IN pmlan_adapter pmadapter,
+			     IN 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(pmadapter, &sta_ptr->vht_oprat,
+			       tdls_ies->vht_oprat,
+			       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) {
+		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(pbss_desc->
+							       channel);
+		}
+		if (vht_oprat &&
+		    vht_oprat->ieee_hdr.element_id == VHT_OPERATION) {
+			ht_info->ht_info.field2 =
+				wlan_get_second_channel_offset(pbss_desc->
+							       channel);
+			ht_info->ht_info.field2 |= MBIT(2);
+		}
+		if (sta_ptr)
+			memcpy(pmadapter, &sta_ptr->HTInfo, tdls_ies->ht_info,
+			       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(pmadapter, pSupp_chan->data, pmpriv->chan_supp,
+			       pmpriv->chan_supp_len);
+		} else {
+			pSupp_chan->ieee_hdr.len = sizeof(supp_chan);
+			memcpy(pmadapter, pSupp_chan->data, supp_chan,
+			       sizeof(supp_chan));
+		}
+		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(pmadapter, pRegulatory_class->data,
+			       pmpriv->supp_regulatory_class,
+			       pmpriv->supp_regulatory_class_len);
+		} else {
+			pRegulatory_class->ieee_hdr.len =
+				sizeof(regulatory_class);
+			memcpy(pmadapter, pRegulatory_class->data,
+			       regulatory_class, sizeof(regulatory_class));
+		}
+		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(IN pmlan_adapter pmadapter,
+				 IN 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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_get_info *pinfo = (mlan_ds_get_info *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_VERSION_EXT,
+			       HostCmd_ACT_GEN_GET,
+			       0,
+			       (t_void *)pioctl_req,
+			       &pinfo->param.ver_ext.version_str_sel);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function convert mlan_wifi_rate to wifi_rate.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param rateStats   wifi_rate_stat array
+ *  @param pnum_rate   A pointer to num_rate
+ *
+ *  @return           N/A
+ */
+t_void
+wlan_fill_hal_wifi_rate_in_host(IN pmlan_private pmpriv,
+				OUT wifi_rate_stat rateStats[],
+				OUT t_u32 *pnumRate)
+{
+	t_u32 total_num_rate = 0;
+	t_u32 mcs_idx = 0;
+	t_u8 index = 0;
+	t_u8 rate_info = 0;
+
+	ENTER();
+
+	/* HT MCS */
+	for (mcs_idx = 0; mcs_idx < MCS_NUM_SUPP; mcs_idx++) {
+		/* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+		rateStats[total_num_rate].rate.preamble = 2;
+		/* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+		rateStats[total_num_rate].rate.bw = 0;
+		rateStats[total_num_rate].rate.rateMcsIdx = mcs_idx;
+		index = rateStats[total_num_rate].rate.rateMcsIdx;
+		rate_info =
+			MLAN_RATE_FORMAT_HT | (rateStats[total_num_rate].rate.
+					       bw << 2);
+		rateStats[total_num_rate].rate.bitrate =
+			wlan_index_to_data_rate(pmpriv->adapter, index,
+						rate_info) * 5;
+		PRINTM(MINFO, "HT[%d] index=0x%x rate_info=0x%x bitrate=0x%x\n",
+		       total_num_rate, index, rate_info,
+		       rateStats[total_num_rate].rate.bitrate / 5);
+
+		/* Get Tx mpdu */
+		rateStats[total_num_rate].tx_mpdu = 0;
+		rateStats[total_num_rate].rx_mpdu = 0;
+
+		/* Todo: mpdu_lost/retries*, need extend GetTxRxRateInfo */
+		rateStats[total_num_rate].mpdu_lost = 0xC1;
+		rateStats[total_num_rate].retries = 0xC2;
+		rateStats[total_num_rate].retries_short = 0xC3;
+		rateStats[total_num_rate].retries_long = 0xC4;
+
+		total_num_rate++;
+	}
+
+	/* VHT MCS */
+	for (mcs_idx = 0; mcs_idx < VHT_NUM_SUPPORT_MCS; mcs_idx++) {
+		/* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+		rateStats[total_num_rate].rate.preamble = 3;
+		/* 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
+		rateStats[total_num_rate].rate.nss = 0;
+		/* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+		rateStats[total_num_rate].rate.bw = 0;
+		rateStats[total_num_rate].rate.rateMcsIdx = mcs_idx;
+		/* nss 2 ? bw 20MHZ ? */
+		index = rateStats[total_num_rate].rate.
+			rateMcsIdx | (rateStats[total_num_rate].rate.nss << 4);
+		rate_info =
+			MLAN_RATE_FORMAT_VHT | (rateStats[total_num_rate].rate.
+						bw << 2);
+		rateStats[total_num_rate].rate.bitrate =
+			wlan_index_to_data_rate(pmpriv->adapter, index,
+						rate_info) * 5;
+		PRINTM(MINFO,
+		       "VHT[%d] index=0x%x rate_info=0x%x bitrate=0x%x\n",
+		       total_num_rate, index, rate_info,
+		       rateStats[total_num_rate].rate.bitrate / 5);
+
+		rateStats[total_num_rate].tx_mpdu = 0;
+		rateStats[total_num_rate].rx_mpdu = 0;
+
+		/* Todo: mpdu_lost/retries*, need extend GetTxRxRateInfo */
+		rateStats[total_num_rate].mpdu_lost = 0xC1;
+		rateStats[total_num_rate].retries = 0xC2;
+		rateStats[total_num_rate].retries_short = 0xC3;
+		rateStats[total_num_rate].retries_long = 0xC4;
+
+		total_num_rate++;
+	}
+
+	*pnumRate = total_num_rate;
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function fill link layer statistic from firmware
+ *
+ *  @param priv       					A pointer to mlan_private structure
+ *  @param link_statistic_ioctl_buf,    A pointer to fill ioctl buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static void
+wlan_fill_link_statistic_in_host(mlan_private *priv,
+				 char *link_statistic_ioctl_buf)
+{
+	char *link_statistic = link_statistic_ioctl_buf;
+	wifi_radio_stat *radio_stat = MNULL;
+	wifi_iface_stat *iface_stat = MNULL;
+	t_u32 num_radio = MAX_RADIO;
+	int i = 0, chan_idx = 0;
+	t_u32 num_peers = 0;
+	sta_node *sta_ptr = MNULL;
+	t_u8 *ptid = MNULL;
+
+	ENTER();
+
+	*((t_u32 *)link_statistic) = num_radio;
+	link_statistic += sizeof(num_radio);
+
+	/* Fill radio stats array */
+	for (i = 0; i < num_radio; i++) {
+		radio_stat = (wifi_radio_stat *) link_statistic;
+		link_statistic += sizeof(wifi_radio_stat);
+
+		radio_stat->radio = 0xF0;
+
+		radio_stat->on_time = 0;
+		radio_stat->tx_time = 0;
+		radio_stat->reserved0 = 0;
+		radio_stat->rx_time = 0;
+		radio_stat->on_time_scan = 0;
+		radio_stat->on_time_nbd = 0;
+		radio_stat->on_time_gscan = 0;
+		radio_stat->on_time_roam_scan = 0;
+		radio_stat->on_time_pno_scan = 0;
+		radio_stat->on_time_hs20 = 0;
+
+		radio_stat->num_channels = 1;
+		for (chan_idx = 0; chan_idx < radio_stat->num_channels;
+		     chan_idx++) {
+			if (radio_stat->num_channels > MAX_NUM_CHAN) {
+				radio_stat->num_channels = MAX_NUM_CHAN;
+				PRINTM(MERROR,
+				       "%s : radio_stat->num_channels=%d\n",
+				       __func__, radio_stat->num_channels);
+				break;
+			}
+
+			if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+				if (priv->media_connected) {
+					radio_stat->channels[chan_idx].channel.
+						width =
+						priv->curr_bss_params.
+						bss_descriptor.curr_bandwidth;
+					radio_stat->channels[chan_idx].channel.
+						center_freq =
+						priv->curr_bss_params.
+						bss_descriptor.freq;
+					radio_stat->channels[chan_idx].channel.
+						center_freq0 = 0;
+					radio_stat->channels[chan_idx].channel.
+						center_freq1 = 0;
+				}
+			} else {
+				radio_stat->channels[chan_idx].channel.width =
+					priv->uap_state_chan_cb.bandcfg.
+					chanWidth;
+				radio_stat->channels[chan_idx].channel.
+					center_freq =
+					wlan_11d_chan_2_freq(priv->adapter,
+							     priv->
+							     uap_state_chan_cb.
+							     channel,
+							     (priv->
+							      uap_state_chan_cb.
+							      channel >
+							      14) ? BAND_A :
+							     BAND_G);
+				radio_stat->channels[chan_idx].channel.
+					center_freq0 = 0;
+				radio_stat->channels[chan_idx].channel.
+					center_freq1 = 0;
+			}
+			radio_stat->channels[chan_idx].on_time = 0xE3;
+			radio_stat->channels[chan_idx].cca_busy_time = 0xE4;
+		}
+	}
+
+	/* Fill iface stats */
+	iface_stat = (wifi_iface_stat *) link_statistic;
+
+	/* get wifi_interface_link_layer_info in driver, not in firmware */
+	if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+		iface_stat->info.mode = WIFI_INTERFACE_STA;
+		if (priv->media_connected)
+			iface_stat->info.state = WIFI_ASSOCIATING;
+		else
+			iface_stat->info.state = WIFI_DISCONNECTED;
+		iface_stat->info.roaming = WIFI_ROAMING_IDLE;
+		iface_stat->info.capabilities = WIFI_CAPABILITY_QOS;
+		memcpy(priv->adapter, iface_stat->info.ssid,
+		       priv->curr_bss_params.bss_descriptor.ssid.ssid,
+		       MLAN_MAX_SSID_LENGTH);
+		memcpy(priv->adapter, iface_stat->info.bssid,
+		       priv->curr_bss_params.bss_descriptor.mac_address,
+		       MLAN_MAC_ADDR_LENGTH);
+	} else {
+		iface_stat->info.mode = WIFI_INTERFACE_SOFTAP;
+		iface_stat->info.capabilities = WIFI_CAPABILITY_QOS;
+	}
+	memcpy(priv->adapter, iface_stat->info.mac_addr, priv->curr_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+	memcpy(priv->adapter, iface_stat->info.ap_country_str,
+	       priv->adapter->country_code, COUNTRY_CODE_LEN);
+	memcpy(priv->adapter, iface_stat->info.country_str,
+	       priv->adapter->country_code, COUNTRY_CODE_LEN);
+
+	iface_stat->beacon_rx = 0;
+	iface_stat->average_tsf_offset = 0;
+	iface_stat->leaky_ap_detected = 0;
+	iface_stat->leaky_ap_avg_num_frames_leaked = 0;
+	iface_stat->leaky_ap_guard_time = 0;
+
+	/* Value of iface_stat should be Reaccumulate by each peer */
+	iface_stat->mgmt_rx = 0;
+	iface_stat->mgmt_action_rx = 0;
+	iface_stat->mgmt_action_tx = 0;
+
+	iface_stat->rssi_mgmt = 0;
+	iface_stat->rssi_data = 0;
+	iface_stat->rssi_ack = 0;
+
+	for (i = WMM_AC_BK; i <= WMM_AC_VO; i++) {
+		iface_stat->ac[i].ac = i;
+		ptid = ac_to_tid[i];
+		iface_stat->ac[i].tx_mpdu =
+			priv->wmm.packets_out[ptid[0]] +
+			priv->wmm.packets_out[ptid[1]];
+		iface_stat->ac[i].rx_mpdu = 0;
+		iface_stat->ac[i].tx_mcast = 0;
+		iface_stat->ac[i].rx_mcast = 0;
+		iface_stat->ac[i].rx_ampdu = 0;
+		iface_stat->ac[i].tx_ampdu = 0;
+		iface_stat->ac[i].mpdu_lost = 0;
+		iface_stat->ac[i].retries = 0;
+		iface_stat->ac[i].retries_short = 0;
+		iface_stat->ac[i].retries_long = 0;
+		iface_stat->ac[i].contention_time_min = 0;
+		iface_stat->ac[i].contention_time_max = 0;
+		iface_stat->ac[i].contention_time_avg = 0;
+		iface_stat->ac[i].contention_num_samples = 0;
+	}
+
+	if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+		if (priv->media_connected) {
+			iface_stat->peer_info[0].type = WIFI_PEER_AP;
+			memcpy(priv->adapter,
+			       iface_stat->peer_info[0].peer_mac_address,
+			       priv->curr_bss_params.bss_descriptor.mac_address,
+			       MLAN_MAC_ADDR_LENGTH);
+			iface_stat->peer_info[0].capabilities =
+				WIFI_CAPABILITY_QOS;
+			wlan_fill_hal_wifi_rate_in_host(priv,
+							iface_stat->
+							peer_info[0].rate_stats,
+							&(iface_stat->
+							  peer_info[0].
+							  num_rate));
+			num_peers = 1;
+		}
+	} else {
+		sta_ptr =
+			(sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+						   &priv->sta_list,
+						   priv->adapter->callbacks.
+						   moal_spin_lock,
+						   priv->adapter->callbacks.
+						   moal_spin_unlock);
+		if (sta_ptr) {
+			while (sta_ptr != (sta_node *)&priv->sta_list) {
+				iface_stat->peer_info[num_peers].type =
+					WIFI_PEER_STA;
+				memcpy(priv->adapter,
+				       iface_stat->peer_info[num_peers].
+				       peer_mac_address, sta_ptr->mac_addr,
+				       MLAN_MAC_ADDR_LENGTH);
+				iface_stat->peer_info[num_peers].capabilities =
+					WIFI_CAPABILITY_QOS;
+				wlan_fill_hal_wifi_rate_in_host(priv,
+								iface_stat->
+								peer_info
+								[num_peers].
+								rate_stats,
+								&(iface_stat->
+								  peer_info
+								  [num_peers].
+								  num_rate));
+				num_peers++;
+
+				sta_ptr = sta_ptr->pnext;
+			}
+		}
+	}
+	iface_stat->num_peers = num_peers;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Set/Get link layer statistics
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_ioctl_link_statistic(IN mlan_private *pmpriv,
+			  IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *info = MNULL;
+	t_u8 *link_statistic = MNULL;
+
+	ENTER();
+
+	/* Check buffer length of MLAN IOCTL */
+	if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+    /** We will not send HostCmd_CMD_802_11_LINK_STATS to FW */
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		info = (mlan_ds_get_info *)pioctl_req->pbuf;
+		link_statistic = info->param.link_statistic;
+	/** Get the LL STATS from driver */
+		wlan_fill_link_statistic_in_host(pmpriv, link_statistic);
+		DBG_HEXDUMP(MCMD_D,
+			    "wlan_ioctl_link_statistic() link_statistic in host",
+			    (t_u8 *)link_statistic, 800);
+	}
+	ret = MLAN_STATUS_SUCCESS;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief config rtt
+ *
+ *  @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_rtt(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!pioctl_req) {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_FTM_CONFIG_SESSION_PARAMS,
+			       HostCmd_ACT_GEN_SET,
+			       OID_RTT_REQUEST,
+			       (t_void *)pioctl_req, &(misc->param.rtt_params));
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief cancel rtt
+ *
+ *  @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_cancel_rtt(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!pioctl_req) {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_FTM_CONFIG_SESSION_PARAMS,
+			       HostCmd_ACT_GEN_SET,
+			       OID_RTT_CANCEL,
+			       (t_void *)pioctl_req, &(misc->param.rtt_cancel));
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief rtt responder 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_rtt_responder_cfg(IN pmlan_adapter pmadapter,
+		       IN pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!pioctl_req) {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_FTM_CONFIG_RESPONDER,
+			       HostCmd_ACT_GEN_SET,
+			       0,
+			       (t_void *)pioctl_req,
+			       &(misc->param.rtt_rsp_cfg));
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(IN mlan_private *priv,
+			       IN t_u8 *payload,
+			       IN t_u32 payload_len, IN 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;
+	IEEE80211_MGMT *mgmt = MNULL;
+	t_u8 category = 0;
+	t_u8 action_code = 0;
+	struct timestamps tstamps;
+	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:
+	case SUBTYPE_DISASSOC:
+	case SUBTYPE_DEAUTH:
+	case SUBTYPE_AUTH:
+	case SUBTYPE_PROBE_RESP:
+		unicast = MTRUE;
+		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 ((category == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM) &&
+		    (action_code == 0x1)) {
+			prx_pd->toa_tod_tstamps =
+				wlan_le64_to_cpu(prx_pd->toa_tod_tstamps);
+			tstamps.t3 = prx_pd->toa_tod_tstamps >> 32;
+			tstamps.t2 = (t_u32)prx_pd->toa_tod_tstamps;
+			tstamps.t2_err = 0;
+			tstamps.t3_err = 0;
+			tstamps.ingress_time =
+				pcb->moal_do_div(pmadapter->host_bbu_clk_delta,
+						 10);
+			tstamps.ingress_time += tstamps.t2;	//t2, t3 is 10ns and delta is in 1 ns unit;
+			PRINTM(MINFO, "T2: %d, T3: %d, ingress: %lu\n",
+			       tstamps.t2, tstamps.t3, tstamps.ingress_time);
+		}
+		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 (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(pmadapter, (t_u8 *)pevent->event_buf,
+		       &mgmt->u.ft_resp.target_ap_addr, MLAN_MAC_ADDR_LENGTH);
+		memcpy(pmadapter,
+		       (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+		       payload + FT_ACTION_HEAD_LEN,
+		       payload_len - FT_ACTION_HEAD_LEN);
+	} else if (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(pmadapter, (t_u8 *)pevent->event_buf, mgmt->sa,
+		       MLAN_MAC_ADDR_LENGTH);
+		memcpy(pmadapter,
+		       (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+		       payload + AUTH_PACKET_LEN,
+		       payload_len - AUTH_PACKET_LEN);
+	} else {
+		pevent->event_id = MLAN_EVENT_ID_DRV_MGMT_FRAME;
+		pevent->event_len = payload_len + sizeof(pevent->event_id);
+		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+		       (t_u8 *)&pevent->event_id, sizeof(pevent->event_id));
+		memcpy(pmadapter,
+		       (t_u8 *)(pevent->event_buf + sizeof(pevent->event_id)),
+		       payload, payload_len);
+		//Append timestamp info at the end of event
+		if ((category == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM) &&
+		    (action_code == 0x1)) {
+			memcpy(pmadapter,
+			       (t_u8 *)(pevent->event_buf +
+					sizeof(pevent->event_id) + payload_len),
+			       &tstamps, sizeof(struct timestamps));
+			pevent->event_len =
+				payload_len + sizeof(pevent->event_id) +
+				sizeof(struct timestamps);
+		}
+
+	}
+	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(IN pmlan_adapter pmadapter,
+		       IN 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(pmpriv->adapter, &misc->param.ext_cap, &pmpriv->ext_cap,
+		       sizeof(misc->param.ext_cap));
+	else if (MLAN_ACT_SET == pioctl_req->action) {
+		memcpy(pmpriv->adapter, &pmpriv->ext_cap, &misc->param.ext_cap,
+		       sizeof(misc->param.ext_cap));
+		/* Save default Extended Capability */
+		memcpy(pmpriv->adapter, &pmpriv->def_ext_cap, &pmpriv->ext_cap,
+		       sizeof(pmpriv->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
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Add Extended Capabilities IE
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param pptlv_out          A pointer to TLV to fill in
+ *
+ *  @return                   N/A
+ */
+void
+wlan_add_ext_capa_info_ie(IN mlan_private *pmpriv, OUT 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);
+	SET_EXTCAP_FTMI(pmpriv->ext_cap);
+	SET_EXTCAP_INTERNETWORKING(pmpriv->ext_cap);
+	memcpy(pmpriv->adapter, &pext_cap->ext_cap, &pmpriv->ext_cap,
+	       sizeof(pmpriv->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(IN pmlan_adapter pmadapter,
+			IN 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;
+#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(priv->adapter, &frame_control,
+			       (t_u8 *)&(mgmt_tlv->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);
+				if (pht_cap) {
+					PRINTM(MCMND, "STA supports 11n\n");
+					sta_ptr->is_11n_enabled = MTRUE;
+					memcpy(priv->adapter,
+					       (t_u8 *)&sta_ptr->HTcap, pht_cap,
+					       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);
+				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");
+				}
+#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);
+				erp = wlan_get_specific_ie(priv, assoc_req_ie,
+							   ie_len, ERP_INFO);
+				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_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
+ *
+ *  @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_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;
+
+	ENTER();
+
+	DBG_HEXDUMP(MCMD_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);
+		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 (element_id == id) {
+			PRINTM(MCMND, "Find IE: id=%d\n", id);
+			DBG_HEXDUMP(MCMND, "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(IN pmlan_adapter pmadapter, IN 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)
+	    || pmadapter->sdio_ireg) {
+		pm_cfg->param.ps_info.is_suspend_allowed = MFALSE;
+		PRINTM(MIOCTL,
+		       "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d sdio_ireg=0x%x\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),
+		       pmadapter->sdio_ireg);
+	}
+	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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(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_radio_cfg *radio_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_ds_ant_cfg *ant_cfg = MNULL;
+
+	ENTER();
+
+	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+	ant_cfg = &radio_cfg->param.ant_cfg;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		/* User input validation */
+		if (!ant_cfg->tx_antenna ||
+		    bitcount(ant_cfg->tx_antenna & 0xFFFF) >
+		    pmadapter->number_of_antenna) {
+			PRINTM(MERROR, "Invalid antenna setting\n");
+			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 & 0xFFFF) >
+			    pmadapter->number_of_antenna) {
+				PRINTM(MERROR, "Invalid antenna setting\n");
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				goto exit;
+			}
+		} else
+			ant_cfg->rx_antenna = ant_cfg->tx_antenna;
+		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_RF_ANTENNA,
+			       cmd_action,
+			       0, (t_void *)pioctl_req, (t_void *)ant_cfg);
+
+	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(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];
+
+	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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			       IN 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 (!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(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];
+
+	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(IN pmlan_adapter pmadapter,
+			       IN 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 < 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_HRDSSS0) &&
+			    (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_MCS0) &&
+			    (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 (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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			      IN 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(IN pmlan_adapter pmadapter,
+				 IN 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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_P2P_PARAMS_CONFIG,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc_cfg->param.p2p_config);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set coalesce config
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,
+			     IN 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 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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+				       IN 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 Get/Set channel time and buffer weight 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_multi_chan_config(IN pmlan_adapter pmadapter,
+				  IN 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_MULTI_CHAN_CONFIG,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc->param.multi_chan_cfg);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set multi-channel policy setting
+ *
+ *  @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_multi_chan_policy(IN pmlan_adapter pmadapter,
+				  IN 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) {
+		if (pmadapter->dfs_repeater) {
+			PRINTM(MMSG,
+			       "DFS-Repeater is on, can not enable DRCS\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto fail;
+		}
+		cmd_action = HostCmd_ACT_GEN_SET;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_MULTI_CHAN_POLICY,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       &misc->param.multi_chan_policy);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+fail:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set DRCS 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_drcs_config(IN pmlan_adapter pmadapter,
+			    IN 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_DRCS_CONFIG,
+			       cmd_action,
+			       0, (t_void *)pioctl_req, &misc->param.drcs_cfg);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+				 IN 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;
+		}
+
+		/* If DRCS is on then we should not set
+		 * DFS-repeater mode */
+		if (pmadapter->mc_policy) {
+			PRINTM(MERROR,
+			       "DFS-repeater cannot be started when DRCS is on\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 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(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];
+
+	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(IN pmlan_adapter pmadapter,
+			    IN 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 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(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_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 (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(pmadapter,
+					       &sec->param.passphrase.ssid,
+					       &pbss_desc->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(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;
+
+	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(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;
+	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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+			IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(IN pmlan_adapter pmadapter,
+				     IN 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 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(IN pmlan_adapter pmadapter,
+			   IN 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;
+	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(IN pmlan_adapter pmadapter,
+			      IN mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_FW_DUMP_EVENT,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get the network monitor 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_net_monitor(IN pmlan_adapter pmadapter,
+			    IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv;
+	mlan_ds_misc_cfg *misc;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (!pioctl_req) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	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_NET_MONITOR,
+			       cmd_action,
+			       0, (t_void *)pioctl_req, &misc->param.net_mon);
+
+	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(IN pmlan_adapter pmadapter, IN 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;
+}
diff --git a/wlan_sd8997/mlan/mlan_module.c b/wlan_sd8997/mlan/mlan_module.c
new file mode 100644
index 0000000..4b94cf2
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_module.c
@@ -0,0 +1,60 @@
+/** @file mlan_module.c
+ *
+ *  @brief This file declares the exported symbols from MLAN.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+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);
+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_interrupt);
+#if defined(SYSKT)
+EXPORT_SYMBOL(mlan_hs_callback);
+#endif /* SYSKT_MULTI || SYSKT */
+
+EXPORT_SYMBOL(mlan_pm_wakeup_card);
+EXPORT_SYMBOL(mlan_is_main_process_running);
+
+MODULE_DESCRIPTION("M-WLAN MLAN Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_VERSION(MLAN_RELEASE_VERSION);
+MODULE_LICENSE("Marvell Proprietary");
+#endif /* LINUX */
diff --git a/wlan_sd8997/mlan/mlan_scan.c b/wlan_sd8997/mlan/mlan_scan.c
new file mode 100644
index 0000000..a179b25
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_scan.c
@@ -0,0 +1,6157 @@
+/** @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.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+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_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+/********************************************************
+			Local Constants
+********************************************************/
+#define MRVDRV_MAX_CHANNELS_PER_SCAN     40
+/** The maximum number of channels the firmware can scan per command */
+#define MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN   4
+
+/**
+ * Number of channels to scan per firmware scan command issuance.
+ *
+ * Number restricted to prevent hitting the limit on the amount of scan data
+ * returned in a single firmware scan command.
+ */
+#define MRVDRV_CHANNELS_PER_SCAN_CMD            4
+
+/** Memory needed to store a max sized Channel List TLV for a firmware scan */
+#define CHAN_TLV_MAX_SIZE  (sizeof(MrvlIEtypesHeader_t)                  \
+				+ (MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN \
+				* sizeof(ChanScanParamSet_t)))
+
+/** Memory needed to store supported rate */
+#define RATE_TLV_MAX_SIZE   (sizeof(MrvlIEtypes_RatesParamSet_t) + HOSTCMD_SUPPORTED_RATES)
+
+/** Memory needed to store a max number/size WildCard
+ *  SSID TLV for a firmware scan */
+#define WILDCARD_SSID_TLV_MAX_SIZE                     \
+		(MRVDRV_MAX_SSID_LIST_LENGTH  *                \
+		 (sizeof(MrvlIEtypes_WildCardSsIdParamSet_t) + \
+		  MRVDRV_MAX_SSID_LENGTH))
+
+/** 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        \
+				+ 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_MAX
+};
+
+static t_u8 wpa_oui[CIPHER_SUITE_MAX][4] = {
+	{0x00, 0x50, 0xf2, 0x01},	/* WEP40 */
+	{0x00, 0x50, 0xf2, 0x02},	/* TKIP */
+	{0x00, 0x50, 0xf2, 0x04},	/* AES */
+	{0x00, 0x50, 0xf2, 0x05},	/* WEP104 */
+};
+
+static t_u8 rsn_oui[CIPHER_SUITE_MAX][4] = {
+	{0x00, 0x0f, 0xac, 0x01},	/* WEP40 */
+	{0x00, 0x0f, 0xac, 0x02},	/* TKIP */
+	{0x00, 0x0f, 0xac, 0x04},	/* AES */
+	{0x00, 0x0f, 0xac, 0x05},	/* WEP104 */
+};
+
+/**
+ *  @brief Convert radio type scan parameter to a band config used in join cmd
+ *
+ *  @param radio_type Scan parameter indicating the radio used for a channel
+ *                    in a scan command.
+ *
+ *  @return          Band type conversion of scanBand used in join/assoc cmds
+ *
+ */
+t_u8
+radio_type_to_band(t_u8 radio_type)
+{
+	t_u8 ret_band;
+
+	switch (radio_type) {
+	case BAND_5GHZ:
+		ret_band = BAND_A;
+		break;
+	case BAND_2GHZ:
+	default:
+		ret_band = BAND_G;
+		break;
+	}
+
+	return ret_band;
+}
+
+/**
+ *  @brief This function will update the channel statistics from scan result
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param pchanstats_tlv   A pointer to MrvlIEtypes_ChannelStats_t tlv
+ *
+ *  @return                NA
+ */
+void
+wlan_update_chan_statistics(mlan_private *pmpriv,
+			    MrvlIEtypes_ChannelStats_t *pchanstats_tlv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 i;
+	ChanStatistics_t *pchan_stats =
+		(ChanStatistics_t *)((t_u8 *)pchanstats_tlv +
+				     sizeof(MrvlIEtypesHeader_t));
+	t_u8 num_chan =
+		wlan_le16_to_cpu(pchanstats_tlv->header.len) /
+		sizeof(ChanStatistics_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(pmadapter,
+		       &pmadapter->pchan_stats[pmadapter->idx_chan_stats],
+		       pchan_stats, sizeof(ChanStatistics_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))) {
+		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 pbss_desc for appropriate IE and then check if WPA IE has AES
+ *  OUI in it. If WPA IE does not have AES in PTK then return 0;
+ *
+ *  @param pbss_desc       A pointer to current BSS descriptor
+ *  @return                0 on failure to find AES OUI, 1 on success.
+ */
+static t_u8
+is_wpa_oui_present(mlan_adapter *pmadapter, BSSDescriptor_t *pbss_desc,
+		   t_u32 cipher_suite)
+{
+	t_u8 *oui = MNULL;
+	IEBody *ie_body = MNULL;
+	t_u8 ret = MLAN_OUI_NOT_PRESENT;
+
+	ENTER();
+	if (((pbss_desc->pwpa_ie) &&
+	     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE))) {
+		ie_body = (IEBody *)pbss_desc->pwpa_ie->data;
+		oui = &wpa_oui[cipher_suite][0];
+		ret = search_oui_in_ie(pmadapter, ie_body, oui);
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief compare config band and a band from the scan result,
+ *  which is defined by functiion radio_type_to_band(t_u8 radio_type) above
+ *
+ *  @param cfg_band:  band configured
+ *         scan_band: band from scan result
+ *
+ *  @return  matched: non-zero. unmatched: 0
+ *
+ */
+static t_u8
+wlan_is_band_compatible(t_u8 cfg_band, t_u8 scan_band)
+{
+	t_u8 band;
+	switch (scan_band) {
+	case BAND_A:
+		band = BAND_A | BAND_AN | BAND_AAC;
+		break;
+	case BAND_G:
+	default:
+		band = BAND_B | BAND_G | BAND_GN | BAND_GAC;
+	}
+	return cfg_band & band;
+}
+
+/**
+ *  @brief This function finds the best SSID in the Scan List
+ *
+ *  Search the scan table for the best SSID that also matches the current
+ *   adapter network preference (infrastructure or adhoc)
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @return             index in BSSID list
+ */
+static t_s32
+wlan_find_best_network_in_list(IN mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u32 mode = pmpriv->bss_mode;
+	t_s32 best_net = -1;
+	t_s32 best_rssi = 0;
+	t_u32 i;
+
+	ENTER();
+
+	PRINTM(MINFO, "Num of BSSIDs = %d\n", pmadapter->num_in_scan_table);
+
+	for (i = 0; i < pmadapter->num_in_scan_table; i++) {
+		switch (mode) {
+		case MLAN_BSS_MODE_INFRA:
+		case MLAN_BSS_MODE_IBSS:
+			if (wlan_is_network_compatible(pmpriv, i, mode) >= 0) {
+				if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+				    best_rssi) {
+					best_rssi =
+						SCAN_RSSI(pmadapter->
+							  pscan_table[i].rssi);
+					best_net = i;
+				}
+			}
+			break;
+		case MLAN_BSS_MODE_AUTO:
+		default:
+			if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+			    best_rssi) {
+				best_rssi =
+					SCAN_RSSI(pmadapter->pscan_table[i].
+						  rssi);
+				best_net = i;
+			}
+			break;
+		}
+	}
+
+	LEAVE();
+	return best_net;
+}
+
+/**
+ *  @brief Create a channel list for the driver to scan based on region info
+ *
+ *  Use the driver region/band information to construct a comprehensive list
+ *    of channels to scan.  This routine is used for any scan that is not
+ *    provided a specific channel list to scan.
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param puser_scan_in    MNULL or pointer to scan configuration parameters
+ *  @param pscan_chan_list  Output parameter: Resulting channel list to scan
+ *  @param filtered_scan    Flag indicating whether or not a BSSID or SSID filter
+ *                          is being sent in the command to firmware.  Used to
+ *                          increase the number of channels sent in a scan
+ *                          command and to disable the firmware channel scan
+ *                          filter.
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_scan_create_channel_list(IN mlan_private *pmpriv,
+			      IN const wlan_user_scan_cfg *puser_scan_in,
+			      OUT ChanScanParamSet_t *pscan_chan_list,
+			      IN 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;
+
+	ENTER();
+
+	for (region_idx = 0;
+	     region_idx < NELEMENTS(pmadapter->region_channel); region_idx++) {
+
+		if (wlan_11d_is_enabled(pmpriv) &&
+		    pmpriv->media_connected != MTRUE) {
+			/* Scan all the supported chan for the first scan */
+			if (!pmadapter->universal_channel[region_idx].valid)
+				continue;
+			pscan_region =
+				&pmadapter->universal_channel[region_idx];
+		} else {
+			if (!pmadapter->region_channel[region_idx].valid)
+				continue;
+			pscan_region = &pmadapter->region_channel[region_idx];
+		}
+
+		if (puser_scan_in && !puser_scan_in->chan_list[0].chan_number &&
+		    puser_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
+			radio_type =
+				puser_scan_in->chan_list[0].
+				radio_type & ~BAND_SPECIFIED;
+			if (!radio_type && (pscan_region->band != BAND_B) &&
+			    (pscan_region->band != BAND_G))
+				continue;
+			if (radio_type && (pscan_region->band != BAND_A))
+				continue;
+		}
+		if ((puser_scan_in &&
+		     (puser_scan_in->bss_mode == MLAN_SCAN_MODE_IBSS)) ||
+		    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+			band = pmadapter->adhoc_start_band;
+		else
+			band = pmpriv->config_bands;
+		if (!wlan_is_band_compatible(band, pscan_region->band))
+			continue;
+		for (next_chan = 0;
+		     next_chan < pscan_region->num_cfp;
+		     next_chan++, chan_idx++) {
+			/* 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;
+
+			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;
+				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) {
+				pscan_chan_list[chan_idx].max_scan_time =
+					wlan_cpu_to_le16((t_u16)puser_scan_in->
+							 chan_list[0].
+							 scan_time);
+			} else if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				pscan_chan_list[chan_idx].max_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 passive_scan_time);
+			} else if (filtered_scan) {
+				pscan_chan_list[chan_idx].max_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 specific_scan_time);
+			} else {
+				pscan_chan_list[chan_idx].max_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 active_scan_time);
+			}
+
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				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;
+
+			if (filtered_scan) {
+				pscan_chan_list[chan_idx].chan_scan_mode.
+					disable_chan_filt = MTRUE;
+			}
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares command of sending acs.
+ *
+ *  @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_acs(IN pmlan_private pmpriv,
+	     IN HostCmd_DS_COMMAND *cmd,
+	     IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	mlan_ds_misc_acs *acs_param = (mlan_ds_misc_acs *) pdata_buf;
+	HostCmd_DS_ACS *acs_cmd = (HostCmd_DS_ACS *) & cmd->params.acs;
+	t_u8 *ptlv_pos = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchanlist_tlv = MNULL;
+	MrvlIEtypes_ScanChanGap_t *pscangap_tlv = MNULL;
+	t_u32 buf_size = 0;
+	ChanScanParamSet_t *pscan_chan_list = MNULL;
+	t_u32 i = 0;
+	t_u32 scan_type = 0;
+	t_u16 scan_dur = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ACS);
+	cmd->size = sizeof(HostCmd_DS_ACS) + S_DS_GEN;
+
+	buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
+	status = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
+				  MLAN_MEM_DEF, (t_u8 **)&pscan_chan_list);
+	if (status != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
+		PRINTM(MERROR,
+		       "wlan_cmd_acs: Failed to allocate scan_chan_list\n");
+		goto done;
+	}
+	memset(pmadapter, pscan_chan_list, 0x00, buf_size);
+
+    /** Prepare channel list, we will use it to fill into MrvlIEtypes_ChanListParamSet_t */
+	if (acs_param->ch_stats_num) {
+		PRINTM(MCMND, "ACS using user specified channels\n");
+		for (i = 0; i < MIN(MAX_CH_STATS, acs_param->ch_stats_num); i++) {
+			if (!acs_param->ch_stats[i].chan_num)
+				continue;
+
+	    /** Set the fields in pscan_chan_list */
+	    /** Set chan_number */
+			pscan_chan_list[i].chan_number =
+				acs_param->ch_stats[i].chan_num;
+
+	    /** Set bandcfg */
+			if (acs_param->ch_stats[i].chan_num <= 14)
+				pscan_chan_list[i].bandcfg.chanBand = BAND_2GHZ;
+			else
+				pscan_chan_list[i].bandcfg.chanBand = BAND_5GHZ;
+			if (pscan_chan_list[i].bandcfg.chanBand == BAND_5GHZ) {
+				if (pmadapter->fw_bands & BAND_A)
+					PRINTM(MINFO,
+					       "UserScan request for A Band channel %d!!\n",
+					       pscan_chan_list[i].chan_number);
+				else {
+					PRINTM(MERROR,
+					       "Scan in A band is not allowed!!\n");
+					status = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+			}
+
+	    /** Set chan_scan_mode */
+			scan_type = pmadapter->scan_type;
+	    /** Prevent active scanning on a radar controlled channel */
+			if (pscan_chan_list[i].bandcfg.chanBand == BAND_5GHZ) {
+				if (pmadapter->active_scan_triggered == MFALSE)
+					if (wlan_11h_radar_detect_required
+					    (pmpriv,
+					     pscan_chan_list[i].chan_number))
+						scan_type =
+							MLAN_SCAN_TYPE_PASSIVE;
+			}
+			if (pscan_chan_list[i].bandcfg.chanBand == BAND_2GHZ) {
+				if (pmadapter->active_scan_triggered == MFALSE)
+					if (wlan_bg_scan_type_is_passive
+					    (pmpriv,
+					     pscan_chan_list[i].chan_number))
+						scan_type =
+							MLAN_SCAN_TYPE_PASSIVE;
+			}
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				pscan_chan_list[i].chan_scan_mode.passive_scan =
+					MTRUE;
+				pscan_chan_list[i].chan_scan_mode.
+					hidden_ssid_report = MTRUE;
+			} else
+				pscan_chan_list[i].chan_scan_mode.passive_scan =
+					MFALSE;
+
+	    /** Set min_scan_time & max_scan_time */
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
+				scan_dur = pmadapter->passive_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;
+			pscan_chan_list[i].min_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+			pscan_chan_list[i].max_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+		}
+	} else {
+		PRINTM(MCMND, "ACS using full region channel list\n");
+		wlan_scan_create_channel_list(pmpriv, MNULL, pscan_chan_list,
+					      MFALSE);
+	}
+
+	ptlv_pos = acs_cmd->tlv_buffer;
+
+	if (!pscan_chan_list[0].chan_number) {
+		PRINTM(MERROR, "No valid chan_number in pscan_chan_list\n");
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pchanlist_tlv = (MrvlIEtypes_ChanListParamSet_t *)ptlv_pos;
+	pchanlist_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+	pchanlist_tlv->header.len = 0;
+	PRINTM(MCMND, "--- pscan_chan_list ---\n");
+	for (i = 0;
+	     i < WLAN_USER_SCAN_CHAN_MAX && pscan_chan_list[i].chan_number;
+	     i++) {
+		memcpy(pmadapter, &(pchanlist_tlv->chan_scan_param[i]),
+		       &(pscan_chan_list[i]), sizeof(ChanScanParamSet_t));
+		pchanlist_tlv->header.len += sizeof(ChanScanParamSet_t);
+		PRINTM(MCMND,
+		       "[%d] chan_number=%d bandcfg=0x%x chan_scan_mode=0x%x scan_time=%d~%d\n",
+		       i, pscan_chan_list[i].chan_number,
+		       pscan_chan_list[i].bandcfg,
+		       pscan_chan_list[i].chan_scan_mode,
+		       pscan_chan_list[i].min_scan_time,
+		       pscan_chan_list[i].max_scan_time);
+	}
+	ptlv_pos += sizeof(pchanlist_tlv->header) + pchanlist_tlv->header.len;
+	pchanlist_tlv->header.len = wlan_cpu_to_le16(pchanlist_tlv->header.len);
+
+	pscangap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
+	pscangap_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
+	pscangap_tlv->header.len = sizeof(pscangap_tlv->gap);
+	pscangap_tlv->gap = wlan_cpu_to_le16(acs_param->scan_chan_gap);
+	ptlv_pos += sizeof(pscangap_tlv->header) + pscangap_tlv->header.len;
+	pscangap_tlv->header.len = wlan_cpu_to_le16(pscangap_tlv->header.len);
+
+	cmd->size += ptlv_pos - acs_cmd->tlv_buffer;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+done:
+	if (pscan_chan_list)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pscan_chan_list);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function handles the command response of acs
+ *
+ *  @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_acs(IN pmlan_private pmpriv,
+	     IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *cfg = MNULL;
+	mlan_ds_misc_acs *acs_param = MNULL;
+	HostCmd_DS_ACS *acs_cmd = (HostCmd_DS_ACS *) & resp->params.acs;
+	int left_len = resp->size;
+	t_u8 *tlv_pos = MNULL;
+	MrvlIEtypesHeader_t *tlv_ie = MNULL;
+	MrvlIEtypes_ChannelStats_t *tlv_ch_stats = MNULL;
+	ChanStatistics_t *ch_stats = MNULL;
+	int ch_stats_num = 0;
+	int i = 0;
+	t_u16 tlv_id = 0;
+	int tlv_ie_len = 0;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		acs_param = &cfg->param.acs;
+		memset(pmpriv->adapter, acs_param, 0x00, sizeof(*acs_param));
+		acs_param->best_ch = acs_cmd->best_ch;
+
+		left_len -= S_DS_GEN + sizeof(HostCmd_DS_ACS);
+		tlv_pos = acs_cmd->tlv_buffer;
+		while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+			tlv_ie = (MrvlIEtypesHeader_t *)(tlv_pos);
+			tlv_id = wlan_le16_to_cpu(tlv_ie->type);
+			tlv_ie_len = wlan_le16_to_cpu(tlv_ie->len);
+			PRINTM(MCMND, "[TLV: id=0x%x len=%d]  left_len=%d\n",
+			       tlv_id, tlv_ie_len, left_len);
+			if ((tlv_id == TLV_TYPE_CHANNEL_STATS) &&
+			    (tlv_ie_len >= sizeof(ChanStatistics_t))) {
+				tlv_ch_stats =
+					(MrvlIEtypes_ChannelStats_t *)tlv_ie;
+				ch_stats = tlv_ch_stats->chanStat;
+				ch_stats_num =
+					tlv_ie_len / sizeof(ChanStatistics_t);
+				for (i = 0; i < MIN(ch_stats_num, MAX_CH_STATS);
+				     i++) {
+					if (ch_stats[i].chan_num) {
+						acs_param->ch_stats[i].
+							chan_num =
+							ch_stats[i].chan_num;
+						acs_param->ch_stats[i].
+							total_networks =
+							wlan_le16_to_cpu
+							(ch_stats[i].
+							 total_networks);
+						acs_param->ch_stats[i].
+							cca_busy_duration =
+							wlan_le16_to_cpu
+							(ch_stats[i].
+							 cca_busy_duration);
+						acs_param->ch_stats_num++;
+					}
+				}
+				if (acs_param->ch_stats_num)
+					break;
+			}
+			left_len -= sizeof(*tlv_ie) + tlv_ie_len;
+			tlv_pos += sizeof(*tlv_ie) + tlv_ie_len;
+		}
+
+		/* Indicate ioctl complete */
+		pioctl_buf->data_read_written = sizeof(*acs_param);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN mlan_private *pmpriv, OUT 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(pmpriv->adapter, *pptlv_out,
+		       pmpriv->wps.wps_ie.vend_hdr.oui,
+		       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(IN mlan_private *pmpriv,
+		       IN t_void *pioctl_buf,
+		       IN t_u32 max_chan_per_scan,
+		       IN t_u8 filtered_scan,
+		       OUT wlan_scan_cmd_config *pscan_cfg_out,
+		       OUT MrvlIEtypes_ChanListParamSet_t *pchan_tlv_out,
+		       IN ChanScanParamSet_t *pscan_chan_list)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	ChanScanParamSet_t *ptmp_chan_list;
+	ChanScanParamSet_t *pstart_chan;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+	t_u8 *pchan_tlv_out_temp = MNULL;
+	t_u8 *ptlv_temp = MNULL;
+	t_bool foundJPch14 = MFALSE;
+	t_u16 tlv_buf_len = 0;
+	t_u32 tlv_idx;
+	t_u32 total_scan_time;
+	t_u32 done_early;
+	t_u32 cmd_no;
+	t_u32 first_chan = 1;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+
+	if (!pscan_cfg_out || !pchan_tlv_out || !pscan_chan_list) {
+		PRINTM(MINFO, "Scan: Null detect: %p, %p, %p\n",
+		       pscan_cfg_out, pchan_tlv_out, pscan_chan_list);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (!pscan_chan_list->chan_number) {
+		PRINTM(MERROR, "Scan: No channel configured\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* check expiry before preparing scan list - may affect blacklist */
+	wlan_11h_get_csa_closed_channel(pmpriv);
+
+	pchan_tlv_out->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+
+	/* Set the temp channel struct pointer to the start of the desired list */
+	ptmp_chan_list = pscan_chan_list;
+
+	/*
+	 * Loop through the desired channel list, sending a new firmware scan
+	 * commands for each max_chan_per_scan channels (or for 1,6,11
+	 * individually if configured accordingly)
+	 */
+	while (ptmp_chan_list->chan_number) {
+
+		tlv_idx = 0;
+		total_scan_time = 0;
+		pchan_tlv_out->header.len = 0;
+		pstart_chan = ptmp_chan_list;
+		done_early = MFALSE;
+
+		/*
+		 * Construct the Channel TLV for the scan command.  Continue to
+		 * insert channel TLVs until:
+		 *   - the tlv_idx hits the maximum configured per scan command
+		 *   - the next channel to insert is 0 (end of desired
+		 *     channel list)
+		 *   - done_early is set (controlling individual
+		 *     scanning of 1,6,11)
+		 */
+		while (tlv_idx < max_chan_per_scan &&
+		       ptmp_chan_list->chan_number && !done_early) {
+			if (wlan_is_chan_blacklisted
+			    (pmpriv,
+			     radio_type_to_band(ptmp_chan_list->bandcfg.
+						chanBand),
+			     ptmp_chan_list->chan_number) ||
+			    wlan_is_chan_disabled(pmpriv,
+						  radio_type_to_band
+						  (ptmp_chan_list->bandcfg.
+						   chanBand),
+						  ptmp_chan_list->
+						  chan_number)) {
+				ptmp_chan_list++;
+				continue;
+			}
+
+			if (first_chan) {
+				ptmp_chan_list->chan_scan_mode.first_chan =
+					MTRUE;
+				first_chan = 0;
+			}
+
+			PRINTM(MINFO,
+			       "Scan: Chan(%3d), bandcfg(%x), Mode(%d,%d), Dur(%d)\n",
+			       ptmp_chan_list->chan_number,
+			       ptmp_chan_list->bandcfg,
+			       ptmp_chan_list->chan_scan_mode.passive_scan,
+			       ptmp_chan_list->chan_scan_mode.disable_chan_filt,
+			       wlan_le16_to_cpu(ptmp_chan_list->max_scan_time));
+
+			if (foundJPch14 == MTRUE) {
+				foundJPch14 = MFALSE;
+				/* Restore the TLV buffer */
+				pchan_tlv_out =
+					(MrvlIEtypes_ChanListParamSet_t *)
+					pchan_tlv_out_temp;
+				pchan_tlv_out->header.type =
+					wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+				pchan_tlv_out->header.len = 0;
+				if (ptlv_temp) {
+					memcpy(pmadapter,
+					       pscan_cfg_out->tlv_buf,
+					       ptlv_temp, 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(pmadapter, ptlv_temp, ptlv_pos,
+				       tlv_buf_len);
+
+				/* 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(pmadapter,
+			       pchan_tlv_out->chan_scan_param + tlv_idx,
+			       ptmp_chan_list,
+			       sizeof(pchan_tlv_out->chan_scan_param));
+
+			/* Increment the TLV header length by the size appended */
+			pchan_tlv_out->header.len +=
+				sizeof(pchan_tlv_out->chan_scan_param);
+
+			/*
+			 * The tlv buffer length is set to the number of
+			 * bytes of the between the channel tlv pointer
+			 * and the start of the tlv buffer.  This
+			 * compensates for any TLVs that were appended
+			 * before the channel list.
+			 */
+			pscan_cfg_out->tlv_buf_len =
+				(t_u32)((t_u8 *)pchan_tlv_out -
+					pscan_cfg_out->tlv_buf);
+
+			/* Add the size of the channel tlv header and the data length */
+			pscan_cfg_out->tlv_buf_len +=
+				(sizeof(pchan_tlv_out->header)
+				 + pchan_tlv_out->header.len);
+
+			/* Increment the index to the channel tlv we are constructing */
+			tlv_idx++;
+
+			/* Count the total scan time per command */
+			total_scan_time +=
+				wlan_le16_to_cpu(ptmp_chan_list->max_scan_time);
+
+			done_early = MFALSE;
+
+			/*
+			 * Stop the loop if the *current* channel is in the 1,6,11 set
+			 * and we are not filtering on a BSSID or SSID.
+			 */
+			if (!filtered_scan &&
+			    (ptmp_chan_list->chan_number == 1 ||
+			     ptmp_chan_list->chan_number == 6 ||
+			     ptmp_chan_list->chan_number == 11)) {
+				done_early = MTRUE;
+			}
+
+			/*
+			 * Stop the loop if the *current* channel is 14
+			 * and region code is Japan (0x40 or 0xFF)
+			 */
+			if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
+			     pmadapter->region_code == COUNTRY_CODE_JP_FF)
+			    && (ptmp_chan_list->chan_number == 14)) {
+				done_early = MTRUE;
+			}
+
+			/* Increment the tmp pointer to the next channel to be scanned */
+			ptmp_chan_list++;
+
+			/*
+			 * Stop the loop if the *next* channel is in the 1,6,11 set.
+			 * This will cause it to be the only channel scanned on the next
+			 * interation
+			 */
+			if (!filtered_scan &&
+			    (ptmp_chan_list->chan_number == 1 ||
+			     ptmp_chan_list->chan_number == 6 ||
+			     ptmp_chan_list->chan_number == 11)) {
+				done_early = MTRUE;
+			}
+
+			/*
+			 * Stop the loop if the *next* channel is 14
+			 * and region code is Japan (0x40 or 0xFF)
+			 */
+			if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
+			     pmadapter->region_code == COUNTRY_CODE_JP_FF)
+			    && (ptmp_chan_list->chan_number == 14)) {
+				done_early = MTRUE;
+			}
+			if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+			    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE)
+				done_early = MFALSE;
+		}
+
+		/* The total scan time should be less than scan command timeout value */
+		if (total_scan_time > MRVDRV_MAX_TOTAL_SCAN_TIME) {
+			PRINTM(MMSG,
+			       "Total scan time %d ms is over limit (%d ms), scan skipped\n",
+			       total_scan_time, MRVDRV_MAX_TOTAL_SCAN_TIME);
+			if (pioctl_req)
+				pioctl_req->status_code =
+					MLAN_ERROR_CMD_SCAN_FAIL;
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+
+		pchan_tlv_out->header.len =
+			wlan_cpu_to_le16(pchan_tlv_out->header.len);
+
+		pmadapter->pscan_channels = pstart_chan;
+
+		/* Send the scan command to the firmware with the specified cfg */
+		if (pmadapter->ext_scan)
+			cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
+		else
+			cmd_no = HostCmd_CMD_802_11_SCAN;
+		ret = wlan_prepare_cmd(pmpriv,
+				       cmd_no,
+				       HostCmd_ACT_GEN_SET,
+				       0, MNULL, pscan_cfg_out);
+		if (ret)
+			break;
+	}
+
+	LEAVE();
+
+	if (ptlv_temp)
+		pcb->moal_mfree(pmadapter->pmoal_handle, ptlv_temp);
+
+	if (ret)
+		return MLAN_STATUS_FAILURE;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Construct a wlan_scan_cmd_config structure to use in scan commands
+ *
+ *  Application layer or other functions can invoke wlan_scan_networks
+ *    with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
+ *    This structure is used as the basis of one or many wlan_scan_cmd_config
+ *    commands that are sent to the command processing module and sent to
+ *    firmware.
+ *
+ *  Create a wlan_scan_cmd_config based on the following user supplied
+ *    parameters (if present):
+ *             - SSID filter
+ *             - BSSID filter
+ *             - Number of Probes to be sent
+ *             - Channel list
+ *
+ *  If the SSID or BSSID filter is not present, disable/clear the filter.
+ *  If the number of probes is not set, use the adapter default setting
+ *  Qualify the channel
+ *
+ *  @param pmpriv              A pointer to mlan_private structure
+ *  @param puser_scan_in       MNULL or pointer to scan config parameters
+ *  @param pscan_cfg_out       Output parameter: Resulting scan configuration
+ *  @param ppchan_list_out     Output parameter: Pointer to the start of the
+ *                             channel TLV portion of the output scan config
+ *  @param pscan_chan_list     Output parameter: Pointer to the resulting
+ *                             channel list to scan
+ *  @param pmax_chan_per_scan  Output parameter: Number of channels to scan for
+ *                             each issuance of the firmware scan command
+ *  @param pfiltered_scan      Output parameter: Flag indicating whether or not
+ *                             a BSSID or SSID filter is being sent in the
+ *                             command to firmware. Used to increase the number
+ *                             of channels sent in a scan command and to
+ *                             disable the firmware channel scan filter.
+ *  @param pscan_current_only  Output parameter: Flag indicating whether or not
+ *                             we are only scanning our current active channel
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_scan_setup_scan_config(IN mlan_private *pmpriv,
+			    IN wlan_user_scan_cfg *puser_scan_in,
+			    OUT wlan_scan_cmd_config *pscan_cfg_out,
+			    OUT MrvlIEtypes_ChanListParamSet_t
+			    **ppchan_list_out,
+			    OUT ChanScanParamSet_t *pscan_chan_list,
+			    OUT t_u8 *pmax_chan_per_scan,
+			    OUT t_u8 *pfiltered_scan,
+			    OUT 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;
+	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(pmadapter, pscan_cfg_out->specific_bssid,
+		       puser_scan_in->specific_bssid,
+		       sizeof(pscan_cfg_out->specific_bssid));
+
+		if (pmadapter->ext_scan
+		    && 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 = MLAN_MAC_ADDR_LENGTH;
+			memcpy(pmadapter, pbssid_tlv->bssid,
+			       puser_scan_in->specific_bssid,
+			       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(pmadapter, pwildcard_ssid_tlv->ssid,
+			       puser_scan_in->ssid_list[ssid_idx].ssid,
+			       MIN(MLAN_MAX_SSID_LENGTH, ssid_len));
+
+			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 && puser_scan_in->scan_chan_gap) {
+		*pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+		PRINTM(MINFO, "Scan: channel gap = %d\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);
+	}
+	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(pmadapter, prates_tlv->rates, rates, 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);
+		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 (wlan_is_ext_capa_support(pmpriv))
+		wlan_add_ext_capa_info_ie(pmpriv, &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(pmadapter, randomMacParam->mac,
+		       puser_scan_in->random_mac, 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;
+
+				}
+			}
+
+			/* Prevent active scanning on a radar controlled channel */
+			if (radio_type == BAND_5GHZ) {
+				if (pmadapter->active_scan_triggered == MFALSE)
+					if (wlan_11h_radar_detect_required
+					    (pmpriv, channel)) {
+						scan_type =
+							MLAN_SCAN_TYPE_PASSIVE;
+					}
+			}
+			if (radio_type == BAND_2GHZ) {
+				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) {
+				(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_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;
+			(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);
+			if (*pfiltered_scan) {
+				(pscan_chan_list +
+				 chan_list_idx)->chan_scan_mode.
+		      disable_chan_filt = MTRUE;
+			}
+			chan_list_idx++;
+		}
+
+		/* Check if we are only scanning the current channel */
+		if ((chan_idx == 1)
+		    && (puser_scan_in->chan_list[0].chan_number
+			== pmpriv->curr_bss_params.bss_descriptor.channel)) {
+			*pscan_current_only = MTRUE;
+			PRINTM(MINFO, "Scan: Scanning current channel only\n");
+		}
+
+	} else {
+		PRINTM(MINFO, "Scan: Creating full region channel list\n");
+		wlan_scan_create_channel_list(pmpriv, puser_scan_in,
+					      pscan_chan_list, *pfiltered_scan);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Inspect the scan response buffer for pointers to expected TLVs
+ *
+ *  TLVs can be included at the end of the scan response BSS information.
+ *    Parse the data in the buffer for pointers to TLVs that can potentially
+ *    be passed back in the response
+ *
+ *  @param pmadapter        Pointer to the mlan_adapter structure
+ *  @param ptlv             Pointer to the start of the TLV buffer to parse
+ *  @param tlv_buf_size     Size of the TLV buffer
+ *  @param req_tlv_type     Request TLV's type
+ *  @param pptlv            Output parameter: Pointer to the request TLV if found
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_ret_802_11_scan_get_tlv_ptrs(IN pmlan_adapter pmadapter,
+				  IN MrvlIEtypes_Data_t *ptlv,
+				  IN t_u32 tlv_buf_size,
+				  IN t_u32 req_tlv_type,
+				  OUT 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(IN pmlan_adapter pmadapter,
+				OUT BSSDescriptor_t *pbss_entry,
+				IN t_u8 **pbeacon_info,
+				IN t_u32 *bytes_left, IN 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 };
+
+	IEEEtypes_CountryInfoSet_t *pcountry_info;
+
+	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(pmadapter, &beacon_size, *pbeacon_info,
+		       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(pmadapter, pbss_entry->mac_address, pcurrent_ptr,
+	       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(pmadapter, fixed_ie.time_stamp, pcurrent_ptr, 8);
+	memcpy(pmadapter, pbss_entry->time_stamp, pcurrent_ptr, 8);
+	pcurrent_ptr += 8;
+	bytes_left_for_current_beacon -= 8;
+
+	/* Beacon interval is 2 bytes long */
+	memcpy(pmadapter, &fixed_ie.beacon_interval, pcurrent_ptr, 2);
+	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(pmadapter, &fixed_ie.capabilities, pcurrent_ptr, 2);
+	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(pmadapter, &pbss_entry->cap_info, pcap_info,
+	       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;
+			continue;
+		}
+
+		switch (element_id) {
+
+		case SSID:
+			if (element_len > MRVDRV_MAX_SSID_LENGTH) {
+				bytes_left_for_current_beacon = 0;
+				continue;
+			}
+			if (!pbss_entry->ssid.ssid_len) {
+				pbss_entry->ssid.ssid_len = element_len;
+				memcpy(pmadapter, pbss_entry->ssid.ssid,
+				       (pcurrent_ptr + 2), element_len);
+			}
+			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;
+				continue;
+			}
+			memcpy(pmadapter, pbss_entry->data_rates,
+			       pcurrent_ptr + 2, element_len);
+			memcpy(pmadapter, pbss_entry->supported_rates,
+			       pcurrent_ptr + 2, element_len);
+			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(pmadapter,
+			       &pbss_entry->phy_param_set.fh_param_set,
+			       pfh_param_set, MIN(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(pmadapter,
+			       &pbss_entry->phy_param_set.ds_param_set,
+			       pds_param_set, MIN(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(pmadapter,
+			       &pbss_entry->ss_param_set.cf_param_set,
+			       pcf_param_set, MIN(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(pmadapter,
+			       &pbss_entry->ss_param_set.ibss_param_set,
+			       pibss_param_set, MIN(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(pmadapter, &pbss_entry->country_info,
+			       pcountry_info, pcountry_info->len + 2);
+			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(pmadapter, prate, pcurrent_ptr + 2,
+				       bytes_to_copy);
+
+				prate = (t_u8 *)pbss_entry->supported_rates;
+				prate += rate_size;
+				memcpy(pmadapter, prate, pcurrent_ptr + 2,
+				       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(pmadapter,
+					       (t_u8 *)&pbss_entry->wmm_ie,
+					       pcurrent_ptr, total_ie_len);
+					HEXDUMP("InterpretIE: Resp WMM_IE",
+						(t_u8 *)&pbss_entry->wmm_ie,
+						total_ie_len);
+				}
+			}
+			break;
+		case RSN_IE:
+			pbss_entry->prsn_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pbss_entry->rsn_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp RSN_IE",
+				(t_u8 *)pbss_entry->prsn_ie,
+				(*(pbss_entry->prsn_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case WAPI_IE:
+			pbss_entry->pwapi_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pbss_entry->wapi_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp WAPI_IE",
+				(t_u8 *)pbss_entry->pwapi_ie,
+				(*(pbss_entry->pwapi_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case HT_CAPABILITY:
+			pbss_entry->pht_cap = (IEEEtypes_HTCap_t *)pcurrent_ptr;
+			pbss_entry->ht_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp HTCAP_IE",
+				(t_u8 *)pbss_entry->pht_cap,
+				(*(pbss_entry->pht_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case HT_OPERATION:
+			pbss_entry->pht_info =
+				(IEEEtypes_HTInfo_t *)pcurrent_ptr;
+			pbss_entry->ht_info_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp HTINFO_IE",
+				(t_u8 *)pbss_entry->pht_info,
+				(*(pbss_entry->pht_info)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case BSSCO_2040:
+			pbss_entry->pbss_co_2040 =
+				(IEEEtypes_2040BSSCo_t *)pcurrent_ptr;
+			pbss_entry->bss_co_2040_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp 2040BSSCOEXISTANCE_IE",
+				(t_u8 *)pbss_entry->pbss_co_2040,
+				(*(pbss_entry->pbss_co_2040)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_CAPABILITY:
+			pbss_entry->pext_cap =
+				(IEEEtypes_ExtCap_t *)pcurrent_ptr;
+			pbss_entry->ext_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTCAP_IE",
+				(t_u8 *)pbss_entry->pext_cap,
+				(*(pbss_entry->pext_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case OVERLAPBSSSCANPARAM:
+			pbss_entry->poverlap_bss_scan_param =
+				(IEEEtypes_OverlapBSSScanParam_t *)pcurrent_ptr;
+			pbss_entry->overlap_bss_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp OBSS_IE",
+				(t_u8 *)pbss_entry->poverlap_bss_scan_param,
+				(*(pbss_entry->poverlap_bss_scan_param)).
+				ieee_hdr.len + sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_CAPABILITY:
+			pbss_entry->pvht_cap =
+				(IEEEtypes_VHTCap_t *)pcurrent_ptr;
+			pbss_entry->vht_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp VHTCAP_IE",
+				(t_u8 *)pbss_entry->pvht_cap,
+				(*(pbss_entry->pvht_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_OPERATION:
+			pbss_entry->pvht_oprat =
+				(IEEEtypes_VHTOprat_t *)pcurrent_ptr;
+			pbss_entry->vht_oprat_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp VHTOPER_IE",
+				(t_u8 *)pbss_entry->pvht_oprat,
+				(*(pbss_entry->pvht_oprat)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_BSS_LOAD:
+			pbss_entry->pext_bssload =
+				(IEEEtypes_ExtBSSload_t *)pcurrent_ptr;
+			pbss_entry->ext_bssload_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTBSSLOAD_IE",
+				(t_u8 *)pbss_entry->pext_bssload,
+				(*(pbss_entry->pext_bssload)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_TX_POWER_ENV:
+			pbss_entry->pvht_txpower =
+				(IEEEtypes_VHTtxpower_t *)pcurrent_ptr;
+			pbss_entry->vht_txpower_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp TXPOW_IE",
+				(t_u8 *)pbss_entry->pvht_txpower,
+				(*(pbss_entry->pvht_txpower)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_POWER_CONSTR:
+			pbss_entry->pext_pwer =
+				(IEEEtypes_ExtPwerCons_t *)pcurrent_ptr;
+			pbss_entry->ext_pwer_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTPOW_IE",
+				(t_u8 *)pbss_entry->pext_pwer,
+				(*(pbss_entry->pext_pwer)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case QUIET_CHAN:
+			pbss_entry->pquiet_chan =
+				(IEEEtypes_QuietChan_t *)pcurrent_ptr;
+			pbss_entry->quiet_chan_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp QUIETCHAN_IE",
+				(t_u8 *)pbss_entry->pquiet_chan,
+				(*(pbss_entry->pquiet_chan)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case BW_CHANNEL_SWITCH:
+			/* RANDYTODO */
+			break;
+		case AID_INFO:
+			break;
+		case OPER_MODE_NTF:
+			pbss_entry->poper_mode =
+				(IEEEtypes_OperModeNtf_t *)pcurrent_ptr;
+			pbss_entry->oper_mode_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp OPERMODENTF_IE",
+				(t_u8 *)pbss_entry->poper_mode,
+				(*(pbss_entry->poper_mode)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case 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(IN mlan_private *pmpriv,
+			    IN 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->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);
+		}
+	} 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->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(IN mlan_private *pmpriv,
+				  IN t_u32 beacon_idx,
+				  IN t_u32 num_of_ent,
+				  IN BSSDescriptor_t *pnew_beacon)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 *pbcn_store;
+	t_u32 new_bcn_size;
+	t_u32 old_bcn_size;
+	t_u32 bcn_space;
+	t_u32 adj_idx;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *tmp_buf;
+	t_u16 bcn_size = 0;
+	t_u32 bcn_offset = 0;
+
+	ENTER();
+
+	if (pmadapter->pscan_table[beacon_idx].pbeacon_buf) {
+
+		new_bcn_size = pnew_beacon->beacon_buf_size;
+		old_bcn_size =
+			pmadapter->pscan_table[beacon_idx].beacon_buf_size;
+		bcn_space =
+			pmadapter->pscan_table[beacon_idx].beacon_buf_size_max;
+		pbcn_store = pmadapter->pscan_table[beacon_idx].pbeacon_buf;
+
+		/* Set the max to be the same as current entry unless changed below */
+		pnew_beacon->beacon_buf_size_max = bcn_space;
+
+		if (new_bcn_size == old_bcn_size) {
+			/*
+			 * Beacon is the same size as the previous entry.
+			 *   Replace the previous contents with the scan result
+			 */
+			memcpy(pmadapter, pbcn_store,
+			       pnew_beacon->pbeacon_buf,
+			       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(pmadapter, pbcn_store, pnew_beacon->pbeacon_buf,
+			       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(pmadapter, pbcn_store, pnew_beacon->pbeacon_buf,
+			       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->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;
+		}
+		/* Point the new entry to its permanent storage space */
+		pnew_beacon->pbeacon_buf = pbcn_store;
+		wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
+	} else {
+		if ((pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+		     SCAN_BEACON_ENTRY_PAD > (pmadapter->bcn_buf +
+					      pmadapter->bcn_buf_size)) &&
+		    (pmadapter->bcn_buf_size < MAX_SCAN_BEACON_BUFFER)) {
+			/* no space for this entry, realloc bcn buffer */
+			ret = pmadapter->callbacks.moal_malloc(pmadapter->
+							       pmoal_handle,
+							       pmadapter->
+							       bcn_buf_size +
+							       DEFAULT_SCAN_BEACON_BUFFER,
+							       MLAN_MEM_DEF,
+							       (t_u8 **)
+							       &tmp_buf);
+
+			if ((ret == MLAN_STATUS_SUCCESS) && (tmp_buf)) {
+				PRINTM(MCMND,
+				       "Realloc Beacon buffer, old size=%d, new_size=%d\n",
+				       pmadapter->bcn_buf_size,
+				       pmadapter->bcn_buf_size +
+				       DEFAULT_SCAN_BEACON_BUFFER);
+				bcn_size =
+					pmadapter->pbcn_buf_end -
+					pmadapter->bcn_buf;
+				memcpy(pmadapter, tmp_buf, pmadapter->bcn_buf,
+				       bcn_size);
+				/* Adjust beacon buffer pointers that are past the current */
+				for (adj_idx = 0; adj_idx < num_of_ent;
+				     adj_idx++) {
+					bcn_offset =
+						pmadapter->pscan_table[adj_idx].
+						pbeacon_buf -
+						pmadapter->bcn_buf;
+					pmadapter->pscan_table[adj_idx].
+						pbeacon_buf =
+						tmp_buf + bcn_offset;
+					wlan_adjust_ie_in_bss_entry(pmpriv,
+								    &pmadapter->
+								    pscan_table
+								    [adj_idx]);
+				}
+				pmadapter->pbcn_buf_end = tmp_buf + bcn_size;
+				pmadapter->callbacks.moal_mfree(pmadapter->
+								pmoal_handle,
+								(t_u8 *)
+								pmadapter->
+								bcn_buf);
+				pmadapter->bcn_buf = tmp_buf;
+				pmadapter->bcn_buf_size +=
+					DEFAULT_SCAN_BEACON_BUFFER;
+			}
+		}
+		/*
+		 * No existing beacon data exists for this entry, check to see
+		 *   if we can fit it in the remaining space
+		 */
+		if (pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+		    SCAN_BEACON_ENTRY_PAD < (pmadapter->bcn_buf +
+					     pmadapter->bcn_buf_size)) {
+
+			/*
+			 * Copy the beacon buffer data from the local entry
+			 * to the adapter dev struct buffer space used to
+			 * store the raw beacon data for each entry in the
+			 * scan table
+			 */
+			memcpy(pmadapter, pmadapter->pbcn_buf_end,
+			       pnew_beacon->pbeacon_buf,
+			       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(IN 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);
+		}
+
+		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 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(IN 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(pmadapter, &pmadapter->pscan_table[j].ssid,
+			       &pmpriv->curr_bss_params.bss_descriptor.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.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.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(pmadapter,
+			       &pmpriv->curr_bss_params.bss_descriptor,
+			       &pmadapter->pscan_table[j],
+			       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(pmadapter, bss_new_entry,
+					       &pmpriv->curr_bss_params.
+					       bss_descriptor,
+					       sizeof(pmpriv->curr_bss_params.
+						      bss_descriptor));
+					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(pmadapter,
+						       &pmadapter->
+						       pscan_table[pmadapter->
+								   num_in_scan_table
+								   - 1],
+						       bss_new_entry,
+						       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);
+
+	/*
+	 * 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(IN mlan_private *pmpriv, IN 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(pmadapter, pmadapter->pscan_table + del_idx,
+		       pmadapter->pscan_table + del_idx + 1,
+		       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].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);
+			}
+		}
+	}
+
+	/* The last entry is invalid now that it has been deleted or moved back */
+	memset(pmadapter,
+	       pmadapter->pscan_table + pmadapter->num_in_scan_table - 1, 0x00,
+	       sizeof(BSSDescriptor_t));
+
+	pmadapter->num_in_scan_table--;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Delete all occurrences of a given SSID from the scan table
+ *
+ *  Iterate through the scan table and delete all entries that match a given
+ *    SSID.  Compact the remaining scan table entries.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pdel_ssid    Pointer to an SSID to be used in deleting all
+ *                        matching SSIDs from the scan table
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_scan_delete_ssid_table_entry(IN mlan_private *pmpriv,
+				  IN 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(IN mlan_private *pmpriv,
+			   IN t_u32 index, IN 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 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 ((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)
+				) {
+
+				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->adhoc_aes_enabled &&
+		    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
+			   && !pmpriv->adhoc_aes_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))
+			   && !pmpriv->adhoc_aes_enabled
+			   /*
+			    * Privacy bit may NOT be set in some APs like
+			    * LinkSys WRT54G && pbss_desc->privacy
+			    */
+			) {
+			/* WPA enabled */
+			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))
+			   && !pmpriv->adhoc_aes_enabled
+			   /*
+			    * 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)
+				) {
+				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 {
+					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->adhoc_aes_enabled &&
+			   pmpriv->sec_info.encryption_mode ==
+			   MLAN_ENCRYPTION_MODE_NONE && pbss_desc->privacy) {
+			/* Ad-hoc AES enabled */
+			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->adhoc_aes_enabled &&
+			   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(IN 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(IN mlan_private *pmpriv,
+		   IN t_void *pioctl_buf, IN wlan_user_scan_cfg *puser_scan_in)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	wlan_scan_cmd_config_tlv *pscan_cfg_out = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchan_list_out;
+	t_u32 buf_size;
+	ChanScanParamSet_t *pscan_chan_list;
+
+	t_u8 keep_previous_scan;
+	t_u8 filtered_scan;
+	t_u8 scan_current_chan_only;
+	t_u8 max_chan_per_scan;
+	t_u8 i;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(wlan_scan_cmd_config_tlv), MLAN_MEM_DEF,
+			       (t_u8 **)&pscan_cfg_out);
+	if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg_out) {
+		PRINTM(MERROR, "Memory allocation for pscan_cfg_out failed!\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF,
+			       (t_u8 **)&pscan_chan_list);
+	if (ret != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
+		PRINTM(MERROR, "Failed to allocate scan_chan_list\n");
+		if (pscan_cfg_out)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_cfg_out);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(pmadapter, pscan_chan_list, 0x00, buf_size);
+	memset(pmadapter, pscan_cfg_out, 0x00,
+	       sizeof(wlan_scan_cmd_config_tlv));
+
+	keep_previous_scan = MFALSE;
+
+	ret = wlan_scan_setup_scan_config(pmpriv,
+					  puser_scan_in,
+					  &pscan_cfg_out->config,
+					  &pchan_list_out,
+					  pscan_chan_list,
+					  &max_chan_per_scan,
+					  &filtered_scan,
+					  &scan_current_chan_only);
+	if (ret != MLAN_STATUS_SUCCESS) {
+
+		PRINTM(MERROR, "Failed to setup scan config\n");
+		if (pscan_cfg_out)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_cfg_out);
+		if (pscan_chan_list)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_chan_list);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (puser_scan_in)
+		keep_previous_scan = puser_scan_in->keep_previous_scan;
+
+	if (keep_previous_scan == MFALSE) {
+		memset(pmadapter, pmadapter->pscan_table, 0x00,
+		       sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
+		pmadapter->num_in_scan_table = 0;
+		pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+		for (i = 0; i < pmadapter->num_in_chan_stats; i++)
+			pmadapter->pchan_stats[i].cca_scan_duration = 0;
+		pmadapter->idx_chan_stats = 0;
+	}
+
+	ret = wlan_scan_channel_list(pmpriv,
+				     pioctl_buf,
+				     max_chan_per_scan,
+				     filtered_scan,
+				     &pscan_cfg_out->config,
+				     pchan_list_out, pscan_chan_list);
+
+	/* Get scan command from scan_pending_q and put to cmd_pending_q */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+			wlan_request_cmd_lock(pmadapter);
+			pmadapter->pscan_ioctl_req = pioctl_req;
+			pmadapter->scan_processing = MTRUE;
+			wlan_release_cmd_lock(pmadapter);
+		} else {
+			wlan_request_cmd_lock(pmadapter);
+			if (util_peek_list
+			    (pmadapter->pmoal_handle,
+			     &pmadapter->scan_pending_q, MNULL, MNULL)) {
+				pcmd_node =
+					(cmd_ctrl_node *)
+					util_dequeue_list(pmadapter->
+							  pmoal_handle,
+							  &pmadapter->
+							  scan_pending_q, MNULL,
+							  MNULL);
+				pmadapter->pscan_ioctl_req = pioctl_req;
+				pmadapter->scan_processing = MTRUE;
+				wlan_insert_cmd_to_pending_q(pmadapter,
+							     pcmd_node, MTRUE);
+			}
+			wlan_release_cmd_lock(pmadapter);
+		}
+	}
+	if (pscan_cfg_out)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_cfg_out);
+
+	if (pscan_chan_list)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pscan_chan_list);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Prepare a scan command to be sent to the firmware
+ *
+ *  Use the wlan_scan_cmd_config sent to the command processing module in
+ *   the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN command
+ *   struct to send to firmware.
+ *
+ *  The fixed fields specifying the BSS type and BSSID filters as well as a
+ *   variable number/length of TLVs are sent in the command to firmware.
+ *
+ *  @param pmpriv     A pointer to mlan_private structure
+ *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
+ *                    firmware with the HostCmd_DS_801_11_SCAN structure
+ *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
+ *                    to set the fields/TLVs for the command sent to firmware
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_scan(IN mlan_private *pmpriv,
+		     IN HostCmd_DS_COMMAND *pcmd, IN 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(pmpriv->adapter, pscan_cmd->bssid, pscan_cfg->specific_bssid,
+	       sizeof(pscan_cmd->bssid));
+	memcpy(pmpriv->adapter, pscan_cmd->tlv_buffer, pscan_cfg->tlv_buf,
+	       pscan_cfg->tlv_buf_len);
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN);
+
+	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+	pcmd->size = (t_u16)wlan_cpu_to_le16((t_u16)(sizeof(pscan_cmd->bss_mode)
+						     + sizeof(pscan_cmd->bssid)
+						     + pscan_cfg->tlv_buf_len
+						     + S_DS_GEN));
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief  Check if any hidden SSID found in passive scan channels
+ *          and do specific SSID active scan for those channels
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MTRUE/MFALSE
+ */
+
+t_bool
+wlan_active_scan_req_for_passive_chan(IN mlan_private *pmpriv,
+				      IN 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(pmpriv->adapter, user_scan_cfg->ssid_list,
+			       puser_scan_in->ssid_list,
+			       sizeof(user_scan_cfg->ssid_list));
+		} else {
+			pscan_req = &pscan->param.scan_req;
+			memcpy(pmpriv->adapter,
+			       user_scan_cfg->ssid_list[0].ssid,
+			       pscan_req->scan_ssid.ssid,
+			       pscan_req->scan_ssid.ssid_len);
+		}
+		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(IN mlan_private *pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = MNULL;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	HostCmd_DS_802_11_SCAN_RSP *pscan_rsp = MNULL;
+	BSSDescriptor_t *bss_new_entry = MNULL;
+	MrvlIEtypes_Data_t *ptlv;
+	MrvlIEtypes_TsfTimestamp_t *ptsf_tlv = MNULL;
+	MrvlIEtypes_ChannelStats_t *pchanstats_tlv = MNULL;
+	t_u8 *pbss_info;
+	t_u32 scan_resp_size;
+	t_u32 bytes_left;
+	t_u32 num_in_table;
+	t_u32 bss_idx;
+	t_u32 idx;
+	t_u32 tlv_buf_size;
+	t_u64 tsf_val;
+	chan_freq_power_t *cfp;
+	MrvlIEtypes_ChanBandListParamSet_t *pchan_band_tlv = MNULL;
+	ChanBandParamSet_t *pchan_band;
+	t_u8 band;
+	t_u8 is_bgscan_resp;
+	t_u32 age_ts_usec;
+	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = { 0 };
+	t_u32 status_code = 0;
+	pmlan_ioctl_req pscan_ioctl_req = MNULL;
+
+	ENTER();
+	pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+	is_bgscan_resp = (resp->command == HostCmd_CMD_802_11_BG_SCAN_QUERY);
+	if (is_bgscan_resp)
+		pscan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
+	else
+		pscan_rsp = &resp->params.scan_resp;
+
+	if (pscan_rsp->number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+		PRINTM(MERROR,
+		       "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
+		       pscan_rsp->number_of_sets);
+		status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bytes_left = wlan_le16_to_cpu(pscan_rsp->bss_descript_size);
+	PRINTM(MINFO, "SCAN_RESP: bss_descript_size %d\n", bytes_left);
+
+	scan_resp_size = resp->size;
+
+	PRINTM(MINFO, "SCAN_RESP: returned %d APs before parsing\n",
+	       pscan_rsp->number_of_sets);
+
+	num_in_table = pmadapter->num_in_scan_table;
+	pbss_info = pscan_rsp->bss_desc_and_tlv_buffer;
+
+	/*
+	 * The size of the TLV buffer is equal to the entire command response
+	 *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
+	 *   BSS Descriptions (bss_descript_size as bytesLef) and the command
+	 *   response header (S_DS_GEN)
+	 */
+	tlv_buf_size = scan_resp_size - (bytes_left
+					 + sizeof(pscan_rsp->bss_descript_size)
+					 + sizeof(pscan_rsp->number_of_sets)
+					 + S_DS_GEN);
+	if (is_bgscan_resp)
+		tlv_buf_size -=
+			sizeof(resp->params.bg_scan_query_resp.
+			       report_condition);
+
+	ptlv = (MrvlIEtypes_Data_t *)(pscan_rsp->bss_desc_and_tlv_buffer +
+				      bytes_left);
+
+	/*
+	 * Search the TLV buffer space in the scan response
+	 * for any valid TLVs
+	 */
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter,
+					  ptlv,
+					  tlv_buf_size,
+					  TLV_TYPE_TSFTIMESTAMP,
+					  (MrvlIEtypes_Data_t **)&ptsf_tlv);
+
+	/*
+	 * Search the TLV buffer space in the scan response
+	 * for any valid TLVs
+	 */
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter,
+					  ptlv,
+					  tlv_buf_size,
+					  TLV_TYPE_CHANNELBANDLIST,
+					  (MrvlIEtypes_Data_t **)
+					  &pchan_band_tlv);
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter, ptlv, tlv_buf_size,
+					  TLV_TYPE_CHANNEL_STATS,
+					  (MrvlIEtypes_Data_t **)
+					  &pchanstats_tlv);
+
+	if (pchanstats_tlv)
+		wlan_update_chan_statistics(pmpriv, pchanstats_tlv);
+
+	/*
+	 * Process each scan response returned (pscan_rsp->number_of_sets).
+	 * Save the information in the bss_new_entry and then insert into
+	 * the driver scan table either as an update to an existing entry
+	 * or as an addition at the end of the table
+	 */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+		status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	for (idx = 0; idx < pscan_rsp->number_of_sets && bytes_left; idx++) {
+		/* Zero out the bss_new_entry we are about to store info in */
+		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+		/* Process the data fields and IEs returned for this BSS */
+		if (wlan_interpret_bss_desc_with_ie(pmadapter,
+						    bss_new_entry,
+						    &pbss_info,
+						    &bytes_left,
+						    MFALSE) ==
+		    MLAN_STATUS_SUCCESS) {
+			PRINTM(MINFO, "SCAN_RESP: BSSID = " MACSTR "\n",
+			       MAC2STR(bss_new_entry->mac_address));
+
+			band = BAND_G;
+			if (pchan_band_tlv) {
+				pchan_band =
+					&pchan_band_tlv->chan_band_param[idx];
+				band = radio_type_to_band(pchan_band->bandcfg.
+							  chanBand);
+				if (!bss_new_entry->channel)
+					bss_new_entry->channel =
+						pchan_band->chan_number;
+			}
+			/*
+			 * Save the band designation for this entry
+			 * for use in join
+			 */
+			bss_new_entry->bss_band = band;
+
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								(t_u8)
+								bss_new_entry->
+								bss_band,
+								(t_u16)
+								bss_new_entry->
+								channel);
+			if (cfp)
+				bss_new_entry->freq = cfp->freq;
+			else
+				bss_new_entry->freq = 0;
+
+			/* Skip entry if on blacklisted channel */
+			if (cfp && cfp->dynamic.blacklist) {
+				PRINTM(MINFO,
+				       "SCAN_RESP: dropping entry on blacklist channel.\n");
+				continue;
+			}
+
+			/*
+			 * Search the scan table for the same bssid
+			 */
+			for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
+				if (!memcmp
+				    (pmadapter, bss_new_entry->mac_address,
+				     pmadapter->pscan_table[bss_idx].
+				     mac_address,
+				     sizeof(bss_new_entry->mac_address))) {
+					/*
+					 * If the SSID matches as well, it is a
+					 * duplicate of this entry.  Keep the
+					 * bss_idx set to this entry so we
+					 * replace the old contents in the table
+					 */
+					if ((bss_new_entry->ssid.ssid_len ==
+					     pmadapter->pscan_table[bss_idx].
+					     ssid.ssid_len)
+					    &&
+					    (!memcmp
+					     (pmadapter,
+					      bss_new_entry->ssid.ssid,
+					      pmadapter->pscan_table[bss_idx].
+					      ssid.ssid,
+					      bss_new_entry->ssid.ssid_len))) {
+						PRINTM(MINFO,
+						       "SCAN_RESP: Duplicate of index: %d\n",
+						       bss_idx);
+
+						break;
+					}
+					/*
+					 * If the SSID is NULL for same BSSID
+					 * keep the bss_idx set to this entry
+					 * so we replace the old contents in
+					 * the table
+					 */
+					if (!memcmp
+					    (pmadapter,
+					     pmadapter->pscan_table[bss_idx].
+					     ssid.ssid, null_ssid,
+					     pmadapter->pscan_table[bss_idx].
+					     ssid.ssid_len)) {
+						PRINTM(MINFO,
+						       "SCAN_RESP: Duplicate of index: %d\n",
+						       bss_idx);
+						break;
+					}
+				}
+			}
+			/*
+			 * If the bss_idx is equal to the number of entries
+			 * in the table, the new entry was not a duplicate;
+			 * append it to the scan table
+			 */
+			if (bss_idx == num_in_table) {
+				/*
+				 * Range check the bss_idx, keep it limited
+				 * to the last entry
+				 */
+				if (bss_idx == MRVDRV_MAX_BSSID_LIST)
+					bss_idx--;
+				else
+					num_in_table++;
+			}
+
+			/*
+			 * 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(pmpriv->adapter, &tsf_val,
+				       &ptsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
+				       sizeof(tsf_val));
+				tsf_val = wlan_le64_to_cpu(tsf_val);
+				memcpy(pmpriv->adapter,
+				       &bss_new_entry->network_tsf, &tsf_val,
+				       sizeof(bss_new_entry->network_tsf));
+			}
+
+			/* Copy the locally created bss_new_entry to the scan table */
+			memcpy(pmadapter, &pmadapter->pscan_table[bss_idx],
+			       bss_new_entry,
+			       sizeof(pmadapter->pscan_table[bss_idx]));
+
+		} else {
+			/* Error parsing/interpreting the scan response, skipped */
+			PRINTM(MERROR,
+			       "SCAN_RESP: wlan_interpret_bss_desc_with_ie returned error\n");
+		}
+	}
+
+	PRINTM(MINFO, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
+	       pscan_rsp->number_of_sets,
+	       num_in_table - pmadapter->num_in_scan_table, num_in_table);
+
+	/* Update the total number of BSSIDs in the scan table */
+	pmadapter->num_in_scan_table = num_in_table;
+	/* Update the age_in_second */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->age_in_secs,
+						  &age_ts_usec);
+	if (is_bgscan_resp)
+		goto done;
+	wlan_request_cmd_lock(pmadapter);
+	if (!util_peek_list
+	    (pmadapter->pmoal_handle, &pmadapter->scan_pending_q, MNULL,
+	     MNULL)) {
+		wlan_release_cmd_lock(pmadapter);
+		if (pmadapter->pscan_ioctl_req) {
+			if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)->
+			    sub_command == MLAN_OID_SCAN_SPECIFIC_SSID ||
+			    ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)->
+			    sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+				if (wlan_active_scan_req_for_passive_chan
+				    (pmpriv, pmadapter->pscan_ioctl_req)) {
+					goto done;
+				}
+			}
+		}
+		/*
+		 * Process the resulting scan table:
+		 *   - Remove any bad ssids
+		 *   - Update our current BSS information from scan data
+		 */
+		wlan_scan_process_results(pmpriv);
+
+		wlan_request_cmd_lock(pmadapter);
+		pmadapter->scan_processing = MFALSE;
+		pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+		pmadapter->pscan_ioctl_req = MNULL;
+		/* Need to indicate IOCTL complete */
+		if (pscan_ioctl_req) {
+			pscan_ioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+			/* Indicate ioctl complete */
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 (pmlan_ioctl_req)
+						 pscan_ioctl_req,
+						 MLAN_STATUS_SUCCESS);
+		}
+		wlan_release_cmd_lock(pmadapter);
+		pmadapter->bgscan_reported = MFALSE;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
+	} else {
+		/* If firmware not ready, do not issue any more scan commands */
+		if (pmadapter->hw_status != WlanHardwareStatusReady) {
+			wlan_release_cmd_lock(pmadapter);
+			status_code = MLAN_ERROR_FW_NOT_READY;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		} else {
+			/* Get scan command from scan_pending_q and put to cmd_pending_q */
+			pcmd_node =
+				(cmd_ctrl_node *)util_dequeue_list(pmadapter->
+								   pmoal_handle,
+								   &pmadapter->
+								   scan_pending_q,
+								   MNULL,
+								   MNULL);
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MTRUE);
+			wlan_release_cmd_lock(pmadapter);
+		}
+	}
+
+done:
+	if (bss_new_entry)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
+	if (ret) {
+		/* Flush all pending scan commands */
+		wlan_flush_scan_queue(pmadapter);
+		wlan_request_cmd_lock(pmadapter);
+		pmadapter->scan_processing = MFALSE;
+		pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+		pmadapter->pscan_ioctl_req = MNULL;
+		if (pscan_ioctl_req) {
+			pscan_ioctl_req->status_code = status_code;
+			/* Indicate ioctl complete */
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pscan_ioctl_req,
+						 MLAN_STATUS_FAILURE);
+		}
+		wlan_release_cmd_lock(pmadapter);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Prepare an extended scan command to be sent to the firmware
+ *
+ *  Use the wlan_scan_cmd_config sent to the command processing module in
+ *   the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN_EXT command
+ *   struct to send to firmware.
+ *
+ *  @param pmpriv     A pointer to mlan_private structure
+ *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
+ *                    firmware with the HostCmd_DS_802_11_SCAN_EXT structure
+ *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
+ *                    to set the fields/TLVs for the command sent to firmware
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_scan_ext(IN mlan_private *pmpriv,
+			 IN HostCmd_DS_COMMAND *pcmd, IN t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &pcmd->params.ext_scan;
+	wlan_scan_cmd_config *pscan_cfg = MNULL;
+
+	ENTER();
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
+
+	if (pmpriv->adapter->ext_scan_enh == MTRUE) {
+		if (pdata_buf) {
+			if (pmpriv->adapter->ext_scan_type == EXT_SCAN_ENHANCE)
+				pext_scan_cmd->ext_scan_type = EXT_SCAN_ENHANCE;
+			else
+				pext_scan_cmd->ext_scan_type = EXT_SCAN_DEFAULT;
+		} else {
+			pcmd->size =
+				wlan_cpu_to_le16((t_u16)
+						 (sizeof
+						  (pext_scan_cmd->ext_scan_type)
+						  +
+						  (t_u16)(sizeof
+							  (pext_scan_cmd->
+							   reserved)) +
+						  S_DS_GEN));
+			pext_scan_cmd->ext_scan_type = EXT_SCAN_CANCEL;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+	pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
+
+	memcpy(pmpriv->adapter, pext_scan_cmd->tlv_buffer,
+	       pscan_cfg->tlv_buf, 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(IN mlan_private *pmpriv,
+			 IN HostCmd_DS_COMMAND *resp, IN 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, "Cancle scan command completed!\n");
+		/* 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 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(IN mlan_private *pmpriv,
+			   IN t_u8 number_of_sets,
+			   IN t_u8 *pscan_resp, IN 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 bss_idx;
+	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;
+	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = { 0 };
+
+	ENTER();
+	pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+	if (number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+		PRINTM(MERROR,
+		       "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
+		       number_of_sets);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bytes_left = scan_resp_size;
+	PRINTM(MINFO, "EXT_SCAN: bss_descript_size %d\n", scan_resp_size);
+	PRINTM(MINFO, "EXT_SCAN: returned %d APs before parsing\n",
+	       number_of_sets);
+
+	num_in_table = pmadapter->num_in_scan_table;
+	ptlv = (MrvlIEtypes_Data_t *)pscan_resp;
+
+	/*
+	 *  Process each scan response returned number_of_sets. Save
+	 *    the information in the bss_new_entry and then insert into the
+	 *    driver scan table either as an update to an existing entry
+	 *    or as an addition at the end of the table
+	 */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	for (idx = 0; idx < number_of_sets && bytes_left >
+	     sizeof(MrvlIEtypesHeader_t); idx++) {
+		tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+		tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+		if (bytes_left < sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+			PRINTM(MERROR,
+			       "EXT_SCAN: Error bytes left < TLV length\n");
+			break;
+		}
+		pscan_rsp_tlv = MNULL;
+		pscan_info_tlv = MNULL;
+		bytes_left_for_tlv = bytes_left;
+		/*
+		 * BSS response TLV with beacon or probe response buffer
+		 * at the initial position of each descriptor
+		 */
+		if (tlv_type == TLV_TYPE_BSS_SCAN_RSP) {
+			pbss_info = (t_u8 *)ptlv;
+			pscan_rsp_tlv = (MrvlIEtypes_Bss_Scan_Rsp_t *)ptlv;
+			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+			bytes_left_for_tlv -=
+				(tlv_len + sizeof(MrvlIEtypesHeader_t));
+		} else
+			break;
+
+		/* Process variable TLV */
+		while (bytes_left_for_tlv >= sizeof(MrvlIEtypesHeader_t) &&
+		       wlan_le16_to_cpu(ptlv->header.type) !=
+		       TLV_TYPE_BSS_SCAN_RSP) {
+			tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+			if (bytes_left_for_tlv <
+			    sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+				PRINTM(MERROR,
+				       "EXT_SCAN: Error in processing TLV, "
+				       "bytes left < TLV length\n");
+				pscan_rsp_tlv = MNULL;
+				bytes_left_for_tlv = 0;
+				continue;
+			}
+			switch (tlv_type) {
+			case TLV_TYPE_BSS_SCAN_INFO:
+				pscan_info_tlv =
+					(MrvlIEtypes_Bss_Scan_Info_t *)ptlv;
+				if (tlv_len !=
+				    sizeof(MrvlIEtypes_Bss_Scan_Info_t) -
+				    sizeof(MrvlIEtypesHeader_t)) {
+					bytes_left_for_tlv = 0;
+					continue;
+				}
+				break;
+			default:
+				break;
+			}
+			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+			bytes_left -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
+			bytes_left_for_tlv -=
+				(tlv_len + sizeof(MrvlIEtypesHeader_t));
+		}
+		/* No BSS response TLV */
+		if (pscan_rsp_tlv == MNULL)
+			break;
+
+		/*
+		 * Advance pointer to the beacon buffer length and
+		 * update the bytes count so that the function
+		 * wlan_interpret_bss_desc_with_ie() can handle the
+		 * scan buffer withut any change
+		 */
+		pbss_info += sizeof(t_u16);
+		bytes_left -= sizeof(t_u16);
+
+		/* Zero out the bss_new_entry we are about to store info in */
+		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+		/* Process the data fields and IEs returned for this BSS */
+		if (wlan_interpret_bss_desc_with_ie(pmadapter,
+						    bss_new_entry,
+						    &pbss_info,
+						    &bytes_left,
+						    MTRUE) ==
+		    MLAN_STATUS_SUCCESS) {
+			PRINTM(MINFO, "EXT_SCAN: BSSID = " MACSTR "\n",
+			       MAC2STR(bss_new_entry->mac_address));
+
+			band = BAND_G;
+			/*
+			 * If the BSS info TLV was appended to the scan results,
+			 * save this entry's TSF value in the networkTSF field.
+			 * The networkTSF is the firmware's TSF value at the
+			 * time the beacon or probe response was received.
+			 */
+			if (pscan_info_tlv) {
+				/* RSSI is 2 byte long */
+				bss_new_entry->rssi =
+					-(t_s32)(wlan_le16_to_cpu
+						 (pscan_info_tlv->rssi));
+				PRINTM(MINFO, "EXT_SCAN: RSSI=%d\n",
+				       bss_new_entry->rssi);
+				memcpy(pmpriv->adapter, &tsf_val,
+				       &pscan_info_tlv->tsf, sizeof(tsf_val));
+				tsf_val = wlan_le64_to_cpu(tsf_val);
+				memcpy(pmpriv->adapter,
+				       &bss_new_entry->network_tsf, &tsf_val,
+				       sizeof(bss_new_entry->network_tsf));
+				band = radio_type_to_band(pscan_info_tlv->
+							  bandcfg.chanBand);
+			}
+			/* Save the band designation for this entry for use in join */
+			bss_new_entry->bss_band = band;
+
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								(t_u8)
+								bss_new_entry->
+								bss_band,
+								(t_u16)
+								bss_new_entry->
+								channel);
+			if (cfp)
+				bss_new_entry->freq = cfp->freq;
+			else
+				bss_new_entry->freq = 0;
+
+			/* Skip entry if on blacklisted channel */
+			if (cfp && cfp->dynamic.blacklist) {
+				PRINTM(MINFO,
+				       "EXT_SCAN: dropping entry on blacklist channel.\n");
+				continue;
+			}
+
+			/*
+			 * 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++;
+			}
+
+			/*
+			 * 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;
+			}
+
+			/* Copy the locally created bss_new_entry to the scan table */
+			memcpy(pmadapter, &pmadapter->pscan_table[bss_idx],
+			       bss_new_entry,
+			       sizeof(pmadapter->pscan_table[bss_idx]));
+		} else {
+			/* Error parsing/interpreting the scan response, skipped */
+			PRINTM(MERROR,
+			       "EXT_SCAN: wlan_interpret_bss_desc_with_ie returned error\n");
+		}
+	}
+
+	PRINTM(MINFO, "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(IN mlan_private *pmpriv,
+				  IN 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(IN mlan_private *pmpriv,
+				  IN mlan_buffer *pmbuf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_event_scan_status *scan_event;
+	mlan_ioctl_req *pioctl_req;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	t_u16 tlv_buf_left, tlv_len, tlv_type;
+	MrvlIEtypesHeader_t *tlv;
+	MrvlIEtypes_ChannelStats_t *tlv_chan_stats;
+	t_u8 status;
+
+	ENTER();
+
+	if (pmbuf->data_len < sizeof(mlan_event_scan_status)) {
+		PRINTM(MERROR, "Wrong ext scan status event data length\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	scan_event =
+		(pmlan_event_scan_status) (pmbuf->pbuf + pmbuf->data_offset);
+	DBG_HEXDUMP(MCMD_D, "EVENT: Ext_Scan_Status", scan_event,
+		    pmbuf->data_len);
+	status = scan_event->scan_status;
+	PRINTM(MEVENT, "ext_scan_status: status %d (scan %s), buf_len %d\n",
+	       status, status ? "cancelled" : "success", scan_event->buf_len);
+
+	tlv = (MrvlIEtypesHeader_t *)scan_event->event_buf;
+	tlv_buf_left = pmbuf->data_len - sizeof(mlan_event_scan_status);
+	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+			PRINTM(MERROR,
+			       "Error process scan gap tlv: length %d type 0x%x\n",
+			       tlv_len, tlv_type);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		switch (tlv_type) {
+		case TLV_TYPE_CHANNEL_STATS:
+			tlv_chan_stats = (MrvlIEtypes_ChannelStats_t *)tlv;
+			wlan_update_chan_statistics(pmpriv, tlv_chan_stats);
+			break;
+		default:
+			break;
+		}
+		tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)(tlv + tlv_len +
+						       sizeof
+						       (MrvlIEtypesHeader_t)));
+	}
+
+done:
+	/* Now we got response from FW, cancel the command timer */
+	if (!pmadapter->curr_cmd && pmadapter->cmd_timer_is_set) {
+		/* Cancel command timeout timer */
+		pcb->moal_stop_timer(pmadapter->pmoal_handle,
+				     pmadapter->pmlan_cmd_timer);
+		/* Cancel command timeout timer */
+		pmadapter->cmd_timer_is_set = MFALSE;
+	}
+	if (pmadapter->pscan_ioctl_req) {
+		if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)->
+		    sub_command == MLAN_OID_SCAN_SPECIFIC_SSID ||
+		    ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)->
+		    sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+			if (wlan_active_scan_req_for_passive_chan
+			    (pmpriv, pmadapter->pscan_ioctl_req)) {
+				LEAVE();
+				return ret;
+			}
+		}
+	}
+	/*
+	 * Process the resulting scan table:
+	 *   - Remove any bad ssids
+	 *   - Update our current BSS information from scan data
+	 */
+	wlan_scan_process_results(pmpriv);
+    /** Complete scan ioctl */
+	wlan_request_cmd_lock(pmadapter);
+	pmadapter->scan_processing = MFALSE;
+	pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
+	pioctl_req = pmadapter->pscan_ioctl_req;
+	pmadapter->pscan_ioctl_req = MNULL;
+	/* Need to indicate IOCTL complete */
+	if (pioctl_req != MNULL) {
+		pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+		/* Indicate ioctl complete */
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+					 pioctl_req, MLAN_STATUS_SUCCESS);
+	}
+	wlan_release_cmd_lock(pmadapter);
+	pmadapter->bgscan_reported = MFALSE;
+	wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of bg_scan_query.
+ *
+ *  @param pmpriv     A pointer to mlan_private structure
+ *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
+ *                    to set the fields/TLVs for the command sent to firmware
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_bg_scan_query(IN mlan_private *pmpriv,
+			      IN HostCmd_DS_COMMAND *pcmd, IN 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(IN mlan_private *pmpriv,
+				IN 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;
+			tlv_chan_list->chan_scan_param[chan_idx].chan_scan_mode.
+				disable_chan_filt = MTRUE;
+		}
+	}
+
+	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(IN mlan_private *pmpriv,
+		       IN HostCmd_DS_COMMAND *pcmd, IN 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;
+	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(pmadapter, pwildcard_ssid_tlv->ssid,
+		       bg_scan_in->ssid_list[ssid_idx].ssid,
+		       MIN(MLAN_MAX_SSID_LENGTH, ssid_len));
+		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;
+	}
+
+	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 (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(pmadapter, randomMacParam->mac, bg_scan_in->random_mac,
+		       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(IN mlan_private *pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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(IN mlan_private *pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_scan *pscan = MNULL;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	ENTER();
+	wlan_ret_802_11_scan(pmpriv, resp, MNULL);
+	if (pioctl_buf) {
+		pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
+		pscan->param.scan_resp.pscan_table =
+			(t_u8 *)pmadapter->pscan_table;
+		pscan->param.scan_resp.num_in_scan_table =
+			pmadapter->num_in_scan_table;
+		pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs;
+		pscan->param.scan_resp.pchan_stats =
+			(t_u8 *)pmadapter->pchan_stats;
+		pscan->param.scan_resp.num_in_chan_stats =
+			pmadapter->num_in_chan_stats;
+
+		pioctl_buf->data_read_written = sizeof(mlan_scan_resp) +
+			MLAN_SUB_COMMAND_SIZE;
+
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function finds ssid in ssid list.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param ssid         SSID to find in the list
+ *  @param bssid        BSSID to qualify the SSID selection (if provided)
+ *  @param mode         Network mode: Infrastructure or IBSS
+ *
+ *  @return             index in BSSID list or < 0 if error
+ */
+t_s32
+wlan_find_ssid_in_list(IN mlan_private *pmpriv,
+		       IN mlan_802_11_ssid *ssid, IN t_u8 *bssid, IN 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(IN mlan_private *pmpriv, IN t_u8 *bssid, IN 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(IN pmlan_adapter pmadapter,
+	      IN mlan_802_11_ssid *ssid1, IN 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(IN mlan_private *pmpriv,
+		       OUT 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(pmadapter, &preq_ssid_bssid->ssid, &preq_bss->ssid,
+		       sizeof(mlan_802_11_ssid));
+		memcpy(pmadapter, (t_u8 *)&preq_ssid_bssid->bssid,
+		       (t_u8 *)&preq_bss->mac_address, 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;
+	}
+
+	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(IN mlan_private *pmpriv,
+			IN t_void *pioctl_buf, IN 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(pmpriv->adapter, pscan_cfg->ssid_list[0].ssid,
+	       preq_ssid->ssid, preq_ssid->ssid_len);
+	pscan_cfg->keep_previous_scan = MTRUE;
+
+	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(IN 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(pmpriv->adapter, pmpriv->pcurr_bcn_buf,
+				       pcurr_bss->pbeacon_buf,
+				       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(IN 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_sd8997/mlan/mlan_sdio.c b/wlan_sd8997/mlan/mlan_sdio.c
new file mode 100644
index 0000000..7d0067b
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_sdio.c
@@ -0,0 +1,2470 @@
+/** @file mlan_sdio.c
+ *
+ *  @brief This file contains SDIO specific code
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/27/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_init.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_sdio.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief This function initialize the SDIO port
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_init_ioport(mlan_adapter *pmadapter)
+{
+	t_u32 reg;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	t_u8 host_int_rsr_reg = HOST_INT_RSR_REG;
+	t_u8 host_int_rsr_mask = HOST_INT_RSR_MASK;
+	t_u8 card_misc_cfg_reg = CARD_MISC_CFG_REG;
+	t_u8 card_config_2_1_reg = CARD_CONFIG_2_1_REG;
+	t_u8 cmd_config_0 = CMD_CONFIG_0;
+	t_u8 cmd_config_1 = CMD_CONFIG_1;
+
+	ENTER();
+	pmadapter->ioport = 0;
+
+	pmadapter->ioport = MEM_PORT;
+
+	PRINTM(MINFO, "SDIO FUNC1 IO port: 0x%x\n", pmadapter->ioport);
+
+	/* enable sdio cmd53 new mode */
+	if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      card_config_2_1_reg,
+						      &reg)) {
+		pcb->moal_write_reg(pmadapter->pmoal_handle,
+				    card_config_2_1_reg, reg | CMD53_NEW_MODE);
+	} else {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* configure cmd port  */
+	/* enable reading rx length from the register  */
+	if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      cmd_config_0, &reg)) {
+		pcb->moal_write_reg(pmadapter->pmoal_handle,
+				    cmd_config_0, reg | CMD_PORT_RD_LEN_EN);
+	} else {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* enable Dnld/Upld ready auto reset for cmd port
+	 * after cmd53 is completed */
+	if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      cmd_config_1, &reg)) {
+		pcb->moal_write_reg(pmadapter->pmoal_handle,
+				    cmd_config_1, reg | CMD_PORT_AUTO_EN);
+	} else {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* 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->mp_rd_bitmap;
+	t_u8 max_ports = MAX_PORT;
+
+	ENTER();
+
+	PRINTM(MIF_D, "wlan_get_rd_port: mp_rd_bitmap=0x%08x\n", rd_bitmap);
+
+	if (!(rd_bitmap & (DATA_PORT_MASK))) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (pmadapter->mp_rd_bitmap & (1 << pmadapter->curr_rd_port)) {
+		pmadapter->mp_rd_bitmap &=
+			(t_u32)(~(1 << pmadapter->curr_rd_port));
+		*pport = pmadapter->curr_rd_port;
+
+		/* hw rx wraps round only after port (MAX_PORT-1) */
+		if (++pmadapter->curr_rd_port == max_ports)
+			/* port 0 is not reserved for cmd port */
+			pmadapter->curr_rd_port = 0;
+	} else {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	PRINTM(MIF_D, "port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n",
+	       *pport, rd_bitmap, pmadapter->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->mp_wr_bitmap;
+
+	ENTER();
+
+	PRINTM(MIF_D, "wlan_get_wr_port_data: mp_wr_bitmap=0x%08x\n",
+	       wr_bitmap);
+
+	if (!(wr_bitmap & pmadapter->mp_data_port_mask)) {
+		pmadapter->data_sent = MTRUE;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	if (pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port)) {
+		pmadapter->mp_wr_bitmap &=
+			(t_u32)(~(1 << pmadapter->curr_wr_port));
+		*pport = pmadapter->curr_wr_port;
+		if (++pmadapter->curr_wr_port == pmadapter->mp_end_port)
+			pmadapter->curr_wr_port = 0;
+	} else {
+		pmadapter->data_sent = MTRUE;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	PRINTM(MIF_D, "port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
+	       *pport, wr_bitmap, pmadapter->mp_wr_bitmap);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function polls the card status register.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param bits       the bit mask
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_poll_card_status(mlan_adapter *pmadapter, t_u8 bits)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 tries;
+	t_u32 cs = 0;
+
+	ENTER();
+
+	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       CARD_TO_HOST_EVENT_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,
+						      CARD_FW_STATUS0_REG,
+						      &fws0)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      CARD_FW_STATUS1_REG,
+						      &fws1)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	*dat = (t_u16)((fws1 << 8) | fws0);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**  @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,
+						      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,
+						       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,
+						       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_prog_fw_w_helper(IN 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;
+	t_u32 read_base_0_reg = READ_BASE_0_REG;
+	t_u32 read_base_1_reg = READ_BASE_1_REG;
+
+	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);
+
+	/* 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)) {
+			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);
+
+			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->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_host_int(pmlan_adapter pmadapter)
+{
+	mlan_status ret;
+
+	ENTER();
+	ret = wlan_sdio_disable_host_int_mask(pmadapter, HIM_DISABLE);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function decodes the rx packet &
+ *  calls corresponding handlers according to the packet type
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf      A pointer to the SDIO data/cmd buffer
+ *  @param upld_typ  Type of rx packet
+ *  @param lock_flag  flag for spin_lock.
+ *  @return          MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_decode_rx_packet(mlan_adapter *pmadapter, mlan_buffer *pmbuf,
+		      t_u32 upld_typ, t_u8 lock_flag)
+{
+	t_u8 *cmd_buf;
+	t_u32 event;
+
+	ENTER();
+
+	switch (upld_typ) {
+	case MLAN_TYPE_SPA_DATA:
+		PRINTM(MINFO, "--- Rx: SPA Data packet ---\n");
+		pmbuf->data_len = pmadapter->upld_len;
+		if (pmadapter->rx_work_flag) {
+			pmbuf->buf_type = MLAN_BUF_TYPE_SPA_DATA;
+			if (lock_flag)
+				pmadapter->callbacks.moal_spin_lock(pmadapter->
+								    pmoal_handle,
+								    pmadapter->
+								    rx_data_queue.
+								    plock);
+			util_enqueue_list_tail(pmadapter->pmoal_handle,
+					       &pmadapter->rx_data_queue,
+					       (pmlan_linked_list)pmbuf, MNULL,
+					       MNULL);
+			pmadapter->rx_pkts_queued++;
+			if (lock_flag)
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 rx_data_queue.plock);
+		} else {
+			wlan_decode_spa_buffer(pmadapter,
+					       pmbuf->pbuf + pmbuf->data_offset,
+					       pmbuf->data_len);
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+		}
+		pmadapter->data_received = MTRUE;
+		break;
+	case MLAN_TYPE_DATA:
+		PRINTM(MINFO, "--- Rx: Data packet ---\n");
+		pmbuf->data_len = (pmadapter->upld_len - INTF_HEADER_LEN);
+		pmbuf->data_offset += INTF_HEADER_LEN;
+		if (pmadapter->rx_work_flag) {
+			if (lock_flag)
+				pmadapter->callbacks.moal_spin_lock(pmadapter->
+								    pmoal_handle,
+								    pmadapter->
+								    rx_data_queue.
+								    plock);
+			util_enqueue_list_tail(pmadapter->pmoal_handle,
+					       &pmadapter->rx_data_queue,
+					       (pmlan_linked_list)pmbuf, MNULL,
+					       MNULL);
+			pmadapter->rx_pkts_queued++;
+			if (lock_flag)
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 rx_data_queue.plock);
+		} else {
+			wlan_handle_rx_packet(pmadapter, pmbuf);
+		}
+		pmadapter->data_received = MTRUE;
+		break;
+
+	case MLAN_TYPE_CMD:
+		PRINTM(MINFO, "--- Rx: Cmd Response ---\n");
+		/* take care of curr_cmd = NULL case */
+		if (!pmadapter->curr_cmd) {
+			cmd_buf = pmadapter->upld_buf;
+			if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
+				wlan_process_sleep_confirm_resp(pmadapter,
+								pmbuf->pbuf +
+								pmbuf->
+								data_offset +
+								INTF_HEADER_LEN,
+								pmadapter->
+								upld_len -
+								INTF_HEADER_LEN);
+			}
+			pmadapter->upld_len -= INTF_HEADER_LEN;
+			memcpy(pmadapter, cmd_buf,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       INTF_HEADER_LEN, MIN(MRVDRV_SIZE_OF_CMD_BUFFER,
+						    pmadapter->upld_len -
+						    INTF_HEADER_LEN));
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+		} else {
+			pmadapter->cmd_resp_received = MTRUE;
+			pmadapter->upld_len -= INTF_HEADER_LEN;
+			pmbuf->data_len = pmadapter->upld_len;
+			pmbuf->data_offset += 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 +
+					       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(pmadapter, pmadapter->event_body,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       MLAN_EVENT_HEADER_LEN,
+			       pmadapter->upld_len - MLAN_EVENT_HEADER_LEN);
+		}
+
+		/* 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 += INTF_HEADER_LEN;
+		pmbuf->data_len -= 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;
+}
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+/**
+ *  @brief This function receives single packet
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_receive_single_packet(mlan_adapter *pmadapter)
+{
+	mlan_buffer *pmbuf;
+	t_u8 port;
+	t_u16 rx_len;
+	t_u32 pkt_type = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	pmbuf = pmadapter->mpa_rx.mbuf_arr[0];
+	port = pmadapter->mpa_rx.start_port;
+	rx_len = pmadapter->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->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->mpa_rx_count[0]++;
+	wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
+done:
+	if (ret != MLAN_STATUS_SUCCESS)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	MP_RX_AGGR_BUF_RESET(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function receives data from the card in aggregate mode.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_receive_mp_aggr_buf(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer mbuf_aggr;
+	mlan_buffer *mbuf_deaggr;
+	t_u32 pind = 0;
+	t_u32 pkt_len, pkt_type = 0;
+	t_u8 *curr_ptr;
+	t_u32 cmd53_port = 0;
+	t_u32 i = 0;
+	t_u32 port_count = 0;
+
+	/* do aggr RX now */
+	PRINTM(MINFO, "do_rx_aggr: num of packets: %d\n",
+	       pmadapter->mpa_rx.pkt_cnt);
+
+	memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+	if (pmadapter->mpa_rx.pkt_cnt == 1)
+		return wlan_receive_single_packet(pmadapter);
+	if (!pmadapter->mpa_rx.buf) {
+		mbuf_aggr.data_len = pmadapter->mpa_rx.buf_len;
+		mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+		mbuf_aggr.use_count = 0;
+		for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) {
+			pmadapter->mpa_rx.mbuf_arr[pind]->data_len =
+				pmadapter->mpa_rx.len_arr[pind];
+			wlan_link_buf_to_aggr(&mbuf_aggr,
+					      pmadapter->mpa_rx.mbuf_arr[pind]);
+		}
+	} else {
+		mbuf_aggr.pbuf = (t_u8 *)pmadapter->mpa_rx.buf;
+		mbuf_aggr.data_len = pmadapter->mpa_rx.buf_len;
+	}
+
+	port_count = bitcount(pmadapter->mpa_rx.ports) - 1;
+	/* port_count = pmadapter->mpa_rx.pkt_cnt - 1; */
+	cmd53_port =
+		(pmadapter->ioport | SDIO_MPA_ADDR_BASE | (port_count << 8))
+		+ pmadapter->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->mpa_rx.buf && pmadapter->mpa_rx.pkt_cnt > 1) {
+		for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) {
+			mbuf_deaggr = pmadapter->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->mpa_rx.buf,
+			    MIN(pmadapter->mpa_rx.buf_len, MAX_DATA_DUMP_LEN));
+
+		curr_ptr = pmadapter->mpa_rx.buf;
+
+		for (pind = 0; pind < pmadapter->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->mpa_rx.mbuf_arr[pind];
+			if ((pkt_type == MLAN_TYPE_DATA
+			     || pkt_type == MLAN_TYPE_SPA_DATA) &&
+			    (pkt_len <= pmadapter->mpa_rx.len_arr[pind])) {
+				memcpy(pmadapter,
+				       mbuf_deaggr->pbuf +
+				       mbuf_deaggr->data_offset, curr_ptr,
+				       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->mpa_rx.len_arr[pind]);
+				wlan_free_mlan_buffer(pmadapter, mbuf_deaggr);
+			}
+			curr_ptr += pmadapter->mpa_rx.len_arr[pind];
+		}
+	}
+	if (pmadapter->rx_work_flag)
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      pmadapter->rx_data_queue.
+						      plock);
+	pmadapter->mpa_rx_count[pmadapter->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;
+
+	ENTER();
+
+	if (!pmadapter->mpa_rx.enabled) {
+		PRINTM(MINFO,
+		       "card_2_host_mp_aggr: rx aggregation disabled !\n");
+
+		f_do_rx_cur = 1;
+		goto rx_curr_single;
+	}
+
+	if (pmadapter->mp_rd_bitmap & DATA_PORT_MASK) {
+		/* Some more data RX pending */
+		PRINTM(MINFO, "card_2_host_mp_aggr: Not last packet\n");
+
+		if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+			if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) {
+				f_aggr_cur = 1;
+			} else {
+				/* No room in Aggr buf, do rx aggr now */
+				f_do_rx_aggr = 1;
+				f_post_aggr_cur = 1;
+			}
+		} else {
+			/* Rx aggr not in progress */
+			f_aggr_cur = 1;
+		}
+
+	} else {
+		/* No more data RX pending */
+		PRINTM(MINFO, "card_2_host_mp_aggr: Last packet\n");
+
+		if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+			f_do_rx_aggr = 1;
+			if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) {
+				f_aggr_cur = 1;
+			} else {
+				/* No room in Aggr buf, do rx aggr now */
+				f_do_rx_cur = 1;
+			}
+		} else {
+			f_do_rx_cur = 1;
+		}
+
+	}
+
+	if (f_aggr_cur) {
+		PRINTM(MINFO, "Current packet aggregation.\n");
+		/* Curr pkt can be aggregated */
+		MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len);
+
+		if (MP_RX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
+		    MP_RX_AGGR_PORT_LIMIT_REACHED(pmadapter)
+			) {
+			PRINTM(MINFO,
+			       "card_2_host_mp_aggr: Aggregation Packet limit reached\n");
+			/* No more pkts allowed in Aggr buf, rx it */
+			f_do_rx_aggr = 1;
+		}
+	}
+
+	if (f_do_rx_aggr) {
+		/* do aggr RX now */
+		if (MLAN_STATUS_SUCCESS != wlan_receive_mp_aggr_buf(pmadapter)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+rx_curr_single:
+	if (f_do_rx_cur) {
+		PRINTM(MINFO, "RX: f_do_rx_cur: port: %d rx_len: %d\n", port,
+		       rx_len);
+
+		if (MLAN_STATUS_SUCCESS !=
+		    wlan_sdio_card_to_host(pmadapter, &pkt_type,
+					   (t_u32 *)&pmadapter->upld_len, pmbuf,
+					   rx_len, pmadapter->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->mpa_rx_count[0]++;
+
+		wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
+	}
+	if (f_post_aggr_cur) {
+		PRINTM(MINFO, "Current packet aggregation.\n");
+		/* Curr pkt can be aggregated */
+		MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len);
+	}
+done:
+	if (ret == MLAN_STATUS_FAILURE) {
+		if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+			/* MP-A transfer failed - cleanup */
+			for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) {
+				wlan_free_mlan_buffer(pmadapter,
+						      pmadapter->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;
+
+}
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/**
+ *  @brief This function sends aggr buf
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_send_mp_aggr_buf(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 cmd53_port = 0;
+	t_u32 port_count = 0;
+	mlan_buffer mbuf_aggr;
+	t_u8 i = 0;
+	t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+
+	ENTER();
+
+	if (!pmadapter->mpa_tx.pkt_cnt) {
+		LEAVE();
+		return ret;
+	}
+	PRINTM(MINFO, "host_2_card_mp_aggr: Send aggregation buffer."
+	       "%d %d\n", pmadapter->mpa_tx.start_port,
+	       pmadapter->mpa_tx.ports);
+
+	memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+	if (!pmadapter->mpa_tx.buf && pmadapter->mpa_tx.pkt_cnt > 1) {
+		mbuf_aggr.data_len = pmadapter->mpa_tx.buf_len;
+		mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+		mbuf_aggr.use_count = 0;
+		for (i = 0; i < pmadapter->mpa_tx.pkt_cnt; i++)
+			wlan_link_buf_to_aggr(&mbuf_aggr,
+					      pmadapter->mpa_tx.mbuf_arr[i]);
+	} else {
+		mbuf_aggr.pbuf = (t_u8 *)pmadapter->mpa_tx.buf;
+		mbuf_aggr.data_len = pmadapter->mpa_tx.buf_len;
+	}
+
+	port_count = bitcount(pmadapter->mpa_tx.ports) - 1;
+	cmd53_port =
+		(pmadapter->ioport | SDIO_MPA_ADDR_BASE | (port_count << 8))
+		+ pmadapter->mpa_tx.start_port;
+
+	if (pmadapter->mpa_tx.pkt_cnt == 1)
+		cmd53_port = pmadapter->ioport + pmadapter->mpa_tx.start_port;
+    /** only one packet */
+	if (!pmadapter->mpa_tx.buf && pmadapter->mpa_tx.pkt_cnt == 1)
+		ret = wlan_write_data_sync(pmadapter,
+					   pmadapter->mpa_tx.mbuf_arr[0],
+					   cmd53_port);
+	else
+		ret = wlan_write_data_sync(pmadapter, &mbuf_aggr, cmd53_port);
+	if (!pmadapter->mpa_tx.buf) {
+	/** free mlan buffer */
+		for (i = 0; i < pmadapter->mpa_tx.pkt_cnt; i++) {
+			wlan_write_data_complete(pmadapter,
+						 pmadapter->mpa_tx.mbuf_arr[i],
+						 MLAN_STATUS_SUCCESS);
+		}
+	}
+	if (!(pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port))
+	    && (pmadapter->mpa_tx.pkt_cnt < mp_aggr_pkt_limit))
+		pmadapter->mpa_sent_no_ports++;
+	pmadapter->mpa_tx_count[pmadapter->mpa_tx.pkt_cnt - 1]++;
+	pmadapter->last_mp_wr_bitmap[pmadapter->last_mp_index] =
+		pmadapter->mp_wr_bitmap;
+	pmadapter->last_mp_wr_ports[pmadapter->last_mp_index] = cmd53_port;
+	pmadapter->last_mp_wr_len[pmadapter->last_mp_index] =
+		pmadapter->mpa_tx.buf_len;
+	pmadapter->last_curr_wr_port[pmadapter->last_mp_index] =
+		pmadapter->curr_wr_port;
+	memcpy(pmadapter,
+	       (t_u8 *)&pmadapter->last_mp_wr_info[pmadapter->last_mp_index *
+						   mp_aggr_pkt_limit],
+	       (t_u8 *)pmadapter->mpa_tx.mp_wr_info,
+	       sizeof(pmadapter->mpa_tx.mp_wr_info)
+		);
+	pmadapter->last_mp_index++;
+	if (pmadapter->last_mp_index >= SDIO_MP_DBG_NUM)
+		pmadapter->last_mp_index = 0;
+	MP_TX_AGGR_BUF_RESET(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card in SDIO aggregated mode.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param mbuf      A pointer to the SDIO data/cmd buffer
+ *  @param port	     current port for aggregation
+ *  @param next_pkt_len Length of next packet used for multiport aggregation
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_host_to_card_mp_aggr(mlan_adapter *pmadapter, mlan_buffer *mbuf, t_u8 port,
+			  t_u32 next_pkt_len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_s32 f_send_aggr_buf = 0;
+	t_s32 f_send_cur_buf = 0;
+	t_s32 f_precopy_cur_buf = 0;
+	t_s32 f_postcopy_cur_buf = 0;
+	t_u8 aggr_sg = 0;
+	t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+
+	ENTER();
+
+	PRINTM(MIF_D, "host_2_card_mp_aggr: next_pkt_len: %d curr_port:%d\n",
+	       next_pkt_len, port);
+
+	if (!pmadapter->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->
+				     mp_wr_bitmap & (1 << pmadapter->
+						     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->
+				     mp_wr_bitmap & (1 << pmadapter->
+						     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->
+			     mp_wr_bitmap & (1 << pmadapter->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->mpa_sent_last_pkt++;
+	}
+
+	if (f_precopy_cur_buf) {
+		PRINTM(MINFO, "host_2_card_mp_aggr: Precopy current buffer\n");
+		if (pmadapter->mpa_buf)
+			memcpy(pmadapter, pmadapter->mpa_buf +
+			       (pmadapter->last_mp_index * mp_aggr_pkt_limit +
+				pmadapter->mpa_tx.pkt_cnt) *
+			       MLAN_SDIO_BLOCK_SIZE,
+			       mbuf->pbuf + mbuf->data_offset,
+			       MLAN_SDIO_BLOCK_SIZE);
+		if (!pmadapter->mpa_tx.buf) {
+			MP_TX_AGGR_BUF_PUT_SG(pmadapter, mbuf, port);
+			aggr_sg = MTRUE;
+		} else {
+
+			MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);
+		}
+		if (MP_TX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
+		    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->ioport + port);
+		if (!(pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port)))
+			pmadapter->mpa_sent_no_ports++;
+		pmadapter->last_mp_wr_bitmap[pmadapter->last_mp_index] =
+			pmadapter->mp_wr_bitmap;
+		pmadapter->last_mp_wr_ports[pmadapter->last_mp_index] =
+			pmadapter->ioport + port;
+		pmadapter->last_mp_wr_len[pmadapter->last_mp_index] =
+			mbuf->data_len;
+		memset(pmadapter,
+		       (t_u8 *)&pmadapter->last_mp_wr_info[pmadapter->
+							   last_mp_index *
+							   mp_aggr_pkt_limit],
+		       0, sizeof(t_u16) * mp_aggr_pkt_limit);
+		pmadapter->last_mp_wr_info[pmadapter->last_mp_index *
+					   mp_aggr_pkt_limit] =
+			*(t_u16 *)(mbuf->pbuf + mbuf->data_offset);
+		pmadapter->last_curr_wr_port[pmadapter->last_mp_index] =
+			pmadapter->curr_wr_port;
+		if (pmadapter->mpa_buf)
+			memcpy(pmadapter,
+			       pmadapter->mpa_buf +
+			       (pmadapter->last_mp_index * mp_aggr_pkt_limit *
+				MLAN_SDIO_BLOCK_SIZE),
+			       mbuf->pbuf + mbuf->data_offset,
+			       MLAN_SDIO_BLOCK_SIZE);
+		pmadapter->last_mp_index++;
+		if (pmadapter->last_mp_index >= SDIO_MP_DBG_NUM)
+			pmadapter->last_mp_index = 0;
+		pmadapter->mpa_tx_count[0]++;
+	}
+	if (f_postcopy_cur_buf) {
+		PRINTM(MINFO, "host_2_card_mp_aggr: Postcopy current buffer\n");
+		if (pmadapter->mpa_buf)
+			memcpy(pmadapter, pmadapter->mpa_buf +
+			       (pmadapter->last_mp_index * mp_aggr_pkt_limit +
+				pmadapter->mpa_tx.pkt_cnt) *
+			       MLAN_SDIO_BLOCK_SIZE,
+			       mbuf->pbuf + mbuf->data_offset,
+			       MLAN_SDIO_BLOCK_SIZE);
+		if (!pmadapter->mpa_tx.buf) {
+			MP_TX_AGGR_BUF_PUT_SG(pmadapter, mbuf, port);
+			aggr_sg = MTRUE;
+		} else {
+			MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);
+		}
+	}
+	/* Always return PENDING in SG mode */
+	if (aggr_sg)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+/********************************************************
+		Global functions
+********************************************************/
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interface is present
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param val        Winner status (0: winner)
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status
+wlan_check_winner_status(mlan_adapter *pmadapter, t_u32 *val)
+{
+	t_u32 winner = 0;
+	pmlan_callbacks pcb;
+	t_u8 card_fw_status0_reg = CARD_FW_STATUS0_REG;
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_read_reg(pmadapter->pmoal_handle, card_fw_status0_reg,
+			       &winner)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param pollnum    Maximum polling number
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_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 == 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 downloads firmware to card
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param pmfw			A pointer to firmware image
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_dnld_fw(IN pmlan_adapter pmadapter, IN pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Download the firmware image via helper */
+	ret = wlan_prog_fw_w_helper(pmadapter, pmfw->pfw_buf, pmfw->fw_len);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	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,
+			   HOST_INT_STATUS_REG, &sdio_ireg);
+
+	/* Disable host interrupt mask register for SDIO */
+	ret = wlan_disable_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 gets interrupt status.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_interrupt(pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer mbuf;
+	t_u32 sdio_ireg = 0;
+
+	t_u8 max_mp_regs = MAX_MP_REGS;
+	t_u8 host_int_status_reg = HOST_INT_STATUS_REG;
+
+	ENTER();
+
+	memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+	mbuf.pbuf = pmadapter->mp_regs;
+	mbuf.data_len = max_mp_regs;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf,
+				     REG_PORT | MLAN_SDIO_BYTE_MODE_MASK, 0)) {
+		PRINTM(MERROR, "moal_read_data_sync: read registers failed\n");
+		pmadapter->dbg.num_int_read_failure++;
+		goto done;
+	}
+
+	DBG_HEXDUMP(MIF_D, "SDIO MP Registers", pmadapter->mp_regs,
+		    max_mp_regs);
+	sdio_ireg = pmadapter->mp_regs[host_int_status_reg];
+	pmadapter->dbg.last_int_status = pmadapter->sdio_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->num_of_irq++;
+		pcb->moal_spin_lock(pmadapter->pmoal_handle,
+				    pmadapter->pint_lock);
+		pmadapter->sdio_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 enables the host interrupts.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_enable_host_int(pmlan_adapter pmadapter)
+{
+	mlan_status ret;
+	t_u8 mask = HIM_ENABLE;
+
+	ENTER();
+	ret = wlan_sdio_enable_host_int_mask(pmadapter, mask);
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @brief This function try to read the packet when fail to alloc rx buffer
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param port      Current port on which packet needs to be rxed
+ *  @param rx_len    Length of received packet
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_card_to_host_recovery(mlan_adapter *pmadapter, t_u8 port,
+				t_u16 rx_len)
+{
+	mlan_buffer mbuf;
+	t_u32 pkt_type = 0;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	ENTER();
+	if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+		PRINTM(MDATA, "Recovery:do Rx Aggr\n");
+		/* do aggr RX now */
+		wlan_receive_mp_aggr_buf(pmadapter);
+	}
+	memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+	mbuf.pbuf = pmadapter->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->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->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;
+}
+#endif
+
+/**
+ *  @brief This function checks the interrupt status and handle it accordingly.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_process_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;
+	t_u8 rd_len_p0_l = RD_LEN_P0_L;
+	t_u8 rd_len_p0_u = RD_LEN_P0_U;
+	t_u8 cmd_rd_len_0 = CMD_RD_LEN_0;
+	t_u8 cmd_rd_len_1 = CMD_RD_LEN_1;
+
+	ENTER();
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+	sdio_ireg = pmadapter->sdio_ireg;
+	pmadapter->sdio_ireg = 0;
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+
+	if (!sdio_ireg)
+		goto done;
+	/* check the command port */
+	if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS) {
+		if (pmadapter->cmd_sent)
+			pmadapter->cmd_sent = MFALSE;
+		PRINTM(MINFO, "cmd_sent=%d\n", pmadapter->cmd_sent);
+	}
+
+	if (sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) {
+		/* read the len of control packet */
+		rx_len = ((t_u16)pmadapter->mp_regs[cmd_rd_len_1]) << 8;
+		rx_len |= (t_u16)pmadapter->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 <= 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->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%d\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->mp_wr_bitmap & pmadapter->mp_data_port_mask)
+			pmadapter->mp_invalid_update++;
+		pmadapter->mp_wr_bitmap =
+			(t_u32)pmadapter->mp_regs[WR_BITMAP_L];
+		pmadapter->mp_wr_bitmap |=
+			((t_u32)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
+		pmadapter->mp_wr_bitmap |=
+			((t_u32)pmadapter->mp_regs[WR_BITMAP_1L]) << 16;
+		pmadapter->mp_wr_bitmap |=
+			((t_u32)pmadapter->mp_regs[WR_BITMAP_1U]) << 24;
+		bit_count =
+			bitcount(pmadapter->mp_wr_bitmap & pmadapter->
+				 mp_data_port_mask);
+		if (bit_count) {
+			pmadapter->mp_update[bit_count - 1]++;
+			if (pmadapter->mp_update[bit_count - 1] == 0xffffffff)
+				memset(pmadapter, pmadapter->mp_update, 0,
+				       sizeof(pmadapter->mp_update));
+		}
+
+		pmadapter->last_recv_wr_bitmap = pmadapter->mp_wr_bitmap;
+		PRINTM(MINTR, "DNLD: wr_bitmap=0x%08x\n",
+		       pmadapter->mp_wr_bitmap);
+		if (pmadapter->data_sent &&
+		    (pmadapter->
+		     mp_wr_bitmap & (1 << pmadapter->curr_wr_port))) {
+			PRINTM(MINFO, " <--- Tx DONE Interrupt --->\n");
+			pmadapter->data_sent = MFALSE;
+		}
+	}
+
+	if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
+		pmadapter->mp_rd_bitmap =
+			(t_u32)pmadapter->mp_regs[RD_BITMAP_L];
+		pmadapter->mp_rd_bitmap |=
+			((t_u32)pmadapter->mp_regs[RD_BITMAP_U]) << 8;
+		pmadapter->mp_rd_bitmap |=
+			((t_u32)pmadapter->mp_regs[RD_BITMAP_1L]) << 16;
+		pmadapter->mp_rd_bitmap |=
+			((t_u32)pmadapter->mp_regs[RD_BITMAP_1U]) << 24;
+		PRINTM(MINTR, "UPLD: rd_bitmap=0x%08x\n",
+		       pmadapter->mp_rd_bitmap);
+
+		while (MTRUE) {
+			ret = wlan_get_rd_port(pmadapter, &port);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MINFO,
+				       "no more rd_port to be handled\n");
+				break;
+			}
+			len_reg_l = rd_len_p0_l + (port << 1);
+			len_reg_u = rd_len_p0_u + (port << 1);
+			rx_len = ((t_u16)pmadapter->mp_regs[len_reg_u]) << 8;
+			rx_len |= (t_u16)pmadapter->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 defined(SDIO_MULTI_PORT_RX_AGGR)
+			if (rx_len <= INTF_HEADER_LEN ||
+			    (rx_blocks * MLAN_SDIO_BLOCK_SIZE) >
+			    pmadapter->mpa_rx.buf_size) {
+#else
+			if (rx_len <= INTF_HEADER_LEN ||
+			    (rx_blocks * MLAN_SDIO_BLOCK_SIZE) >
+			    ALLOC_BUF_SIZE) {
+#endif
+				PRINTM(MERROR, "invalid rx_len=%d\n", rx_len);
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
+			if (rx_len > MLAN_TX_DATA_BUF_SIZE_2K
+			    && !pmadapter->enable_net_mon)
+				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 defined(SDIO_MULTI_PORT_RX_AGGR)
+				if (MLAN_STATUS_SUCCESS ==
+				    wlan_sdio_card_to_host_recovery(pmadapter,
+								    port,
+								    rx_len))
+					continue;
+#endif
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(MINFO, "rx_len = %d\n", rx_len);
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+			if (MLAN_STATUS_SUCCESS !=
+			    wlan_sdio_card_to_host_mp_aggr(pmadapter, pmbuf,
+							   port, rx_len)) {
+#else
+			/* 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->ioport + port)) {
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+				pmadapter->dbg.num_rx_card_to_host_failure++;
+
+				PRINTM(MERROR,
+				       "Card to host failed: int status=0x%x\n",
+				       sdio_ireg);
+#ifndef SDIO_MULTI_PORT_RX_AGGR
+				wlan_free_mlan_buffer(pmadapter, pmbuf);
+#endif
+				ret = MLAN_STATUS_FAILURE;
+				goto term_cmd53;
+			}
+#ifndef SDIO_MULTI_PORT_RX_AGGR
+			wlan_decode_rx_packet(pmadapter, pmbuf, upld_typ,
+					      MTRUE);
+#endif
+		}
+		/* We might receive data/sleep_cfm at the same time */
+		/* reset data_receive flag to avoid ps_state change */
+		if ((ps_state == PS_STATE_SLEEP_CFM) &&
+		    (pmadapter->ps_state == PS_STATE_SLEEP))
+			pmadapter->data_received = MFALSE;
+	}
+
+	ret = MLAN_STATUS_SUCCESS;
+	goto done;
+
+term_cmd53:
+	/* terminate cmd53 */
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      HOST_TO_CARD_EVENT_REG,
+						      &cr))
+		PRINTM(MERROR, "read CFG reg failed\n");
+	PRINTM(MINFO, "Config Reg val = %d\n", cr);
+	if (MLAN_STATUS_SUCCESS != pcb->moal_write_reg(pmadapter->pmoal_handle,
+						       HOST_TO_CARD_EVENT_REG,
+						       (cr | HOST_TERM_CMD53)))
+		PRINTM(MERROR, "write CFG reg failed\n");
+	PRINTM(MINFO, "write success\n");
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      HOST_TO_CARD_EVENT_REG,
+						      &cr))
+		PRINTM(MERROR, "read CFG reg failed\n");
+	PRINTM(MINFO, "Config reg val =%x\n", cr);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param type      data or command
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include SDIO header)
+ *  @param tx_param  A pointer to mlan_tx_param
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_sdio_host_to_card(mlan_adapter *pmadapter, t_u8 type, mlan_buffer *pmbuf,
+		       mlan_tx_param *tx_param)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 buf_block_len;
+	t_u32 blksz;
+	t_u8 port = 0;
+	t_u32 cmd53_port = 0;
+	t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset;
+
+	ENTER();
+
+	/* Allocate buffer and copy payload */
+	blksz = MLAN_SDIO_BLOCK_SIZE;
+	buf_block_len = (pmbuf->data_len + blksz - 1) / blksz;
+	*(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+	*(t_u16 *)&payload[2] = wlan_cpu_to_le16(type);
+
+	/*
+	 * This is SDIO specific header
+	 *  t_u16 length,
+	 *  t_u16 type (MLAN_TYPE_DATA = 0,
+	 *    MLAN_TYPE_CMD = 1, MLAN_TYPE_EVENT = 3)
+	 */
+	if (type == MLAN_TYPE_DATA) {
+		ret = wlan_get_wr_port_data(pmadapter, &port);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "no wr_port available: wr_bitmap=0x%08x curr_wr_port=%d\n",
+			       pmadapter->mp_wr_bitmap,
+			       pmadapter->curr_wr_port);
+			goto exit;
+		}
+		/* Transfer data to card */
+		pmbuf->data_len = buf_block_len * blksz;
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+		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
+		ret = wlan_write_data_sync(pmadapter, pmbuf,
+					   pmadapter->ioport + port);
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+	} else {
+		/*Type must be MLAN_TYPE_CMD */
+		pmadapter->cmd_sent = MTRUE;
+		if (pmbuf->data_len <= INTF_HEADER_LEN ||
+		    pmbuf->data_len > WLAN_UPLD_SIZE)
+			PRINTM(MWARN,
+			       "wlan_sdio_host_to_card(): Error: payload=%p, nb=%d\n",
+			       payload, pmbuf->data_len);
+		/* Transfer data to card */
+		pmbuf->data_len = buf_block_len * blksz;
+		cmd53_port = (pmadapter->ioport) | CMD_PORT_SLCT;
+		ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port);
+	}
+
+	if (ret == MLAN_STATUS_FAILURE) {
+		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->
+			     mp_wr_bitmap & (1 << pmadapter->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;
+}
+
+/**
+ *  @brief Deaggregate single port aggregation packet
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param buf	A pointer to aggregated data packet
+ *  @param len
+ *
+ *  @return		N/A
+ */
+void
+wlan_decode_spa_buffer(mlan_adapter *pmadapter, t_u8 *buf, t_u32 len)
+{
+	int total_pkt_len;
+	t_u8 block_num = 0;
+	t_u16 block_size = 0;
+	t_u8 *data;
+	t_u32 pkt_len, pkt_type = 0;
+	mlan_buffer *mbuf_deaggr = MNULL;
+
+	ENTER();
+
+	data = (t_u8 *)buf;
+	total_pkt_len = len;
+	if (total_pkt_len < pmadapter->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 + INTF_HEADER_LEN)) {
+		block_num = *(data + OFFSET_OF_BLOCK_NUMBER);
+		block_size = pmadapter->sdio_rx_block_size * block_num;
+		if (block_size > total_pkt_len) {
+			PRINTM(MERROR,
+			       "Error in pkt, block_num=%d, pkt_len=%d\n",
+			       block_num, total_pkt_len);
+			break;
+		}
+		pkt_len =
+			wlan_le16_to_cpu(*(t_u16 *)
+					 (data + OFFSET_OF_SDIO_HEADER));
+		pkt_type =
+			wlan_le16_to_cpu(*(t_u16 *)
+					 (data + OFFSET_OF_SDIO_HEADER + 2));
+		if ((pkt_len + OFFSET_OF_SDIO_HEADER) > block_size) {
+			PRINTM(MERROR,
+			       "Error in pkt, pkt_len=%d, block_size=%d\n",
+			       pkt_len, block_size);
+			break;
+		}
+		mbuf_deaggr =
+			wlan_alloc_mlan_buffer(pmadapter,
+					       pkt_len - 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(pmadapter, mbuf_deaggr->pbuf + mbuf_deaggr->data_offset,
+		       data + OFFSET_OF_SDIO_HEADER + INTF_HEADER_LEN,
+		       pkt_len - INTF_HEADER_LEN);
+		mbuf_deaggr->data_len = pkt_len - INTF_HEADER_LEN;
+		wlan_handle_rx_packet(pmadapter, mbuf_deaggr);
+		data += block_size;
+		total_pkt_len -= block_size;
+		if (total_pkt_len < pmadapter->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(IN 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);
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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(IN mlan_adapter *pmadapter,
+			    t_u32 mpa_tx_buf_size, t_u32 mpa_rx_buf_size)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+
+	ENTER();
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	if ((pmadapter->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->max_seg_size < pmadapter->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->mpa_tx.head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mpa_tx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP TX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->mpa_tx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->mpa_tx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable TX SG mode\n");
+		pmadapter->mpa_tx.head_ptr = MNULL;
+		pmadapter->mpa_tx.buf = MNULL;
+	}
+	pmadapter->mpa_tx.buf_size = mpa_tx_buf_size;
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	if ((pmadapter->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->max_seg_size < pmadapter->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->mpa_rx.head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mpa_rx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP RX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->mpa_rx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->mpa_rx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable RX SG mode\n");
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+	}
+	pmadapter->mpa_rx.buf_size = mpa_rx_buf_size;
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+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(IN mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	if (pmadapter->mpa_tx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mpa_tx.head_ptr);
+		pmadapter->mpa_tx.head_ptr = MNULL;
+		pmadapter->mpa_tx.buf = MNULL;
+		pmadapter->mpa_tx.buf_size = 0;
+	}
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	if (pmadapter->mpa_rx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mpa_rx.head_ptr);
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+		pmadapter->mpa_rx.buf_size = 0;
+	}
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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(IN mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+
+	t_u32 mpa_rx_buf_size = SDIO_MP_RX_AGGR_DEF_BUF_SIZE;
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	if (pmadapter->mpa_rx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->mpa_rx.head_ptr);
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+		pmadapter->mpa_rx.buf_size = 0;
+	}
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+	if (pmadapter->sdio_rx_aggr_enable)
+		mpa_rx_buf_size = MAX(mpa_rx_buf_size, SDIO_CMD53_MAX_SIZE);
+	if ((pmadapter->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->max_seg_size < pmadapter->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->mpa_rx.head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mpa_rx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP RX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->mpa_rx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->mpa_rx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable RX SG mode\n");
+		pmadapter->mpa_rx.head_ptr = MNULL;
+		pmadapter->mpa_rx.buf = MNULL;
+	}
+	pmadapter->mpa_rx.buf_size = mpa_rx_buf_size;
+	PRINTM(MMSG, "mpa_rx_buf_size=%d\n", mpa_rx_buf_size);
+error:
+	return ret;
+}
+#endif
+
+#endif /* SDIO_MULTI_PORT_TX_AGGR || SDIO_MULTI_PORT_RX_AGGR */
+
+/**
+ *  @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(IN 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->int_mode == INT_MODE_GPIO) {
+		if (pmadapter->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->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,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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(pmpriv->adapter, psdio_gpio_int, pdata_buf,
+		       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;
+}
+
+#define FW_RESET_REG  0x0EE
+#define FW_RESET_VAL  0x99
+mlan_status
+wlan_reset_fw(pmlan_adapter pmadapter)
+{
+	t_u32 tries = 0;
+	t_u32 value = 1;
+	t_u32 reset_reg = FW_RESET_REG;
+	t_u8 reset_val = FW_RESET_VAL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	wlan_pm_wakeup_card(pmadapter);
+
+    /** 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;
+	}
+	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);
+	/* 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;
+}
diff --git a/wlan_sd8997/mlan/mlan_sdio.h b/wlan_sd8997/mlan/mlan_sdio.h
new file mode 100644
index 0000000..44a7e03
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_sdio.h
@@ -0,0 +1,440 @@
+/** @file mlan_sdio.h
+ *
+ *  @brief This file contains definitions for SDIO interface.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+/****************************************************
+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 : Host interrupt RSR */
+#define HOST_INT_RSR_REG		0x04
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR		(0x1U)
+#define HOST_INT_RSR_MASK		0xFF
+
+/** Host Control Registers : Host interrupt mask */
+#define HOST_INT_MASK_REG		0x08
+
+/** 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 : Host interrupt status */
+#define HOST_INT_STATUS_REG		0x0C
+
+/** 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 status */
+#define UP_LD_HOST_INT_STATUS		(0x1U)
+/** Host Control Registers : Download host interrupt status */
+#define DN_LD_HOST_INT_STATUS		(0x2U)
+
+/** Port for registers */
+#define REG_PORT			0
+/** Port for memory */
+#define MEM_PORT			0x10000
+/** LSB of read bitmap */
+#define RD_BITMAP_L			0x10
+/** MSB of read bitmap */
+#define RD_BITMAP_U			0x11
+/** LSB of read bitmap second word */
+#define RD_BITMAP_1L		0x12
+/** MSB of read bitmap second word */
+#define RD_BITMAP_1U		0x13
+/** LSB of write bitmap */
+#define WR_BITMAP_L			0x14
+/** MSB of write bitmap */
+#define WR_BITMAP_U			0x15
+/** LSB of write bitmap second word */
+#define WR_BITMAP_1L		0x16
+/** MSB of write bitmap second word */
+#define WR_BITMAP_1U		0x17
+/** LSB of read length for port 0 */
+#define RD_LEN_P0_L			0x18
+/** MSB of read length for port 0 */
+#define RD_LEN_P0_U			0x19
+
+/* Card Control Registers : Command port read length 0 */
+#define CMD_RD_LEN_0   0xC0
+/* Card Control Registers : Command port read length 1 */
+#define CMD_RD_LEN_1   0xC1
+/* Card Control Registers : Command port read length 2 (reserved)  */
+#define CMD_RD_LEN_2   0xC2
+/* Card Control Registers : Command port read length 3  */
+#define CMD_RD_LEN_3   0xC3
+/* Card Control Registers : Command port configuration 0 */
+#define CMD_CONFIG_0   0xC4
+#define CMD_PORT_RD_LEN_EN            (0x1U << 2)
+/* Card Control Registers : Command port configuration 1 */
+#define CMD_CONFIG_1   0xC5
+/* Card Control Registers : cmd port auto enable */
+#define CMD_PORT_AUTO_EN              (0x1U << 0)
+/* Card Control Registers : Command port configuration 2 (reserved) */
+#define CMD_CONFIG_2   0xC6
+/* Card Control Registers : Command port configuration 3 (reserved) */
+#define CMD_CONFIG_3   0xC7
+
+/* Command port */
+#define CMD_PORT_SLCT			0x8000
+/** Data port mask */
+#define DATA_PORT_MASK			0xffffffff
+
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT		MBIT(4)
+
+/** Host Control Registers : Host transfer status */
+#define HOST_RESTART_REG		0x58
+/** 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 */
+/** Card Control Registers : Card to host event */
+#define CARD_TO_HOST_EVENT_REG		0x5C
+/** 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 interrupt mask register */
+#define HOST_INTERRUPT_MASK_REG		0x60
+/** 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 : Card interrupt status register */
+#define CARD_INTERRUPT_STATUS_REG	0x64
+/** 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 : Card interrupt RSR register */
+#define CARD_INTERRUPT_RSR_REG		0x68
+/** 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 : SQ Read base address 0 register */
+#define READ_BASE_0_REG			0xf8
+/** Card Control Registers : SQ Read base address 1 register */
+#define READ_BASE_1_REG			0xf9
+/** 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
+
+/** Card Control Registers : Card revision register */
+#define CARD_REVISION_REG		0xC8
+
+/** Firmware status 0 register (SCRATCH0_0) */
+#define CARD_FW_STATUS0_REG		0xe8
+/** Firmware status 1 register (SCRATCH0_1) */
+#define CARD_FW_STATUS1_REG		0xe9
+/** Rx length register (SCRATCH0_2) */
+#define CARD_RX_LEN_REG			0xea
+/** Rx unit register (SCRATCH0_3) */
+#define CARD_RX_UNIT_REG		0xeb
+
+/** Card Control Registers : Card OCR 0 register */
+#define CARD_OCR_0_REG			0xD4
+/** Card Control Registers : Card OCR 1 register */
+#define CARD_OCR_1_REG			0xD5
+/** Card Control Registers : Card OCR 3 register */
+#define CARD_OCR_3_REG			0xD6
+/** Card Control Registers : Card config register */
+#define CARD_CONFIG_REG			0xD7
+/** Card Control Registers : Miscellaneous Configuration Register */
+#define CARD_MISC_CFG_REG		0xD8
+
+/** Card Control Registers : sdio new mode register 1 */
+#define CARD_CONFIG_2_1_REG             0xD9
+/** 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)
+
+/** Card Control Registers : sdio new mode register 2 */
+#define CARD_CONFIG_2_2_REG             0xDA
+/** Card Control Registers : test data out (0x01) */
+#define TEST_DATA_OUT_1           (0x1U << 0)
+/** Card Control Registers : test data out (0x02) */
+#define TEST_DATA_OUT_2           (0x1U << 1)
+/** Card Control Registers : test data out (0x04) */
+#define TEST_DATA_OUT_3           (0x1U << 2)
+/** Card Control Registers : test data out (0x08) */
+#define TEST_DATA_OUT_4           (0x1U << 3)
+/** Card Control Registers : test cmd out (0x10) */
+#define TEST_CMD_OUT			(0x1U << 4)
+
+/** Card Control Registers : sdio new mode register 3 */
+#define CARD_CONFIG_2_3_REG             0xDB
+/** Card Control Registers : test data enable (0x01) */
+#define TEST_DATA_EN_1           (0x1U << 0)
+/** Card Control Registers : test data enable (0x02) */
+#define TEST_DATA_EN_2           (0x1U << 1)
+/** Card Control Registers : test data enable (0x04) */
+#define TEST_DATA_EN_3           (0x1U << 2)
+/** Card Control Registers : test data enable (0x08) */
+#define TEST_DATA_EN_4           (0x1U << 3)
+/** Card Control Registers : test cmd enable (0x10) */
+#define TEST_CMD_EN		(0x1U << 4)
+/** Card Control Registers : test mode (0x20) */
+#define TEST_MODE			(0x1U << 5)
+
+/** Card Control Registers : Debug 0 register */
+#define DEBUG_0_REG			0xDC
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0			(0x1U)
+/** Card Control Registers : Debug 1 register */
+#define DEBUG_1_REG			0xDD
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1			(0x1U)
+/** Card Control Registers : Debug 2 register */
+#define DEBUG_2_REG			0xDE
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2			(0x1U)
+/** Card Control Registers : Debug 3 register */
+#define DEBUG_3_REG			0xDF
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3			(0x1U)
+
+/** Host Control Registers : I/O port 0 */
+#define IO_PORT_0_REG			0xE4
+/** Host Control Registers : I/O port 1 */
+#define IO_PORT_1_REG			0xE5
+/** Host Control Registers : I/O port 2 */
+#define IO_PORT_2_REG			0xE6
+
+#define FW_RESET_REG  0x0EE
+#define FW_RESET_VAL  0x99
+
+/** Event header Len*/
+#define MLAN_EVENT_HEADER_LEN           8
+
+/** SDIO byte mode size */
+#define MAX_BYTE_MODE_SIZE             512
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** The base address for packet with multiple ports aggregation */
+#define SDIO_MPA_ADDR_BASE             0x1000
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+
+/** SDIO Tx aggregation in progress ? */
+#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0)
+
+/** SDIO Tx aggregation buffer room for next packet ? */
+#define MP_TX_AGGR_BUF_HAS_ROOM(a, mbuf, len) \
+			(((a->mpa_tx.buf_len) + len) <= (a->mpa_tx.buf_size))
+
+/** Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */
+#define MP_TX_AGGR_BUF_PUT(a, mbuf, port) do {          \
+	pmadapter->callbacks.moal_memmove(a->pmoal_handle, \
+		&a->mpa_tx.buf[a->mpa_tx.buf_len], \
+		mbuf->pbuf+mbuf->data_offset, mbuf->data_len);\
+	a->mpa_tx.buf_len += mbuf->data_len;                \
+	a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = \
+		*(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+	if (!a->mpa_tx.pkt_cnt) {                           \
+		a->mpa_tx.start_port = port;                    \
+	}                                                   \
+	a->mpa_tx.ports |= (1 << port);                     \
+	a->mpa_tx.pkt_cnt++;                                \
+} while (0)
+
+#define MP_TX_AGGR_BUF_PUT_SG(a, mbuf, port) do {       \
+	a->mpa_tx.buf_len += mbuf->data_len;                \
+	a->mpa_tx.mp_wr_info[a->mpa_tx.pkt_cnt] = \
+		*(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+	a->mpa_tx.mbuf_arr[a->mpa_tx.pkt_cnt] = mbuf;       \
+	if (!a->mpa_tx.pkt_cnt) {                           \
+		a->mpa_tx.start_port = port;                    \
+	}                                                   \
+	a->mpa_tx.ports |= (1 << port);                     \
+	a->mpa_tx.pkt_cnt++;                                \
+} while (0)
+/** SDIO Tx aggregation limit ? */
+#define MP_TX_AGGR_PKT_LIMIT_REACHED(a) ((a->mpa_tx.pkt_cnt) \
+			== (a->mpa_tx.pkt_aggr_limit))
+
+/** SDIO Tx aggregation port limit ? */
+#define MP_TX_AGGR_PORT_LIMIT_REACHED(a)    (MFALSE)
+
+/** Reset SDIO Tx aggregation buffer parameters */
+#define MP_TX_AGGR_BUF_RESET(a) do {         \
+	memset(a, a->mpa_tx.mp_wr_info, 0, sizeof(a->mpa_tx.mp_wr_info)); \
+	a->mpa_tx.pkt_cnt = 0;                   \
+	a->mpa_tx.buf_len = 0;                   \
+	a->mpa_tx.ports = 0;                     \
+	a->mpa_tx.start_port = 0;                \
+} while (0)
+
+#endif /* SDIO_MULTI_PORT_TX_AGGR */
+
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+
+/** SDIO Rx aggregation limit ? */
+#define MP_RX_AGGR_PKT_LIMIT_REACHED(a) (a->mpa_rx.pkt_cnt \
+		== a->mpa_rx.pkt_aggr_limit)
+
+/** SDIO Rx aggregation 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->curr_rd_port < a->mpa_rx.start_port) && \
+		(((MAX_PORT - a->mpa_rx.start_port) + a->curr_rd_port) \
+		>= (a->mp_end_port >> 1))) || \
+		((a->curr_rd_port - a->mpa_rx.start_port) >= \
+		(a->mp_end_port >> 1)))
+
+/** SDIO Rx aggregation in progress ? */
+#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0)
+
+/** SDIO Rx aggregation buffer room for next packet ? */
+#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len)   \
+	((a->mpa_rx.buf_len + rx_len) <= a->mpa_rx.buf_size)
+
+/** Prepare to copy current packet from card to SDIO Rx aggregation buffer */
+#define MP_RX_AGGR_SETUP(a, mbuf, port, rx_len) do {   \
+	a->mpa_rx.buf_len += rx_len;                       \
+	if (!a->mpa_rx.pkt_cnt) {                          \
+		a->mpa_rx.start_port = port;                   \
+	}                                                  \
+	a->mpa_rx.ports |= (1 << port);                    \
+	a->mpa_rx.mbuf_arr[a->mpa_rx.pkt_cnt] = mbuf;      \
+	a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = rx_len;     \
+	a->mpa_rx.pkt_cnt++;                              \
+} while (0)
+
+/** Reset SDIO Rx aggregation buffer parameters */
+#define MP_RX_AGGR_BUF_RESET(a) do {         \
+	a->mpa_rx.pkt_cnt = 0;                   \
+	a->mpa_rx.buf_len = 0;                   \
+	a->mpa_rx.ports = 0;                     \
+	a->mpa_rx.start_port = 0;                \
+} while (0)
+
+#endif /* SDIO_MULTI_PORT_RX_AGGR */
+
+/** Enable host interrupt */
+mlan_status wlan_enable_host_int(pmlan_adapter pmadapter);
+/** Probe and initialization function */
+mlan_status wlan_sdio_probe(pmlan_adapter pmadapter);
+/** multi interface download check */
+mlan_status wlan_check_winner_status(mlan_adapter *pmadapter, t_u32 *val);
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+mlan_status wlan_send_mp_aggr_buf(mlan_adapter *pmadapter);
+#endif
+
+#if defined(SDIO_MULTI_PORT_RX_AGGR)
+mlan_status wlan_re_alloc_sdio_rx_mpa_buffer(IN mlan_adapter *pmadapter);
+#endif
+
+void wlan_decode_spa_buffer(mlan_adapter *pmadapter, t_u8 *buf, t_u32 len);
+t_void wlan_sdio_deaggr_rx_pkt(IN pmlan_adapter pmadapter, mlan_buffer *pmbuf);
+/** Firmware status check */
+mlan_status wlan_check_fw_status(mlan_adapter *pmadapter, t_u32 pollnum);
+/** Read interrupt status */
+mlan_status wlan_interrupt(pmlan_adapter pmadapter);
+/** Process Interrupt Status */
+mlan_status wlan_process_int_status(mlan_adapter *pmadapter);
+/** 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(IN pmlan_private priv);
+mlan_status wlan_cmd_sdio_gpio_int(pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *cmd,
+				   IN t_u16 cmd_action, IN t_void *pdata_buf);
+mlan_status wlan_reset_fw(pmlan_adapter pmadapter);
+#endif /* _MLAN_SDIO_H */
diff --git a/wlan_sd8997/mlan/mlan_shim.c b/wlan_sd8997/mlan/mlan_shim.c
new file mode 100644
index 0000000..30cd0ba
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_shim.c
@@ -0,0 +1,1466 @@
+/** @file mlan_shim.c
+ *
+ *  @brief This file contains APIs to MOAL module.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/**
+ *  @mainpage MLAN Driver
+ *
+ *  @section overview_sec Overview
+ *
+ *  The MLAN is an OS independent WLAN driver for Marvell 802.11
+ *  embedded chipset.
+ *
+ *  @section copyright_sec Copyright
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell International Ltd
+ *  or its suppliers and licensors. The Material contains trade secrets and
+ *  proprietary and confidential information of Marvell or its suppliers and
+ *  licensors. The Material is protected by worldwide copyright and trade secret
+ *  laws and treaty provisions. No part of the Material may be used, copied,
+ *  reproduced, modified, published, uploaded, posted, transmitted, distributed,
+ *  or disclosed in any way without Marvell's prior express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/13/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_sdio.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+#include "mlan_11h.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+#ifdef STA_SUPPORT
+mlan_operations mlan_sta_ops = {
+	/* init cmd handler */
+	wlan_ops_sta_init_cmd,
+	/* ioctl handler */
+	wlan_ops_sta_ioctl,
+	/* cmd handler */
+	wlan_ops_sta_prepare_cmd,
+	/* cmdresp handler */
+	wlan_ops_sta_process_cmdresp,
+	/* rx handler */
+	wlan_ops_sta_process_rx_packet,
+	/* Event handler */
+	wlan_ops_sta_process_event,
+	/* txpd handler */
+	wlan_ops_sta_process_txpd,
+	/* BSS role: STA */
+	MLAN_BSS_ROLE_STA,
+};
+#endif
+#ifdef UAP_SUPPORT
+mlan_operations mlan_uap_ops = {
+	/* init cmd handler */
+	wlan_ops_uap_init_cmd,
+	/* ioctl handler */
+	wlan_ops_uap_ioctl,
+	/* cmd handler */
+	wlan_ops_uap_prepare_cmd,
+	/* cmdresp handler */
+	wlan_ops_uap_process_cmdresp,
+	/* rx handler */
+	wlan_ops_uap_process_rx_packet,
+	/* Event handler */
+	wlan_ops_uap_process_event,
+	/* txpd handler */
+	wlan_ops_uap_process_txpd,
+	/* BSS role: uAP */
+	MLAN_BSS_ROLE_UAP,
+};
+#endif
+
+/** mlan function table */
+mlan_operations *mlan_ops[] = {
+#ifdef STA_SUPPORT
+	&mlan_sta_ops,
+#endif
+#ifdef UAP_SUPPORT
+	&mlan_uap_ops,
+#endif
+	MNULL,
+};
+
+/** Global moal_assert callback */
+t_void (*assert_callback) (IN t_void *pmoal_handle, IN 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) (IN t_void *pmoal_handle,
+			  IN t_u32 level, IN char *pformat, IN ...
+	) = MNULL;
+
+/** Global moal_get_system_time callback */
+mlan_status (*get_sys_time_callback) (IN t_void *pmoal_handle,
+				      OUT t_u32 *psec,
+				      OUT t_u32 *pusec) = MNULL;
+
+/** Global driver debug mit masks */
+t_u32 mlan_drvdbg = DEFAULT_DEBUG_MASK;
+#endif
+
+/********************************************************
+			Local Functions
+*******************************************************/
+/**
+ *  @brief This function process pending ioctl
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ */
+void
+wlan_process_pending_ioctl(mlan_adapter *pmadapter)
+{
+	pmlan_ioctl_req pioctl_buf;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	mlan_ds_bss *bss = MNULL;
+#endif
+#ifdef STA_SUPPORT
+	mlan_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\n");
+				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 (
+ *   IN pmlan_device     pmdevice,
+ *   OUT 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(IN pmlan_device pmdevice, OUT 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_memset);
+	MASSERT(pmdevice->callbacks.moal_memmove);
+
+	if (!pmdevice->callbacks.moal_malloc ||
+	    !pmdevice->callbacks.moal_memset ||
+	    !pmdevice->callbacks.moal_memmove) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Allocate memory for adapter structure */
+	if (pmdevice->callbacks.moal_vmalloc && pmdevice->callbacks.moal_vfree)
+		ret = pmdevice->callbacks.moal_vmalloc(pmdevice->pmoal_handle,
+						       sizeof(mlan_adapter),
+						       (t_u8 **)&pmadapter);
+	else
+		ret = pmdevice->callbacks.moal_malloc(pmdevice->pmoal_handle,
+						      sizeof(mlan_adapter),
+						      MLAN_MEM_DEF,
+						      (t_u8 **)&pmadapter);
+	if ((ret != MLAN_STATUS_SUCCESS) || !pmadapter) {
+		ret = MLAN_STATUS_FAILURE;
+		goto exit_register;
+	}
+
+	pmdevice->callbacks.moal_memset(pmdevice->pmoal_handle, pmadapter,
+					0, sizeof(mlan_adapter));
+
+	pcb = &pmadapter->callbacks;
+
+	/* Save callback functions */
+	pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
+					 &pmdevice->callbacks,
+					 sizeof(mlan_callbacks));
+
+	/* Assertion for all callback functions */
+	MASSERT(pcb->moal_get_hw_spec_complete);
+	MASSERT(pcb->moal_init_fw_complete);
+	MASSERT(pcb->moal_shutdown_fw_complete);
+	MASSERT(pcb->moal_send_packet_complete);
+	MASSERT(pcb->moal_recv_packet);
+	MASSERT(pcb->moal_recv_event);
+	MASSERT(pcb->moal_ioctl_complete);
+
+	MASSERT(pcb->moal_write_reg);
+	MASSERT(pcb->moal_read_reg);
+	MASSERT(pcb->moal_alloc_mlan_buffer);
+	MASSERT(pcb->moal_free_mlan_buffer);
+	MASSERT(pcb->moal_write_data_sync);
+	MASSERT(pcb->moal_read_data_sync);
+	MASSERT(pcb->moal_mfree);
+	MASSERT(pcb->moal_memcpy);
+	MASSERT(pcb->moal_memcmp);
+	MASSERT(pcb->moal_get_system_time);
+	MASSERT(pcb->moal_init_timer);
+	MASSERT(pcb->moal_free_timer);
+	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;
+
+	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;
+	}
+#ifdef DEBUG_LEVEL1
+	mlan_drvdbg = pmdevice->drvdbg;
+#endif
+
+#ifdef MFG_CMD_SUPPORT
+	pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
+#endif
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	pmadapter->max_segs = pmdevice->max_segs;
+	pmadapter->max_seg_size = pmdevice->max_seg_size;
+#endif
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
+#endif
+	pmadapter->sdio_rx_aggr_enable = pmdevice->sdio_rx_aggr_enable;
+	pmadapter->init_para.auto_ds = pmdevice->auto_ds;
+	pmadapter->init_para.ps_mode = pmdevice->ps_mode;
+	if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
+	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
+	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_12K ||
+	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
+		pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;
+#ifdef STA_SUPPORT
+	pmadapter->init_para.cfg_11d = pmdevice->cfg_11d;
+#else
+	pmadapter->init_para.cfg_11d = 0;
+#endif
+	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->fixed_beacon_buffer = pmdevice->fixed_beacon_buffer;
+
+	pmadapter->multiple_dtim = pmdevice->multi_dtim;
+	pmadapter->inact_tmo = pmdevice->inact_tmo;
+	pmadapter->init_para.drcs_chantime_mode = pmdevice->drcs_chantime_mode;
+	pmadapter->init_para.fw_region = pmdevice->fw_region;
+	pmadapter->hs_wake_interval = pmdevice->hs_wake_interval;
+	if (pmdevice->indication_gpio != 0xff) {
+		pmadapter->ind_gpio = pmdevice->indication_gpio & 0x0f;
+		pmadapter->level = (pmdevice->indication_gpio & 0xf0) >> 4;
+		if (pmadapter->level != 0 && pmadapter->level != 1) {
+			PRINTM(MERROR,
+			       "Indication GPIO level is wrong and will use default value 0.\n");
+			pmadapter->level = 0;
+		}
+	}
+
+	pmadapter->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(pmadapter, &pmadapter->priv[0]->ops, mlan_ops[j],
+			       sizeof(mlan_operations));
+		}
+	}
+    /** back up bss_attr table */
+	memcpy(pmadapter, pmadapter->bss_attr, pmdevice->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 timers */
+	wlan_free_timer(pmadapter);
+	/* Free adapter structure */
+	wlan_free_adapter(pmadapter);
+	/* Free lock variables */
+	wlan_free_lock_list(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
+				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
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+
+exit_register:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function unregisters MOAL from MLAN module.
+ *
+ *  @param pmlan_adapter   A pointer to a mlan_device structure
+ *                         allocated in MOAL
+ *
+ *  @return                MLAN_STATUS_SUCCESS
+ *                             The deregistration succeeded.
+ */
+mlan_status
+mlan_unregister(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_callbacks pcb;
+	t_s32 i = 0;
+
+	MASSERT(pmlan_adapter);
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+	/* Free adapter structure */
+	wlan_free_adapter(pmadapter);
+
+	/* Free timers */
+	wlan_free_timer(pmadapter);
+
+	/* Free lock variables */
+	wlan_free_lock_list(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
+				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
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads the firmware
+ *
+ *  @param pmlan_adapter   A pointer to a t_void pointer to store
+ *                         mlan_adapter structure pointer
+ *  @param pmfw            A pointer to firmware image
+ *
+ *  @return                MLAN_STATUS_SUCCESS
+ *                             The firmware download succeeded.
+ *                         MLAN_STATUS_FAILURE
+ *                             The firmware download failed.
+ */
+mlan_status
+mlan_dnld_fw(IN t_void *pmlan_adapter, IN pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	t_u32 poll_num = 1;
+	t_u32 winner = 0;
+
+	ENTER();
+	MASSERT(pmlan_adapter);
+
+/*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_check_fw_status(pmadapter, poll_num);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		if (pmfw->fw_reload) {
+			ret = wlan_reset_fw(pmadapter);
+			if (ret == MLAN_STATUS_FAILURE) {
+				PRINTM(MERROR, "FW reset failure!");
+				LEAVE();
+				return ret;
+			}
+		} else {
+			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_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;
+	}
+
+	if (pmfw) {
+		/* Download helper/firmware */
+		ret = wlan_dnld_fw(pmadapter, pmfw);
+		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_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_host_int(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function pass init param to MLAN
+ *
+ *  @param pmlan_adapter  A pointer to a t_void pointer to store
+ *                        mlan_adapter structure pointer
+ *  @param pparam         A pointer to mlan_init_param structure
+ *
+ *  @return               MLAN_STATUS_SUCCESS
+ *
+ */
+mlan_status
+mlan_set_init_param(IN t_void *pmlan_adapter, IN pmlan_init_param pparam)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+	ENTER();
+	MASSERT(pmlan_adapter);
+
+    /** Save DPD data in MLAN */
+	if ((pparam->pdpd_data_buf) && (pparam->dpd_data_len > 0)) {
+		pmadapter->pdpd_data = pparam->pdpd_data_buf;
+		pmadapter->dpd_data_len = pparam->dpd_data_len;
+	}
+	if (pparam->ptxpwr_data_buf && (pparam->txpwr_data_len > 0)) {
+		pmadapter->ptxpwr_data = pparam->ptxpwr_data_buf;
+		pmadapter->txpwr_data_len = pparam->txpwr_data_len;
+	}
+    /** Save cal data in MLAN */
+	if ((pparam->pcal_data_buf) && (pparam->cal_data_len > 0)) {
+		pmadapter->pcal_data = pparam->pcal_data_buf;
+		pmadapter->cal_data_len = pparam->cal_data_len;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes the firmware
+ *
+ *  @param pmlan_adapter   A pointer to a t_void pointer to store
+ *                         mlan_adapter structure pointer
+ *
+ *  @return                MLAN_STATUS_SUCCESS
+ *                             The firmware initialization succeeded.
+ *                         MLAN_STATUS_PENDING
+ *                             The firmware initialization is pending.
+ *                         MLAN_STATUS_FAILURE
+ *                             The firmware initialization failed.
+ */
+mlan_status
+mlan_init_fw(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+	ENTER();
+	MASSERT(pmlan_adapter);
+
+	pmadapter->hw_status = WlanHardwareStatusGetHwSpec;
+
+	/* Initialize firmware, may return PENDING */
+	ret = wlan_init_fw(pmadapter);
+	PRINTM(MINFO, "wlan_init_fw returned ret=0x%x\n", ret);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Shutdown firmware
+ *
+ *  @param pmlan_adapter    A pointer to mlan_adapter structure
+ *
+ *  @return     MLAN_STATUS_SUCCESS
+ *                              The firmware shutdown call succeeded.
+ *              MLAN_STATUS_PENDING
+ *                              The firmware shutdown call is pending.
+ *              MLAN_STATUS_FAILURE
+ *                              The firmware shutdown call failed.
+ */
+mlan_status
+mlan_shutdown_fw(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_PENDING;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_buffer pmbuf;
+	pmlan_ioctl_req pioctl_buf;
+	pmlan_callbacks pcb;
+	t_s32 i = 0;
+
+	ENTER();
+
+	MASSERT(pmlan_adapter);
+	/* MLAN already shutdown */
+	if (pmadapter->hw_status == WlanHardwareStatusNotReady) {
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	pmadapter->hw_status = WlanHardwareStatusClosing;
+	/* Wait for mlan_process to complete */
+	if (pmadapter->mlan_processing) {
+		PRINTM(MWARN, "MLAN main processing is still running\n");
+		LEAVE();
+		return ret;
+	}
+
+	/* Shut down MLAN */
+	PRINTM(MINFO, "Shutdown MLAN...\n");
+
+	/* Cancel all pending commands and complete ioctls */
+	wlan_cancel_all_pending_cmd(pmadapter);
+
+	/* 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))) {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+	pmadapter->rx_pkts_queued = 0;
+
+	/* Notify completion */
+	ret = wlan_shutdown_fw_complete(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief queue main work
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return			N/A
+ */
+static t_void
+mlan_queue_main_work(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmain_proc_lock);
+
+	/* Check if already processing */
+	if (pmadapter->mlan_processing) {
+		pmadapter->more_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+	} else {
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+		wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+				MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief queue rx_work
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return			N/A
+ */
+static t_void
+mlan_queue_rx_work(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+
+	/* Check if already processing */
+	if (pmadapter->mlan_rx_processing) {
+		pmadapter->more_rx_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+	} else {
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+		wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
+				MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief block main process
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param block            MTRUE/MFALSE
+ *
+ *  @return			N/A
+ */
+void
+mlan_block_main_process(mlan_adapter *pmadapter, t_u8 block)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmain_proc_lock);
+	if (!block) {
+		pmadapter->main_lock_flag = MFALSE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+	} else {
+		pmadapter->main_lock_flag = MTRUE;
+		if (pmadapter->mlan_processing) {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->pmain_proc_lock);
+			PRINTM(MEVENT, "wlan: wait main work done...\n");
+			wlan_recv_event(wlan_get_priv
+					(pmadapter, MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK,
+					MNULL);
+		} else {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->pmain_proc_lock);
+		}
+	}
+}
+
+/**
+ *  @brief block rx process
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param block            MTRUE/MFALSE;
+ *
+ *  @return			N/A
+ */
+void
+mlan_block_rx_process(mlan_adapter *pmadapter, t_u8 block)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+	if (!block) {
+		pmadapter->rx_lock_flag = MFALSE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+	} else {
+		pmadapter->rx_lock_flag = MTRUE;
+		if (pmadapter->mlan_rx_processing) {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->prx_proc_lock);
+			PRINTM(MEVENT, "wlan: wait rx work done...\n");
+			wlan_recv_event(wlan_get_priv
+					(pmadapter, MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
+		} else {
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->prx_proc_lock);
+		}
+	}
+}
+
+/**
+ *  @brief The receive process
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param rx_pkts		    A pointer to save receive pkts number
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_callbacks pcb;
+	pmlan_buffer pmbuf;
+	t_u8 limit = 0;
+	t_u8 rx_num = 0;
+
+	ENTER();
+
+	MASSERT(pmlan_adapter);
+	pcb = &pmadapter->callbacks;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+	if (pmadapter->mlan_rx_processing || pmadapter->rx_lock_flag) {
+		pmadapter->more_rx_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+		goto exit_rx_proc;
+	} else {
+		pmadapter->mlan_rx_processing = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+	}
+	if (rx_pkts)
+		limit = *rx_pkts;
+
+rx_process_start:
+	/* Check for Rx data */
+	while (MTRUE) {
+		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);
+		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);
+		}
+		wlan_sdio_deaggr_rx_pkt(pmadapter, pmbuf);
+		if (limit && rx_num >= limit)
+			break;
+	}
+	if (rx_pkts)
+		*rx_pkts = rx_num;
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
+	if (pmadapter->more_rx_task_flag) {
+		pmadapter->more_rx_task_flag = MFALSE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->prx_proc_lock);
+		goto rx_process_start;
+	}
+	pmadapter->mlan_rx_processing = MFALSE;
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+			      pmadapter->prx_proc_lock);
+exit_rx_proc:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief The main process
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+mlan_main_process(IN t_void *pmlan_adapter
+	)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	MASSERT(pmlan_adapter);
+
+	pcb = &pmadapter->callbacks;
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmain_proc_lock);
+
+	/* Check if already processing */
+	if (pmadapter->mlan_processing || pmadapter->main_lock_flag) {
+		pmadapter->more_task_flag = MTRUE;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+		goto exit_main_proc;
+	} else {
+		pmadapter->mlan_processing = MTRUE;
+		pmadapter->main_process_cnt++;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pmain_proc_lock);
+	}
+process_start:
+	do {
+		/* Is MLAN shutting down or not ready? */
+		if ((pmadapter->hw_status == WlanHardwareStatusClosing) ||
+		    (pmadapter->hw_status == WlanHardwareStatusNotReady))
+			break;
+		if (pmadapter->pending_ioctl) {
+			wlan_process_pending_ioctl(pmadapter);
+			pmadapter->pending_ioctl = MFALSE;
+		}
+		if (pmadapter->rx_pkts_queued > HIGH_RX_PENDING) {
+			PRINTM(MEVENT, "Pause\n");
+			pmadapter->delay_task_flag = MTRUE;
+			mlan_queue_rx_work(pmadapter);
+			break;
+		}
+		/* Handle pending SDIO interrupts if any */
+		if (pmadapter->sdio_ireg) {
+			if (pmadapter->hs_activated == MTRUE)
+				wlan_process_hs_config(pmadapter);
+			wlan_process_int_status(pmadapter);
+			if (pmadapter->data_received && pmadapter->rx_work_flag)
+				mlan_queue_rx_work(pmadapter);
+		}
+
+		/* 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)
+		    )) {
+			wlan_pm_wakeup_card(pmadapter);
+			pmadapter->pm_wakeup_fw_try = MTRUE;
+			continue;
+		}
+		if (IS_CARD_RX_RCVD(pmadapter)) {
+			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;
+		} 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)
+					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)
+				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;
+		}
+
+		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 pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param pmbuf		A pointer to mlan_buffer structure
+ *
+ *  @return			MLAN_STATUS_PENDING
+ */
+mlan_status
+mlan_send_packet(IN t_void *pmlan_adapter, IN pmlan_buffer pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_PENDING;
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	mlan_private *pmpriv;
+	t_u16 eth_type = 0;
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	tdlsStatus_e tdls_status;
+
+	ENTER();
+	MASSERT(pmlan_adapter &&pmbuf);
+
+	if (!pmlan_adapter ||!pmbuf) {
+		return MLAN_STATUS_FAILURE;
+	}
+
+	MASSERT(pmbuf->bss_index < pmadapter->priv_num);
+	pmbuf->flags |= MLAN_BUF_FLAG_MOAL_TX_BUF;
+	pmpriv = pmadapter->priv[pmbuf->bss_index];
+
+	eth_type =
+		mlan_ntohs(*(t_u16 *)&pmbuf->
+			   pbuf[pmbuf->data_offset +
+				MLAN_ETHER_PKT_TYPE_OFFSET]);
+	if (((pmadapter->priv[pmbuf->bss_index]->port_ctrl_mode == MTRUE) &&
+	     ((eth_type == MLAN_ETHER_PKT_TYPE_EAPOL)
+	      || (eth_type == MLAN_ETHER_PKT_TYPE_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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+			       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;
+		}
+		PRINTM(MINFO, "mlan_send_pkt(): enq(bybass_txq)\n");
+		wlan_add_buf_bypass_txqueue(pmadapter, pmbuf);
+	} 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(IN t_void *adapter, IN 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);
+		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;
+}
+
+/**
+ *  @brief Packet receive completion callback handler
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param pmbuf		A pointer to mlan_buffer structure
+ *  @param status		Callback status
+ *
+ *  @return			MLAN_STATUS_SUCCESS
+ */
+mlan_status
+mlan_recv_packet_complete(IN t_void *pmlan_adapter,
+			  IN pmlan_buffer pmbuf, IN mlan_status status)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+
+	ENTER();
+	wlan_recv_packet_complete(pmadapter, pmbuf, status);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief select wmm queue
+ *
+ *  @param pmlan_adapter	A pointer to mlan_adapter structure
+ *  @param bss_num		BSS number
+ *  @param tid			TID
+ *
+ *  @return			wmm queue priority (0 - 3)
+ */
+t_u8
+mlan_select_wmm_queue(IN t_void *pmlan_adapter, IN t_u8 bss_num, IN t_u8 tid)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
+	pmlan_private pmpriv = pmadapter->priv[bss_num];
+	t_u8 ret;
+	ENTER();
+	ret = wlan_wmm_select_queue(pmpriv, tid);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets interrupt status.
+ *
+ */
+/**
+ *  @param adapter  A pointer to mlan_adapter structure
+ *  @return         N/A
+ */
+mlan_status
+mlan_interrupt(IN t_void *adapter)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+	mlan_status ret;
+
+	ENTER();
+	ret = wlan_interrupt(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function wakeup firmware.
+ *
+ *  @param adapter  A pointer to mlan_adapter structure
+ *  @return         N/A
+ */
+t_void
+mlan_pm_wakeup_card(IN t_void *adapter)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)adapter;
+	ENTER();
+	wlan_pm_wakeup_card(pmadapter);
+	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(IN 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;
+}
diff --git a/wlan_sd8997/mlan/mlan_sta_cmd.c b/wlan_sd8997/mlan/mlan_sta_cmd.c
new file mode 100644
index 0000000..0a66f30
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_sta_cmd.c
@@ -0,0 +1,3594 @@
+/** @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.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+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_11h.h"
+#include "mlan_sdio.h"
+#include "mlan_meas.h"
+
+/********************************************************
+			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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *pcmd, IN 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_ext
+ *
+ *  @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
+ */
+static mlan_status
+wlan_cmd_802_11_rssi_info_ext(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *pcmd,
+			      IN t_u16 cmd_action, IN 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 +
+			sizeof(HostCmd_DS_802_11_RSSI_INFO_EXT);
+		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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action,
+			 IN t_u32 cmd_oid, IN 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(pmpriv->adapter, psnmp_mib->value, &ul_temp,
+			       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(IN pmlan_private pmpriv, IN 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 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd,
+			    IN t_u16 cmd_action, IN 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(IN 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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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;
+
+	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(pmpriv->adapter,
+		       ((t_u8 *)phs_cfg) + sizeof(HostCmd_DS_802_11_HS_CFG_ENH),
+		       pmadapter->arp_filter, 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(pmadapter, (t_u8 *)mgmt_filter_tlv->filter,
+			       (t_u8 *)mgmt_filter,
+			       i * sizeof(mgmt_frame_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);
+		}
+		cmd->size = wlan_cpu_to_le16(cmd->size);
+		PRINTM(MCMND,
+		       "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x holdoff=%d wake_interval=%d inactivity_timeout=%d\n",
+		       phs_cfg->params.hs_config.conditions,
+		       phs_cfg->params.hs_config.gpio,
+		       phs_cfg->params.hs_config.gap,
+		       pmadapter->min_wake_holdoff, pmadapter->hs_wake_interval,
+		       pmadapter->hs_inactivity_timeout);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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
+ */
+static mlan_status
+wlan_cmd_802_11_mac_address(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, cmd->params.mac_addr.mac_addr,
+		       pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
+		/* HEXDUMP("SET_CMD: MAC ADDRESS-", priv->CurrentAddr, 6); */
+	}
+	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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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(pmpriv->adapter, pmc_addr->mac_list, pmcast_list->mac_list,
+	       pmcast_list->num_multicast_addr * MLAN_MAC_ADDR_LENGTH);
+
+	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(IN pmlan_private pmpriv,
+			       IN t_u16 cmd_no,
+			       IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, pdeauth, (t_u8 *)pdata_buf, 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(IN pmlan_private pmpriv, IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *cmd,
+			     IN t_u16 cmd_action,
+			     IN t_u32 cmd_oid, IN 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		       pkey->mac_addr, 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		       pkey->mac_addr, 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+	       pkey->mac_addr, 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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wep.key,
+		       pkey->key_material, pkey->key_len);
+		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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.pn,
+		       pkey->pn, PN_SIZE);
+		pkey_material->key_param_set.key_params.wapi.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.key,
+		       pkey->key_material, pkey->key_len);
+		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_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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.aes.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.aes.key,
+		       pkey->key_material, pkey->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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.cmac_aes.
+			       ipn, pkey->pn, SEQ_MAX_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+		pkey_material->key_param_set.key_params.cmac_aes.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.cmac_aes.key,
+		       pkey->key_material, pkey->key_len);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set CMAC AES Key\n");
+		goto done;
+	}
+	if (pkey->key_len == WPA_TKIP_KEY_LEN) {
+		if (pkey->
+		    key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.tkip.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.tkip.key,
+		       pkey->key_material, pkey->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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action,
+			   IN t_u32 cmd_oid, IN 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(pmpriv->adapter, rekey->kek, data->kek, MLAN_KEK_LEN);
+		memcpy(pmpriv->adapter, rekey->kck, data->kck, 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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *cmd,
+		   IN t_u16 cmd_action, IN 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(pmpriv->adapter, eapol_pkt->tlv_eapol.pkt_buf,
+	       pmbuf->pbuf + pmbuf->data_offset, 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
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_802_11_supplicant_profile(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *cmd,
+				   IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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)
+		    || (pmpriv->adapter->adhoc_start_band & BAND_AN)
+			)
+			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(IN pmlan_private pmpriv,
+				IN HostCmd_DS_COMMAND *cmd,
+				IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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);
+
+	if (pmgmt_ie_list->ds_mgmt_ie.ie_data_list && cust_ie->ie_data_list) {
+		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(pmpriv->adapter,
+			       pmgmt_ie_list->ds_mgmt_ie.ie_data_list,
+			       cust_ie->ie_data_list, cust_ie->len);
+	}
+
+	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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN 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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_setup, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       (t_u8 *)&tdls_all_cfg->u.tdls_set.cap_info,
+		       sizeof(t_u16));
+		memcpy(pmpriv->adapter,
+		       (t_u8 *)ptdls_config_data->tdls_info.tdls_data +
+		       sizeof(t_u16), &tdls_all_cfg->u.tdls_set.tlv_buffer,
+		       travel_len);
+		travel_len += sizeof(t_u16);
+		break;
+	case WLAN_TDLS_DISCOVERY_REQ:
+		travel_len = MLAN_MAC_ADDR_LENGTH;
+		memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       tdls_all_cfg->u.tdls_discovery.peer_mac_addr,
+		       travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_setup, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_tear_down, travel_len);
+		break;
+	case WLAN_TDLS_STOP_CHAN_SWITCH:
+		travel_len = MLAN_MAC_ADDR_LENGTH;
+		memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
+		       travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_chan_switch, travel_len);
+		break;
+	case WLAN_TDLS_CS_PARAMS:
+		travel_len = sizeof(tdls_all_cfg->u.tdls_cs_params);
+		memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_cs_params, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_disable_cs, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_power_mode, travel_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(pmpriv->adapter,
+			       ptdls_config_data->tdls_info.tdls_data,
+			       tdls_all_cfg->u.tdls_link_status_req.
+			       peer_mac_addr, travel_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(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
+		       &tdls_all_cfg->u.tdls_debug_data, travel_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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *cmd,
+		   IN t_u16 cmd_action, IN 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(pmpriv->adapter, ptdls_oper->peer_mac, tdls_oper->peer_mac,
+	       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(pmpriv->adapter,
+			       pos + travel_len + sizeof(MrvlIEtypesHeader_t),
+			       sta_ptr->support_rate, Rate_tlv->header.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(pmpriv->adapter, &ExCap->ext_cap,
+				       &sta_ptr->ExtCap.ext_cap,
+				       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(pmpriv->adapter, Rsn_ie->rsn_ie,
+				       sta_ptr->rsn_ie.data,
+				       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(pmpriv->adapter, &LinkID->bssid,
+				       &sta_ptr->link_ie.bssid,
+				       sta_ptr->link_ie.len);
+				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(pmpriv->adapter, &HTcap_tlv->ht_cap,
+				       &sta_ptr->HTcap.ht_cap,
+				       sta_ptr->HTcap.ieee_hdr.len);
+				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(pmpriv->adapter, &HTInfo_tlv->ht_info,
+				       &sta_ptr->HTInfo.ht_info,
+				       sta_ptr->HTInfo.ieee_hdr.len);
+				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(pmpriv->adapter, &BSSCo->bss_co_2040,
+				       &sta_ptr->BSSCO_20_40.bss_co_2040,
+				       sta_ptr->BSSCO_20_40.ieee_hdr.len);
+				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(pmpriv->adapter,
+					       &VHTcap_tlv->vht_cap,
+					       &sta_ptr->vht_cap.vht_cap,
+					       sta_ptr->vht_cap.ieee_hdr.len);
+					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);
+					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(pmpriv->adapter,
+				       &VHTOper_tlv->chan_width,
+				       &sta_ptr->vht_oprat.chan_width,
+				       sta_ptr->vht_oprat.ieee_hdr.len);
+				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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_otp_user_data *user_data =
+		(mlan_ds_misc_otp_user_data *)pdata_buf;
+	HostCmd_DS_OTP_USER_DATA *cmd_user_data =
+		(HostCmd_DS_OTP_USER_DATA *)&cmd->params.otp_user_data;
+	t_u16 cmd_size = 0;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_OTP_READ_USER_DATA);
+	cmd_size = sizeof(HostCmd_DS_OTP_USER_DATA) + S_DS_GEN - 1;
+
+	cmd_user_data->action = wlan_cpu_to_le16(cmd_action);
+	cmd_user_data->reserved = 0;
+	cmd_user_data->user_data_length =
+		wlan_cpu_to_le16(user_data->user_data_length);
+	cmd_size += user_data->user_data_length;
+	cmd->size = wlan_cpu_to_le16(cmd_size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares 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(IN HostCmd_DS_COMMAND *cmd,
+			    IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	pmlan_ds_inactivity_to inac_to;
+	HostCmd_DS_INACTIVITY_TIMEOUT_EXT *cmd_inac_to =
+		&cmd->params.inactivity_to;
+
+	ENTER();
+
+	inac_to = (mlan_ds_inactivity_to *)pdata_buf;
+
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_INACTIVITY_TIMEOUT_EXT) +
+				 S_DS_GEN);
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+	cmd_inac_to->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cmd_inac_to->timeout_unit =
+			wlan_cpu_to_le16((t_u16)inac_to->timeout_unit);
+		cmd_inac_to->unicast_timeout =
+			wlan_cpu_to_le16((t_u16)inac_to->unicast_timeout);
+		cmd_inac_to->mcast_timeout =
+			wlan_cpu_to_le16((t_u16)inac_to->mcast_timeout);
+		cmd_inac_to->ps_entry_timeout =
+			wlan_cpu_to_le16((t_u16)inac_to->ps_entry_timeout);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares network monitor command
+ *
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_net_monitor(IN HostCmd_DS_COMMAND *cmd,
+		     IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_net_monitor *net_mon;
+	HostCmd_DS_802_11_NET_MONITOR *cmd_net_mon = &cmd->params.net_mon;
+	ChanBandParamSet_t *pchan_band = MNULL;
+	t_u8 sec_chan_offset = 0;
+	t_u32 bw_offset = 0;
+
+	ENTER();
+
+	net_mon = (mlan_ds_misc_net_monitor *)pdata_buf;
+
+	cmd->size = wlan_cpu_to_le16(S_DS_GEN +
+				     sizeof(HostCmd_DS_802_11_NET_MONITOR));
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+	cmd_net_mon->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cmd_net_mon->enable_net_mon =
+			wlan_cpu_to_le16((t_u16)net_mon->enable_net_mon);
+		if (net_mon->enable_net_mon)
+			cmd_net_mon->filter_flag =
+				wlan_cpu_to_le16((t_u16)net_mon->filter_flag);
+		/* fill the TLV only if channel is specified */
+		if (net_mon->enable_net_mon && net_mon->channel) {
+			pchan_band =
+				&cmd_net_mon->monitor_chan.chan_band_param[0];
+			cmd_net_mon->monitor_chan.header.type =
+				wlan_cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
+			cmd_net_mon->monitor_chan.header.len =
+				wlan_cpu_to_le16(sizeof(ChanBandParamSet_t));
+			pchan_band->chan_number = (t_u8)net_mon->channel;
+			pchan_band->bandcfg.chanBand =
+				wlan_band_to_radio_type((t_u8)net_mon->band);
+
+			if (net_mon->band & BAND_GN
+			    || net_mon->band & BAND_AN
+			    || net_mon->band & BAND_GAC
+			    || net_mon->band & BAND_AAC) {
+				bw_offset = net_mon->chan_bandwidth;
+				if (bw_offset == CHANNEL_BW_40MHZ_ABOVE) {
+					pchan_band->bandcfg.chan2Offset =
+						SEC_CHAN_ABOVE;
+					pchan_band->bandcfg.chanWidth =
+						CHAN_BW_40MHZ;
+				} else if (bw_offset == CHANNEL_BW_40MHZ_BELOW) {
+					pchan_band->bandcfg.chan2Offset =
+						SEC_CHAN_BELOW;
+					pchan_band->bandcfg.chanWidth =
+						CHAN_BW_40MHZ;
+				} else if (bw_offset == CHANNEL_BW_80MHZ) {
+					sec_chan_offset =
+						wlan_get_second_channel_offset
+						(net_mon->channel);
+					if (sec_chan_offset == SEC_CHAN_ABOVE)
+						pchan_band->bandcfg.
+							chan2Offset =
+							SEC_CHAN_ABOVE;
+					else if (sec_chan_offset ==
+						 SEC_CHAN_BELOW)
+						pchan_band->bandcfg.
+							chan2Offset =
+							SEC_CHAN_BELOW;
+					pchan_band->bandcfg.chanWidth =
+						CHAN_BW_80MHZ;
+				}
+			}
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	mlan_ds_misc_dfs_repeater *dfs_repeater = MNULL;
+	HostCmd_DS_DFS_REPEATER_MODE *cmd_dfs_repeater =
+		&cmd->params.dfs_repeater;
+
+	ENTER();
+
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_DFS_REPEATER_MODE);
+
+	dfs_repeater = (mlan_ds_misc_dfs_repeater *)pdata_buf;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+	cmd_dfs_repeater->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET)
+		cmd_dfs_repeater->mode = wlan_cpu_to_le16(dfs_repeater->mode);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of coalesce_config.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_coalesce_config(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	HostCmd_DS_COALESCE_CONFIG *coalesce_config =
+		&cmd->params.coalesce_config;
+	mlan_ds_coalesce_cfg *cfg = (mlan_ds_coalesce_cfg *) pdata_buf;
+	t_u16 cnt, idx, length;
+	struct coalesce_filt_field_param *param;
+	struct coalesce_receive_filt_rule *rule;
+	ENTER();
+
+	cmd->size = sizeof(HostCmd_DS_COALESCE_CONFIG) + S_DS_GEN;
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_COALESCE_CFG);
+	coalesce_config->action = wlan_cpu_to_le16(cmd_action);
+	coalesce_config->num_of_rules = wlan_cpu_to_le16(cfg->num_of_rules);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		rule = coalesce_config->rule;
+		for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
+			rule->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_COALESCE_RULE);
+			rule->max_coalescing_delay =
+				wlan_cpu_to_le16(cfg->rule[cnt].
+						 max_coalescing_delay);
+			rule->pkt_type = cfg->rule[cnt].pkt_type;
+			rule->num_of_fields = cfg->rule[cnt].num_of_fields;
+
+			length = 0;
+
+			param = rule->params;
+			for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) {
+				param->operation =
+					cfg->rule[cnt].params[idx].operation;
+				param->operand_len =
+					cfg->rule[cnt].params[idx].operand_len;
+				param->offset =
+					wlan_cpu_to_le16(cfg->rule[cnt].
+							 params[idx].offset);
+				memcpy(pmpriv->adapter,
+				       param->operand_byte_stream,
+				       cfg->rule[cnt].params[idx].
+				       operand_byte_stream, param->operand_len);
+
+				length +=
+					sizeof(struct
+					       coalesce_filt_field_param);
+
+				param++;
+			}
+
+			/* Total rule length is sizeof max_coalescing_delay(t_u16),
+			 * num_of_fields(t_u8), pkt_type(t_u8) and total length of the all
+			 * params
+			 */
+			rule->header.len =
+				wlan_cpu_to_le16(length + sizeof(t_u16) +
+						 sizeof(t_u8) + sizeof(t_u8));
+
+			/* Add the rule length to the command size */
+			cmd->size +=
+				wlan_le16_to_cpu(rule->header.len) +
+				sizeof(MrvlIEtypesHeader_t);
+
+			rule = (void *)((t_u8 *)rule->params + length);
+		}
+
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function prepares command for sensor temperature.
+ *
+ *  @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_get_sensor_temp(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *cmd, IN 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 sends get nlist to FW
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param pcmd          Hostcmd ID
+ *  @param cmd_action   Command action
+ *  @return             N/A
+ */
+mlan_status
+wlan_cmd_802_11k_get_nlist(mlan_private *pmpriv,
+			   HostCmd_DS_COMMAND *pcmd, t_u16 cmd_action)
+{
+	HostCmd_DS_802_11K_GET_NLIST *pget_nlist = &pcmd->params.get_nlist;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11K_GET_NLIST);
+	pget_nlist->action = wlan_cpu_to_le16(cmd_action);	/* only for get */
+	pcmd->size =
+		wlan_cpu_to_le16(S_DS_GEN +
+				 sizeof(HostCmd_DS_802_11K_GET_NLIST));
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends get nlist.
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param pcmd          Hostcmd ID
+ *  @param cmd_action   Command action
+ *  @param pdata_buf    A pointer to information buffer
+ *  @return             N/A
+ */
+mlan_status
+wlan_cmd_offload_feature_ctrl(mlan_private *pmpriv,
+			      HostCmd_DS_COMMAND *pcmd,
+			      t_u16 cmd_action, void *pdata_buf)
+{
+	HostCmd_OFFLOAD_FEATURE_CTRL *pfctrl = &pcmd->params.fctrl;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_OFFLOAD_FEATURE_CONTROL);
+	memcpy(pmpriv->adapter, pfctrl, pdata_buf,
+	       sizeof(HostCmd_OFFLOAD_FEATURE_CTRL));
+	pcmd->size =
+		wlan_cpu_to_le16(S_DS_GEN +
+				 sizeof(HostCmd_OFFLOAD_FEATURE_CTRL));
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends get sta band channel command to firmware.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action  Command action
+ *  @param pioctl_buf  A pointer to mlan_ioctl_req structure
+ *  @param pdata_buf   A pointer to information buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_sta_config(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *cmd,
+		    IN t_u16 cmd_action,
+		    IN mlan_ioctl_req *pioctl_buf, IN t_void *pdata_buf)
+{
+	mlan_ds_bss *bss = MNULL;
+	HostCmd_DS_STA_CONFIGURE *sta_cfg_cmd = &cmd->params.sta_cfg;
+	MrvlIEtypes_channel_band_t *tlv_band_channel = MNULL;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	ENTER();
+	if (!pioctl_buf)
+		return ret;
+
+	if (pioctl_buf->req_id == MLAN_IOCTL_BSS) {
+		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+		if ((bss->sub_command == MLAN_OID_BSS_CHAN_INFO) &&
+		    (cmd_action == HostCmd_ACT_GEN_GET)) {
+			cmd->command =
+				wlan_cpu_to_le16(HostCmd_CMD_STA_CONFIGURE);
+			cmd->size =
+				wlan_cpu_to_le16(S_DS_GEN +
+						 sizeof
+						 (HostCmd_DS_STA_CONFIGURE) +
+						 sizeof(*tlv_band_channel));
+			sta_cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+			tlv_band_channel =
+				(MrvlIEtypes_channel_band_t *)sta_cfg_cmd->
+				tlv_buffer;
+			memset(pmpriv->adapter, tlv_band_channel, 0x00,
+			       sizeof(*tlv_band_channel));
+			tlv_band_channel->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
+			tlv_band_channel->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_channel_band_t)
+						 - sizeof(MrvlIEtypesHeader_t));
+			ret = MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepare the config tlvs of roam offload.
+ *
+ *  @param priv                   A pointer to mlan_private structure
+ *  @param tlv_no                 TLV type
+ *  @param roam         	  Pointer to mlan_ds_misc_roam_offload structure
+ *  @param trigger_condition      Value of trigger_condition
+ *  @param pos                    Pointer to the buffer of HostCmd_DS_ROAM_OFFLOAD
+ *
+ *  @return                       Command size
+*/
+static t_u16
+mlan_prepare_roam_offload_tlv(IN pmlan_private pmpriv,
+			      IN t_u32 type,
+			      IN mlan_ds_misc_roam_offload * roam,
+			      IN t_u8 trigger_condition, IN t_u8 *pos)
+{
+	MrvlIEtypes_fw_roam_enable_t *enable_tlv = MNULL;
+	MrvlIEtypes_fw_roam_trigger_condition_t *trigger_condition_tlv = MNULL;
+	MrvlIEtypes_Bssid_t *bssid_tlv = MNULL;
+	MrvlIEtypes_SsIdParamSet_t *ssid_tlv = MNULL;
+	MrvlIEtypes_fw_roam_retry_count_t *retry_count_tlv = MNULL;
+	MrvlIEtypes_para_rssi_t *rssi_para_tlv = MNULL;
+	MrvlIEtypes_fw_roam_bgscan_setting_t *bgscan_set_tlv = MNULL;
+	MrvlIEtypes_roam_blacklist_t *blacklist_tlv = MNULL;
+	MrvlIEtypes_ees_param_set_t *ees_param_tlv = MNULL;
+	MrvlIEtypes_band_rssi_t *band_rssi_tlv = MNULL;
+	MrvlIEtypes_beacon_miss_threshold_t *bcn_miss_threshold_tlv = MNULL;
+	MrvlIEtypes_pre_beacon_miss_threshold_t *pre_bcn_miss_threshold_tlv =
+		MNULL;
+	MrvlIEtypes_RepeatCount_t *tlv_repeat = MNULL;
+	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 }, *begin;
+	int i = 0;
+
+	ENTER();
+
+	begin = pos;
+	if (type & FW_ROAM_ENABLE) {
+		enable_tlv = (MrvlIEtypes_fw_roam_enable_t *) pos;
+		enable_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_ROAM);
+		enable_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypes_fw_roam_enable_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		if (roam->enable <= ROAM_OFFLOAD_WITHOUT_APLIST)
+			enable_tlv->roam_enable = roam->enable;
+		else
+			enable_tlv->roam_enable = ROAM_OFFLOAD_WITHOUT_APLIST;
+		pos += sizeof(MrvlIEtypes_fw_roam_enable_t);
+	}
+	if (type & FW_ROAM_TRIGGER_COND) {
+		trigger_condition_tlv =
+			(MrvlIEtypes_fw_roam_trigger_condition_t *) pos;
+		trigger_condition_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_ROM_TRIGGER);
+		trigger_condition_tlv->header.len =
+			wlan_cpu_to_le16(sizeof
+					 (trigger_condition_tlv->
+					  trigger_condition));
+		trigger_condition_tlv->trigger_condition =
+			wlan_cpu_to_le16(trigger_condition);
+		pos += sizeof(trigger_condition_tlv->header) +
+			sizeof(trigger_condition_tlv->trigger_condition);
+	}
+	if (type & FW_ROAM_BSSID) {
+		bssid_tlv = (MrvlIEtypes_Bssid_t *)pos;
+		bssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_BSSID);
+		bssid_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(bssid_tlv->bssid));
+		if (0 !=
+		    memcmp(pmpriv->adapter, roam->bssid_reconnect, zero_mac,
+			   sizeof(zero_mac)))
+			memcpy(pmpriv->adapter, bssid_tlv->bssid,
+			       roam->bssid_reconnect, bssid_tlv->header.len);
+		else {
+			if (roam->config_mode == ROAM_OFFLOAD_SUSPEND_CFG)
+				memcpy(pmpriv->adapter, bssid_tlv->bssid,
+				       pmpriv->curr_bss_params.bss_descriptor.
+				       mac_address, bssid_tlv->header.len);
+			else if (roam->config_mode == ROAM_OFFLOAD_RESUME_CFG)
+				memcpy(pmpriv->adapter, bssid_tlv->bssid,
+				       zero_mac, bssid_tlv->header.len);
+		}
+		pos += sizeof(bssid_tlv->header) + sizeof(bssid_tlv->bssid);
+	}
+	if (type & FW_ROAM_SSID) {
+		for (i = 0; i < roam->ssid_list.ssid_num; i++) {
+			ssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)pos;
+			ssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+			memcpy(pmpriv->adapter, ssid_tlv->ssid,
+			       roam->ssid_list.ssids[i].ssid,
+			       roam->ssid_list.ssids[i].ssid_len);
+			pos += sizeof(ssid_tlv->header) +
+				wlan_strlen(ssid_tlv->ssid);
+			ssid_tlv->header.len =
+				wlan_cpu_to_le16(wlan_strlen(ssid_tlv->ssid));
+		}
+		if (!roam->ssid_list.ssid_num) {
+			ssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)pos;
+			ssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+			memcpy(pmpriv->adapter, ssid_tlv->ssid,
+			       pmpriv->curr_bss_params.bss_descriptor.ssid.ssid,
+			       pmpriv->curr_bss_params.bss_descriptor.ssid.
+			       ssid_len);
+			ssid_tlv->header.len =
+				wlan_cpu_to_le16(wlan_strlen(ssid_tlv->ssid));
+			pos += sizeof(ssid_tlv->header) + ssid_tlv->header.len;
+		}
+	}
+	if (type & FW_ROAM_RETRY_COUNT) {
+		retry_count_tlv = (MrvlIEtypes_fw_roam_retry_count_t *) pos;
+		retry_count_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_ROM_RETRY_COUNT);
+		retry_count_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(retry_count_tlv->retry_count));
+		if (roam->retry_count)
+			retry_count_tlv->retry_count =
+				wlan_cpu_to_le16(roam->retry_count);
+		else
+			retry_count_tlv->retry_count =
+				wlan_cpu_to_le16(RETRY_UNLIMITED_TIME);
+		pos += sizeof(retry_count_tlv->header) +
+			sizeof(retry_count_tlv->retry_count);
+	}
+	if (type & FW_ROAM_RSSI_PARA) {
+		rssi_para_tlv = (MrvlIEtypes_para_rssi_t *) pos;
+		rssi_para_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_ROM_PARA_RSSI);
+		rssi_para_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(rssi_para_tlv->max_rssi) +
+					 sizeof(rssi_para_tlv->min_rssi) +
+					 sizeof(rssi_para_tlv->step_rssi));
+		rssi_para_tlv->max_rssi = roam->para_rssi.max_rssi;
+		rssi_para_tlv->min_rssi = roam->para_rssi.min_rssi;
+		rssi_para_tlv->step_rssi = roam->para_rssi.step_rssi;
+		pos += sizeof(rssi_para_tlv->header) +
+			sizeof(rssi_para_tlv->max_rssi) +
+			sizeof(rssi_para_tlv->min_rssi) +
+			sizeof(rssi_para_tlv->step_rssi);
+	}
+
+	if (type & FW_ROAM_BAND_RSSI) {
+		band_rssi_tlv = (MrvlIEtypes_band_rssi_t *) pos;
+		band_rssi_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_BAND_RSSI);
+		band_rssi_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypes_band_rssi_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		band_rssi_tlv->band_rssi.band_preferred =
+			roam->band_rssi.band_preferred;
+		band_rssi_tlv->band_rssi.rssi_hysteresis =
+			roam->band_rssi.rssi_hysteresis;
+		pos += sizeof(MrvlIEtypes_band_rssi_t);
+	}
+
+	if (type & FW_ROAM_BGSCAN_PARAM) {
+		bgscan_set_tlv = (MrvlIEtypes_fw_roam_bgscan_setting_t *) pos;
+		bgscan_set_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_ROM_BGSCAN);
+		bgscan_set_tlv->header.len =
+			wlan_cpu_to_le16(sizeof
+					 (MrvlIEtypes_fw_roam_bgscan_setting_t)
+					 - sizeof(MrvlIEtypesHeader_t));
+		bgscan_set_tlv->bss_type = roam->bgscan_cfg.bss_type;
+		bgscan_set_tlv->channels_perscan =
+			roam->bgscan_cfg.channels_per_scan;
+		bgscan_set_tlv->scan_interval =
+			wlan_cpu_to_le32(roam->bgscan_cfg.scan_interval);
+		bgscan_set_tlv->report_condition =
+			wlan_cpu_to_le32(roam->bgscan_cfg.bg_rpt_condition);
+		pos += sizeof(MrvlIEtypes_fw_roam_bgscan_setting_t);
+	}
+
+	if (type & FW_ROAM_EES_PARAM) {
+		ees_param_tlv = (MrvlIEtypes_ees_param_set_t *) pos;
+		ees_param_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_ENERGYEFFICIENTSCAN);
+		ees_param_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypes_ees_param_set_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		ees_param_tlv->ees_cfg.ees_mode =
+			wlan_cpu_to_le16(roam->ees_cfg.ees_mode);
+		ees_param_tlv->ees_cfg.ees_rpt_condition =
+			wlan_cpu_to_le16(roam->ees_cfg.ees_rpt_condition);
+		ees_param_tlv->ees_cfg.high_scan_period =
+			wlan_cpu_to_le16(roam->ees_cfg.high_scan_period);
+		ees_param_tlv->ees_cfg.high_scan_count =
+			wlan_cpu_to_le16(roam->ees_cfg.high_scan_count);
+		ees_param_tlv->ees_cfg.mid_scan_period =
+			wlan_cpu_to_le16(roam->ees_cfg.mid_scan_period);
+		ees_param_tlv->ees_cfg.mid_scan_count =
+			wlan_cpu_to_le16(roam->ees_cfg.mid_scan_count);
+		ees_param_tlv->ees_cfg.low_scan_period =
+			wlan_cpu_to_le16(roam->ees_cfg.low_scan_period);
+		ees_param_tlv->ees_cfg.low_scan_count =
+			wlan_cpu_to_le16(roam->ees_cfg.low_scan_count);
+		pos += sizeof(MrvlIEtypes_ees_param_set_t);
+	}
+
+	if (type & FW_ROAM_BCN_MISS_THRESHOLD) {
+		bcn_miss_threshold_tlv =
+			(MrvlIEtypes_beacon_miss_threshold_t *) pos;
+		bcn_miss_threshold_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_BCNMISS);
+		bcn_miss_threshold_tlv->header.len =
+			wlan_cpu_to_le16(sizeof
+					 (MrvlIEtypes_beacon_miss_threshold_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		bcn_miss_threshold_tlv->bcn_miss_threshold =
+			roam->bcn_miss_threshold;
+		pos += sizeof(MrvlIEtypes_beacon_miss_threshold_t);
+	}
+
+	if (type & FW_ROAM_PRE_BCN_MISS_THRESHOLD) {
+		pre_bcn_miss_threshold_tlv =
+			(MrvlIEtypes_pre_beacon_miss_threshold_t *) pos;
+		pre_bcn_miss_threshold_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_PRE_BCNMISS);
+		pre_bcn_miss_threshold_tlv->header.len =
+			wlan_cpu_to_le16(sizeof
+					 (MrvlIEtypes_pre_beacon_miss_threshold_t)
+					 - sizeof(MrvlIEtypesHeader_t));
+		pre_bcn_miss_threshold_tlv->pre_bcn_miss_threshold =
+			roam->pre_bcn_miss_threshold;
+		pos += sizeof(MrvlIEtypes_pre_beacon_miss_threshold_t);
+	}
+
+	if (type & FW_ROAM_BLACKLIST) {
+		blacklist_tlv = (MrvlIEtypes_roam_blacklist_t *) pos;
+		blacklist_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_BLACKLIST_BSSID);
+		blacklist_tlv->header.len =
+			roam->black_list.ap_num * MLAN_MAC_ADDR_LENGTH +
+			sizeof(roam->black_list.ap_num);
+		memcpy(pmpriv->adapter, (t_u8 *)&blacklist_tlv->blacklist,
+		       (t_u8 *)&roam->black_list, blacklist_tlv->header.len);
+		pos += sizeof(MrvlIEtypesHeader_t) + blacklist_tlv->header.len;
+		blacklist_tlv->header.len =
+			wlan_cpu_to_le16(blacklist_tlv->header.len);
+	}
+
+	if (type & FW_ROAM_REPEAT_CNT) {
+		tlv_repeat = (MrvlIEtypes_RepeatCount_t *)pos;
+		tlv_repeat->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
+		tlv_repeat->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypes_RepeatCount_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		tlv_repeat->repeat_count = wlan_cpu_to_le16(roam->repeat_count);
+		pos += sizeof(MrvlIEtypes_RepeatCount_t);
+	}
+
+	LEAVE();
+	return (pos - begin);
+}
+
+/**
+ *  @brief This function sends enable/disable roam offload command to firmware.
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   Command action
+ *  @param pdata_buf    A pointer to information buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_roam_offload(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	HostCmd_DS_ROAM_OFFLOAD *roam_cmd = &cmd->params.roam_offload;
+	MrvlIEtypes_roam_aplist_t *aplist = MNULL;
+	t_u8 *pos = (t_u8 *)roam_cmd + sizeof(roam_cmd->action);
+	mlan_ds_misc_roam_offload *roam = MNULL;
+	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 };
+	t_u32 type = 0;
+	t_u8 trigger_condition = 0;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ROAM_OFFLOAD);
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_ROAM_OFFLOAD);
+	roam_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	roam = (mlan_ds_misc_roam_offload *) pdata_buf;
+
+	if (roam->config_mode) {
+		switch (roam->config_mode) {
+		case ROAM_OFFLOAD_ENABLE:
+			type |= FW_ROAM_ENABLE;
+			if (roam->enable && roam->enable != AUTO_RECONNECT) {
+				type |= FW_ROAM_TRIGGER_COND;
+				trigger_condition |=
+					RSSI_LOW_TRIGGER |
+					PRE_BEACON_LOST_TRIGGER;
+			}
+			break;
+		case ROAM_OFFLOAD_SUSPEND_CFG:
+			type |= FW_ROAM_TRIGGER_COND | FW_ROAM_RETRY_COUNT;
+			if (roam->enable == AUTO_RECONNECT) {
+				type |= FW_ROAM_BSSID | FW_ROAM_SSID;
+				trigger_condition =
+					LINK_LOST_TRIGGER |
+					DEAUTH_WITH_EXT_AP_TRIGGER;
+			} else
+				trigger_condition =
+					LINK_LOST_TRIGGER |
+					DEAUTH_WITH_EXT_AP_TRIGGER |
+					RSSI_LOW_TRIGGER |
+					PRE_BEACON_LOST_TRIGGER;
+
+			if (roam->enable == ROAM_OFFLOAD_WITH_BSSID)
+				type |= FW_ROAM_BSSID;
+			if (roam->enable == ROAM_OFFLOAD_WITH_SSID)
+				type |= FW_ROAM_SSID;
+			break;
+		case ROAM_OFFLOAD_RESUME_CFG:
+			type |= FW_ROAM_TRIGGER_COND;
+			if (roam->enable == AUTO_RECONNECT)
+				trigger_condition = NO_TRIGGER;
+			else
+				trigger_condition =
+					RSSI_LOW_TRIGGER |
+					PRE_BEACON_LOST_TRIGGER;
+			if (roam->enable == ROAM_OFFLOAD_WITH_BSSID ||
+			    roam->enable == AUTO_RECONNECT)
+				type |= FW_ROAM_BSSID;
+			break;
+		case ROAM_OFFLOAD_PARAM_CFG:
+			if (roam->enable && roam->enable != AUTO_RECONNECT) {
+				if (roam->retry_count != 0)
+					type |= FW_ROAM_RETRY_COUNT;
+				if (roam->ssid_list.ssid_num)
+					type |= FW_ROAM_SSID;
+				if (roam->para_rssi.set_flag)
+					type |= FW_ROAM_RSSI_PARA;
+				if (0 !=
+				    memcmp(pmpriv->adapter,
+					   roam->bssid_reconnect, zero_mac,
+					   sizeof(zero_mac)))
+					type |= FW_ROAM_BSSID;
+				if (roam->band_rssi_flag)
+					type |= FW_ROAM_BAND_RSSI;
+				if (roam->bgscan_set_flag)
+					type |= FW_ROAM_BGSCAN_PARAM;
+				if (roam->ees_param_set_flag)
+					type |= FW_ROAM_EES_PARAM;
+				if (roam->bcn_miss_threshold)
+					type |= FW_ROAM_BCN_MISS_THRESHOLD;
+				if (roam->pre_bcn_miss_threshold)
+					type |= FW_ROAM_PRE_BCN_MISS_THRESHOLD;
+				if (roam->black_list.ap_num)
+					type |= FW_ROAM_BLACKLIST;
+				if (roam->trigger_condition != 0xff) {
+					type |= FW_ROAM_TRIGGER_COND;
+					trigger_condition =
+						roam->trigger_condition;
+				}
+				if (roam->repeat_count)
+					type |= FW_ROAM_REPEAT_CNT;
+			}
+			break;
+		}
+		cmd->size +=
+			mlan_prepare_roam_offload_tlv(pmpriv, type, roam,
+						      trigger_condition, pos);
+	}
+	if (roam->aplist.ap_num) {
+		aplist = (MrvlIEtypes_roam_aplist_t *) pos;
+		aplist->header.type = wlan_cpu_to_le16(TLV_TYPE_APLIST);
+		aplist->header.len = roam->aplist.ap_num * MLAN_MAC_ADDR_LENGTH;
+		memcpy(pmpriv->adapter, aplist->ap_mac, roam->aplist.ap_mac,
+		       roam->aplist.ap_num * MLAN_MAC_ADDR_LENGTH);
+		pos += sizeof(aplist->header) + aplist->header.len;
+		cmd->size += sizeof(aplist->header) + aplist->header.len;
+		aplist->header.len = wlan_cpu_to_le16(aplist->header.len);
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function check if the command is supported by firmware
+ *
+ *  @param priv       A pointer to mlan_private structure
+ *  @param cmd_no       Command number
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_is_cmd_allowed(mlan_private *priv, IN t_u16 cmd_no)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	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 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             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_config_dyn_bw(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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 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(IN t_void *priv,
+			 IN t_u16 cmd_no,
+			 IN t_u16 cmd_action,
+			 IN t_u32 cmd_oid,
+			 IN t_void *pioctl_buf,
+			 IN t_void *pdata_buf, IN 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;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, pdata_buf);
+		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_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);
+		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_FW_WAKE_METHOD:
+		ret = wlan_cmd_802_11_fw_wakeup_method(pmpriv, cmd_ptr,
+						       cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_ROBUSTCOEX:
+		ret = wlan_cmd_robustcoex(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_FTM_CONFIG_SESSION_PARAMS:
+		ret = wlan_cmd_802_11_ftm_config_session_params(pmpriv, cmd_ptr,
+								cmd_action,
+								cmd_oid,
+								pdata_buf);
+		break;
+	case HostCmd_CMD_FTM_CONFIG_RESPONDER:
+		ret = wlan_cmd_802_11_ftm_config_responder(pmpriv, cmd_ptr,
+							   cmd_action, cmd_oid,
+							   pdata_buf);
+		break;
+	case HostCmd_CMD_RSSI_INFO:
+		ret = wlan_cmd_802_11_rssi_info(pmpriv, cmd_ptr, cmd_action);
+		break;
+	case HostCmd_CMD_RSSI_INFO_EXT:
+		ret = wlan_cmd_802_11_rssi_info_ext(pmpriv, cmd_ptr, cmd_action,
+						    pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_SNMP_MIB:
+		ret = wlan_cmd_802_11_snmp_mib(pmpriv, cmd_ptr, cmd_action,
+					       cmd_oid, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_RADIO_CONTROL:
+		ret = wlan_cmd_802_11_radio_control(pmpriv, cmd_ptr, cmd_action,
+						    pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		cmd_ptr->command =
+			wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) +
+					 S_DS_GEN);
+		pmpriv->tx_rate = 0;
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_VERSION_EXT:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->params.verext.version_str_sel =
+			(t_u8)(*((t_u32 *)pdata_buf));
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_VERSION_EXT) +
+					 S_DS_GEN);
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_RX_MGMT_IND:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->params.rx_mgmt_ind.action =
+			wlan_cpu_to_le16(cmd_action);
+		cmd_ptr->params.rx_mgmt_ind.mgmt_subtype_mask =
+			wlan_cpu_to_le32((t_u32)(*((t_u32 *)pdata_buf)));
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_RX_MGMT_IND) +
+					 S_DS_GEN);
+		break;
+	case HostCmd_CMD_802_11_RF_CHANNEL:
+		ret = wlan_cmd_802_11_rf_channel(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_FUNC_INIT:
+		if (pmpriv->adapter->hw_status == WlanHardwareStatusReset)
+			pmpriv->adapter->hw_status =
+				WlanHardwareStatusInitializing;
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HostCmd_CMD_FUNC_SHUTDOWN:
+		pmpriv->adapter->hw_status = WlanHardwareStatusReset;
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HostCmd_CMD_SOFT_RESET:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HostCmd_CMD_11N_ADDBA_REQ:
+		ret = wlan_cmd_11n_addba_req(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_11N_DELBA:
+		ret = wlan_cmd_11n_delba(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_11N_ADDBA_RSP:
+		ret = wlan_cmd_11n_addba_rspgen(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_KEY_MATERIAL:
+		ret = wlan_cmd_802_11_key_material(pmpriv, cmd_ptr, cmd_action,
+						   cmd_oid, pdata_buf);
+		break;
+
+	case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG:
+		ret = wlan_cmd_gtk_rekey_offload(pmpriv, cmd_ptr, cmd_action,
+						 cmd_oid, pdata_buf);
+		break;
+
+	case HostCmd_CMD_SUPPLICANT_PMK:
+		ret = wlan_cmd_802_11_supplicant_pmk(pmpriv, cmd_ptr,
+						     cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_EAPOL_PKT:
+		ret = wlan_cmd_eapol_pkt(pmpriv, cmd_ptr, cmd_action,
+					 pdata_buf);
+		break;
+	case HostCmd_CMD_SUPPLICANT_PROFILE:
+		ret = wlan_cmd_802_11_supplicant_profile(pmpriv, cmd_ptr,
+							 cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11D_DOMAIN_INFO:
+		ret = wlan_cmd_802_11d_domain_info(pmpriv, cmd_ptr, cmd_action);
+		break;
+	case HostCmd_CMD_802_11K_GET_NLIST:
+		ret = wlan_cmd_802_11k_get_nlist(pmpriv, cmd_ptr, cmd_action);
+		break;
+	case HostCmd_CMD_OFFLOAD_FEATURE_CONTROL:
+		ret = wlan_cmd_offload_feature_ctrl(pmpriv, cmd_ptr, cmd_action,
+						    pdata_buf);
+		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:
+		ret = wlan_cmd_reg_access(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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		ret = wlan_cmd_sdio_gpio_int(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	case HostCmd_CMD_SET_BSS_MODE:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+#ifdef WIFI_DIRECT_SUPPORT
+		if (pdata_buf) {
+			cmd_ptr->params.bss_mode.con_type = *(t_u8 *)pdata_buf;
+		} else
+#endif
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+			cmd_ptr->params.bss_mode.con_type =
+				CONNECTION_TYPE_ADHOC;
+		else if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
+			cmd_ptr->params.bss_mode.con_type =
+				CONNECTION_TYPE_INFRA;
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_SET_BSS_MODE) +
+					 S_DS_GEN);
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_802_11_NET_MONITOR:
+		ret = wlan_cmd_net_monitor(cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_MEASUREMENT_REQUEST:
+	case HostCmd_CMD_MEASUREMENT_REPORT:
+		ret = wlan_meas_cmd_process(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	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;
+#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_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_cmd_multi_chan_cfg(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_cmd_multi_chan_policy(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_cmd_drcs_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_DFS_REPEATER_MODE:
+		ret = wlan_cmd_dfs_repeater_cfg(pmpriv, cmd_ptr,
+						cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_COALESCE_CFG:
+		ret = wlan_cmd_coalesce_config(pmpriv, cmd_ptr,
+					       cmd_action, pdata_buf);
+		break;
+	case HostCmd_DS_GET_SENSOR_TEMP:
+		ret = wlan_cmd_get_sensor_temp(pmpriv, cmd_ptr, cmd_action);
+		break;
+	case HostCmd_CMD_802_11_MIMO_SWITCH:
+		ret = wlan_cmd_802_11_mimo_switch(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_STA_CONFIGURE:
+		ret = wlan_cmd_sta_config(pmpriv, cmd_ptr, cmd_action,
+					  pioctl_buf, pdata_buf);
+		break;
+
+	case HostCmd_CMD_INDEPENDENT_RESET_CFG:
+		ret = wlan_cmd_ind_rst_cfg(cmd_ptr, cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_ROAM_OFFLOAD:
+		ret = wlan_cmd_roam_offload(pmpriv, cmd_ptr, cmd_action,
+					    pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT:
+		ret = wlan_cmd_ps_inactivity_timeout(pmpriv, cmd_ptr,
+						     cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_HOST_CLOCK_CFG:
+		ret = wlan_cmd_host_clock_cfg(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_DYN_BW:
+		ret = wlan_cmd_config_dyn_bw(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	case HostCmd_CMD_ACS:
+		ret = wlan_cmd_acs(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;
+	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(IN t_void *priv, IN t_u8 first_bss)
+{
+	pmlan_private pmpriv = (pmlan_private)priv;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 enable = MTRUE;
+	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;
+	}
+
+	if (IS_FW_SUPPORT_ADHOC(pmpriv->adapter)) {
+		/* set ibss coalescing_status */
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+				       HostCmd_ACT_GEN_SET, 0, MNULL, &enable);
+		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_sd8997/mlan/mlan_sta_cmdresp.c b/wlan_sd8997/mlan/mlan_sta_cmdresp.c
new file mode 100644
index 0000000..2d24088
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_sta_cmdresp.c
@@ -0,0 +1,2944 @@
+/** @file mlan_sta_cmdresp.c
+ *
+ *  @brief This file contains the handling of command
+ *  responses generated by firmware.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+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_11h.h"
+#include "mlan_sdio.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
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @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: command 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 (MTRUE == wlan_is_station_list_empty(pmpriv))
+			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: command 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 mlan_ioctl_req structure
+ *
+ *  @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);
+
+	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_802_11_ASSOCIATE:
+		wlan_reset_connect_state(pmpriv, MTRUE);
+		break;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		pmadapter->sdio_rx_aggr_enable = MFALSE;
+		PRINTM(MMSG, "FW don't support SDIO single port rx aggr\n");
+		break;
+
+	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_ROAM_OFFLOAD:
+		wlan_clear_fw_roaming_pmk(pmpriv);
+		pmpriv->adapter->fw_roaming = MFALSE;
+		PRINTM(MERROR, "FW do not support roaming!\n");
+		break;
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		ret = MLAN_STATUS_SUCCESS;
+		PRINTM(MCMND, "FW don't support chan region cfg command!\n");
+		break;
+	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_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
+ */
+static mlan_status
+wlan_ret_802_11_rssi_info_ext(IN pmlan_private pmpriv,
+			      IN HostCmd_DS_COMMAND *resp,
+			      IN 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 *) ((t_u8 *)prssi_info_rsp +
+						    sizeof
+						    (HostCmd_DS_802_11_RSSI_INFO_EXT));
+		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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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(IN pmlan_private pmpriv,
+		 IN HostCmd_DS_COMMAND *resp, IN 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;
+		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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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 *)((t_u8 *)ptxp_cfg
+					      + sizeof(HostCmd_DS_TXPWR_CFG));
+	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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN 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 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
+ */
+static mlan_status
+wlan_ret_802_11_mac_address(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_MAC_ADDRESS *pmac_addr = &resp->params.mac_addr;
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+
+	memcpy(pmpriv->adapter, pmpriv->curr_addr, pmac_addr->mac_addr,
+	       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(pmpriv->adapter, &bss->param.mac_addr, pmpriv->curr_addr,
+		       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 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(IN pmlan_private pmpriv,
+			       IN HostCmd_DS_COMMAND *resp,
+			       IN 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(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+	       &resp->params.deauth.reason_code, 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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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(IN pmlan_private pmpriv,
+			     IN HostCmd_DS_COMMAND *resp,
+			     IN 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 for WPA/WPA2 h-supp mode\n");
+				pmpriv->port_open = MTRUE;
+			}
+			if (0 !=
+			    memcmp(pmpriv->adapter, pmpriv->gtk_rekey.kek,
+				   zero_kek, sizeof(zero_kek))) {
+				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 (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(pmpriv->adapter, sec->param.encrypt_key.mac_addr,
+			       pkey->key_param_set.mac_addr,
+			       MLAN_MAC_ADDR_LENGTH);
+			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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.wapi.key,
+				       sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.wapi.pn,
+				       PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.tkip.key,
+				       sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.tkip.pn,
+				       WPA_PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.aes.key,
+				       sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.aes.pn,
+				       WPA_PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.cmac_aes.
+				       key, sec->param.encrypt_key.key_len);
+				memcpy(pmpriv->adapter,
+				       sec->param.encrypt_key.pn,
+				       pkey->key_param_set.key_params.cmac_aes.
+				       ipn, IGTK_PN_SIZE);
+				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(pmpriv->adapter,
+				       sec->param.encrypt_key.key_material,
+				       pkey->key_param_set.key_params.wep.key,
+				       sec->param.encrypt_key.key_len);
+				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(IN pmlan_private pmpriv,
+				   IN HostCmd_DS_COMMAND *resp,
+				   IN 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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(IN pmlan_private pmpriv,
+				IN 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(pmpriv->adapter,
+		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		       pibss_coal_resp->bssid, MLAN_MAC_ADDR_LENGTH);
+
+		/* 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      OUT 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(pmpriv->adapter, &misc->param.cust_ie, cust_ie,
+		       (cust_ie->len + sizeof(MrvlIEtypesHeader_t)));
+		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(pmpriv->adapter,
+				       (t_u8 *)&misc->param.cust_ie +
+				       (cust_ie->len +
+					sizeof(MrvlIEtypesHeader_t)),
+				       max_mgmt_ie,
+				       max_mgmt_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(IN 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp,
+		     OUT 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(pmpriv->adapter, &misc->param.tdls_config,
+		       &ptdls_config_data->tdls_info,
+		       MIN(sizeof(mlan_ds_misc_tdls_config),
+			   (resp->size - S_DS_GEN)));
+		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);
+			/* 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);
+			link_ptr->u.final_data_rate = final_data_rate / 2;
+
+			link_ptr =
+				(tdls_each_link_status *)(((t_u8 *)link_ptr) +
+							  link_length);
+		}
+		memcpy(pmpriv->adapter, &misc->param.tdls_config,
+		       &ptdls_config_data->tdls_info,
+		       MIN(sizeof(mlan_ds_misc_tdls_config),
+			   (resp->size - S_DS_GEN)));
+		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(IN pmlan_private pmpriv,
+		   IN HostCmd_DS_COMMAND *resp, OUT 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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(IN pmlan_private pmpriv,
+			    IN HostCmd_DS_COMMAND *resp,
+			    IN 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
+ *  network monitor
+ *
+ *  @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_net_monitor(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pmisc = MNULL;
+	mlan_ds_misc_net_monitor *net_mon = MNULL;
+	HostCmd_DS_802_11_NET_MONITOR *cmd_net_mon =
+		(HostCmd_DS_802_11_NET_MONITOR *)&resp->params.net_mon;
+	ChanBandParamSet_t *pchan_band = MNULL;
+	t_u8 band_info = 0;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pmisc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		net_mon = &pmisc->param.net_mon;
+		net_mon->enable_net_mon =
+			wlan_le16_to_cpu(cmd_net_mon->enable_net_mon);
+		net_mon->filter_flag =
+			wlan_le16_to_cpu(cmd_net_mon->filter_flag);
+		pchan_band = &cmd_net_mon->monitor_chan.chan_band_param[0];
+		/* Band information in the TLV is bits[1:0] */
+		band_info = pchan_band->bandcfg.chanBand;
+		net_mon->channel = pchan_band->chan_number;
+		if (band_info == BAND_2GHZ)
+			net_mon->band |= (BAND_B | BAND_G);
+		if (band_info == BAND_5GHZ)
+			net_mon->band |= BAND_A;
+		net_mon->chan_bandwidth =
+			GET_SECONDARYCHAN(pchan_band->bandcfg.chan2Offset);
+		if (band_info == BAND_2GHZ)
+			net_mon->band |= BAND_GN;
+		if (band_info == BAND_5GHZ)
+			net_mon->band |= BAND_AN;
+		if (band_info == BAND_2GHZ)
+			net_mon->band |= BAND_GAC;
+		if (band_info == BAND_5GHZ)
+			net_mon->band |= BAND_AAC;
+	}
+	pmpriv->adapter->enable_net_mon =
+		wlan_le16_to_cpu(cmd_net_mon->enable_net_mon);
+
+	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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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(pmpriv->adapter, user_data->user_data,
+		       cmd_user_data->user_data, user_data->user_data_length);
+		pioctl_buf->data_read_written =
+			sizeof(mlan_ds_misc_otp_user_data) +
+			user_data->user_data_length;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *resp,
+			  IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_DFS_REPEATER_MODE *cmd_dfs_repeater =
+		&resp->params.dfs_repeater;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_misc_dfs_repeater *dfs_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		dfs_cfg =
+			(mlan_ds_misc_dfs_repeater *)&misc->param.dfs_repeater;
+		dfs_cfg->mode = wlan_le16_to_cpu(cmd_dfs_repeater->mode);
+	}
+	if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_SET)) {
+		if (wlan_le16_to_cpu(cmd_dfs_repeater->mode) == 1) {
+			/* Set dfs_repeater mode to true/enabled
+			 * for futher references.
+			 */
+			pmpriv->adapter->dfs_repeater = MTRUE;
+		} else {
+			pmpriv->adapter->dfs_repeater = MFALSE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of coalesce config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_coalesce_config(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN mlan_ioctl_req *pioctl_buf)
+{
+	ENTER();
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+mlan_status
+wlan_ret_get_sensor_temp(IN pmlan_private pmpriv,
+			 const IN HostCmd_DS_COMMAND *resp,
+			 OUT 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 offload feature
+ *
+ *  @param priv             A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_offload_feature_ctrl(mlan_private *priv, HostCmd_DS_COMMAND *resp)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_OFFLOAD_FEATURE_CTRL *fctrl = &resp->params.fctrl;
+	ENTER();
+
+	PRINTM(MINFO, "offload feature ctrl set successful \n");
+	if (fctrl->featureSelect == 0) {
+		PRINTM(MCMND, "11k:  Neighbor Report %s \n",
+		       fctrl->control.std.
+		       dot11k_nbor_support ? "enabled" : "disabled");
+		PRINTM(MCMND, "11k:  Traffic Stream Measurement %s \n",
+		       fctrl->control.std.dot11k_tsm ? "enabled" : "disabled");
+		PRINTM(MCMND, "11k:  Link Measurement %s \n",
+		       fctrl->control.std.dot11k_lm ? "enabled" : "disabled");
+		PRINTM(MCMND, "11k:  Beacon Report %s \n",
+		       fctrl->control.std.dot11k_rm ? "enabled" : "disabled");
+		PRINTM(MCMND, "11v:  BSS Transition %s \n",
+		       fctrl->control.std.
+		       dot11v_bss_trans ? "enabled" : "disabled");
+
+		priv->enable_11k = fctrl->control.std.dot11k_nbor_support
+			| fctrl->control.std.dot11k_tsm
+			| fctrl->control.std.dot11k_lm
+			| fctrl->control.std.dot11k_rm;
+		if (priv->enable_11k)
+			SET_EXTCAP_BSS_TRANSITION(priv->ext_cap);
+		else
+			RESET_EXTCAP_BSS_TRANSITION(priv->ext_cap);
+		PRINTM(MMSG, "11K %s \n",
+		       priv->enable_11k ? "enable" : "disable");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+		    IN HostCmd_DS_COMMAND *resp, IN 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.chanBand,
+				       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 clears PMK in fw for fw roaming
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_clear_fw_roaming_pmk(IN pmlan_private pmpriv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_SUPPLICANT_PMK,
+			       HostCmd_ACT_GEN_REMOVE, 0, MNULL, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of enable/disable roaming offload to fw
+ *
+ *  @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_roam_offload(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_ROAM_OFFLOAD *cmdrsp_roam_offload =
+		(HostCmd_DS_ROAM_OFFLOAD *) & resp->params.roam_offload;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	MrvlIEtypesHeader_t *header = MNULL;
+	MrvlIEtypes_fw_roam_enable_t *roam_offload_enable = MNULL;
+
+	ENTER();
+
+	if (resp->result == HostCmd_RESULT_OK) {
+		header = (MrvlIEtypesHeader_t *)cmdrsp_roam_offload->tlv;
+		header->type = wlan_le16_to_cpu(header->type);
+		if (header->type == TLV_TYPE_ROAM) {
+			roam_offload_enable =
+				(MrvlIEtypes_fw_roam_enable_t *)
+				cmdrsp_roam_offload->tlv;
+			if ((t_u8)roam_offload_enable->roam_enable)
+				pmpriv->adapter->fw_roaming = MTRUE;
+			else {
+				pmpriv->adapter->fw_roaming = MFALSE;
+				wlan_clear_fw_roaming_pmk(pmpriv);
+			}
+		}
+	}
+
+	LEAVE();
+	return status;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @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(IN pmlan_private pmpriv,
+		IN HostCmd_DS_COMMAND *resp, IN 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 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(IN t_void *priv,
+			     IN t_u16 cmdresp_no,
+			     IN t_void *pcmd_buf, IN 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;
+	int ctr;
+
+	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;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_ret_sdio_rx_aggr_cfg(pmpriv, resp);
+		break;
+	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_FW_WAKE_METHOD:
+		ret = wlan_ret_fw_wakeup_method(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_ROBUSTCOEX:
+		break;
+	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_FTM_CONFIG_SESSION_PARAMS:
+		ret = wlan_ret_802_11_ftm_config_session_params(pmpriv, resp,
+								pioctl_buf);
+		break;
+	case HostCmd_CMD_FTM_CONFIG_RESPONDER:
+		ret = wlan_ret_802_11_ftm_config_responder(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_11K_GET_NLIST:
+		break;
+	case HostCmd_CMD_OFFLOAD_FEATURE_CONTROL:
+		ret = wlan_ret_offload_feature_ctrl(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);
+		pmadapter->tx_buf_size =
+			(pmadapter->tx_buf_size / MLAN_SDIO_BLOCK_SIZE) *
+			MLAN_SDIO_BLOCK_SIZE;
+		pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+		pmadapter->mp_end_port =
+			wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port);
+		pmadapter->mp_data_port_mask = DATA_PORT_MASK;
+
+		for (ctr = 1; ctr <= MAX_PORT - pmadapter->mp_end_port; ctr++) {
+			pmadapter->mp_data_port_mask &=
+				~(1 << (MAX_PORT - ctr));
+		}
+
+		pmadapter->curr_wr_port = 0;
+		pmadapter->mpa_tx.pkt_aggr_limit =
+			MIN(SDIO_MP_AGGR_DEF_PKT_LIMIT,
+			    (pmadapter->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->mp_data_port_mask);
+		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:
+		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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		break;
+	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;
+	case HostCmd_CMD_802_11_NET_MONITOR:
+		ret = wlan_ret_net_monitor(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;
+#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;
+#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_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_ret_multi_chan_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_ret_multi_chan_policy(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_ret_drcs_cfg(pmpriv, resp, pioctl_buf);
+		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_DS_GET_SENSOR_TEMP:
+		ret = wlan_ret_get_sensor_temp(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_MIMO_SWITCH:
+		break;
+	case HostCmd_CMD_STA_CONFIGURE:
+		ret = wlan_ret_sta_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HOST_CMD_PMIC_CONFIGURE:
+		break;
+	case HostCmd_CMD_INDEPENDENT_RESET_CFG:
+		ret = wlan_ret_ind_rst_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT:
+		break;
+	case HostCmd_CMD_ROAM_OFFLOAD:
+		ret = wlan_ret_roam_offload(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_GET_TSF:
+		ret = wlan_ret_get_tsf(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_HOST_CLOCK_CFG:
+		ret = wlan_ret_host_clock_cfg(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_DYN_BW:
+		ret = wlan_ret_dyn_bw(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_ACS:
+		ret = wlan_ret_acs(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_BOOT_SLEEP:
+		ret = wlan_ret_boot_sleep(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_sd8997/mlan/mlan_sta_event.c b/wlan_sd8997/mlan/mlan_sta_event.c
new file mode 100644
index 0000000..348db77
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_sta_event.c
@@ -0,0 +1,1499 @@
+/** @file mlan_sta_event.c
+ *
+ *  @brief This file contains MLAN event handling.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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
+
+/********************************************************
+			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);
+				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(priv->adapter, tdls_oper.peer_mac,
+				       tdls_event->peer_mac_addr,
+				       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(priv->adapter,
+				       (t_u8 *)tdls_evt->peer_mac_addr,
+				       tdls_event->peer_mac_addr,
+				       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
+ */
+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(priv->adapter, (t_u8 *)tdls_evt->peer_mac_addr,
+			       sta_ptr->mac_addr, 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;
+}
+
+/**
+ *  @brief This function will handle the generic NAN event for further wlan action
+ *   based on the Event subtypes
+ *
+ *  @param pmpriv     A pointer to mlan_private
+ *  @param evt_buf    A pointer to mlan_event
+ *  @param pmbuf    A pointer to mlan buffer
+ *
+ *  @return         N/A
+ */
+static void
+wlan_process_nan_event(pmlan_private pmpriv, pmlan_buffer pmbuf)
+{
+	t_u8 *evt_buf = MNULL;
+	mlan_event *pevent;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	event_nan_generic *nan_event = (event_nan_generic *)
+		(pmbuf->pbuf + pmbuf->data_offset + sizeof(mlan_event_id));
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+			       MLAN_MEM_DEF, &evt_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !evt_buf) {
+		LEAVE();
+		return;
+	}
+
+	pevent = (pmlan_event)evt_buf;
+
+	pevent->bss_index = pmpriv->bss_index;
+	if (wlan_le16_to_cpu(nan_event->event_sub_type) ==
+	    NAN_EVT_SUBTYPE_SD_EVENT ||
+	    wlan_le16_to_cpu(nan_event->event_sub_type) ==
+	    NAN_EVT_SUBTYPE_SDF_TX_DONE) {
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+	} else {
+		t_u8 test_mac[MLAN_MAC_ADDR_LENGTH]
+		= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
+		pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
+		pevent->event_len = MLAN_MAC_ADDR_LENGTH;
+		memcpy(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+		       test_mac, MLAN_MAC_ADDR_LENGTH);
+		wlan_ralist_add(pmpriv, test_mac);
+		memcpy(pmpriv->adapter,
+		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		       test_mac, MLAN_MAC_ADDR_LENGTH);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
+		if (pmpriv->port_ctrl_mode == MTRUE)
+			pmpriv->port_open = MTRUE;
+		pmpriv->media_connected = MTRUE;
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "nan interface - opened\n");
+		pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+	}
+
+	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");
+
+	/* 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);
+
+	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;
+	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.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));
+		priv->assoc_rsp_size = 0;
+	}
+	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_11d_is_enabled(priv)) &&
+	    (priv->state_11d.user_enable_11d == DISABLE_11D)) {
+
+		priv->state_11d.enable_11d = DISABLE_11D;
+		enable = DISABLE_11D;
+
+		/* Send cmd to FW to enable/disable 11D function */
+		ret = wlan_prepare_cmd(priv,
+				       HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET,
+				       Dot11D_i, MNULL, &enable);
+		if (ret)
+			PRINTM(MERROR, "11D: Failed to enable 11D\n");
+	}
+	if (pmadapter->num_cmd_timeout && pmadapter->curr_cmd &&
+	    (pmadapter->cmd_timer_is_set == MFALSE)) {
+		LEAVE();
+		return;
+	}
+
+	pevent->bss_index = priv->bss_index;
+	pevent->event_id = MLAN_EVENT_ID_FW_DISCONNECTED;
+	pevent->event_len = sizeof(priv->disconnect_reason_code);
+	memcpy(priv->adapter, pevent->event_buf, &priv->disconnect_reason_code,
+	       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;
+		/* Copy OBSS scan parameters */
+		memcpy(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 = ele_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(IN 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[100];
+	t_u8 *evt_buf = MNULL;
+	pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
+	t_u16 reason_code;
+	t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+	sta_node *sta_ptr = MNULL;
+	t_u8 i = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_event *pevent = (mlan_event *)event_buf;
+	Event_WLS_FTM_t *event_ftm = MNULL;
+
+	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;
+	}
+
+	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(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(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:
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+				       MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO;
+			pevent->event_len =
+				pmbuf->data_len - sizeof(eventcause);
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       sizeof(eventcause), pevent->event_len);
+			PRINTM(MEVENT, "EVENT: FW Debug Info %s\n",
+			       (t_u8 *)pevent->event_buf);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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_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;
+		}
+		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_ANN:
+		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);
+		if (pmadapter->ecsa_enable) {
+			t_u8 stop_tx = *(t_u8 *)pmadapter->event_body;
+			if (stop_tx)
+				pmadapter->state_rdh.tx_block = MTRUE;
+		} else
+			wlan_11h_handle_event_chanswann(pmpriv);
+		break;
+	case EVENT_RADAR_DETECTED:
+		PRINTM(MEVENT, "EVENT: Radar Detected\n");
+
+		/* Send as passthru first, this event can cause other events */
+		memset(pmadapter, pevent, 0x00, sizeof(event_buf));
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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(MEVENT, "EVENT: Channel Report Ready\n");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+				       MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			memset(pmadapter, evt_buf, 0x00, MAX_EVENT_SIZE);
+			/* Setup event buffer */
+			pevent = (pmlan_event)evt_buf;
+			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(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset +
+			       sizeof(eventcause), pevent->event_len);
+			/* Handle / pass event data */
+			ret = wlan_11h_handle_event_chanrpt_ready(pmpriv,
+								  pevent);
+
+			/* Also send this event as passthru */
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			/* Now done with buffer */
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		/* Send up this Event to unblock MOAL waitqueue */
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL);
+		break;
+	case EVENT_EXT_SCAN_REPORT:
+		PRINTM(MEVENT, "EVENT: EXT_SCAN Report (%d)\n",
+		       pmbuf->data_len);
+		if (pmadapter->pscan_ioctl_req && pmadapter->ext_scan)
+			ret = wlan_handle_event_ext_scan_report(priv, pmbuf);
+		break;
+	case EVENT_EXT_SCAN_STATUS_REPORT:
+		PRINTM(MEVENT, "EVENT: EXT_SCAN status report (%d)\n",
+		       pmbuf->data_len);
+		pmadapter->ext_scan_timeout = MFALSE;
+		ret = wlan_handle_event_ext_scan_status(priv, pmbuf);
+		break;
+	case EVENT_MEAS_REPORT_RDY:
+		PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n",
+		       eventcause);
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_MEASUREMENT_REPORT,
+				       HostCmd_ACT_GEN_SET, 0, 0, MNULL);
+		break;
+	case EVENT_WMM_STATUS_CHANGE:
+		if (pmbuf && pmbuf->data_len
+		    > sizeof(eventcause) + sizeof(MrvlIEtypesHeader_t)) {
+			PRINTM(MEVENT, "EVENT: WMM status changed: %d\n",
+			       pmbuf->data_len);
+
+			evt_buf = (pmbuf->pbuf
+				   + pmbuf->data_offset + sizeof(eventcause));
+
+			wlan_ret_wmm_get_status(pmpriv,
+						evt_buf,
+						pmbuf->data_len -
+						sizeof(eventcause));
+		} else {
+			PRINTM(MEVENT, "EVENT: WMM status changed\n");
+			ret = wlan_cmd_wmm_status_change(pmpriv);
+		}
+		break;
+
+	case EVENT_RSSI_LOW:
+		PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			memset(pmadapter, evt_buf, 0x00, MAX_EVENT_SIZE);
+			pevent = (pmlan_event)evt_buf;
+			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(pmadapter, (t_u8 *)pevent->event_buf,
+			       (t_u8 *)&pmadapter->event_body,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			memset(pmadapter, evt_buf, 0x00, MAX_EVENT_SIZE);
+			pevent = (pmlan_event)evt_buf;
+			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(pmadapter, (t_u8 *)pevent->event_buf,
+			       (t_u8 *)&pmadapter->event_body,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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));
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmadapter->event_body, 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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmadapter->event_body, pevent->event_len);
+		if (pmadapter->dfs_repeater)
+			wlan_dfs_rep_bw_change(pmadapter);
+		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);
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		break;
+	case EVENT_WIFIDIRECT_SERVICE_DISCOVERY:
+		PRINTM(MEVENT, "EVENT: WIFIDIRECT service discovery event %d\n",
+		       eventcause);
+		/* Allocate large memory for service discovery */
+		if (pmbuf->data_len < MAX_EVENT_SIZE)
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       MAX_EVENT_SIZE, MLAN_MEM_DEF,
+					       &evt_buf);
+		else
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       MAX_EVENT_SIZE * 2, MLAN_MEM_DEF,
+					       &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		break;
+	case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+		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;
+#endif /* WIFI_DIRECT_SUPPORT */
+
+	case EVENT_TDLS_GENERIC_EVENT:
+		PRINTM(MEVENT, "EVENT: TDLS event %d\n", eventcause);
+		wlan_parse_tdls_event(pmpriv, pmbuf);
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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:
+		memcpy(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		sta_ptr = wlan_add_station_entry(pmpriv, sta_addr);
+		if (sta_ptr) {
+			PRINTM(MMSG,
+			       "wlan: EVENT: IBSS_STA_CONNECT " MACSTR "\n",
+			       MAC2STR(sta_addr));
+			if (pmpriv->adapter->adhoc_11n_enabled) {
+				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->ibss_ampdu[i];
+					else
+						sta_ptr->ampdu_sta[i] =
+							BA_STREAM_NOT_ALLOWED;
+				}
+				memset(pmadapter, sta_ptr->rx_seq, 0xff,
+				       sizeof(sta_ptr->rx_seq));
+			}
+		}
+		break;
+	case EVENT_IBSS_STATION_DISCONNECT:
+		memcpy(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		PRINTM(MMSG, "wlan: EVENT: IBSS_STA_DISCONNECT " MACSTR "\n",
+		       MAC2STR(sta_addr));
+
+		if (pmpriv->adapter->adhoc_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);
+		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_MULTI_CHAN_INFO:
+		PRINTM(MEVENT, "EVENT: MULTI_CHAN_INFO\n");
+		wlan_handle_event_multi_chan_info(pmpriv, pmbuf);
+		break;
+
+	case EVENT_FW_DUMP_INFO:
+		PRINTM(MEVENT, "EVENT: Dump FW info\n");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_FW_DUMP_INFO;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, MIN(pevent->event_len,
+							     sizeof
+							     (event_buf)));
+		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;
+	case EVENT_NLIST_REPORT:
+		PRINTM(MEVENT, "EVENT: 11K NLIST REPORT: len=%d\n",
+		       pmbuf->data_len);
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+			pevent->event_len = pmbuf->data_len;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       pevent->event_len);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		break;
+	case EVENT_NAN_GENERIC:
+		PRINTM(MEVENT, "EVENT: NAN_GENERIC_EVENT\n");
+		wlan_process_nan_event(pmpriv, pmbuf);
+		break;
+
+	case EVENT_MANAGEMENT_FRAME_WAKEUP:
+		PRINTM(MEVENT, "EVENT: EVENT_MANAGEMENT_FRAME_WAKEUP HOST\n");
+		break;
+	case EVENT_ROAM_OFFLOAD:
+		memcpy(pmadapter,
+		       pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		       (t_u8 *)(pmadapter->event_body + 2),
+		       MLAN_MAC_ADDR_LENGTH);
+		/*Update the BSS for inform kernel, otherwise kernel will give warning for not find BSS */
+		memcpy(pmadapter, (t_u8 *)&pmadapter->pscan_table[0],
+		       (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor,
+		       sizeof(BSSDescriptor_t));
+		if (!pmadapter->num_in_scan_table)
+			pmadapter->num_in_scan_table = 1;
+		PRINTM(MEVENT, "EVENT: ROAM OFFLOAD IN FW SUCCESS\n");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_FW_ROAM_OFFLOAD_RESULT;
+		/** Drop event id length and 2 bytes reverved length*/
+			pevent->event_len =
+				pmbuf->data_len - sizeof(eventcause) - 2;
+			memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+			       pmadapter->event_body + 2, MIN(pevent->event_len,
+							      MAX_EVENT_SIZE));
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		break;
+	case EVENT_WLS_FTM_COMPLETE:
+		PRINTM(MEVENT, "EVENT: FTM_GENERIC_EVENT\n");
+		/* Allocate memory for event buffer */
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+				       MLAN_MEM_DEF, &evt_buf);
+		if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
+			pevent = (pmlan_event)evt_buf;
+			pevent->bss_index = pmpriv->bss_index;
+			event_ftm =
+				(Event_WLS_FTM_t *) (pmbuf->pbuf +
+						     pmbuf->data_offset);
+			if (event_ftm->sub_event_id ==
+			    WLS_SUB_EVENT_RTT_RESULTS)
+				wlan_fill_hal_rtt_results(pmpriv, event_ftm,
+							  pmbuf->data_len,
+							  pevent);
+			else {
+				pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+				pevent->event_len = pmbuf->data_len;
+				memcpy(pmadapter, (t_u8 *)pevent->event_buf,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pevent->event_len);
+			}
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
+		}
+		break;
+	default:
+		PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL);
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8997/mlan/mlan_sta_ioctl.c b/wlan_sd8997/mlan/mlan_sta_ioctl.c
new file mode 100644
index 0000000..fd7b22c
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_sta_ioctl.c
@@ -0,0 +1,6172 @@
+/** @file mlan_sta_ioctl.c
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+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_sdio.h"
+#include "mlan_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief enable adhoc aes key
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *
+ *  @return         N/A
+ */
+static void
+wlan_enable_aes_key(pmlan_private pmpriv)
+{
+
+	ENTER();
+
+	if (pmpriv->aes_key.key_len != WPA_AES_KEY_LEN) {
+		LEAVE();
+		return;
+	}
+	wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+			 HostCmd_ACT_GEN_SET, 0, MNULL, &pmpriv->aes_key);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			     IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(pmadapter, &info->param.bss_info.ssid, &pbss_desc->ssid,
+	       sizeof(mlan_802_11_ssid));
+
+	/* BSSID */
+	memcpy(pmadapter, &info->param.bss_info.bssid, &pbss_desc->mac_address,
+	       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(pmadapter, &info->param.bss_info.capability_info,
+	       &pbss_desc->cap_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(pmadapter, &info->param.bss_info.ext_cap,
+		       (t_u8 *)pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t),
+		       pbss_desc->pext_cap->ieee_hdr.len);
+	}
+
+	/* Listen Interval */
+	info->param.bss_info.listen_interval = pmpriv->listen_interval;
+
+	/* Association ID */
+	if (pmpriv->assoc_rsp_buf)
+		info->param.bss_info.assoc_id =
+			(t_u16)((IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf)->
+			a_id;
+	else
+		info->param.bss_info.assoc_id = 0;
+
+	/* AP/Peer supported rates */
+	memset(pmadapter, info->param.bss_info.peer_supp_rates, 0,
+	       sizeof(info->param.bss_info.peer_supp_rates));
+	memcpy(pmadapter, info->param.bss_info.peer_supp_rates,
+	       pbss_desc->supported_rates,
+	       MIN(sizeof(info->param.bss_info.peer_supp_rates),
+		   sizeof(pbss_desc->supported_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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *pget_info = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
+
+	switch (pget_info->sub_command) {
+	case MLAN_OID_GET_STATS:
+		status = wlan_get_info_stats(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_SIGNAL:
+		status = wlan_get_info_signal(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_SIGNAL_EXT:
+		status = wlan_get_info_signal_ext(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_FW_INFO:
+		pioctl_req->data_read_written =
+			sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
+		pget_info->param.fw_info.fw_ver = pmadapter->fw_release_number;
+		memcpy(pmadapter, &pget_info->param.fw_info.mac_addr,
+		       pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
+		pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+		pget_info->param.fw_info.region_code = pmadapter->region_code;
+		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;
+		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.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_roaming_support =
+			(pmadapter->
+			 fw_cap_info & FW_ROAMING_SUPPORT) ? 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(IN pmlan_adapter pmadapter, IN 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 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
+ */
+static mlan_status
+wlan_radio_ioctl_band_cfg(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req)
+{
+	t_u8 i, global_band = 0;
+	t_u8 chan_offset;
+	t_u8 infra_band = 0;
+	t_u8 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 = (t_u8)radio_cfg->param.band_cfg.config_bands;
+		adhoc_band = (t_u8)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 |= 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;
+		}
+
+		if (wlan_11d_set_universaltable
+		    (pmpriv, global_band | adhoc_band)) {
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		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;
+		pmadapter->chan_bandwidth =
+			(t_u8)radio_cfg->param.band_cfg.adhoc_chan_bandwidth;
+		/*
+		 * 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)
+				    || (pmadapter->adhoc_start_band & BAND_AN)
+					) {
+					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;
+		}
+
+		/* validate the channel offset */
+		chan_offset = wlan_validate_chan_offset(pmpriv,
+							pmadapter->
+							adhoc_start_band,
+							pmpriv->adhoc_channel,
+							pmadapter->
+							chan_bandwidth);
+
+		if (chan_offset != SEC_CHAN_NONE) {
+			if (chan_offset == SEC_CHAN_ABOVE)
+				pmadapter->chan_bandwidth =
+					CHANNEL_BW_40MHZ_ABOVE;
+			else
+				pmadapter->chan_bandwidth =
+					CHANNEL_BW_40MHZ_BELOW;
+		}
+		if ((adhoc_band & BAND_GN)
+		    || (adhoc_band & BAND_AN)
+			) {
+			pmadapter->adhoc_11n_enabled = MTRUE;
+		} else {
+			pmadapter->adhoc_11n_enabled = MFALSE;
+		}
+	} 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);
+		/* adhoc channel bandwidth */
+		radio_cfg->param.band_cfg.adhoc_chan_bandwidth =
+			pmadapter->chan_bandwidth;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+		       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(IN pmlan_adapter pmadapter,
+				  IN 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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+		       IN 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_AN)
+		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
+	else 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) {
+				if (pmadapter->adhoc_11n_enabled)
+					pmadapter->adhoc_start_band =
+						BAND_A | BAND_AN;
+				else
+					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) {
+				if (pmadapter->adhoc_11n_enabled)
+					pmadapter->adhoc_start_band =
+						BAND_A | BAND_AN;
+				else
+					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(IN pmlan_adapter pmadapter, IN 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(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_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");
+
+			/* Clear any past association response stored for application retrieval */
+			pmpriv->assoc_rsp_size = 0;
+			pmpriv->curr_chan_flags =
+				bss->param.ssid_bssid.channel_flags;
+			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;
+			if (pmpriv->adhoc_aes_enabled)
+				wlan_enable_aes_key(pmpriv);
+		} 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 (pmpriv->adhoc_aes_enabled)
+				wlan_enable_aes_key(pmpriv);
+		}
+	}
+
+	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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+			   IN 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 passphrase
+ *
+ *  @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;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ssid_bssid *ssid_bssid = MNULL;
+	mlan_ds_sec_cfg sec;
+	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;
+
+	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(pmadapter, (t_u8 *)&sec_pp->ssid,
+			       &pbss_desc->ssid, sizeof(mlan_802_11_ssid));
+		} else
+			memcpy(pmadapter, (t_u8 *)&sec_pp->bssid,
+			       &ssid_bssid->bssid, MLAN_MAC_ADDR_LENGTH);
+	} else {
+		memcpy(pmadapter, (t_u8 *)&sec_pp->ssid, &ssid_bssid->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);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Search for a BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_bss_ioctl_find_bss(IN pmlan_adapter pmadapter,
+			IN 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 Check if BSS channel is valid for Station's region
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_bss_ioctl_bss_11d_check_channel(IN pmlan_adapter pmadapter,
+				     IN 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(IN pmlan_adapter pmadapter, IN 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_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(IN pmlan_adapter pmadapter,
+				   IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			   IN t_u16 cmd_no, IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(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_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(IN pmlan_adapter pmadapter, IN 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;
+	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(IN pmlan_adapter pmadapter,
+		      IN pmlan_ioctl_req pioctl_req, IN 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(IN pmlan_adapter pmadapter,
+				 IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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.adhoc_awake_period =
+			(t_u32)pmadapter->adhoc_awake_period;
+		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.adhoc_awake_period)
+			pmadapter->adhoc_awake_period =
+				(t_u16)pm_cfg->param.ps_cfg.adhoc_awake_period;
+		else
+			pm_cfg->param.ps_cfg.adhoc_awake_period =
+				(t_u32)pmadapter->adhoc_awake_period;
+		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(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_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(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_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(IN pmlan_adapter pmadapter,
+			IN 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(pmadapter, (t_u8 *)pmadapter->mgmt_filter,
+		       (t_u8 *)pm_cfg->param.mgmt_filter,
+		       (i + 1) * sizeof(mlan_mgmt_frame_wakeup));
+	} 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(IN pmlan_adapter pmadapter, IN 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_FW_WAKEUP_METHOD:
+		status = wlan_fw_wakeup_method(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(priv->adapter, priv->wpa_ie, ie_data_ptr, ie_len);
+		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 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(priv->adapter, priv->wapi_ie, ie_data_ptr, ie_len);
+		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(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_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(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_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(IN pmlan_adapter pmadapter,
+				IN 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(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_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(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_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		sec->param.encrypt_mode = pmpriv->sec_info.encryption_mode;
+	else
+		pmpriv->sec_info.encryption_mode = sec->param.encrypt_mode;
+
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Random charactor
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return		random charactor
+ */
+t_u8
+wlan_get_random_charactor(pmlan_adapter pmadapter)
+{
+	t_u32 sec, usec;
+	t_u8 ch = 0;
+
+	ENTER();
+
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+						  &usec);
+	sec = (sec & 0xFFFF) + (sec >> 16);
+	usec = (usec & 0xFFFF) + (usec >> 16);
+	ch = (((sec << 16) + usec) % 26) + 'a';
+	LEAVE();
+	return ch;
+}
+
+/**
+ *  @brief Set/Get WPA status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_sec_ioctl_wpa_enable(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_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);
+		/** clear adhoc aes flag, when WPA enabled */
+		pmpriv->adhoc_aes_enabled = MFALSE;
+		pmpriv->aes_key.key_len = 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(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_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,
+						       MNULL,
+						       &sec->param.encrypt_key);
+				goto exit;
+			}
+			PRINTM(MERROR, "Key_index is invalid\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+		index = sec->param.encrypt_key.key_index;
+	}
+
+	if ((sec->param.encrypt_key.key_disable == MTRUE)||
+	    (sec->param.encrypt_key.key_remove == MTRUE)) {
+		pmpriv->sec_info.wep_status = Wlan802_11WEPDisabled;
+		/* remove key */
+		if (sec->param.encrypt_key.key_remove == MTRUE) {
+			memset(pmadapter, &pmpriv->wep_key[index], 0,
+			       sizeof(mrvl_wep_key_t));
+			/* call firmware remove key */
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_802_11_KEY_MATERIAL,
+					       HostCmd_ACT_GEN_SET,
+					       0,
+					       MNULL, &sec->param.encrypt_key);
+			if (ret)
+				goto exit;
+		}
+	} else {
+		if (sec->param.encrypt_key.key_len) {
+			if ((sec->param.encrypt_key.key_len !=
+			     WEP_104_BIT_LEN)&&(sec->param.encrypt_key.
+						key_len != WEP_40_BIT_LEN)) {
+				PRINTM(MERROR, "Invalid wep key len=%d\n",
+				       sec->param.encrypt_key.key_len);
+				/* We will use random key to clear the key buffer in FW */
+				if (sec->param.encrypt_key.key_len <
+				    WEP_40_BIT_LEN)
+					sec->param.encrypt_key.key_len =
+						WEP_40_BIT_LEN;
+				else
+					sec->param.encrypt_key.key_len =
+						WEP_104_BIT_LEN;
+				for (i = 0; i < sec->param.encrypt_key.key_len;
+				     i++)
+					sec->param.encrypt_key.key_material[i] =
+						wlan_get_random_charactor
+						(pmadapter);
+			}
+			pwep_key = &pmpriv->wep_key[index];
+			/* Cleanup */
+			memset(pmadapter, pwep_key, 0, sizeof(mrvl_wep_key_t));
+			/* Copy the key in the driver */
+
+			memcpy(pmadapter, pwep_key->key_material,
+			       sec->param.encrypt_key.key_material,
+			       sec->param.encrypt_key.key_len);
+			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 (0
+				    || &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(pmadapter, sec->param.encrypt_key.key_material,
+			       pwep_key->key_material,
+			       sec->param.encrypt_key.key_len);
+		}
+		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(pmadapter,
+				       sec->param.encrypt_key.key_material,
+				       pwep_key->key_material,
+				       sec->param.encrypt_key.key_len);
+			}
+			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(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_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;
+	}
+
+	if (sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN) {
+	/** back up adhoc AES key */
+		memset(pmpriv->adapter, &pmpriv->aes_key, 0,
+		       sizeof(pmpriv->aes_key));
+		memcpy(pmpriv->adapter, (t_u8 *)&pmpriv->aes_key,
+		       (t_u8 *)&sec->param.encrypt_key,
+		       sizeof(pmpriv->aes_key));
+	}
+
+    /** only adhoc aes key_index = MLAN_KEY_INDEX_UNICAST */
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS &&
+	    sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN
+	    && sec->param.encrypt_key.key_index & MLAN_KEY_INDEX_UNICAST) {
+		t_u8 zero_key_material[WPA_AES_KEY_LEN];
+		memset(pmadapter, zero_key_material, 0,
+		       sizeof(zero_key_material));
+		if (memcmp
+		    (pmadapter, sec->param.encrypt_key.key_material,
+		     zero_key_material, WPA_AES_KEY_LEN)) {
+			PRINTM(MINFO, "Adhoc AES Enabled.\n");
+			pmpriv->adhoc_aes_enabled = MTRUE;
+		} else {
+			PRINTM(MINFO, "Adhoc AES Disabled.\n");
+			pmpriv->adhoc_aes_enabled = MFALSE;
+	    /** clear adhoc AES key */
+			pmpriv->aes_key.key_len = 0;
+		}
+	}
+
+	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(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_sec_cfg *sec = MNULL;
+	int index;
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+
+	if ((sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_UNICAST)&&
+	    (sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN)) {
+		if (pmpriv->adhoc_aes_enabled == MTRUE &&
+		    (pmpriv->aes_key.key_len == WPA_AES_KEY_LEN)) {
+			HEXDUMP("Get ADHOCAES Key",
+				pmpriv->aes_key.key_material, WPA_AES_KEY_LEN);
+			memcpy(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->aes_key.key_material, WPA_AES_KEY_LEN);
+			LEAVE();
+			return ret;
+		} else {
+			PRINTM(MERROR, " ADHOCAES key is not set yet!\n");
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			LEAVE();
+			return ret;
+		}
+	}
+	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 || pmpriv->adhoc_aes_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(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->wep_key[index].key_material,
+			       MIN(MLAN_MAX_KEY_LENGTH,
+				   pmpriv->wep_key[index].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)
+			   || (pmpriv->adhoc_aes_enabled)
+			) {
+			/* Return WPA enabled */
+			sec->param.encrypt_key.key_disable = MFALSE;
+
+			memcpy(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->aes_key.key_material,
+			       MIN(MLAN_MAX_KEY_LENGTH,
+				   pmpriv->aes_key.key_len));
+			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(pmadapter, sec->param.encrypt_key.key_material,
+			       pmpriv->wep_key[index].key_material,
+			       MIN(MLAN_MAX_KEY_LENGTH,
+				   pmpriv->wep_key[index].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)
+			   || (pmpriv->adhoc_aes_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(IN pmlan_adapter pmadapter,
+			   IN 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 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(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_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(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];
+	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(IN pmlan_adapter pmadapter, IN 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_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 };
+
+	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);
+	} 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) {
+			t_u8 len = sizeof(priv->ext_cap);
+			if (len > pvendor_ie->len)
+				len = pvendor_ie->len;
+			memcpy(priv->adapter, &priv->ext_cap, &ie_data_ptr[2],
+			       len);
+		} 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 == 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(priv->adapter, (t_u8 *)&priv->wps.wps_ie,
+				       ie_data_ptr, ie_len);
+				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(priv->adapter,
+				       priv->gen_ie_buf + priv->gen_ie_buf_len,
+				       ie_data_ptr, ie_len);
+				/* Increment the stored buffer length by
+				 * the size passed */
+				priv->gen_ie_buf_len += ie_len;
+			} else {
+				/* Passed data does not fit in the
+				 * remaining buffer space */
+				ret = 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(IN pmlan_adapter pmadapter,
+			IN 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(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_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(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];
+
+	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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			   IN 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)
+	    || (pmadapter->adhoc_start_band & BAND_AN)
+		) {
+		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(IN pmlan_adapter pmadapter,
+				      IN 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(IN pmlan_adapter pmadapter, IN 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;
+#if defined(DFS_TESTING_SUPPORT)
+	case MLAN_OID_11H_DFS_TESTING:
+		status = wlan_11h_ioctl_dfs_testing(pmadapter, pioctl_req);
+		break;
+#endif
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief 11k enable
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param pioctl_buf 	A pointer to ioctl request buffer
+ *  @param enable_11k   11k enable flag.
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_11k_enable(mlan_private *pmpriv, t_void *pioctl_buf, t_u8 enable_11k)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_OFFLOAD_FEATURE_CTRL fctrl;
+
+	ENTER();
+
+	/* Send cmd HostCmd_CMD_OFFLOAD_FEATURE_CONTROL to FW to enable/disable 11K function */
+	/* need to active 11h first  when enable 11k */
+	if (!wlan_11h_is_active(pmpriv)) {
+		ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR, "11h enable failed \n");
+			goto done;
+		}
+	}
+	memset(pmpriv->adapter, &fctrl, 0, sizeof(fctrl));
+	fctrl.featureSelect = 0;	/* Std feature */
+
+	/* enable or disable Neighbor AP list Report */
+	fctrl.control.std.dot11k_nbor_support = enable_11k;
+	/* enable or disable Traffic Stream Measurement */
+	fctrl.control.std.dot11k_tsm = enable_11k;
+	/* enable or disable Link Measurement */
+	fctrl.control.std.dot11k_lm = enable_11k;
+	/* enable or disable Radio Measurement (Beacon Report) */
+	fctrl.control.std.dot11k_rm = enable_11k;
+
+	/* enable 11v BSS Transition with 11k */
+	fctrl.control.std.dot11v_bss_trans = enable_11k;
+
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_OFFLOAD_FEATURE_CONTROL,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_buf, &fctrl);
+
+	if (ret) {
+		PRINTM(MERROR, "11K: Failed to %s 11K\n",
+		       (enable_11k) ? "enable" : "disable");
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 11k enable ioctl
+ *
+ *  @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_11k_cfg_ioctl_enable(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_11k_cfg *pcfg_11k = MNULL;
+
+	ENTER();
+
+	pcfg_11k = (mlan_ds_11k_cfg *) pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (pmpriv->media_connected == MTRUE
+		    && pcfg_11k->param.enable_11k != pmpriv->enable_11k) {
+			PRINTM(MERROR,
+			       "11K setting cannot be changed while connecting with AP.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		PRINTM(MINFO, "11K: 11kcfg SET=%d\n",
+		       pcfg_11k->param.enable_11k);
+
+		/* Compare with current settings */
+		if (pmpriv->enable_11k != pcfg_11k->param.enable_11k) {
+			ret = wlan_11k_enable(pmpriv, pioctl_req,
+					      pcfg_11k->param.enable_11k);
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = MLAN_STATUS_PENDING;
+		} else {
+			PRINTM(MINFO,
+			       "11K: same as current setting, do nothing\n");
+		}
+	} else {
+		pcfg_11k->param.enable_11k = pmpriv->enable_11k;
+		pioctl_req->data_read_written =
+			sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+		PRINTM(MINFO, "11K: 11kcfg GET=%d\n",
+		       pcfg_11k->param.enable_11k);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 11k get nlist
+ *
+ *  @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_11k_get_nlist(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];
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_GET && pmpriv->media_connected) {
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_802_11K_GET_NLIST,
+				       HostCmd_ACT_GEN_GET,
+				       0, pioctl_req, MNULL);
+		if (ret) {
+			PRINTM(MERROR, "11K: prepare get_nlist failed\n");
+			ret = MLAN_STATUS_FAILURE;
+		} else {
+			/* start excute command */
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = MLAN_STATUS_PENDING;
+		}
+	} else {
+		PRINTM(MERROR, " 11k get_nlist only support GET oper\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 11K cfg ioctl
+ *
+ *  @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_11k_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_11k_cfg *ds_11kcfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_11k_cfg)) {
+		PRINTM(MWARN, "MLAN 11K IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_11k_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	ds_11kcfg = (mlan_ds_11k_cfg *) pioctl_req->pbuf;
+	switch (ds_11kcfg->sub_command) {
+	case MLAN_OID_11K_CFG_ENABLE:
+		status = wlan_11k_cfg_ioctl_enable(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11K_GET_NLIST:
+		status = wlan_11k_get_nlist(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(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;
+
+	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(pmadapter, misc->param.gen_ie.ie_data,
+			       pmpriv->wpa_ie, misc->param.gen_ie.len);
+		} 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(pmadapter, pmadapter->arp_filter,
+			       misc->param.gen_ie.ie_data,
+			       misc->param.gen_ie.len);
+			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(IN pmlan_adapter pmadapter,
+			   IN 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;
+	t_u16 mc_policy = pmadapter->mc_policy;
+	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);
+    /** 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))) {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+	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;
+	}
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MULTI_CHAN_POLICY,
+			       HostCmd_ACT_GEN_SET, 0, MNULL, &mc_policy);
+	if (ret == MLAN_STATUS_FAILURE) {
+		LEAVE();
+		return ret;
+	}
+	if (ret == MLAN_STATUS_PENDING)
+		pmadapter->pwarm_reset_ioctl_req = pioctl_req;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+			      IN 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->mpa_tx.buf_size =
+					mpa_ctrl->tx_buf_size;
+
+			if (mpa_ctrl->rx_buf_size > 0)
+				pmadapter->mpa_rx.buf_size =
+					mpa_ctrl->rx_buf_size;
+
+			if (wlan_alloc_sdio_mpa_buffers(pmadapter,
+							pmadapter->mpa_tx.
+							buf_size,
+							pmadapter->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->mpa_tx.pkt_aggr_limit =
+				mpa_ctrl->tx_max_ports;
+		if (mpa_ctrl->rx_max_ports > 0)
+			pmadapter->mpa_rx.pkt_aggr_limit =
+				mpa_ctrl->rx_max_ports;
+
+		pmadapter->mpa_tx.enabled = (t_u8)mpa_ctrl->tx_enable;
+		pmadapter->mpa_rx.enabled = (t_u8)mpa_ctrl->rx_enable;
+
+	} else {
+		mpa_ctrl->tx_enable = (t_u16)pmadapter->mpa_tx.enabled;
+		mpa_ctrl->rx_enable = (t_u16)pmadapter->mpa_rx.enabled;
+		mpa_ctrl->tx_buf_size = (t_u16)pmadapter->mpa_tx.buf_size;
+		mpa_ctrl->rx_buf_size = (t_u16)pmadapter->mpa_rx.buf_size;
+		mpa_ctrl->tx_max_ports =
+			(t_u16)pmadapter->mpa_tx.pkt_aggr_limit;
+		mpa_ctrl->rx_max_ports =
+			(t_u16)pmadapter->mpa_rx.pkt_aggr_limit;
+	}
+
+exit:
+	LEAVE();
+	return ret;
+}
+#endif /* SDIO_MULTI_PORT_TX_AGGR || SDIO_MULTI_PORT_RX_AGGR */
+
+/**
+ *  @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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			      IN 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(pmadapter, misc->param.assoc_resp.assoc_resp_buf,
+		       pmpriv->assoc_rsp_buf, MIN(ASSOC_RSP_BUF_SIZE,
+						  pmpriv->assoc_rsp_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(IN pmlan_adapter pmadapter,
+			   IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_SOFT_RESET,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get the thermal reading
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_thermal(IN pmlan_adapter pmadapter,
+			IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		PRINTM(MERROR, "Thermal reading setting is not allowed!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	}
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_802_11_SNMP_MIB,
+			       cmd_action,
+			       Thermal_i, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set subscribe event
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_subscribe_evt(IN pmlan_adapter pmadapter,
+			      IN 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
+ */
+mlan_status
+wlan_ipaddr_arp_filter(IN pmlan_adapter pmadapter,
+		       IN pmlan_ioctl_req pioctl_req, IN 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(pmadapter, pmadapter->arp_filter, buf, len);
+		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;
+}
+
+#define FLTR_BUF_IP_OFFSET              24
+#define FLTR_BUF_IP_OFFSET_2_IP_1       9
+#define FLTR_BUF_IP_OFFSET_2_IP_2       26
+
+/**
+ *  @brief Enable/Disable Auto ARP resonse
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *  @param ipv4_addr    ipv4 Address
+ *  @param num_ipv4     Number of ipv4 Addresses
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_ipaddr_auto_arp_resp(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req,
+			  IN t_u32 *ipv4_addr, IN t_u8 num_ipv4)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_GEN *hostcmd_hdr;
+	HostCmd_DS_MEF_CFG *mefcmd;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_ds_misc_cmd *hostcmd;
+	t_u32 buf_len = 0;
+	t_u8 *buf, *filter;
+
+	t_u8 fltr_buf[] = { 0x01, 0x10, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0x08, 0x06, 0x02, 0x02, 0x14, 0x00, 0x00,
+		0x00, 0x01, 0x41, 0x01, 0x00, 0x00, 0x00, 0x01,
+		0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e, 0x00,
+		0x00, 0x00, 0x01, 0x41, 0x44
+	};
+	t_u8 fltr_buf_2_ip[] = { 0x01, 0x10, 0x33, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e,
+		0x00, 0x00, 0x00, 0x01, 0x41, 0x01, 0x00, 0x00,
+		0x00, 0x01, 0xc0, 0xa8, 0x02, 0x6d, 0x04, 0x02,
+		0x2e, 0x00, 0x00, 0x00, 0x01, 0x41, 0x45, 0x01,
+		0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x02, 0x02,
+		0x14, 0x00, 0x00, 0x00, 0x01, 0x41, 0x44
+	};
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_cmd),
+			       MLAN_MEM_DEF, (t_u8 **)&hostcmd);
+
+	if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
+		PRINTM(MERROR, "Failed to allocate hostcmd  buffer\n");
+		pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(pmpriv->adapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
+	buf = hostcmd->cmd;
+
+	/* Prepare hostcmd buffer */
+	hostcmd_hdr = (HostCmd_DS_GEN *)(buf);
+	hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
+	mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN);
+	buf_len = S_DS_GEN;
+
+	if (!ipv4_addr) {
+		PRINTM(MINFO, "Disable Auto ARP Response\n");
+		mefcmd->criteria = wlan_cpu_to_le32(0);
+		mefcmd->nentries = wlan_cpu_to_le16(0);
+		buf_len += sizeof(HostCmd_DS_MEF_CFG);
+	} else {
+		/* Event bit (bit2) of HS conditions should be masked out */
+		mefcmd->criteria =
+			wlan_cpu_to_le32(pmpriv->adapter->hs_cfg.
+					 conditions & ~MBIT(2));
+		mefcmd->nentries = wlan_cpu_to_le16(1);
+		buf_len += sizeof(HostCmd_DS_MEF_CFG);
+		filter = buf + buf_len;
+		if (num_ipv4 == 1) {
+			memcpy(pmpriv->adapter, filter, fltr_buf,
+			       sizeof(fltr_buf));
+			memcpy(pmpriv->adapter, &filter[FLTR_BUF_IP_OFFSET],
+			       &ipv4_addr[0], sizeof(t_u32));
+			buf_len += sizeof(fltr_buf);
+		} else if (num_ipv4 >= 2) {
+			memcpy(pmpriv->adapter, filter, fltr_buf_2_ip,
+			       sizeof(fltr_buf_2_ip));
+			memcpy(pmpriv->adapter,
+			       &filter[FLTR_BUF_IP_OFFSET_2_IP_1],
+			       &ipv4_addr[0], sizeof(t_u32));
+			memcpy(pmpriv->adapter,
+			       &filter[FLTR_BUF_IP_OFFSET_2_IP_2],
+			       &ipv4_addr[1], sizeof(t_u32));
+			buf_len += sizeof(fltr_buf_2_ip);
+		}
+	}
+	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+	hostcmd->len = buf_len;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       0,
+			       0, 0, (t_void *)pioctl_req, (t_void *)hostcmd);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief MEF configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_mef_cfg(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_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(pmpriv->adapter, filter, fltr_buf, sizeof(fltr_buf));
+		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(pmpriv->adapter, filter, mef_cfg->param.cmd_buf.cmd,
+		       mef_cfg->param.cmd_buf.len);
+		buf_len += mef_cfg->param.cmd_buf.len;
+		break;
+	default:
+		PRINTM(MERROR, "Invalid sub ID parameter\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+		break;
+	}
+	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+	hostcmd->len = buf_len;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       0,
+			       0, 0, (t_void *)pioctl_req, (t_void *)hostcmd);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+done:
+	if (hostcmd)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief ipaddr configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_ipaddr_cfg(IN pmlan_adapter pmadapter,
+			   IN 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];
+	int i = 0;
+
+	ENTER();
+
+	/* GET operation */
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		memcpy(pmadapter, misc->param.ipaddr_cfg.ip_addr,
+		       pmpriv->ip_addr, IPADDR_LEN);
+		misc->param.ipaddr_cfg.op_code = pmpriv->op_code;
+		goto done;
+	}
+	/* only one IP is supported in current firmware */
+	for (i = 0; i < misc->param.ipaddr_cfg.ip_addr_num; i++) {
+		memcpy(pmadapter, &ipv4_addr[i],
+		       misc->param.ipaddr_cfg.ip_addr[i], 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;
+	if (misc->param.ipaddr_cfg.op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP)
+		ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req,
+						ipv4_addr,
+						misc->param.ipaddr_cfg.
+						ip_addr_num);
+	else if (pmpriv->op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP)
+		ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req, MNULL,
+						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(pmadapter, pmpriv->ip_addr,
+		       misc->param.ipaddr_cfg.ip_addr, IPADDR_LEN);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief CFP code configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_cfp_code_cfg(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 = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_ds_misc_cfp_code *cfp_code = MNULL;
+	t_u32 region_bg = 0;
+	t_u32 region_a = 0;
+	int i;
+
+	ENTER();
+
+	cfp_code = &misc->param.cfp_code;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+			PRINTM(MERROR,
+			       "ForceRegionRule is set in the on-chip OTP"
+			       "memory\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		/* Save the values in MLAN */
+		if (!cfp_code->cfp_code_bg)
+			cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+			/* Use the region code to search for the index */
+			if (cfp_code->cfp_code_bg == region_code_index[i]) {
+				region_bg = cfp_code->cfp_code_bg;
+				break;
+			}
+		}
+		if (!cfp_code->cfp_code_a)
+			cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+			/* Use the region code to search for the index */
+			if (cfp_code->cfp_code_a == region_code_index[i]) {
+				region_a = cfp_code->cfp_code_a;
+				break;
+			}
+		}
+		if (!region_a) {
+			for (i = 0; i < MRVDRV_MAX_CFP_CODE_A; i++) {
+				/* Use the CFP code to search for the index */
+				if (cfp_code->cfp_code_a == cfp_code_index_a[i])
+					break;
+			}
+			if (i >= MRVDRV_MAX_CFP_CODE_A) {
+				PRINTM(MERROR,
+				       "CFP Code not identified for A\n");
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		pmadapter->cfp_code_bg = (t_u8)cfp_code->cfp_code_bg;
+		pmadapter->cfp_code_a = (t_u8)cfp_code->cfp_code_a;
+		if (region_bg && region_a && (region_bg == region_a))
+			pmadapter->region_code = pmadapter->cfp_code_a;
+		else
+			pmadapter->region_code = 0;
+		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+					 pmadapter->config_bands | pmadapter->
+					 adhoc_start_band)) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	} else {
+		/* GET operation */
+		cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+		cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets up country code and downloads CMD to FW
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_ioctl_country_code(IN pmlan_adapter pmadapter,
+			     IN 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_bg && cfp_a && (cfp_bg == cfp_a))
+			pmadapter->region_code = cfp_a;
+		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(pmadapter, pmadapter->country_code,
+		       country_code->country_code, COUNTRY_CODE_LEN);
+	} else {
+		/* GET operation */
+		memcpy(pmadapter, country_code->country_code,
+		       pmadapter->country_code, COUNTRY_CODE_LEN);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Configure MFPC and MFPR for management frame protection
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_pmfcfg(IN pmlan_adapter pmadapter, IN 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 get sensor temperature
+ *
+ *  @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_get_sensor_temp(IN pmlan_adapter pmadapter,
+				IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, " sensor temp only support get operation \n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_DS_GET_SENSOR_TEMP,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Gtk Rekey Offload
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_gtk_rekey_offload(IN pmlan_adapter pmadapter,
+				  IN 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(pmadapter, &pmpriv->gtk_rekey,
+		       &misc_cfg->param.gtk_rekey,
+		       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 enable/disable roam offload in firmware
+ *
+ *  @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_roam_offload(IN pmlan_adapter pmadapter,
+		       IN 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 (!(pmadapter->fw_cap_info & FW_ROAMING_SUPPORT)) {
+		PRINTM(MERROR, "Firmware roaming not support\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (!IS_FW_SUPPORT_SUPPLICANT(pmadapter)) {
+		PRINTM(MERROR, "Embedded supplicant do not enable\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if ((misc->param.roam_offload.config_mode == ROAM_OFFLOAD_ENABLE) &&
+	    misc->param.roam_offload.userset_passphrase) {
+		pmpriv->adapter->userset_passphrase =
+			misc->param.roam_offload.userset_passphrase;
+		if (!misc->param.roam_offload.enable) {
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_ROAM_OFFLOAD,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req, &misc->param.roam_offload);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set roam offload aplist to firmware
+ *
+ *  @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_roam_offload_aplist(IN pmlan_adapter pmadapter,
+			      IN 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 {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_ROAM_OFFLOAD,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req, &misc->param.roam_offload);
+
+	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(IN pmlan_adapter pmadapter,
+		       IN 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 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(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+
+	if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
+		PRINTM(MERROR, "Request buffer not found!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	switch (misc->sub_command) {
+	case MLAN_OID_MISC_GEN_IE:
+		status = wlan_misc_ioctl_gen_ie(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_REGION:
+		status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_WARM_RESET:
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &pmadapter->ioctl_pending_q,
+				       (pmlan_linked_list)pioctl_req,
+				       pmadapter->callbacks.moal_spin_lock,
+				       pmadapter->callbacks.moal_spin_unlock);
+		pmadapter->pending_ioctl = MTRUE;
+		status = MLAN_STATUS_PENDING;
+		break;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	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_COALESCING_STATUS:
+		status = wlan_misc_ioctl_coalescing_status(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_NET_MONITOR:
+		status = wlan_misc_ioctl_net_monitor(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_OTP_USER_DATA:
+		status = wlan_misc_otp_user_data(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;
+	case MLAN_OID_MISC_MULTI_CHAN_CFG:
+		status = wlan_misc_ioctl_multi_chan_config(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_MISC_MULTI_CHAN_POLICY:
+		status = wlan_misc_ioctl_multi_chan_policy(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_MISC_DRCS_CFG:
+		status = wlan_misc_ioctl_drcs_config(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_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_DFS_REAPTER_MODE:
+		status = wlan_misc_ioctl_dfs_repeater_cfg(pmadapter,
+							  pioctl_req);
+		break;
+	case MLAN_OID_MISC_COALESCE_CFG:
+		status = wlan_misc_ioctl_coalesce_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_SENSOR_TEMP:
+		status = wlan_misc_ioctl_get_sensor_temp(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_OPER_CLASS:
+		status = wlan_misc_ioctl_oper_class(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_OPER_CLASS_CHECK:
+		status = wlan_misc_ioctl_operclass_validation(pmadapter,
+							      pioctl_req);
+		break;
+	case MLAN_OID_MISC_GTK_REKEY_OFFLOAD:
+		status = wlan_misc_ioctl_gtk_rekey_offload(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_MISC_IND_RST_CFG:
+		status = wlan_misc_ioctl_ind_rst_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_TSF:
+		status = wlan_misc_ioctl_get_tsf(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_ROAM_OFFLOAD:
+		status = wlan_misc_roam_offload(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_ROAM_OFFLOAD_APLIST:
+		status = wlan_misc_roam_offload_aplist(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_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_CONFIG_RTT:
+		status = wlan_config_rtt(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_CANCEL_RTT:
+		status = wlan_cancel_rtt(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_RTT_RESPONDER_CFG:
+		status = wlan_rtt_responder_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_CORRELATED_TIME:
+		status = wlan_misc_get_correlated_time(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;
+	case MLAN_OID_MISC_ACS:
+		status = wlan_misc_acs(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(IN pmlan_adapter pmadapter,
+		      IN pmlan_ioctl_req pioctl_req, IN t_u32 action)
+{
+	mlan_ds_scan *scan = MNULL;
+
+	ENTER();
+
+	scan = (mlan_ds_scan *)pioctl_req->pbuf;
+	if (action == MLAN_ACT_GET) {
+		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.ext_scan = pmadapter->ext_scan;
+	} else {
+		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;
+		pmadapter->ext_scan = scan->param.scan_cfg.ext_scan;
+	}
+	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(IN pmlan_adapter pmadapter, IN 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(pmadapter, mac, &bss->param.ssid_bssid.bssid,
+			       sizeof(mac));
+			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(pmadapter, &bss->param.ssid_bssid.ssid, &pbss_desc->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(pmadapter, (t_u8 *)&bss->param.ssid_bssid.bssid,
+		       (t_u8 *)&pbss_desc->mac_address, 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_11K_CFG:
+		status = wlan_11k_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_sd8997/mlan/mlan_sta_rx.c b/wlan_sd8997/mlan/mlan_sta_rx.c
new file mode 100644
index 0000000..b5c44e2
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_sta_rx.c
@@ -0,0 +1,688 @@
+/** @file mlan_sta_rx.c
+ *
+ *  @brief This file contains the handling of RX in MLAN
+ *  module.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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;
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/********************************************************
+		Global functions
+********************************************************/
+
+/**
+ *  @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;
+
+#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 = pos[1];
+			for (i = 0; i < pos[1]; i++)
+				sta_ptr->support_rate[i] = pos[2 + i];
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+			for (i = 0; i < pos[1]; i++)
+				sta_ptr->support_rate[sta_ptr->rate_len + i] =
+					pos[2 + i];
+			sta_ptr->rate_len += pos[1];
+			break;
+		case HT_CAPABILITY:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->HTcap, pos,
+			       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(priv->adapter, &sta_ptr->HTInfo, pos,
+			       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(priv->adapter, (t_u8 *)&sta_ptr->BSSCO_20_40,
+			       pos, sizeof(IEEEtypes_2040BSSCo_t));
+			break;
+		case EXT_CAPABILITY:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->ExtCap, pos,
+			       pos[1] + sizeof(IEEEtypes_Header_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS Extended capability",
+				    (t_u8 *)(&sta_ptr->ExtCap),
+				    sta_ptr->ExtCap.ieee_hdr.len + 2);
+			break;
+		case RSN_IE:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->rsn_ie, pos,
+			       pos[1] + sizeof(IEEEtypes_Header_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS Rsn ie ",
+				    (t_u8 *)(&sta_ptr->rsn_ie),
+				    pos[1] + 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(priv->adapter, (t_u8 *)&sta_ptr->link_ie, pos,
+			       sizeof(IEEEtypes_LinkIDElement_t));
+			break;
+
+		case VHT_CAPABILITY:
+			memcpy(priv->adapter, (t_u8 *)&sta_ptr->vht_cap, pos,
+			       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(priv->adapter, (t_u8 *)&sta_ptr->vht_oprat, pos,
+			       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(priv->adapter, (t_u8 *)&sta_ptr->aid_info, pos,
+			       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 get pxpd info for radiotap info
+ *
+ *  @param priv A pointer to pmlan_private
+ *  @param prx_pd   A pointer to RxPD
+ *  @param prt_info   A pointer to radiotap_info
+ *
+ *  @return        N/A
+ */
+void
+wlan_rxpdinfo_to_radiotapinfo(pmlan_private priv, RxPD *prx_pd,
+			      radiotap_info * prt_info)
+{
+	radiotap_info rt_info_tmp;
+	t_u8 rx_rate_info = 0;
+	t_u8 mcs_index = 0;
+	t_u8 format = 0;
+	t_u8 bw = 0;
+	t_u8 gi = 0;
+	t_u8 ldpc = 0;
+
+	memset(priv->adapter, &rt_info_tmp, 0x00, sizeof(rt_info_tmp));
+	rt_info_tmp.snr = prx_pd->snr;
+	rt_info_tmp.nf = prx_pd->nf;
+	rt_info_tmp.band_config = (prx_pd->rx_info & 0xf);
+	rt_info_tmp.chan_num = (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+
+	rt_info_tmp.antenna = prx_pd->antenna;
+	rx_rate_info = prx_pd->rate_info;
+	if ((rx_rate_info & 0x3) == MLAN_RATE_FORMAT_VHT) {
+		/* VHT rate */
+		format = MLAN_RATE_FORMAT_VHT;
+		mcs_index = MIN(prx_pd->rx_rate & 0xF, 9);
+		/* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
+		bw = (rx_rate_info & 0xC) >> 2;
+		/* LGI: gi =0, SGI: gi = 1 */
+		gi = (rx_rate_info & 0x10) >> 4;
+	} else if ((rx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
+		/* HT rate */
+		format = MLAN_RATE_FORMAT_HT;
+		mcs_index = prx_pd->rx_rate;
+		/* 20M: bw=0, 40M: bw=1 */
+		bw = (rx_rate_info & 0xC) >> 2;
+		/* LGI: gi =0, SGI: gi = 1 */
+		gi = (rx_rate_info & 0x10) >> 4;
+	} else {
+		/* LG rate */
+		format = MLAN_RATE_FORMAT_LG;
+		mcs_index = (prx_pd->rx_rate > MLAN_RATE_INDEX_OFDM0) ?
+			prx_pd->rx_rate - 1 : prx_pd->rx_rate;
+	}
+	ldpc = rx_rate_info & 0x40;
+
+	rt_info_tmp.rate_info.mcs_index = mcs_index;
+	rt_info_tmp.rate_info.rate_info =
+		(ldpc << 5) | (format << 3) | (bw << 1) | gi;
+	rt_info_tmp.rate_info.bitrate =
+		wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
+					prx_pd->rate_info);
+
+	if (prx_pd->flags & RXPD_FLAG_EXTRA_HEADER)
+		memcpy(priv->adapter, &rt_info_tmp.extra_info,
+		       (t_u8 *)prx_pd + sizeof(*prx_pd),
+		       sizeof(rt_info_tmp.extra_info));
+
+	memset(priv->adapter, prt_info, 0x00, sizeof(*prt_info));
+	memcpy(priv->adapter, prt_info, &rt_info_tmp, sizeof(*prt_info));
+
+	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
+
+	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(pmadapter, peth_hdr->src_addr,
+		       prx_pkt->eth803_hdr.src_addr,
+		       sizeof(peth_hdr->src_addr));
+		memcpy(pmadapter, peth_hdr->dest_addr,
+		       prx_pkt->eth803_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 (!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);
+
+	if (pmadapter->enable_net_mon) {
+		/* set netmon flag only for a sniffed pkt */
+		if (prx_pd->rx_pkt_type == PKT_TYPE_802DOT11) {
+			pmbuf->flags |= MLAN_BUF_FLAG_NET_MONITOR;
+			goto mon_process;
+		}
+	}
+
+#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)) {
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+			ret = MLAN_STATUS_SUCCESS;
+			PRINTM(MMSG,
+			       "host supplicant eapol pkt process done.\n");
+
+			LEAVE();
+			return ret;
+		}
+	}
+#endif
+
+mon_process:
+	if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
+		//Use some rxpd space to save rxpd info for radiotap header
+		//We should insure radiotap_info is not bigger than RxPD
+		wlan_rxpdinfo_to_radiotapinfo(priv, prx_pd,
+					      (radiotap_info *) (pmbuf->pbuf +
+								 pmbuf->
+								 data_offset -
+								 sizeof
+								 (radiotap_info)));
+	}
+	if (MFALSE || priv->rx_pkt_info) {
+		pmbuf->u.rx_info.data_rate =
+			wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
+						prx_pd->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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	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(IN t_void *adapter, IN 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_u8 adj_rx_rate = 0;
+	t_u8 antenna = 0;
+	rxpd_extra_info *pextra_info = MNULL;
+	ENTER();
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	/* Endian conversion */
+	endian_convert_RxPD(prx_pd);
+
+	if (prx_pd->flags & RXPD_FLAG_EXTRA_HEADER) {
+		pextra_info =
+			(rxpd_extra_info *) ((t_u8 *)prx_pd + sizeof(*prx_pd));
+		endian_convert_RxPD_extra_header(pextra_info);
+	}
+	rx_pkt_type = prx_pd->rx_pkt_type;
+	prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+	priv->rxpd_rate_info = prx_pd->rate_info;
+	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 ((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;
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		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);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		goto done;
+	}
+
+	/*
+	 * 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)
+	     && !IS_11N_ADHOC_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)) {
+		wlan_process_rx_packet(pmadapter, pmbuf);
+		goto done;
+	}
+
+	if (queuing_ra_based(priv) ||
+	    (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)) {
+		memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+		       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;
+				if (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK) {
+					sta_ptr->snr = prx_pd->snr;
+					sta_ptr->nf = prx_pd->nf;
+					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 {
+		if ((rx_pkt_type != PKT_TYPE_BAR) &&
+		    (prx_pd->priority < MAX_NUM_TID))
+			priv->rx_seq[prx_pd->priority] = prx_pd->seq_num;
+		memcpy(pmadapter, ta,
+		       priv->curr_bss_params.bss_descriptor.mac_address,
+		       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)
+		) {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+
+done:
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8997/mlan/mlan_sta_tx.c b/wlan_sd8997/mlan/mlan_sta_tx.c
new file mode 100644
index 0000000..214b769
--- /dev/null
+++ b/wlan_sd8997/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.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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_sdio.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(IN t_void *priv, IN 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(pmpriv->adapter, &pkt_type,
+		       pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type));
+		memcpy(pmpriv->adapter, &tx_control,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+		       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 |=
+				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 = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf, MNULL);
+
+	switch (ret) {
+	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:
+		pmadapter->data_sent = MFALSE;
+		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_sd8997/mlan/mlan_txrx.c b/wlan_sd8997/mlan/mlan_txrx.c
new file mode 100644
index 0000000..0270ec1
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_txrx.c
@@ -0,0 +1,401 @@
+/**
+ * @file mlan_txrx.c
+ *
+ *  @brief This file contains the handling of TX/RX in MLAN
+ *
+ *  (C) Copyright 2009-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/*************************************************************
+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"
+#include "mlan_sdio.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
+	TxPD *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
+
+	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf,
+				     tx_param);
+done:
+	switch (ret) {
+	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;
+			plocal_tx_pd->flags = 0;
+		}
+#endif
+		PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
+		break;
+	case MLAN_STATUS_FAILURE:
+		pmadapter->data_sent = MFALSE;
+		PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
+		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(IN pmlan_adapter pmadapter,
+			 IN pmlan_buffer pmbuf, IN 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 (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);
+		}
+	}
+
+	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(IN pmlan_adapter pmadapter,
+			  IN pmlan_buffer pmbuf, IN mlan_status status)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	MASSERT(pmadapter && pmbuf);
+	if (!pmadapter || !pmbuf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pcb = &pmadapter->callbacks;
+	MASSERT(pmbuf->bss_index < pmadapter->priv_num);
+
+	if (pmbuf->pparent) {
+	/** we will free the pparaent at the end of deaggr */
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	} else {
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+
+	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();
+	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) {
+				PRINTM(MINFO, "Dequeuing bypassed packet %p\n",
+				       pmbuf);
+				/* XXX: nex_pkt_len ??? */
+				tx_param.next_pkt_len = 0;
+				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 */
+					util_enqueue_list_head(pmadapter->
+							       pmoal_handle,
+							       &priv->
+							       bypass_txq,
+							       (pmlan_linked_list)
+							       pmbuf,
+							       pmadapter->
+							       callbacks.
+							       moal_spin_lock,
+							       pmadapter->
+							       callbacks.
+							       moal_spin_unlock);
+				} else {
+					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);
+				}
+				break;
+			} else {
+				PRINTM(MINFO, "Nothing to send\n");
+			}
+		}
+	}
+	LEAVE();
+}
diff --git a/wlan_sd8997/mlan/mlan_uap.h b/wlan_sd8997/mlan/mlan_uap.h
new file mode 100644
index 0000000..c985eb2
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_uap.h
@@ -0,0 +1,93 @@
+/** @file mlan_uap.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of uap functionalities
+ *
+ *  (C) Copyright 2009-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/05/2009: initial version
+********************************************************/
+
+#ifndef _MLAN_UAP_H_
+#define _MLAN_UAP_H_
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert TxPD to little endian format from CPU format */
+#define uap_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 uap_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 TxPD to little endian format from CPU format */
+#define uap_endian_convert_TxPD(x)  do {} while (0)
+/** Convert RxPD from little endian format to CPU format */
+#define uap_endian_convert_RxPD(x)  do {} while (0)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+mlan_status wlan_uap_get_channel(IN pmlan_private pmpriv);
+
+mlan_status wlan_uap_set_channel(IN pmlan_private pmpriv,
+				 IN Band_Config_t uap_band_cfg,
+				 IN t_u8 channel);
+
+mlan_status wlan_uap_get_beacon_dtim(IN pmlan_private pmpriv);
+
+mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_ops_uap_prepare_cmd(IN t_void *priv,
+				     IN t_u16 cmd_no,
+				     IN t_u16 cmd_action,
+				     IN t_u32 cmd_oid,
+				     IN t_void *pioctl_buf,
+				     IN t_void *pdata_buf, IN t_void *pcmd_buf);
+
+mlan_status wlan_ops_uap_process_cmdresp(IN t_void *priv,
+					 IN t_u16 cmdresp_no,
+					 IN t_void *pcmd_buf,
+					 IN t_void *pioctl);
+
+mlan_status wlan_ops_uap_process_rx_packet(IN t_void *adapter,
+					   IN pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_process_event(IN t_void *priv);
+
+t_void *wlan_ops_uap_process_txpd(IN t_void *priv, IN pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_init_cmd(IN t_void *priv, IN t_u8 first_bss);
+
+#endif /* _MLAN_UAP_H_ */
diff --git a/wlan_sd8997/mlan/mlan_uap_cmdevent.c b/wlan_sd8997/mlan/mlan_uap_cmdevent.c
new file mode 100644
index 0000000..5c42fab
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_uap_cmdevent.c
@@ -0,0 +1,4845 @@
+/** @file mlan_uap_cmdevent.c
+ *
+ *  @brief This file contains the handling of AP mode command and event
+ *
+ *  (C) Copyright 2009-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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_sdio.h"
+#include "mlan_11n.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief This function handles the command response error
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             N/A
+ */
+static mlan_status
+uap_process_cmdresp_error(mlan_private *pmpriv, HostCmd_DS_COMMAND *resp,
+			  mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	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) {
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		pmadapter->sdio_rx_aggr_enable = MFALSE;
+		PRINTM(MMSG, "FW don't support SDIO single port rx aggr\n");
+		break;
+
+	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_CHAN_REGION_CFG:
+		ret = MLAN_STATUS_SUCCESS;
+		PRINTM(MCMND, "FW don't support chan region cfg command!\n");
+		break;
+
+	default:
+		break;
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+	pmadapter->curr_cmd = MNULL;
+	wlan_release_cmd_lock(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will return the pointer to station entry in station list
+ *          table which matches the give mac address
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+void
+wlan_notify_station_deauth(mlan_private *priv)
+{
+	sta_node *sta_ptr;
+	t_u8 event_buf[100];
+	mlan_event *pevent = (mlan_event *)event_buf;
+	t_u8 *pbuf;
+
+	ENTER();
+	sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+					     &priv->sta_list,
+					     priv->adapter->callbacks.
+					     moal_spin_lock,
+					     priv->adapter->callbacks.
+					     moal_spin_unlock);
+	if (!sta_ptr) {
+		LEAVE();
+		return;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		memset(priv->adapter, event_buf, 0, sizeof(event_buf));
+		pevent->bss_index = priv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT;
+		pevent->event_len = MLAN_MAC_ADDR_LENGTH + 2;
+		pbuf = (t_u8 *)pevent->event_buf;
+		/* reason field set to 0, Unspecified */
+		memcpy(priv->adapter, pbuf + 2, sta_ptr->mac_addr,
+		       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(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action, IN 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_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(pmadapter, (t_u8 *)mgmt_filter_tlv->filter,
+			       (t_u8 *)mgmt_filter,
+			       i * sizeof(mgmt_frame_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);
+		}
+	}
+	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,
+			 IN HostCmd_DS_COMMAND *cmd,
+			 IN t_u16 cmd_action, IN 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(IN pmlan_private pmpriv,
+			 IN HostCmd_DS_COMMAND *resp,
+			 IN 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 };
+
+	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_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 (!memcmp
+			    (priv->adapter, bc_mac, tx_pause_tlv->peermac,
+			     MLAN_MAC_ADDR_LENGTH))
+				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;
+						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 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,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN 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;
+	t_u32 cmd_size = 0;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+	t_u16 i;
+	t_u16 ac;
+
+	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(pmpriv->adapter, tlv_mac->mac,
+		       &bss->param.bss_config.mac_addr, 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(pmpriv->adapter, tlv_ssid->ssid,
+		       bss->param.bss_config.ssid.ssid,
+		       bss->param.bss_config.ssid.ssid_len);
+		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(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);
+		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(pmpriv->adapter,
+				       tlv_passphrase->passphrase,
+				       bss->param.bss_config.wpa_cfg.passphrase,
+				       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key0.key,
+			       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key1.key,
+			       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key2.key,
+			       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(pmpriv->adapter, tlv_wep_key->key,
+			       bss->param.bss_config.wep_cfg.key3.key,
+			       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(pmpriv->adapter, tlv_htcap->ht_cap.supported_mcs_set,
+		       bss->param.bss_config.supported_mcs_set, 16);
+		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.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(pmpriv->adapter, tlv_wmm_parameter->wmm_para.ouitype,
+		       bss->param.bss_config.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
+	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,
+			   IN HostCmd_DS_COMMAND *cmd,
+			   IN t_u16 cmd_action,
+			   IN pmlan_ioctl_req pioctl_buf, IN t_void *pdata_buf)
+{
+	mlan_ds_bss *bss = MNULL;
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config;
+	MrvlIEtypes_MacAddr_t *mac_tlv = MNULL;
+	MrvlIEtypes_channel_band_t *pdat_tlv_cb = MNULL;
+	MrvlIEtypes_beacon_period_t *bcn_pd_tlv = MNULL, *pdat_tlv_bcnpd =
+		MNULL;
+	MrvlIEtypes_dtim_period_t *dtim_pd_tlv = MNULL, *pdat_tlv_dtimpd =
+		MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	MrvlIEtypes_channel_band_t *chan_band_tlv = MNULL;
+	MrvlIEtypes_chan_bw_oper_t *poper_class_tlv = MNULL;
+	t_u8 length = 0;
+	t_u8 curr_oper_class = 1;
+	t_u8 *oper_class_ie = (t_u8 *)sys_config->tlv_buffer;
+	t_u16 i = 0;
+	t_u8 ac = 0;
+	mlan_ds_misc_custom_ie *cust_ie = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	MrvlIEtypesHeader_t *ie_header =
+		(MrvlIEtypesHeader_t *)sys_config->tlv_buffer;
+	MrvlIEtypesHeader_t *pdata_header = (MrvlIEtypesHeader_t *)pdata_buf;
+	t_u8 *ie = (t_u8 *)sys_config->tlv_buffer + sizeof(MrvlIEtypesHeader_t);
+	t_u16 req_len = 0, travel_len = 0;
+	custom_ie *cptr = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
+	sys_config->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN);
+	if (pioctl_buf == MNULL) {
+
+		if (pdata_buf) {
+			switch (pdata_header->type) {
+			case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
+				pdat_tlv_cb =
+					(MrvlIEtypes_channel_band_t *)pdata_buf;
+				chan_band_tlv =
+					(MrvlIEtypes_channel_band_t *)
+					sys_config->tlv_buffer;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_channel_band_t));
+				chan_band_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+				chan_band_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_channel_band_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				if (cmd_action) {
+					chan_band_tlv->bandcfg =
+						pdat_tlv_cb->bandcfg;
+					chan_band_tlv->channel =
+						pdat_tlv_cb->channel;
+				}
+				ret = MLAN_STATUS_SUCCESS;
+				break;
+			case TLV_TYPE_UAP_BEACON_PERIOD:
+				pdat_tlv_bcnpd =
+					(MrvlIEtypes_beacon_period_t *)
+					pdata_buf;
+				bcn_pd_tlv =
+					(MrvlIEtypes_beacon_period_t *)
+					sys_config->tlv_buffer;
+				cmd->size =
+					sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+					S_DS_GEN +
+					sizeof(MrvlIEtypes_beacon_period_t);
+				bcn_pd_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_BEACON_PERIOD);
+				bcn_pd_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_beacon_period_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				if (cmd_action) {
+					bcn_pd_tlv->beacon_period =
+						wlan_cpu_to_le16
+						(pdat_tlv_bcnpd->beacon_period);
+				}
+				/* Add TLV_UAP_DTIM_PERIOD if it follws in pdata_buf */
+				pdat_tlv_dtimpd =
+					(MrvlIEtypes_dtim_period_t
+					 *)(((t_u8 *)pdata_buf)
+					    +
+					    sizeof
+					    (MrvlIEtypes_beacon_period_t));
+				if (TLV_TYPE_UAP_DTIM_PERIOD ==
+				    pdat_tlv_dtimpd->header.type) {
+					dtim_pd_tlv =
+						(MrvlIEtypes_dtim_period_t
+						 *)(sys_config->tlv_buffer +
+						    sizeof
+						    (MrvlIEtypes_beacon_period_t));
+					cmd->size +=
+						sizeof
+						(MrvlIEtypes_dtim_period_t);
+					dtim_pd_tlv->header.type =
+						wlan_cpu_to_le16
+						(TLV_TYPE_UAP_DTIM_PERIOD);
+					dtim_pd_tlv->header.len =
+						wlan_cpu_to_le16(sizeof
+								 (MrvlIEtypes_dtim_period_t)
+								 -
+								 sizeof
+								 (MrvlIEtypesHeader_t));
+					if (cmd_action) {
+						dtim_pd_tlv->dtim_period =
+							pdat_tlv_dtimpd->
+							dtim_period;
+					}
+				}
+				/* Finalize cmd size */
+				cmd->size = wlan_cpu_to_le16(cmd->size);
+				ret = MLAN_STATUS_SUCCESS;
+				break;
+			case TLV_TYPE_MGMT_IE:
+				cust_ie = (mlan_ds_misc_custom_ie *)pdata_buf;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypesHeader_t) +
+							 cust_ie->len);
+				ie_header->type =
+					wlan_cpu_to_le16(TLV_TYPE_MGMT_IE);
+				ie_header->len = wlan_cpu_to_le16(cust_ie->len);
+
+				if (ie && cust_ie->ie_data_list) {
+					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(pmpriv->adapter, ie,
+					       cust_ie->ie_data_list,
+					       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;
+
+			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(pmpriv->adapter, mac_tlv->mac,
+				       &bss->param.mac_addr,
+				       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.chanBand,
+				       bss->param.ap_channel.channel);
+			}
+		} else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG) &&
+			   (cmd_action == HostCmd_ACT_GEN_SET)) {
+			ret = wlan_uap_cmd_ap_config(pmpriv, cmd, cmd_action,
+						     pioctl_buf);
+			goto done;
+		}
+	} else if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		if ((misc->sub_command == MLAN_OID_MISC_GEN_IE) &&
+		    (misc->param.gen_ie.type == MLAN_IE_TYPE_GEN_IE)
+			) {
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof(MrvlIEtypesHeader_t) +
+						 misc->param.gen_ie.len);
+			ie_header->type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE);
+			ie_header->len =
+				wlan_cpu_to_le16(misc->param.gen_ie.len);
+			if (cmd_action == HostCmd_ACT_GEN_SET)
+				memcpy(pmpriv->adapter, ie,
+				       misc->param.gen_ie.ie_data,
+				       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 && misc->param.cust_ie.ie_data_list) {
+				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(pmpriv->adapter, ie,
+					       misc->param.cust_ie.ie_data_list,
+					       misc->param.cust_ie.len);
+			}
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles command resp for get uap settings
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_cmd_ap_config(IN pmlan_private pmpriv,
+			   IN HostCmd_DS_COMMAND *resp,
+			   IN 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(pmpriv->adapter, &bss->param.bss_config.mac_addr,
+			       tlv_mac->mac, 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(pmpriv->adapter, bss->param.bss_config.ssid.ssid,
+			       tlv_ssid->ssid, MIN(MLAN_MAX_SSID_LENGTH,
+						   tlv_len));
+			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(pmpriv->adapter, bss->param.bss_config.rates,
+			       tlv_rates->rates, MIN(MAX_DATA_RATES, tlv_len));
+			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(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);
+			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;
+			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(pmpriv->adapter,
+			       bss->param.bss_config.wpa_cfg.passphrase,
+			       tlv_passphrase->passphrase,
+			       bss->param.bss_config.wpa_cfg.length);
+			break;
+#ifdef WIFI_DIRECT_SUPPORT
+		case TLV_TYPE_UAP_PSK:
+			tlv_psk = (MrvlIEtypes_psk_t *)tlv;
+			memcpy(pmpriv->adapter, bss->param.bss_config.psk,
+			       tlv_psk->psk, MIN(MLAN_MAX_KEY_LENGTH, tlv_len));
+			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(pmpriv->adapter, pkey->key,
+				       tlv_wep_key->key, 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(pmpriv->adapter,
+			       bss->param.bss_config.supported_mcs_set,
+			       tlv_htcap->ht_cap.supported_mcs_set, 16);
+			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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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(IN pmlan_private pmpriv,
+			IN HostCmd_DS_COMMAND *resp,
+			IN mlan_ioctl_req *pioctl_buf)
+{
+	int resp_len = 0, travel_len = 0;
+	int i = 0;
+	custom_ie *cptr;
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	MrvlIEtypes_MacAddr_t *tlv =
+		(MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer;
+	mlan_ds_misc_custom_ie *cust_ie = MNULL;
+	tlvbuf_max_mgmt_ie *max_mgmt_ie = MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter =
+		(MrvlIEtypes_wmm_parameter_t *)sys_config->tlv_buffer;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list =
+		(MrvlIEtypes_ChanListParamSet_t *)sys_config->tlv_buffer;
+	MrvlIEtypes_channel_band_t *chan_band_tlv =
+		(MrvlIEtypes_channel_band_t *)sys_config->tlv_buffer;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	t_u8 ac = 0;
+	MrvlIEtypes_channel_band_t *tlv_cb = MNULL;
+	MrvlIEtypes_beacon_period_t *tlv_bcnpd = MNULL;
+	MrvlIEtypes_dtim_period_t *tlv_dtimpd = MNULL;
+
+	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(pmpriv->adapter,
+					       &bss->param.mac_addr, tlv->mac,
+					       MLAN_MAC_ADDR_LENGTH);
+				}
+			} else if (bss->sub_command ==
+				   MLAN_OID_UAP_CFG_WMM_PARAM) {
+				if (TLV_TYPE_AP_WMM_PARAM ==
+				    wlan_le16_to_cpu(tlv_wmm_parameter->header.
+						     type)) {
+					if (wlan_le16_to_cpu
+					    (tlv_wmm_parameter->header.len) <
+					    sizeof(bss->param.ap_wmm_para)) {
+						PRINTM(MCMND,
+						       "FW don't support AP WMM PARAM\n");
+					} else {
+						bss->param.ap_wmm_para.
+							reserved =
+							MLAN_STATUS_COMPLETE;
+						for (ac = 0; ac < 4; ac++) {
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								aci_aifsn.
+								aifsn =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								aci_aifsn.aifsn;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								aci_aifsn.aci =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								aci_aifsn.aci;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								ecw.ecw_max =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								ecw.ecw_max;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								ecw.ecw_min =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac].
+								ecw.ecw_min;
+							bss->param.ap_wmm_para.
+								ac_params[ac].
+								tx_op_limit =
+								wlan_le16_to_cpu
+								(tlv_wmm_parameter->
+								 wmm_para.
+								 ac_params[ac].
+								 tx_op_limit);
+							PRINTM(MCMND,
+							       "ac=%d, aifsn=%d, aci=%d, ecw_max=%d, ecw_min=%d, tx_op=%d\n",
+							       ac,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       aci_aifsn.aifsn,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       aci_aifsn.aci,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       ecw.ecw_max,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       ecw.ecw_min,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac].
+							       tx_op_limit);
+						}
+					}
+				}
+			} else if (bss->sub_command ==
+				   MLAN_OID_UAP_SCAN_CHANNELS) {
+				if (TLV_TYPE_CHANLIST ==
+				    wlan_le16_to_cpu(tlv_chan_list->header.
+						     type)) {
+					pscan_chan =
+						tlv_chan_list->chan_scan_param;
+					bss->param.ap_scan_channels.
+						num_of_chan = 0;
+					for (i = 0;
+					     i <
+					     wlan_le16_to_cpu(tlv_chan_list->
+							      header.len) /
+					     sizeof(ChanScanParamSet_t); i++) {
+						if (bss->param.ap_scan_channels.
+						    remove_nop_channel &&
+						    wlan_11h_is_channel_under_nop
+						    (pmpriv->adapter,
+						     pscan_chan->chan_number)) {
+							bss->param.
+								ap_scan_channels.
+								num_remvoed_channel++;
+							PRINTM(MCMND,
+							       "Remove nop channel=%d\n",
+							       pscan_chan->
+							       chan_number);
+							pscan_chan++;
+							continue;
+						}
+						bss->param.ap_scan_channels.
+							chan_list[bss->param.
+								  ap_scan_channels.
+								  num_of_chan].
+							chan_number =
+							pscan_chan->chan_number;
+						bss->param.ap_scan_channels.
+							chan_list[bss->param.
+								  ap_scan_channels.
+								  num_of_chan].
+							bandcfg =
+							pscan_chan->bandcfg;
+						bss->param.ap_scan_channels.
+							num_of_chan++;
+						pscan_chan++;
+					}
+					PRINTM(MCMND,
+					       "AP scan channel list=%d\n",
+					       bss->param.ap_scan_channels.
+					       num_of_chan);
+				}
+			} else if (bss->sub_command == MLAN_OID_UAP_CHANNEL) {
+				if (TLV_TYPE_UAP_CHAN_BAND_CONFIG ==
+				    wlan_le16_to_cpu(chan_band_tlv->header.
+						     type)) {
+					bss->param.ap_channel.bandcfg =
+						chan_band_tlv->bandcfg;
+					bss->param.ap_channel.channel =
+						chan_band_tlv->channel;
+					bss->param.ap_channel.is_11n_enabled =
+						pmpriv->is_11n_enabled;
+					bss->param.ap_channel.is_dfs_chan =
+						wlan_11h_radar_detect_required
+						(pmpriv,
+						 bss->param.ap_channel.channel);
+					if (chan_band_tlv->bandcfg.chanWidth ==
+					    CHAN_BW_80MHZ)
+						bss->param.ap_channel.
+							center_chan =
+							wlan_get_center_freq_idx
+							(pmpriv, BAND_AAC,
+							 chan_band_tlv->channel,
+							 CHANNEL_BW_80MHZ);
+					PRINTM(MCMND,
+					       "AP channel, band=0x%x, channel=%d, is_11n_enabled=%d center_chan=%d\n",
+					       bss->param.ap_channel.bandcfg.
+					       chanBand,
+					       bss->param.ap_channel.channel,
+					       bss->param.ap_channel.
+					       is_11n_enabled,
+					       bss->param.ap_channel.
+					       center_chan);
+				}
+			} else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG)
+				   && (pioctl_buf->action == MLAN_ACT_GET)) {
+				wlan_uap_ret_cmd_ap_config(pmpriv, resp,
+							   pioctl_buf);
+			}
+		}
+		if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+			misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+			cust_ie =
+				(mlan_ds_misc_custom_ie *)sys_config->
+				tlv_buffer;
+			if ((pioctl_buf->action == MLAN_ACT_GET ||
+			     pioctl_buf->action == MLAN_ACT_SET) &&
+			    (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)) {
+
+				cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+				resp_len = cust_ie->len =
+					wlan_le16_to_cpu(cust_ie->len);
+				travel_len = 0;
+				/* conversion for index, mask, len */
+				if (resp_len == sizeof(t_u16))
+					cust_ie->ie_data_list[0].ie_index =
+						wlan_cpu_to_le16(cust_ie->
+								 ie_data_list
+								 [0].ie_index);
+
+				while (resp_len > sizeof(t_u16)) {
+					cptr = (custom_ie
+						*)(((t_u8 *)cust_ie->
+						    ie_data_list) + travel_len);
+					cptr->ie_index =
+						wlan_le16_to_cpu(cptr->
+								 ie_index);
+					cptr->mgmt_subtype_mask =
+						wlan_le16_to_cpu(cptr->
+								 mgmt_subtype_mask);
+					cptr->ie_length =
+						wlan_le16_to_cpu(cptr->
+								 ie_length);
+					travel_len +=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+					resp_len -=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+				}
+				memcpy(pmpriv->adapter, &misc->param.cust_ie,
+				       cust_ie,
+				       MIN(sizeof(mlan_ds_misc_custom_ie) -
+					   sizeof(tlvbuf_max_mgmt_ie),
+					   (cust_ie->len +
+					    sizeof(MrvlIEtypesHeader_t))));
+				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(pmpriv->adapter,
+						       (t_u8 *)&misc->param.
+						       cust_ie + (cust_ie->len +
+								  sizeof
+								  (MrvlIEtypesHeader_t)),
+						       max_mgmt_ie,
+						       MIN(sizeof
+							   (tlvbuf_max_mgmt_ie),
+							   max_mgmt_ie->len +
+							   sizeof
+							   (MrvlIEtypesHeader_t)));
+					}
+				}
+			}
+		}
+	} else {		/* no ioctl: driver generated get/set */
+		switch (wlan_le16_to_cpu(tlv->header.type)) {
+		case TLV_TYPE_UAP_MAC_ADDRESS:
+			memcpy(pmpriv->adapter, pmpriv->curr_addr, tlv->mac,
+			       MLAN_MAC_ADDR_LENGTH);
+			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,
+		      IN HostCmd_DS_COMMAND *cmd,
+		      IN t_u16 cmd_action,
+		      IN t_u32 cmd_oid,
+		      IN pmlan_ioctl_req pioctl_buf, IN t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = &cmd->params.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 *)&psnmp_mib->oid;
+			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(IN pmlan_private pmpriv, IN 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 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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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(pmadapter, &data, psnmp_oid, 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(IN pmlan_private pmpriv,
+		     IN HostCmd_DS_COMMAND *resp, IN 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;
+		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,
+			IN HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, pcmd_sta_deauth->mac, deauth->mac_addr,
+	       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 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(IN pmlan_private pmpriv,
+			  IN HostCmd_DS_COMMAND *cmd,
+			  IN t_u16 cmd_action,
+			  IN t_u16 cmd_oid, IN 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		       pkey->mac_addr, 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(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+	       pkey->mac_addr, 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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wep.key,
+		       pkey->key_material, pkey->key_len);
+		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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.pn,
+		       pkey->pn, PN_SIZE);
+		pkey_material->key_param_set.key_params.wapi.key_len =
+			wlan_cpu_to_le16(MIN(WAPI_KEY_SIZE, pkey->key_len));
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.wapi.key,
+		       pkey->key_material, MIN(WAPI_KEY_SIZE, pkey->key_len));
+		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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.aes.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.aes.key,
+		       pkey->key_material, pkey->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(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.cmac_aes.
+			       ipn, pkey->pn, SEQ_MAX_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC;
+		pkey_material->key_param_set.key_params.cmac_aes.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.cmac_aes.key,
+		       pkey->key_material, pkey->key_len);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(cmac_aes_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set CMAC AES Key\n");
+		goto done;
+	}
+	if (pkey->key_len == WPA_TKIP_KEY_LEN) {
+		if (pkey->
+		    key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy(pmpriv->adapter,
+			       pkey_material->key_param_set.key_params.tkip.pn,
+			       pkey->pn, SEQ_MAX_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(pmpriv->adapter,
+		       pkey_material->key_param_set.key_params.tkip.key,
+		       pkey->key_material, pkey->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(IN pmlan_private pmpriv,
+		      IN HostCmd_DS_COMMAND *resp,
+		      IN 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;
+
+	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);
+		tlv = (MrvlIEtypes_sta_info_t *)((t_u8 *)sta_list +
+						 sizeof(HostCmd_DS_STA_LIST));
+		info->param.sta_list.sta_count =
+			MIN(info->param.sta_list.sta_count, MAX_NUM_CLIENTS);
+		for (i = 0; i < info->param.sta_list.sta_count; i++) {
+			memcpy(pmpriv->adapter,
+			       info->param.sta_list.info[i].mac_address,
+			       tlv->mac_address, MLAN_MAC_ADDR_LENGTH);
+			info->param.sta_list.info[i].power_mfg_status =
+				tlv->power_mfg_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;
+			else
+				info->param.sta_list.info[i].bandmode = 0xFF;
+			tlv++;
+		}
+	}
+
+	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;
+	priv->wmm_enabled = MFALSE;
+	priv->pkt_fwd = MFALSE;
+	priv->is_11n_enabled = MFALSE;
+
+	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 == 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 == 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(priv->adapter, &wmm_param_ie,
+				       ((t_u8 *)tlv + 2),
+				       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(priv->adapter, (t_u8 *)&pchan_band_info->bandcfg,
+			       (t_u8 *)&pchan_info->bandcfg, 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(priv->adapter, (t_u8 *)tx_pn,
+			       wapi_tlv->multicast_PN, PN_SIZE);
+			for (i = 0; i < 4; i++)
+				tx_pn[i] = mlan_ntohl(tx_pn[i]);
+			memcpy(priv->adapter, wapi_tlv->multicast_PN,
+			       (t_u8 *)tx_pn, PN_SIZE);
+			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(priv->adapter, pevent->event_buf,
+	       pmbuf->pbuf + pmbuf->data_offset + 6, 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(priv->adapter, &frame_control,
+			       (t_u8 *)&(mgmt_tlv->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(priv->adapter,
+				       pevent->event_buf + pevent->event_len,
+				       assoc_req_ie, 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 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,
+		       IN HostCmd_DS_COMMAND *cmd,
+		       IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	HostCmd_DS_UAP_OPER_CTRL *poper_ctl =
+		(HostCmd_DS_UAP_OPER_CTRL *) & cmd->params.uap_oper_ctrl;
+	mlan_ds_bss *bss = (mlan_ds_bss *)pdata_buf;
+	mlan_uap_oper_ctrl *uap_oper_ctrl = &bss->param.ap_oper_ctrl;
+	Band_Config_t *bandcfg = MNULL;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_OPER_CTRL);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_UAP_OPER_CTRL) + S_DS_GEN);
+	poper_ctl->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		poper_ctl->ctrl = wlan_cpu_to_le16(uap_oper_ctrl->ctrl_value);
+		if (uap_oper_ctrl->ctrl_value == 2) {
+			poper_ctl->chan_opt =
+				wlan_cpu_to_le16(uap_oper_ctrl->chan_opt);
+			if (uap_oper_ctrl->chan_opt == 3) {
+				poper_ctl->channel_band.header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+				poper_ctl->channel_band.header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_channel_band_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				bandcfg = &poper_ctl->channel_band.bandcfg;
+				if (uap_oper_ctrl->channel > 14)
+					bandcfg->chanBand = BAND_5GHZ;
+				bandcfg->chanWidth = uap_oper_ctrl->band_cfg;
+				if (bandcfg->chanWidth)
+					bandcfg->chan2Offset =
+						wlan_get_second_channel_offset
+						(uap_oper_ctrl->channel);
+				bandcfg->scanMode = SCAN_MODE_MANUAL;
+				poper_ctl->channel_band.channel =
+					uap_oper_ctrl->channel;
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of uap operation control
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_oper_ctrl(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       IN 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;
+}
+
+/********************************************************
+			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(IN t_void *priv,
+			 IN t_u16 cmd_no,
+			 IN t_u16 cmd_action,
+			 IN t_u32 cmd_oid,
+			 IN t_void *pioctl_buf,
+			 IN t_void *pdata_buf, IN 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_CMD_SOFT_RESET:
+	case HOST_CMD_APCMD_BSS_STOP:
+	case HOST_CMD_APCMD_BSS_START:
+	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);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		if ((HOST_CMD_APCMD_BSS_START == cmd_no) &&
+		    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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		ret = wlan_cmd_sdio_gpio_int(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_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 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;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, pdata_buf);
+		break;
+	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_FW_WAKE_METHOD:
+		ret = wlan_cmd_802_11_fw_wakeup_method(pmpriv, cmd_ptr,
+						       cmd_action,
+						       (t_u16 *)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_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_FTM_CONFIG_SESSION_PARAMS:
+		ret = wlan_cmd_802_11_ftm_config_session_params(pmpriv, cmd_ptr,
+								cmd_action,
+								cmd_oid,
+								pdata_buf);
+		break;
+	case HostCmd_CMD_FTM_CONFIG_RESPONDER:
+		ret = wlan_cmd_802_11_ftm_config_responder(pmpriv, cmd_ptr,
+							   cmd_action, cmd_oid,
+							   pdata_buf);
+		break;
+	case HostCmd_CMD_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);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		cmd_ptr->command =
+			wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) +
+					 S_DS_GEN);
+		pmpriv->tx_rate = 0;
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_cmd_wifi_direct_mode(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+	case HOST_CMD_P2P_PARAMS_CONFIG:
+		ret = wlan_cmd_p2p_params_config(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_RF_ANTENNA:
+		ret = wlan_cmd_802_11_rf_antenna(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_MIMO_SWITCH:
+		ret = wlan_cmd_802_11_mimo_switch(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_cmd_11ac_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_MAC_REG_ACCESS:
+	case HostCmd_CMD_BBP_REG_ACCESS:
+	case HostCmd_CMD_RF_REG_ACCESS:
+	case HostCmd_CMD_CAU_REG_ACCESS:
+	case HostCmd_CMD_802_11_EEPROM_ACCESS:
+		ret = wlan_cmd_reg_access(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;
+	case HostCmd_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_cmd_multi_chan_cfg(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_cmd_multi_chan_policy(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_cmd_drcs_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+#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_HOST_CLOCK_CFG:
+		ret = wlan_cmd_host_clock_cfg(cmd_ptr, cmd_action, pdata_buf);
+		break;
+#ifdef STA_SUPPORT
+	case HostCmd_CMD_ACS:
+		ret = wlan_cmd_acs(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+#endif
+	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_802_11_NET_MONITOR:
+		ret = wlan_cmd_net_monitor(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;
+	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_BOOT_SLEEP:
+		ret = wlan_cmd_boot_sleep(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(IN t_void *priv,
+			     IN t_u16 cmdresp_no,
+			     IN t_void *pcmd_buf, IN 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;
+	int ctr;
+	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
+			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 = MFALSE;
+		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 = MFALSE;
+#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;
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		break;
+	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 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;
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_ret_sdio_rx_aggr_cfg(pmpriv, resp);
+		break;
+	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_FW_WAKE_METHOD:
+		ret = wlan_ret_fw_wakeup_method(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_ROBUSTCOEX:
+		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_802_11_NET_MONITOR:
+		ret = wlan_ret_net_monitor(pmpriv, resp, pioctl_buf);
+		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);
+		pmadapter->tx_buf_size =
+			(pmadapter->tx_buf_size / MLAN_SDIO_BLOCK_SIZE) *
+			MLAN_SDIO_BLOCK_SIZE;
+		pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+		pmadapter->mp_end_port =
+			wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port);
+		pmadapter->mp_data_port_mask = DATA_PORT_MASK;
+
+		for (ctr = 1; ctr <= MAX_PORT - pmadapter->mp_end_port; ctr++) {
+			pmadapter->mp_data_port_mask &=
+				~(1 << (MAX_PORT - ctr));
+		}
+		pmadapter->curr_wr_port = 0;
+		pmadapter->mpa_tx.pkt_aggr_limit =
+			MIN(SDIO_MP_AGGR_DEF_PKT_LIMIT,
+			    (pmadapter->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->mp_data_port_mask);
+		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_FTM_CONFIG_SESSION_PARAMS:
+		ret = wlan_ret_802_11_ftm_config_session_params(pmpriv, resp,
+								pioctl_buf);
+		break;
+	case HostCmd_CMD_FTM_CONFIG_RESPONDER:
+		ret = wlan_ret_802_11_ftm_config_responder(pmpriv, resp,
+							   pioctl_buf);
+		break;
+	case HostCmd_CMD_VERSION_EXT:
+		ret = wlan_ret_ver_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RX_MGMT_IND:
+		ret = wlan_ret_rx_mgmt_ind(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_CFG_TX_DATA_PAUSE:
+		ret = wlan_uap_ret_txdatapause(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_RADIO_CONTROL:
+		ret = wlan_ret_802_11_radio_control(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_RATE_CFG:
+		ret = wlan_ret_tx_rate_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		ret = wlan_ret_802_11_tx_rate_query(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_ret_remain_on_channel(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_ret_wifi_direct_mode(pmpriv, resp, pioctl_buf);
+		break;
+	case HOST_CMD_P2P_PARAMS_CONFIG:
+		ret = wlan_ret_p2p_params_config(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_RF_ANTENNA:
+		ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_MIMO_SWITCH:
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_ret_11ac_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MAC_REG_ACCESS:
+	case HostCmd_CMD_BBP_REG_ACCESS:
+	case HostCmd_CMD_RF_REG_ACCESS:
+	case HostCmd_CMD_CAU_REG_ACCESS:
+	case HostCmd_CMD_802_11_EEPROM_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;
+	case HostCmd_CMD_MULTI_CHAN_CONFIG:
+		ret = wlan_ret_multi_chan_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MULTI_CHAN_POLICY:
+		ret = wlan_ret_multi_chan_policy(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DRCS_CONFIG:
+		ret = wlan_ret_drcs_cfg(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 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_HOST_CLOCK_CFG:
+		ret = wlan_ret_host_clock_cfg(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef STA_SUPPORT
+	case HostCmd_CMD_ACS:
+		ret = wlan_ret_acs(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		ret = wlan_ret_chan_region_cfg(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;
+	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(IN 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;
+	Event_WLS_FTM_t *event_ftm = MNULL;
+
+	ENTER();
+
+	/* 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,
+			       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;
+		memcpy(pmadapter, pmpriv->curr_addr, pmadapter->event_body + 2,
+		       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))
+			AuthenticatorKeyMgmtInit(pmpriv->psapriv,
+						 pmpriv->curr_addr);
+#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->tx_pause = MFALSE;
+		break;
+	case EVENT_PS_AWAKE:
+		PRINTM(MINFO, "EVENT: AWAKE\n");
+		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(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(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		sta_ptr = wlan_add_station_entry(pmpriv, sta_addr);
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + 4, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		memcpy(pmadapter, sta_addr, pmadapter->event_body + 2,
+		       MLAN_MAC_ADDR_LENGTH);
+		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));
+		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(MEVENT, "EVENT: Radar Detected\n");
+
+		/* 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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		pevent->event_id = 0;	/* clear to avoid resending at end of fcn */
+
+		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,
+							MNULL);
+			} else {
+				PRINTM(MEVENT,
+				       "Ignore Event Radar Detected - handling"
+				       " already in progress.\n");
+			}
+		} else {
+
+#ifdef DFS_TESTING_SUPPORT
+			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 {
+#endif
+				pmpriv->intf_state_11h.tx_disabled = MTRUE;
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_FW_RADAR_DETECTED,
+						MNULL);
+
+#ifdef DFS_TESTING_SUPPORT
+			}
+#endif
+		}
+
+		break;
+	case EVENT_CHANNEL_REPORT_RDY:
+		PRINTM(MEVENT, "EVENT: Channel Report Ready\n");
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause),
+		       pevent->event_len);
+		/* Handle / pass event data, and free buffer */
+		ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent);
+
+		if (pmpriv->intf_state_11h.is_11h_host) {
+			*((t_u8 *)pevent->event_buf) =
+				pmpriv->adapter->state_dfs.dfs_radar_found;
+			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(MEVENT, "EVENT: CHANNEL_SWITCH new channel %d\n",
+		       channel);
+		pmpriv->uap_channel = channel;
+
+		if ((pmpriv->adapter->state_rdh.stage != RDH_OFF &&
+		     !pmpriv->intf_state_11h.is_11h_host)
+#ifdef DFS_TESTING_SUPPORT
+		    || pmpriv->adapter->dfs_test_params.
+		    no_channel_change_on_radar ||
+		    pmpriv->adapter->dfs_test_params.fixed_new_channel_on_radar
+#endif
+			) {
+			/* 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(pmadapter, (t_u8 *)&pchan_band_info->bandcfg,
+			       (t_u8 *)&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;
+#ifdef WIFI_DIRECT_SUPPORT
+	case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+		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;
+#endif
+	case EVENT_MULTI_CHAN_INFO:
+		PRINTM(MEVENT, "EVENT: MULTI_CHAN_INFO\n");
+		wlan_handle_event_multi_chan_info(pmpriv, pmbuf);
+		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(pmadapter,
+		       (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause),
+		       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_WLS_FTM_COMPLETE:
+		PRINTM(MEVENT, "EVENT: FTM_GENERIC_EVENT\n");
+		pevent = (pmlan_event)event_buf;
+		pevent->bss_index = pmpriv->bss_index;
+		event_ftm =
+			(Event_WLS_FTM_t *) (pmbuf->pbuf + pmbuf->data_offset);
+		if (event_ftm->sub_event_id == WLS_SUB_EVENT_RTT_RESULTS) {
+			wlan_fill_hal_rtt_results(pmpriv, event_ftm,
+						  pmbuf->data_len, pevent);
+			wlan_recv_event(pmpriv, pevent->event_id, pevent);
+			pevent->event_id = 0;	/* clear to avoid resending at end of fcn */
+			goto done;
+		} else
+			pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		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(pmadapter, (t_u8 *)pevent->event_buf,
+		       pmbuf->pbuf + pmbuf->data_offset, 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 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(IN t_void *priv, IN 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;
+		}
+	}
+
+	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_sd8997/mlan/mlan_uap_ioctl.c b/wlan_sd8997/mlan/mlan_uap_ioctl.c
new file mode 100644
index 0000000..d4a319e
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_uap_ioctl.c
@@ -0,0 +1,2055 @@
+/** @file mlan_uap_ioctl.c
+ *
+ *  @brief This file contains the handling of AP mode ioctls
+ *
+ *  (C) Copyright 2009-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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_sdio.h"
+#include "mlan_11n.h"
+#include "mlan_fw.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+
+/********************************************************
+			Global Variables
+********************************************************/
+extern t_u8 tos_to_tid_inv[];
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief Stop BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_stop(IN pmlan_adapter pmadapter,
+			IN 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 (!priv->adapter->mc_policy &&
+	    (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(IN t_void *priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = (mlan_private *)priv;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+	wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
+	t_u8 old_channel;
+	t_bool under_nop = MFALSE;
+
+	ENTER();
+	/* clear callback now that we're here */
+	puap_state_chan_cb->get_chan_callback = MNULL;
+
+	/*
+	 * Check if the region and channel requires we check for radar.
+	 */
+	if ((puap_state_chan_cb->bandcfg.chanBand == BAND_5GHZ) &&
+	    !wlan_can_radar_det_skip(pmpriv) &&
+	    wlan_11h_radar_detect_required(pmpriv,
+					   puap_state_chan_cb->channel)) {
+		/* If DFS repeater mode is on then before starting the uAP
+		 * make sure that mlan0 is connected to some external AP
+		 * for DFS channel operations.
+		 */
+		if (pmpriv->adapter->dfs_repeater) {
+			pmlan_private tmpriv = MNULL;
+			tmpriv = wlan_get_priv(pmpriv->adapter,
+					       MLAN_BSS_ROLE_STA);
+
+			if (tmpriv && !tmpriv->media_connected) {
+				PRINTM(MERROR,
+				       "BSS start is blocked when DFS-repeater\n"
+				       "mode is on and STA is not connected\n");
+				pcb->moal_ioctl_complete(pmpriv->adapter->
+							 pmoal_handle,
+							 puap_state_chan_cb->
+							 pioctl_req_curr,
+							 MLAN_STATUS_FAILURE);
+				goto done;
+			} else {
+				/* STA is connected.
+				 * Skip DFS check for bss_start since its a repeater
+				 * mode
+				 */
+				goto prep_bss_start;
+			}
+		}
+
+		/* first check if channel is under NOP */
+		if (wlan_11h_is_channel_under_nop(pmpriv->adapter,
+						  puap_state_chan_cb->
+						  channel)) {
+			/* recently we've seen radar on this channel */
+			ret = MLAN_STATUS_FAILURE;
+			under_nop = MTRUE;
+		}
+
+		/* Check cached radar check on the channel */
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = wlan_11h_check_chan_report(pmpriv,
+							 puap_state_chan_cb->
+							 channel);
+
+		/* Found radar: try to switch to a non-dfs channel */
+		if (ret != MLAN_STATUS_SUCCESS) {
+			old_channel = puap_state_chan_cb->channel;
+			ret = wlan_11h_switch_non_dfs_chan(pmpriv,
+							   &puap_state_chan_cb->
+							   channel);
+
+			if (ret == MLAN_STATUS_SUCCESS) {
+
+				wlan_11h_update_bandcfg(&pmpriv->
+							uap_state_chan_cb.
+							bandcfg,
+							puap_state_chan_cb->
+							channel);
+				PRINTM(MCMD_D,
+				       "NOP: uap band config:0x%x  channel=%d\n",
+				       pmpriv->uap_state_chan_cb.bandcfg,
+				       puap_state_chan_cb->channel);
+
+				ret = wlan_uap_set_channel(pmpriv,
+							   pmpriv->
+							   uap_state_chan_cb.
+							   bandcfg,
+							   puap_state_chan_cb->
+							   channel);
+				if (ret == MLAN_STATUS_SUCCESS) {
+					if (under_nop) {
+						PRINTM(MMSG,
+						       "Channel %d under NOP,"
+						       " switched to new channel %d successfully.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					} else {
+						PRINTM(MMSG,
+						       "Radar found on channel %d,"
+						       " switched to new channel %d successfully.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					}
+				} else {
+					if (under_nop) {
+						PRINTM(MMSG,
+						       "Channel %d under NOP,"
+						       " switch to new channel %d failed.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					} else {
+						PRINTM(MMSG,
+						       "Radar found on channel %d,"
+						       " switch to new channel %d failed.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					}
+					pcb->moal_ioctl_complete(pmpriv->
+								 adapter->
+								 pmoal_handle,
+								 puap_state_chan_cb->
+								 pioctl_req_curr,
+								 MLAN_STATUS_FAILURE);
+					goto done;
+				}
+			} else {
+				if (under_nop) {
+					PRINTM(MMSG,
+					       "Channel %d under NOP, no switch channel available.\n",
+					       old_channel);
+				} else {
+					PRINTM(MMSG,
+					       "Radar found on channel %d, no switch channel available.\n",
+					       old_channel);
+				}
+				/* No command sent with the ioctl, need manually signal completion */
+				pcb->moal_ioctl_complete(pmpriv->adapter->
+							 pmoal_handle,
+							 puap_state_chan_cb->
+							 pioctl_req_curr,
+							 MLAN_STATUS_FAILURE);
+				goto done;
+			}
+		} else {
+			PRINTM(MINFO, "No Radar found on channel %d\n",
+			       puap_state_chan_cb->channel);
+		}
+	}
+
+prep_bss_start:
+	/* else okay to send command:  not DFS channel or no radar */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_APCMD_BSS_START,
+			       HostCmd_ACT_GEN_SET,
+			       0,
+			       (t_void *)puap_state_chan_cb->pioctl_req_curr,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+done:
+	puap_state_chan_cb->pioctl_req_curr = MNULL;	/* prevent re-use */
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Start BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+/**
+ *  @sa         wlan_uap_callback_bss_ioctl_start
+ */
+static mlan_status
+wlan_uap_bss_ioctl_start(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			 IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u8 i = 0;
+
+	ENTER();
+
+	/*
+	 * Reset any uap private parameters here
+	 */
+	for (i = 0; i < pmadapter->max_mgmt_ie_index; i++)
+		memset(pmadapter, &pmpriv->mgmt_ie[i], 0, sizeof(custom_ie));
+	pmpriv->add_ba_param.timeout = MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
+	pmpriv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+	pmpriv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE;
+	pmpriv->user_rxwinsize = pmpriv->add_ba_param.rx_win_size;
+
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		pmpriv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i];
+		pmpriv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i];
+		pmpriv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+	}
+	pmpriv->aggr_prio_tbl[6].ampdu_user =
+		pmpriv->aggr_prio_tbl[7].ampdu_user = BA_STREAM_NOT_ALLOWED;
+	pmpriv->addba_reject[6] =
+		pmpriv->addba_reject[7] = ADDBA_RSP_STATUS_REJECT;
+
+	/* hs_configured, hs_activated are reset by main loop */
+	pmadapter->hs_cfg.conditions = HOST_SLEEP_DEF_COND;
+	pmadapter->hs_cfg.gpio = HOST_SLEEP_DEF_GPIO;
+	pmadapter->hs_cfg.gap = HOST_SLEEP_DEF_GAP;
+
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_APCMD_SYS_RESET,
+			       HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 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(IN pmlan_adapter pmadapter,
+			       IN 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(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+		       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(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get scan channels
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_scan_channels(IN pmlan_adapter pmadapter,
+				     IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get UAP channel
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_channel(IN pmlan_adapter pmadapter,
+			       IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get UAP operation control vaule
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_oper_ctrl(IN pmlan_adapter pmadapter,
+				 IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pmadapter->fw_ver == HOST_API_VERSION_V15
+	    && pmadapter->fw_min_ver >= FW_MINOR_VERSION_1) {
+		bss = (mlan_ds_bss *)pioctl_req->pbuf;
+		if (pioctl_req->action == MLAN_ACT_SET)
+			cmd_action = HostCmd_ACT_GEN_SET;
+		else
+			cmd_action = HostCmd_ACT_GEN_GET;
+		/* Send request to firmware */
+		ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_OPER_CTRL,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       (t_void *)pioctl_req->pbuf);
+
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	} else {
+		PRINTM(MMSG, "FW don't support uap oper ctrl\n");
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Uap statistics
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_get_stats(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(IN pmlan_adapter pmadapter,
+			  IN 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(IN pmlan_adapter pmadapter,
+			      IN 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(IN pmlan_adapter pmadapter, IN 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(IN pmlan_adapter pmadapter,
+			       IN 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(IN pmlan_adapter pmadapter,
+				IN 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(IN pmlan_adapter pmadapter,
+		       IN 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(priv->adapter, priv->wapi_ie, misc->param.gen_ie.ie_data,
+		       misc->param.gen_ie.len);
+		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(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;
+	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(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_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 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(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_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(IN pmlan_adapter pmadapter, IN 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(pmadapter, &info->param.bss_info.bssid, pmpriv->curr_addr,
+	       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(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_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 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(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_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(IN 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(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];
+
+	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(IN 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(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_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) {
+#ifdef DFS_TESTING_SUPPORT
+			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;
+			}
+#endif
+			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(IN 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_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);
+		}
+	}
+
+	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;
+
+	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(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_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_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;
+}
+
+/********************************************************
+			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(IN 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(IN pmlan_private pmpriv,
+		     IN Band_Config_t uap_band_cfg, IN 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(IN pmlan_private pmpriv)
+{
+	t_u8 tlv_buffer[sizeof(MrvlIEtypes_beacon_period_t) +
+			sizeof(MrvlIEtypes_dtim_period_t)];
+	MrvlIEtypes_beacon_period_t *ptlv_beacon_pd;
+	MrvlIEtypes_dtim_period_t *ptlv_dtim_pd;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(pmpriv->adapter, &tlv_buffer, 0, sizeof(tlv_buffer));
+	ptlv_beacon_pd = (MrvlIEtypes_beacon_period_t *)tlv_buffer;
+	ptlv_beacon_pd->header.type = TLV_TYPE_UAP_BEACON_PERIOD;
+	ptlv_beacon_pd->header.len = sizeof(MrvlIEtypes_beacon_period_t)
+		- sizeof(MrvlIEtypesHeader_t);
+
+	ptlv_dtim_pd = (MrvlIEtypes_dtim_period_t *)(tlv_buffer
+						     +
+						     sizeof
+						     (MrvlIEtypes_beacon_period_t));
+	ptlv_dtim_pd->header.type = TLV_TYPE_UAP_DTIM_PERIOD;
+	ptlv_dtim_pd->header.len = sizeof(MrvlIEtypes_dtim_period_t)
+		- sizeof(MrvlIEtypesHeader_t);
+
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, tlv_buffer);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get deauth control.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_uap_snmp_mib_ctrl_deauth(IN pmlan_adapter pmadapter,
+			      IN 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_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)
+	mlan_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_OPER_CTRL)
+			status = wlan_uap_bss_ioctl_uap_oper_ctrl(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(pmadapter, &pget_info->param.fw_info.mac_addr,
+			       pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
+			pget_info->param.fw_info.fw_ver =
+				pmadapter->fw_release_number;
+			pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+			pget_info->param.fw_info.ecsa_enable =
+				pmadapter->ecsa_enable;
+			pget_info->param.fw_info.getlog_enable =
+				pmadapter->getlog_enable;
+			pget_info->param.fw_info.hw_dev_mcs_support =
+				pmadapter->hw_dev_mcs_support;
+			pget_info->param.fw_info.hw_dot_11n_dev_cap =
+				pmadapter->hw_dot_11n_dev_cap;
+			pget_info->param.fw_info.usr_dev_mcs_support =
+				pmpriv->usr_dev_mcs_support;
+			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.region_code =
+				pmadapter->region_code;
+			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);
+		if (misc->sub_command == MLAN_OID_MISC_MULTI_CHAN_CFG)
+			status = wlan_misc_ioctl_multi_chan_config(pmadapter,
+								   pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_MULTI_CHAN_POLICY)
+			status = wlan_misc_ioctl_multi_chan_policy(pmadapter,
+								   pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_DRCS_CFG)
+			status = wlan_misc_ioctl_drcs_config(pmadapter,
+							     pioctl_req);
+#ifdef RX_PACKET_COALESCE
+		if (misc->sub_command == MLAN_OID_MISC_RX_PACKET_COALESCE)
+			status = wlan_misc_ioctl_rx_pkt_coalesce_config
+				(pmadapter, pioctl_req);
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		if (misc->sub_command == MLAN_OID_MISC_WIFI_DIRECT_CONFIG)
+			status = wlan_misc_p2p_config(pmadapter, pioctl_req);
+#endif
+
+		if (misc->sub_command == MLAN_OID_MISC_DFS_REAPTER_MODE) {
+			mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+			misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+			misc_cfg->param.dfs_repeater.mode =
+				pmadapter->dfs_repeater;
+			pioctl_req->data_read_written =
+				sizeof(mlan_ds_misc_dfs_repeater);
+
+			status = MLAN_STATUS_SUCCESS;
+		}
+		if (misc->sub_command == MLAN_OID_MISC_IND_RST_CFG)
+			status = wlan_misc_ioctl_ind_rst_cfg(pmadapter,
+							     pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GET_TSF)
+			status = wlan_misc_ioctl_get_tsf(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GET_CHAN_REGION_CFG)
+			status = wlan_misc_chan_reg_cfg(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_OPER_CLASS_CHECK)
+			status = wlan_misc_ioctl_operclass_validation(pmadapter,
+								      pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_OPER_CLASS)
+			status = wlan_misc_ioctl_oper_class(pmadapter,
+							    pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_PER_PKT_CFG)
+			status = wlan_misc_per_pkt_cfg(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_NET_MONITOR)
+			status = wlan_misc_ioctl_net_monitor(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_ROBUSTCOEX)
+			status = wlan_misc_robustcoex(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_CONFIG_RTT)
+			status = wlan_config_rtt(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_CANCEL_RTT)
+			status = wlan_cancel_rtt(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_RTT_RESPONDER_CFG)
+			status = wlan_rtt_responder_cfg(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GET_CORRELATED_TIME)
+			status = wlan_misc_get_correlated_time(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);
+#ifdef STA_SUPPORT
+		if (misc->sub_command == MLAN_OID_MISC_ACS)
+			status = wlan_misc_acs(pmadapter, pioctl_req);
+#endif
+		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);
+		if (pm->sub_command == MLAN_OID_PM_CFG_FW_WAKEUP_METHOD)
+			status = wlan_fw_wakeup_method(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);
+		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 defined(DFS_TESTING_SUPPORT)
+		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);
+#endif
+		if (cfg11h->sub_command == MLAN_OID_11H_CHAN_REPORT_REQUEST)
+			status = wlan_11h_ioctl_dfs_cancel_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);
+		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);
+		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_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;
+		status = MLAN_ERROR_IOCTL_INVALID;
+		break;
+	}
+	LEAVE();
+	return status;
+}
diff --git a/wlan_sd8997/mlan/mlan_uap_txrx.c b/wlan_sd8997/mlan/mlan_uap_txrx.c
new file mode 100644
index 0000000..faf4a51
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_uap_txrx.c
@@ -0,0 +1,770 @@
+/** @file mlan_uap_txrx.c
+ *
+ *  @brief This file contains AP mode transmit and receive functions
+ *
+ *  (C) Copyright 2009-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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_sdio.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
+	UapRxPD *prx_pd;
+	ENTER();
+	prx_pd = (UapRxPD *)(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(UapRxPD), 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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	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(IN t_void *priv, IN pmlan_buffer pmbuf)
+{
+	pmlan_private pmpriv = (pmlan_private)priv;
+	UapTxPD *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(pmpriv->adapter, &pkt_type,
+		       pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type));
+		memcpy(pmpriv->adapter, &tx_control,
+		       pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+		       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(UapTxPD) + pmpriv->intf_hr_len +
+				  DMA_ALIGNMENT)) {
+		PRINTM(MERROR,
+		       "not enough space for UapTxPD: headroom=%d pkt_len=%d, required=%d\n",
+		       pmbuf->data_offset, pmbuf->data_len,
+		       sizeof(UapTxPD) + 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(UapTxPD) -
+		pmpriv->intf_hr_len;
+	head_ptr = (t_u8 *)((t_ptr)head_ptr & ~((t_ptr)(DMA_ALIGNMENT - 1)));
+
+	plocal_tx_pd = (UapTxPD *)(head_ptr + pmpriv->intf_hr_len);
+	memset(pmpriv->adapter, plocal_tx_pd, 0, sizeof(UapTxPD));
+
+	/* 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(pmpriv->adapter, dst_mac,
+			       pmbuf->pbuf + pmbuf->data_offset,
+			       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 |=
+				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;
+		}
+	}
+
+	uap_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(IN t_void *adapter, IN pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	UapRxPD *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_u8 adj_rx_rate = 0;
+	t_u8 antenna = 0;
+	rxpd_extra_info *pextra_info = MNULL;
+
+	ENTER();
+
+	prx_pd = (UapRxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	/* Endian conversion */
+	uap_endian_convert_RxPD(prx_pd);
+	priv->rxpd_rate = prx_pd->rx_rate;
+	if (prx_pd->flags & RXPD_FLAG_EXTRA_HEADER) {
+		pextra_info =
+			(rxpd_extra_info *) ((t_u8 *)prx_pd + sizeof(*prx_pd));
+		endian_convert_RxPD_extra_header(pextra_info);
+	}
+
+	priv->rxpd_rate_info = prx_pd->rate_info;
+
+	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);
+	}
+
+	if (priv->rx_pkt_info) {
+		pmbuf->u.rx_info.data_rate =
+			wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
+						prx_pd->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;
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		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);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		goto done;
+	}
+#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) {
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+			goto done;
+		}
+	}
+#endif
+
+	pmbuf->priority = prx_pd->priority;
+	if (pmadapter->enable_net_mon &&
+	    (prx_pd->rx_pkt_type == PKT_TYPE_802DOT11)) {
+		wlan_process_uap_rx_packet(priv, pmbuf);
+		goto done;
+	}
+	memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+	       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;
+	}
+	/* 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)) {
+		wlan_free_mlan_buffer(pmadapter, 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_uap_recv_packet(IN mlan_private *priv, IN 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(UapTxPD) + 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(pmadapter,
+				       (t_u8 *)newbuf->pbuf +
+				       newbuf->data_offset,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pmbuf->data_len);
+				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(UapTxPD) + 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(pmadapter,
+				       (t_u8 *)newbuf->pbuf +
+				       newbuf->data_offset,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pmbuf->data_len);
+				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(IN mlan_private *priv, IN pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	UapRxPD *prx_pd;
+	RxPacketHdr_t *prx_pkt;
+	pmlan_buffer newbuf = MNULL;
+
+	ENTER();
+
+	prx_pd = (UapRxPD *)(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(UapRxPD), 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));
+
+	if (pmadapter->enable_net_mon) {
+		/* set netmon flag only for a sniffed pkt */
+		if (prx_pd->rx_pkt_type == PKT_TYPE_802DOT11) {
+			pmbuf->flags |= MLAN_BUF_FLAG_NET_MONITOR;
+			goto upload;
+		}
+	}
+
+	/* 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(UapTxPD) + 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(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);
+				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 */
+			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;
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+			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);
+	if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
+		//Use some rxpd space to save rxpd info for radiotap header
+		//We should insure radiotap_info is not bigger than RxPD
+		wlan_rxpdinfo_to_radiotapinfo(priv, (RxPD *)prx_pd,
+					      (radiotap_info *) (pmbuf->pbuf +
+								 pmbuf->
+								 data_offset -
+								 sizeof
+								 (radiotap_info)));
+	}
+
+	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)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+done:
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8997/mlan/mlan_util.h b/wlan_sd8997/mlan/mlan_util.h
new file mode 100644
index 0000000..ddc0174
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_util.h
@@ -0,0 +1,543 @@
+/** @file mlan_util.h
+ *
+ *  @brief This file contains wrappers for linked-list,
+ *  spinlock and timer defines.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/28/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_UTIL_H_
+#define _MLAN_UTIL_H_
+
+/** Circular doubly linked list */
+typedef struct _mlan_linked_list {
+    /** Pointer to previous node */
+	struct _mlan_linked_list *pprev;
+    /** Pointer to next node */
+	struct _mlan_linked_list *pnext;
+} mlan_linked_list, *pmlan_linked_list;
+
+/** List head */
+typedef struct _mlan_list_head {
+    /** Pointer to previous node */
+	struct _mlan_linked_list *pprev;
+    /** Pointer to next node */
+	struct _mlan_linked_list *pnext;
+    /** Pointer to lock */
+	t_void *plock;
+} mlan_list_head, *pmlan_list_head;
+
+/**
+ *  @brief This function initializes a list without locking
+ *
+ *  @param phead		List head
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_init_list(pmlan_linked_list phead)
+{
+	/* Both next and prev point to self */
+	phead->pprev = phead->pnext = (pmlan_linked_list)phead;
+}
+
+/**
+ *  @brief This function initializes a list
+ *
+ *  @param phead		List head
+ *  @param lock_required	A flag for spinlock requirement
+ *  @param moal_init_lock	A pointer to init lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_init_list_head(t_void *pmoal_handle,
+		    pmlan_list_head phead,
+		    t_u8 lock_required,
+		    mlan_status (*moal_init_lock) (t_void *handle,
+						   t_void **pplock))
+{
+	/* Both next and prev point to self */
+	util_init_list((pmlan_linked_list)phead);
+	if (lock_required)
+		moal_init_lock(pmoal_handle, &phead->plock);
+	else
+		phead->plock = 0;
+}
+
+/**
+ *  @brief This function frees a list
+ *
+ *  @param phead		List head
+ *  @param moal_free_lock	A pointer to free lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_free_list_head(t_void *pmoal_handle,
+		    pmlan_list_head phead,
+		    mlan_status (*moal_free_lock) (t_void *handle,
+						   t_void *plock))
+{
+	phead->pprev = phead->pnext = 0;
+	if (phead->plock)
+		moal_free_lock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function peeks into a list
+ *
+ *  @param phead		List head
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			List node
+ */
+static INLINE pmlan_linked_list
+util_peek_list(t_void *pmoal_handle,
+	       pmlan_list_head phead,
+	       mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+	       mlan_status (*moal_spin_unlock) (t_void *handle, t_void *plock))
+{
+	pmlan_linked_list pnode = 0;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	if (phead->pnext != (pmlan_linked_list)phead)
+		pnode = phead->pnext;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+	return pnode;
+}
+
+/**
+ *  @brief This function queues a node at the list tail
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to queue
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_enqueue_list_tail(t_void *pmoal_handle,
+		       pmlan_list_head phead,
+		       pmlan_linked_list pnode,
+		       mlan_status (*moal_spin_lock) (t_void *handle,
+						      t_void *plock),
+		       mlan_status (*moal_spin_unlock) (t_void *handle,
+							t_void *plock))
+{
+	pmlan_linked_list pold_last;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pold_last = phead->pprev;
+	pnode->pprev = pold_last;
+	pnode->pnext = (pmlan_linked_list)phead;
+
+	phead->pprev = pold_last->pnext = pnode;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function adds a node at the list head
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to add
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_enqueue_list_head(t_void *pmoal_handle,
+		       pmlan_list_head phead,
+		       pmlan_linked_list pnode,
+		       mlan_status (*moal_spin_lock) (t_void *handle,
+						      t_void *plock),
+		       mlan_status (*moal_spin_unlock) (t_void *handle,
+							t_void *plock))
+{
+	pmlan_linked_list pold_first;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pold_first = phead->pnext;
+	pnode->pprev = (pmlan_linked_list)phead;
+	pnode->pnext = pold_first;
+
+	phead->pnext = pold_first->pprev = pnode;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function removes a node from the list
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to remove
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_unlink_list(t_void *pmoal_handle,
+		 pmlan_list_head phead,
+		 pmlan_linked_list pnode,
+		 mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		 mlan_status (*moal_spin_unlock) (t_void *handle,
+						  t_void *plock))
+{
+	pmlan_linked_list pmy_prev;
+	pmlan_linked_list pmy_next;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pmy_prev = pnode->pprev;
+	pmy_next = pnode->pnext;
+	pmy_next->pprev = pmy_prev;
+	pmy_prev->pnext = pmy_next;
+
+	pnode->pnext = pnode->pprev = 0;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function dequeues a node from the list
+ *
+ *  @param phead		List head
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			List node
+ */
+static INLINE pmlan_linked_list
+util_dequeue_list(t_void *pmoal_handle,
+		  pmlan_list_head phead,
+		  mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		  mlan_status (*moal_spin_unlock) (t_void *handle,
+						   t_void *plock))
+{
+	pmlan_linked_list pnode;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pnode = phead->pnext;
+	if (pnode && (pnode != (pmlan_linked_list)phead))
+		util_unlink_list(pmoal_handle, phead, pnode, 0, 0);
+	else
+		pnode = 0;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+	return pnode;
+}
+
+/** Access controlled scalar variable */
+typedef struct _mlan_scalar {
+    /** Value */
+	t_s32 value;
+    /** Pointer to lock */
+	t_void *plock;
+    /** Control flags */
+	t_u32 flags;
+} mlan_scalar, *pmlan_scalar;
+
+/** Flag to scalar lock acquired */
+#define MLAN_SCALAR_FLAG_UNIQUE_LOCK	MBIT(16)
+
+/** scalar conditional value list */
+typedef enum _MLAN_SCALAR_CONDITIONAL {
+	MLAN_SCALAR_COND_EQUAL,
+	MLAN_SCALAR_COND_NOT_EQUAL,
+	MLAN_SCALAR_COND_GREATER_THAN,
+	MLAN_SCALAR_COND_GREATER_OR_EQUAL,
+	MLAN_SCALAR_COND_LESS_THAN,
+	MLAN_SCALAR_COND_LESS_OR_EQUAL
+} MLAN_SCALAR_CONDITIONAL;
+
+/**
+ *  @brief This function initializes a scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param val				Initial scalar value
+ *  @param plock_to_use		A new lock is created if NULL, else lock to use
+ *  @param moal_init_lock	A pointer to init lock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_init(t_void *pmoal_handle,
+		 pmlan_scalar pscalar,
+		 t_s32 val,
+		 t_void *plock_to_use,
+		 mlan_status (*moal_init_lock) (t_void *handle,
+						t_void **pplock))
+{
+	pscalar->value = val;
+	pscalar->flags = 0;
+	if (plock_to_use) {
+		pscalar->flags &= ~MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+		pscalar->plock = plock_to_use;
+	} else {
+		pscalar->flags |= MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+		moal_init_lock(pmoal_handle, &pscalar->plock);
+	}
+}
+
+/**
+ *  @brief This function frees a scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_free_lock	A pointer to free lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_scalar_free(t_void *pmoal_handle,
+		 pmlan_scalar pscalar,
+		 mlan_status (*moal_free_lock) (t_void *handle, t_void *plock))
+{
+	if (pscalar->flags & MLAN_SCALAR_FLAG_UNIQUE_LOCK)
+		moal_free_lock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function reads value from scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					Stored value
+ */
+static INLINE t_s32
+util_scalar_read(t_void *pmoal_handle,
+		 pmlan_scalar pscalar,
+		 mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		 mlan_status (*moal_spin_unlock) (t_void *handle,
+						  t_void *plock))
+{
+	t_s32 val;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	val = pscalar->value;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+	return val;
+}
+
+/**
+ *  @brief This function writes value to scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param val				Value to write
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_write(t_void *pmoal_handle,
+		  pmlan_scalar pscalar,
+		  t_s32 val,
+		  mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		  mlan_status (*moal_spin_unlock) (t_void *handle,
+						   t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value = val;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function increments the value in scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_increment(t_void *pmoal_handle,
+		      pmlan_scalar pscalar,
+		      mlan_status (*moal_spin_lock) (t_void *handle,
+						     t_void *plock),
+		      mlan_status (*moal_spin_unlock) (t_void *handle,
+						       t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value++;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function decrements the value in scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_decrement(t_void *pmoal_handle,
+		      pmlan_scalar pscalar,
+		      mlan_status (*moal_spin_lock) (t_void *handle,
+						     t_void *plock),
+		      mlan_status (*moal_spin_unlock) (t_void *handle,
+						       t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value--;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function adds an offset to the value in scalar,
+ *         and returns the new value
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param offset			Offset value (can be negative)
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					Value after offset
+ */
+static INLINE t_s32
+util_scalar_offset(t_void *pmoal_handle,
+		   pmlan_scalar pscalar,
+		   t_s32 offset,
+		   mlan_status (*moal_spin_lock) (t_void *handle,
+						  t_void *plock),
+		   mlan_status (*moal_spin_unlock) (t_void *handle,
+						    t_void *plock))
+{
+	t_s32 newval;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	newval = (pscalar->value += offset);
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+	return newval;
+}
+
+/**
+ *  @brief This function writes the value to the scalar
+ *         if existing value compared with other value is true.
+ *
+ *  @param pscalar          Pointer to scalar
+ *  @param condition        Condition to check
+ *  @param val_compare      Value to compare against current value
+ *                          ((A X B), where B = val_compare)
+ *  @param val_to_set       Value to set if comparison is true
+ *  @param moal_spin_lock   A pointer to spin lock handler
+ *  @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ *  @return                 Comparison result (MTRUE or MFALSE)
+ */
+static INLINE t_u8
+util_scalar_conditional_write(t_void *pmoal_handle,
+			      pmlan_scalar pscalar,
+			      MLAN_SCALAR_CONDITIONAL condition,
+			      t_s32 val_compare,
+			      t_s32 val_to_set,
+			      mlan_status (*moal_spin_lock) (t_void *handle,
+							     t_void *plock),
+			      mlan_status (*moal_spin_unlock) (t_void *handle,
+							       t_void *plock))
+{
+	t_u8 update;
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+
+	switch (condition) {
+	case MLAN_SCALAR_COND_EQUAL:
+		update = (pscalar->value == val_compare);
+		break;
+	case MLAN_SCALAR_COND_NOT_EQUAL:
+		update = (pscalar->value != val_compare);
+		break;
+	case MLAN_SCALAR_COND_GREATER_THAN:
+		update = (pscalar->value > val_compare);
+		break;
+	case MLAN_SCALAR_COND_GREATER_OR_EQUAL:
+		update = (pscalar->value >= val_compare);
+		break;
+	case MLAN_SCALAR_COND_LESS_THAN:
+		update = (pscalar->value < val_compare);
+		break;
+	case MLAN_SCALAR_COND_LESS_OR_EQUAL:
+		update = (pscalar->value <= val_compare);
+		break;
+	default:
+		update = MFALSE;
+		break;
+	}
+	if (update)
+		pscalar->value = val_to_set;
+
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+	return (update) ? MTRUE : MFALSE;
+}
+
+/**
+ *  @brief This function counts the bits of unsigned int number
+ *
+ *  @param num  number
+ *  @return     number of bits
+ */
+static INLINE t_u32
+bitcount(t_u32 num)
+{
+	t_u32 count = 0;
+	static t_u32 nibblebits[] = {
+		0, 1, 1, 2, 1, 2, 2, 3,
+		1, 2, 2, 3, 2, 3, 3, 4
+	};
+	for (; num != 0; num >>= 4)
+		count += nibblebits[num & 0x0f];
+	return count;
+}
+
+#endif /* !_MLAN_UTIL_H_ */
diff --git a/wlan_sd8997/mlan/mlan_wmm.c b/wlan_sd8997/mlan/mlan_wmm.c
new file mode 100644
index 0000000..829cb30
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_wmm.c
@@ -0,0 +1,3758 @@
+/** @file mlan_wmm.c
+ *
+ *  @brief This file contains functions for WMM.
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/********************************************************
+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"
+#include "mlan_sdio.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/** Maximum value FW can accept for driver delay in packet transmission */
+#define DRV_PKT_DELAY_TO_FW_MAX   512
+
+/*
+ * Upper and Lower threshold for packet queuing in the driver
+
+ *    - When the number of packets queued reaches the upper limit,
+ *      the driver will stop the net queue in the app/kernel space.
+
+ *    - When the number of packets drops beneath the lower limit after
+ *      having reached the upper limit, the driver will restart the net
+ *      queue.
+ */
+
+/** Lower threshold for packet queuing in the driver.
+  * When the number of packets drops beneath the lower limit after having
+  * reached the upper limit, the driver will restart the net queue.
+  */
+#define WMM_QUEUED_PACKET_LOWER_LIMIT   180
+
+/** Upper threshold for packet queuing in the driver.
+  * When the number of packets queued reaches the upper limit, the driver
+  * will stop the net queue in the app/kernel space.
+  */
+#define WMM_QUEUED_PACKET_UPPER_LIMIT   200
+
+/** Offset for TOS field in the IP header */
+#define IPTOS_OFFSET 5
+
+/** WMM information IE */
+static const t_u8 wmm_info_ie[] = { WMM_IE, 0x07,
+	0x00, 0x50, 0xf2, 0x02,
+	0x00, 0x01, 0x00
+};
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _wmm_ac_e {
+	AC_BE,
+	AC_BK,
+	AC_VI,
+	AC_VO
+} MLAN_PACK_END wmm_ac_e;
+
+/**
+ * AC Priorities go from AC_BK to AC_VO.  The ACI enumeration for AC_BK (1)
+ *   is higher than the enumeration for AC_BE (0); hence the needed
+ *   mapping conversion for wmm AC to priority Queue Index
+ */
+static const t_u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE,
+	WMM_AC_BK,
+	WMM_AC_VI,
+	WMM_AC_VO
+};
+
+/**
+ * This table will be used to store the tid values based on ACs.
+ * It is initialized to default values per TID.
+ */
+t_u8 tos_to_tid[] = {
+	/* TID        DSCP_P2   DSCP_P1  DSCP_P0   WMM_AC   */
+	0x01,			/*    0         1        0       AC_BK   */
+	0x02,			/*    0         0        0       AC_BK   */
+	0x00,			/*    0         0        1       AC_BE   */
+	0x03,			/*    0         1        1       AC_BE   */
+	0x04,			/*    1         0        0       AC_VI   */
+	0x05,			/*    1         0        1       AC_VI   */
+	0x06,			/*    1         1        0       AC_VO   */
+	0x07			/*    1         1        1       AC_VO   */
+};
+
+/**
+ * This table inverses the tos_to_tid operation to get a priority
+ * which is in sequential order, and can be compared.
+ * Use this to compare the priority of two different TIDs.
+ */
+t_u8 tos_to_tid_inv[] = { 0x02,	/* from tos_to_tid[2] = 0 */
+	0x00,			/* from tos_to_tid[0] = 1 */
+	0x01,			/* from tos_to_tid[1] = 2 */
+	0x03,
+	0x04,
+	0x05,
+	0x06,
+	0x07
+};
+
+/**
+ * This table will provide the tid value for given ac. This table does not
+ * change and will be used to copy back the default values to tos_to_tid in
+ * case of disconnect.
+ */
+const t_u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} };
+
+/* Map of TOS UP values to WMM AC */
+static const mlan_wmm_ac_e tos_to_ac[] = { WMM_AC_BE,
+	WMM_AC_BK,
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VI,
+	WMM_AC_VO,
+	WMM_AC_VO
+};
+
+raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid,
+				    t_u8 *ra_addr);
+
+/********************************************************
+			Local Functions
+********************************************************/
+#ifdef DEBUG_LEVEL2
+/**
+ *  @brief Debug print function to display the priority parameters for a WMM AC
+ *
+ *  @param pac_param	Pointer to the AC parameters to display
+ *
+ *  @return		N/A
+ */
+static void
+wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t *pac_param)
+{
+	const char *ac_str[] = { "BK", "BE", "VI", "VO" };
+
+	ENTER();
+
+	PRINTM(MINFO, "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
+	       "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
+	       ac_str[wmm_aci_to_qidx_map[pac_param->aci_aifsn.aci]],
+	       pac_param->aci_aifsn.aci, pac_param->aci_aifsn.acm,
+	       pac_param->aci_aifsn.aifsn, pac_param->ecw.ecw_min,
+	       pac_param->ecw.ecw_max,
+	       wlan_le16_to_cpu(pac_param->tx_op_limit));
+
+	LEAVE();
+}
+
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param) wlan_wmm_ac_debug_print(pac_param)
+#else
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param)
+#endif
+
+/**
+ *  @brief Allocate route address
+ *
+ *  @param pmadapter       Pointer to the mlan_adapter structure
+ *  @param ra              Pointer to the route address
+ *
+ *  @return         ra_list
+ */
+static
+raListTbl *
+wlan_wmm_allocate_ralist_node(pmlan_adapter pmadapter, t_u8 *ra)
+{
+	raListTbl *ra_list = MNULL;
+
+	ENTER();
+
+	if (pmadapter->callbacks.
+	    moal_malloc(pmadapter->pmoal_handle, sizeof(raListTbl),
+			MLAN_MEM_DEF, (t_u8 **)&ra_list)) {
+		PRINTM(MERROR, "Fail to allocate ra_list\n");
+		goto done;
+	}
+	util_init_list((pmlan_linked_list)ra_list);
+	util_init_list_head((t_void *)pmadapter->pmoal_handle,
+			    &ra_list->buf_head, MFALSE,
+			    pmadapter->callbacks.moal_init_lock);
+
+	memcpy(pmadapter, ra_list->ra, ra, 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;
+#if defined(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;
+	}
+#if defined(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(MDATA, "Drop packets to unknown station\n");
+			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(priv->adapter, pout_buf, (t_u8 *)"TSPEC:", 6);
+	pout_buf += 6;
+
+	memcpy(priv->adapter, pout_buf, (t_u8 *)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(priv->adapter, pout_buf, (t_u8 *)"]:TID", 5);
+	pout_buf += 5;
+	*pout_buf++ = tid + '0';
+
+	memcpy(priv->adapter, pout_buf, (t_u8 *)":UP", 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 = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf,
+					     &tx_param);
+		switch (ret) {
+		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:
+			pmadapter->data_sent = MFALSE;
+			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;
+
+	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->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           N/A
+ */
+t_void
+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();
+}
+
+#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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       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);
+			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
+#define BA_SETUP_PACKET_OFFSET          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) +
+		BA_SETUP_PACKET_OFFSET;
+	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);
+	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(pmadapter, tos_to_tid, ac_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;
+#if defined(UAP_SUPPORT)
+	priv->num_drop_pkts = 0;
+#endif
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	memset(pmadapter, pmadapter->mpa_tx_count, 0,
+	       sizeof(pmadapter->mpa_tx_count));
+	pmadapter->mpa_sent_no_ports = 0;
+	pmadapter->mpa_sent_last_pkt = 0;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	memset(pmadapter, pmadapter->mpa_rx_count, 0,
+	       sizeof(pmadapter->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 =
+					BA_STREAM_NOT_ALLOWED;
+				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
+			if (priv->bss_type == MLAN_BSS_TYPE_NAN) {
+				priv->add_ba_param.tx_win_size =
+					MLAN_NAN_AMPDU_DEF_TXRXWINSIZE;
+				priv->add_ba_param.rx_win_size =
+					MLAN_NAN_AMPDU_DEF_TXRXWINSIZE;
+			}
+#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 = MFALSE;
+			priv->add_ba_param.rx_amsdu = MFALSE;
+			memset(priv->adapter, priv->rx_seq, 0xff,
+			       sizeof(priv->rx_seq));
+			wlan_wmm_default_queue_priorities(priv);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Setup the queue priorities and downgrade any queues as required
+ *         by the WMM info.  Setups default values if WMM is not active
+ *         for this association.
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         N/A
+ */
+void
+wlan_wmm_setup_queues(pmlan_private priv)
+{
+	ENTER();
+	wlan_wmm_setup_queue_priorities(priv, MNULL);
+	wlan_wmm_setup_ac_downgrade(priv);
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief  Send a command to firmware to retrieve the current WMM status
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         MLAN_STATUS_SUCCESS; MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_wmm_status_change(pmlan_private priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, 0, 0, 0,
+			       MNULL);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Check if wmm TX queue is empty
+ *
+ *  @param pmadapter  Pointer to the mlan_adapter driver data struct
+ *
+ *  @return         MFALSE if not empty; MTRUE if empty
+ */
+int
+wlan_wmm_lists_empty(pmlan_adapter pmadapter)
+{
+	int j;
+	pmlan_private priv;
+
+	ENTER();
+
+	for (j = 0; j < pmadapter->priv_num; ++j) {
+		priv = pmadapter->priv[j];
+		if (priv) {
+			if ((priv->port_ctrl_mode == MTRUE) &&
+			    (priv->port_open == MFALSE)) {
+				PRINTM(MINFO,
+				       "wmm_lists_empty: PORT_CLOSED Ignore pkts from BSS%d\n",
+				       j);
+				continue;
+			}
+			if (priv->tx_pause)
+				continue;
+
+			if (util_scalar_read(pmadapter->pmoal_handle,
+					     &priv->wmm.tx_pkts_queued,
+					     pmadapter->callbacks.
+					     moal_spin_lock,
+					     pmadapter->callbacks.
+					     moal_spin_unlock)) {
+				LEAVE();
+				return MFALSE;
+			}
+		}
+	}
+
+	LEAVE();
+	return MTRUE;
+}
+
+/**
+ *   @brief Get ralist node
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param tid      TID
+ *   @param ra_addr  Pointer to the route address
+ *
+ *   @return         ra_list or MNULL
+ */
+raListTbl *
+wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 *ra_addr)
+{
+	raListTbl *ra_list;
+	ENTER();
+	ra_list =
+		(raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					    &priv->wmm.tid_tbl_ptr[tid].ra_list,
+					    MNULL, MNULL);
+	while (ra_list && (ra_list != (raListTbl *)
+			   &priv->wmm.tid_tbl_ptr[tid].ra_list)) {
+		if (!memcmp
+		    (priv->adapter, ra_list->ra, ra_addr,
+		     MLAN_MAC_ADDR_LENGTH)) {
+			LEAVE();
+			return ra_list;
+		}
+		ra_list = ra_list->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *   @brief Check if RA list is valid or not
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param ra_list  Pointer to raListTbl
+ *   @param ptrindex TID pointer index
+ *
+ *   @return         MTRUE- valid. MFALSE- invalid.
+ */
+int
+wlan_is_ralist_valid(mlan_private *priv, raListTbl *ra_list, int ptrindex)
+{
+	raListTbl *rlist;
+
+	ENTER();
+
+	rlist = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					    &priv->wmm.tid_tbl_ptr[ptrindex].
+					    ra_list, MNULL, MNULL);
+
+	while (rlist && (rlist != (raListTbl *)
+			 &priv->wmm.tid_tbl_ptr[ptrindex].ra_list)) {
+		if (rlist == ra_list) {
+			LEAVE();
+			return MTRUE;
+		}
+
+		rlist = rlist->pnext;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief  Update an existing raList with a new RA and 11n capability
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *  @param old_ra   Old receiver address
+ *  @param new_ra   New receiver address
+ *
+ *  @return         integer count of updated nodes
+ */
+int
+wlan_ralist_update(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra)
+{
+	t_u8 tid;
+	int update_count;
+	raListTbl *ra_list;
+
+	ENTER();
+
+	update_count = 0;
+
+	for (tid = 0; tid < MAX_NUM_TID; ++tid) {
+
+		ra_list = wlan_wmm_get_ralist_node(priv, tid, old_ra);
+
+		if (ra_list) {
+			update_count++;
+
+			if (queuing_ra_based(priv))
+				ra_list->is_11n_enabled =
+					wlan_is_11n_enabled(priv, new_ra);
+			else
+				ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+			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(priv->adapter, ra_list->ra, new_ra,
+			       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;
+#if defined(UAP_SUPPORT)
+	sta_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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       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(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+		       MLAN_MAC_ADDR_LENGTH);
+	/** put multicast/broadcast packet in the same ralist */
+		if (ra[0] & 0x01)
+			memset(pmadapter, ra, 0xff, sizeof(ra));
+#if defined(UAP_SUPPORT)
+		else if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			sta_ptr = wlan_get_station_entry(priv, ra);
+			if (sta_ptr) {
+				if (!sta_ptr->is_wmm_enabled
+				    && !priv->is_11ac_enabled) {
+					tid_down =
+						wlan_wmm_downgrade_tid(priv,
+								       0xff);
+				}
+			}
+		}
+#endif
+		ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, ra);
+	}
+
+	if (!ra_list) {
+		PRINTM_NETINTF(MWARN, priv);
+		PRINTM(MWARN,
+		       "Drop packet %p, ra_list=%p, media_connected=%d\n",
+		       pmbuf, ra_list, priv->media_connected);
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+		LEAVE();
+		return;
+	}
+
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA,
+	       "Adding pkt %p (priority=%d, tid_down=%d) to ra_list %p\n",
+	       pmbuf, pmbuf->priority, tid_down, ra_list);
+	util_enqueue_list_tail(pmadapter->pmoal_handle, &ra_list->buf_head,
+			       (pmlan_linked_list)pmbuf, MNULL, MNULL);
+
+	ra_list->total_pkts++;
+	ra_list->packet_count++;
+
+	priv->wmm.pkts_queued[tid_down]++;
+	if (ra_list->tx_pause) {
+		priv->wmm.pkts_paused[tid_down]++;
+	} else {
+		util_scalar_increment(pmadapter->pmoal_handle,
+				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+		/* if highest_queued_prio < prio(tid_down), set it to prio(tid_down) */
+		util_scalar_conditional_write(pmadapter->pmoal_handle,
+					      &priv->wmm.highest_queued_prio,
+					      MLAN_SCALAR_COND_LESS_THAN,
+					      tos_to_tid_inv[tid_down],
+					      tos_to_tid_inv[tid_down],
+					      MNULL, MNULL);
+	}
+	/* Record the current time the packet was queued; used to determine
+	 *   the amount of time the packet was queued in the driver before it
+	 *   was sent to the firmware.  The delay is then sent along with the
+	 *   packet to the firmware for aggregate delay calculation for stats
+	 *   and MSDU lifetime expiry.
+	 */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmbuf->in_ts_sec,
+						  &pmbuf->in_ts_usec);
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Process the GET_WMM_STATUS command response from firmware
+ *
+ *  The GET_WMM_STATUS response may contain multiple TLVs for:
+ *      - AC Queue status TLVs
+ *      - Current WMM Parameter IE TLV
+ *      - Admission Control action frame TLVs
+ *
+ *  This function parses the TLVs and then calls further functions
+ *   to process any changes in the queue prioritize or state.
+ *
+ *  @param priv      Pointer to the mlan_private driver data struct
+ *  @param ptlv      Pointer to the tlv block returned in the response.
+ *  @param resp_len  Length of TLV block
+ *
+ *  @return MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_get_status(pmlan_private priv, t_u8 *ptlv, int resp_len)
+{
+	t_u8 *pcurrent = ptlv;
+	t_u32 tlv_len;
+	t_u8 send_wmm_event;
+	MrvlIEtypes_Data_t *ptlv_hdr;
+	MrvlIEtypes_WmmQueueStatus_t *ptlv_wmm_q_status;
+	IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
+	WmmAcStatus_t *pac_status;
+
+	MrvlIETypes_ActionFrame_t *ptlv_action;
+	IEEEtypes_Action_WMM_AddTsRsp_t *padd_ts_rsp;
+	IEEEtypes_Action_WMM_DelTs_t *pdel_ts;
+
+	ENTER();
+
+	send_wmm_event = MFALSE;
+
+	PRINTM(MINFO, "WMM: WMM_GET_STATUS cmdresp received: %d\n", resp_len);
+	HEXDUMP("CMD_RESP: WMM_GET_STATUS", pcurrent, resp_len);
+
+	while (resp_len >= sizeof(ptlv_hdr->header)) {
+		ptlv_hdr = (MrvlIEtypes_Data_t *)pcurrent;
+		tlv_len = wlan_le16_to_cpu(ptlv_hdr->header.len);
+		if ((tlv_len + sizeof(ptlv_hdr->header)) > resp_len) {
+			PRINTM(MERROR,
+			       "WMM get status: Error in processing  TLV buffer\n");
+			resp_len = 0;
+			continue;
+		}
+
+		switch (wlan_le16_to_cpu(ptlv_hdr->header.type)) {
+		case TLV_TYPE_WMMQSTATUS:
+			ptlv_wmm_q_status =
+				(MrvlIEtypes_WmmQueueStatus_t *)ptlv_hdr;
+			PRINTM(MEVENT, "WMM_STATUS: QSTATUS TLV: %d\n",
+			       ptlv_wmm_q_status->queue_index);
+
+			PRINTM(MINFO,
+			       "CMD_RESP: WMM_GET_STATUS: QSTATUS TLV: %d, %d, %d\n",
+			       ptlv_wmm_q_status->queue_index,
+			       ptlv_wmm_q_status->flow_required,
+			       ptlv_wmm_q_status->disabled);
+
+			pac_status =
+				&priv->wmm.ac_status[ptlv_wmm_q_status->
+						     queue_index];
+			pac_status->disabled = ptlv_wmm_q_status->disabled;
+			pac_status->flow_required =
+				ptlv_wmm_q_status->flow_required;
+			pac_status->flow_created =
+				ptlv_wmm_q_status->flow_created;
+			break;
+
+		case TLV_TYPE_VENDOR_SPECIFIC_IE:	/* WMM_IE */
+			/*
+			 * Point the regular IEEE IE 2 bytes into the Marvell 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(priv->adapter,
+			       (t_u8 *)&priv->curr_bss_params.bss_descriptor.
+			       wmm_ie, pwmm_param_ie,
+			       MIN(sizeof(IEEEtypes_WmmParameter_t),
+				   (pwmm_param_ie->vend_hdr.len + 2)));
+			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 Marvell 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(priv->adapter, pwmm_tlv->wmm_ie, &wmm_info_ie[2],
+		       pwmm_tlv->header.len);
+		if (pwmm_ie->qos_info.qos_uapsd)
+			memcpy(priv->adapter,
+			       (t_u8 *)(pwmm_tlv->wmm_ie +
+					pwmm_tlv->header.len -
+					sizeof(priv->wmm_qosinfo)),
+			       &priv->wmm_qosinfo, sizeof(priv->wmm_qosinfo));
+
+		ret_len = sizeof(pwmm_tlv->header) + pwmm_tlv->header.len;
+		pwmm_tlv->header.len = wlan_cpu_to_le16(pwmm_tlv->header.len);
+
+		HEXDUMP("ASSOC_CMD: WMM IE", (t_u8 *)pwmm_tlv, ret_len);
+		*ppassoc_buf += ret_len;
+	}
+
+	LEAVE();
+	return ret_len;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *   @brief Compute the time delay in the driver queues for a given packet.
+ *
+ *   When the packet is received at the OS/Driver interface, the current
+ *     time is set in the packet structure.  The difference between the present
+ *     time and that received time is computed in this function and limited
+ *     based on pre-compiled limits in the driver.
+ *
+ *   @param priv   Ptr to the mlan_private driver data struct
+ *   @param pmbuf  Ptr to the mlan_buffer which has been previously timestamped
+ *
+ *   @return  Time delay of the packet in 2ms units after having limit applied
+ */
+t_u8
+wlan_wmm_compute_driver_packet_delay(pmlan_private priv,
+				     const pmlan_buffer pmbuf)
+{
+	t_u8 ret_val = 0;
+	t_u32 out_ts_sec, out_ts_usec;
+	t_s32 queue_delay;
+
+	ENTER();
+
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &out_ts_sec,
+						      &out_ts_usec);
+
+	queue_delay = (t_s32)(out_ts_sec - pmbuf->in_ts_sec) * 1000;
+	queue_delay += (t_s32)(out_ts_usec - pmbuf->in_ts_usec) / 1000;
+
+	/*
+	 * Queue delay is passed as a uint8 in units of 2ms (ms shifted
+	 *  by 1). Min value (other than 0) is therefore 2ms, max is 510ms.
+	 *
+	 * Pass max value if queue_delay is beyond the uint8 range
+	 */
+	ret_val = (t_u8)(MIN(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1);
+
+	PRINTM(MINFO, "WMM: Pkt Delay: %d ms, %d ms sent to FW\n",
+	       queue_delay, ret_val);
+
+	LEAVE();
+	return ret_val;
+}
+
+/**
+ *  @brief Transmit the highest priority packet awaiting in the WMM Queues
+ *
+ *  @param pmadapter Pointer to the mlan_adapter driver data struct
+ *
+ *  @return        N/A
+ */
+void
+wlan_wmm_process_tx(pmlan_adapter pmadapter)
+{
+	ENTER();
+
+	do {
+		if (wlan_dequeue_tx_packet(pmadapter))
+			break;
+		if (pmadapter->sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) {
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+			wlan_send_mp_aggr_buf(pmadapter);
+#endif
+			break;
+		}
+
+		/* 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(IN pmlan_private pmpriv,
+		       OUT HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter,
+	       pcmd_addts->tspec_data,
+	       paddts->ie_data, MIN(WMM_TSPEC_SIZE, paddts->ie_data_len));
+
+	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(IN pmlan_private pmpriv,
+		       const IN HostCmd_DS_COMMAND *resp,
+		       OUT 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(pmpriv->adapter,
+			       paddts->ie_data,
+			       presp_addts->tspec_data, paddts->ie_data_len);
+		} 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(IN pmlan_private pmpriv,
+		       OUT HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter,
+	       pcmd_delts->tspec_data,
+	       pdelts->ie_data, MIN(WMM_TSPEC_SIZE, pdelts->ie_data_len));
+
+	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(IN pmlan_private pmpriv,
+		       const IN HostCmd_DS_COMMAND *resp,
+		       OUT 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(IN pmlan_private pmpriv,
+			 OUT HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			 const IN HostCmd_DS_COMMAND *resp,
+			 OUT 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(IN pmlan_private pmpriv,
+		       OUT HostCmd_DS_COMMAND *cmd, IN 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(pmpriv->adapter, (t_void *)pcmd_ts_status, (t_void *)pts_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(IN pmlan_private pmpriv,
+		       IN HostCmd_DS_COMMAND *resp,
+		       OUT 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(pmpriv->adapter,
+		       (t_void *)&pwmm->param.ts_status,
+		       (t_void *)presp_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(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_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(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_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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_adapter pmadapter,
+			   IN 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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter,
+			 IN 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(IN pmlan_private pmpriv,
+			  OUT HostCmd_DS_COMMAND *cmd,
+			  IN t_u8 cmd_action, IN 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(pmpriv->adapter, pcmd_cfg->ac_params, ac_params,
+		       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(IN pmlan_private pmpriv,
+			  const IN HostCmd_DS_COMMAND *resp,
+			  OUT 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(pmpriv->adapter, pwmm->param.ac_params, pcfg->ac_params,
+		       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(IN pmlan_private pmpriv,
+			  OUT HostCmd_DS_COMMAND *cmd, IN 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(IN pmlan_private pmpriv,
+			  const IN HostCmd_DS_COMMAND *resp,
+			  OUT 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(IN pmlan_adapter pmadapter,
+			    IN 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(IN pmlan_adapter pmadapter, IN 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(priv->adapter, plist->ra, ra_list->ra,
+				       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_sd8997/mlan/mlan_wmm.h b/wlan_sd8997/mlan/mlan_wmm.h
new file mode 100644
index 0000000..6b3694f
--- /dev/null
+++ b/wlan_sd8997/mlan/mlan_wmm.h
@@ -0,0 +1,247 @@
+/** @file mlan_wmm.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of wmm functionalities
+ *
+ *  (C) Copyright 2008-2018 Marvell International Ltd. All Rights Reserved
+ *
+ *  MARVELL CONFIDENTIAL
+ *  The source code contained or described herein and all documents related to
+ *  the source code ("Material") are owned by Marvell International Ltd or its
+ *  suppliers or licensors. Title to the Material remains with Marvell
+ *  International Ltd or its suppliers and licensors. The Material contains
+ *  trade secrets and proprietary and confidential information of Marvell or its
+ *  suppliers and licensors. The Material is protected by worldwide copyright
+ *  and trade secret laws and treaty provisions. No part of the Material may be
+ *  used, copied, reproduced, modified, published, uploaded, posted,
+ *  transmitted, distributed, or disclosed in any way without Marvell's prior
+ *  express written permission.
+ *
+ *  No license under any patent, copyright, trade secret or other intellectual
+ *  property right is granted to or conferred upon you by disclosure or delivery
+ *  of the Materials, either expressly, by implication, inducement, estoppel or
+ *  otherwise. Any license under such intellectual property rights must be
+ *  express and approved by Marvell in writing.
+ *
+ */
+
+/****************************************************
+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, raListTbl *ptr)
+{
+	pmlan_buffer mbuf;
+
+	ENTER();
+	mbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+					    &ptr->buf_head, MNULL, MNULL);
+	LEAVE();
+
+	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(IN mlan_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(IN mlan_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(IN pmlan_private pmpriv,
+				      OUT HostCmd_DS_COMMAND *cmd,
+				      IN t_u8 cmd_action, IN t_void *pdata_buf);
+
+/* process wmm_param_config command response */
+mlan_status wlan_ret_wmm_param_config(IN pmlan_private pmpriv,
+				      const IN HostCmd_DS_COMMAND *resp,
+				      OUT 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(IN pmlan_private pmpriv,
+					  OUT HostCmd_DS_COMMAND *cmd,
+					  IN t_void *pdata_buf);
+/** WMM DELTS request command handler */
+extern mlan_status wlan_cmd_wmm_delts_req(IN pmlan_private pmpriv,
+					  OUT HostCmd_DS_COMMAND *cmd,
+					  IN t_void *pdata_buf);
+/** WMM QUEUE_STATS command handler */
+extern mlan_status wlan_cmd_wmm_queue_stats(IN pmlan_private pmpriv,
+					    OUT HostCmd_DS_COMMAND *cmd,
+					    IN t_void *pdata_buf);
+/** WMM TS_STATUS command handler */
+extern mlan_status wlan_cmd_wmm_ts_status(IN pmlan_private pmpriv,
+					  OUT HostCmd_DS_COMMAND *cmd,
+					  IN 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(IN pmlan_private priv,
+					   IN t_u8 *ptlv, IN int resp_len);
+/** WMM ADDTS request command response handler */
+extern mlan_status wlan_ret_wmm_addts_req(IN pmlan_private pmpriv,
+					  const IN HostCmd_DS_COMMAND *resp,
+					  OUT mlan_ioctl_req *pioctl_buf);
+/** WMM DELTS request command response handler */
+extern mlan_status wlan_ret_wmm_delts_req(IN pmlan_private pmpriv,
+					  const IN HostCmd_DS_COMMAND *resp,
+					  OUT mlan_ioctl_req *pioctl_buf);
+/** WMM QUEUE_STATS command response handler */
+extern mlan_status wlan_ret_wmm_queue_stats(IN pmlan_private pmpriv,
+					    const IN HostCmd_DS_COMMAND *resp,
+					    OUT mlan_ioctl_req *pioctl_buf);
+/** WMM TS_STATUS command response handler */
+extern mlan_status wlan_ret_wmm_ts_status(IN pmlan_private pmpriv,
+					  IN HostCmd_DS_COMMAND *resp,
+					  OUT mlan_ioctl_req *pioctl_buf);
+#endif /* STA_SUPPORT */
+
+/** WMM QUEUE_CONFIG command handler */
+extern mlan_status wlan_cmd_wmm_queue_config(IN pmlan_private pmpriv,
+					     OUT HostCmd_DS_COMMAND *cmd,
+					     IN t_void *pdata_buf);
+
+/** WMM QUEUE_CONFIG command response handler */
+extern mlan_status wlan_ret_wmm_queue_config(IN pmlan_private pmpriv,
+					     const IN HostCmd_DS_COMMAND *resp,
+					     OUT mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_wmm_cfg_ioctl(IN pmlan_adapter pmadapter,
+			       IN pmlan_ioctl_req pioctl_req);
+#endif /* !_MLAN_WMM_H_ */
diff --git a/wlan_sd8997/mlinux/mlan.h b/wlan_sd8997/mlinux/mlan.h
new file mode 100644
index 0000000..2afcb54
--- /dev/null
+++ b/wlan_sd8997/mlinux/mlan.h
@@ -0,0 +1,35 @@
+/** @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 (C) 2008-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+/******************************************************
+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_sd8997/mlinux/mlan_decl.h b/wlan_sd8997/mlinux/mlan_decl.h
new file mode 100644
index 0000000..f7684a6
--- /dev/null
+++ b/wlan_sd8997/mlinux/mlan_decl.h
@@ -0,0 +1,2060 @@
+/** @file mlan_decl.h
+ *
+ *  @brief This file declares the generic data structures and APIs.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+Change log:
+    11/07/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_DECL_H_
+#define _MLAN_DECL_H_
+
+/** MLAN release version */
+#define MLAN_RELEASE_VERSION		 "C536"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef signed char t_s8;
+/** Unsigned char (1-byte) */
+typedef unsigned char t_u8;
+/** Signed short (2-bytes) */
+typedef short t_s16;
+/** Unsigned short (2-bytes) */
+typedef unsigned short t_u16;
+/** Signed long (4-bytes) */
+typedef int t_s32;
+/** Unsigned long (4-bytes) */
+typedef unsigned int t_u32;
+/** Signed long long 8-bytes) */
+typedef long long t_s64;
+/** Unsigned long long 8-bytes) */
+typedef unsigned long long t_u64;
+/** Void pointer (4-bytes) */
+typedef void t_void;
+/** 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)
+
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM         (16)
+
+/** NET IP alignment */
+#define MLAN_NET_IP_ALIGN        2
+
+/** DMA alignment */
+/* SDIO3.0 Inrevium Adapter require 32 bit DMA alignment */
+#define DMA_ALIGNMENT            32
+
+/** max size of TxPD */
+#define MAX_TXPD_SIZE            32
+
+/** Minimum data header length */
+#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT+MAX_TXPD_SIZE)
+
+/** rx data header length */
+#define MLAN_RX_HEADER_LEN       MLAN_MIN_DATA_HEADER_LEN
+
+/** This is current limit on Maximum Tx AMPDU allowed */
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED          16
+#define MLAN_MAX_TX_BASTREAM_DEFAULT            2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED     16
+
+#ifdef STA_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_STA_AMPDU_DEF_TXWINSIZE       64
+/** Default Win size attached during ADDBA response */
+#define MLAN_STA_AMPDU_DEF_RXWINSIZE       64
+/** RX winsize for COEX */
+#define MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE  16
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_UAP_AMPDU_DEF_TXWINSIZE       48
+/** Default Win size attached during ADDBA response */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE       32
+/** 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
+
+/** NAN use the same window size for tx/rx */
+#define MLAN_NAN_AMPDU_DEF_TXRXWINSIZE     16
+/** RX winsize for COEX */
+#define MLAN_NAN_COEX_AMPDU_DEF_RXWINSIZE  16
+
+/** 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 7 */
+#define MLAN_RATE_INDEX_MCS7    7
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9    9
+/** 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 */
+#define MLAN_RX_DATA_BUF_SIZE     (4 * 1024)
+/** Size of rx command buffer */
+#define MLAN_RX_CMD_BUF_SIZE      (2 * 1024)
+
+#define MLAN_USB_RX_DATA_BUF_SIZE       MLAN_RX_DATA_BUF_SIZE
+
+/** 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
+
+/** 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           (4 * 1024)
+/** SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT       (16)
+
+/** SDIO IO Port mask */
+#define MLAN_SDIO_IO_PORT_MASK		0xfffff
+/** SDIO Block/Byte mode mask */
+#define MLAN_SDIO_BYTE_MODE_MASK	0x80000000
+
+/** Max retry number of IO write */
+#define MAX_WRITE_IOMEM_RETRY		2
+
+/** 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)
+
+/** 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 NET_MONITOR */
+#define MLAN_BUF_FLAG_NET_MONITOR        MBIT(11)
+
+/** Buffer flag for NULL data packet */
+#define MLAN_BUF_FLAG_NULL_PKT        MBIT(12)
+
+#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 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,
+	MLAN_STATUS_COMPLETE,
+} 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,
+	MLAN_BUF_TYPE_SPA_DATA,
+} mlan_buf_type;
+
+/** 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_NAN = 4,
+	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 bit mask */
+#define BSS_ROLE_BIT_MASK    MBIT(0)
+
+/** Get BSS role */
+#define GET_BSS_ROLE(priv)   ((priv)->bss_role & BSS_ROLE_BIT_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_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,
+	/* 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_FW_ROAM_OFFLOAD_RESULT = 0x80000023,
+	MLAN_EVENT_ID_NAN_STARTED = 0x80000024,
+	MLAN_EVENT_ID_DRV_RTT_RESULT = 0x80000025,
+	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;
+
+/** Data Structures */
+/** mlan_image data structure */
+typedef struct _mlan_fw_image {
+    /** Helper image buffer pointer */
+	t_u8 *phelper_buf;
+    /** Helper image length */
+	t_u32 helper_len;
+    /** 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;
+
+#define OID_TYPE_CAL    0x2
+#define OID_TYPE_DPD    0xa
+
+/** 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 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,
+};
+
+/** 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;
+
+/** 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[0];
+} mlan_event, *pmlan_event;
+
+/** 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;
+
+/** mix rate information structure */
+typedef MLAN_PACK_START struct _mix_rate_info {
+    /**  bit0: LGI: gi=0, SGI: gi= 1 */
+    /**  bit1-2: 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3  */
+    /**  bit3-4: LG: format=0, HT: format=1, VHT: format=2 */
+    /**  bit5: LDPC: 0-not support,  1-support */
+    /**  bit6-7:reserved */
+	t_u8 rate_info;
+    /** MCS index */
+	t_u8 mcs_index;
+    /** bitrate, in 500Kbps */
+	t_u16 bitrate;
+} MLAN_PACK_END mix_rate_info, *pmix_rate_info;
+
+/** rxpd extra information structure */
+typedef MLAN_PACK_START struct _rxpd_extra_info {
+    /** flags */
+	t_u8 flags;
+    /** channel.flags */
+	t_u16 channel_flags;
+    /** mcs.known */
+	t_u8 mcs_known;
+    /** mcs.flags */
+	t_u8 mcs_flags;
+    /** vht sig1 */
+	t_u32 vht_sig1;
+    /** vht sig2 */
+	t_u32 vht_sig2;
+} MLAN_PACK_END rxpd_extra_info, *prxpd_extra_info;
+
+/** rdaio tap information structure */
+typedef MLAN_PACK_START struct _radiotap_info {
+    /** Rate Info */
+	mix_rate_info rate_info;
+    /** SNR */
+	t_s8 snr;
+    /** Noise Floor */
+	t_s8 nf;
+    /** band config */
+	t_u8 band_config;
+    /** chan number */
+	t_u8 chan_num;
+    /** antenna */
+	t_u8 antenna;
+    /** extra rxpd info from FW */
+	rxpd_extra_info extra_info;
+} MLAN_PACK_END radiotap_info, *pradiotap_info;
+
+/** 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;
+    /** Offset to data */
+	t_u32 data_offset;
+    /** Data length */
+	t_u32 data_len;
+    /** Buffer type: data, cmd, event etc. */
+	mlan_buf_type buf_type;
+
+    /** Fields below are valid for data packet only */
+    /** QoS priority */
+	t_u32 priority;
+    /** Time stamp when packet is received (seconds) */
+	t_u32 in_ts_sec;
+    /** Time stamp when packet is received (micro seconds) */
+	t_u32 in_ts_usec;
+    /** Time stamp when packet is processed (seconds) */
+	t_u32 out_ts_sec;
+    /** Time stamp when packet is processed (micro seconds) */
+	t_u32 out_ts_usec;
+    /** tx_seq_num */
+	t_u32 tx_seq_num;
+
+    /** Fields below are valid for MLAN module only */
+    /** Pointer to parent mlan_buffer */
+	struct _mlan_buffer *pparent;
+    /** Use count for this buffer */
+	t_u32 use_count;
+	union {
+		pkt_txctrl tx_info;
+		pkt_rxinfo rx_info;
+	} u;
+} mlan_buffer, *pmlan_buffer;
+
+/** mlan_fw_info data structure */
+typedef struct _mlan_hw_info {
+    /** Firmware capabilities */
+	t_u32 fw_cap;
+} mlan_hw_info, *pmlan_hw_info;
+
+/** mlan_bss_attr data structure */
+typedef struct _mlan_bss_attr {
+    /** BSS type */
+	t_u32 bss_type;
+    /** Data frame type: Ethernet II, 802.11, etc. */
+	t_u32 frame_type;
+    /** The BSS is active (non-0) or not (0). */
+	t_u32 active;
+    /** BSS Priority */
+	t_u32 bss_priority;
+    /** BSS number */
+	t_u32 bss_num;
+    /** The BSS is virtual */
+	t_u32 bss_virtual;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+/** bss tbl data structure */
+typedef struct _mlan_bss_tbl {
+    /** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+} mlan_bss_tbl, *pmlan_bss_tbl;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** Type enumeration for the command result */
+typedef MLAN_PACK_START enum _mlan_cmd_result_e {
+	MLAN_CMD_RESULT_SUCCESS = 0,
+	MLAN_CMD_RESULT_FAILURE = 1,
+	MLAN_CMD_RESULT_TIMEOUT = 2,
+	MLAN_CMD_RESULT_INVALID_DATA = 3
+} MLAN_PACK_END mlan_cmd_result_e;
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} MLAN_PACK_END mlan_wmm_ac_e;
+
+/** Type enumeration for the action field in the Queue Config command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e {
+	MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_config_action_e;
+
+/** Type enumeration for the action field in the queue stats command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e {
+	MLAN_WMM_STATS_ACTION_START = 0,
+	MLAN_WMM_STATS_ACTION_STOP = 1,
+	MLAN_WMM_STATS_ACTION_GET_CLR = 2,
+	MLAN_WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_stats_action_e;
+
+/**
+ *  @brief IOCTL structure for a Traffic stream status.
+ *
+ */
+typedef MLAN_PACK_START struct {
+    /** TSID: Range: 0->7 */
+	t_u8 tid;
+    /** TSID specified is valid */
+	t_u8 valid;
+    /** AC TSID is active on */
+	t_u8 access_category;
+    /** UP specified for the TSID */
+	t_u8 user_priority;
+    /** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 psb;
+    /** Upstream(0), Downlink(1), Bidirectional(3) */
+	t_u8 flow_dir;
+    /** Medium time granted for the TSID */
+	t_u16 medium_time;
+} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t,
+/** Type definition of mlan_ds_wmm_ts_status for MLAN_OID_WMM_CFG_TS_STATUS */
+mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status;
+
+/** Max Ie length */
+#define MAX_IE_SIZE             256
+
+/** custom IE */
+typedef MLAN_PACK_START struct _custom_ie {
+    /** IE Index */
+	t_u16 ie_index;
+    /** Mgmt Subtype Mask */
+	t_u16 mgmt_subtype_mask;
+    /** IE Length */
+	t_u16 ie_length;
+    /** IE buffer */
+	t_u8 ie_buffer[MAX_IE_SIZE];
+} MLAN_PACK_END custom_ie;
+
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW         4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX               26
+
+/** custom IE info */
+typedef MLAN_PACK_START struct _custom_ie_info {
+    /** size of buffer */
+	t_u16 buf_size;
+    /** no of buffers of buf_size */
+	t_u16 buf_count;
+} MLAN_PACK_END custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** No of tuples */
+	t_u16 count;
+    /** custom IE info tuples */
+	custom_ie_info info[MAX_MGMT_IE_INDEX];
+} MLAN_PACK_END tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef MLAN_PACK_START struct _tlvbuf_custom_ie {
+    /** Type */
+	t_u16 type;
+    /** Length */
+	t_u16 len;
+    /** IE data */
+	custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW];
+    /** Max mgmt IE TLV */
+	tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+/** 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[0];
+} 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[0];
+		} 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[0];
+		} 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[0];
+		} 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;
+
+#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 {
+	WIFI_DISCONNECTED = 0,
+	WIFI_AUTHENTICATING = 1,
+	WIFI_ASSOCIATING = 2,
+	WIFI_ASSOCIATED = 3,
+    /** if done by firmware/driver */
+	WIFI_EAPOL_STARTED = 4,
+    /** if done by firmware/driver */
+	WIFI_EAPOL_COMPLETED = 5,
+} wifi_connection_state;
+/** roam state */
+typedef enum {
+	WIFI_ROAMING_IDLE = 0,
+	WIFI_ROAMING_ACTIVE = 1,
+} wifi_roam_state;
+/** interface mode */
+typedef enum {
+	WIFI_INTERFACE_STA = 0,
+	WIFI_INTERFACE_SOFTAP = 1,
+	WIFI_INTERFACE_IBSS = 2,
+	WIFI_INTERFACE_P2P_CLIENT = 3,
+	WIFI_INTERFACE_P2P_GO = 4,
+	WIFI_INTERFACE_NAN = 5,
+	WIFI_INTERFACE_MESH = 6,
+} wifi_interface_mode;
+
+/** set for QOS association */
+#define WIFI_CAPABILITY_QOS          0x00000001
+/** set for protected association (802.11 beacon frame control protected bit set) */
+#define WIFI_CAPABILITY_PROTECTED    0x00000002
+/** set if 802.11 Extended Capabilities element interworking bit is set */
+#define WIFI_CAPABILITY_INTERWORKING 0x00000004
+/** set for HS20 association */
+#define WIFI_CAPABILITY_HS20         0x00000008
+/** set is 802.11 Extended Capabilities element UTF-8 SSID bit is set */
+#define WIFI_CAPABILITY_SSID_UTF8    0x00000010
+/** set is 802.11 Country Element is present */
+#define WIFI_CAPABILITY_COUNTRY      0x00000020
+
+/** link layer status */
+typedef struct {
+    /** interface mode */
+	wifi_interface_mode mode;
+    /** interface mac address (self) */
+	t_u8 mac_addr[6];
+    /** connection state (valid for STA, CLI only) */
+	wifi_connection_state state;
+    /** roaming state */
+	wifi_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];
+} wifi_interface_link_layer_info;
+
+typedef wifi_interface_link_layer_info *wifi_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;
+
+/** 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 */
+	wifi_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) */
+
+/** =========== Define Copied from HAL START =========== */
+/** Ranging status */
+typedef enum {
+	RTT_STATUS_SUCCESS = 0,
+    /** general failure status */
+	RTT_STATUS_FAILURE = 1,
+    /** target STA does not respond to request */
+	RTT_STATUS_FAIL_NO_RSP = 2,
+    /** request rejected. Applies to 2-sided RTT only */
+	RTT_STATUS_FAIL_REJECTED = 3,
+	RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4,
+    /** timing measurement times out */
+	RTT_STATUS_FAIL_TM_TIMEOUT = 5,
+    /** Target on different channel, cannot range */
+	RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6,
+    /** ranging not supported */
+	RTT_STATUS_FAIL_NO_CAPABILITY = 7,
+    /** request aborted for unknown reason */
+	RTT_STATUS_ABORTED = 8,
+    /** Invalid T1-T4 timestamp */
+	RTT_STATUS_FAIL_INVALID_TS = 9,
+    /** 11mc protocol failed */
+	RTT_STATUS_FAIL_PROTOCOL = 10,
+    /** request could not be scheduled */
+	RTT_STATUS_FAIL_SCHEDULE = 11,
+    /** responder cannot collaborate at time of request */
+	RTT_STATUS_FAIL_BUSY_TRY_LATER = 12,
+    /** bad request args */
+	RTT_STATUS_INVALID_REQ = 13,
+    /** WiFi not enabled */
+	RTT_STATUS_NO_WIFI = 14,
+    /** Responder overrides param info, cannot range with new params */
+	RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15
+} wifi_rtt_status;
+
+/** RTT peer type */
+typedef enum {
+	RTT_PEER_AP = 0x1,
+	RTT_PEER_STA = 0x2,
+	RTT_PEER_P2P_GO = 0x3,
+	RTT_PEER_P2P_CLIENT = 0x4,
+	RTT_PEER_NAN = 0x5
+} rtt_peer_type;
+
+/** RTT Measurement Bandwidth */
+typedef enum {
+	WIFI_RTT_BW_5 = 0x01,
+	WIFI_RTT_BW_10 = 0x02,
+	WIFI_RTT_BW_20 = 0x04,
+	WIFI_RTT_BW_40 = 0x08,
+	WIFI_RTT_BW_80 = 0x10,
+	WIFI_RTT_BW_160 = 0x20
+} wifi_rtt_bw;
+
+/** RTT Type */
+typedef enum {
+	RTT_TYPE_1_SIDED = 0x1,
+	RTT_TYPE_2_SIDED = 0x2,
+} wifi_rtt_type;
+
+/** RTT configuration */
+typedef struct {
+    /** peer device mac address */
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+    /** 1-sided or 2-sided RTT */
+	wifi_rtt_type type;
+    /** optional - peer device hint (STA, P2P, AP) */
+	rtt_peer_type peer;
+    /** Required for STA-AP mode, optional for P2P, NBD etc. */
+	wifi_channel_info channel;
+    /** Time interval between bursts (units: 100 ms).
+      * Applies to 1-sided and 2-sided RTT multi-burst requests.
+      * Range: 0-31, 0: no preference by initiator (2-sided RTT) */
+	t_u32 burst_period;
+    /** Total number of RTT bursts to be executed. It will be
+      * specified in the same way as the parameter "Number of
+      * Burst Exponent" found in the FTM frame format. It
+      * applies to both: 1-sided RTT and 2-sided RTT. Valid
+      * values are 0 to 15 as defined in 802.11mc std.
+      * 0 means single shot
+      * The implication of this parameter on the maximum
+      * number of RTT results is the following:
+      * for 1-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst)
+      * for 2-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst - 1) */
+	t_u32 num_burst;
+    /** num of frames per burst. Minimum value = 1, Maximum value = 31
+      * For 2-sided this equals the number of FTM frames to be attempted in a single burst.
+      * This also equals the number of FTM frames that the initiator will request that the responder send
+      * in a single frame. */
+	t_u32 num_frames_per_burst;
+    /** number of retries for a failed RTT frame. Applies
+      * to 1-sided RTT only. Minimum value = 0, Maximum value = 3 */
+	t_u32 num_retries_per_rtt_frame;
+
+    /** following fields are only valid for 2-side RTT */
+    /** Maximum number of retries that the initiator can retry an FTMR frame.
+      * Minimum value = 0, Maximum value = 3 */
+	t_u32 num_retries_per_ftmr;
+    /** 1: request LCI, 0: do not request LCI */
+	t_u8 LCI_request;
+    /** 1: request LCR, 0: do not request LCR */
+	t_u8 LCR_request;
+    /** Applies to 1-sided and 2-sided RTT. Valid values will
+      * be 2-11 and 15 as specified by the 802.11mc std for
+      * the FTM parameter burst duration. In a multi-burst
+      * request, if responder overrides with larger value,
+      * the initiator will return failure. In a single-burst
+      * request if responder overrides with larger value,
+      * the initiator will sent TMR_STOP to terminate RTT
+      * at the end of the burst_duration it requested. */
+	t_u32 burst_duration;
+    /** RTT preamble to be used in the RTT frames */
+	wifi_preamble preamble;
+    /** RTT BW to be used in the RTT frames */
+	wifi_rtt_bw bw;
+} wifi_rtt_config;
+
+/** Format of information elements found in the beacon */
+typedef struct {
+    /** element identifier */
+	t_u8 id;
+    /** number of bytes to follow */
+	t_u8 len;
+	t_u8 data[];
+} wifi_information_element;
+
+/** RTT results */
+typedef struct {
+    /** device mac address */
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+    /** burst number in a multi-burst request */
+	t_u32 burst_num;
+    /** Total RTT measurement frames attempted */
+	t_u32 measurement_number;
+    /** Total successful RTT measurement frames */
+	t_u32 success_number;
+    /** Maximum number of "FTM frames per burst" supported by
+      * the responder STA. Applies to 2-sided RTT only.
+      * If reponder overrides with larger value:
+      * - for single-burst request initiator will truncate the
+      * larger value and send a TMR_STOP after receiving as
+      * many frames as originally requested.
+      * - for multi-burst request, initiator will return
+      * failure right away */
+	t_u8 number_per_burst_peer;
+    /** ranging status */
+	wifi_rtt_status status;
+    /** When status == RTT_STATUS_FAIL_BUSY_TRY_LATER,
+      * this will be the time provided by the responder as to
+      * when the request can be tried again. Applies to 2-sided
+      * RTT only. In sec, 1-31sec. */
+	t_u8 retry_after_duration;
+    /** RTT type */
+	wifi_rtt_type type;
+    /** average rssi in 0.5 dB steps e.g. 143 implies -71.5 dB */
+	int rssi;
+    /** rssi spread in 0.5 dB steps e.g. 5 implies 2.5 dB spread (optional) */
+	int rssi_spread;
+    /** 1-sided RTT: TX rate of RTT frame.
+      * 2-sided RTT: TX rate of initiator's Ack in response to FTM frame. */
+	wifi_rate tx_rate;
+    /** 1-sided RTT: TX rate of Ack from other side.
+      * 2-sided RTT: TX rate of FTM frame coming from responder. */
+	wifi_rate rx_rate;
+    /** round trip time in picoseconds */
+	t_s64 rtt;
+    /** rtt standard deviation in picoseconds */
+	t_s64 rtt_sd;
+    /** difference between max and min rtt times recorded in picoseconds */
+	t_s64 rtt_spread;
+    /** distance in mm (optional) */
+	int distance_mm;
+    /** standard deviation in mm (optional) */
+	int distance_sd_mm;
+    /** difference between max and min distance recorded in mm (optional) */
+	int distance_spread_mm;
+    /** time of the measurement (in microseconds since boot) */
+	t_s64 ts;
+    /** in ms, actual time taken by the FW to finish one burst
+      * measurement. Applies to 1-sided and 2-sided RTT. */
+	int burst_duration;
+    /** Number of bursts allowed by the responder. Applies
+      * to 2-sided RTT only. */
+	int negotiated_burst_num;
+    /** for 11mc only */
+	wifi_information_element *LCI;
+    /** for 11mc only */
+	wifi_information_element *LCR;
+} wifi_rtt_result;
+
+/** Preamble definition for bit mask used in wifi_rtt_capabilities */
+#define PREAMBLE_LEGACY 0x1
+#define PREAMBLE_HT     0x2
+#define PREAMBLE_VHT    0x4
+
+/** BW definition for bit mask used in wifi_rtt_capabilities */
+#define BW_5_SUPPORT   0x1
+#define BW_10_SUPPORT  0x2
+#define BW_20_SUPPORT  0x4
+#define BW_40_SUPPORT  0x8
+#define BW_80_SUPPORT  0x10
+#define BW_160_SUPPORT 0x20
+
+/** RTT Capabilities */
+typedef struct {
+    /** if 1-sided rtt data collection is supported */
+	t_u8 rtt_one_sided_supported;
+    /** if ftm rtt data collection is supported */
+	t_u8 rtt_ftm_supported;
+    /** if initiator supports LCI request. Applies to 2-sided RTT */
+	t_u8 lci_support;
+    /** if initiator supports LCR request. Applies to 2-sided RTT */
+	t_u8 lcr_support;
+    /** bit mask indicates what preamble is supported by initiator */
+	t_u8 preamble_support;
+    /** bit mask indicates what BW is supported by initiator */
+	t_u8 bw_support;
+    /** if 11mc responder mode is supported */
+	t_u8 responder_supported;
+    /** draft 11mc spec version supported by chip. For instance,
+      * version 4.0 should be 40 and version 4.3 should be 43 etc. */
+	t_u8 mc_version;
+} wifi_rtt_capabilities;
+
+/** API for setting LCI/LCR information to be provided to a requestor */
+typedef enum {
+    /** Not expected to change location */
+	WIFI_MOTION_NOT_EXPECTED = 0,
+    /** Expected to change location */
+	WIFI_MOTION_EXPECTED = 1,
+    /** Movement pattern unknown */
+	WIFI_MOTION_UNKNOWN = 2,
+} wifi_motion_pattern;
+
+/** LCI information */
+typedef struct {
+    /** latitude in degrees * 2^25 , 2's complement */
+	long latitude;
+    /** latitude in degrees * 2^25 , 2's complement */
+	long longitude;
+    /** Altitude in units of 1/256 m */
+	int altitude;
+    /** As defined in Section 2.3.2 of IETF RFC 6225 */
+	t_u8 latitude_unc;
+    /** As defined in Section 2.3.2 of IETF RFC 6225 */
+	t_u8 longitude_unc;
+    /** As defined in Section 2.4.5 from IETF RFC 6225: */
+	t_u8 altitude_unc;
+    /** Following element for configuring the Z subelement */
+	wifi_motion_pattern motion_pattern;
+    /** floor in units of 1/16th of floor. 0x80000000 if unknown. */
+	int floor;
+    /** in units of 1/64 m */
+	int height_above_floor;
+    /** in units of 1/64 m. 0 if unknown */
+	int height_unc;
+} wifi_lci_information;
+
+/** LCR information */
+typedef struct {
+    /** country code */
+	char country_code[2];
+    /** length of the info field */
+	int length;
+    /** Civic info to be copied in FTM frame */
+	char civic_info[256];
+} wifi_lcr_information;
+
+/**
+ * RTT Responder information
+ */
+typedef struct {
+	wifi_channel_info channel;
+	wifi_preamble preamble;
+} wifi_rtt_responder;
+
+/** =========== Define Copied from HAL END =========== */
+
+#define MAX_RTT_CONFIG_NUM 10
+
+/** RTT config params */
+typedef struct wifi_rtt_config_params {
+	t_u8 rtt_config_num;
+	wifi_rtt_config rtt_config[MAX_RTT_CONFIG_NUM];
+} wifi_rtt_config_params_t;
+
+#define OID_RTT_REQUEST  0
+#define OID_RTT_CANCEL   1
+
+/** Pass RTT result element between mlan and moal */
+typedef struct {
+    /** element identifier  */
+	t_u16 id;
+    /** number of bytes to follow  */
+	t_u16 len;
+    /** data: fill with one wifi_rtt_result  */
+	t_u8 data[0];
+} wifi_rtt_result_element;
+
+#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) (IN t_void *pmoal_handle,
+					 IN t_u32 offset,
+					 IN t_u32 len, OUT t_u8 *pbuf);
+    /** moal_get_hw_spec_complete */
+	mlan_status (*moal_get_hw_spec_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status,
+						  IN mlan_hw_info * phw,
+						  IN pmlan_bss_tbl ptbl);
+    /** moal_init_fw_complete */
+	mlan_status (*moal_init_fw_complete) (IN t_void *pmoal_handle,
+					      IN mlan_status status);
+    /** moal_shutdown_fw_complete */
+	mlan_status (*moal_shutdown_fw_complete) (IN t_void *pmoal_handle,
+						  IN mlan_status status);
+    /** moal_send_packet_complete */
+	mlan_status (*moal_send_packet_complete) (IN t_void *pmoal_handle,
+						  IN pmlan_buffer pmbuf,
+						  IN mlan_status status);
+    /** moal_recv_complete */
+	mlan_status (*moal_recv_complete) (IN t_void *pmoal_handle,
+					   IN pmlan_buffer pmbuf,
+					   IN t_u32 port,
+					   IN mlan_status status);
+    /** moal_recv_packet */
+	mlan_status (*moal_recv_packet) (IN t_void *pmoal_handle,
+					 IN pmlan_buffer pmbuf);
+    /** moal_recv_event */
+	mlan_status (*moal_recv_event) (IN t_void *pmoal_handle,
+					IN pmlan_event pmevent);
+    /** moal_ioctl_complete */
+	mlan_status (*moal_ioctl_complete) (IN t_void *pmoal_handle,
+					    IN pmlan_ioctl_req pioctl_req,
+					    IN mlan_status status);
+
+    /** moal_alloc_mlan_buffer */
+	mlan_status (*moal_alloc_mlan_buffer) (IN t_void *pmoal_handle,
+					       IN t_u32 size,
+					       OUT pmlan_buffer *pmbuf);
+    /** moal_free_mlan_buffer */
+	mlan_status (*moal_free_mlan_buffer) (IN t_void *pmoal_handle,
+					      IN pmlan_buffer pmbuf);
+
+    /** moal_write_reg */
+	mlan_status (*moal_write_reg) (IN t_void *pmoal_handle,
+				       IN t_u32 reg, IN t_u32 data);
+    /** moal_read_reg */
+	mlan_status (*moal_read_reg) (IN t_void *pmoal_handle,
+				      IN t_u32 reg, OUT t_u32 *data);
+    /** moal_write_data_sync */
+	mlan_status (*moal_write_data_sync) (IN t_void *pmoal_handle,
+					     IN pmlan_buffer pmbuf,
+					     IN t_u32 port, IN t_u32 timeout);
+    /** moal_read_data_sync */
+	mlan_status (*moal_read_data_sync) (IN t_void *pmoal_handle,
+					    IN OUT pmlan_buffer pmbuf,
+					    IN t_u32 port, IN t_u32 timeout);
+    /** moal_malloc */
+	mlan_status (*moal_malloc) (IN t_void *pmoal_handle,
+				    IN t_u32 size,
+				    IN t_u32 flag, OUT t_u8 **ppbuf);
+    /** moal_mfree */
+	mlan_status (*moal_mfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_vmalloc */
+	mlan_status (*moal_vmalloc) (IN t_void *pmoal_handle,
+				     IN t_u32 size, OUT t_u8 **ppbuf);
+    /** moal_vfree */
+	mlan_status (*moal_vfree) (IN t_void *pmoal_handle, IN t_u8 *pbuf);
+    /** moal_memset */
+	t_void *(*moal_memset) (IN t_void *pmoal_handle,
+				IN t_void *pmem, IN t_u8 byte, IN t_u32 num);
+    /** moal_memcpy */
+	t_void *(*moal_memcpy) (IN t_void *pmoal_handle,
+				IN t_void *pdest,
+				IN const t_void *psrc, IN t_u32 num);
+    /** moal_memmove */
+	t_void *(*moal_memmove) (IN t_void *pmoal_handle,
+				 IN t_void *pdest,
+				 IN const t_void *psrc, IN t_u32 num);
+    /** moal_memcmp */
+	t_s32 (*moal_memcmp) (IN t_void *pmoal_handle,
+			      IN const t_void *pmem1,
+			      IN const t_void *pmem2, IN t_u32 num);
+    /** moal_udelay */
+	t_void (*moal_udelay) (IN t_void *pmoal_handle, IN t_u32 udelay);
+    /** moal_get_system_time */
+	mlan_status (*moal_get_system_time) (IN t_void *pmoal_handle,
+					     OUT t_u32 *psec, OUT t_u32 *pusec);
+    /** moal_init_timer*/
+	mlan_status (*moal_init_timer) (IN t_void *pmoal_handle,
+					OUT t_void **pptimer,
+					IN t_void (*callback) (t_void
+							       *pcontext),
+					IN t_void *pcontext);
+    /** moal_free_timer */
+	mlan_status (*moal_free_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_start_timer*/
+	mlan_status (*moal_start_timer) (IN t_void *pmoal_handle,
+					 IN t_void *ptimer,
+					 IN t_u8 periodic, IN t_u32 msec);
+    /** moal_stop_timer*/
+	mlan_status (*moal_stop_timer) (IN t_void *pmoal_handle,
+					IN t_void *ptimer);
+    /** moal_init_lock */
+	mlan_status (*moal_init_lock) (IN t_void *pmoal_handle,
+				       OUT t_void **pplock);
+    /** moal_free_lock */
+	mlan_status (*moal_free_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_lock */
+	mlan_status (*moal_spin_lock) (IN t_void *pmoal_handle,
+				       IN t_void *plock);
+    /** moal_spin_unlock */
+	mlan_status (*moal_spin_unlock) (IN t_void *pmoal_handle,
+					 IN t_void *plock);
+    /** moal_print */
+	t_void (*moal_print) (IN t_void *pmoal_handle,
+			      IN t_u32 level, IN char *pformat, IN ...
+		);
+    /** moal_print_netintf */
+	t_void (*moal_print_netintf) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index, IN t_u32 level);
+    /** moal_assert */
+	t_void (*moal_assert) (IN t_void *pmoal_handle, IN t_u32 cond);
+    /** moal_hist_data_add */
+	t_void (*moal_hist_data_add) (IN t_void *pmoal_handle,
+				      IN t_u32 bss_index,
+				      IN t_u8 rx_rate,
+				      IN t_s8 snr,
+				      IN t_s8 nflr, IN t_u8 antenna);
+	t_void (*moal_updata_peer_signal) (IN t_void *pmoal_handle,
+					   IN t_u32 bss_index,
+					   IN t_u8 *peer_addr,
+					   IN t_s8 snr, IN t_s8 nflr);
+	mlan_status (*moal_get_host_time_ns) (OUT t_u64 *time);
+	t_u64 (*moal_do_div) (IN t_u64 num, IN t_u32 base);
+} 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
+
+/** 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
+
+/** 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
+
+/** 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
+    /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+    /** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#ifdef DEBUG_LEVEL1
+    /** Driver debug bit masks */
+	t_u32 drvdbg;
+#endif
+    /** allocate fixed buffer size for scan beacon buffer*/
+	t_u32 fixed_beacon_buffer;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** SDIO MPA Rx */
+	t_u32 mpa_rx_cfg;
+#endif
+	/** SDIO Single port rx aggr */
+	t_u8 sdio_rx_aggr_enable;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/* 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
+    /** 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;
+    /** Host sleep wakeup interval */
+	t_u32 hs_wake_interval;
+    /** GPIO to indicate wakeup source */
+	t_u8 indication_gpio;
+    /** channel time and mode for DRCS*/
+	t_u32 drcs_chantime_mode;
+	t_bool fw_region;
+} mlan_device, *pmlan_device;
+
+/** MLAN API function prototype */
+#define MLAN_API
+
+/** Registration */
+MLAN_API mlan_status mlan_register(IN pmlan_device pmdevice,
+				   OUT t_void **ppmlan_adapter);
+
+/** Un-registration */
+MLAN_API mlan_status mlan_unregister(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Downloading */
+MLAN_API mlan_status mlan_dnld_fw(IN t_void *pmlan_adapter,
+				  IN pmlan_fw_image pmfw);
+
+/** Custom data pass API */
+MLAN_API mlan_status mlan_set_init_param(IN t_void *pmlan_adapter,
+					 IN pmlan_init_param pparam);
+
+/** Firmware Initialization */
+MLAN_API mlan_status mlan_init_fw(IN t_void *pmlan_adapter
+	);
+
+/** Firmware Shutdown */
+MLAN_API mlan_status mlan_shutdown_fw(IN t_void *pmlan_adapter
+	);
+
+/** Main Process */
+MLAN_API mlan_status mlan_main_process(IN t_void *pmlan_adapter
+	);
+
+/** Rx process */
+mlan_status mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts);
+
+/** Packet Transmission */
+MLAN_API mlan_status mlan_send_packet(IN t_void *pmlan_adapter,
+				      IN pmlan_buffer pmbuf);
+
+/** Packet Reception complete callback */
+MLAN_API mlan_status mlan_recv_packet_complete(IN t_void *pmlan_adapter,
+					       IN pmlan_buffer pmbuf,
+					       IN mlan_status status);
+
+/** interrupt handler */
+MLAN_API mlan_status mlan_interrupt(IN t_void *pmlan_adapter);
+
+#if defined(SYSKT)
+/** GPIO IRQ callback function */
+MLAN_API t_void mlan_hs_callback(IN t_void *pctx);
+#endif /* SYSKT_MULTI || SYSKT */
+
+MLAN_API t_void mlan_pm_wakeup_card(IN t_void *pmlan_adapter);
+
+MLAN_API t_u8 mlan_is_main_process_running(IN t_void *adapter);
+
+/** mlan ioctl */
+MLAN_API mlan_status mlan_ioctl(IN t_void *pmlan_adapter,
+				IN pmlan_ioctl_req pioctl_req);
+/** mlan select wmm queue */
+MLAN_API t_u8 mlan_select_wmm_queue(IN t_void *pmlan_adapter,
+				    IN t_u8 bss_num, IN t_u8 tid);
+#endif /* !_MLAN_DECL_H_ */
diff --git a/wlan_sd8997/mlinux/mlan_ieee.h b/wlan_sd8997/mlinux/mlan_ieee.h
new file mode 100644
index 0000000..a74a44b
--- /dev/null
+++ b/wlan_sd8997/mlinux/mlan_ieee.h
@@ -0,0 +1,1954 @@
+/** @file mlan_ieee.h
+ *
+ *  @brief This file contains IEEE information element related
+ *  definitions used in MLAN and MOAL module.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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
+
+/** 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,
+	MEASUREMENT_REQUEST = 38,
+	MEASUREMENT_REPORT = 39,
+	REGULATORY_CLASS = 59,
+	HT_CAPABILITY = 45,
+	QOS_INFO = 46,
+	HT_OPERATION = 61,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	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_IE = VENDOR_SPECIFIC_221,
+	RSN_IE = 48,
+	VS_IE = VENDOR_SPECIFIC_221,
+	WAPI_IE = 68,
+} 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;
+
+#define MEASURE_TYPE_CLI 8
+#define MEASURE_TYPE_LOCATION_CIVIC 9
+
+/** Measurement Report IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MeasurementReport_t {
+    /** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+    /** Measurement Token */
+	t_u8 ms_token;
+    /** Measurement Report Mode */
+	t_u8 ms_rp_mode;
+    /** Measurement Type, value in MEASURE_TYPE_XXX */
+	t_u8 ms_type;
+    /** variable */
+	t_u8 variable[0];
+} MLAN_PACK_END IEEEtypes_MeasurementReport_t;
+
+/** Report */
+typedef MLAN_PACK_START struct _IEEEtypes_Report_t {
+    /** Subelement ID */
+	t_u8 subelement_id;
+    /** length */
+	t_u8 length;
+    /** variable */
+	t_u8 variable[0];
+} MLAN_PACK_END IEEEtypes_Report_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;
+
+/** 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[0];
+} MLAN_PACK_END IEEEtypes_Auth_framebody;
+
+/*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[0];
+} 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[0];
+} MLAN_PACK_END IEEEtypes_Ft_action_request;
+
+/*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_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_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_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
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN    4
+/** AKM Suite length */
+#define AKM_SUITE_LEN    4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT    7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT    6
+/** PMF ORing mask */
+#define PMF_MASK    0x00c0
+#endif
+
+/** wpa_suite_t */
+typedef MLAN_PACK_START struct _wpa_suite_t {
+    /** OUI */
+	t_u8 oui[3];
+    /** tyep */
+	t_u8 type;
+} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t;
+
+/** wpa_suite_ucast_t */
+typedef MLAN_PACK_START struct {
+	/* count */
+	t_u16 count;
+    /** wpa_suite list */
+	wpa_suite list[1];
+} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+
+/** IEEEtypes_Rsn_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t {
+    /** Rsn : Element ID */
+	t_u8 element_id;
+    /** Rsn : Length */
+	t_u8 len;
+    /** Rsn : version */
+	t_u16 version;
+    /** Rsn : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Rsn : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t;
+
+/** IEEEtypes_Wpa_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t {
+    /** Wpa : Element ID */
+	t_u8 element_id;
+    /** Wpa : Length */
+	t_u8 len;
+    /** Wpa : oui */
+	t_u8 oui[4];
+    /** version */
+	t_u16 version;
+    /** Wpa : group cipher */
+	wpa_suite_mcast_t group_cipher;
+    /** Wpa : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+    /** Parameter set count */
+	t_u8 para_set_count:4;
+    /** Reserved */
+	t_u8 reserved:3;
+    /** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Reserved */
+	t_u8 reserved:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aifsn */
+	t_u8 aifsn:4;
+#else
+    /** Aifsn */
+	t_u8 aifsn:4;
+    /** Acm */
+	t_u8 acm:1;
+    /** Aci */
+	t_u8 aci:2;
+    /** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+    /** Minimum Ecw */
+	t_u8 ecw_min:4;
+    /** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn;   /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;		    /**< Ecw */
+	t_u16 tx_op_limit;		      /**< Tx op limit */
+} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t {
+
+    /**
+     * WMM Info IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [7]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [0]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+
+} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t {
+    /**
+     * WMM Parameter IE - Vendor Specific Header:
+     *   element_id  [221/0xdd]
+     *   Len         [24]
+     *   Oui         [00:50:f2]
+     *   OuiType     [2]
+     *   OuiSubType  [1]
+     *   Version     [1]
+     */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+    /** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+    /** Reserved */
+	t_u8 reserved;
+
+    /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/** Enumerator for TSPEC direction */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e {
+
+	TSPEC_DIR_UPLINK = 0,
+	TSPEC_DIR_DOWNLINK = 1,
+	/* 2 is a reserved value */
+	TSPEC_DIR_BIDIRECT = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e;
+
+/** Enumerator for TSPEC PSB */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e {
+
+	TSPEC_PSB_LEGACY = 0,
+	TSPEC_PSB_TRIG = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e;
+
+/** Enumerator for TSPEC Ack Policy */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e {
+
+	TSPEC_ACKPOLICY_NORMAL = 0,
+	TSPEC_ACKPOLICY_NOACK = 1,
+	/* 2 is reserved */
+	TSPEC_ACKPOLICY_BLOCKACK = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e;
+
+/** Enumerator for TSPEC Trafffice type */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e {
+
+	TSPEC_TRAFFIC_APERIODIC = 0,
+	TSPEC_TRAFFIC_PERIODIC = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e;
+
+/** Data structure of WMM TSPEC information */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+	t_u8 Schedule:1;
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 AccessPolicy1:1;	/* ! */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+#else
+	IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 AccessPolicy1:1;	/* ! */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1;	/* ! Legacy/Trigg */
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 Schedule:1;
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t;
+
+/** Data structure of WMM TSPEC Nominal Size */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+	t_u16 Size:15;		/* ! Nominal size in octets */
+#else
+	t_u16 Size:15;		/* ! Nominal size in octets */
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is nominal */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t;
+
+/** Data structure of WMM TSPEC SBWA */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Whole:3;		/* ! Whole portion */
+	t_u16 Fractional:13;	/* ! Fractional portion */
+#else
+	t_u16 Fractional:13;	/* ! Fractional portion */
+	t_u16 Whole:3;		/* ! Whole portion */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA;
+
+/** Data structure of WMM TSPEC Body */
+typedef MLAN_PACK_START struct {
+
+    /** TS Information */
+	IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo;
+    /** NomMSDU size */
+	IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize;
+    /** MAximum MSDU size */
+	t_u16 MaximumMSDUSize;
+    /** Minimum Service Interval */
+	t_u32 MinServiceInterval;
+    /** Maximum Service Interval */
+	t_u32 MaxServiceInterval;
+    /** Inactivity Interval */
+	t_u32 InactivityInterval;
+    /** Suspension Interval */
+	t_u32 SuspensionInterval;
+    /** Service Start Time */
+	t_u32 ServiceStartTime;
+    /** Minimum Data Rate */
+	t_u32 MinimumDataRate;
+    /** Mean Data Rate */
+	t_u32 MeanDataRate;
+    /** Peak Data Rate */
+	t_u32 PeakDataRate;
+    /** Maximum Burst Size */
+	t_u32 MaxBurstSize;
+    /** Delay Bound */
+	t_u32 DelayBound;
+    /** Minimum Phy Rate */
+	t_u32 MinPHYRate;
+    /** Surplus BA Allowance */
+	IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance;
+    /** Medium Time */
+	t_u16 MediumTime;
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t;
+
+/** Data structure of WMM TSPEC all elements */
+typedef MLAN_PACK_START struct {
+    /** Element ID */
+	t_u8 ElementId;
+    /** Length */
+	t_u8 Len;
+    /** Oui Type */
+	t_u8 OuiType[4];	/* 00:50:f2:02 */
+    /** Ouisubtype */
+	t_u8 OuiSubType;	/* 01 */
+    /** Version */
+	t_u8 Version;
+
+    /** TspecBody */
+	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 {
+
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+    /** Action */
+	IEEEtypes_WMM_Tspec_Action_e action;
+    /** Dialog Token */
+	t_u8 dialogToken;
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t;
+
+/** WMM TSPEC AddTS request structure */
+typedef MLAN_PACK_START struct {
+
+    /** Tspec action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Status Code */
+	t_u8 statusCode;
+    /** tspecIE */
+	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 {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+    /** Reason Code */
+	t_u8 reasonCode;
+    /** tspecIE */
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t;
+
+/** union of WMM TSPEC structures */
+typedef MLAN_PACK_START union {
+    /** tspec Action */
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+
+    /** add TS request */
+	IEEEtypes_Action_WMM_AddTsReq_t addTsReq;
+    /** add TS response */
+	IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp;
+    /** Delete TS */
+	IEEEtypes_Action_WMM_DelTs_t delTs;
+
+} MLAN_PACK_END IEEEtypes_Action_WMMAC_t;
+
+/** union of WMM TSPEC & Action category */
+typedef MLAN_PACK_START union {
+    /** Category */
+	IEEEtypes_ActionCategory_e category;
+
+    /** wmmAc */
+	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;
+
+/** 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;
+    /** Channel width */
+	t_u8 chan_width;
+    /** Channel center frequency 1 */
+	t_u8 chan_center_freq_1;
+    /** Channel center frequency 2 */
+	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;
+    /** maximum tx power */
+	t_u8 max_tx_power;
+    /** channel center frequency */
+	t_u8 chan_center_freq;
+    /** channel width */
+	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;
+    /** MIMO capability count */
+	t_u8 MU_MIMO_capa_count;
+    /** stream under utilization */
+	t_u8 stream_underutilization;
+    /** VHT 40 util */
+	t_u8 VHT40_util;
+    /** VHT 80 util */
+	t_u8 VHT80_util;
+    /** VHT 160 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;
+    /** AP quiet mode */
+	t_u8 AP_quiet_mode;
+    /** Quiet count */
+	t_u8 quiet_count;
+    /** Quiet period */
+	t_u8 quiet_period;
+    /** Quiet duration */
+	t_u16 quiet_dur;
+    /** Quiet offset */
+	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;
+    /** New channel width */
+	t_u8 new_chan_width;
+    /** New channel center frequency 1 */
+	t_u8 new_chan_center_freq_1;
+    /** New channel center frequency 2 */
+	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;
+
+/** default channel switch count */
+#define DEF_CHAN_SWITCH_COUNT       5
+
+/*  IEEE Channel Switch Announcement Element (7.3.2.20) */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a chan switch element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id;	/**< IEEE Element ID = 37 */
+	t_u8 len;		/**< Element length after id and len */
+	t_u8 chan_switch_mode;	/**< STA should not transmit any frames if 1 */
+	t_u8 new_channel_num;	/**< Channel # that AP/IBSS is moving to */
+	t_u8 chan_switch_count;	/**< # of TBTTs before channel switch */
+
+} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t;
+
+/** data structure for extended channel switch */
+typedef MLAN_PACK_START struct {
+   /** IEEE element ID = 60 */
+	t_u8 element_id;
+    /** Element length after id and len, set to 4 */
+	t_u8 len;
+    /** STA should not transmit any frames if 1 */
+	t_u8 chan_switch_mode;
+    /** Operate class # that AP/IBSS is moving to */
+	t_u8 new_oper_class;
+    /** Channel # that AP/IBSS is moving to */
+	t_u8 new_channel_num;
+    /** of TBTTs before channel switch */
+	t_u8 chan_switch_count;
+} MLAN_PACK_END IEEEtypes_ExtChanSwitchAnn_t;
+
+/*  IEEE Wide Bandwidth Channel Switch Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a wide bandwidth chan
+ *    switch element.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 194*/
+	IEEEtypes_Header_t ieee_hdr;
+    /** New channel width */
+	t_u8 new_channel_width;
+    /** New channel center frequency 0*/
+	t_u8 new_channel_center_freq0;
+    /** New channel center frequency 1*/
+	t_u8 new_channel_center_freq1;
+} MLAN_PACK_END IEEEtypes_WideBWChanSwitch_t;
+
+/*  IEEE VHT Transmit Power Envelope Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise the max
+ *    TX power in sepeate bandwidth and as a sub element of Channel Switch
+ *    Wrapper IE.
+ */
+typedef MLAN_PACK_START struct {
+    /** Generic IE header IEEE Element ID = 195*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 tpc_info;		/**< Transmit Power Information>*/
+	t_u8 local_max_tp_20mhz;/**< Local Maximum Transmit Power for 20 MHZ>*/
+	t_u8 local_max_tp_40mhz;/**< Local Maximum Transmit Power for 40 MHZ>*/
+	t_u8 local_max_tp_80mhz;/**< Local Maximum Transmit Power for 80 MHZ>*/
+} MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t;
+
+/** 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 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
+
+/** 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;
+
+/** 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];
+} 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
+
+/**
+ *  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;
+	t_u8 random_mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END wlan_bgscan_cfg;
+#endif /* STA_SUPPORT */
+
+/** 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;
+} MLAN_PACK_END ChanStatistics_t;
+
+#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 */
+	t_u32 channel;
+
+    /** Freq */
+	t_u32 freq;
+
+    /** Beacon period */
+	t_u16 beacon_period;
+
+    /** ATIM window */
+	t_u32 atim_window;
+
+    /** ERP flags */
+	t_u8 erp_flags;
+
+    /** Type of network in use */
+	WLAN_802_11_NETWORK_TYPE network_type_use;
+
+    /** Network infrastructure mode */
+	t_u32 bss_mode;
+
+    /** Network supported rates */
+	WLAN_802_11_RATES supported_rates;
+
+    /** Supported data rates */
+	t_u8 data_rates[WLAN_SUPPORTED_RATES];
+
+    /** Current channel bandwidth
+     *  0 : 20MHZ
+     *  1 : 40MHZ
+     *  2 : 80MHZ
+     *  3 : 160MHZ
+     */
+	t_u8 curr_bandwidth;
+
+    /** Network band.
+     * BAND_B(0x01): 'b' band
+     * BAND_G(0x02): 'g' band
+     * BAND_A(0X04): 'a' band
+     */
+	t_u16 bss_band;
+
+    /** TSF timestamp from the current firmware TSF */
+	t_u64 network_tsf;
+
+    /** TSF value included in the beacon/probe response */
+	t_u8 time_stamp[8];
+
+    /** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+
+    /** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+
+    /** Capability information */
+	IEEEtypes_CapInfo_t cap_info;
+
+    /** WMM IE */
+	IEEEtypes_WmmParameter_t wmm_ie;
+
+    /** 802.11h BSS information */
+	wlan_11h_bss_info_t wlan_11h_bss_info;
+
+    /** Indicate disabling 11n when associate with AP */
+	t_u8 disable_11n;
+    /** 802.11n BSS information */
+    /** HT Capabilities IE */
+	IEEEtypes_HTCap_t *pht_cap;
+    /** HT Capabilities Offset */
+	t_u16 ht_cap_offset;
+    /** HT Information IE */
+	IEEEtypes_HTInfo_t *pht_info;
+    /** HT Information Offset */
+	t_u16 ht_info_offset;
+    /** 20/40 BSS Coexistence IE */
+	IEEEtypes_2040BSSCo_t *pbss_co_2040;
+    /** 20/40 BSS Coexistence Offset */
+	t_u16 bss_co_2040_offset;
+    /** Extended Capabilities IE */
+	IEEEtypes_ExtCap_t *pext_cap;
+    /** Extended Capabilities Offset */
+	t_u16 ext_cap_offset;
+    /** Overlapping BSS Scan Parameters IE */
+	IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param;
+    /** Overlapping BSS Scan Parameters Offset */
+	t_u16 overlap_bss_offset;
+
+    /** VHT Capabilities IE */
+	IEEEtypes_VHTCap_t *pvht_cap;
+    /** VHT Capabilities IE offset */
+	t_u16 vht_cap_offset;
+    /** VHT Operations IE */
+	IEEEtypes_VHTOprat_t *pvht_oprat;
+    /** VHT Operations IE offset */
+	t_u16 vht_oprat_offset;
+    /** VHT Transmit Power Envelope IE */
+	IEEEtypes_VHTtxpower_t *pvht_txpower;
+    /** VHT Transmit Power Envelope IE offset */
+	t_u16 vht_txpower_offset;
+    /** Extended Power Constraint IE */
+	IEEEtypes_ExtPwerCons_t *pext_pwer;
+    /** Extended Power Constraint IE offset */
+	t_u16 ext_pwer_offset;
+    /** Extended BSS Load IE  */
+	IEEEtypes_ExtBSSload_t *pext_bssload;
+    /** Extended BSS Load IE offset */
+	t_u16 ext_bssload_offset;
+    /** Quiet Channel IE */
+	IEEEtypes_QuietChan_t *pquiet_chan;
+    /** Quiet Channel IE offset */
+	t_u16 quiet_chan_offset;
+    /** Operating Mode Notification IE */
+	IEEEtypes_OperModeNtf_t *poper_mode;
+    /** Operating Mode Notification IE offset */
+	t_u16 oper_mode_offset;
+
+#ifdef STA_SUPPORT
+    /** Country information set */
+	IEEEtypes_CountryInfoFullSet_t country_info;
+#endif				/* STA_SUPPORT */
+
+    /** WPA IE */
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+    /** WPA IE offset in the beacon buffer */
+	t_u16 wpa_offset;
+    /** RSN IE */
+	IEEEtypes_Generic_t *prsn_ie;
+    /** RSN IE offset in the beacon buffer */
+	t_u16 rsn_offset;
+#ifdef STA_SUPPORT
+    /** WAPI IE */
+	IEEEtypes_Generic_t *pwapi_ie;
+    /** WAPI IE offset in the beacon buffer */
+	t_u16 wapi_offset;
+#endif
+	/* Mobility domain IE */
+	IEEEtypes_MobilityDomain_t *pmd_ie;
+	/** Mobility domain IE offset in the beacon buffer */
+	t_u16 md_offset;
+
+    /** Pointer to the returned scan response */
+	t_u8 *pbeacon_buf;
+    /** Length of the stored scan response */
+	t_u32 beacon_buf_size;
+    /** Max allocated size for updated scan response */
+	t_u32 beacon_buf_size_max;
+
+} BSSDescriptor_t, *pBSSDescriptor_t;
+
+/**
+ *  Type definitions for TCLAS element
+ */
+#define TCLAS_CLASSIFIER_TYPE_4      4
+
+/**
+ *  IEEE TCLAS Classifier Type 4
+ *
+ *  Type definition for Classifier Type 4 in TCLAS element
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_IPv4_t {
+    /** Version */
+	t_u8 version;
+    /** Source IP address */
+	t_u8 source_ip_addr[4];
+    /** Dest IP address */
+	t_u8 dest_ip_addr[4];
+    /** Source port */
+	t_u8 source_port[2];
+    /** Dest port */
+	t_u8 dest_port[2];
+    /** DSCP value */
+	t_u8 dscp;
+    /** Protocol value */
+	t_u8 protocol;
+    /** Reserved */
+	t_u8 reserved;
+} MLAN_PACK_END IEEEtypes_TCLAS_IPv4_t;
+
+/**
+ *  IEEE TCLAS base
+ *
+ *  Type definition for common parameters for every
+ *    classifier type
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_Base_t {
+    /** Element id */
+	t_u8 element_id;
+    /** Element len */
+	t_u8 element_len;
+    /** User priority */
+	t_u8 user_priority;
+    /** Classifier type */
+	t_u8 classifier_type;
+    /** Classifier mask */
+	t_u8 classifier_mask;
+} MLAN_PACK_END IEEEtypes_TCLAS_Base_t;
+
+/**
+ *  IEEE TCLAS element
+ *
+ *  Type definition for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _IEEEtypes_TCLAS_t {
+    /** Base structure for TCLAS */
+	IEEEtypes_TCLAS_Base_t tclas_base;
+
+	union MLAN_PACK_START {
+	/** Classifier type 4 */
+		IEEEtypes_TCLAS_IPv4_t ipv4;
+	} MLAN_PACK_END classifier;
+} MLAN_PACK_END IEEEtypes_TCLAS_t;
+
+/**
+ *  TCLAS element TLV
+ *
+ *  Structure that defines TLV for TCLAS element with different
+ *    classifier types
+ *
+ */
+typedef struct MLAN_PACK_START _tclasElemen_tlv {
+    /** Type */
+	t_u16 type;
+    /** Length of TLV */
+	t_u16 len;
+    /** Tclas Ie */
+	IEEEtypes_TCLAS_t tclas_ie;
+} MLAN_PACK_END tclas_element_tlv_t;
+
+#endif /* !_MLAN_IEEE_H_ */
diff --git a/wlan_sd8997/mlinux/mlan_ioctl.h b/wlan_sd8997/mlinux/mlan_ioctl.h
new file mode 100644
index 0000000..5a66592
--- /dev/null
+++ b/wlan_sd8997/mlinux/mlan_ioctl.h
@@ -0,0 +1,4745 @@
+/** @file mlan_ioctl.h
+ *
+ *  @brief This file declares the IOCTL data structures and APIs.
+ *
+ *  Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ *  This software file (the "File") is distributed by Marvell International
+ *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ *  (the "License").  You may use, redistribute and/or modify this File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ */
+
+/******************************************************
+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_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
+
+	/* 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,
+
+	/* 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,
+
+	/* 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_FW_WAKEUP_METHOD = 0x00090007,
+	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,
+
+	/* 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,
+#if defined(DFS_TESTING_SUPPORT)
+	MLAN_OID_11H_DFS_TESTING = 0x00110003,
+#endif
+	MLAN_OID_11H_CHAN_REPORT_REQUEST = 0x00110004,
+	MLAN_OID_11H_CHAN_SWITCH_COUNT = 0x00110005,
+#ifdef DFS_TESTING_SUPPORT
+	MLAN_OID_11H_CHAN_NOP_INFO = 0x00110006,
+#endif
+
+	/* 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,
+
+	MLAN_IOCTL_11K_CFG = 0x00130000,
+	MLAN_OID_11K_CFG_ENABLE = 0x00130001,
+	MLAN_OID_11K_GET_NLIST = 0x00130002,
+
+	/* 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,
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	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_COALESCING_STATUS = 0x0020000E,
+	MLAN_OID_MISC_CUSTOM_IE = 0x0020000F,
+	MLAN_OID_MISC_TDLS_CONFIG = 0x00200010,
+	MLAN_OID_MISC_NET_MONITOR = 0x00200011,
+	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_OTP_USER_DATA = 0x0020001D,
+	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
+	MLAN_OID_MISC_MULTI_CHAN_CFG = 0x00200023,
+	MLAN_OID_MISC_MULTI_CHAN_POLICY = 0x00200024,
+#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_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_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_ROAM_OFFLOAD = 0x00200042,
+	MLAN_OID_MISC_ROAM_OFFLOAD_APLIST = 0x00200043,
+	MLAN_OID_MISC_GET_TSF = 0x00200045,
+	MLAN_OID_MISC_GET_CHAN_REGION_CFG = 0x00200046,
+	MLAN_OID_MISC_OPER_CLASS_CHECK = 0x00200049,
+	MLAN_OID_MISC_DRCS_CFG = 0x00200050,
+
+	MLAN_OID_MISC_CWMODE_CTRL = 0x00200051,
+	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_CORRELATED_TIME = 0x00200058,
+	MLAN_OID_MISC_CONFIG_RTT = 0x00200059,
+	MLAN_OID_MISC_CANCEL_RTT = 0x0020005A,
+	MLAN_OID_MISC_RTT_RESPONDER_CFG = 0x0020005B,
+	MLAN_OID_MISC_CFP_INFO = 0x00200060,
+	MLAN_OID_MISC_BOOT_SLEEP = 0x00200061,
+	MLAN_OID_MISC_ACS = 0x00200063,
+};
+
+/** 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
+};
+
+/** 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
+};
+
+/** Max number of supported rates */
+#define MLAN_SUPPORTED_RATES	32
+
+/** 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
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES      4
+
+/** Default number of probes to send on each channel */
+#define DEFAULT_PROBES  4
+
+/** MAX BG channel */
+#define MAX_BG_CHANNEL 14
+
+/**
+ *  @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;
+    /** 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;
+
+/** tx status event structure */
+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;
+	/** t1 time stamp */
+	t_u64 t1_tstamp;
+	/** t4 time stamp */
+	t_u64 t4_tstamp;
+	/** t1 error */
+	t_u64 t1_error;
+	/** t4 error */
+	t_u64 t4_error;
+	/** egress time */
+	t_u64 egress_time;
+} 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[0]; */
+} 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;
+    /** Ext_scan:  0 disable, 1: enable, 2: enhance scan*/
+	t_u32 ext_scan;
+} 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 PMK R0 NAME key length */
+#define MLAN_MAX_PMKR0_NAME_LENGTH      16
+
+/** 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)
+
+/** mlan_ssid_bssid  data structure for
+ *  MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS
+ */
+typedef struct _mlan_ssid_bssid {
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+    /** index in BSSID list, start from 1 */
+	t_u32 idx;
+    /** Receive signal strength in dBm */
+	t_s32 rssi;
+    /**channel*/
+	t_u16 channel;
+    /**mobility domain value*/
+	t_u16 ft_md;
+    /**ft capability*/
+	t_u8 ft_cap;
+    /**band*/
+	t_u16 bss_band;
+	t_u32 channel_flags;
+} mlan_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
+/** 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   10
+/** 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  300
+/** 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           16
+
+/* 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
+
+/** 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
+
+/** 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;
+
+/** 5G band */
+#define BAND_CONFIG_5G        0x01
+/** 2.4 G band */
+#define BAND_CONFIG_2G        0x00
+/** 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;
+
+} mlan_uap_bss_param;
+
+/** mlan_uap_scan_channels */
+typedef struct _mlan_uap_scan_channels {
+    /** flag for remove nop channel*/
+	t_u8 remove_nop_channel;
+	/** num of removed channel */
+	t_u8 num_remvoed_channel;
+    /** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+    /** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+} mlan_uap_scan_channels;
+
+/** mlan_uap_oper_ctrl */
+typedef struct _mlan_uap_oper_ctrl {
+    /** control value
+      *  0: do nothing,
+      *  2: uap stops and restarts automaticaly
+     */
+	t_u16 ctrl_value;
+    /** channel opt
+      *  1: uap restart on default 2.4G/channel 6
+      *  2: uap restart on the band/channel configured by driver previously
+      *  3: uap restart on the band/channel specified by band_cfg and channel
+	*/
+	t_u16 chan_opt;
+    /** band cfg   0
+      *  0: 20Mhz  2: 40 Mhz  3: 80Mhz
+     */
+	t_u8 band_cfg;
+    /** channel */
+	t_u8 channel;
+} mlan_uap_oper_ctrl;
+
+#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 uap flag for MLAN_OID_BSS_START */
+		t_u8 host_based;
+	/** BSS param for AP mode for MLAN_OID_UAP_BSS_CONFIG */
+		mlan_uap_bss_param bss_config;
+	/** AP Wmm parameters for MLAN_OID_UAP_CFG_WMM_PARAM */
+		wmm_parameter_t ap_wmm_para;
+	/** ap scan channels for MLAN_OID_UAP_SCAN_CHANNELS*/
+		mlan_uap_scan_channels ap_scan_channels;
+	/** ap channel for MLAN_OID_UAP_CHANNEL*/
+		chan_band_info ap_channel;
+	/** ap operation control for MLAN_OID_UAP_OPER_CTRL*/
+		mlan_uap_oper_ctrl ap_oper_ctrl;
+#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
+	} param;
+} mlan_ds_bss, *pmlan_ds_bss;
+
+/** Type definition of mlan_ds_custom_reg_domain */
+typedef struct _mlan_ds_custom_reg_domain {
+	t_u8 cfg_len;
+	t_u8 cfg_buf[0];
+} 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,
+};
+
+/** 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;
+    /** Ad-hoc channel bandwidth */
+	t_u32 adhoc_chan_bandwidth;
+    /** 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
+
+/** filt field param structure */
+struct filt_field_param {
+	/** Operation */
+	t_u8 operation;
+	/** Operand len */
+	t_u8 operand_len;
+	/** offset */
+	t_u16 offset;
+	/** Operand byte stream */
+	t_u8 operand_byte_stream[COALESCE_MAX_BYTESEQ];
+};
+
+/** coalesce rule structure */
+struct coalesce_rule {
+	/** max coalescing delay */
+	t_u16 max_coalescing_delay;
+	/** number of fields */
+	t_u8 num_of_fields;
+	/** packet type */
+	t_u8 pkt_type;
+	struct filt_field_param params[COALESCE_MAX_FILTERS];
+};
+
+/** coalesce configuration structure */
+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
+};
+
+/** Get stats org structure */
+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;
+} mlan_ds_get_stats, *pmlan_ds_get_stats;
+
+/** Type definition of mlan_ds_get_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_get_correlated_time {
+   /** System time */
+	t_u64 sys_time;
+   /** FW time */
+	t_u64 hw_time;
+} mlan_ds_get_correlated_time, *pmlan_ds_get_correlated_time;
+
+/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_uap_stats {
+    /** tkip mic failures */
+	t_u32 tkip_mic_failures;
+    /** ccmp decrypt errors */
+	t_u32 ccmp_decrypt_errors;
+    /** wep undecryptable count */
+	t_u32 wep_undecryptable_count;
+    /** wep icv error count */
+	t_u32 wep_icv_error_count;
+    /** decrypt failure count */
+	t_u32 decrypt_failure_count;
+    /** dot11 multicast tx count */
+	t_u32 mcast_tx_count;
+    /** dot11 failed count */
+	t_u32 failed_count;
+    /** dot11 retry count */
+	t_u32 retry_count;
+    /** dot11 multi retry count */
+	t_u32 multi_retry_count;
+    /** dot11 frame duplicate count */
+	t_u32 frame_dup_count;
+    /** dot11 rts success count */
+	t_u32 rts_success_count;
+    /** dot11 rts failure count */
+	t_u32 rts_failure_count;
+    /** dot11 ack failure count */
+	t_u32 ack_failure_count;
+    /** dot11 rx ragment count */
+	t_u32 rx_fragment_count;
+    /** dot11 mcast rx frame count */
+	t_u32 mcast_rx_frame_count;
+    /** dot11 fcs error count */
+	t_u32 fcs_error_count;
+    /** dot11 tx frame count */
+	t_u32 tx_frame_count;
+    /** dot11 rsna tkip cm invoked */
+	t_u32 rsna_tkip_cm_invoked;
+    /** dot11 rsna 4way handshake failures */
+	t_u32 rsna_4way_hshk_failures;
+} mlan_ds_uap_stats, *pmlan_ds_uap_stats;
+
+/** Mask of last beacon RSSI */
+#define BCN_RSSI_LAST_MASK              0x00000001
+/** Mask of average beacon RSSI */
+#define BCN_RSSI_AVG_MASK               0x00000002
+/** Mask of last data RSSI */
+#define DATA_RSSI_LAST_MASK             0x00000004
+/** Mask of average data RSSI */
+#define DATA_RSSI_AVG_MASK              0x00000008
+/** Mask of last beacon SNR */
+#define BCN_SNR_LAST_MASK               0x00000010
+/** Mask of average beacon SNR */
+#define BCN_SNR_AVG_MASK                0x00000020
+/** Mask of last data SNR */
+#define DATA_SNR_LAST_MASK              0x00000040
+/** Mask of average data SNR */
+#define DATA_SNR_AVG_MASK               0x00000080
+/** Mask of last beacon NF */
+#define BCN_NF_LAST_MASK                0x00000100
+/** Mask of average beacon NF */
+#define BCN_NF_AVG_MASK                 0x00000200
+/** Mask of last data NF */
+#define DATA_NF_LAST_MASK               0x00000400
+/** Mask of average data NF */
+#define DATA_NF_AVG_MASK                0x00000800
+/** Mask of all RSSI_INFO */
+#define ALL_RSSI_INFO_MASK              0x00000fff
+#define MAX_PATH_NUM                    3
+/** path A */
+#define PATH_A							0x01
+/** path B */
+#define PATH_B							0x02
+/** path AB */
+#define PATH_AB							0x03
+/** ALL the path */
+#define PATH_ALL						0
+/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */
+typedef struct _mlan_ds_get_signal {
+    /** Selector of get operation */
+	/*
+	 * Bit0:  Last Beacon RSSI,  Bit1:  Average Beacon RSSI,
+	 * Bit2:  Last Data RSSI,    Bit3:  Average Data RSSI,
+	 * Bit4:  Last Beacon SNR,   Bit5:  Average Beacon SNR,
+	 * Bit6:  Last Data SNR,     Bit7:  Average Data SNR,
+	 * Bit8:  Last Beacon NF,    Bit9:  Average Beacon NF,
+	 * Bit10: Last Data NF,      Bit11: Average Data NF
+	 *
+	 * Bit0: PATH A
+	 * Bit1: PATH B
+	 */
+	t_u16 selector;
+
+    /** RSSI */
+    /** RSSI of last beacon */
+	t_s16 bcn_rssi_last;
+    /** RSSI of beacon average */
+	t_s16 bcn_rssi_avg;
+    /** RSSI of last data packet */
+	t_s16 data_rssi_last;
+    /** RSSI of data packet average */
+	t_s16 data_rssi_avg;
+
+    /** SNR */
+    /** SNR of last beacon */
+	t_s16 bcn_snr_last;
+    /** SNR of beacon average */
+	t_s16 bcn_snr_avg;
+    /** SNR of last data packet */
+	t_s16 data_snr_last;
+    /** SNR of data packet average */
+	t_s16 data_snr_avg;
+
+    /** NF */
+    /** NF of last beacon */
+	t_s16 bcn_nf_last;
+    /** NF of beacon average */
+	t_s16 bcn_nf_avg;
+    /** NF of last data packet */
+	t_s16 data_nf_last;
+    /** NF of data packet average */
+	t_s16 data_nf_avg;
+} mlan_ds_get_signal, *pmlan_ds_get_signal;
+
+/** bit for 2.4 G antenna diversity */
+#define ANT_DIVERSITY_2G   MBIT(3)
+/** bit for 5 G antenna diversity */
+#define ANT_DIVERSITY_5G   MBIT(7)
+
+/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */
+typedef struct _mlan_fw_info {
+    /** Firmware version */
+	t_u32 fw_ver;
+    /** MAC address */
+	mlan_802_11_mac_addr mac_addr;
+    /** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+    /** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+    /** user's MCS setting */
+	t_u8 usr_dev_mcs_support;
+    /** 802.11ac device capabilities */
+	t_u32 hw_dot_11ac_dev_cap;
+    /** 802.11ac device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11ac_dev_cap_bg;
+    /** 802.11ac device Capabilities for 5GHz */
+	t_u32 usr_dot_11ac_dev_cap_a;
+    /** 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_u8 fw_bands;
+	/** region code */
+	t_u16 region_code;
+    /** 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;
+    /** FW support roaming offload */
+	t_u8 fw_roaming_support;
+} mlan_fw_info, *pmlan_fw_info;
+
+/** Version string buffer length */
+#define MLAN_MAX_VER_STR_LEN    128
+
+/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */
+typedef struct _mlan_ver_ext {
+    /** Selected version string */
+	t_u32 version_str_sel;
+    /** Version string */
+	char version_str[MLAN_MAX_VER_STR_LEN];
+} mlan_ver_ext, *pmlan_ver_ext;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+    /** Extended Capabilities value */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit77: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 MaxAMSDU:2;	/* bit 63-bit 64 */
+	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 MaxAMSDU:2;	/* bit 63-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 rsvdBit77:1;	/* bit 77 */
+	t_u8 rsvdBit78:1;	/* bit 78 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#endif
+
+/** ExtCap : TDLS prohibited */
+#define IS_EXTCAP_TDLS_PROHIBITED(ext_cap) (ext_cap.TDLSProhibited)
+/** ExtCap : TDLS channel switch prohibited */
+#define IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ext_cap) (ext_cap.TDLSChlSwitchProhib)
+
+/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */
+typedef struct _mlan_bss_info {
+    /** BSS mode */
+	t_u32 bss_mode;
+    /** SSID */
+	mlan_802_11_ssid ssid;
+    /** Table index */
+	t_u32 scan_table_idx;
+    /** Channel */
+	t_u32 bss_chan;
+    /** Band */
+	t_u8 bss_band;
+    /** Region code */
+	t_u32 region_code;
+    /** Connection status */
+	t_u32 media_connected;
+    /** Radio on */
+	t_u32 radio_on;
+    /** Max power level in dBm */
+	t_s32 max_power_level;
+    /** Min power level in dBm */
+	t_s32 min_power_level;
+    /** Adhoc state */
+	t_u32 adhoc_state;
+    /** NF of last beacon */
+	t_s32 bcn_nf_last;
+    /** wep status */
+	t_u32 wep_status;
+    /** scan block status */
+	t_u8 scan_block;
+     /** Host Sleep configured flag */
+	t_u32 is_hs_configured;
+    /** Deep Sleep flag */
+	t_u32 is_deep_sleep;
+    /** BSSID */
+	mlan_802_11_mac_addr bssid;
+#ifdef STA_SUPPORT
+    /** Capability Info */
+	t_u16 capability_info;
+    /** Beacon Interval */
+	t_u16 beacon_interval;
+    /** Listen Interval */
+	t_u16 listen_interval;
+    /** Association Id  */
+	t_u16 assoc_id;
+    /** AP/Peer supported rates */
+	t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES];
+    /** extend capability for AP */
+	ExtCap_t ext_cap;
+#endif				/* STA_SUPPORT */
+    /** Mobility Domain ID */
+	t_u16 mdid;
+    /** FT Capability policy */
+	t_u8 ft_cap;
+    /** 11h active */
+	t_bool is_11h_active;
+    /** dfs check channel */
+	t_u8 dfs_check_channel;
+} mlan_bss_info, *pmlan_bss_info;
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID     8
+
+/** Max RX Win size */
+#define MAX_RX_WINSIZE  64
+
+/** rx_reorder_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** TA */
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+    /** Start window */
+	t_u32 start_win;
+    /** Window size */
+	t_u32 win_size;
+    /** amsdu flag */
+	t_u8 amsdu;
+    /** buffer status */
+	t_u32 buffer[MAX_RX_WINSIZE];
+} rx_reorder_tbl;
+
+/** tx_ba_stream_tbl */
+typedef struct {
+    /** TID */
+	t_u16 tid;
+    /** RA */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+    /** amsdu flag */
+	t_u8 amsdu;
+} tx_ba_stream_tbl;
+
+/** Debug command number */
+#define DBG_CMD_NUM	10
+
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+/** 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;
+
+/** 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;
+    /** Corresponds to is_hs_configured member of mlan_adapter */
+	t_u8 is_hs_configured;
+    /** Corresponds to hs_activated member of mlan_adapter */
+	t_u8 hs_activated;
+    /** Corresponds to pps_uapsd_mode member of mlan_adapter */
+	t_u16 pps_uapsd_mode;
+    /** Corresponds to sleep_period.period member of mlan_adapter */
+	t_u16 sleep_pd;
+    /** Corresponds to wmm_qosinfo member of mlan_private */
+	t_u8 qos_cfg;
+    /** Corresponds to tx_lock_flag member of mlan_adapter */
+	t_u8 tx_lock_flag;
+    /** Corresponds to port_open member of mlan_private */
+	t_u8 port_open;
+    /** bypass pkt count */
+	t_u16 bypass_pkt_count;
+    /** Corresponds to scan_processing member of mlan_adapter */
+	t_u32 scan_processing;
+    /** Corresponds to mlan_processing member of mlan_adapter */
+	t_u32 mlan_processing;
+    /** Corresponds to main_lock_flag member of mlan_adapter */
+	t_u32 main_lock_flag;
+    /** Corresponds to main_process_cnt member of mlan_adapter */
+	t_u32 main_process_cnt;
+	/** Corresponds to delay_task_flag member of mlan_adapter */
+	t_u32 delay_task_flag;
+    /** mlan_rx_processing */
+	t_u32 mlan_rx_processing;
+    /** rx pkts queued */
+	t_u32 rx_pkts_queued;
+    /** Number of host to card command failures */
+	t_u32 num_cmd_host_to_card_failure;
+    /** Number of host to card sleep confirm failures */
+	t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+    /** Number of host to card Tx failures */
+	t_u32 num_tx_host_to_card_failure;
+    /** Number of allocate buffer failure */
+	t_u32 num_alloc_buffer_failure;
+	/** Number of pkt dropped */
+	t_u32 num_pkt_dropped;
+    /** 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 * 2];
+	/** Invalid port update count */
+	t_u32 mp_invalid_update;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+    /** Number of packets tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT];
+    /** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+    /** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+	/** last recv wr_bitmap */
+	t_u32 last_recv_wr_bitmap;
+    /** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+    /** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+	/** last len for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+    /** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+    /** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT];
+    /** 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;
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+    /** Number of packets rx aggr */
+	t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_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 Tx timeouts */
+	t_u32 num_tx_timeout;
+    /** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+    /** Number of command timeouts */
+	t_u32 dbg_num_cmd_timeout;
+    /** Timeout command ID */
+	t_u16 timeout_cmd_id;
+    /** Timeout command action */
+	t_u16 timeout_cmd_act;
+    /** List of last command IDs */
+	t_u16 last_cmd_id[DBG_CMD_NUM];
+    /** List of last command actions */
+	t_u16 last_cmd_act[DBG_CMD_NUM];
+    /** Last command index */
+	t_u16 last_cmd_index;
+    /** List of last command response IDs */
+	t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+    /** Last command response index */
+	t_u16 last_cmd_resp_index;
+    /** List of last events */
+	t_u16 last_event[DBG_CMD_NUM];
+    /** Last event index */
+	t_u16 last_event_index;
+    /** Number of no free command node */
+	t_u16 num_no_cmd_node;
+    /** pending command id */
+	t_u16 pending_cmd;
+    /** time stamp for dnld last cmd */
+	t_u32 dnld_cmd_in_secs;
+    /** Corresponds to data_sent member of mlan_adapter */
+	t_u8 data_sent;
+    /** Corresponds to cmd_sent member of mlan_adapter */
+	t_u8 cmd_sent;
+    /** SDIO multiple port read bitmap */
+	t_u32 mp_rd_bitmap;
+    /** SDIO multiple port write bitmap */
+	t_u32 mp_wr_bitmap;
+    /** Current available port for read */
+	t_u8 curr_rd_port;
+    /** Current available port for write */
+	t_u8 curr_wr_port;
+    /** 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
+    /** mlan_adapter pointer */
+	t_void *mlan_adapter;
+    /** mlan_adapter_size */
+	t_u32 mlan_adapter_size;
+    /** mlan_priv vector */
+	t_void *mlan_priv[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_size */
+	t_u32 mlan_priv_size[MLAN_MAX_BSS_NUM];
+    /** mlan_priv_num */
+	t_u8 mlan_priv_num;
+} mlan_debug_info, *pmlan_debug_info;
+
+#ifdef UAP_SUPPORT
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS         MAX_STA_COUNT
+
+/** station info */
+typedef struct _sta_info {
+    /** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+    /** Power mfg status */
+	t_u8 power_mfg_status;
+    /** RSSI */
+	t_s8 rssi;
+    /** station bandmode */
+	t_u8 bandmode;
+} sta_info;
+
+/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */
+typedef struct _mlan_ds_sta_list {
+    /** station count */
+	t_u16 sta_count;
+    /** station list */
+	sta_info info[MAX_NUM_CLIENTS];
+} mlan_ds_sta_list, *pmlan_ds_sta_list;
+#endif
+
+/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */
+typedef struct _mlan_ds_get_info {
+    /** Sub-command */
+	t_u32 sub_command;
+
+    /** Status information parameter */
+	union {
+	/** Signal information for MLAN_OID_GET_SIGNAL */
+		mlan_ds_get_signal signal;
+		/** Signal path id for MLAN_OID_GET_SIGNAL_EXT */
+		t_u16 path_id;
+	/** Signal information for MLAN_OID_GET_SIGNAL_EXT */
+		mlan_ds_get_signal signal_ext[MAX_PATH_NUM];
+	/** Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_get_stats stats;
+	/** Statistics information for MLAN_OID_LINK_STATS*/
+		t_u8 link_statistic[1];
+	/** Firmware information for MLAN_OID_GET_FW_INFO */
+		mlan_fw_info fw_info;
+	/** Extended version information for MLAN_OID_GET_VER_EXT */
+		mlan_ver_ext ver_ext;
+	/** BSS information for MLAN_OID_GET_BSS_INFO */
+		mlan_bss_info bss_info;
+	/** Debug information for MLAN_OID_GET_DEBUG_INFO */
+		t_u8 debug_info[1];
+#ifdef UAP_SUPPORT
+	/** UAP Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_uap_stats ustats;
+	/** UAP station list for MLAN_OID_UAP_STA_LIST */
+		mlan_ds_sta_list sta_list;
+#endif
+	} param;
+} mlan_ds_get_info, *pmlan_ds_get_info;
+
+/*-----------------------------------------------------------------*/
+/** Security Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for authentication mode */
+enum _mlan_auth_mode {
+	MLAN_AUTH_MODE_OPEN = 0x00,
+	MLAN_AUTH_MODE_SHARED = 0x01,
+	MLAN_AUTH_MODE_FT = 0x02,
+	MLAN_AUTH_MODE_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_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,
+};
+
+/** Enumeration for PSK */
+enum _mlan_psk_type {
+	MLAN_PSK_PASSPHRASE = 1,
+	MLAN_PSK_PMK,
+	MLAN_PSK_CLEAR,
+	MLAN_PSK_QUERY,
+};
+
+/** 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
+/** 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
+/** 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 defnition of mlan_pmk_t */
+typedef struct _mlan_pmk_t {
+    /** PMK */
+	t_u8 pmk[MLAN_MAX_KEY_LENGTH];
+	t_u8 pmk_r0[MLAN_MAX_KEY_LENGTH];
+	t_u8 pmk_r0_name[MLAN_MAX_PMKR0_NAME_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;
+	/** 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;
+
+/* Security SSID MAX number support by firmware*/
+#define MAX_SEC_SSID_NUM 6
+
+/** Type definition of mlan_ds_sec_cfg for MLAN_IOCTL_SEC_CFG */
+typedef struct _mlan_ds_sec_cfg {
+    /** Sub-command */
+	t_u32 sub_command;
+    /** Flag to extend some structures to support multiple values.
+     ** For example, mlan_ds_passphrase can only contain one value,
+     ** if need use mlan_ds_passphrase[N], just set this flag and
+     ** use mlan_ds_passphrase[] instead to avoid modify
+     ** more already exist code.
+     */
+	t_u8 multi_passphrase;
+    /** 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;
+		mlan_ds_passphrase roam_passphrase[MAX_SEC_SSID_NUM];
+	} param;
+} mlan_ds_sec_cfg, *pmlan_ds_sec_cfg;
+
+/*-----------------------------------------------------------------*/
+/** 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_AUTO = 0xFF,
+};
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE   18
+
+/** 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;
+} 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;
+	} param;
+} mlan_ds_power_cfg, *pmlan_ds_power_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 adhoc awake period */
+#define MIN_ADHOC_AWAKE_PD      0
+/** Maximum adhoc awake period */
+#define MAX_ADHOC_AWAKE_PD      31
+/** Special adhoc awake period */
+#define SPECIAL_ADHOC_AWAKE_PD  255
+
+/** 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;
+    /** Adhoc awake period */
+	t_u32 adhoc_awake_period;
+    /** 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_fw_wakeup_params for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+typedef struct _mlan_fw_wakeup_params {
+    /** FW wakeup method */
+	t_u16 method;
+    /** GPIO pin NO.*/
+	t_u8 gpio_pin;
+} mlan_fw_wakeup_params, *pmlan_fw_wakeup_params;
+
+/** 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;
+	/** FW wakeup method for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+		mlan_fw_wakeup_params fw_wakeup_params;
+	/** 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;
+
+/** tx sounding cfg args */
+typedef struct _mlan_tx_sounding_cfg_args {
+    /** enable/disable tx sounding */
+	t_u8 tx_sounding_enbl;
+    /** Sounding Type */
+	t_u8 sounding_type;
+    /** Sounding interval in milliseconds */
+	t_u16 sounding_interval;
+} mlan_tx_sounding_cfg_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];
+		mlan_tx_sounding_cfg_args tx_sounding_cfg;
+	} 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;
+	} 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;
+
+/** 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;
+
+typedef struct _mlan_ds_11k_cfg {
+    /** Sub-command */
+	t_u32 sub_command;
+	union {
+		t_u32 enable_11k;
+	} param;
+} mlan_ds_11k_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,
+};
+
+/** 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 */
+/*-----------------------------------------------------------------*/
+#if defined(DFS_TESTING_SUPPORT)
+/** 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;
+} 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;
+#endif
+
+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;
+
+/** 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;
+#if defined(DFS_TESTING_SUPPORT)
+	/** 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;
+#endif
+		mlan_ds_11h_chan_rep_req chan_rpt_req;
+		t_s8 cs_count;
+	} param;
+} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Miscellaneous Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** CMD buffer size */
+#define MLAN_SIZE_OF_CMD_BUFFER 2048
+
+/** 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;
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** 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[MLAN_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;
+
+/** 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;
+
+/** Enumeration for function init/shutdown */
+enum _mlan_func_cmd {
+	MLAN_FUNC_INIT = 1,
+	MLAN_FUNC_SHUTDOWN,
+};
+
+/** Enumeration for Coalescing status */
+enum _mlan_coal_status {
+	MLAN_MISC_COALESCING_ENABLE = 1,
+	MLAN_MISC_COALESCING_DISABLE = 0
+};
+
+/* Net monitor filters: */
+/* management frame */
+#define MLAN_NETMON_MANAGEMENT    MBIT(0)
+/* control frame */
+#define MLAN_NETMON_CONTROL       MBIT(1)
+/* data frame */
+#define MLAN_NETMON_DATA          MBIT(2)
+/* only unicast frame (no promiscuous) */
+#define MLAN_NETMON_NOPROM        MBIT(3)
+/* decrypted frame */
+#define MLAN_NETMON_DECRYPTED     MBIT(4)
+
+typedef struct _mlan_ds_misc_net_monitor {
+    /** Enable/disable network monitor */
+	t_u32 enable_net_mon;
+    /** Set net monitor filer flag */
+	t_u32 filter_flag;
+   /** Radio type */
+	t_u32 band;
+    /** Channel */
+	t_u32 channel;
+    /** Secondary channel bandwidth */
+	t_u32 chan_bandwidth;
+} mlan_ds_misc_net_monitor;
+
+/** 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;
+
+/** 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;
+
+/* 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_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;
+
+/** Type definition of mlan_ds_host_clock  */
+typedef struct _mlan_ds_host_clock {
+    /** host time in secs */
+	t_u64 time;
+	/** fw time */
+	t_u64 fw_time;
+    /** host-bbu clock delta */
+	t_u64 host_bbu_clk_delta;
+} mlan_ds_host_clock;
+
+/** 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;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** flag for NOA */
+#define WIFI_DIRECT_NOA         1
+/** flag for OPP_PS */
+#define WIFI_DIRECT_OPP_PS      2
+/** Type definition of mlan_ds_wifi_direct_config
+ *  for MLAN_OID_MISC_WIFI_DIRECT_CONFIG
+ */
+typedef struct _mlan_ds_wifi_direct_config {
+    /** flags for NOA/OPP_PS */
+	t_u8 flags;
+     /** NoA enable/disable */
+	t_u8 noa_enable;
+    /** index */
+	t_u16 index;
+    /** NoA count */
+	t_u8 noa_count;
+    /** NoA duration */
+	t_u32 noa_duration;
+    /** NoA interval */
+	t_u32 noa_interval;
+    /** opp ps enable/disable */
+	t_u8 opp_ps_enable;
+    /** CT window value */
+	t_u8 ct_window;
+} mlan_ds_wifi_direct_config;
+#endif
+
+#if defined(STA_SUPPORT)
+/** mlan_ds_misc_pmfcfg structure */
+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
+
+/** mlan_ds_multi_chan_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_multi_chan_cfg {
+    /** Channel Time */
+	t_u32 channel_time;
+    /** Buffer Weight */
+	t_u8 buffer_weight;
+    /** tlv len */
+	t_u16 tlv_len;
+    /** TLV buffer */
+	t_u8 tlv_buf[0];
+} MLAN_PACK_END mlan_ds_multi_chan_cfg;
+
+/** mlan_ds_drcs_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_drcs_cfg {
+    /** Channel Index*/
+	t_u16 chan_idx;
+    /** Channel time (in TU) for chan_idx */
+	t_u8 chantime;
+    /** Channel swith time (in TU) for chan_idx */
+	t_u8 switchtime;
+    /** Undoze time (in TU) for chan_idx */
+	t_u8 undozetime;
+    /** Rx traffic control scheme when channel switch*/
+    /** only valid for GC/STA interface*/
+	t_u8 mode;
+} MLAN_PACK_END mlan_ds_drcs_cfg;
+
+#define MAX_SSID_NUM 16
+#define MAX_AP_LIST 8
+#define RETRY_UNLIMITED_TIME 0xFF
+
+#define FW_ROAM_ENABLE                        MBIT(0)
+#define FW_ROAM_TRIGGER_COND                  MBIT(1)
+#define FW_ROAM_BSSID                         MBIT(2)
+#define FW_ROAM_SSID                          MBIT(3)
+#define FW_ROAM_RETRY_COUNT                   MBIT(4)
+#define FW_ROAM_RSSI_PARA                     MBIT(5)
+#define FW_ROAM_BAND_RSSI                     MBIT(6)
+#define FW_ROAM_BGSCAN_PARAM                  MBIT(7)
+#define FW_ROAM_EES_PARAM                     MBIT(8)
+#define FW_ROAM_BCN_MISS_THRESHOLD            MBIT(9)
+#define FW_ROAM_PRE_BCN_MISS_THRESHOLD        MBIT(10)
+#define FW_ROAM_BLACKLIST                     MBIT(11)
+#define FW_ROAM_REPEAT_CNT                    MBIT(12)
+
+/*Roam offload configuration for auto reconnection when suspend and resume*/
+typedef enum _roam_offload_config_mode {
+	ROAM_OFFLOAD_ENABLE = 1,
+	ROAM_OFFLOAD_SUSPEND_CFG,
+	ROAM_OFFLOAD_RESUME_CFG,
+	ROAM_OFFLOAD_PARAM_CFG,
+} roam_offload_config_mode;
+
+typedef enum _roam_offload_set_mode {
+	ROAM_OFFLOAD_DISABLE = 0,
+	ROAM_OFFLOAD_WITH_APLIST,
+	ROAM_OFFLOAD_WITHOUT_APLIST,
+	ROAM_OFFLOAD_WITH_BSSID,
+	ROAM_OFFLOAD_WITH_SSID,
+	AUTO_RECONNECT,
+} roam_offload_set_mode;
+
+typedef enum _roam_offload_trigger_mode {
+	NO_TRIGGER = 0x00,
+	RSSI_LOW_TRIGGER = 0x01,
+	PRE_BEACON_LOST_TRIGGER = 0x02,
+	LINK_LOST_TRIGGER = 0x04,
+	DEAUTH_WITH_EXT_AP_TRIGGER = 0x08,
+} roam_offload_trigger_mode;
+
+/** mlan_ds_misc_ees_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_ees_cfg {
+	/* EES mode */
+	t_u16 ees_mode;
+	/* EES report condition */
+	t_u16 ees_rpt_condition;
+	/* High scan period(milliseconds) */
+	t_u16 high_scan_period;
+	/* High scan count */
+	t_u16 high_scan_count;
+	/* Middle scan period(milliseconds) */
+	t_u16 mid_scan_period;
+	/* Middle scan count */
+	t_u16 mid_scan_count;
+	/* Low scan period(milliseconds) */
+	t_u16 low_scan_period;
+	/* Low scan count */
+	t_u16 low_scan_count;
+} MLAN_PACK_END mlan_ds_misc_ees_cfg;
+
+/** mlan_ds_misc_bgscan_cfg structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_bgscan_cfg {
+	/* BSS Type  0x1-bss independent, 0x2-bss infrastructure, 0x3-bss any */
+	t_u8 bss_type;
+	/* Number of channels scanned for each scan */
+	t_u8 channels_per_scan;
+	/* Interval between consective scans */
+	t_u32 scan_interval;
+	/* Conditons to trigger report to host */
+	t_u32 bg_rpt_condition;
+} MLAN_PACK_END mlan_ds_misc_bgscan_cfg;
+
+/** mlan_ds_misc_band_rssi structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_band_rssi {
+	/* RSSI hysteresis */
+	t_u8 rssi_hysteresis;
+	/*  Preferred channel band for fw roaming
+	 *  0:2.4G band; 1: 5G band; 2:4G band; 0xFF:band not set(invalid)
+	 */
+	t_u8 band_preferred;
+} MLAN_PACK_END mlan_ds_misc_band_rssi;
+
+/** mlan_ds_misc_ssid_list structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_ssid_list {
+	/* SSID number */
+	t_u8 ssid_num;
+	/* SSID for fw roaming/auto_reconnect */
+	mlan_802_11_ssid ssids[MAX_SSID_NUM];
+} MLAN_PACK_END mlan_ds_misc_ssid_list;
+
+/** mlan_ds_misc_roam_offload_aplist structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_roam_offload_aplist {
+    /** Number of AP**/
+	t_u8 ap_num;
+    /** AP mac addrs**/
+	t_u8 ap_mac[MAX_AP_LIST][MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END mlan_ds_misc_roam_offload_aplist;
+
+/** _mlan_ds_misc_roam_offload_para_rssi structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_roam_offload_para_rssi {
+    /** Setting flag**/
+	t_u8 set_flag;
+    /** Max value of RSSI threshold**/
+	t_u8 max_rssi;
+    /** Min value of RSSI threshold**/
+	t_u8 min_rssi;
+    /** Adjusting step value of RSSI threshold**/
+	t_u8 step_rssi;
+} MLAN_PACK_END mlan_ds_misc_roam_offload_para_rssi;
+
+/** mlan_ds_misc_roam_offload structure */
+typedef MLAN_PACK_START struct _mlan_ds_misc_roam_offload {
+    /** Enable roam offload**/
+	t_u8 enable;
+    /** User set passphrase**/
+	t_u8 userset_passphrase;
+	/* Condition to trigger roaming
+	 * Bit0 : RSSI low trigger
+	 * Bit1 : Pre-beacon lost trigger
+	 * Bit2 : Link Lost trigger
+	 * Bit3 : Deauth by ext-AP trigger
+	 * Bit4 ~ Bit15 : Reserved
+	 * value 0 : no trigger
+	 * value 0xff : invalid
+	 */
+	t_u16 trigger_condition;
+    /** AP list**/
+	mlan_ds_misc_roam_offload_aplist aplist;
+	/*Roam offload configuration mode for auto connection when suspend and resume */
+	roam_offload_config_mode config_mode;
+    /** Retry count**/
+	t_u8 retry_count;
+    /** RSSI para**/
+	mlan_ds_misc_roam_offload_para_rssi para_rssi;
+    /** BSSID of reconnection**/
+	mlan_802_11_mac_addr bssid_reconnect;
+	/* SSID List(White list) */
+	mlan_ds_misc_ssid_list ssid_list;
+	/* Black list(BSSID list) */
+	mlan_ds_misc_roam_offload_aplist black_list;
+	/* BAND and RSSI_HYSTERESIS set flag */
+	t_u8 band_rssi_flag;
+	mlan_ds_misc_band_rssi band_rssi;
+
+	/* BGSCAN params set flag */
+	t_u8 bgscan_set_flag;
+	mlan_ds_misc_bgscan_cfg bgscan_cfg;
+
+	/* EES mode params set flag */
+	t_u8 ees_param_set_flag;
+	mlan_ds_misc_ees_cfg ees_cfg;
+
+	/* Beacon miss threshold */
+	t_u8 bcn_miss_threshold;
+
+	/* Beacon miss threshold */
+	t_u8 pre_bcn_miss_threshold;
+
+	/* Scan repeat count */
+	t_u16 repeat_count;
+} MLAN_PACK_END mlan_ds_misc_roam_offload;
+
+/**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
+
+/** mlan_ds_misc_dfs_repeater structure */
+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
+
+/** Temperature Sensor structure */
+typedef struct _mlan_ds_sensor_temp {
+    /** Temperature */
+	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;
+
+/** mlan_ds_cw_mode_ctrl structure */
+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[0];
+} 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;
+
+/** RTT configuration */
+typedef struct _mlan_rtt_config {
+    /** peer device mac address */
+	t_u8 addr[MLAN_MAC_ADDR_LENGTH];
+    /** 1-sided or 2-sided RTT */
+	t_u8 type;
+    /** optional - peer device hint (STA, P2P, AP) */
+	t_u8 peer;
+    /** Required for STA-AP mode, optional for P2P, NBD etc. */
+	t_u8 channel;
+    /** Required for STA-AP mode, optional for P2P, NBD etc. */
+	Band_Config_t bandcfg;
+    /** Time interval between bursts (units: 100 ms).
+      * Applies to 1-sided and 2-sided RTT multi-burst requests.
+      * Range: 0-31, 0: no preference by initiator (2-sided RTT) */
+	t_u8 burst_period;
+    /** Total number of RTT bursts to be executed. It will be
+      * specified in the same way as the parameter "Number of
+      * Burst Exponent" found in the FTM frame format. It
+      * applies to both: 1-sided RTT and 2-sided RTT. Valid
+      * values are 0 to 15 as defined in 802.11mc std.
+      * 0 means single shot
+      * The implication of this parameter on the maximum
+      * number of RTT results is the following:
+      * for 1-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst)
+      * for 2-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst - 1) */
+	t_u8 num_burst;
+    /** num of frames per burst.
+      * Minimum value = 1, Maximum value = 31
+      * For 2-sided this equals the number of FTM frames
+      * to be attempted in a single burst. This also
+      * equals the number of FTM frames that the
+      * initiator will request that the responder send
+      * in a single frame. */
+	t_u8 num_frames_per_burst;
+    /** number of retries for a failed RTT frame. Applies
+      * to 1-sided RTT only. Minimum value = 0, Maximum value = 3 */
+	t_u8 num_retries_per_rtt_frame;
+
+    /** following fields are only valid for 2-side RTT */
+    /** Maximum number of retries that the initiator can
+      * retry an FTMR frame.
+      * Minimum value = 0, Maximum value = 3 */
+	t_u8 num_retries_per_ftmr;
+    /** 1: request LCI, 0: do not request LCI */
+	t_u8 LCI_request;
+    /** 1: request LCR, 0: do not request LCR */
+	t_u8 LCR_request;
+    /** Applies to 1-sided and 2-sided RTT. Valid values will
+      * be 2-11 and 15 as specified by the 802.11mc std for
+      * the FTM parameter burst duration. In a multi-burst
+      * request, if responder overrides with larger value,
+      * the initiator will return failure. In a single-burst
+      * request if responder overrides with larger value,
+      * the initiator will sent TMR_STOP to terminate RTT
+      * at the end of the burst_duration it requested. */
+	t_u8 burst_duration;
+    /** RTT preamble to be used in the RTT frames */
+	t_u8 preamble;
+    /** RTT BW to be used in the RTT frames */
+	t_u8 bw;
+} mlan_rtt_config, *pmlan_rtt_config;
+
+/** RTT config params */
+typedef struct _mlan_rtt_config_params {
+	t_u8 rtt_config_num;
+	mlan_rtt_config rtt_config[MAX_RTT_CONFIG_NUM];
+} mlan_rtt_config_params;
+
+/** RTT cancel params */
+typedef struct _mlan_rtt_cancel_params {
+	t_u8 rtt_cancel_num;
+	t_u8 rtt_cancel[MAX_RTT_CONFIG_NUM][MLAN_MAC_ADDR_LENGTH];
+} mlan_rtt_cancel_params;
+
+/** RTT responder info */
+typedef struct _rtt_responder_info {
+	t_u8 channel;
+	Band_Config_t bandcfg;
+	t_u8 preamble;
+} rtt_responder_info;
+
+/** RTT responder enable configure */
+typedef struct _rtt_responder_encfg {
+	t_u8 channel;
+	Band_Config_t bandcfg;
+	t_u32 max_dur_sec;
+} rtt_responder_encfg;
+
+/** Define for mlan_rtt_responder.action */
+#define RTT_GET_RESPONDER_INFO       0
+#define RTT_SET_RESPONDER_ENABLE   1
+#define RTT_SET_RESPONDER_DISABLE  2
+#define RTT_SET_RESPONDER_LCI           3
+#define RTT_SET_RESPONDER_LCR          4
+
+/** RTT responder configure for MLAN_OID_MISC_RTT_RESPONDER_CFG */
+typedef struct _mlan_rtt_responder {
+	t_u8 action;
+	union {
+		rtt_responder_info info;
+		rtt_responder_encfg encfg;
+		wifi_lci_information lci;
+		wifi_lcr_information lcr;
+	} u;
+} mlan_rtt_responder;
+
+/** channel statictics */
+typedef struct _ChStat_t {
+    /** channle number */
+	t_u8 chan_num;
+    /** total network */
+	t_u16 total_networks;
+    /** busy duration */
+	t_u16 cca_busy_duration;
+} ChStat_t, *pChStat_t;
+
+#define MAX_CH_STATS    MAX_BG_CHANNEL
+/** Type definition of mlan_acs_scan */
+typedef struct _mlan_ds_misc_acs {
+    /** Best Channel Number */
+	t_u8 best_ch;
+    /** Scan channel gap */
+	t_u16 scan_chan_gap;
+    /** Channel Statistics Number */
+	t_u8 ch_stats_num;
+    /** Channel Statistics */
+	ChStat_t ch_stats[MAX_CH_STATS];
+} mlan_ds_misc_acs, *pmlan_ds_misc_acs;
+
+/** 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	/** 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;
+	/** Coalescing status for MLAN_OID_MISC_COALESCING_STATUS */
+		t_u16 coalescing_status;
+	/** 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;
+	/** Net monitor for MLAN_OID_MISC_NET_MONITOR */
+		mlan_ds_misc_net_monitor net_mon;
+	/** Tx data pause for MLAN_OID_MISC_TX_DATAPAUSE */
+		mlan_ds_misc_tx_datapause tx_datapause;
+	/** IP address configuration */
+		mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
+	/** MAC control for MLAN_OID_MISC_MAC_CONTROL */
+		t_u32 mac_ctrl;
+	/** MEF configuration for MLAN_OID_MISC_MEF_CFG */
+		mlan_ds_misc_mef_cfg mef_cfg;
+	/** CFP code for MLAN_OID_MISC_CFP_CODE */
+		mlan_ds_misc_cfp_code cfp_code;
+	/** Country code for MLAN_OID_MISC_COUNTRY_CODE */
+		mlan_ds_misc_country_code country_code;
+	/** Thermal reading for MLAN_OID_MISC_THERMAL */
+		t_u32 thermal;
+	/** Mgmt subtype mask for MLAN_OID_MISC_RX_MGMT_IND */
+		t_u32 mgmt_subtype_mask;
+	/** subscribe event for MLAN_OID_MISC_SUBSCRIBE_EVENT */
+		mlan_ds_subscribe_evt subscribe_event;
+#ifdef DEBUG_LEVEL1
+	/** Driver debug bit masks */
+		t_u32 drvdbg;
+#endif
+#ifdef STA_SUPPORT
+		ExtCap_t ext_cap;
+#endif
+		mlan_ds_misc_otp_user_data otp_user_data;
+	/** Tx control */
+		t_u32 tx_control;
+#if defined(STA_SUPPORT)
+		mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+	/** Multi-channel config for MLAN_OID_MISC_MULTI_CHAN_CFG */
+		mlan_ds_multi_chan_cfg multi_chan_cfg;
+	/** Multi-channel policy for MLAN_OID_MISC_MULTI_CHAN_POLICY */
+		t_u16 multi_chan_policy;
+	/** channel drcs time slicing config for MLAN_OID_MISC_DRCS_CFG */
+		mlan_ds_drcs_cfg drcs_cfg[2];
+#ifdef WIFI_DIRECT_SUPPORT
+		mlan_ds_wifi_direct_config p2p_config;
+#endif
+		mlan_ds_coalesce_cfg coalesce_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;
+	/** Sensor temperature */
+		mlan_ds_sensor_temp sensor_temp;
+	/** GTK rekey data */
+		mlan_ds_misc_gtk_rekey_data gtk_rekey;
+	/** Bandwidth Channel operation */
+		mlan_ds_bw_chan_oper bw_chan_oper;
+    /** Independent Reset Configuration */
+		mlan_ds_ind_rst_cfg ind_rst_cfg;
+    /** Roam offload */
+		mlan_ds_misc_roam_offload roam_offload;
+    /** misc tsf */
+		t_u64 misc_tsf;
+    /** Custom regulatory domain */
+		mlan_ds_custom_reg_domain custom_reg_domain;
+    /** cwmmode */
+		mlan_ds_cw_mode_ctrl cwmode;
+   /**  Tx/Rx per-packet control */
+		t_u8 txrx_pkt_ctrl;
+		mlan_ds_misc_robustcoex_params robustcoexparams;
+    /** config RTT for MLAN_OID_MISC_CONFIG_RTT */
+		mlan_rtt_config_params rtt_params;
+    /** cancel RTT for MLAN_OID_MISC_CANCEL_RTT */
+		mlan_rtt_cancel_params rtt_cancel;
+    /** config RTT responder for MLAN_OID_MISC_RTT_RESPONDER_CFG */
+		mlan_rtt_responder rtt_rsp_cfg;
+		mlan_ds_host_clock host_clock;
+    /** boot sleep enable or disable */
+		t_u16 boot_sleep;
+    /** ACS */
+		mlan_ds_misc_acs acs;
+	} param;
+} mlan_ds_misc_cfg, *pmlan_ds_misc_cfg;
+
+/** 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_sd8997/mlinux/moal_cfg80211.c b/wlan_sd8997/mlinux/moal_cfg80211.c
new file mode 100644
index 0000000..d284fb3
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_cfg80211.c
@@ -0,0 +1,3790 @@
+/** @file moal_cfg80211.c
+  *
+  * @brief This file contains the functions for CFG80211.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include    "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},
+};
+
+/********************************************************
+				Global Variables
+********************************************************/
+extern int cfg80211_wext;
+
+struct ieee80211_supported_band cfg80211_band_2ghz = {
+	.channels = cfg80211_channels_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,
+	.n_channels = ARRAY_SIZE(cfg80211_channels_5ghz),
+	.bitrates = cfg80211_rates + 4,
+	.n_bitrates = ARRAY_SIZE(cfg80211_rates) - 4,
+};
+
+#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
+
+/** gtk rekey offload mode */
+extern int gtk_rekey_offload;
+/********************************************************
+				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;
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+								      ,
+								      (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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+								      ,
+								      (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:
+	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;
+			memcpy(priv->uap_wep_key[key_index].key, key, key_len);
+			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 &&
+		    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) {
+			memcpy(sec->param.encrypt_key.key_material, key,
+			       key_len);
+			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) {
+				memcpy(sec->param.encrypt_key.pn, seq, PN_SIZE);
+				DBG_HEXDUMP(MCMD_D, "WAPI PN",
+					    sec->param.encrypt_key.pn, seq_len);
+			}
+		}
+		if (addr) {
+			memcpy(sec->param.encrypt_key.mac_addr, addr, ETH_ALEN);
+			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;
+		} else {
+			memcpy(sec->param.encrypt_key.mac_addr, bcast_addr,
+			       ETH_ALEN);
+			sec->param.encrypt_key.key_flags =
+				KEY_FLAG_GROUP_KEY | KEY_FLAG_SET_TX_KEY;
+		}
+		if (seq && seq_len) {
+			memcpy(sec->param.encrypt_key.pn, seq, seq_len);
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_RX_SEQ_VALID;
+		}
+
+		if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_AES_MCAST_IGTK;
+		}
+	} 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)
+			memcpy(sec->param.encrypt_key.mac_addr, addr, ETH_ALEN);
+	}
+
+	/* 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);
+		/* 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
+
+#if defined(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, channnel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		default:
+			PRINTM(MMSG,
+			       "wlan: %s Unknow P2P Action Frame, channel=%d, subtype=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0, subtype);
+			break;
+		}
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @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) {
+		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 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;
+	}
+
+	/* 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 && V14_FEATURE */
+
+/**
+ * @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 CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
+				  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 (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_MONITOR) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	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);
+
+#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 = 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 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
+
+	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_ADHOC:
+		bss->param.bss_mode = MLAN_BSS_MODE_IBSS;
+		priv->wdev->iftype = NL80211_IFTYPE_ADHOC;
+		PRINTM(MINFO, "Setting interface type to adhoc\n");
+		break;
+	case NL80211_IFTYPE_STATION:
+#if defined(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 && V14_FEATURE */
+#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;
+#if defined(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 && V14_FEATURE */
+	case NL80211_IFTYPE_AP:
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	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 (MLAN_STATUS_SUCCESS != status) {
+		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
+	mlan_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 == MLAN_FRAG_RTS_DISABLED)
+		rts_thr = MLAN_RTS_MAX_VALUE;
+	if (frag_thr == 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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+		      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;
+	}
+	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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+		      bool pairwise,
+#endif
+		      const t_u8 *mac_addr)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
+
+	ENTER();
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_del_key in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+			      , bool ucast, bool mcast
+#endif
+	)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
+	mlan_bss_info bss_info;
+
+	ENTER();
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+/**
+ *  @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)
+{
+	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 (NULL == req) {
+		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)
+			memcpy(&misc_cfg->param.gtk_rekey, gtk_rekey,
+			       sizeof(mlan_ds_misc_gtk_rekey_data));
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (MLAN_STATUS_SUCCESS != status)
+			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 (gtk_rekey_offload == GTK_REKEY_OFFLOAD_DISABLE) {
+		PRINTM(MMSG,
+		       "woal_cfg80211_set_rekey_data return: gtk_rekey_offload is DISABLE\n");
+		LEAVE();
+		return ret;
+	}
+
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (!fw_info.fw_supplicant_support) {
+		LEAVE();
+		return -1;
+	}
+
+	memcpy(rekey.kek, data->kek, MLAN_KEK_LEN);
+	memcpy(rekey.kck, data->kck, MLAN_KCK_LEN);
+	memcpy(rekey.replay_ctr, data->replay_ctr, MLAN_REPLAY_CTR_LEN);
+
+	memcpy(&priv->gtk_rekey_data, &rekey,
+	       sizeof(mlan_ds_misc_gtk_rekey_data));
+	if (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)) {
+		ret = -EFAULT;
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef STA_SUPPORT
+#endif
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+/**
+ * @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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+			  struct net_device *dev,
+#endif
+			  struct ieee80211_channel *chan,
+			  enum nl80211_channel_type channel_type)
+{
+	int ret = 0;
+	moal_private *priv = NULL;
+
+	ENTER();
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+/**
+ * @brief Functions check whether the pattern is supported
+ *
+ * @param pat             A pointer to cfg80211_pkt_pattern structure
+ * @param byte_seq        Byte sequence
+ * @param max_byte_seq    Maximum byte sequence
+ *
+ * @return                true -- success, otherwise false
+ */
+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) {
+				memcpy(byte_seq + valid_byte_cnt,
+				       &pat->pattern[j * 8 + k], 1);
+				valid_byte_cnt++;
+				if (dont_care_byte)
+					return false;
+			} else {
+				if (valid_byte_cnt)
+					dont_care_byte = true;
+			}
+
+			if (valid_byte_cnt > max_byte_seq)
+				return false;
+		}
+	}
+
+	byte_seq[max_byte_seq] = valid_byte_cnt;
+
+	return true;
+}
+
+/**
+ * @brief Get coalesce packet type
+ *
+ * @param byte_seq        Byte Sequence
+
+ * @return                0 -- success, otherwise fail
+ */
+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;
+}
+
+/**
+ * @brief Functions fills the coalesce rule information
+ *
+ * @param crule           A pointer to cfg80211_coalesce_rules structure
+ * @param mrule           A pointer to coalesce_rules structure
+ *
+ * @return                0-- success, otherwise fail
+ */
+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];
+		memcpy(param->operand_byte_stream, byte_seq,
+		       param->operand_len);
+		param->offset = crule->patterns[i].pkt_offset;
+		param++;
+
+		mrule->num_of_fields++;
+	}
+
+	if (!mrule->pkt_type) {
+		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
+ */
+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;
+
+	memcpy(&misc_cfg->param.coalesce_cfg, 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	/* Fill MCS rates */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	rate_cfg->bitmap_rates[2] = mask->control[band].ht_mcs[0];
+#else
+	rate_cfg->bitmap_rates[2] = mask->control[band].mcs[0];
+#endif
+#if defined(SD_8XXX)
+	if (priv->phandle->card_type ==
+#if defined(SD_8XXX)
+	    CARD_TYPE_SD8797
+#endif
+		)
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		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 (MLAN_STATUS_SUCCESS != status) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+/**
+ * @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 (MLAN_STATUS_SUCCESS != status) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	*tx_ant = radio->param.ant_cfg.tx_antenna;
+	*rx_ant = radio->param.ant_cfg.rx_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;
+	radio->param.ant_cfg.tx_antenna = tx_ant;
+	radio->param.ant_cfg.rx_antenna = rx_ant;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (MLAN_STATUS_SUCCESS != status) {
+		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
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+/**
+ * @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
+/**
+ * @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
+{
+#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);
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	t_u32 mgmt_subtype_mask = 0x0;
+	t_u32 last_mgmt_subtype_mask = priv->mgmt_subtype_mask;
+
+	ENTER();
+	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: mgmt_subtype_mask=0x%x last_mgmt_subtype_mask=0x%x\n",
+	       dev->name, 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. */
+		status = 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+/**
+ * @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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		      struct net_device *dev,
+#else
+		      struct wireless_dev *wdev,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		      struct cfg80211_mgmt_tx_params *params,
+#else
+		      struct ieee80211_channel *chan, bool offchan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+		      enum nl80211_channel_type channel_type,
+		      bool channel_type_valid,
+#endif
+		      unsigned int wait, const u8 *buf, size_t len,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+		      bool no_cck,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+		      bool dont_wait_for_ack,
+#endif
+#endif
+		      u64 * cookie)
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct net_device *dev = wdev->netdev;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	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;
+
+	ENTER();
+
+	if (buf == NULL || len == 0) {
+		PRINTM(MERROR, "woal_cfg80211_mgmt_tx() corrupt data\n");
+		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) &&
+	    ieee80211_is_probe_resp(((struct ieee80211_mgmt *)buf)->
+				    frame_control)) {
+		PRINTM(MIOCTL, "Skip send probe_resp in GO/UAP mode\n");
+		goto done;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	if (ieee80211_is_action(((struct ieee80211_mgmt *)buf)->frame_control)) {
+#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 ((priv->phandle->chan.center_freq !=
+			     chan->center_freq)
+				) {
+				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 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;
+		}
+#ifdef STA_CFG80211
+		/** cancel pending scan */
+		woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+#endif
+
+		duration =
+			(wait >
+			 MGMT_TX_DEFAULT_WAIT_TIME) ? wait :
+			MGMT_TX_DEFAULT_WAIT_TIME;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+		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 connnection fail */
+			woal_sched_timeout(2);
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+			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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+			priv->phandle->channel_type = channel_type;
+#endif
+			memcpy(&priv->phandle->chan, chan,
+			       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 CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+	*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;
+	/* Add pkt_type and tx_control */
+	memcpy(pmbuf->pbuf + pmbuf->data_offset, &pkt_type, sizeof(pkt_type));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type), &tx_control,
+	       sizeof(tx_control));
+	/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */
+#define PACKET_ADDR4_POS		(2 + 2 + 6 + 6 + 6 + 2)
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &packet_len,
+	       sizeof(packet_len));
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
+	       sizeof(packet_len), buf, PACKET_ADDR4_POS);
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
+	       sizeof(packet_len)
+	       + PACKET_ADDR4_POS, addr, MLAN_MAC_ADDR_LENGTH);
+	memcpy(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);
+
+	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)) {
+		pmbuf->flags = MLAN_BUF_FLAG_TX_STATUS;
+		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) {
+				memcpy(skb->data, buf, 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;
+				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,
+		 * becuase 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 (tx_info)
+				break;
+			else
+				woal_sched_timeout(30);
+		}
+
+		/* Notify the mgmt tx status */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		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 int
+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 *custom_ie = NULL;
+	t_u8 *pos = NULL;
+	t_u16 len = 0;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	custom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), GFP_KERNEL);
+	if (!custom_ie) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	custom_ie->type = TLV_TYPE_MGMT_IE;
+
+	pos = (t_u8 *)custom_ie->ie_data_list;
+	if (beacon_ies_data) {
+		len = sizeof(*beacon_ies_data) - MAX_IE_SIZE
+			+ beacon_ies_data->ie_length;
+		memcpy(pos, beacon_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+
+	if (proberesp_ies_data) {
+		len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE
+			+ proberesp_ies_data->ie_length;
+		memcpy(pos, proberesp_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+
+	if (assocresp_ies_data) {
+		len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE
+			+ assocresp_ies_data->ie_length;
+		memcpy(pos, assocresp_ies_data, len);
+		custom_ie->len += len;
+	}
+
+	if (probereq_ies_data) {
+		len = sizeof(*probereq_ies_data) - MAX_IE_SIZE
+			+ probereq_ies_data->ie_length;
+		memcpy(pos, probereq_ies_data, len);
+		pos += len;
+		custom_ie->len += len;
+	}
+	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;
+
+	memcpy(&misc->param.cust_ie, custom_ie, sizeof(mlan_ds_misc_custom_ie));
+
+	status = woal_request_ioctl(priv, ioctl_req, wait_option);
+	if (MLAN_STATUS_SUCCESS != status) {
+		ret = -EFAULT;
+		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;
+	}
+
+	if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL)
+		ret = -EFAULT;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	kfree(custom_ie);
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,14,0)
+/**
+ * @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;
+
+		memcpy(qos_map_ie.data, (t_u8 *)qos_map->dscp_exception,
+		       2 * qos_map->num_des);
+		memcpy(&qos_map_ie.data[2 * qos_map->num_des],
+		       (t_u8 *)qos_map->up, sizeof(qos_map->up));
+		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);
+
+		/* 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 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_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 */
+					memcpy(ie_out + out_len, pos,
+					       length + 2);
+					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) {
+					memcpy(ie_out + out_len, pos,
+					       length + 2);
+					out_len += length + 2;
+				}
+			} 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) {
+					memcpy(ie_out + out_len, pos,
+					       length + 2);
+					out_len += length + 2;
+				}
+			} else if (mask & IE_MASK_VENDOR) {
+				memcpy(ie_out + out_len, pos, length + 2);
+				out_len += length + 2;
+			}
+		}
+		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 specifc 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;
+	t_u8 id = 0;
+
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		id = *pos;
+		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 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_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;
+
+	/* 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;
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+		case WLAN_EID_ERP_INFO:
+		case HT_CAPABILITY:
+		case HT_OPERATION:
+		case VHT_CAPABILITY:
+		case VHT_OPERATION:
+		case REGULATORY_CLASS:
+		case OVERLAPBSSSCANPARAM:
+		case WAPI_IE:
+			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;
+			}
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			break;
+		default:
+			memcpy(ie_out + out_len, pos, length + 2);
+			out_len += length + 2;
+			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
+ */
+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 > sizeof(TLV_Generic_t)) {
+		tlv_type = ntohs(tlv->type);
+		tlv_len = ntohs(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,
+						       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 (MLAN_STATUS_SUCCESS !=
+		    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;
+	}
+
+	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;
+			assocresp_ies_data->ie_length = assocresp_ies_len;
+			pos = assocresp_ies_data->ie_buffer;
+			memcpy(pos, assocresp_ies, assocresp_ies_len);
+			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_SUCCESS !=
+		    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 (MLAN_CUSTOM_IE_AUTO_IDX_MASK == beacon_vendor_index)
+				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,
+						     IE_MASK_VENDOR);
+			DBG_HEXDUMP(MCMD_D, "beacon vendor IE",
+				    beacon_ies_data->ie_buffer,
+				    beacon_ies_data->ie_length);
+		} else if (beacon_vendor_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+			/* 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 &&
+		     (beacon_vendor_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK))) {
+			if (MLAN_STATUS_SUCCESS !=
+			    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,
+						       IE_MASK_WPS | IE_MASK_WFD
+						       | IE_MASK_P2P |
+						       IE_MASK_VENDOR,
+						       proberesp_ies,
+						       proberesp_ies_len);
+			DBG_HEXDUMP(MCMD_D, "beacon ie",
+				    beacon_ies_data->ie_buffer,
+				    beacon_ies_data->ie_length);
+		} 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, 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 &&
+		     (proberesp_p2p_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK))) {
+			if (MLAN_STATUS_SUCCESS !=
+			    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 (MLAN_CUSTOM_IE_AUTO_IDX_MASK == proberesp_index)
+				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,
+						       IE_MASK_P2P |
+						       IE_MASK_VENDOR, NULL, 0);
+			DBG_HEXDUMP(MCMD_D, "proberesp ie",
+				    proberesp_ies_data->ie_buffer,
+				    proberesp_ies_data->ie_length);
+		} 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 (MLAN_CUSTOM_IE_AUTO_IDX_MASK == assocresp_index)
+				assocresp_ies_data->mgmt_subtype_mask |=
+					MLAN_CUSTOM_IE_NEW_MASK;
+			assocresp_ies_data->ie_length = assocresp_ies_len;
+			pos = assocresp_ies_data->ie_buffer;
+			memcpy(pos, assocresp_ies, assocresp_ies_len);
+			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;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+			if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
+				/* filter out P2P/WFD ie */
+				probereq_ies_data->ie_length =
+					woal_filter_beacon_ies(priv,
+							       probereq_ies,
+							       probereq_ies_len,
+							       probereq_ies_data->
+							       ie_buffer,
+							       IE_MASK_P2P |
+							       IE_MASK_WFD,
+							       NULL, 0);
+			} else {
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+				probereq_ies_data->ie_length = probereq_ies_len;
+				pos = probereq_ies_data->ie_buffer;
+				memcpy(pos, probereq_ies, probereq_ies_len);
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+			}
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+			DBG_HEXDUMP(MCMD_D, "probereq ie",
+				    probereq_ies_data->ie_buffer,
+				    probereq_ies_data->ie_length);
+		} 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 (MLAN_STATUS_SUCCESS !=
+	    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 informations
+ *  @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)
+		memcpy(ht_info->mcs.rx_mask, mcs_set,
+		       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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+/**
+ *  @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 (MLAN_STATUS_SUCCESS != status) {
+		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 = (t_u16)cfg_11ac->param.vht_cfg.vht_rx_mcs;
+	vht_cap->vht_mcs.rx_highest =
+		(t_u16)cfg_11ac->param.vht_cfg.vht_rx_max_rate;
+	vht_cap->vht_mcs.tx_mcs_map = (t_u16)cfg_11ac->param.vht_cfg.vht_tx_mcs;
+	vht_cap->vht_mcs.tx_highest =
+		(t_u16)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();
+	return;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ * @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();
+	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
+
+/**
+ * @brief Get second channel offset
+ *
+ * @param chan             channel num
+ * @return                second channel offset
+ */
+t_u8
+woal_get_second_channel_offset(int chan)
+{
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+
+	switch (chan) {
+	case 36:
+	case 44:
+	case 52:
+	case 60:
+	case 100:
+	case 108:
+	case 116:
+	case 124:
+	case 132:
+	case 140:
+	case 149:
+	case 157:
+		chan2Offset = SEC_CHAN_ABOVE;
+		break;
+	case 40:
+	case 48:
+	case 56:
+	case 64:
+	case 104:
+	case 112:
+	case 120:
+	case 128:
+	case 136:
+	case 144:
+	case 153:
+	case 161:
+		chan2Offset = SEC_CHAN_BELOW;
+		break;
+	case 165:
+		/* Special Case: 20Mhz-only Channel */
+		chan2Offset = SEC_CHAN_NONE;
+		break;
+	}
+	return chan2Offset;
+}
diff --git a/wlan_sd8997/mlinux/moal_cfg80211.h b/wlan_sd8997/mlinux/moal_cfg80211.h
new file mode 100644
index 0000000..bf5a5e5
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_cfg80211.h
@@ -0,0 +1,446 @@
+/** @file moal_cfg80211.h
+  *
+  * @brief This file contains the CFG80211 specific defines.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _MOAL_CFG80211_H_
+#define _MOAL_CFG80211_H_
+
+#include    "moal_main.h"
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR
+#define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+#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
+
+/* define for custom ie operation */
+#define MLAN_CUSTOM_IE_AUTO_IDX_MASK    0xffff
+#define MLAN_CUSTOM_IE_DELETE_MASK      0x0
+#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 MRVL_PKT_TYPE_MGMT_FRAME 0xE5
+
+/**
+ * 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 */
+moal_private *woal_get_scan_interface(moal_handle *handle);
+#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 CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
+				      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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+			  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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+			  bool pairwise,
+#endif
+			  const t_u8 *mac_addr);
+#ifdef STA_SUPPORT
+#endif
+
+int woal_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
+				   struct net_device *dev,
+				   const u8 *peer,
+				   const struct cfg80211_bitrate_mask *mask);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+	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,
+					     mlan_ssid_bssid *ssid_bssid,
+					     t_u8 wait_option);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+int woal_cfg80211_set_channel(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 34)
+			      struct net_device *dev,
+#endif
+			      struct ieee80211_channel *chan,
+			      enum nl80211_channel_type channel_type);
+#endif
+
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
+				       struct net_device *netdev,
+				       t_u8 key_index);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+int woal_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
+				 struct cfg80211_gtk_rekey_data *data);
+#endif
+
+void woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+				       struct wireless_dev *wdev,
+#else
+				       struct net_device *dev,
+#endif
+				       t_u16 frame_type, bool reg);
+
+int woal_cfg80211_mgmt_tx(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+			  struct wireless_dev *wdev,
+#else
+			  struct net_device *dev,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			  struct cfg80211_mgmt_tx_params *params,
+#else
+			  struct ieee80211_channel *chan, bool offchan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+			  enum nl80211_channel_type channel_type,
+			  bool channel_type_valid,
+#endif
+			  unsigned int wait, const u8 *buf, size_t len,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+			  bool no_cck,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+			  bool dont_wait_for_ack,
+#endif
+#endif
+			  u64 * cookie);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+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;
+
+#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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+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);
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+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 CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+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)
+/* 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);
+
+void woal_remove_virtual_interface(moal_handle *handle);
+
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+
+/** Define for remain on channel duration timer */
+#define MAX_REMAIN_ON_CHANNEL_DURATION      (1000)
+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 nl80211_channel_type channel_type,
+					t_u32 duration);
+
+#ifdef UAP_CFG80211
+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);
+
+int woal_uap_cfg80211_dump_station(struct wiphy *wiphy,
+				   struct net_device *dev, int idx,
+				   t_u8 *mac, struct station_info *sinfo);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+int woal_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
+			     struct bss_parameters *params);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+int woal_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *dev,
+			      const struct cfg80211_acl_data *params);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+int woal_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev,
+				 struct ieee80211_txq_params *params);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+int woal_cfg80211_set_coalesce(struct wiphy *wiphy,
+			       struct cfg80211_coalesce *coalesce);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+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 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, 12, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+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_cac_timer_func(void *context);
+void woal_csa_work_queue(struct work_struct *work);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+void woal_cfg80211_notify_uap_channel(moal_private *priv,
+				      chan_band_info * pchan_info);
+#endif
+#endif /* UAP_CFG80211 */
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+mlan_status woal_chandef_create(moal_private *priv,
+				struct cfg80211_chan_def *chandef,
+				chan_band_info * pchan_info);
+#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 CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+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);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#define REGULATORY_CFG_LEN  (NL80211_MAX_SUPP_REG_RULES << 1)
+enum marvell_channel_flags {
+	MARVELL_CHANNEL_PASSIVE = BIT(0),
+	MARVELL_CHANNEL_DFS = BIT(1),
+	MARVELL_CHANNEL_NOHT40 = BIT(2),
+	MARVELL_CHANNEL_NOHT80 = BIT(3),
+	MARVELL_CHANNEL_DISABLED = BIT(7),
+};
+#endif
+
+t_u8 woal_get_second_channel_offset(int chan);
+
+#endif /* _MOAL_CFG80211_H_ */
diff --git a/wlan_sd8997/mlinux/moal_cfgvendor.c b/wlan_sd8997/mlinux/moal_cfgvendor.c
new file mode 100644
index 0000000..deb753c
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_cfgvendor.c
@@ -0,0 +1,5520 @@
+/** @file moal_cfgvendor.c
+  *
+  * @brief This file contains the functions for CFG80211 vendor.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include    "moal_cfgvendor.h"
+#include    "moal_cfg80211.h"
+
+/********************************************************
+				Local Variables
+********************************************************/
+
+/********************************************************
+				Global Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+extern int roamoffload_in_hs;
+/********************************************************
+				Local Functions
+********************************************************/
+
+/********************************************************
+				Global Functions
+********************************************************/
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+/**marvell vendor command and event*/
+#define MRVL_VENDOR_ID  0x005043
+/** vendor events */
+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_rssi_monitor,},	/*event_id 0x1501 */
+	{.vendor_id = MRVL_VENDOR_ID,.subcmd = event_set_key_mgmt_offload,},	/*event_id 0x10001 */
+	{.vendor_id = MRVL_VENDOR_ID,.subcmd = event_fw_roam_success,},	/*event_id 0x10002 */
+	{.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,},
+	{.vendor_id = MRVL_VENDOR_ID,.subcmd = event_nan_cb,},
+	/**add vendor event here*/
+	{.vendor_id = MRVL_VENDOR_ID,.subcmd = event_rtt_result,},	/*event_id ??? */
+};
+
+/**
+ * @brief get the event id of the events array
+ *
+ * @param event     vendor event
+ *
+ * @return    index of events array
+ */
+int
+woal_get_event_id(int event)
+{
+	int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(vendor_events); i++) {
+		if (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(IN moal_private *priv,
+			   IN int event, IN t_u8 *data, IN 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL, 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);
+	memcpy(pos, data, len);
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief send vendor event to kernel
+ *
+ * @param priv       A pointer to moal_private
+ * @param event    vendor event
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+struct sk_buff *
+woal_cfg80211_alloc_vendor_event(IN moal_private *priv,
+				 IN int event, IN int len)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int event_id = 0;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "Not find this event %d \n", event_id);
+		goto done;
+	}
+	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);
+		goto done;
+	}
+
+	/**allocate skb*/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL, 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");
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return skb;
+}
+
+/**
+ * @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();
+	return;
+}
+
+/**
+ * @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));
+	memcpy(pos, &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];
+	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 woal_cfg80211_subcmd_get_valid_channels\n");
+
+	err = nla_parse(tb, ATTR_WIFI_MAX, data, len, NULL
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err) {
+		PRINTM(MERROR, "%s: nla_parse fail\n", __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+
+	if (!tb[ATTR_CHANNELS_BAND]) {
+		PRINTM(MERROR, "%s: null attr: tb[ATTR_GET_CH]=%p\n",
+		       __FUNCTION__, 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", __FUNCTION__, 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;
+	}
+
+	nla_put_u32(skb, ATTR_NUM_CHANNELS, nchannel);
+	nla_put(skb, ATTR_CHANNEL_LIST, nchannel * sizeof(ch_out[0]), ch_out);
+	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();
+	memcpy(drv_version, &priv->phandle->driver_version,
+	       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)
+		memcpy(pos, pos + 3, strlen(pos) - 3);
+
+	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->firmware_dump_file) {
+		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];
+	char path_name[64];
+	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(path_name, 0, sizeof(path_name));
+	woal_create_dump_dir(handle, path_name, sizeof(path_name));
+	PRINTM(MMSG, "driver dump path name is %s\n", path_name);
+	woal_dump_drv_info(handle, path_name);
+	memset(driver_dump_file, 0, sizeof(driver_dump_file));
+	sprintf(driver_dump_file, "%s/%s", path_name, "file_drv_info");
+	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;
+	}
+	nla_put_string(skb, ATTR_DRV_DUMP_PATH, driver_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 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;
+	t_u32 reply_len = 0;
+	int ret = 0;
+	t_u32 supp_feature_set = 0;
+	ENTER();
+
+	supp_feature_set = WIFI_FEATURE_INFRA
+#if defined(UAP_SUPPORT) && defined(STA_SUPPORT)
+		| WIFI_FEATURE_AP_STA
+#endif
+		| WIFI_FEATURE_LINK_LAYER_STATS
+		| WIFI_FEATURE_LOGGER
+		| WIFI_FEATURE_RSSI_MONITOR
+		| WIFI_FEATURE_CONFIG_NDO | WIFI_FEATURE_SCAN_RAND;
+
+	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;
+	}
+	nla_put_u32(skb, ATTR_FEATURE_SET, supp_feature_set);
+	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 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(sizeof(country) - 1, nla_len(iter)));
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			return ret;
+		}
+	}
+
+	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;
+	}
+	nla_put_u32(skb, ATTR_WIFI_LOGGER_FEATURE_SET, supp_feature_set);
+	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 (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",
+			       __FUNCTION__, status->name, status->ring_id,
+			       status->ring_buffer_byte_size,
+			       status->written_bytes, status->written_records,
+			       status->read_bytes);
+			break;
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ * @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;
+	}
+
+	/* shoud 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);
+		memcpy(&status[ring_cnt++], &ring_status,
+		       sizeof(wifi_ring_buffer_status));
+	}
+
+	nla_put_u32(skb, ATTR_NUM_RINGS, ring_cnt);
+	nla_put(skb, ATTR_RING_BUFFER_STATUS,
+		sizeof(wifi_ring_buffer_status) * ring_cnt, status);
+
+	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 (!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",
+	       __FUNCTION__, log_level, time_intval, threshold);
+
+	ring_buffer = (wifi_ring_buffer *) priv->rings[ring_id];
+	if (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 {
+		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->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 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);
+
+	ENTER();
+
+	if (!entry->entry_size) {
+		entry = (wifi_ring_buffer_entry *) ring->ring_buf;
+		LEAVE();
+		return ENTRY_LENGTH(entry);
+	}
+
+	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 avail_len, r_len = 0;
+	unsigned long flags;
+	wifi_ring_buffer *ring;
+	wifi_ring_buffer_entry *hdr;
+
+	ENTER();
+
+	ring = (wifi_ring_buffer *) priv->rings[ring_id];
+	if (ring->state != RING_ACTIVE) {
+		PRINTM(MERROR, "Ring is not active!\n");
+		goto done;
+	}
+
+	spin_lock_irqsave(&ring->lock, flags);
+
+	/* get a fresh pending length */
+	avail_len = READ_AVAIL_SPACE(ring->wp, ring->rp, ring->ring_size);
+	while (avail_len > 0 && buf_len > 0) {
+		hdr = woal_get_ring_entry(ring, ring->rp);
+		memcpy(data, hdr, ENTRY_LENGTH(hdr));
+		r_len += ENTRY_LENGTH(hdr);
+		/* update read pointer */
+		ring->rp = woal_get_ring_next_entry(ring, ring->rp);
+		data += ENTRY_LENGTH(hdr);
+		avail_len -= ENTRY_LENGTH(hdr);
+		buf_len -= ENTRY_LENGTH(hdr);
+		ring->ctrl.read_bytes += ENTRY_LENGTH(hdr);
+		PRINTM(MINFO, "%s read_bytes  %d\n", __FUNCTION__,
+		       ring->ctrl.read_bytes);
+	}
+	spin_unlock_irqrestore(&ring->lock, flags);
+
+done:
+	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
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_ring_buffer_data_vendor_event(IN moal_private *priv, IN int ring_id,
+				   IN t_u8 *data, IN int len)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int event_id = 0;
+	int ret = 0;
+	wifi_ring_buffer_status ring_status;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "priv is null \n");
+		ret = -EINVAL;
+		goto done;
+	}
+	wiphy = priv->wdev->wiphy;
+	PRINTM(MEVENT, "woal_ring_buffer_data_vendor_event ring_id:%d\n",
+	       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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL,
+					  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;
+	}
+
+	woal_get_ring_status(priv, ring_id, &ring_status);
+
+	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, const 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);
+
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ * @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;
+	wifi_ring_buffer_entry *hdr;
+	t_s32 buflen, rlen;
+
+	ENTER();
+
+	woal_get_ring_status(priv, ringid, &ring_status);
+	PRINTM(MINFO, "woal_ring_poll_worker write %d, read %d, size %d\n",
+	       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;
+	else if (ring_status.written_bytes < ring_status.read_bytes)
+		buflen = ring_status.ring_buffer_byte_size +
+			ring_status.written_bytes - ring_status.read_bytes;
+	else {
+		PRINTM(MERROR, "No new records\n");
+		goto exit;
+	}
+
+	buf = kmalloc(buflen, GFP_KERNEL);
+	if (!buf) {
+		PRINTM(MERROR, "%s failed to allocate read buf\n",
+		       __FUNCTION__);
+		LEAVE();
+		return;
+	}
+	rlen = woal_ring_pull_data(priv, ringid, buf, buflen);
+	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));
+	}
+	kfree(buf);
+
+	if (!ring_info->interval) {
+		LEAVE();
+		return;
+	}
+	woal_get_ring_status(priv, ring_info->ring_id, &ring_status);
+
+exit:
+	if (ring_info->interval) {
+		/* retrigger the work at same interval */
+		if (READ_AVAIL_SPACE
+		    (ring_info->wp, ring_info->rp, ring_info->ring_size) <= 0)
+			schedule_delayed_work(d_work, ring_info->interval);
+		else
+			schedule_delayed_work(d_work, 0);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @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->state != RING_ACTIVE) {
+		PRINTM(MERROR, "Ring is not active\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	spin_lock_irqsave(&ring->lock, flags);
+
+	w_len = ENTRY_LENGTH(hdr);
+	/* prep the space */
+	do {
+		if (ring->rp == ring->wp)
+			break;
+		if (ring->rp < ring->wp) {
+			if (ring->ring_size - ring->wp == w_len) {
+				if (ring->rp == 0)
+					ring->rp =
+						woal_get_ring_next_entry(ring,
+									 ring->
+									 rp);
+				break;
+			} else if (ring->ring_size - ring->wp < w_len) {
+				if (ring->rp == 0)
+					ring->rp =
+						woal_get_ring_next_entry(ring,
+									 ring->
+									 rp);
+				ring->wp = 0;
+				continue;
+			} else {
+				break;
+			}
+		}
+		if (ring->rp > ring->wp) {
+			if (ring->rp - ring->wp <= w_len) {
+				ring->rp =
+					woal_get_ring_next_entry(ring,
+								 ring->rp);
+				if (ring->rp >= ring->ring_size) {
+					PRINTM(MINFO,
+					       "log size exceed ring size\n");
+					ring->rp = 0;
+					break;
+				} else
+					continue;
+			} else {
+				break;
+			}
+		}
+	} while (1);
+
+	w_entry = (wifi_ring_buffer_entry *) (ring->ring_buf + ring->wp);
+	/* header */
+	memcpy(w_entry, hdr, RING_ENTRY_SIZE);
+	/* payload */
+	memcpy((char *)w_entry + RING_ENTRY_SIZE, data, 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(MINFO, "%s : written_records %d, written_bytes %d\n",
+	       __FUNCTION__, ring->ctrl.written_records,
+	       ring->ctrl.written_bytes);
+
+	/* if the current pending size is bigger than threshold */
+	if (ring->threshold > 0 &&
+	    (READ_AVAIL_SPACE(ring->wp, ring->rp, ring->ring_size) >=
+	     ring->threshold) && ring->interval != 0)
+		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));
+	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");
+	}
+	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);
+	memcpy(ring_buff->name, name, MIN(strlen(name), RING_NAME_MAX));
+	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);
+
+	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 - 1; i++) {
+		ring_buff = (wifi_ring_buffer *) priv->rings[i];
+		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->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;
+			if (pbss_desc->oui) {
+				tlv = (tlv_log *) pos;
+				tlv->tag = WIFI_TAG_VENDOR_SPECIFIC;
+				tlv->length = MLAN_MAC_ADDR_LENGTH / 2;
+				memcpy(tlv->value, pbss_desc->oui, tlv->length);
+				msg_hdr.entry_size +=
+					tlv->length + TLV_LOG_HEADER_LEN;
+				pos = pos + tlv->length + TLV_LOG_HEADER_LEN;
+			}
+			if (pbss_desc->bssid) {
+				tlv = (tlv_log *) pos;
+				tlv->tag = WIFI_TAG_BSSID;
+				tlv->length = sizeof(pbss_desc->bssid);
+				memcpy(tlv->value, pbss_desc->bssid,
+				       sizeof(pbss_desc->bssid));
+				msg_hdr.entry_size +=
+					tlv->length + TLV_LOG_HEADER_LEN;
+				pos = pos + tlv->length + TLV_LOG_HEADER_LEN;
+			}
+			if (pbss_desc->ssid) {
+				tlv = (tlv_log *) pos;
+				tlv->tag = WIFI_TAG_SSID;
+				tlv->length = strlen(pbss_desc->ssid);
+				memcpy(tlv->value, pbss_desc->ssid,
+				       tlv->length);
+				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);
+				memcpy(tlv->value, &pbss_desc->rssi,
+				       tlv->length);
+				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);
+				memcpy(tlv->value, &pbss_desc->channel,
+				       sizeof(pbss_desc->channel));
+				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);
+			memcpy(tlv->value, &status_code, sizeof(status_code));
+			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);
+			memcpy(tlv->value, &reason_code, sizeof(reason_code));
+			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(IN moal_private *priv,
+			      IN 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL,
+					  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 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;
+
+	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;
+	}
+
+	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(IN moal_private *priv,
+			      IN packet_fate_packet_type pkt_type, IN t_u8 fate,
+			      IN frame_type payload_type, IN t_u32 drv_ts_usec,
+			      IN t_u32 fw_ts_usec, IN t_u8 *data, IN 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL,
+					  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(pkt_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(MCMD_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;
+	}
+
+	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);
+	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
+accept_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 memory[MEMORY_ITEMS] = { };
+	/* Register values. */
+	t_u32 registers[2] = { };
+	/* Count of instructions remaining to execute. This is done to ensure an
+	 * 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_remaining = 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_packet_offs;
+	t_u32 imm = 0;
+	int32_t signed_imm = 0;
+	t_u32 offs = 0;
+	t_u32 i;
+	t_u32 load_size;
+
+/* Is offset within program bounds? */
+#define IN_PROGRAM_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < program_len)
+/* Is offset within packet bounds? */
+#define IN_PACKET_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < packet_len)
+/* Verify an internal condition and accept packet if it fails. */
+#define ASSERT_RETURN(c) if (!(c)) return PASS_PACKET
+/* Accept packet if not within program bounds */
+#define ASSERT_IN_PROGRAM_BOUNDS(p) ASSERT_RETURN(IN_PROGRAM_BOUNDS(p))
+/* Accept packet if not within packet bounds */
+#define ASSERT_IN_PACKET_BOUNDS(p) ASSERT_RETURN(IN_PACKET_BOUNDS(p))
+/* Accept packet if not within program or not ahead of program counter */
+#define ASSERT_FORWARD_IN_PROGRAM(p) ASSERT_RETURN(IN_PROGRAM_BOUNDS(p) && (p) >= pc)
+
+	/* Fill in pre-filled memory slot values. */
+	memory[MEMORY_OFFSET_PACKET_SIZE] = packet_len;
+	memory[MEMORY_OFFSET_FILTER_AGE] = filter_age;
+	ASSERT_IN_PACKET_BOUNDS(APF_FRAME_HEADER_SIZE);
+
+	/* Only populate if IP version is IPv4. */
+	if ((packet[APF_FRAME_HEADER_SIZE] & 0xf0) == 0x40) {
+		memory[MEMORY_OFFSET_IPV4_HEADER_SIZE] =
+			(packet[APF_FRAME_HEADER_SIZE] & 15) * 4;
+	}
+
+	do {
+		if (pc == program_len) {
+			return PASS_PACKET;
+		} else if (pc == (program_len + 1)) {
+			return DROP_PACKET;
+		}
+		ASSERT_IN_PROGRAM_BOUNDS(pc);
+		bytecode = program[pc++];
+		opcode = EXTRACT_OPCODE(bytecode);
+		reg_num = EXTRACT_REGISTER(bytecode);
+
+		/* All instructions have immediate fields, so load them now. */
+		len_field = EXTRACT_IMM_LENGTH(bytecode);
+		imm = 0;
+		signed_imm = 0;
+
+#define REG (registers[reg_num])
+#define OTHER_REG (registers[reg_num ^ 1])
+
+		if (len_field != 0) {
+			imm_len = 1 << (len_field - 1);
+			ASSERT_FORWARD_IN_PROGRAM(pc + imm_len - 1);
+			for (i = 0; i < imm_len; i++)
+				imm = (imm << 8) | program[pc++];
+			/* Sign extend imm into signed_imm. */
+			signed_imm = imm << ((4 - imm_len) * 8);
+			signed_imm >>= (4 - imm_len) * 8;
+		}
+		switch (opcode) {
+		case LDB_OPCODE:
+		case LDH_OPCODE:
+		case LDW_OPCODE:
+		case LDBX_OPCODE:
+		case LDHX_OPCODE:
+		case LDWX_OPCODE:{
+				offs = imm;
+				if (opcode >= LDBX_OPCODE) {
+					/* Note: this can overflow and actually decrease offs. */
+					offs += registers[1];
+				}
+				ASSERT_IN_PACKET_BOUNDS(offs);
+				switch (opcode) {
+				case LDB_OPCODE:
+				case LDBX_OPCODE:
+					load_size = 1;
+					break;
+				case LDH_OPCODE:
+				case LDHX_OPCODE:
+					load_size = 2;
+					break;
+				case LDW_OPCODE:
+				case 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_IN_PACKET_BOUNDS(end_offs);
+				val = 0;
+				while (load_size--)
+					val = (val << 8) | packet[offs++];
+				REG = val;
+				break;
+			}
+		case JMP_OPCODE:
+			/* This can jump backwards. Infinite looping prevented by instructions_remaining. */
+			pc += imm;
+			break;
+		case JEQ_OPCODE:
+		case JNE_OPCODE:
+		case JGT_OPCODE:
+		case JLT_OPCODE:
+		case JSET_OPCODE:
+		case JNEBS_OPCODE:{
+				/* Load second immediate field. */
+				t_u32 cmp_imm = 0;
+				if (reg_num == 1) {
+					cmp_imm = registers[1];
+				} else if (len_field != 0) {
+					t_u32 cmp_imm_len =
+						1 << (len_field - 1);
+					ASSERT_FORWARD_IN_PROGRAM(pc +
+								  cmp_imm_len -
+								  1);
+					for (i = 0; i < cmp_imm_len; i++)
+						cmp_imm =
+							(cmp_imm << 8) |
+							program[pc++];
+				}
+				switch (opcode) {
+				case JEQ_OPCODE:
+					if (registers[0] == cmp_imm)
+						pc += imm;
+					break;
+				case JNE_OPCODE:
+					if (registers[0] != cmp_imm)
+						pc += imm;
+					break;
+				case JGT_OPCODE:
+					if (registers[0] > cmp_imm)
+						pc += imm;
+					break;
+				case JLT_OPCODE:
+					if (registers[0] < cmp_imm)
+						pc += imm;
+					break;
+				case JSET_OPCODE:
+					if (registers[0] & cmp_imm)
+						pc += imm;
+					break;
+				case 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_IN_PROGRAM(pc +
+									  cmp_imm
+									  - 1);
+						ASSERT_IN_PACKET_BOUNDS(REG);
+						last_packet_offs =
+							REG + cmp_imm - 1;
+						ASSERT_RETURN(last_packet_offs
+							      >= REG);
+						ASSERT_IN_PACKET_BOUNDS
+							(last_packet_offs);
+						if (memcmp
+						    (program + pc, packet + REG,
+						     cmp_imm))
+							pc += imm;
+						/* skip past comparison bytes */
+						pc += cmp_imm;
+						break;
+					}
+				}
+				break;
+			}
+		case ADD_OPCODE:
+			registers[0] += reg_num ? registers[1] : imm;
+			break;
+		case MUL_OPCODE:
+			registers[0] *= reg_num ? registers[1] : imm;
+			break;
+		case DIV_OPCODE:{
+				const t_u32 div_operand =
+					reg_num ? registers[1] : imm;
+				ASSERT_RETURN(div_operand);
+				registers[0] /= div_operand;
+				break;
+			}
+		case AND_OPCODE:
+			registers[0] &= reg_num ? registers[1] : imm;
+			break;
+		case OR_OPCODE:
+			registers[0] |= reg_num ? registers[1] : imm;
+			break;
+		case SH_OPCODE:{
+				const int32_t shift_val =
+					reg_num ? (int32_t) registers[1] :
+					signed_imm;
+				if (shift_val > 0)
+					registers[0] <<= shift_val;
+				else
+					registers[0] >>= -shift_val;
+				break;
+			}
+		case LI_OPCODE:
+			REG = signed_imm;
+			break;
+		case 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 LDM_EXT_OPCODE == 0
+				   ENFORCE_UNSIGNED(imm) &&
+#else
+				   imm >= LDM_EXT_OPCODE &&
+#endif
+				   imm < (LDM_EXT_OPCODE + MEMORY_ITEMS)) {
+				REG = memory[imm - LDM_EXT_OPCODE];
+			} else if (imm >= STM_EXT_OPCODE &&
+				   imm < (STM_EXT_OPCODE + MEMORY_ITEMS)) {
+				memory[imm - STM_EXT_OPCODE] = REG;
+			} else
+				switch (imm) {
+				case NOT_EXT_OPCODE:
+					REG = ~REG;
+					break;
+				case NEG_EXT_OPCODE:
+					REG = -REG;
+					break;
+				case SWAP_EXT_OPCODE:{
+						t_u32 tmp = REG;
+						REG = OTHER_REG;
+						OTHER_REG = tmp;
+						break;
+					}
+				case MOV_EXT_OPCODE:
+					REG = OTHER_REG;
+					break;
+					/* Unknown extended opcode */
+				default:
+					/* Bail out */
+					return PASS_PACKET;
+				}
+			break;
+			/* Unknown opcode */
+		default:
+			/* Bail out */
+			return PASS_PACKET;
+		}
+	} while (instructions_remaining--);
+	return PASS_PACKET;
+}
+
+/**
+ * @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_PACKET;
+	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(MCMD_D, "packet_filter_program",
+		    pkt_filter->packet_filter_program,
+		    pkt_filter->packet_filter_len);
+	DBG_HEXDUMP(MCMD_D, "packet_filter_data", data, len);
+	spin_lock_irqsave(&pkt_filter->lock, flags);
+	ret = accept_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 send vendor event to kernel
+ *
+ * @param priv     A pointer to moal_private
+ * @param cmd      nan_cmd
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_nan_vendor_event(IN moal_private *priv, nan_cmd cmd)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int ret = 0;
+	int event_id = 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, "woal_nan_worker\n");
+	event_id = woal_get_event_id(event_nan_cb);
+	if (event_max == event_id) {
+		PRINTM(MERROR, "Not find this event %d \n", event_id);
+		ret = -EINVAL;
+		goto done;
+	}
+
+/**allocate skb*/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL, sizeof(nan_cmd),
+					  event_id, GFP_ATOMIC);
+#else
+	skb = cfg80211_vendor_event_alloc(wiphy, sizeof(nan_cmd), event_id,
+					  GFP_ATOMIC);
+#endif
+
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor event\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	nla_put(skb, ATTR_NAN_FAKE, sizeof(NanHeader_Ext), &cmd.nan_header_ext);
+
+	if (cmd.indicate_enable) {
+		nla_put_u32(skb, ATTR_NAN_IND, cmd.indicate_type);
+	}
+
+	PRINTM(MCMND, "woal_nan_vendor_event %d, %d, %d,%d\n",
+	       cmd.nan_header_ext.nan_header.MsgId,
+	       cmd.nan_header_ext.nan_header.transactionId, cmd.indicate_enable,
+	       cmd.indicate_type);
+
+    /**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief worker to send vendor event
+ *
+ * @param work       A pointer to work_struct struct
+ *
+ * @return void
+ */
+void
+woal_nan_worker(struct work_struct *work)
+{
+	struct delayed_work *d_work = to_delayed_work(work);
+	nan_cb *nan = container_of(d_work, nan_cb, response_work);
+	moal_private *priv = nan->priv;
+	nan_cmd cmd;
+	int ret;
+	ENTER();
+
+	PRINTM(MCMND, "fifo len: %u\n", kfifo_len(&nan->cmd_fifo));
+
+	ret = kfifo_out_peek(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+	PRINTM(MCMND, "fifo ret: %u\n", ret);
+
+	if (ret) {
+		kfifo_out(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+	} else {
+		PRINTM(MERROR, "not enough element:\n");
+		goto done;
+	}
+
+	woal_nan_vendor_event(priv, cmd);
+
+	ret = kfifo_out_peek(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+
+	if (ret)
+		schedule_delayed_work(&nan->response_work, 0);
+
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief init nan in moal_private
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_init_nan(moal_private *priv)
+{
+	int ret = 0;
+	nan_cb *nan;
+	moal_handle *phandle = priv->phandle;
+	ENTER();
+
+	nan = vmalloc(sizeof(nan_cb));
+	if (!unlikely(nan)) {
+		PRINTM(MERROR, "WiFi Logger: packet_filter alloc failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (!unlikely(phandle)) {
+		PRINTM(MERROR, "WiFi Logger: phandle is null\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	memset(nan, 0, sizeof(nan_cb));
+	INIT_DELAYED_WORK(&nan->response_work, woal_nan_worker);
+	nan->priv = priv;
+
+	ret = kfifo_alloc(&nan->cmd_fifo, CMD_FIFO_SIZE * sizeof(nan_cmd),
+			  GFP_KERNEL);
+	if (ret) {
+		PRINTM(MERROR, "error kfifo_alloc\n");
+		goto done;
+	}
+
+	priv->nan_cb = nan;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief deinit nan in moal_private
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_deinit_nan(moal_private *priv)
+{
+	int ret = 0;
+	nan_cb *nan = NULL;
+
+	ENTER();
+
+	nan = priv->nan_cb;
+
+	if (!unlikely(nan)) {
+		goto done;
+	}
+
+	cancel_delayed_work_sync(&nan->response_work);
+
+	kfifo_free(&nan->cmd_fifo);
+
+	vfree(nan);
+	priv->nan_cb = NULL;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to enable nan
+ *
+ * @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
+nan_handler(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;
+	t_u32 reply_len = 0;
+	int ret = 0;
+	int rem, type;
+
+	const struct nlattr *iter;
+	nan_cb *nan = priv->nan_cb;
+	nan_cmd cmd;
+	t_u32 indicate_number_total = 0;
+	t_u32 indicate_array[MAX_INDICATE_ARRAY_SIZE] = { 0 };
+	int i = 0;
+
+	ENTER();
+
+	memset(&cmd, 0, sizeof(nan_cmd));
+    /** 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 (!unlikely(nan)) {
+		PRINTM(MERROR, "WiFi hal: nan not init\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case ATTR_NAN_FAKE:
+			memcpy(&cmd, nla_data(iter), sizeof(NanHeader));
+			PRINTM(MCMND, "ATTR_NAN_FAKE %d, %d\n",
+			       cmd.nan_header_ext.nan_header.MsgId,
+			       cmd.nan_header_ext.nan_header.transactionId);
+			break;
+		case ATTR_NAN_IND:
+			indicate_array[indicate_number_total] =
+				nla_get_u32(iter);
+			indicate_number_total++;
+			PRINTM(MCMND, "ATTR_NAN_IND %d, %d\n",
+			       indicate_array[indicate_number_total - 1],
+			       indicate_number_total);
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	cmd.indicate_enable = 0;
+	kfifo_in(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+	PRINTM(MCMND, "fifo len: %u\n", kfifo_len(&nan->cmd_fifo));
+
+	for (i = 0; i < MAX_INDICATE_ARRAY_SIZE && i < indicate_number_total;
+	     i++) {
+		cmd.indicate_enable = 1;
+		cmd.indicate_type = indicate_array[i];
+		kfifo_in(&nan->cmd_fifo, &cmd, sizeof(nan_cmd));
+		PRINTM(MCMND, "fifo len: %u\n", kfifo_len(&nan->cmd_fifo));
+		DBG_HEXDUMP(MCMD_D, "nan_cmd", (t_u8 *)&cmd, sizeof(nan_cmd));
+	}
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+
+	schedule_delayed_work(&nan->response_work, 0);
+
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to enable nan
+ *
+ * @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_nan_enable_req(struct wiphy *wiphy,
+				    struct wireless_dev *wdev, const void *data,
+				    int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to disable nan
+ *
+ * @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_nan_disable_req(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to nan publish req
+ *
+ * @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_nan_publish_req(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to cancel nan publish
+ *
+ * @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_nan_publish_cancel(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to nan subscribe req
+ *
+ * @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_nan_subscribe_req(struct wiphy *wiphy,
+				       struct wireless_dev *wdev,
+				       const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to cancel nan subscribe
+ *
+ * @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_nan_subscribe_cancel(struct wiphy *wiphy,
+					  struct wireless_dev *wdev,
+					  const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to trasmit followup
+ *
+ * @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_nan_trasmit_followup(struct wiphy *wiphy,
+					  struct wireless_dev *wdev,
+					  const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to req nan stats
+ *
+ * @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_nan_stats_req(struct wiphy *wiphy,
+				   struct wireless_dev *wdev, const void *data,
+				   int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to config nan
+ *
+ * @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_nan_config_req(struct wiphy *wiphy,
+				    struct wireless_dev *wdev, const void *data,
+				    int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to nan tca req
+ *
+ * @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_nan_tca_req(struct wiphy *wiphy, struct wireless_dev *wdev,
+				 const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to beacon sdf payload
+ *
+ * @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_nan_beacon_sdf_payload(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get nan 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_nan_get_version(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get nan 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_nan_get_capability(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to data if create
+ *
+ * @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_nan_data_if_create(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to data if delete
+ *
+ * @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_nan_data_if_delete(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to data req initor
+ *
+ * @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_nan_data_req_initor(struct wiphy *wiphy,
+					 struct wireless_dev *wdev,
+					 const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to data indication resp
+ *
+ * @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_nan_data_indi_resp(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to date end
+ *
+ * @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_nan_data_end(struct wiphy *wiphy,
+				  struct wireless_dev *wdev, const void *data,
+				  int len)
+{
+	int ret = 0;
+	ENTER();
+
+	ret = nan_handler(wiphy, wdev, data, len);
+
+	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);
+	woal_init_nan(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);
+	woal_deinit_nan(priv);
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief vendor command to get correlated HW and System time
+ *
+ * @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_correlated_time(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_misc_cfg *misc = NULL;
+	mlan_ds_get_correlated_time *info = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int err = -1;
+	int length = 0;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		PRINTM(MERROR, "Could not allocate mlan ioctl request!\n");
+		return -ENOMEM;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+	misc->sub_command = MLAN_OID_MISC_GET_CORRELATED_TIME;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "get correleted time fail\n");
+		goto done;
+	}
+
+	length = sizeof(mlan_ds_get_correlated_time);
+	info = (mlan_ds_get_correlated_time *) (&misc->param.host_clock);
+
+	DBG_HEXDUMP(MCMD_D, "get_correlated_time", (t_u8 *)info, length);
+
+	/* 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;
+	}
+
+	/* Push the data to the skb */
+	nla_put_nohdr(skb, length, info);
+
+	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 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_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;
+	mlan_ds_get_stats stats;
+
+	/* 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;
+	}
+
+	/* Get Log 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");
+		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);
+
+	iface_stat =
+		(wifi_iface_stat *) (info->param.link_statistic +
+				     sizeof(num_radio) + radio_stat_len);
+	iface_stat_len = sizeof(wifi_iface_stat);
+	/* Fill some fileds */
+	iface_stat->beacon_rx = stats.bcn_rcv_cnt;
+
+	/* could get peer info with seperate 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);
+		goto done;
+	}
+	PRINTM(MCMD_D, "num_radio=%d\n", num_radio);
+	DBG_HEXDUMP(MCMD_D, "radio_stat", (t_u8 *)radio_stat, radio_stat_len);
+	DBG_HEXDUMP(MCMD_D, "iface_stat", (t_u8 *)iface_stat, iface_stat_len);
+
+	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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err)
+		return err;
+
+	if (!tb[ATTR_LL_STATS_MPDU_SIZE_THRESHOLD] ||
+	    !tb[ATTR_LL_STATS_AGGRSSIVE_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_AGGRSSIVE_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 */
+	memcpy(info->param.link_statistic, &ll_params, sizeof(ll_params));
+
+	/* 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, 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, "enable 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);
+		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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, 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);
+	memcpy(pos, data, 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 key_mgmt_set_key
+ *
+ * @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_set_roaming_offload_key(struct wiphy *wiphy,
+					     struct wireless_dev *wdev,
+					     const void *data, int data_len)
+{
+	moal_private *priv;
+	struct net_device *dev;
+	struct sk_buff *skb = NULL;
+	t_u8 *pos = (t_u8 *)data;
+	int ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (data)
+		DBG_HEXDUMP(MCMD_D, "Vendor pmk", (t_u8 *)data, data_len);
+
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	dev = wdev->netdev;
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+	if (!priv) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (data_len > MLAN_MAX_KEY_LENGTH) {
+		memcpy(&priv->pmk.pmk_r0, pos, MLAN_MAX_KEY_LENGTH);
+		pos += MLAN_MAX_KEY_LENGTH;
+		memcpy(&priv->pmk.pmk_r0_name, pos,
+		       MIN(MLAN_MAX_PMKR0_NAME_LENGTH,
+			   data_len - MLAN_MAX_KEY_LENGTH));
+	} else {
+		memcpy(&priv->pmk.pmk, data,
+		       MIN(MLAN_MAX_KEY_LENGTH, data_len));
+	}
+	priv->pmk_saved = MTRUE;
+
+    /** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, data_len);
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	pos = skb_put(skb, data_len);
+	memcpy(pos, data, data_len);
+	ret = cfg80211_vendor_cmd_reply(skb);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to supplicant to update AP info
+ *
+ * @param priv     A pointer to moal_private
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_roam_ap_info(IN moal_private *priv, IN t_u8 *data, IN int len)
+{
+	struct wiphy *wiphy = priv->wdev->wiphy;
+	struct sk_buff *skb = NULL;
+	int ret = MLAN_STATUS_SUCCESS;
+	key_info *pkey = NULL;
+	apinfo *pinfo = NULL;
+	apinfo *req_tlv = NULL;
+	MrvlIEtypesHeader_t *tlv = NULL;
+	t_u16 tlv_type = 0, tlv_len = 0, tlv_buf_left = 0;
+	int event_id = 0;
+	t_u8 authorized = 1;
+
+	ENTER();
+
+	event_id = woal_get_event_id(event_fw_roam_success);
+	if (event_max == event_id) {
+		PRINTM(MERROR, "Not find this event %d \n", event_id);
+		ret = 1;
+		LEAVE();
+		return ret;
+	}
+	/**allocate skb*/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	skb = cfg80211_vendor_event_alloc(wiphy, NULL, 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 = 1;
+		LEAVE();
+		return ret;
+	}
+
+	nla_put(skb, MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
+		MLAN_MAC_ADDR_LENGTH, (t_u8 *)data);
+	nla_put(skb, MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
+		sizeof(authorized), &authorized);
+	tlv = (MrvlIEtypesHeader_t *)(data + MLAN_MAC_ADDR_LENGTH);
+	tlv_buf_left = len - MLAN_MAC_ADDR_LENGTH;
+	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = woal_le16_to_cpu(tlv->type);
+		tlv_len = woal_le16_to_cpu(tlv->len);
+
+		if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+			PRINTM(MERROR,
+			       "Error processing firmware roam success TLVs, bytes left < TLV length\n");
+			break;
+		}
+
+		switch (tlv_type) {
+		case TLV_TYPE_APINFO:
+			pinfo = (apinfo *) tlv;
+			nla_put(skb, MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
+				pinfo->header.len, pinfo->rsp_ie);
+			break;
+
+		case TLV_TYPE_ASSOC_REQ_IE:
+			req_tlv = (apinfo *) tlv;
+			nla_put(skb, MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
+				req_tlv->header.len, req_tlv->rsp_ie);
+			break;
+
+		case TLV_TYPE_KEYINFO:
+			pkey = (key_info *) tlv;
+			nla_put(skb,
+				MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
+				MLAN_REPLAY_CTR_LEN, pkey->key.replay_ctr);
+			nla_put(skb, MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
+				MLAN_KCK_LEN, pkey->key.kck);
+			nla_put(skb, MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
+				MLAN_KEK_LEN, pkey->key.kek);
+			break;
+		default:
+			break;
+		}
+		tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @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;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	t_u8 enable = 0;
+#endif
+#endif
+
+	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);
+	ret = woal_enable_fw_roaming(priv, fw_roaming_enable);
+	/* 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);
+	}
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (!fw_roaming_enable) {
+		woal_cfg80211_vendor_event(priv, event_set_key_mgmt_offload,
+					   &enable, sizeof(enable));
+	}
+#endif
+#endif
+
+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;
+	woal_roam_offload_cfg *roam_offload_cfg = NULL;
+	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:
+			memcpy((t_u8 *)&blacklist, nla_data(iter),
+			       sizeof(wifi_bssid_params));
+			break;
+		case MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONFIG_SSID:
+			memcpy((t_u8 *)&whitelist, nla_data(iter),
+			       sizeof(wifi_ssid_params));
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	if (roamoffload_in_hs) {
+		/*save blacklist and whitelist in driver */
+		priv->phandle->fw_roam_params.black_list.ap_num =
+			blacklist.num_bssid;
+		memcpy((t_u8 *)priv->phandle->fw_roam_params.black_list.ap_mac,
+		       (t_u8 *)blacklist.mac_addr,
+		       sizeof(wifi_bssid_params) - sizeof(blacklist.num_bssid));
+		priv->phandle->fw_roam_params.ssid_list.ssid_num =
+			whitelist.num_ssid;
+		memcpy((t_u8 *)priv->phandle->fw_roam_params.ssid_list.ssids,
+		       (t_u8 *)whitelist.whitelist_ssid,
+		       sizeof(wifi_ssid_params) - sizeof(whitelist.num_ssid));
+	} else {
+		roam_offload_cfg =
+			(woal_roam_offload_cfg *)
+			kmalloc(sizeof(woal_roam_offload_cfg), GFP_KERNEL);
+		if (!roam_offload_cfg) {
+			PRINTM(MERROR, "kmalloc failed!\n");
+			ret = -ENOMEM;
+			goto done;
+		}
+		/*download parameters directly to fw */
+		memset((char *)roam_offload_cfg, 0,
+		       sizeof(woal_roam_offload_cfg));
+		roam_offload_cfg->black_list.ap_num = blacklist.num_bssid;
+		memcpy((t_u8 *)&roam_offload_cfg->black_list.ap_mac,
+		       (t_u8 *)blacklist.mac_addr,
+		       sizeof(wifi_bssid_params) - sizeof(blacklist.num_bssid));
+		roam_offload_cfg->ssid_list.ssid_num = whitelist.num_ssid;
+		memcpy((t_u8 *)&roam_offload_cfg->ssid_list.ssids,
+		       (t_u8 *)whitelist.whitelist_ssid,
+		       sizeof(wifi_ssid_params) - sizeof(whitelist.num_ssid));
+		woal_config_fw_roaming(priv, ROAM_OFFLOAD_PARAM_CFG,
+				       roam_offload_cfg);
+	}
+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;
+	mlan_ds_11k_cfg *pcfg_11k = 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+		  , NULL
+#endif
+		);
+	if (!tb_vendor[ATTR_ND_OFFLOAD_CONTROL]) {
+		PRINTM(MINFO, "%s: ATTR_ND_OFFLOAD not found\n", __FUNCTION__);
+		ret = -EFAULT;
+		goto done;
+	}
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11k_cfg));
+	if (req == NULL) {
+		PRINTM(MERROR, "Could not allocate mlan ioctl request!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	/* Fill request buffer */
+	pcfg_11k = (mlan_ds_11k_cfg *) req->pbuf;
+	pcfg_11k->sub_command = MLAN_OID_11K_CFG_ENABLE;
+	req->req_id = MLAN_IOCTL_11K_CFG;
+	req->action = MLAN_ACT_SET;
+	if (nla_get_u32(tb_vendor[ATTR_ND_OFFLOAD_CONTROL]))
+		pcfg_11k->param.enable_11k = MTRUE;
+	else
+		pcfg_11k->param.enable_11k = MFALSE;
+	PRINTM(MCMND, "11k enable = %d\n", pcfg_11k->param.enable_11k);
+	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 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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+		  , NULL
+#endif
+		);
+	if (!tb_vendor[ATTR_SCAN_MAC_OUI_SET]) {
+		PRINTM(MINFO, "%s: ATTR_SCAN_MAC_OUI_SET not found\n",
+		       __FUNCTION__);
+		ret = -EFAULT;
+		goto done;
+	}
+	memcpy(mac_oui, nla_data(tb_vendor[ATTR_SCAN_MAC_OUI_SET]), 3);
+	memcpy(priv->random_mac, priv->current_addr, 6);
+	memcpy(priv->random_mac, mac_oui, 3);
+	PRINTM(MCMND, "random_mac is " FULL_MACSTR "\n",
+	       FULL_MAC2STR(priv->random_mac));
+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;
+	int ret = 1;
+
+	ENTER();
+
+	/** 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;
+}
+
+/**
+ * @brief vendor command to get rtt 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_rtt_get_capa(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);
+	moal_handle *handle = priv->phandle;
+	struct sk_buff *skb = NULL;
+	int err = 0;
+
+	ENTER();
+	PRINTM(MCMND, "CfgVendor: cfg80211_subcmd_rtt_get_capa\n");
+
+	DBG_HEXDUMP(MCMD_D, "input data", (t_u8 *)data, len);
+
+	/* Alloc the SKB for vendor_event */
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+						  nla_total_size(sizeof
+								 (handle->
+								  rtt_capa)) +
+						  VENDOR_REPLY_OVERHEAD);
+	if (unlikely(!skb)) {
+		PRINTM(MERROR, "skb alloc failed in %s\n", __FUNCTION__);
+		goto done;
+	}
+
+	/* Put the attribute to the skb */
+	nla_put(skb, ATTR_RTT_CAPA, sizeof(handle->rtt_capa),
+		&(handle->rtt_capa));
+
+	PRINTM(MCMND, "NL80211_CMD_VENDOR=0x%x\n", NL80211_CMD_VENDOR);
+	PRINTM(MCMND, "NL80211_ATTR_WIPHY=0x%x\n", NL80211_ATTR_WIPHY);
+	PRINTM(MCMND, "NL80211_ATTR_VENDOR_ID=0x%x\n", NL80211_ATTR_VENDOR_ID);
+	PRINTM(MCMND, "NL80211_ATTR_VENDOR_SUBCMD=0x%x\n",
+	       NL80211_ATTR_VENDOR_SUBCMD);
+	PRINTM(MCMND, "NL80211_ATTR_VENDOR_DATA=0x%x\n",
+	       NL80211_ATTR_VENDOR_DATA);
+	PRINTM(MCMND, "NL80211_ATTR_VENDOR_EVENTS=0x%x\n",
+	       NL80211_ATTR_VENDOR_EVENTS);
+
+	DBG_HEXDUMP(MCMD_D, "output data skb->head", (t_u8 *)skb->head, 50);
+	DBG_HEXDUMP(MCMD_D, "output data skb->data", (t_u8 *)skb->data, 50);
+	err = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(err))
+		PRINTM(MERROR, "Vendor Command reply failed err:%d \n", err);
+
+done:
+	LEAVE();
+	return err;
+}
+
+static void
+woal_dump_rtt_params(wifi_rtt_config_params_t * rtt_params)
+{
+	int i = 0;
+
+	PRINTM(MMSG, "===== Start DUMP RTT Params =====\n");
+	PRINTM(MMSG, "rtt_config_num=%d\n\n", rtt_params->rtt_config_num);
+
+	for (i = 0; i < rtt_params->rtt_config_num; i++) {
+		PRINTM(MMSG, "----------[%d]----------\n", i);
+		PRINTM(MMSG, "rtt_config[%d].addr=" MACSTR "\n", i,
+		       MAC2STR(rtt_params->rtt_config[i].addr));
+		PRINTM(MMSG, "rtt_config[%d].type=%d\n", i,
+		       rtt_params->rtt_config[i].type);
+		PRINTM(MMSG, "rtt_config[%d].peer=%d\n", i,
+		       rtt_params->rtt_config[i].peer);
+		PRINTM(MMSG, "rtt_config[%d].channel=[%d %d %d %d]\n", i,
+		       rtt_params->rtt_config[i].channel.width,
+		       rtt_params->rtt_config[i].channel.center_freq,
+		       rtt_params->rtt_config[i].channel.center_freq0,
+		       rtt_params->rtt_config[i].channel.center_freq1);
+		PRINTM(MMSG, "rtt_config[%d].burst_period=%d\n", i,
+		       rtt_params->rtt_config[i].burst_period);
+		PRINTM(MMSG, "rtt_config[%d].num_burst=%d\n", i,
+		       rtt_params->rtt_config[i].num_burst);
+		PRINTM(MMSG, "rtt_config[%d].num_frames_per_burst=%d\n", i,
+		       rtt_params->rtt_config[i].num_frames_per_burst);
+		PRINTM(MMSG, "rtt_config[%d].num_retries_per_rtt_frame=%d\n", i,
+		       rtt_params->rtt_config[i].num_retries_per_rtt_frame);
+		PRINTM(MMSG, "rtt_config[%d].num_retries_per_ftmr=%d\n", i,
+		       rtt_params->rtt_config[i].num_retries_per_ftmr);
+		PRINTM(MMSG, "rtt_config[%d].LCI_request=%d\n", i,
+		       rtt_params->rtt_config[i].LCI_request);
+		PRINTM(MMSG, "rtt_config[%d].LCR_request=%d\n", i,
+		       rtt_params->rtt_config[i].LCR_request);
+		PRINTM(MMSG, "rtt_config[%d].burst_duration=%d\n", i,
+		       rtt_params->rtt_config[i].burst_duration);
+		PRINTM(MMSG, "rtt_config[%d].preamble=%d\n", i,
+		       rtt_params->rtt_config[i].preamble);
+		PRINTM(MMSG, "rtt_config[%d].bw=%d\n", i,
+		       rtt_params->rtt_config[i].bw);
+		PRINTM(MMSG, "\n");
+	}
+}
+
+/**
+ * @brief vendor command to request rtt range
+ *
+ * @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_rtt_range_request(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);
+	moal_handle *handle = priv->phandle;
+	struct nlattr *tb[ATTR_RTT_MAX];
+	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 };
+	t_u8 rtt_config_num = 0;
+	wifi_rtt_config *rtt_config = NULL;
+	t_u8 i = 0, j = 0;
+	wifi_rtt_config_params_t rtt_params;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err = 0;
+
+	ENTER();
+	PRINTM(MCMND, "Enter woal_cfg80211_subcmd_rtt_range_request()\n");
+
+	err = nla_parse(tb, ATTR_RTT_MAX, data, len, NULL
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err) {
+		err = -EFAULT;
+		PRINTM(MERROR, "%s: nla_parse fail\n", __FUNCTION__);
+		goto done;
+	}
+
+	if (!tb[ATTR_RTT_TARGET_NUM] || !tb[ATTR_RTT_TARGET_CONFIG]) {
+		PRINTM(MERROR,
+		       "%s: null attr: tb[ATTR_RTT_TARGET_NUM]=%p tb[ATTR_RTT_TARGET_CONFIG]=%p\n",
+		       __FUNCTION__, tb[ATTR_RTT_TARGET_NUM],
+		       tb[ATTR_RTT_TARGET_CONFIG]);
+		err = -EINVAL;
+		goto done;
+	}
+
+	rtt_config_num = nla_get_u8(tb[ATTR_RTT_TARGET_NUM]);
+
+	if ((rtt_config_num == 0) ||
+	    ((handle->rtt_params.rtt_config_num + rtt_config_num) >
+	     MAX_RTT_CONFIG_NUM)) {
+		PRINTM(MERROR, "%s: invalid num=%d  num in handle=%d  MAX=%d\n",
+		       __FUNCTION__, rtt_config_num,
+		       handle->rtt_params.rtt_config_num, MAX_RTT_CONFIG_NUM);
+		err = -EINVAL;
+		goto done;
+	}
+	if (nla_len(tb[ATTR_RTT_TARGET_CONFIG]) !=
+	    sizeof(rtt_params.rtt_config[0]) * rtt_config_num) {
+		PRINTM(MERROR, "%s: invalid %d(total) != %d(num) * %lu(each)\n",
+		       __FUNCTION__, nla_len(tb[ATTR_RTT_TARGET_CONFIG]),
+		       rtt_config_num, sizeof(rtt_params.rtt_config[0]));
+		err = -EINVAL;
+		goto done;
+	}
+
+	rtt_config = (wifi_rtt_config *) nla_data(tb[ATTR_RTT_TARGET_CONFIG]);
+	memset(&rtt_params, 0, sizeof(rtt_params));
+	/** Strip the zero mac config */
+	for (i = 0; i < rtt_config_num; i++) {
+		if (!memcmp
+		    (rtt_config[i].addr, zero_mac, sizeof(rtt_config[i].addr)))
+			continue;
+		else {
+			memcpy(&rtt_params.
+			       rtt_config[rtt_params.rtt_config_num],
+			       &rtt_config[i],
+			       sizeof(rtt_params.
+				      rtt_config[rtt_params.rtt_config_num]));
+			rtt_params.rtt_config_num++;
+		}
+	}
+	if (!rtt_params.rtt_config_num) {
+		PRINTM(MERROR, "%s: no valid mac addr\n", __FUNCTION__);
+		goto done;
+	}
+	woal_dump_rtt_params(&rtt_params);
+
+	ret = woal_config_rtt(priv, MOAL_IOCTL_WAIT, &rtt_params);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: woal_config_rtt() failed\n", __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+
+	for (i = 0; i < rtt_params.rtt_config_num; i++) {
+		for (j = 0; j < handle->rtt_params.rtt_config_num; j++) {
+			if (!memcmp
+			    (handle->rtt_params.rtt_config[j].addr,
+			     rtt_params.rtt_config[i].addr,
+			     sizeof(handle->rtt_params.rtt_config[j].addr)))
+				break;
+		}
+		memcpy(&(handle->rtt_params.rtt_config[j]),
+		       &(rtt_params.rtt_config[i]),
+		       sizeof(handle->rtt_params.rtt_config[j]));
+		if (j == handle->rtt_params.rtt_config_num)
+			handle->rtt_params.rtt_config_num++;
+	}
+
+	woal_dump_rtt_params(&(handle->rtt_params));
+
+done:
+	LEAVE();
+	return err;
+}
+
+/**
+ * @brief vendor command to cancel rtt range
+ *
+ * @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_rtt_range_cancel(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);
+	moal_handle *handle = priv->phandle;
+	t_u8 rtt_config_num = handle->rtt_params.rtt_config_num;
+	struct nlattr *tb[ATTR_RTT_MAX];
+	t_u32 target_num = 0;
+	t_u8 addr[MAX_RTT_CONFIG_NUM][MLAN_MAC_ADDR_LENGTH];
+	int i = 0, j = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err = 0;
+
+	ENTER();
+	PRINTM(MCMND, "Enter woal_cfg80211_subcmd_rtt_range_cancel()\n");
+
+	err = nla_parse(tb, ATTR_RTT_MAX, data, len, NULL
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err) {
+		PRINTM(MERROR, "%s: nla_parse fail\n", __FUNCTION__);
+		goto done;
+	}
+
+	if (!tb[ATTR_RTT_TARGET_NUM] || !tb[ATTR_RTT_TARGET_ADDR]) {
+		PRINTM(MERROR,
+		       "%s: null attr: tb[ATTR_RTT_TARGET_NUM]=%p tb[ATTR_RTT_TARGET_ADDR]=%p\n",
+		       __FUNCTION__, tb[ATTR_RTT_TARGET_NUM],
+		       tb[ATTR_RTT_TARGET_ADDR]);
+		err = -EINVAL;
+		goto done;
+	}
+
+	target_num = nla_get_u8(tb[ATTR_RTT_TARGET_NUM]);
+
+	if ((target_num <= 0 || target_num > MAX_RTT_CONFIG_NUM) ||
+	    (nla_len(tb[ATTR_RTT_TARGET_ADDR]) !=
+	     sizeof(t_u8) * MLAN_MAC_ADDR_LENGTH * target_num)) {
+		PRINTM(MERROR, "%s: Check if %din[1-%d] or %d*%lu=%d\n",
+		       __FUNCTION__, target_num, MAX_RTT_CONFIG_NUM, target_num,
+		       sizeof(t_u8) * MLAN_MAC_ADDR_LENGTH,
+		       nla_len(tb[ATTR_RTT_TARGET_ADDR]));
+		err = -EINVAL;
+		goto done;
+	}
+	woal_dump_rtt_params(&(handle->rtt_params));
+
+	memcpy(addr, nla_data(tb[ATTR_RTT_TARGET_ADDR]),
+	       nla_len(tb[ATTR_RTT_TARGET_ADDR]));
+
+	for (i = 0; i < target_num; i++)
+		PRINTM(MMSG, "cancel[%d].addr=" MACSTR "\n", i,
+		       MAC2STR(addr[i]));
+
+	for (i = 0; i < target_num; i++) {
+		for (j = 0; j < handle->rtt_params.rtt_config_num; j++) {
+			if (!memcmp
+			    (addr[i], handle->rtt_params.rtt_config[j].addr,
+			     sizeof(addr[0]))) {
+				memset(&(handle->rtt_params.rtt_config[j]),
+				       0x00,
+				       sizeof(handle->rtt_params.
+					      rtt_config[0]));
+				if ((j + 1) < handle->rtt_params.rtt_config_num) {
+					memmove(&
+						(handle->rtt_params.
+						 rtt_config[j]),
+						&(handle->rtt_params.
+						  rtt_config[j + 1]),
+						sizeof(handle->rtt_params.
+						       rtt_config[0]) *
+						(handle->rtt_params.
+						 rtt_config_num - (j + 1)));
+					memset(&
+					       (handle->rtt_params.
+						rtt_config[handle->rtt_params.
+							   rtt_config_num - 1]),
+					       0x00,
+					       sizeof(handle->rtt_params.
+						      rtt_config[0]));
+				}
+				handle->rtt_params.rtt_config_num--;
+				continue;
+			}
+		}
+	}
+
+	if (handle->rtt_params.rtt_config_num >= rtt_config_num) {
+		PRINTM(MERROR, "%s: No matched mac addr in rtt_config\n",
+		       __FUNCTION__);
+		goto done;
+	}
+
+	ret = woal_cancel_rtt(priv, MOAL_IOCTL_WAIT, target_num, addr);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: woal_cancel_rtt() failed\n", __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+	woal_dump_rtt_params(&(handle->rtt_params));
+
+done:
+	LEAVE();
+	return err;
+}
+
+/**
+ * @brief vendor event to report RTT Results
+ *
+ * @param priv     A pointer to moal_private
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      mlan_status
+ */
+mlan_status
+woal_cfg80211_event_rtt_result(IN moal_private *priv, IN t_u8 *data, IN int len)
+{
+	//moal_handle *handle = priv->phandle;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *pos = data;
+	t_u32 event_left_len = len;
+	struct sk_buff *skb = NULL;
+	t_u32 vdr_event_len = 0;
+	t_u32 complete = 0;
+	wifi_rtt_result_element *rtt_result_elem = NULL;
+	t_u32 num_results = 0;
+
+	ENTER();
+
+	PRINTM(MEVENT, "Enter woal_cfg80211_event_rtt_result()\n");
+
+	vdr_event_len = nla_total_size(sizeof(complete)) +
+		nla_total_size(sizeof(num_results)) +
+		nla_total_size(len) + NLA_ALIGNTO * num_results
+		+ VENDOR_REPLY_OVERHEAD;
+	PRINTM(MEVENT, "vdr_event_len = %d\n", vdr_event_len);
+	skb = woal_cfg80211_alloc_vendor_event(priv, event_rtt_result,
+					       vdr_event_len);
+	if (!skb)
+		goto done;
+
+	complete = *pos;
+	nla_put(skb, ATTR_RTT_RESULT_COMPLETE, sizeof(complete), &complete);
+	pos++;
+	event_left_len--;
+
+	while (event_left_len > sizeof(wifi_rtt_result_element)) {
+		rtt_result_elem = (wifi_rtt_result_element *) pos;
+
+		nla_put(skb, ATTR_RTT_RESULT_FULL, rtt_result_elem->len,
+			rtt_result_elem->data);
+		num_results++;
+
+		pos += sizeof(*rtt_result_elem) + rtt_result_elem->len;
+		event_left_len -=
+			sizeof(*rtt_result_elem) + rtt_result_elem->len;
+	}
+
+	nla_put(skb, ATTR_RTT_RESULT_NUM, sizeof(num_results), &num_results);
+
+	DBG_HEXDUMP(MEVT_D, "output data skb->data", (t_u8 *)skb->data,
+		    skb->len);
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_KERNEL);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get rtt responder info
+ *
+ * @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_rtt_get_responder_info(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);
+	mlan_rtt_responder rtt_rsp_cfg;
+	struct sk_buff *skb = NULL;
+	wifi_rtt_responder rtt_rsp;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err = 0;
+
+	ENTER();
+	PRINTM(MCMND, "Enter woal_cfg80211_subcmd_rtt_get_responder_info()\n");
+
+	memset(&rtt_rsp_cfg, 0x00, sizeof(rtt_rsp_cfg));
+	rtt_rsp_cfg.action = RTT_GET_RESPONDER_INFO;
+	ret = woal_rtt_responder_cfg(priv, MOAL_IOCTL_WAIT, &rtt_rsp_cfg);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: woal_rtt_responder_cfg() failed\n",
+		       __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+	PRINTM(MCMD_D,
+	       "mlan_rtt_responder from FW: channel=%d bandcfg=%d %d %d %d preamble=%d\n",
+	       rtt_rsp_cfg.u.info.channel, rtt_rsp_cfg.u.info.bandcfg.chanBand,
+	       rtt_rsp_cfg.u.info.bandcfg.chanWidth,
+	       rtt_rsp_cfg.u.info.bandcfg.chan2Offset,
+	       rtt_rsp_cfg.u.info.bandcfg.scanMode,
+	       rtt_rsp_cfg.u.info.preamble);
+
+	memset(&rtt_rsp, 0x00, sizeof(rtt_rsp));
+	woal_bandcfg_to_channel_info(priv, &(rtt_rsp_cfg.u.info.bandcfg),
+				     rtt_rsp_cfg.u.info.channel,
+				     &(rtt_rsp.channel));
+	rtt_rsp.preamble = rtt_rsp_cfg.u.info.preamble;
+	PRINTM(MCMD_D, "wifi_rtt_responder report to HAL:\n");
+	PRINTM(MCMD_D,
+	       "channel: width=%d center_freq=%d center_freq0=%d center_freq1=%d\n",
+	       rtt_rsp.channel.width, rtt_rsp.channel.center_freq,
+	       rtt_rsp.channel.center_freq0, rtt_rsp.channel.center_freq1);
+	PRINTM(MCMD_D, "preamble=%d\n", rtt_rsp.preamble);
+
+	/* Alloc the SKB for vendor_event */
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+						  nla_total_size(sizeof
+								 (rtt_rsp)) +
+						  VENDOR_REPLY_OVERHEAD);
+	if (unlikely(!skb)) {
+		PRINTM(MERROR, "skb alloc failed in %s\n", __FUNCTION__);
+		goto done;
+	}
+
+	/* Put the attribute to the skb */
+	nla_put(skb, ATTR_RTT_CHANNEL_INFO, sizeof(rtt_rsp.channel),
+		&(rtt_rsp.channel));
+	nla_put(skb, ATTR_RTT_PREAMBLE, sizeof(rtt_rsp.preamble),
+		&(rtt_rsp.preamble));
+	DBG_HEXDUMP(MCMD_D, "output data skb->data", (t_u8 *)skb->data,
+		    skb->len);
+
+	err = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(err))
+		PRINTM(MERROR, "Vendor Command reply failed err:%d \n", err);
+
+done:
+	LEAVE();
+	return err;
+}
+
+/**
+ * @brief vendor command to enable rtt responder
+ *
+ * @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_rtt_enable_responder(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_RTT_MAX];
+	wifi_channel_info *ch_info = NULL;
+	t_u32 max_dur_sec = 0;
+	mlan_rtt_responder rtt_rsp_cfg;
+	wifi_rtt_responder rtt_rsp;
+	struct sk_buff *skb = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err = 0;
+
+	ENTER();
+	PRINTM(MCMND, "Enter woal_cfg80211_subcmd_rtt_enable_responder()\n");
+
+	err = nla_parse(tb, ATTR_RTT_MAX, data, len, NULL
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err) {
+		err = -EFAULT;
+		PRINTM(MERROR, "%s: nla_parse fail\n", __FUNCTION__);
+		goto done;
+	}
+
+	if (!tb[ATTR_RTT_CHANNEL_INFO] || !tb[ATTR_RTT_MAX_DUR_SEC]) {
+		PRINTM(MERROR,
+		       "%s: null attr: tb[ATTR_RTT_TARGET_NUM]=%p tb[ATTR_RTT_TARGET_CONFIG]=%p\n",
+		       __FUNCTION__, tb[ATTR_RTT_CHANNEL_INFO],
+		       tb[ATTR_RTT_MAX_DUR_SEC]);
+		err = -EINVAL;
+		goto done;
+	}
+	ch_info = (wifi_channel_info *) nla_data(tb[ATTR_RTT_CHANNEL_INFO]);
+	max_dur_sec = nla_get_u32(tb[ATTR_RTT_MAX_DUR_SEC]);
+	PRINTM(MCMD_D, "HAL input: \n");
+	PRINTM(MCMD_D,
+	       "wifi_channel_info: width=%d center_freq=%d center_freq0=%d center_freq1=%d\n",
+	       ch_info->width, ch_info->center_freq, ch_info->center_freq0,
+	       ch_info->center_freq1);
+	PRINTM(MCMD_D, "max_dur_sec=%d\n", max_dur_sec);
+
+	memset(&rtt_rsp_cfg, 0x00, sizeof(rtt_rsp_cfg));
+	rtt_rsp_cfg.action = RTT_SET_RESPONDER_ENABLE;
+	rtt_rsp_cfg.u.encfg.channel =
+		ieee80211_frequency_to_channel(ch_info->center_freq);
+	woal_channel_info_to_bandcfg(priv, ch_info,
+				     &(rtt_rsp_cfg.u.encfg.bandcfg));
+	rtt_rsp_cfg.u.encfg.max_dur_sec = max_dur_sec;
+	PRINTM(MCMD_D, "HAL input to rtt_responder_encfg: \n");
+	PRINTM(MCMD_D,
+	       "channel=%d bandcfg=[chanBand=%d chanWidth=%d chan2Offset=%d scanMode=%d]\n",
+	       rtt_rsp_cfg.u.encfg.channel,
+	       rtt_rsp_cfg.u.encfg.bandcfg.chanBand,
+	       rtt_rsp_cfg.u.encfg.bandcfg.chanWidth,
+	       rtt_rsp_cfg.u.encfg.bandcfg.chan2Offset,
+	       rtt_rsp_cfg.u.encfg.bandcfg.scanMode);
+	PRINTM(MCMD_D, "max_dur_sec=%d\n", rtt_rsp_cfg.u.encfg.max_dur_sec);
+	ret = woal_rtt_responder_cfg(priv, MOAL_IOCTL_WAIT, &rtt_rsp_cfg);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: woal_rtt_responder_cfg() failed\n",
+		       __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+
+	memset(&rtt_rsp, 0x00, sizeof(rtt_rsp));
+	woal_bandcfg_to_channel_info(priv, &(rtt_rsp_cfg.u.info.bandcfg),
+				     rtt_rsp_cfg.u.info.channel,
+				     &(rtt_rsp.channel));
+	rtt_rsp.preamble = rtt_rsp_cfg.u.info.preamble;
+	PRINTM(MCMD_D, "wifi_rtt_responder report to HAL:\n");
+	PRINTM(MCMD_D,
+	       "channel: width=%d center_freq=%d center_freq0=%d center_freq1=%d\n",
+	       rtt_rsp.channel.width, rtt_rsp.channel.center_freq,
+	       rtt_rsp.channel.center_freq0, rtt_rsp.channel.center_freq1);
+	PRINTM(MCMD_D, "preamble=%d\n", rtt_rsp.preamble);
+
+	/* Alloc the SKB for vendor_event */
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+						  nla_total_size(sizeof
+								 (rtt_rsp)) +
+						  VENDOR_REPLY_OVERHEAD);
+	if (unlikely(!skb)) {
+		PRINTM(MERROR, "skb alloc failed in %s\n", __FUNCTION__);
+		goto done;
+	}
+
+	/* Put the attribute to the skb */
+	nla_put(skb, ATTR_RTT_CHANNEL_INFO, sizeof(rtt_rsp.channel),
+		&(rtt_rsp.channel));
+	nla_put(skb, ATTR_RTT_PREAMBLE, sizeof(rtt_rsp.preamble),
+		&(rtt_rsp.preamble));
+	DBG_HEXDUMP(MCMD_D, "output data skb->data", (t_u8 *)skb->data,
+		    skb->len);
+
+	err = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(err))
+		PRINTM(MERROR, "Vendor Command reply failed err:%d \n", err);
+
+done:
+	LEAVE();
+	return err;
+}
+
+/**
+ * @brief vendor command to disable rtt responder
+ *
+ * @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_rtt_disable_responder(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);
+	mlan_rtt_responder rtt_rsp_cfg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err = 0;
+
+	ENTER();
+	PRINTM(MCMND, "Enter woal_cfg80211_subcmd_rtt_disable_responder()\n");
+
+	memset(&rtt_rsp_cfg, 0x00, sizeof(rtt_rsp_cfg));
+	rtt_rsp_cfg.action = RTT_SET_RESPONDER_DISABLE;
+	ret = woal_rtt_responder_cfg(priv, MOAL_IOCTL_WAIT, &rtt_rsp_cfg);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: woal_rtt_responder_cfg() failed\n",
+		       __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return err;
+}
+
+/**
+ * @brief vendor command to set rtt lci
+ * @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_rtt_set_lci(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_RTT_MAX];
+	mlan_rtt_responder rtt_rsp_cfg;
+	wifi_lci_information *lci_info;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err = 0;
+
+	ENTER();
+	PRINTM(MCMND, "Enter woal_cfg80211_subcmd_rtt_set_lci()\n");
+
+	err = nla_parse(tb, ATTR_RTT_MAX, data, len, NULL
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err) {
+		err = -EFAULT;
+		PRINTM(MERROR, "%s: nla_parse fail\n", __FUNCTION__);
+		goto done;
+	}
+
+	if (!tb[ATTR_RTT_LCI_INFO]) {
+		PRINTM(MERROR, "%s: null attr: tb[ATTR_RTT_LCI_INFO]=%p\n",
+		       __FUNCTION__, tb[ATTR_RTT_LCI_INFO]);
+		err = -EINVAL;
+		goto done;
+	}
+	lci_info = (wifi_lci_information *) nla_data(tb[ATTR_RTT_LCI_INFO]);
+	PRINTM(MCMD_D, "HAL input: \n");
+	PRINTM(MCMD_D,
+	       "wifi_lci_information: latitude=%lu longitude=%lu altitude=%d latitude_unc=%d longitude_unc=%d altitude_unc=%d \n",
+	       lci_info->latitude, lci_info->longitude, lci_info->altitude,
+	       lci_info->latitude_unc, lci_info->longitude_unc,
+	       lci_info->altitude_unc);
+	PRINTM(MCMD_D,
+	       "wifi_lci_information: motion_pattern=%d floor=%d height_above_floor=%d height_unc=%d\n",
+	       lci_info->motion_pattern, lci_info->floor,
+	       lci_info->height_above_floor, lci_info->height_unc);
+
+	memset(&rtt_rsp_cfg, 0x00, sizeof(rtt_rsp_cfg));
+	rtt_rsp_cfg.action = RTT_SET_RESPONDER_LCI;
+	memcpy(&(rtt_rsp_cfg.u.lci), lci_info, sizeof(rtt_rsp_cfg.u.lci));
+	ret = woal_rtt_responder_cfg(priv, MOAL_IOCTL_WAIT, &rtt_rsp_cfg);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: woal_rtt_responder_cfg() failed\n",
+		       __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return err;
+}
+
+/**
+ * @brief vendor command to set rtt lcr
+ *
+ * @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_rtt_set_lcr(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_RTT_MAX];
+	mlan_rtt_responder rtt_rsp_cfg;
+	wifi_lcr_information *lcr_info;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err = 0;
+
+	ENTER();
+	PRINTM(MCMND, "Enter woal_cfg80211_subcmd_rtt_set_lcr()\n");
+
+	err = nla_parse(tb, ATTR_RTT_MAX, data, len, NULL
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			, NULL
+#endif
+		);
+	if (err) {
+		err = -EFAULT;
+		PRINTM(MERROR, "%s: nla_parse fail\n", __FUNCTION__);
+		goto done;
+	}
+
+	if (!tb[ATTR_RTT_LCR_INFO]) {
+		PRINTM(MERROR, "%s: null attr: tb[ATTR_RTT_LCR_INFO]=%p\n",
+		       __FUNCTION__, tb[ATTR_RTT_LCR_INFO]);
+		err = -EINVAL;
+		goto done;
+	}
+	lcr_info = (wifi_lcr_information *) nla_data(tb[ATTR_RTT_LCR_INFO]);
+	PRINTM(MCMD_D, "HAL input: \n");
+	PRINTM(MCMD_D, "wifi_lcr_information: country_code='%c' '%c'\n",
+	       lcr_info->country_code[0], lcr_info->country_code[1]);
+	PRINTM(MCMD_D, "wifi_lci_information: length=%d civic_info=%s\n",
+	       lcr_info->length, lcr_info->civic_info);
+
+	memset(&rtt_rsp_cfg, 0x00, sizeof(rtt_rsp_cfg));
+	rtt_rsp_cfg.action = RTT_SET_RESPONDER_LCR;
+	memcpy(&(rtt_rsp_cfg.u.lcr), lcr_info, sizeof(rtt_rsp_cfg.u.lcr));
+	ret = woal_rtt_responder_cfg(priv, MOAL_IOCTL_WAIT, &rtt_rsp_cfg);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: woal_rtt_responder_cfg() failed\n",
+		       __FUNCTION__);
+		err = -EFAULT;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return err;
+}
+
+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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+#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,
+	 },
+#endif
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  sub_cmd_set_roaming_offload_key,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_set_roaming_offload_key,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+
+	{
+	 .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,
+	 },
+
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  sub_cmd_get_correlated_time,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_get_correlated_time,
+	 },
+
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = SUBCMD_RTT_GET_CAPA,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_rtt_get_capa,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  SUBCMD_RTT_RANGE_REQUEST,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_rtt_range_request,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  SUBCMD_RTT_RANGE_CANCEL,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_rtt_range_cancel,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  SUBCMD_RTT_GET_RESPONDER_INFO,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_rtt_get_responder_info,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  SUBCMD_RTT_ENABLE_RESPONDER,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_rtt_enable_responder,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  SUBCMD_RTT_DISABLE_RESPONDER,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_rtt_disable_responder,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = SUBCMD_RTT_SET_LCI,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_rtt_set_lci,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = SUBCMD_RTT_SET_LCR,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_rtt_set_lcr,
+	 },
+
+	{
+	 .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,
+	 },
+
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .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,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_enable_req,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_enable_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_disable_req,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_disable_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_publish_req,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_publish_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_publish_cancel,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_publish_cancel,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_subscribe_req,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_subscribe_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_subscribe_cancel,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_subscribe_cancel,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_trasmit_followup,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_trasmit_followup,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_stats_req,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_stats_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_config_req,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_config_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_tca_req,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_tca_req,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_beacon_sdf_payload,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_beacon_sdf_payload,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_get_version,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_get_version,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_get_capa,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_get_capability,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_data_if_create,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_if_create,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_data_if_delete,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_if_delete,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_data_req_initor,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_req_initor,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd =
+		  subcmd_nan_data_indi_resp,},
+	 .flags =
+	 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
+	 WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_indi_resp,
+	 },
+	{
+	 .info = {.vendor_id = MRVL_VENDOR_ID,.subcmd = subcmd_nan_data_end,},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_nan_data_end,
+	 },
+};
+
+/**
+ * @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_sd8997/mlinux/moal_cfgvendor.h b/wlan_sd8997/mlinux/moal_cfgvendor.h
new file mode 100644
index 0000000..b8680d5
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_cfgvendor.h
@@ -0,0 +1,890 @@
+/** @file moal_cfgvendor.h
+  *
+  * @brief This file contains the CFG80211 vendor specific defines.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _MOAL_CFGVENDOR_H_
+#define _MOAL_CFGVENDOR_H_
+
+#include   "moal_main.h"
+#include   "linux/kfifo.h"
+
+#define PROPRIETARY_TLV_BASE_ID 0x100
+#define TLV_TYPE_APINFO (PROPRIETARY_TLV_BASE_ID + 249)
+#define TLV_TYPE_KEYINFO (PROPRIETARY_TLV_BASE_ID + 250)
+#define TLV_TYPE_ASSOC_REQ_IE (PROPRIETARY_TLV_BASE_ID + 292)
+
+/** MrvlIEtypesHeader_t */
+typedef struct MrvlIEtypesHeader {
+	/** Header type */
+	t_u16 type;
+	/** Header length */
+	t_u16 len;
+} __ATTRIB_PACK__ MrvlIEtypesHeader_t;
+
+/** Key Info structure */
+typedef struct _key_info_tlv {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** kck, kek, key_replay*/
+	mlan_ds_misc_gtk_rekey_data key;
+} key_info;
+
+/** APinfo TLV structure */
+typedef struct _apinfo_tlv {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Assoc response buffer */
+	t_u8 rsp_ie[1];
+} apinfo;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#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(w, r, d) ((w >= r) ? (w - r) : (d - r))
+
+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 {
+	RING_BUFFER_ENTRY_FLAGS_HAS_BINARY = (1 << (0)),	// set for binary entries
+	RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP = (1 << (1))	// set if 64 bits timestamp is present
+};
+
+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[0];
+} __attribute__ ((packed)) tlv_log;
+
+/** WiFi ring buffer driver structure */
+typedef struct {
+    /** event */
+	u16 event;
+    /** TLV log structure array */
+	tlv_log tlvs[0];
+    /** 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 MEMORY_ITEMS 16
+/* Upon program execution starting some memory slots are prefilled: */
+/* 4*([APF_FRAME_HEADER_SIZE]&15) */
+#define MEMORY_OFFSET_IPV4_HEADER_SIZE 13
+/* Size of packet in bytes. */
+#define MEMORY_OFFSET_PACKET_SIZE 14
+/* Age since filter installed in seconds. */
+#define MEMORY_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 LDB_OPCODE 1
+/* Load 2 bytes from immediate offset, e.g. "ldh R0, [5]" */
+#define LDH_OPCODE 2
+/* Load 4 bytes from immediate offset, e.g. "ldw R0, [5]" */
+#define LDW_OPCODE 3
+/* Load 1 byte from immediate offset plus register, e.g. "ldbx R0, [5]R0" */
+#define LDBX_OPCODE 4
+/* Load 2 byte from immediate offset plus register, e.g. "ldhx R0, [5]R0" */
+#define LDHX_OPCODE 5
+/* Load 4 byte from immediate offset plus register, e.g. "ldwx R0, [5]R0" */
+#define LDWX_OPCODE 6
+/* Add, e.g. "add R0,5" */
+#define ADD_OPCODE 7
+/* Multiply, e.g. "mul R0,5" */
+#define MUL_OPCODE 8
+/* Divide, e.g. "div R0,5" */
+#define DIV_OPCODE 9
+/* And, e.g. "and R0,5" */
+#define AND_OPCODE 10
+/* Or, e.g. "or R0,5" */
+#define OR_OPCODE 11
+/* Left shift, e.g, "sh R0, 5" or "sh R0, -5" (shifts right) */
+#define SH_OPCODE 12
+/* Load immediate, e.g. "li R0,5" (immediate encoded as signed value) */
+#define LI_OPCODE 13
+/* Unconditional jump, e.g. "jmp label" */
+#define JMP_OPCODE 14
+/* Compare equal and branch, e.g. "jeq R0,5,label" */
+#define JEQ_OPCODE 15
+/* Compare not equal and branch, e.g. "jne R0,5,label" */
+#define JNE_OPCODE 16
+/* Compare greater than and branch, e.g. "jgt R0,5,label" */
+#define JGT_OPCODE 17
+/* Compare less than and branch, e.g. "jlt R0,5,label" */
+#define JLT_OPCODE 18
+/* Compare any bits set and branch, e.g. "jset R0,5,label" */
+#define JSET_OPCODE 19
+/* Compare not equal byte sequence, e.g. "jnebs R0,5,label,0x1122334455" */
+#define 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 EXT_OPCODE 21
+/* Load from memory, e.g. "ldm R0,5"
+ * Values 0-15 represent loading the different memory slots. */
+#define LDM_EXT_OPCODE 0
+/* Store to memory, e.g. "stm R0,5" *
+ * Values 16-31 represent storing to the different memory slots. */
+#define STM_EXT_OPCODE 16
+/* Not, e.g. "not R0" */
+#define NOT_EXT_OPCODE 32
+/* Negate, e.g. "neg R0" */
+#define NEG_EXT_OPCODE 33
+/* Swap, e.g. "swap R0,R1" */
+#define SWAP_EXT_OPCODE 34
+/* Move, e.g. "move R0,R1" */
+#define MOV_EXT_OPCODE 35
+
+#define EXTRACT_OPCODE(i) (((i) >> 3) & 31)
+#define EXTRACT_REGISTER(i) ((i)&1)
+#define EXTRACT_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_PACKET 1
+/* Return code indicating "packet" should be dropped. */
+#define DROP_PACKET 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_MAX,
+};
+
+/** 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);
+
+#define CMD_FIFO_SIZE 8
+#define MAX_INDICATE_ARRAY_SIZE 5
+
+enum {
+	ATTR_NAN_FAKE = 1,
+	ATTR_NAN_IND = 2,
+};
+
+/** nan_cb */
+typedef struct _nan_cb {
+    /** Delayed work response */
+	struct delayed_work response_work;
+    /** Priv */
+	moal_private *priv;
+    /** CMD fifo */
+	struct kfifo cmd_fifo;
+} nan_cb;
+
+/** NanHeader */
+typedef struct _NanHeader {
+    /** Msg ID */
+	t_u16 MsgId;
+    /** Msg length */
+	t_u16 MsgLen;
+    /** Handle */
+	t_u16 handle;
+    /** Transaction ID */
+	t_u16 transactionId;
+} NanHeader;
+
+/** NanHeader_Ext */
+typedef struct _NanHeader_Ext {
+	NanHeader nan_header;
+    /** Status */
+	t_u16 status;
+    /** Value */
+	t_u16 value;
+} NanHeader_Ext;
+
+/** nan_cmd */
+typedef struct _nan_cmd {
+	NanHeader_Ext nan_header_ext;
+    /** Enable Indication */
+	t_u16 indicate_enable;
+    /** Type Indicate */
+	t_u16 indicate_type;
+} nan_cmd;
+
+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)
+
+/* Feature enums */
+#define WIFI_FEATURE_INFRA              0x0001	// Basic infrastructure mode
+#define WIFI_FEATURE_INFRA_5G           0x0002	// Support for 5 GHz Band
+#define WIFI_FEATURE_HOTSPOT            0x0004	// Support for GAS/ANQP
+#define WIFI_FEATURE_P2P                0x0008	// Wifi-Direct
+#define WIFI_FEATURE_SOFT_AP            0x0010	// Soft AP
+#define WIFI_FEATURE_GSCAN              0x0020	// Google-Scan APIs
+#define WIFI_FEATURE_NAN                0x0040	// Neighbor Awareness Networking
+#define WIFI_FEATURE_D2D_RTT            0x0080	// Device-to-device RTT
+#define WIFI_FEATURE_D2AP_RTT           0x0100	// Device-to-AP RTT
+#define WIFI_FEATURE_BATCH_SCAN         0x0200	// Batched Scan (legacy)
+#define WIFI_FEATURE_PNO                0x0400	// Preferred network offload
+#define WIFI_FEATURE_ADDITIONAL_STA     0x0800	// Support for two STAs
+#define WIFI_FEATURE_TDLS               0x1000	// Tunnel directed link setup
+#define WIFI_FEATURE_TDLS_OFFCHANNEL    0x2000	// Support for TDLS off channel
+#define WIFI_FEATURE_EPR                0x4000	// Enhanced power reporting
+#define WIFI_FEATURE_AP_STA             0x8000	// Support for AP STA Concurrency
+#define WIFI_FEATURE_LINK_LAYER_STATS   0x10000	// Link layer stats collection
+#define WIFI_FEATURE_LOGGER             0x20000	// WiFi Logger
+#define WIFI_FEATURE_HAL_EPNO           0x40000	// WiFi PNO enhanced
+#define WIFI_FEATURE_RSSI_MONITOR       0x80000	// RSSI Monitor
+#define WIFI_FEATURE_MKEEP_ALIVE        0x100000	// WiFi mkeep_alive
+#define WIFI_FEATURE_CONFIG_NDO         0x200000	// ND offload configure
+#define WIFI_FEATURE_TX_TRANSMIT_POWER  0x400000	// Capture Tx transmit power levels
+#define WIFI_FEATURE_CONTROL_ROAMING    0x800000	// Enable/Disable firmware roaming
+#define WIFI_FEATURE_IE_WHITELIST       0x1000000	// Support Probe IE white listing
+#define WIFI_FEATURE_SCAN_RAND          0x2000000	// Support MAC & Probe Sequence Number randomization
+// 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_MAX,
+} 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_rtt_result = 0x07,
+	event_rssi_monitor = 0x1501,
+	event_set_key_mgmt_offload = 0x10001,
+	event_fw_roam_success = 0x10002,
+	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_nan_cb = 0x10010,
+	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_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_MAX,
+};
+void woal_cfg80211_rssi_monitor_event(moal_private *priv, t_s16 rssi);
+
+enum ATTR_LINK_LAYER_STAT {
+	ATTR_LL_STATS_INVALID,
+	ATTR_LL_STATS_MPDU_SIZE_THRESHOLD,
+	ATTR_LL_STATS_AGGRSSIVE_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_MAX,
+};
+
+/**vendor sub command*/
+enum vendor_sub_command {
+	sub_cmd_set_drvdbg = 0,
+	sub_cmd_set_roaming_offload_key = 0x0002,
+	sub_cmd_dfs_capability = 0x0005,
+	sub_cmd_get_correlated_time = 0x0006,
+	sub_cmd_set_scan_mac_oui = 0x0007,
+	sub_cmd_set_packet_filter = 0x0011,
+	sub_cmd_get_packet_filter_capability,
+	sub_cmd_nd_offload = 0x0100,
+	SUBCMD_RTT_GET_CAPA = 0x1100,
+	SUBCMD_RTT_RANGE_REQUEST,
+	SUBCMD_RTT_RANGE_CANCEL,
+	SUBCMD_RTT_GET_RESPONDER_INFO,
+	SUBCMD_RTT_ENABLE_RESPONDER,
+	SUBCMD_RTT_DISABLE_RESPONDER,
+	SUBCMD_RTT_SET_LCI,
+	SUBCMD_RTT_SET_LCR,
+	sub_cmd_get_valid_channels = 0x1009,
+	sub_cmd_get_wifi_supp_feature_set = 0x100a,
+	sub_cmd_set_country_code = 0x100d,
+	sub_cmd_link_statistic_set = 0x1200,
+	sub_cmd_link_statistic_get = 0x1201,
+	sub_cmd_link_statistic_clr = 0x1202,
+	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,
+	subcmd_nan_enable_req = 0x1800,
+	subcmd_nan_disable_req,
+	subcmd_nan_publish_req,
+	subcmd_nan_publish_cancel,
+	subcmd_nan_subscribe_req,
+	subcmd_nan_subscribe_cancel,
+	subcmd_nan_trasmit_followup,
+	subcmd_nan_stats_req,
+	subcmd_nan_config_req,
+	subcmd_nan_tca_req,
+	subcmd_nan_beacon_sdf_payload,
+	subcmd_nan_get_version,
+	subcmd_nan_get_capa,
+	subcmd_nan_data_if_create,
+	subcmd_nan_data_if_delete,
+	subcmd_nan_data_req_initor,
+	subcmd_nan_data_indi_resp,
+	subcmd_nan_data_end,
+	sub_cmd_max,
+};
+
+void woal_register_cfg80211_vendor_command(struct wiphy *wiphy);
+int woal_cfg80211_vendor_event(IN moal_private *priv,
+			       IN int event, IN t_u8 *data, IN 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_MAX,
+} ND_OFFLOAD_ATTR;
+
+int woal_roam_ap_info(IN moal_private *priv, IN t_u8 *data, IN int len);
+
+/*Attribute for wpa_supplicant*/
+enum mrvl_wlan_vendor_attr_roam_auth {
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
+	/* keep last */
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX =
+		MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_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
+};
+
+enum attr_rtt {
+	ATTR_RTT_INVALID = 0,
+	ATTR_RTT_CAPA,
+	ATTR_RTT_TARGET_NUM,
+	ATTR_RTT_TARGET_CONFIG,
+	ATTR_RTT_TARGET_ADDR,
+	ATTR_RTT_RESULT_COMPLETE,
+	ATTR_RTT_RESULT_NUM,
+	ATTR_RTT_RESULT_FULL,
+	ATTR_RTT_CHANNEL_INFO,
+	ATTR_RTT_MAX_DUR_SEC,
+	ATTR_RTT_PREAMBLE,
+	ATTR_RTT_LCI_INFO,
+	ATTR_RTT_LCR_INFO,
+
+	/* keep last */
+	ATTR_RTT_AFTER_LAST,
+	ATTR_RTT_MAX = ATTR_RTT_AFTER_LAST
+};
+
+mlan_status woal_cfg80211_event_rtt_result(IN moal_private *priv,
+					   IN t_u8 *data, IN int len);
+#endif
+#endif /* _MOAL_CFGVENDOR_H_ */
diff --git a/wlan_sd8997/mlinux/moal_debug.c b/wlan_sd8997/mlinux/moal_debug.c
new file mode 100644
index 0000000..05e12cb
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_debug.c
@@ -0,0 +1,1300 @@
+/** @file moal_debug.c
+  *
+  * @brief This file contains functions for debug proc file.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    11/03/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+
+/********************************************************
+		Global Variables
+********************************************************/
+/** MLAN debug info */
+extern mlan_debug_info info;
+
+/********************************************************
+		Local Variables
+********************************************************/
+#ifdef CONFIG_PROC_FS
+
+/** Get info item size */
+#define item_size(n) (sizeof(info.n))
+/** Get info item address */
+#define item_addr(n) ((t_ptr) &(info.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 STA_SUPPORT
+static struct debug_data items[] = {
+#ifdef DEBUG_LEVEL1
+	{"drvdbg", sizeof(drvdbg), (t_ptr)&drvdbg},
+#endif
+	{"mlan_processing", item_size(mlan_processing),
+	 item_addr(mlan_processing)},
+	{"main_process_cnt", item_size(main_process_cnt),
+	 item_addr(main_process_cnt)},
+	{"main_lock_flag", item_size(main_lock_flag),
+	 item_addr(main_lock_flag)},
+	{"delay_task_flag", item_size(delay_task_flag),
+	 item_addr(delay_task_flag)},
+	{"mlan_rx_processing", item_size(mlan_rx_processing),
+	 item_addr(mlan_rx_processing)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"wmm_ac_vo", item_size(wmm_ac_vo), item_addr(wmm_ac_vo)},
+	{"wmm_ac_vi", item_size(wmm_ac_vi), item_addr(wmm_ac_vi)},
+	{"wmm_ac_be", item_size(wmm_ac_be), item_addr(wmm_ac_be)},
+	{"wmm_ac_bk", item_size(wmm_ac_bk), item_addr(wmm_ac_bk)},
+	{"max_tx_buf_size", item_size(max_tx_buf_size),
+	 item_addr(max_tx_buf_size)},
+	{"tx_buf_size", item_size(tx_buf_size), item_addr(tx_buf_size)},
+	{"curr_tx_buf_size", item_size(curr_tx_buf_size),
+	 item_addr(curr_tx_buf_size)},
+	{"ps_mode", item_size(ps_mode), item_addr(ps_mode)},
+	{"ps_state", item_size(ps_state), item_addr(ps_state)},
+	{"is_deep_sleep", item_size(is_deep_sleep), item_addr(is_deep_sleep)},
+	{"wakeup_dev_req", item_size(pm_wakeup_card_req),
+	 item_addr(pm_wakeup_card_req)},
+	{"wakeup_tries", item_size(pm_wakeup_fw_try),
+	 item_addr(pm_wakeup_fw_try)},
+	{"hs_configured", item_size(is_hs_configured),
+	 item_addr(is_hs_configured)},
+	{"hs_activated", item_size(hs_activated), item_addr(hs_activated)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"tx_pkts_queued", item_size(tx_pkts_queued),
+	 item_addr(tx_pkts_queued)},
+	{"pps_uapsd_mode", item_size(pps_uapsd_mode),
+	 item_addr(pps_uapsd_mode)},
+	{"sleep_pd", item_size(sleep_pd), item_addr(sleep_pd)},
+	{"qos_cfg", item_size(qos_cfg), item_addr(qos_cfg)},
+	{"tx_lock_flag", item_size(tx_lock_flag), item_addr(tx_lock_flag)},
+	{"port_open", item_size(port_open), item_addr(port_open)},
+	{"bypass_pkt_count", item_size(bypass_pkt_count),
+	 item_addr(bypass_pkt_count)},
+	{"scan_processing", item_size(scan_processing),
+	 item_addr(scan_processing)},
+	{"num_tx_timeout", item_size(num_tx_timeout),
+	 item_addr(num_tx_timeout)},
+	{"num_cmd_timeout", item_size(num_cmd_timeout),
+	 item_addr(num_cmd_timeout)},
+	{"dbg.num_cmd_timeout", item_size(dbg_num_cmd_timeout),
+	 item_addr(dbg_num_cmd_timeout)},
+	{"timeout_cmd_id", item_size(timeout_cmd_id),
+	 item_addr(timeout_cmd_id)},
+	{"timeout_cmd_act", item_size(timeout_cmd_act),
+	 item_addr(timeout_cmd_act)},
+	{"last_cmd_id", item_size(last_cmd_id), item_addr(last_cmd_id)},
+	{"last_cmd_act", item_size(last_cmd_act), item_addr(last_cmd_act)},
+	{"last_cmd_index", item_size(last_cmd_index),
+	 item_addr(last_cmd_index)},
+	{"last_cmd_resp_id", item_size(last_cmd_resp_id),
+	 item_addr(last_cmd_resp_id)},
+	{"last_cmd_resp_index", item_size(last_cmd_resp_index),
+	 item_addr(last_cmd_resp_index)},
+	{"last_event", item_size(last_event), item_addr(last_event)},
+	{"last_event_index", item_size(last_event_index),
+	 item_addr(last_event_index)},
+	{"num_no_cmd_node", item_size(num_no_cmd_node),
+	 item_addr(num_no_cmd_node)},
+	{"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
+	 item_addr(num_cmd_host_to_card_failure)},
+	{"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)},
+	{"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
+	 item_addr(num_tx_host_to_card_failure)},
+	{"num_alloc_buffer_failure", item_size(num_alloc_buffer_failure),
+	 item_addr(num_alloc_buffer_failure)},
+	{"num_cmdevt_c2h_fail", item_size(num_cmdevt_card_to_host_failure),
+	 item_addr(num_cmdevt_card_to_host_failure)},
+	{"num_rx_c2h_fail", item_size(num_rx_card_to_host_failure),
+	 item_addr(num_rx_card_to_host_failure)},
+	{"num_int_read_fail", item_size(num_int_read_failure),
+	 item_addr(num_int_read_failure)},
+	{"last_int_status", item_size(last_int_status),
+	 item_addr(last_int_status)},
+	{"num_of_irq", item_size(num_of_irq), item_addr(num_of_irq)},
+	{"mp_invalid_update", item_size(mp_invalid_update),
+	 item_addr(mp_invalid_update)},
+	{"sdio_rx_aggr", item_size(sdio_rx_aggr), item_addr(sdio_rx_aggr)},
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	{"mpa_sent_last_pkt", item_size(mpa_sent_last_pkt),
+	 item_addr(mpa_sent_last_pkt)},
+	{"mpa_sent_no_ports", item_size(mpa_sent_no_ports),
+	 item_addr(mpa_sent_no_ports)},
+#endif
+	{"num_evt_deauth", item_size(num_event_deauth),
+	 item_addr(num_event_deauth)},
+	{"num_evt_disassoc", item_size(num_event_disassoc),
+	 item_addr(num_event_disassoc)},
+	{"num_evt_link_lost", item_size(num_event_link_lost),
+	 item_addr(num_event_link_lost)},
+	{"num_cmd_deauth", item_size(num_cmd_deauth),
+	 item_addr(num_cmd_deauth)},
+	{"num_cmd_assoc_ok", item_size(num_cmd_assoc_success),
+	 item_addr(num_cmd_assoc_success)},
+	{"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure),
+	 item_addr(num_cmd_assoc_failure)},
+	{"cmd_sent", item_size(cmd_sent), item_addr(cmd_sent)},
+	{"data_sent", item_size(data_sent), item_addr(data_sent)},
+	{"mp_rd_bitmap", item_size(mp_rd_bitmap), item_addr(mp_rd_bitmap)},
+	{"curr_rd_port", item_size(curr_rd_port), item_addr(curr_rd_port)},
+	{"mp_wr_bitmap", item_size(mp_wr_bitmap), item_addr(mp_wr_bitmap)},
+	{"curr_wr_port", item_size(curr_wr_port), item_addr(curr_wr_port)},
+	{"cmd_resp_received", item_size(cmd_resp_received),
+	 item_addr(cmd_resp_received)},
+	{"event_received", item_size(event_received),
+	 item_addr(event_received)},
+
+	{"ioctl_pending", item_handle_size(ioctl_pending),
+	 item_handle_addr(ioctl_pending)},
+	{"tx_pending", item_handle_size(tx_pending),
+	 item_handle_addr(tx_pending)},
+	{"rx_pending", item_handle_size(rx_pending),
+	 item_handle_addr(rx_pending)},
+	{"lock_count", item_handle_size(lock_count),
+	 item_handle_addr(lock_count)},
+	{"malloc_count", item_handle_size(malloc_count),
+	 item_handle_addr(malloc_count)},
+	{"vmalloc_count", item_handle_size(vmalloc_count),
+	 item_handle_addr(vmalloc_count)},
+	{"mbufalloc_count", item_handle_size(mbufalloc_count),
+	 item_handle_addr(mbufalloc_count)},
+	{"main_state", item_handle_size(main_state),
+	 item_handle_addr(main_state)},
+	{"driver_state", item_handle_size(driver_state),
+	 item_handle_addr(driver_state)},
+#ifdef SDIO_MMC_DEBUG
+	{"sdiocmd53w", item_handle_size(cmd53w), item_handle_addr(cmd53w)},
+	{"sdiocmd53r", item_handle_size(cmd53r), item_handle_addr(cmd53r)},
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+	{"hs_skip_count", item_handle_size(hs_skip_count),
+	 item_handle_addr(hs_skip_count)},
+	{"hs_force_count", item_handle_size(hs_force_count),
+	 item_handle_addr(hs_force_count)},
+#endif
+};
+
+#endif
+
+#ifdef UAP_SUPPORT
+static struct debug_data uap_items[] = {
+#ifdef DEBUG_LEVEL1
+	{"drvdbg", sizeof(drvdbg), (t_ptr)&drvdbg},
+#endif
+	{"mlan_processing", item_size(mlan_processing),
+	 item_addr(mlan_processing)},
+	{"main_process_cnt", item_size(main_process_cnt),
+	 item_addr(main_process_cnt)},
+	{"main_lock_flag", item_size(main_lock_flag),
+	 item_addr(main_lock_flag)},
+	{"delay_task_flag", item_size(delay_task_flag),
+	 item_addr(delay_task_flag)},
+	{"mlan_rx_processing", item_size(mlan_rx_processing),
+	 item_addr(mlan_rx_processing)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"wmm_ac_vo", item_size(wmm_ac_vo), item_addr(wmm_ac_vo)},
+	{"wmm_ac_vi", item_size(wmm_ac_vi), item_addr(wmm_ac_vi)},
+	{"wmm_ac_be", item_size(wmm_ac_be), item_addr(wmm_ac_be)},
+	{"wmm_ac_bk", item_size(wmm_ac_bk), item_addr(wmm_ac_bk)},
+	{"max_tx_buf_size", item_size(max_tx_buf_size),
+	 item_addr(max_tx_buf_size)},
+	{"tx_buf_size", item_size(tx_buf_size), item_addr(tx_buf_size)},
+	{"curr_tx_buf_size", item_size(curr_tx_buf_size),
+	 item_addr(curr_tx_buf_size)},
+	{"ps_mode", item_size(ps_mode), item_addr(ps_mode)},
+	{"ps_state", item_size(ps_state), item_addr(ps_state)},
+	{"wakeup_dev_req", item_size(pm_wakeup_card_req),
+	 item_addr(pm_wakeup_card_req)},
+	{"wakeup_tries", item_size(pm_wakeup_fw_try),
+	 item_addr(pm_wakeup_fw_try)},
+	{"hs_configured", item_size(is_hs_configured),
+	 item_addr(is_hs_configured)},
+	{"hs_activated", item_size(hs_activated), item_addr(hs_activated)},
+	{"rx_pkts_queued", item_size(rx_pkts_queued),
+	 item_addr(rx_pkts_queued)},
+	{"tx_pkts_queued", item_size(tx_pkts_queued),
+	 item_addr(tx_pkts_queued)},
+	{"bypass_pkt_count", item_size(bypass_pkt_count),
+	 item_addr(bypass_pkt_count)},
+	{"num_bridge_pkts", item_size(num_bridge_pkts),
+	 item_addr(num_bridge_pkts)},
+	{"num_drop_pkts", item_size(num_drop_pkts), item_addr(num_drop_pkts)},
+	{"num_tx_timeout", item_size(num_tx_timeout),
+	 item_addr(num_tx_timeout)},
+	{"num_cmd_timeout", item_size(num_cmd_timeout),
+	 item_addr(num_cmd_timeout)},
+	{"timeout_cmd_id", item_size(timeout_cmd_id),
+	 item_addr(timeout_cmd_id)},
+	{"timeout_cmd_act", item_size(timeout_cmd_act),
+	 item_addr(timeout_cmd_act)},
+	{"last_cmd_id", item_size(last_cmd_id), item_addr(last_cmd_id)},
+	{"last_cmd_act", item_size(last_cmd_act), item_addr(last_cmd_act)},
+	{"last_cmd_index", item_size(last_cmd_index),
+	 item_addr(last_cmd_index)},
+	{"last_cmd_resp_id", item_size(last_cmd_resp_id),
+	 item_addr(last_cmd_resp_id)},
+	{"last_cmd_resp_index", item_size(last_cmd_resp_index),
+	 item_addr(last_cmd_resp_index)},
+	{"last_event", item_size(last_event), item_addr(last_event)},
+	{"last_event_index", item_size(last_event_index),
+	 item_addr(last_event_index)},
+	{"num_no_cmd_node", item_size(num_no_cmd_node),
+	 item_addr(num_no_cmd_node)},
+	{"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
+	 item_addr(num_cmd_host_to_card_failure)},
+	{"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)},
+	{"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
+	 item_addr(num_tx_host_to_card_failure)},
+	{"num_alloc_buffer_failure", item_size(num_alloc_buffer_failure),
+	 item_addr(num_alloc_buffer_failure)},
+	{"num_cmdevt_c2h_fail", item_size(num_cmdevt_card_to_host_failure),
+	 item_addr(num_cmdevt_card_to_host_failure)},
+	{"num_rx_c2h_fail", item_size(num_rx_card_to_host_failure),
+	 item_addr(num_rx_card_to_host_failure)},
+	{"num_int_read_fail", item_size(num_int_read_failure),
+	 item_addr(num_int_read_failure)},
+	{"last_int_status", item_size(last_int_status),
+	 item_addr(last_int_status)},
+	{"num_of_irq", item_size(num_of_irq), item_addr(num_of_irq)},
+	{"mp_invalid_update", item_size(mp_invalid_update),
+	 item_addr(mp_invalid_update)},
+	{"sdio_rx_aggr", item_size(sdio_rx_aggr), item_addr(sdio_rx_aggr)},
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	{"mpa_sent_last_pkt", item_size(mpa_sent_last_pkt),
+	 item_addr(mpa_sent_last_pkt)},
+	{"mpa_sent_no_ports", item_size(mpa_sent_no_ports),
+	 item_addr(mpa_sent_no_ports)},
+#endif
+	{"cmd_sent", item_size(cmd_sent), item_addr(cmd_sent)},
+	{"data_sent", item_size(data_sent), item_addr(data_sent)},
+	{"mp_rd_bitmap", item_size(mp_rd_bitmap), item_addr(mp_rd_bitmap)},
+	{"curr_rd_port", item_size(curr_rd_port), item_addr(curr_rd_port)},
+	{"mp_wr_bitmap", item_size(mp_wr_bitmap), item_addr(mp_wr_bitmap)},
+	{"curr_wr_port", item_size(curr_wr_port), item_addr(curr_wr_port)},
+	{"cmd_resp_received", item_size(cmd_resp_received),
+	 item_addr(cmd_resp_received)},
+	{"event_received", item_size(event_received),
+	 item_addr(event_received)},
+
+	{"ioctl_pending", item_handle_size(ioctl_pending),
+	 item_handle_addr(ioctl_pending)},
+	{"tx_pending", item_handle_size(tx_pending),
+	 item_handle_addr(tx_pending)},
+	{"rx_pending", item_handle_size(rx_pending),
+	 item_handle_addr(rx_pending)},
+	{"lock_count", item_handle_size(lock_count),
+	 item_handle_addr(lock_count)},
+	{"malloc_count", item_handle_size(malloc_count),
+	 item_handle_addr(malloc_count)},
+	{"vmalloc_count", item_handle_size(vmalloc_count),
+	 item_handle_addr(vmalloc_count)},
+	{"mbufalloc_count", item_handle_size(mbufalloc_count),
+	 item_handle_addr(mbufalloc_count)},
+	{"main_state", item_handle_size(main_state),
+	 item_handle_addr(main_state)},
+	{"driver_state", item_handle_size(driver_state),
+	 item_handle_addr(driver_state)},
+#ifdef SDIO_MMC_DEBUG
+	{"sdiocmd53w", item_handle_size(cmd53w), item_handle_addr(cmd53w)},
+	{"sdiocmd53r", item_handle_size(cmd53r), item_handle_addr(cmd53r)},
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+	{"hs_skip_count", item_handle_size(hs_skip_count),
+	 item_handle_addr(hs_skip_count)},
+	{"hs_force_count", item_handle_size(hs_force_count),
+	 item_handle_addr(hs_force_count)},
+#endif
+};
+#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_u8 rx_rate_max_size = 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->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
+ *  @param antenna             Antenna
+ *  @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);
+}
+
+/**
+ *  @brief This function set histogram data
+ *
+ *  @param priv 		A pointer to moal_private
+ *  @param rx_rate              rx rate
+ *  @param snr			snr
+ *  @param nflr			NF
+ *  @param antenna              Antenna
+ *  @return   N/A
+ */
+static void
+woal_hist_data_set(moal_private *priv, t_u8 rx_rate, t_s8 snr, t_s8 nflr,
+		   t_u8 antenna)
+{
+	hgm_data *phist_data = priv->hist_data[antenna];
+
+	atomic_inc(&(phist_data->num_samples));
+	atomic_inc(&(phist_data->rx_rate[rx_rate]));
+	atomic_inc(&(phist_data->snr[snr]));
+	atomic_inc(&(phist_data->noise_flr[128 + nflr]));
+	atomic_inc(&(phist_data->sig_str[nflr - snr]));
+}
+
+/**
+ *  @brief This function add histogram data
+ *
+ *  @param priv 		A pointer to moal_private
+ *  @param rx_rate              rx rate
+ *  @param snr			snr
+ *  @param nflr			NF
+ *  @param antenna              Antenna
+ *  @return   N/A
+ */
+void
+woal_hist_data_add(moal_private *priv, t_u8 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->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 RATE_INDEX_MCS0   12
+/**
+ *  @brief histogram info in proc
+ *
+ *  @param sfp     A pointer to seq_file structure
+ *  @param data    void pointer to 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 rx_rate_max_size = 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");
+
+	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" : "");
+			}
+		}
+	}
+	for (i = 0; i < SNR_MAX; i++) {
+		value = atomic_read(&(phist_data->snr[i]));
+		if (value)
+			seq_printf(sfp, "snr[%02ddB] = %d\n", i, 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", i,
+				   value);
+	}
+
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc read function for histogram
+ *
+ *  @param sfp     A pointer to seq_file structure
+ *  @param data    Void pointer to 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 (!priv->hist_data) {
+		LEAVE();
+		return -EFAULT;
+	}
+	if (hist_data->ant_idx < priv->phandle->histogram_table_num)
+		woal_histogram_info(sfp, priv->hist_data[hist_data->ant_idx]);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc open function for histogram
+ *
+ *  @param inode     A pointer to inode structure
+ *  @param file      A pointer to file structure
+ *
+ *  @return         0--sucess, otherise fail
+**/
+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     A pointer to seq_file structure
+ *  @param data    void pointer to 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     A pointer to seq_file structure
+ *  @param data    Void pointer to 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;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	unsigned int j;
+	t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+#endif
+
+	ENTER();
+
+	if (priv == NULL) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	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 (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 {
+			unsigned int j;
+			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")
+			)
+			seq_printf(sfp, "%s=0x%x\n", d[i].name, val);
+		else
+			seq_printf(sfp, "%s=%d\n", d[i].name, val);
+	}
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	seq_printf(sfp, "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++) {
+		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");
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+	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");
+#endif
+	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");
+	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);
+#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++) {
+			unsigned int j;
+
+			seq_printf(sfp,
+				   "tid = %d, ta =  %02x:%02x:%02x:%02x:%02x:%02x, start_win = %d, "
+				   "win_size = %d, amsdu=%d\n",
+				   (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, "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++) {
+		unsigned int j;
+		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;
+#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;
+	}
+
+	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;
+}
+
+/**
+ *  @brief debug proc open function
+ *
+ *  @param inode     A pointer to inode structure
+ *  @param file      A pointer to file structure
+ *
+ *  @return         0--sucess, otherise fail
+**/
+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
+}
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+/********************************************************
+		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;
+	int handle_items;
+	char hist_entry[50];
+
+	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;
+		}
+		memcpy(priv->items_priv.items, 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;
+		}
+		memcpy(priv->items_priv.items, uap_items, sizeof(uap_items));
+		priv->items_priv.num_of_items = ARRAY_SIZE(uap_items);
+	}
+#endif
+
+	priv->items_priv.priv = priv;
+	handle_items = 9;
+#ifdef SDIO_MMC_DEBUG
+	handle_items += 2;
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+	handle_items += 2;
+#endif
+	for (i = 1; i <= handle_items; i++)
+		priv->items_priv.items[priv->items_priv.num_of_items -
+				       i].addr += (t_ptr)(priv->phandle);
+
+	/* 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->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->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_sd8997/mlinux/moal_eth_ioctl.c b/wlan_sd8997/mlinux/moal_eth_ioctl.c
new file mode 100644
index 0000000..c2b43b6
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_eth_ioctl.c
@@ -0,0 +1,15668 @@
+/** @file  moal_eth_ioctl.c
+  *
+  * @brief This file contains private ioctl functions
+  *
+  * Copyright (C) 2014-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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
+#include	"moal_sdio.h"
+#ifdef STA_CFG80211
+#include    "moal_sta_cfg80211.h"
+#endif
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#include    "moal_cfgvendor.h"
+#endif
+#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_GAC,
+		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_GN, BAND_B | BAND_G | BAND_GN, BAND_G | BAND_GN,
+	BAND_GN | BAND_GAC, BAND_B | BAND_G | BAND_GN | BAND_GAC,
+		BAND_G | BAND_GN | BAND_GAC,
+	BAND_A,
+	BAND_AN, BAND_A | BAND_AN,
+	BAND_AN | BAND_AAC, BAND_A | BAND_AN | BAND_AAC,
+};
+
+/********************************************************
+			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
+extern int cfg80211_wext;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+extern int roamoffload_in_hs;
+extern int hw_test;
+extern int cntry_txpwr;
+/********************************************************
+			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
+ */
+mlan_status
+parse_arguments(t_u8 *pos, int *data, int datalen, int *user_data_len)
+{
+	unsigned 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 <= strlen(pos); i++) {
+		if ((k == 0) && (i <= (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 {
+			cdata[k] = pos[i];
+			k++;
+		}
+	}
+
+	*user_data_len = j;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/** Convert character to integer */
+#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0'))
+/**
+ * @brief Converts a string to hex value
+ *
+ * @param str      A pointer to the string
+ * @param raw      A pointer to the raw data buffer
+ * @return         Number of bytes read
+ **/
+int
+string2raw(char *str, unsigned char *raw)
+{
+	int len = (strlen(str) + 1) / 2;
+
+	do {
+		if (!isxdigit(*str)) {
+			return -1;
+		}
+		*str = toupper(*str);
+		*raw = CHAR2INT(*str) << 4;
+		++str;
+		*str = toupper(*str);
+		if (*str == '\0')
+			break;
+		*raw |= CHAR2INT(*str);
+		++raw;
+	} while (*++str != '\0');
+	return len;
+}
+
+#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;
+	t_u32 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
+ */
+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) {
+		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.
+ */
+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, (respbuflen - 1));
+		memcpy(respbuf, buf, ret);
+	} 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_MARVELL) + strlen(PRIV_CMD_HOSTCMD));
+	buf_len = *((t_u32 *)data_ptr);
+	memcpy(&cmd_header, data_ptr + sizeof(buf_len), 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) > MLAN_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 */
+	memcpy(misc_cfg->param.hostcmd.cmd, data_ptr + sizeof(buf_len),
+	       misc_cfg->param.hostcmd.len);
+
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto error;
+	}
+	memcpy(data_ptr + sizeof(buf_len), misc_cfg->param.hostcmd.cmd,
+	       misc_cfg->param.hostcmd.len);
+	ret = misc_cfg->param.hostcmd.len + sizeof(buf_len) +
+		strlen(CMD_MARVELL) + strlen(PRIV_CMD_HOSTCMD);
+	memcpy(data_ptr, (t_u8 *)&misc_cfg->param.hostcmd.len, sizeof(t_u32));
+
+error:
+	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.
+ */
+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 *custom_ie = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	data_ptr = respbuf + (strlen(CMD_MARVELL) + strlen(PRIV_CMD_CUSTOMIE));
+
+	custom_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 ((custom_ie->len == 0)||(custom_ie->len ==
+				    sizeof(custom_ie->ie_data_list[0].
+					   ie_index)))
+		ioctl_req->action = MLAN_ACT_GET;
+	else
+		ioctl_req->action = MLAN_ACT_SET;
+
+	memcpy(&misc->param.cust_ie, 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;
+	}
+	custom_ie = (mlan_ds_misc_custom_ie *)data_ptr;
+	memcpy(custom_ie, &misc->param.cust_ie, sizeof(mlan_ds_misc_custom_ie));
+	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.
+ */
+int
+woal_setget_priv_bandcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	unsigned int i;
+	int data[4];
+	int user_data_len = 0;
+	t_u32 infra_band = 0;
+	t_u32 adhoc_band = 0;
+	t_u32 adhoc_channel = 0;
+	t_u32 adhoc_chan_bandwidth = 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_MARVELL) + strlen(PRIV_CMD_BANDCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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); 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;
+			}
+		}
+		if (user_data_len == 4) {
+			if (!(adhoc_band & (BAND_GN
+					    | BAND_GAC | BAND_AN | BAND_AAC))) {
+				PRINTM(MERROR,
+				       "11n is not enabled for adhoc, can not set HT/VHT channel bandwidth\n");
+				ret = -EINVAL;
+				goto error;
+			}
+			adhoc_chan_bandwidth = data[3];
+			/* sanity test */
+			if ((adhoc_chan_bandwidth != CHANNEL_BW_20MHZ) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_ABOVE) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_BELOW)
+			    && (adhoc_chan_bandwidth != CHANNEL_BW_80MHZ)
+				) {
+				PRINTM(MERROR,
+				       "Invalid secondary channel bandwidth, only allowed 0, 1, 3 or 4\n");
+				ret = -EINVAL;
+				goto error;
+			}
+
+			/* VHT 80 MHz is valid only for 5G band */
+			if ((adhoc_chan_bandwidth == CHANNEL_BW_80MHZ) &&
+			    ((adhoc_band & BAND_AAC) == 0)) {
+				PRINTM(MERROR,
+				       "Invalid adhoc band for 11ac 80 Mhz, only 5G is allowed.\n");
+				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;
+		radio_cfg->param.band_cfg.adhoc_chan_bandwidth =
+			adhoc_chan_bandwidth;
+	}
+
+	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;
+
+	memcpy(band_cfg, &radio_cfg->param.band_cfg, sizeof(mlan_ds_band_cfg));
+
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_HTTXCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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]);
+	}
+
+	memcpy(respbuf, data, sizeof(data));
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_HTCAPINFO))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ADDBAPARA))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DELBA);
+
+	if (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)
+		memcpy(del_ba->peer_mac_addr, peer_mac, ETH_ALEN);
+
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_REJECTADDBAREQ))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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
+ */
+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)
+		memcpy(cfg_11n->param.addba_reject, 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)
+		memcpy(addba_reject, cfg_11n->param.addba_reject,
+		       sizeof(cfg_11n->param.addba_reject));
+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
+ */
+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)
+		memcpy(&cfg_11n->param.aggr_prio_tbl, 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)
+		memcpy(aggr_prio_tbl, &cfg_11n->param.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
+ */
+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)
+		memcpy(&cfg_11n->param.addba_param, 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)
+		memcpy(addba_param, &cfg_11n->param.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
+ */
+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] != 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
+ */
+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] != 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_AGGRPRIOTBL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ADDBAREJECT))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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_MARVELL) + 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);
+	memcpy(vhtcfg, &cfg_11ac->param.vht_cfg, sizeof(mlan_ds_11ac_vht_cfg));
+	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++;
+		memcpy(vhtcfg, &cfg_11ac->param.vht_cfg,
+		       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.
+ */
+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_MARVELL) +
+			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;
+	memcpy(opermodecfg, &(cfg_11ac->param.opermode_cfg),
+	       sizeof(*opermodecfg));
+	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.
+ */
+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;
+
+	memcpy(data_rate, &rate->param.data_rate, sizeof(mlan_data_rate));
+
+	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.
+ */
+int
+woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[3];
+	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;
+
+	ENTER();
+
+	if (strlen(respbuf) ==
+	    (strlen(CMD_MARVELL) + strlen(PRIV_CMD_TXRATECFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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] >= 3)) {
+			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_VHT)
+				) {
+				PRINTM(MERROR, "Invalid format selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			rate->param.rate_cfg.rate_format = data[0];
+		}
+
+		if ((user_data_len >= 2) && (data[0] != AUTO_RATE)) {
+			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))
+				) {
+				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 ((user_data_len >= 3) && (data[0] != AUTO_RATE)) {
+			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];
+		}
+	}
+
+	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)
+			ratecfg->nss = rate->param.rate_cfg.nss;
+	}
+
+	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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+			memcpy(stats, &info->param.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.
+ */
+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.
+ */
+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 (strlen(respbuf) ==
+	    (strlen(CMD_MARVELL) + strlen(PRIV_CMD_ESUPPMODE))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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 (strlen(respbuf) ==
+	    (strlen(CMD_MARVELL) + 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_MARVELL) + 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);
+			strncpy((char *)sec->param.passphrase.ssid.ssid, end,
+				MIN(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;
+			memcpy(sec->param.passphrase.psk.passphrase.passphrase,
+			       end,
+			       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;
+	}
+
+	memset(respbuf, 0, respbuflen);
+	if (sec->param.passphrase.ssid.ssid_len) {
+		len += sprintf(respbuf + len, "ssid:");
+		memcpy(respbuf + len, sec->param.passphrase.ssid.ssid,
+		       sec->param.passphrase.ssid.ssid_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);
+
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DEAUTH))) {
+		/* Deauth mentioned BSSID */
+		woal_mac2u8(mac,
+			    respbuf + strlen(CMD_MARVELL) +
+			    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_MARVELL) + strlen(PRIV_CMD_AP_DEAUTH));
+	memset(&deauth_param, 0, sizeof(mlan_deauth_param));
+	memcpy(&deauth_param, data_ptr, 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;
+
+	memcpy(&bss->param.deauth_param, &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;
+	}
+
+	memcpy(data_ptr, &ioctl_req->status_code, sizeof(t_u32));
+	ret = sizeof(t_u32);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap get station list 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_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_MARVELL) +
+				     strlen(PRIV_CMD_GET_STA_LIST));
+	memcpy(sta_list, &info->param.sta_list, sizeof(mlan_ds_sta_list));
+	ret = sizeof(mlan_ds_sta_list);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap bss_config 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_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_MARVELL) + strlen(PRIV_CMD_BSS_CONFIG);
+	memcpy((u8 *)&action, respbuf + offset, 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 */
+		memcpy(&bss->param.bss_config, respbuf + offset,
+		       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) {
+		memcpy(respbuf + offset, &bss->param.bss_config,
+		       sizeof(mlan_uap_bss_param));
+	}
+	ret = sizeof(mlan_uap_bss_param);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if defined(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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_BSSROLE))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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 && V14_FEATURE */
+
+#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.
+ */
+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 */
+	memcpy((char *)&scan_cfg,
+	       respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_SETUSERSCAN),
+	       sizeof(wlan_user_scan_cfg));
+	memcpy(scan_cfg.random_mac, priv->random_mac, ETH_ALEN);
+	/* Call for scan */
+	if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_cfg))
+		ret = -EFAULT;
+
+	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
+ */
+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.
+ */
+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 */
+	memcpy(&scan_start,
+	       respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_GETSCANTABLE),
+	       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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_EXTCAPCFG);
+	if (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));
+		memcpy(&cfg->param.ext_cap, ie + 1, ie->len);
+	}
+
+	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);
+	memcpy(ie + 1, &cfg->param.ext_cap, sizeof(ExtCap_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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DEEPSLEEP))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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);
+		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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_WPSSESSION))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + 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_MARVELL) +
+			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]);
+		memcpy(respbuf, otp->user_data, ret);
+	}
+
+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.
+ */
+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_MARVELL) + 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);
+		memcpy(country_code->country_code, respbuf + header,
+		       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);
+		memcpy(respbuf, country_code->country_code, COUNTRY_CODE_LEN);
+	}
+
+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.
+ */
+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;
+	int header = 0, data_length = 0;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header = strlen(CMD_MARVELL) + strlen(PRIV_CMD_CFPINFO);
+	data_length = strlen(respbuf) - header;
+
+	/* 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;
+	}
+	memcpy(respbuf, (t_u8 *)req->pbuf, req->data_read_written);
+	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.
+ */
+int
+woal_priv_setgettcpackenh(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[1];
+	int ret = 0;
+	int user_data_len = 0;
+
+	ENTER();
+
+	if (strlen(respbuf) ==
+	    (strlen(CMD_MARVELL) + strlen(PRIV_CMD_TCPACKENH))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				strlen(PRIV_CMD_TCPACKENH), data,
+				ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len >= 2) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (user_data_len == 0) {
+		/* get operation */
+		respbuf[0] = priv->enable_tcp_ack_enh;
+	} else {
+		/* set operation */
+		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);
+		} else {
+			PRINTM(MERROR, "Unknown option = %u\n", data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		respbuf[0] = priv->enable_tcp_ack_enh;
+	}
+	ret = 1;
+
+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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_ASSOCBSSID);
+	else
+		header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ASSOCESSID);
+
+	if (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, (sizeof(buf) - 1));
+	memset(buf, 0, sizeof(buf));
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+	memcpy(buf, respbuf + header_len, buflen);
+	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 */
+	memcpy(ssid_bssid.ssid.ssid, buf + i,
+	       MIN(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;
+	}
+	memcpy(&priv->prev_ssid_bssid, &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.
+ */
+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_MARVELL) + 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_LISTENINTERVAL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_DRVDBG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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);
+
+	memcpy(respbuf, &drvdbg, sizeof(drvdbg));
+
+	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 "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
+ */
+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_MARVELL);
+
+	if (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 >
+		    MAX_MGMT_FRAME_FILTER * sizeof(mlan_mgmt_frame_wakeup)) {
+			PRINTM(MERROR, "%d: Invalid arguments\n", __LINE__);
+			ret = -EINVAL;
+			goto done;
+		}
+		memcpy((t_u8 *)pm_cfg->param.mgmt_filter, argument, data_len);
+		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
+ */
+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_MARVELL) + strlen(PRIV_CMD_HSCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		arguments =
+			respbuf + strlen(CMD_MARVELL) + 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] != 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 */
+		memcpy(respbuf, &hscfg, sizeof(mlan_ds_hs_cfg));
+		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
+ */
+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_MARVELL) + 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_MARVELL) +
+				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_MARVELL, PRIV_CMD_HSCFG,
+			respbuf + (strlen(CMD_MARVELL) +
+				   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
+ */
+int
+woal_priv_set_get_scancfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0;
+	int arg_len = 7;
+	int data[arg_len];
+	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_MARVELL) + strlen(PRIV_CMD_SCANCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_MARVELL) +
+				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] > 2)) {
+			PRINTM(MERROR, "Invalid argument for extended scan\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		memcpy(&scan->param.scan_cfg, data, sizeof(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) {
+		memcpy(respbuf, &scan->param.scan_cfg, sizeof(mlan_scan_cfg));
+		ret = sizeof(mlan_scan_cfg);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#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_MARVELL) + 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;
+		}
+		memcpy(&ssid_bssid.bssid, awrq->sa_data, ETH_ALEN);
+	}
+
+	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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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_MARVELL) + 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 (hw_test) {
+		PRINTM(MIOCTL, "block set power in hw_test mode\n");
+		LEAVE();
+		return ret;
+	}
+
+	data_ptr = respbuf + (strlen(CMD_MARVELL) + 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_MARVELL) + 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 */
+		memcpy(req_ssid.ssid, mwr->u.essid.pointer,
+		       MIN(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);
+		memcpy(&ssid_bssid.ssid, &req_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;
+		}
+	} 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);
+
+	/* 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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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_MARVELL) + 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)
+{
+	int ret = 0;
+	mlan_bss_info bss_info;
+	struct mwreq *mwr;
+	t_u8 *data_ptr;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_MARVELL) + 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) {
+		memcpy(mwr->u.ap_addr.sa_data, &bss_info.bssid,
+		       MLAN_MAC_ADDR_LENGTH);
+	} else {
+		memset(mwr->u.ap_addr.sa_data, 0, MLAN_MAC_ADDR_LENGTH);
+	}
+
+	mwr->u.ap_addr.sa_family = ARPHRD_ETHER;
+	ret = strlen(CMD_MARVELL) + 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_MARVELL) + 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_MARVELL) + 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_MARVELL) + strlen(PRIV_CMD_PSMODE);
+
+	if (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;
+	}
+
+	/* 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;
+
+	memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+	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;
+	int intf_num;
+	moal_handle *handle = priv->phandle;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+#if defined(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 && V14_FEATURE */
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	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);
+#if defined(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 && V14_FEATURE */
+	}
+
+	/* 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;
+		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) {
+			ret = -EFAULT;
+			if (status != MLAN_STATUS_PENDING)
+				kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+
+	/* 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 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_MARVELL) + strlen(PRIV_CMD_TXPOWERCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		arguments =
+			respbuf + strlen(CMD_MARVELL) +
+			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 */
+		memcpy(respbuf, (t_u8 *)&pcfg->param.power_ext,
+		       sizeof(pcfg->param.power_ext.num_pwr_grp) +
+		       (pcfg->param.power_ext.num_pwr_grp *
+			sizeof(mlan_power_group)));
+		ret = sizeof(pcfg->param.power_ext.num_pwr_grp) +
+			(pcfg->param.power_ext.num_pwr_grp *
+			 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 ad-hoc awake period parameter */
+	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_MARVELL) + strlen(PRIV_CMD_PSCFG);
+
+	if (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] != SPECIAL_ADHOC_AWAKE_PD) &&
+		    ((data[i] < MIN_ADHOC_AWAKE_PD) ||
+		     (data[i] > MAX_ADHOC_AWAKE_PD))) {
+			PRINTM(MERROR,
+			       "Invalid argument for adhoc awake period\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		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;
+		memcpy(&pm_cfg->param.ps_cfg, data,
+		       MIN(sizeof(pm_cfg->param.ps_cfg), sizeof(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;
+	}
+	memcpy(data, &pm_cfg->param.ps_cfg,
+	       MIN((sizeof(int) * allowed), sizeof(pm_cfg->param.ps_cfg)));
+	memcpy(respbuf, (t_u8 *)data, sizeof(int) * allowed);
+	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_MARVELL) + 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_MARVELL) + strlen(PRIV_CMD_SLEEPPD);
+
+	if (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");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	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;
+		memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_TXCONTROL);
+
+	if (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");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	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;
+		memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_REGRDWR);
+
+	if (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) {
+		memcpy(respbuf, &reg_mem->param.reg_rw,
+		       sizeof(reg_mem->param.reg_rw));
+		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_MARVELL) + strlen(PRIV_CMD_RDEEPROM);
+
+	if (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) {
+		memcpy(respbuf, &reg_mem->param.rd_eeprom,
+		       sizeof(reg_mem->param.rd_eeprom));
+		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_MARVELL) + strlen(PRIV_CMD_MEMRDWR);
+
+	if (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) {
+		memcpy(respbuf, &reg_mem->param.mem_rw,
+		       sizeof(reg_mem->param.mem_rw));
+		ret = sizeof(reg_mem->param.mem_rw);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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_MARVELL) + strlen(PRIV_CMD_SDCMD52RW);
+	memset((t_u8 *)buf, 0, sizeof(buf));
+
+	if (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) {
+		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 {
+		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;
+		}
+	}
+
+	/* Action = GET */
+	buf[0] = data;
+
+	memcpy(respbuf, &buf, sizeof(int));
+	ret = sizeof(int);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#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_MARVELL) + strlen(PRIV_CMD_ARPFILTER));
+	buf_len = *((t_u16 *)data_ptr);
+	misc->param.gen_ie.len = buf_len;
+	memcpy((void *)(misc->param.gen_ie.ie_data), data_ptr + sizeof(buf_len),
+	       buf_len);
+
+	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 */
+
+#if defined(SDIO_SUSPEND_RESUME)
+/**
+ *  @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.
+ */
+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_MARVELL) + 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_MARVELL) +
+				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");
+	}
+
+	memcpy(respbuf, &handle->hs_auto_arp, sizeof(handle->hs_auto_arp));
+	ret = sizeof(handle->hs_auto_arp);
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @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_MARVELL) + strlen(PRIV_CMD_DEAUTH_CTRL);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	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_MARVELL) + strlen(PRIV_CMD_PER_PKT_CFG);
+	pos = respbuf + header_len;
+	left_len = respbuflen - header_len;
+
+	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;
+			memcpy(perpkt->ether_type, priv->tx_protocols.protocols,
+			       perpkt->proto_type_num * 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;
+			memcpy(perpkt->ether_type, priv->rx_protocols.protocols,
+			       perpkt->proto_type_num * 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)
+					memcpy(priv->tx_protocols.protocols,
+					       perpkt->ether_type,
+					       perpkt->proto_type_num *
+					       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)
+					memcpy(priv->rx_protocols.protocols,
+					       perpkt->ether_type,
+					       perpkt->proto_type_num *
+					       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);
+		}
+	}
+	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 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
+ */
+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_MARVELL) + strlen(PRIV_CMD_MGMT_FRAME_CTRL);
+	if (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;
+	memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+	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_MARVELL) + 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));
+
+	memcpy((t_u8 *)&addts_ioctl, data_ptr, sizeof(addts_ioctl));
+
+	cfg->param.addts.timeout = addts_ioctl.timeout_ms;
+	cfg->param.addts.ie_data_len = addts_ioctl.ie_data_len;
+
+	memcpy(cfg->param.addts.ie_data,
+	       addts_ioctl.ie_data, cfg->param.addts.ie_data_len);
+
+	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;
+
+	memcpy(addts_ioctl.ie_data,
+	       cfg->param.addts.ie_data, cfg->param.addts.ie_data_len);
+
+	copy_len = (sizeof(addts_ioctl)
+		    - sizeof(addts_ioctl.ie_data)
+		    + cfg->param.addts.ie_data_len);
+
+	memcpy(respbuf, (t_u8 *)&addts_ioctl, copy_len);
+	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_MARVELL) + 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 (strlen(respbuf) > header_len) {
+		copy_len = MIN(strlen(data_ptr), sizeof(delts_ioctl));
+		memcpy((t_u8 *)&delts_ioctl, data_ptr, copy_len);
+
+		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;
+
+		memcpy(cfg->param.delts.ie_data,
+		       delts_ioctl.ie_data, cfg->param.delts.ie_data_len);
+
+		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);
+		memcpy(respbuf, (t_u8 *)&delts_ioctl, copy_len);
+		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_MARVELL) + strlen(PRIV_CMD_QCONFIG));
+
+	memcpy((t_u8 *)&qcfg_ioctl, data_ptr, 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;
+	memcpy(data_ptr, (t_u8 *)&qcfg_ioctl, sizeof(qcfg_ioctl));
+	ret = strlen(CMD_MARVELL) + 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_MARVELL) + 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 (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));
+		memcpy((void *)&qstatus_ioctl, (void *)&pwmm->param.q_status,
+		       sizeof(qstatus_ioctl));
+		memcpy(respbuf, (t_u8 *)&qstatus_ioctl, sizeof(qstatus_ioctl));
+		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_MARVELL) + 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));
+
+	memcpy((t_u8 *)&ts_status_ioctl, data_ptr, 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));
+	memcpy((void *)&ts_status_ioctl, (void *)&pwmm->param.ts_status,
+	       sizeof(ts_status_ioctl));
+	memcpy(respbuf, (t_u8 *)&ts_status_ioctl, sizeof(ts_status_ioctl));
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_MAC_CTRL);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.mac_ctrl, sizeof(data));
+	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
+ */
+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) {
+			memcpy(respbuf, (t_u8 *)&bss_info.bssid,
+			       MLAN_MAC_ADDR_LENGTH);
+		} 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) {
+			memcpy(respbuf, priv->current_addr,
+			       MLAN_MAC_ADDR_LENGTH);
+		} 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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_REGION_CODE);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.region_code, sizeof(data));
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get channel time and buffer weight
+ *
+ *  @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.
+ */
+int
+woal_priv_multi_chan_config(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	t_u8 *data_ptr;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr =
+		respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_MULTI_CHAN_CFG);
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_MULTI_CHAN_CFG);
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		user_data_len = sizeof(mlan_ds_multi_chan_cfg);
+	}
+
+	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_MULTI_CHAN_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		memcpy(&cfg->param.multi_chan_cfg, data_ptr,
+		       sizeof(mlan_ds_multi_chan_cfg));
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, (mlan_ds_multi_chan_cfg *)&cfg->param.multi_chan_cfg,
+	       req->buf_len);
+	ret = req->buf_len;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get multi_channel policy 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.
+ */
+int
+woal_priv_multi_chan_policy(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	int data = 0;
+	t_u16 enable;
+	t_u8 action;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_MULTI_CHAN_POLICY);
+	if (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;
+	}
+
+	if (user_data_len == 0) {
+		action = MLAN_ACT_GET;
+	} else {
+		action = MLAN_ACT_SET;
+		enable = (t_u16)data;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_mc_policy_cfg(priv, &enable, MOAL_IOCTL_WAIT, action)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memcpy(respbuf, &enable, sizeof(t_u16));
+	ret = sizeof(t_u16);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get drcs time slicing 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.
+ */
+int
+woal_priv_drcs_time_slicing_cfg(moal_private *priv, t_u8 *respbuf,
+				t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_ds_drcs_cfg *drcs_cfg = NULL;
+	t_u8 *data_ptr;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	int data[8];
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr = respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_DRCS_CFG);
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_DRCS_CFG);
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(data_ptr, data, ARRAY_SIZE(data),
+				&user_data_len);
+	}
+
+	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_DRCS_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		drcs_cfg = (mlan_ds_drcs_cfg *) & cfg->param.drcs_cfg[0];
+		drcs_cfg->chantime = (t_u8)data[0];
+		drcs_cfg->switchtime = (t_u8)data[1];
+		drcs_cfg->undozetime = (t_u8)data[2];
+		drcs_cfg->mode = (t_u8)data[3];
+		/* Set the same parameters for two channels */
+		if (user_data_len < ARRAY_SIZE(data))
+			drcs_cfg->chan_idx = 0x03;
+		else {
+			/* Set the different parameters for two channels */
+			drcs_cfg->chan_idx = 0x1;
+			drcs_cfg =
+				(mlan_ds_drcs_cfg *) & cfg->param.drcs_cfg[1];
+			drcs_cfg->chan_idx = 0x2;
+			drcs_cfg->chantime = (t_u8)data[4];
+			drcs_cfg->switchtime = (t_u8)data[5];
+			drcs_cfg->undozetime = (t_u8)data[6];
+			drcs_cfg->mode = (t_u8)data[7];
+		}
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.drcs_cfg, req->buf_len);
+	ret = req->buf_len;
+
+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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_RX_COAL_CFG);
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_RX_COAL_CFG);
+	if (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;
+	}
+
+	memcpy(respbuf,
+	       (mlan_ds_misc_rx_packet_coalesce *)&cfg->param.rx_coalesce,
+	       req->buf_len);
+	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
+ */
+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_MARVELL) + 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 (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);
+		memcpy(bss->param.mac_addr, data, ETH_ALEN);
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, bss->param.mac_addr, sizeof(data));
+	ret = sizeof(data);
+	HEXDUMP("FW MAC Addr:", respbuf, ETH_ALEN);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_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
+ */
+int
+woal_priv_offchannel(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[3];
+	int ret = 0;
+	t_u8 status = 1;
+	int user_data_len = 0, header_len = 0;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_OFFCHANNEL);
+
+	if (header_len == 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 (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
+					   )), 0, (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
+ */
+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_MARVELL) + strlen(PRIV_CMD_DSCP_MAP);
+	if (strlen(respbuf) != header_len) {
+		/* SET operation */
+		pos = respbuf + header_len;
+		memcpy(priv->dscp_map, pos, sizeof(priv->dscp_map));
+	}
+
+	copy_size = MIN(sizeof(priv->dscp_map), respbuflen);
+	memcpy(respbuf, priv->dscp_map, copy_size);
+	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.
+ */
+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_MARVELL) + strlen(PRIV_CMD_VEREXT);
+
+	if (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);
+	memcpy(respbuf, info->param.ver_ext.version_str, copy_size);
+	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;
+}
+
+#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_MARVELL) + strlen(PRIV_CMD_RADIO_CTRL);
+
+	if (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);
+		memcpy(respbuf, &bss_info.radio_on, sizeof(bss_info.radio_on));
+		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_MARVELL) + strlen(PRIV_CMD_WMM_CFG);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &wmm->param.wmm_enable, sizeof(wmm->param.wmm_enable));
+	ret = sizeof(wmm->param.wmm_enable);
+
+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_MARVELL) + strlen(PRIV_CMD_11D_CFG);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &pcfg_11d->param.enable_11d,
+	       sizeof(pcfg_11d->param.enable_11d));
+	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_MARVELL) + strlen(PRIV_CMD_11D_CLR_TBL);
+
+	if (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
+
+/**
+ *  @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_MARVELL) + strlen(PRIV_CMD_WWS_CFG);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &wws->param.wws_cfg, sizeof(wws->param.wws_cfg));
+	ret = sizeof(wws->param.wws_cfg);
+
+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 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_MARVELL) + strlen(PRIV_CMD_REASSOCTRL);
+
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		data = (int)(priv->reassoc_on);
+		memcpy(respbuf, &data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_TXBUF_CFG);
+
+	if (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;
+	memcpy(respbuf, &buf_size, sizeof(buf_size));
+	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_MARVELL) + strlen(PRIV_CMD_AUTH_TYPE);
+
+	if (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;
+		memcpy(respbuf, &auth_type, sizeof(auth_type));
+		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_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;
+			}
+		} 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_MARVELL) + strlen(PRIV_CMD_POWER_CONS);
+
+	if (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;
+		memcpy(respbuf, &data, sizeof(data));
+		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_MARVELL) + strlen(PRIV_CMD_HT_STREAM_CFG);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	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_MARVELL) + strlen(PRIV_CMD_MIMO_SWITCH);
+
+	if (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_MARVELL) + strlen(PRIV_CMD_THERMAL);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	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_MARVELL) + strlen(PRIV_CMD_BCN_INTERVAL);
+
+	if (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;
+	memcpy(respbuf, &data, sizeof(data));
+	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 buflen = 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_MARVELL) + strlen(PRIV_CMD_GET_SIGNAL);
+
+	if (strlen(respbuf) != header_len)
+		parse_arguments(respbuf + header_len, in_data, IN_DATA_SIZE,
+				&user_data_len);
+	buflen = MIN(user_data_len, IN_DATA_SIZE);
+
+	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;
+	}
+
+	memcpy(respbuf, out_data, (data_length * sizeof(int)));
+	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_MARVELL) + strlen(PRIV_CMD_GET_SIGNAL_EXT);
+
+	if (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) {
+		memcpy(signal_get, info->param.signal_ext, sizeof(signal_get));
+		path_num = MAX_PATH_NUM;
+	} else
+		memcpy(signal_get, info->param.signal_ext,
+		       sizeof(mlan_ds_get_signal));
+
+	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;
+	}
+	memcpy(respbuf, out_data,
+	       (MIN((PATH_SIZE * MAX_PATH_NUM), data_len) * sizeof(int)));
+	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_MARVELL) + strlen(PRIV_CMD_GET_SIGNAL_EXT_V2);
+	if (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) {
+		memcpy(signal_get, info->param.signal_ext, sizeof(signal_get));
+		path_num = MAX_PATH_NUM;
+	} else
+		memcpy(signal_get, info->param.signal_ext,
+		       sizeof(mlan_ds_get_signal));
+
+	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;
+	}
+	memcpy(respbuf, out_data,
+	       (MIN((PATH_SIZE * MAX_PATH_NUM), data_len) * sizeof(int)));
+	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_MARVELL) + strlen(PRIV_CMD_SIGNALEXT_CFG);
+	if (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
+ */
+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();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_PMFCFG);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&cfg->param.pmfcfg,
+	       sizeof(mlan_ds_misc_pmfcfg));
+	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_MARVELL) + strlen(PRIV_CMD_INACTIVITYTO);
+	memset(data, 0, sizeof(data));
+	if (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;
+
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get ATIM window
+ * @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_atim_window(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	int ret = 0, atim = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ATIM_WINDOW);
+	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_ATIM_WINDOW;
+	req->req_id = MLAN_IOCTL_BSS;
+
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &atim, 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;
+		bss->param.atim_window = atim;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, (t_u8 *)&bss->param.atim_window, sizeof(int));
+	ret = sizeof(int);
+
+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];
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + 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 (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;
+
+	memcpy(respbuf, (t_u8 *)data, sizeof(data));
+	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_MARVELL) + 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 (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;
+
+	memcpy(respbuf, (t_u8 *)&bf_cap, sizeof(bf_cap));
+	ret = sizeof(bf_cap);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @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_MARVELL) + strlen(PRIV_CMD_SDIO_CLOCK);
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		memcpy(respbuf, (t_u8 *)&clock_state, sizeof(clock_state));
+		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;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ * @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_MARVELL) + strlen(PRIV_CMD_MPA_CTRL);
+	if (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]);
+
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		ret = sizeof(data);
+		goto done;
+	}
+
+	switch (user_data_len) {
+	case 6:
+		misc->param.mpa_ctrl.rx_max_ports = data[5];
+	case 5:
+		misc->param.mpa_ctrl.tx_max_ports = data[4];
+	case 4:
+		misc->param.mpa_ctrl.rx_buf_size = data[3];
+	case 3:
+		misc->param.mpa_ctrl.tx_buf_size = data[2];
+	case 2:
+		misc->param.mpa_ctrl.rx_enable = data[1];
+	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[][35] = { {"sleep clock error in ppm"},
+	{"wakeup offset in usec"},
+	{"clock stabilization time in usec"},
+	{"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_MARVELL) + strlen(PRIV_CMD_SLEEP_PARAMS);
+	if (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;
+
+	memcpy(respbuf, (t_u8 *)data, sizeof(data));
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get network monitor configurations
+ *
+ * @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_net_monitor_ioctl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int user_data_len = 0, header_len = 0;
+	int data_length = 0;
+	int data[5] = { 0 };
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_net_monitor *net_mon = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = priv->phandle;
+	monitor_iface *mon_if = NULL;
+	struct net_device *ndev = NULL;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_NET_MON);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
+	misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if (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 || user_data_len == 2 ||
+		    user_data_len == 4 || user_data_len == 5) {
+			if (data[0] != MTRUE && data[0] != MFALSE) {
+				PRINTM(MERROR,
+				       "NET_MON: Activity should be enable(=1)/"
+				       "disable(=0)\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			net_mon->enable_net_mon = data[0];
+			if (data[0] == MTRUE) {
+				int i;
+				if (user_data_len != 2 && user_data_len != 4
+				    && user_data_len != 5) {
+					PRINTM(MERROR,
+					       "NET_MON: Invalid number of args!\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				/* Supported filter flags */
+				if (!data[1] || data[1] &
+				    ~(MLAN_NETMON_DATA | MLAN_NETMON_MANAGEMENT
+				      | MLAN_NETMON_CONTROL | MLAN_NETMON_NOPROM
+				      | MLAN_NETMON_DECRYPTED)) {
+					PRINTM(MERROR,
+					       "NET_MON: Invalid filter flag\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				if (user_data_len > 2) {
+					/* Supported bands */
+					for (i = 0;
+					     i < sizeof(SupportedAdhocBand);
+					     i++)
+						if (data[2] ==
+						    SupportedAdhocBand[i])
+							break;
+					if (i == sizeof(SupportedAdhocBand)) {
+						PRINTM(MERROR,
+						       "NET_MON: Invalid band\n");
+						ret = -EINVAL;
+						goto done;
+					}
+				}
+				/* Supported channel */
+				if (user_data_len > 3 &&
+				    (data[3] < 1 ||
+				     data[3] > MLAN_MAX_CHANNEL)) {
+					PRINTM(MERROR,
+					       "NET_MON: Invalid channel number\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				if (user_data_len == 5) {
+					/* Secondary channel offset */
+					if (!(data[2] & (BAND_GN | BAND_AN))) {
+						PRINTM(MERROR,
+						       "No 11n in band, can not set "
+						       "secondary channel offset\n");
+						ret = -EINVAL;
+						goto done;
+					}
+					if ((data[4] != CHANNEL_BW_20MHZ) &&
+					    (data[4] != CHANNEL_BW_40MHZ_ABOVE)
+					    && (data[4] !=
+						CHANNEL_BW_40MHZ_BELOW)
+					    && (data[4] != CHANNEL_BW_80MHZ)
+						) {
+						PRINTM(MERROR,
+						       "Invalid secondary channel bandwidth, "
+						       "only allowed 0, 1, 3 or 4\n");
+						ret = -EINVAL;
+						goto done;
+					}
+					net_mon->chan_bandwidth = data[4];
+				}
+
+				net_mon->filter_flag = data[1];
+				net_mon->band = data[2];
+				net_mon->channel = data[3];
+			}
+			req->action = MLAN_ACT_SET;
+		} else {
+			PRINTM(MERROR, "NET_MON: Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "NET_MON: woal_request_ioctl fail\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_SET) {
+		if (data[0]) {
+			/* Enable sniffer mode */
+			if (!handle->mon_if) {
+				mon_if = woal_prepare_mon_if(priv, "rtap", 0);
+				if (!mon_if) {
+					PRINTM(MFATAL,
+					       "Prepare mon_if fail.\n");
+					ret = -EFAULT;
+					goto done;
+				}
+				ndev = mon_if->mon_ndev;
+				ret = register_netdevice(ndev);
+				if (ret) {
+					PRINTM(MFATAL,
+					       "register net_device failed, ret=%d\n",
+					       ret);
+					free_netdev(ndev);
+					ret = -EFAULT;
+					goto done;
+				}
+				handle->mon_if = mon_if;
+			}
+			/* Save band channel config */
+			handle->mon_if->band_chan_cfg.band = net_mon->band;
+			handle->mon_if->band_chan_cfg.channel =
+				net_mon->channel;
+			handle->mon_if->band_chan_cfg.chan_bandwidth =
+				net_mon->chan_bandwidth;
+		} else {
+			/* Disable sniffer mode */
+			if (handle->mon_if) {
+				ndev = handle->mon_if->mon_ndev;
+				handle->mon_if = NULL;
+				unregister_netdevice(ndev);
+			}
+		}
+	}
+
+	data[0] = net_mon->enable_net_mon;
+	data[1] = net_mon->filter_flag;
+	data[2] = net_mon->band;
+	data[3] = net_mon->channel;
+	data[4] = net_mon->chan_bandwidth;
+	data_length = 5;
+	memcpy(respbuf, (t_u8 *)data, sizeof(int) * data_length);
+	ret = sizeof(int) * data_length;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ * @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[4];
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + 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 (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 != 4) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[0] > 0xFFFFF) {
+			PRINTM(MERROR,
+			       "The maximum user CAC is 1048575 msec (17 mins approx).\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[1] > 0xFFFFF) {
+			PRINTM(MERROR,
+			       "The maximum user NOP is 1048575 msec (17 mins approx).\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_u32)data[0];
+		ds_11hcfg->param.dfs_testing.usr_nop_period_sec =
+			(t_u32)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 / 1000;
+		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;
+		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;
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif /* DFS_SUPPORT && DFS_TESTING_SUPPORT */
+
+/**
+ * @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];
+	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_MARVELL) + 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 (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;
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		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_MARVELL) + 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 (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;
+		}
+		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];
+		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) {
+		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;
+		memcpy(respbuf, (t_u8 *)data, 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_MARVELL) + strlen(PRIV_CMD_CWMODE);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&misc->param.cwmode,
+	       sizeof(misc->param.cwmode));
+	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_MARVELL) + 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 (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 || data[1] > 15)) {
+					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;
+	memcpy(respbuf, (t_u8 *)data, sizeof(data));
+	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_MARVELL) + strlen(PRIV_CMD_SYSCLOCK);
+	memset(data, 0, sizeof(data));
+	if (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++;
+
+		memcpy(respbuf, data, sizeof(int) * data_length);
+		ret = data_length * sizeof(int);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/** AES key length */
+#define AES_KEY_LEN 16
+/**
+ * @brief               Adhoc AES control
+ * @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_adhoc_aes(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	static char buf[256];
+	int ret = 0, action = -1;
+	unsigned int i;
+	t_u8 key_ascii[32];
+	t_u8 key_hex[16];
+	t_u8 *tmp;
+	mlan_bss_info bss_info;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	int header_len = 0;
+	int copy_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ADHOC_AES);
+	memset(key_ascii, 0x00, sizeof(key_ascii));
+	memset(key_hex, 0x00, sizeof(key_hex));
+	memset(buf, 0x00, sizeof(buf));
+
+	/* Get current BSS information */
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (bss_info.bss_mode != MLAN_BSS_MODE_IBSS ||
+	    bss_info.media_connected == MTRUE) {
+		PRINTM(MERROR, "STA is connected or not in IBSS mode.\n");
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (strlen(respbuf) == header_len) {
+		/* Get Adhoc AES 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_CFG_ENCRYPT_KEY;
+		sec->param.encrypt_key.key_len = AES_KEY_LEN;
+		sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_UNICAST;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memcpy(key_hex, sec->param.encrypt_key.key_material,
+		       sizeof(key_hex));
+		HEXDUMP("Adhoc AES Key (HEX)", key_hex, sizeof(key_hex));
+
+		tmp = key_ascii;
+		for (i = 0; i < sizeof(key_hex); i++)
+			tmp += sprintf((char *)tmp, "%02x", key_hex[i]);
+	} else {
+		/* SET operation */
+		copy_len = (strlen(respbuf) - header_len);
+		if (copy_len >= sizeof(buf)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		memcpy(buf, respbuf + header_len, copy_len);
+
+		/* Parse the buf to get the cmd_action */
+		action = woal_atox(&buf[0]);
+		if (action < 1 || action > 2) {
+			PRINTM(MERROR, "Invalid action argument %d\n", action);
+			ret = -EINVAL;
+			goto done;
+		}
+
+		req->req_id = MLAN_IOCTL_SEC_CFG;
+		req->action = MLAN_ACT_SET;
+		sec = (mlan_ds_sec_cfg *)req->pbuf;
+		sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+
+		if (action == 1) {
+			/* Set Adhoc AES Key  */
+			memcpy(key_ascii, &buf[2], sizeof(key_ascii));
+			woal_ascii2hex(key_hex, (char *)key_ascii,
+				       sizeof(key_hex));
+			HEXDUMP("Adhoc AES Key (HEX)", key_hex,
+				sizeof(key_hex));
+
+			sec->param.encrypt_key.key_len = AES_KEY_LEN;
+			sec->param.encrypt_key.key_index =
+				MLAN_KEY_INDEX_UNICAST;
+			sec->param.encrypt_key.key_flags =
+				KEY_FLAG_SET_TX_KEY | KEY_FLAG_GROUP_KEY;
+			memcpy(sec->param.encrypt_key.mac_addr,
+			       (u8 *)bcast_addr, ETH_ALEN);
+			memcpy(sec->param.encrypt_key.key_material, key_hex,
+			       sec->param.encrypt_key.key_len);
+
+			status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				ret = -EFAULT;
+				goto done;
+			}
+		} else {
+			/* Clear Adhoc AES Key */
+			sec->param.encrypt_key.key_len = AES_KEY_LEN;
+			sec->param.encrypt_key.key_index =
+				MLAN_KEY_INDEX_UNICAST;
+			sec->param.encrypt_key.key_flags = KEY_FLAG_REMOVE_KEY;
+			memcpy(sec->param.encrypt_key.mac_addr,
+			       (u8 *)bcast_addr, ETH_ALEN);
+			memset(sec->param.encrypt_key.key_material, 0,
+			       sizeof(sec->param.encrypt_key.key_material));
+
+			status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	}
+
+	HEXDUMP("Adhoc AES Key (ASCII)", key_ascii, sizeof(key_ascii));
+	copy_len = sizeof(key_ascii);
+	memcpy(respbuf, &key_ascii, copy_len);
+	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_MARVELL) + strlen(PRIV_CMD_ASSOCIATE);
+	if (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, (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;
+	}
+
+	memcpy(buf, respbuf + header_len, buflen);
+
+	/* 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;
+	memcpy(ssid_bssid.ssid.ssid, buf + i, 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)) {
+		memcpy(&priv->prev_ssid_bssid.ssid,
+		       &bss_info.ssid, sizeof(mlan_802_11_ssid));
+		memcpy(&priv->prev_ssid_bssid.bssid,
+		       &bss_info.bssid, MLAN_MAC_ADDR_LENGTH);
+	}
+#endif /* REASSOCIATION */
+
+done:
+	LEAVE();
+	return 0;
+}
+
+/* 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 MAX_TX_BF_GLOBAL_ARGS   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;
+	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;
+	mlan_tx_sounding_cfg_args *tx_sounding_cfg = NULL;
+
+	ENTER();
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_TX_BF_CFG);
+	if (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;
+	tx_sounding_cfg = &bf_cfg.body.tx_sounding_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 > sizeof(buf)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		memcpy(buf, respbuf + header_len, copy_len);
+
+		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;
+		case TX_SOUNDING_CFG:
+			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 1:	//the 1st parameter: enable /disable (1/0) tx sounding
+						tx_sounding_cfg->
+							tx_sounding_enbl =
+							(t_u8)tmp_val;
+						break;
+					case 2:	//the 2nd parameter (sounding type: HT:1, vHT:2)
+						tx_sounding_cfg->sounding_type =
+							(t_u8)tmp_val;
+						break;
+					case 3:	//the 3rd parameter: sounding period: ms
+						tx_sounding_cfg->
+							sounding_interval =
+							(t_u16)tmp_val;
+						break;
+					default:
+						PRINTM(MERROR,
+						       "Invalid Argument\n");
+						ret = -EINVAL;
+						goto done;
+					}
+				}
+			}
+			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:
+		memcpy(respbuf, bf_global, sizeof(mlan_bf_global_cfg_args));
+		ret = sizeof(mlan_bf_global_cfg_args);
+		break;
+	case TRIGGER_SOUNDING_FOR_PEER:
+		memcpy(respbuf, bf_sound, sizeof(mlan_bf_global_cfg_args));
+		ret = sizeof(mlan_bf_global_cfg_args);
+		break;
+	case SET_GET_BF_PERIODICITY:
+		memcpy(respbuf, bf_periodicity,
+		       sizeof(mlan_bf_periodicity_args));
+		ret = sizeof(mlan_bf_periodicity_args);
+		break;
+	case TX_BF_FOR_PEER_ENBL:
+		memcpy(respbuf, tx_bf_peer, sizeof(mlan_tx_bf_peer_args));
+		ret = sizeof(mlan_tx_bf_peer_args);
+		break;
+	case SET_SNR_THR_PEER:
+		memcpy(respbuf, bf_snr, sizeof(mlan_snr_thr_args));
+		ret = sizeof(mlan_snr_thr_args);
+		break;
+	case TX_SOUNDING_CFG:
+		memcpy(respbuf, tx_sounding_cfg,
+		       sizeof(mlan_tx_sounding_cfg_args));
+		ret = sizeof(mlan_tx_sounding_cfg_args);
+		break;
+	default:
+		ret = 0;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @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, func, 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_MARVELL) + 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;
+	}
+	memcpy(&cmd_len, respbuf + header_len, sizeof(cmd_len));
+	buf = respbuf + header_len + sizeof(cmd_len);
+
+	rw = buf[0];		/* read/write (0/1) */
+	func = buf[1];		/* func (0/1/2) */
+	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, func = %d, addr = %#x, mode = %d, "
+	       "block size = %d, block(byte) number = %d\n",
+	       func, 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 < 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;
+}
+
+/**
+ * @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_MARVELL) + strlen(PRIV_CMD_PORT_CTRL);
+	if (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) {
+		memcpy(respbuf, &sec->param.port_ctrl_enabled, sizeof(int));
+		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_MARVELL) + 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);
+
+	memcpy(skb_put(skb, copyLen), respbuf + header_len, 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               Control Coalescing status Enable/Disable
+ * @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_coalescing_status(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data = 0;
+	mlan_ds_misc_cfg *pcoal = 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;
+	}
+	pcoal = (mlan_ds_misc_cfg *)req->pbuf;
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_COALESCE_STATUS);
+	if (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) {
+			if (data == 1)
+				pcoal->param.coalescing_status =
+					MLAN_MISC_COALESCING_ENABLE;
+			else
+				pcoal->param.coalescing_status =
+					MLAN_MISC_COALESCING_DISABLE;
+			req->action = MLAN_ACT_SET;
+		} else {
+			PRINTM(MERROR, "Invalid number of parameters\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	pcoal->sub_command = MLAN_OID_MISC_COALESCING_STATUS;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	data = (int)(((mlan_ds_misc_cfg *)req->pbuf)->param.coalescing_status);
+
+	memcpy(respbuf, &data, sizeof(int));
+	ret = sizeof(int);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get module 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_fw_wakeup_method(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[2];
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	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;
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_FW_WAKEUP_METHOD);
+	if (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 > 2) {
+			PRINTM(MERROR, "Invalid parameter number\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] != FW_WAKEUP_METHOD_INTERFACE &&
+		    data[0] != FW_WAKEUP_METHOD_GPIO) {
+			PRINTM(MERROR, "Invalid FW wake up method:%d\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == FW_WAKEUP_METHOD_GPIO) {
+			if (user_data_len == 1) {
+				PRINTM(MERROR,
+				       "Please provide gpio pin number for FW_WAKEUP_METHOD gpio\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			pm_cfg->param.fw_wakeup_params.gpio_pin = data[1];
+		}
+
+		req->action = MLAN_ACT_SET;
+		pm_cfg->param.fw_wakeup_params.method = data[0];
+	}
+
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_FW_WAKEUP_METHOD;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = ((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.method;
+	data[1] =
+		((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.gpio_pin;
+	memcpy(respbuf, &data, sizeof(data));
+	ret = sizeof(int) * 2;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	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];
+	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 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_MARVELL) + strlen(PRIV_CMD_BOOTSLEEP);
+
+	if (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;
+	}
+
+	memcpy(respbuf, &misc->param.boot_sleep,
+	       sizeof(misc->param.boot_sleep));
+	ret = sizeof(misc->param.boot_sleep);
+
+	PRINTM(MIOCTL, "boot sleep cfg: 0x%u\n", misc->param.boot_sleep);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief                    Keep connect to refuse disconnect
+ * @param priv            Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return                 0 for success, negative for failure.
+ */
+static int
+woal_priv_keep_connect(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int user_data_len = 0;
+	int keep_connect_en = 0;
+	int ret = 0;
+
+	ENTER();
+	parse_arguments(respbuf, &keep_connect_en,
+			sizeof(keep_connect_en) / sizeof(int), &user_data_len);
+	if (!user_data_len) {
+		PRINTM(MERROR, "Invalid parameter number\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (keep_connect_en != 0 && keep_connect_en != 1) {
+		PRINTM(MERROR, "Invalid agrs!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (keep_connect_en == 1) {
+		priv->keep_connect = MTRUE;
+	} else {
+		priv->keep_connect = MFALSE;
+	}
+
+done:
+	LEAVE();
+	return 0;
+}
+
+#if defined(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_MARVELL) + 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 (strlen(respbuf) == header_len) {
+		/* GET operation */
+		memcpy(respbuf, &noa_cfg, sizeof(noa_cfg));
+		ret = sizeof(noa_cfg);
+	} else {
+		switch (user_data_len) {
+		case 5:
+			noa_cfg.noa_interval = (t_u32)data[4];
+		case 4:
+			noa_cfg.noa_duration = (t_u32)data[3];
+		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];
+		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];
+		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_MARVELL) + 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 (strlen(respbuf) == header_len) {
+		/* GET operation */
+		memcpy(respbuf, &opp_ps_cfg, sizeof(opp_ps_cfg));
+		ret = sizeof(opp_ps_cfg);
+	} else {
+		switch (user_data_len) {
+		case 2:
+			opp_ps_cfg.ct_window = (t_u8)data[1];
+		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;
+		default:
+			break;
+		}
+		woal_p2p_config(priv, MLAN_ACT_SET, &opp_ps_cfg);
+	}
+
+done:
+
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+#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];
+	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_MARVELL) + 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 (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) {
+		memcpy(respbuf, (t_u8 *)dfs_repeater,
+		       sizeof(mlan_ds_misc_dfs_repeater));
+		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_MARVELL) + strlen(PRIV_CMD_MIRACAST_CFG);
+
+	if (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;
+
+		memcpy(respbuf, (t_u8 *)data, sizeof(data));
+		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
+ */
+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_MARVELL) + 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 (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) {
+		memcpy(respbuf, (t_u8 *)&cfg_11n->param.coex_rx_winsize,
+		       sizeof(t_u32));
+		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_MARVELL) + 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 (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) {
+		memcpy(respbuf, (t_u8 *)&cfg_11n->param.txaggrctrl,
+		       sizeof(t_u32));
+		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_MARVELL) + strlen(PRIV_CMD_AUTO_TDLS);
+
+	if (strlen(respbuf) == header_len) {
+		/* GET operation */
+		data = priv->enable_auto_tdls;
+		memcpy(respbuf, (t_u8 *)&data, sizeof(data));
+		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;
+}
+
+/**
+ * @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);
+	memcpy(respbuf, &pcfg->param.sensor_temp.temperature, sizeof(t_u32));
+
+	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;
+
+	ENTER();
+
+	if (priv && priv->wdev)
+		wiphy = priv->wdev->wiphy;
+	if (!wiphy) {
+		PRINTM(MERROR, "wiphy is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	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_MARVELL) + 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;
+		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 (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_MARVELL) + strlen(PRIV_CMD_TDLS_IDLE_TIME);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&misc->param.tdls_idle_time, sizeof(t_u16));
+	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_MARVELL) + strlen(PRIV_CMD_DYN_BW);
+	if (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;
+	}
+
+	memcpy(respbuf, (t_u8 *)&misc->param.dyn_bw, sizeof(t_u16));
+	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 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
+ */
+
+t_u8
+woal_get_center_freq_idx(IN moal_private *priv,
+			 IN t_u8 band, IN t_u32 pri_chan, IN 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;
+			}
+		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;
+			}
+		case 52:
+		case 56:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 54;
+				break;
+			}
+		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;
+			}
+		case 68:
+		case 72:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 70;
+				break;
+			}
+		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;
+			}
+		case 84:
+		case 88:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 86;
+				break;
+			}
+		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;
+			}
+		case 100:
+		case 104:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 102;
+				break;
+			}
+		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;
+			}
+		case 116:
+		case 120:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 118;
+				break;
+			}
+		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;
+			}
+		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;
+			}
+		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;
+			}
+		case 165:
+		case 169:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 167;
+				break;
+			}
+		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;
+			}
+		case 184:
+		case 188:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 186;
+				break;
+			}
+		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;
+			}
+
+		default:	/* error. go to the default */
+			center_freq_idx = 42;
+		}
+	}
+	return center_freq_idx;
+}
+
+/**
+ ** @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 };
+	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;
+
+	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_ChanSwitchAnn_t);
+	pcust_chansw_ie->mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP;	/*Add IE for BEACON/probe resp */
+
+	parse_arguments(respbuf + strlen(CMD_MARVELL) +
+			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;
+		goto done;
+	}
+	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 = data[0];
+	chan_switch->new_channel_num = data[2];
+	chan_switch->chan_switch_count = data[3];
+	DBG_HEXDUMP(MCMD_D, "CSA IE", (t_u8 *)pcust_chansw_ie->ie_buffer,
+		    pcust_chansw_ie->ie_length);
+
+	if (data[1] != 0) {
+		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 = data[0];
+		ext_chan_switch->new_oper_class = data[1];
+		ext_chan_switch->new_channel_num = data[2];
+		ext_chan_switch->chan_switch_count = data[3];
+		if (woal_check_valid_channel_operclass(priv, data[2], data[1])) {
+			PRINTM(MERROR, "Wrong channel switch parameters!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		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 (data[4] && data[2] > 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, data[2],
+						 data[4]);
+		if (data[4] == CHANNEL_BW_40MHZ_ABOVE ||
+		    data[4] == CHANNEL_BW_40MHZ_BELOW) {
+			pbwchansw_ie->new_channel_width = 0;
+			pbwchansw_ie->new_channel_center_freq0 =
+				center_freq_idx;
+		} else if (data[4] == 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 (data[4] == 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;
+		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 (data[0]) {
+		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 * (data[3] + 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;
+}
+
+/**
+ * @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/get 11k
+ **
+ ** @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_11k_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_11k_cfg *pcfg_11k = 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_11k_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pcfg_11k = (mlan_ds_11k_cfg *) ioctl_req->pbuf;
+	pcfg_11k->sub_command = MLAN_OID_11K_CFG_ENABLE;
+	ioctl_req->req_id = MLAN_IOCTL_11K_CFG;
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_11K_CFG);
+	if (strlen(respbuf) == header_len) {
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		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;
+			}
+			ioctl_req->action = MLAN_ACT_SET;
+			if (data == CMD_DISABLED)
+				pcfg_11k->param.enable_11k = MFALSE;
+			else
+				pcfg_11k->param.enable_11k = MTRUE;
+		} else {
+			PRINTM(MERROR, "Too many arguments  %d \n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memcpy(respbuf, &pcfg_11k->param.enable_11k,
+	       sizeof(pcfg_11k->param.enable_11k));
+	ret = sizeof(pcfg_11k->param.enable_11k);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ ** @brief               neighbor_report
+ **
+ ** @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_11k_neighbor_report(moal_private *priv, t_u8 *respbuf,
+			      t_u32 respbuflen)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_11k_cfg *pcfg_11k = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	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_11k_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pcfg_11k = (mlan_ds_11k_cfg *) ioctl_req->pbuf;
+	pcfg_11k->sub_command = MLAN_OID_11K_GET_NLIST;
+	ioctl_req->req_id = MLAN_IOCTL_11K_CFG;
+	ioctl_req->action = MLAN_ACT_GET;
+
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_11K_NEIGHBOR_REPORT);
+	if (strlen(respbuf) != header_len) {
+		PRINTM(MERROR, "argument error\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	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 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 (strlen(respbuf) >= header_len) {
+
+		for (i = 0; i < (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;
+			}
+			memcpy(priv->random_mac, priv->current_addr, ETH_ALEN);
+			get_random_bytes(rand_data, 3);
+			memcpy(priv->random_mac + 3, rand_data, 3);
+		} else if (strncmp
+			   (respbuf + header_len + 1 + space_len, "Off",
+			    strlen("Off")) == 0) {
+			memset(priv->random_mac, 0, ETH_ALEN);
+		} else {
+			PRINTM(MERROR, "Invalid parameter!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	} else {
+		PRINTM(MERROR, "Invalid parameter!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ret = sprintf(respbuf, "FAKEMAC parameter is %s\n",
+		      (t_u8 *)(respbuf + header_len + 1 + space_len)) + 1;
+	PRINTM(MMSG, "FAKEMAC parameter is %s\n",
+	       (t_u8 *)(respbuf + header_len + 1 + space_len));
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               enable/disable roaming offload to firmware
+ *
+ * @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_roam_offload(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int user_data_len = 0, header_len = 0, ret = 0;
+	int data = 0;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	t_u8 enable = 0;
+#endif
+#endif
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	header_len = strlen("SETROAMOFFLOAD");
+	parse_arguments(respbuf + header_len + 1, &data, 1, &user_data_len);
+
+	if (data < 0 || data > 5) {
+		PRINTM(MERROR, "Invalid parameters\n");
+		ret = -EFAULT;
+		goto done;
+	}
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (!data) {
+		woal_cfg80211_vendor_event(priv, event_set_key_mgmt_offload,
+					   &enable, sizeof(enable));
+	}
+#endif
+#endif
+	ret = woal_enable_fw_roaming(priv, data);
+done:
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               set roaming offload aplist to firmware
+ *
+ * @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_roam_offload_aplist(moal_private *priv, t_u8 *respbuf,
+				  t_u32 respbuflen)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_roam_offload *roam = NULL;
+	mlan_ds_misc_roam_offload_aplist *aplist = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int ret = 0, i = 0;
+	int user_data_len = 0, header_len = 0;
+	int ap_count = 0;
+	char *begin, *end;
+	t_u8 mac_addr[6];
+
+	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_ROAM_OFFLOAD_APLIST;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	roam = (mlan_ds_misc_roam_offload *) & misc->param.roam_offload;
+	/*Set enable to invalid value(valid: 0, 1, 2) */
+	roam->enable = 3;
+	aplist = &roam->aplist;
+
+	header_len = strlen("SETROAMOFFLAPLIST");
+	user_data_len = strlen(respbuf) - header_len;
+	if (!user_data_len) {
+		/* GET operation */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		begin = &respbuf[header_len + 1];
+		end = begin;
+		while (begin && *begin == ' ') {
+			begin++;
+			end++;
+		}
+		while (end && *end != ' ')
+			end++;
+		*end = '\0';
+		end++;
+		if (woal_atoi(&ap_count, begin) != MLAN_STATUS_SUCCESS) {
+			ret = -EINVAL;
+			goto done;
+		}
+		aplist->ap_num = ap_count;
+		if (ap_count > 0 && ap_count <= MAX_AP_LIST) {
+			/* SET operation */
+			ioctl_req->action = MLAN_ACT_SET;
+			for (i = 0; i < ap_count; i++) {
+				begin = end;
+				while (begin && *begin == ' ') {
+					begin++;
+					end++;
+				}
+				while (end && *end != ' ' && *end != '\0')
+					end++;
+				if (end == begin) {
+					PRINTM(MERROR,
+					       "AP number %d is wrong\n",
+					       ap_count);
+					ret = -EINVAL;
+					goto done;
+				}
+				*end = '\0';
+				end++;
+				woal_mac2u8(mac_addr, begin);
+				memcpy(aplist->ap_mac[i], mac_addr,
+				       MLAN_MAC_ADDR_LENGTH);
+			}
+		} else {
+			PRINTM(MERROR,
+			       "AP number is wrong.Support max 8 APs\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	DBG_HEXDUMP(MERROR, "APLIST", (t_u8 *)aplist->ap_mac,
+		    aplist->ap_num * MLAN_MAC_ADDR_LENGTH);
+	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               Configure roaming offload to firmware
+ *
+ * @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_roam_offload_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0, user_data_len = 0, header_len = 0, data = 0;
+	char *begin, *end, *pvariable_name;
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	woal_roam_offload_cfg roam_offload_cfg;
+	t_u8 len = 0;
+	int count = 0, i = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	memset((char *)&roam_offload_cfg, 0, sizeof(roam_offload_cfg));
+	header_len = strlen("CFGROAMOFFLOAD");
+	user_data_len = strlen(respbuf) - header_len;
+	if (!user_data_len) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	roam_offload_cfg.band_rssi.band_preferred = 0xff;
+	roam_offload_cfg.trigger_condition = 0xff;
+	end = &respbuf[header_len];
+	while (((t_u8 *)end - &respbuf[header_len]) < user_data_len - 1) {
+		end++;
+		begin = end;
+		while (begin && *begin == ' ') {
+			begin++;
+			end++;
+		}
+		while (end && *end != ' ' && *end != '\0' && *end != '=')
+			end++;
+		if (end == begin) {
+			PRINTM(MERROR, "Invalid command specified!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (end)
+			*end = '\0';
+		pvariable_name = begin;
+
+		if (((t_u8 *)end - &respbuf[header_len]) >= user_data_len) {
+			PRINTM(MERROR, "Invalid command length!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		end++;
+		begin = end;
+		while (begin && (*begin == ' ' || *begin == '=')) {
+			begin++;
+			end++;
+		}
+		while (end && *end != ' ' && *end != '\0' && *end != '=')
+			end++;
+		if (end == begin) {
+			PRINTM(MERROR, "Invalid command specified!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		*end = '\0';
+
+		if (strcmp(pvariable_name, "AUTO_RECONNECT") == 0) {
+			woal_atoi(&data, begin);
+		} else if (strcmp(pvariable_name, "BSSID") == 0) {
+			woal_mac2u8(mac_addr, begin);
+			memcpy(roam_offload_cfg.bssid, mac_addr,
+			       MLAN_MAC_ADDR_LENGTH);
+		} else if (strcmp(pvariable_name, "BLACKLIST") == 0) {
+			if (woal_atoi(&count, begin) != MLAN_STATUS_SUCCESS) {
+				ret = -EINVAL;
+				goto done;
+			}
+			if (count > 0 && count <= MAX_AP_LIST) {
+				roam_offload_cfg.black_list.ap_num = count;
+				for (i = 0; i < count; i++) {
+					end++;
+					begin = end;
+					while (begin && *begin == ' ') {
+						begin++;
+						end++;
+					}
+					while (end && *end != ' ' &&
+					       *end != '\0')
+						end++;
+					if (end == begin) {
+						PRINTM(MERROR,
+						       "BSSID %d is wrong\n",
+						       count);
+						ret = -EINVAL;
+						goto done;
+					}
+					*end = '\0';
+					woal_mac2u8(mac_addr, begin);
+					memcpy(roam_offload_cfg.black_list.
+					       ap_mac[i], mac_addr,
+					       MLAN_MAC_ADDR_LENGTH);
+				}
+			} else {
+				PRINTM(MERROR,
+				       "BSSID number is wrong.Support max %d BSSIDs\n",
+				       MAX_AP_LIST);
+				ret = -EINVAL;
+				goto done;
+			}
+		} else if (strcmp(pvariable_name, "SSID") == 0) {
+			if (woal_atoi(&count, begin) != MLAN_STATUS_SUCCESS) {
+				ret = -EINVAL;
+				goto done;
+			}
+			if (count > 0 && count <= MAX_SSID_NUM) {
+				roam_offload_cfg.ssid_list.ssid_num = count;
+				for (i = 0; i < count; i++) {
+					end++;
+					begin = end;
+					while (begin && *begin == ' ') {
+						begin++;
+						end++;
+					}
+					while (end && *end != ' ' &&
+					       *end != '\0') {
+						end++;
+						len++;
+					}
+					if ((end == begin) ||
+					    len >= MLAN_MAX_SSID_LENGTH) {
+						PRINTM(MERROR,
+						       "SSID %d is wrong\n",
+						       count);
+						ret = -EINVAL;
+						goto done;
+					}
+					*end = '\0';
+					roam_offload_cfg.ssid_list.ssids[i].
+						ssid_len = len + 1;
+					memcpy((t_u8 *)&roam_offload_cfg.
+					       ssid_list.ssids[i].ssid, begin,
+					       len + 1);
+					len = 0;
+				}
+			} else {
+				PRINTM(MERROR,
+				       "SSID number is wrong.Support max %d SSIDs\n",
+				       MAX_SSID_NUM);
+				ret = -EINVAL;
+				goto done;
+			}
+		} else if (strcmp(pvariable_name, "RETRY_COUNT") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.retry_count = (t_u8)data;
+		}
+
+		else if (strcmp(pvariable_name, "TRIGGER_CONDITION") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.trigger_condition = (t_u16)data;
+		}
+
+		else if (strcmp(pvariable_name, "MAX_RSSI") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.max_rssi = (t_u8)data;
+			roam_offload_cfg.rssi_param_set_flag = 1;
+		} else if (strcmp(pvariable_name, "MIN_RSSI") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.min_rssi = (t_u8)data;
+			roam_offload_cfg.rssi_param_set_flag = 1;
+		} else if (strcmp(pvariable_name, "STEP_RSSI") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.step_rssi = (t_u8)data;
+			roam_offload_cfg.rssi_param_set_flag = 1;
+		}
+
+		else if (strcmp(pvariable_name, "BAND_PREFER") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.band_rssi.band_preferred = (t_u8)data;
+			roam_offload_cfg.band_rssi_flag = 1;
+		} else if (strcmp(pvariable_name, "RSSI_HYSTERESIS") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.band_rssi.rssi_hysteresis = (t_u8)data;
+			roam_offload_cfg.band_rssi_flag = 1;
+		}
+
+		else if (strcmp(pvariable_name, "BSSTYPE") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.bgscan_cfg.bss_type = (t_u8)data;
+			roam_offload_cfg.bgscan_set_flag++;
+		} else if (strcmp(pvariable_name, "CHANSPERSCAN") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.bgscan_cfg.channels_per_scan =
+				(t_u8)data;
+			roam_offload_cfg.bgscan_set_flag++;
+		} else if (strcmp(pvariable_name, "BGRPTCONDITION") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.bgscan_cfg.bg_rpt_condition =
+				(t_u32)data;
+			roam_offload_cfg.bgscan_set_flag++;
+		} else if (strcmp(pvariable_name, "SCANINTERVAL") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.bgscan_cfg.scan_interval = (t_u32)data;
+			roam_offload_cfg.bgscan_set_flag++;
+		}
+
+		else if (strcmp(pvariable_name, "EESMODE") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.ees_cfg.ees_mode = (t_u16)data;
+			roam_offload_cfg.ees_param_set_flag++;
+		} else if (strcmp(pvariable_name, "EESRPTCONDITION") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.ees_cfg.ees_rpt_condition =
+				(t_u16)data;
+			roam_offload_cfg.ees_param_set_flag++;
+		} else if (strcmp(pvariable_name, "HIGHSCANPERIOD") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.ees_cfg.high_scan_period = (t_u16)data;
+			roam_offload_cfg.ees_param_set_flag++;
+		} else if (strcmp(pvariable_name, "HIGHSCANCOUNT") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.ees_cfg.high_scan_count = (t_u16)data;
+			roam_offload_cfg.ees_param_set_flag++;
+		} else if (strcmp(pvariable_name, "MIDSCANPERIOD") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.ees_cfg.mid_scan_period = (t_u16)data;
+			roam_offload_cfg.ees_param_set_flag++;
+		} else if (strcmp(pvariable_name, "MIDSCANCOUNT") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.ees_cfg.mid_scan_count = (t_u16)data;
+			roam_offload_cfg.ees_param_set_flag++;
+		} else if (strcmp(pvariable_name, "LOWSCANPERIOD") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.ees_cfg.low_scan_period = (t_u16)data;
+			roam_offload_cfg.ees_param_set_flag++;
+		} else if (strcmp(pvariable_name, "LOWSCANCOUNT") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.ees_cfg.low_scan_count = (t_u16)data;
+			roam_offload_cfg.ees_param_set_flag++;
+		}
+
+		else if (strcmp(pvariable_name, "BCNMISSTHRESHOLD") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.bcn_miss_threshold = (t_u8)data;
+		}
+
+		else if (strcmp(pvariable_name, "PREBCNMISSTHRESHOLD") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.pre_bcn_miss_threshold = (t_u8)data;
+		} else if (strcmp(pvariable_name, "REPEATCOUNT") == 0) {
+			woal_atoi(&data, begin);
+			roam_offload_cfg.repeat_count = (t_u16)data;
+		} else {
+			PRINTM(MERROR, "Un-support parameter: %s\n",
+			       pvariable_name);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	if (priv->phandle->fw_roam_enable == AUTO_RECONNECT) {
+		memcpy(priv->phandle->auto_reconnect_bssid,
+		       roam_offload_cfg.bssid, MLAN_MAC_ADDR_LENGTH);
+		memcpy(priv->phandle->auto_reconnect_ssid.ssid,
+		       roam_offload_cfg.ssid_list.ssids[0].ssid,
+		       roam_offload_cfg.ssid_list.ssids[0].ssid_len);
+		priv->phandle->auto_reconnect_retry_count = (t_u8)data;
+	} else {
+		if (roamoffload_in_hs)
+			memcpy((void *)&priv->phandle->fw_roam_params,
+			       (void *)&roam_offload_cfg,
+			       sizeof(roam_offload_cfg));
+		else
+			woal_config_fw_roaming(priv, ROAM_OFFLOAD_PARAM_CFG,
+					       &roam_offload_cfg);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Configure roaming SSID passphrase
+ *
+ * @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_roam_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;
+	int user_data_len = 0, header_len = 0;
+	char *begin, *end, *opt, *item;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	woal_roam_offload_cfg roam_offload_cfg;
+	mlan_ds_passphrase *ssid_passphrase = NULL;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset((char *)&roam_offload_cfg, 0, sizeof(roam_offload_cfg));
+	header_len = strlen("SETROAMPASSPHRASE");
+	user_data_len = strlen(respbuf) - header_len;
+	if (!user_data_len) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Parse the buf to get the cmd_action */
+	begin = respbuf + header_len;
+	while (begin && *begin == ' ')
+		begin++;
+	end = woal_strsep(&begin, ';', '/');
+	if (end)
+		action = woal_atox(end);
+	PRINTM(MMSG, "action= %d\n", action);
+	if (action != 1 || 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;
+	sec->multi_passphrase = 1;
+	req->action = MLAN_ACT_SET;
+
+	/*Parse the buffer like "ssid=xxx passphrase=xxxx;ssid=xxx passphrase=xxx" */
+	while (begin) {
+		while (begin && *begin == ' ')
+			begin++;
+		end = woal_strsep(&begin, ';', '/');
+		item = woal_strsep(&end, ' ', '/');
+		opt = woal_strsep(&item, '=', '/');
+		while (opt) {
+			if (roam_offload_cfg.userset_passphrase >=
+			    MAX_SEC_SSID_NUM - 1) {
+				PRINTM(MERROR,
+				       "Support max %d security SSIDs!\n",
+				       MAX_SEC_SSID_NUM);
+				break;
+			}
+			ssid_passphrase =
+				&sec->param.roam_passphrase[roam_offload_cfg.
+							    userset_passphrase];
+			if (!opt || !item) {
+				PRINTM(MERROR, "Invalid option\n");
+				ret = -EINVAL;
+				goto done;
+			} else if (!strnicmp(opt, "ssid", strlen(opt))) {
+				if (strlen(end) > MLAN_MAX_SSID_LENGTH) {
+					PRINTM(MERROR,
+					       "SSID length exceeds max length\n");
+					ret = -EFAULT;
+					goto done;
+				}
+				ssid_passphrase->ssid.ssid_len = strlen(item);
+				strncpy((char *)ssid_passphrase->ssid.ssid,
+					item, MIN(strlen(item),
+						  MLAN_MAX_SSID_LENGTH));
+				PRINTM(MINFO, "ssid=%s, len=%d\n",
+				       ssid_passphrase->ssid.ssid,
+				       (int)ssid_passphrase->ssid.ssid_len);
+			} else if (!strnicmp(opt, "passphrase", strlen(opt)) &&
+				   req->action == MLAN_ACT_SET) {
+				if (strlen(item) < MLAN_MIN_PASSPHRASE_LENGTH ||
+				    strlen(item) > MLAN_MAX_PASSPHRASE_LENGTH) {
+					PRINTM(MERROR,
+					       "Invalid length for passphrase\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				ssid_passphrase->psk_type = MLAN_PSK_PASSPHRASE;
+				memcpy(ssid_passphrase->psk.passphrase.
+				       passphrase, item, MIN(strlen(item),
+							     MLAN_MAX_PASSPHRASE_LENGTH));
+				ssid_passphrase->psk.passphrase.passphrase_len =
+					strlen(item);
+				PRINTM(MINFO, "passphrase=%s, len=%d\n",
+				       ssid_passphrase->psk.passphrase.
+				       passphrase,
+				       (int)ssid_passphrase->psk.passphrase.
+				       passphrase_len);
+			} else {
+				PRINTM(MERROR, "Invalid option %s\n", opt);
+				ret = -EINVAL;
+				goto done;
+			}
+			if (!end || *end == '\0')
+				break;
+			while (end && *end == ' ')
+				end++;
+			item = woal_strsep(&end, ' ', '/');
+			opt = woal_strsep(&item, '=', '/');
+		}
+		roam_offload_cfg.userset_passphrase++;
+	}
+
+	if (roamoffload_in_hs) {
+		memcpy((char *)priv->phandle->ssid_passphrase,
+		       (char *)sec->param.roam_passphrase,
+		       MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
+		priv->phandle->fw_roam_params.userset_passphrase =
+			roam_offload_cfg.userset_passphrase;
+		goto done;
+	}
+
+	woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, &roam_offload_cfg);
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (ret)
+		goto done;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Issue ACS command to FW to get best channel and channel stats
+ *
+ * @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_acs(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0;
+	int data[MAX_BG_CHANNEL + 1];
+	int user_data_len = 0;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_acs *acs = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int i = 0, j = 0;
+	int ch_cnt = 0;
+	int resp_len = 0;
+	acs_result *pacs_result = NULL;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ACS_SCAN);
+
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+	if (user_data_len < 0 || user_data_len > MAX_CH_STATS) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+    /** Input format: [channels on 2.4G] */
+    /** Check validity of input channels if enable */
+	if (user_data_len < 2 && user_data_len != 0) {
+		PRINTM(MERROR,
+		       "If specify channels, at least specify 2 channels.\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	for (i = 0; i < user_data_len; i++) {
+		if (data[i] < 1 || data[i] > MAX_BG_CHANNEL) {
+			PRINTM(MERROR, "Invalid input channel %d.\n", data[i]);
+			ret = -EINVAL;
+			goto done;
+		}
+		for (j = 0; j < i; j++) {
+			if (data[j] == data[i]) {
+				PRINTM(MERROR, "Duplicate input channel %d.\n",
+				       data[i]);
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		ch_cnt++;
+	}
+
+	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;
+	req->action = MLAN_ACT_SET;
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_ACS;
+	acs = &(misc->param.acs);
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	acs->scan_chan_gap = priv->phandle->scan_chan_gap;
+#endif
+	for (i = 0; i < ch_cnt; i++)
+		acs->ch_stats[i].chan_num = data[i];
+	acs->ch_stats_num = ch_cnt;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	resp_len = sizeof(acs_result) + acs->ch_stats_num * sizeof(ChStat_t);
+	if (respbuflen < resp_len) {
+		PRINTM(MERROR, "response buffer length is too short!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+    /** Fill respond buf */
+	pacs_result = (acs_result *) respbuf;
+	pacs_result->best_ch = acs->best_ch;
+	pacs_result->ch_stats_num = acs->ch_stats_num;
+	memcpy(pacs_result->ch_stats, acs->ch_stats,
+	       sizeof(ChStat_t) * MIN(MAX_CH_STATS, pacs_result->ch_stats_num));
+
+	ret = resp_len;
+
+done:
+	if (req && status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+static int
+woal_get_correlated_time(moal_private *priv, t_u8 *buf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *rate = NULL;
+	int ret = 1;
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	rate = (mlan_ds_misc_cfg *)req->pbuf;
+	rate->sub_command = MLAN_OID_MISC_GET_CORRELATED_TIME;;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_NO_WAIT);
+	if (status == MLAN_STATUS_FAILURE) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	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;
+
+	ENTER();
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&priv_cmd, req->ifr_data,
+			   sizeof(android_wifi_priv_cmd))) {
+		ret = -EFAULT;
+		goto done;
+	}
+#define CMD_BUF_LEN   2048
+	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
+	memcpy(&cmd_buf, &priv_cmd.buf, sizeof(cmd_buf));
+#else
+	cmd_buf = priv_cmd.buf;
+#endif
+	if (copy_from_user(buf, 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_MARVELL, strlen(CMD_MARVELL)) &&
+	    woal_check_driver_status(priv->phandle)) {
+		PRINTM(MERROR, "%s fail when driver hang\n", buf);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (strncmp(buf, CMD_MARVELL, strlen(CMD_MARVELL)) == 0) {
+		/* This command has come from mlanutl app */
+
+		/* Check command */
+		if (strnicmp
+		    (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_MEMRDWR,
+			    strlen(PRIV_CMD_MEMRDWR)) == 0) {
+			/* Memory Read/Write */
+			len = woal_priv_memrdwr(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_SDCMD52RW,
+			    strlen(PRIV_CMD_SDCMD52RW)) == 0) {
+			/* Cmd52 read/write register */
+			len = woal_priv_sdcmd52rw(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#ifdef STA_SUPPORT
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_ARPFILTER,
+			    strlen(PRIV_CMD_ARPFILTER)) == 0) {
+			/* ARPFilter Configuration */
+			len = woal_priv_arpfilter(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#endif
+#if defined(SDIO_SUSPEND_RESUME)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#endif
+#ifdef RX_PACKET_COALESCE
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_QOS_CFG,
+			    strlen(PRIV_CMD_QOS_CFG)) == 0) {
+			t_u32 action = MLAN_ACT_GET;
+			if (strlen(buf) ==
+			    strlen(CMD_MARVELL) + strlen(PRIV_CMD_QOS_CFG)) {
+				pdata = buf;	/* GET operation */
+			} else {
+				pdata = buf + strlen(CMD_MARVELL) +
+					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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_DRCS_CFG,
+			    strlen(PRIV_CMD_DRCS_CFG)) == 0) {
+			/* DRCS configuration for mc_cfg_ext */
+			len = woal_priv_drcs_time_slicing_cfg(priv, buf,
+							      priv_cmd.
+							      total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_MULTI_CHAN_CFG,
+			    strlen(PRIV_CMD_MULTI_CHAN_CFG)) == 0) {
+			/* Channel time and buffer weight configuration */
+			len = woal_priv_multi_chan_config(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL),
+			    PRIV_CMD_MULTI_CHAN_POLICY,
+			    strlen(PRIV_CMD_MULTI_CHAN_POLICY)) == 0) {
+			/* Multi-channel Policy enable/disable */
+			len = woal_priv_multi_chan_policy(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_FWMACADDR,
+			    strlen(PRIV_CMD_FWMACADDR)) == 0) {
+			/* Set FW MAC address */
+			len = woal_priv_fwmacaddr(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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;
+#if defined(STA_SUPPORT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_11K_CFG,
+			    strlen(PRIV_CMD_11K_CFG)) == 0) {
+			/* Implement 802.11K enable command */
+			len = woal_priv_11k_cfg(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL),
+			    PRIV_CMD_11K_NEIGHBOR_REPORT,
+			    strlen(PRIV_CMD_11K_NEIGHBOR_REPORT)) == 0) {
+			/* Implement 802.11K get neighbor AP list command */
+			len = woal_priv_11k_neighbor_report(priv, buf,
+							    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#if defined(REASSOCIATION)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL),
+			    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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_ATIM_WINDOW,
+			    strlen(PRIV_CMD_ATIM_WINDOW)) == 0) {
+			/* Set/Get ATIM window */
+			len = woal_priv_atim_window(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#endif
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), PRIV_CMD_NET_MON,
+			    strlen(PRIV_CMD_NET_MON)) == 0) {
+			/* Set/Get network monitor configurations */
+			len = woal_priv_net_monitor_ioctl(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+#if defined(DFS_TESTING_SUPPORT)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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;
+#endif
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_ADHOC_AES,
+			    strlen(PRIV_CMD_ADHOC_AES)) == 0) {
+			/* Adhoc AES control */
+			len = woal_priv_adhoc_aes(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_ROBUSTCOEX,
+			    strlen(PRIV_CMD_ROBUSTCOEX)) == 0) {
+			/* Set Robustcoex GPIOcfg */
+			pdata = buf + strlen(CMD_MARVELL) +
+				strlen(PRIV_CMD_ROBUSTCOEX);
+			len = priv_cmd.total_len - strlen(PRIV_CMD_ROBUSTCOEX) -
+				strlen(CMD_MARVELL);
+			len = woal_priv_robustcoex(priv, pdata, len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), PRIV_CMD_KEEP_CONNECT,
+			    strlen(PRIV_CMD_KEEP_CONNECT)) == 0) {
+			pdata = buf + strlen(CMD_MARVELL) +
+				strlen(PRIV_CMD_KEEP_CONNECT);
+			len = woal_priv_keep_connect(priv, pdata, len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), PRIV_CMD_COALESCE_STATUS,
+			    strlen(PRIV_CMD_COALESCE_STATUS)) == 0) {
+			/* Control Coalescing status Enable/Disable */
+			len = woal_priv_coalescing_status(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL),
+			    PRIV_CMD_FW_WAKEUP_METHOD,
+			    strlen(PRIV_CMD_FW_WAKEUP_METHOD)) == 0) {
+			/* Set/Get module configuration */
+			len = woal_priv_fw_wakeup_method(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(UAP_CFG80211)
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL),
+			    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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL),
+			    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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), 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_MARVELL), PRIV_CMD_ACS_SCAN,
+			    strlen(PRIV_CMD_ACS_SCAN)) == 0) {
+			len = woal_priv_acs(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_MARVELL),
+			    PRIV_CMD_GET_CORRELATED_TIME,
+			    strlen(PRIV_CMD_GET_CORRELATED_TIME)) == 0) {
+			len = woal_get_correlated_time(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+		} else {
+			PRINTM(MERROR,
+			       "Unknown MARVELL 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 (!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, "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));
+		memcpy(country_code, buf + strlen("COUNTRY") + 1, copy_len);
+		PRINTM(MIOCTL, "Set COUNTRY %s\n", country_code);
+		if (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);
+			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 <= 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);
+		memcpy(buf, priv->current_addr, ETH_ALEN);
+		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, "SETROAMOFFLOAD", strlen("SETROAMOFFLOAD")) ==
+		   0) {
+		len = woal_priv_set_roam_offload(priv, buf, priv_cmd.total_len);
+	} else if (strncmp
+		   (buf, "SETROAMOFFLAPLIST",
+		    strlen("SETROAMOFFLAPLIST")) == 0) {
+		len = woal_priv_set_roam_offload_aplist(priv, buf,
+							priv_cmd.total_len);
+	} else if (strncmp(buf, "CFGROAMOFFLOAD", strlen("CFGROAMOFFLOAD")) ==
+		   0) {
+		len = woal_priv_roam_offload_cfg(priv, buf, priv_cmd.total_len);
+	} else if (strncmp
+		   (buf, "SETROAMPASSPHRASE",
+		    strlen("SETROAMPASSPHRASE")) == 0) {
+		len = woal_priv_set_roam_passphrase(priv, buf,
+						    priv_cmd.total_len);
+	} 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(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();
+
+	memcpy(ptmp_buf, pbss_desc->time_stamp, sizeof(pbss_desc->time_stamp));
+	ptmp_buf += sizeof(pbss_desc->time_stamp);
+
+	memcpy(ptmp_buf, &pbss_desc->beacon_period,
+	       sizeof(pbss_desc->beacon_period));
+	ptmp_buf += sizeof(pbss_desc->beacon_period);
+
+	memcpy(ptmp_buf, &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;
+	memcpy(ptmp_buf, tmp_ssid_hdr, sizeof(tmp_ssid_hdr));
+	ptmp_buf += sizeof(tmp_ssid_hdr);
+
+	memcpy(ptmp_buf, pbss_desc->ssid.ssid, 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;
+		memcpy(ptmp_buf, &pbss_desc->wmm_ie, 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;
+			memcpy(ptmp_buf, pbss_desc->pwpa_ie, 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;
+			memcpy(ptmp_buf, pbss_desc->prsn_ie, 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));
+
+	memcpy(tmp_rsp_entry.fixed_fields.bssid,
+	       pbss_desc->mac_address, 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.network_tsf = pbss_desc->network_tsf;
+	tmp_rsp_entry.bss_info_length = variable_size;
+
+	/*
+	 *  Copy fixed fields to user space
+	 */
+	memcpy(pcurrent, &tmp_rsp_entry, fixed_size);
+	pcurrent += fixed_size;
+
+	if (pbss_desc->pbeacon_buf) {
+		/*
+		 *  Copy variable length elements to user space
+		 */
+		memcpy(pcurrent, pbss_desc->pbeacon_buf,
+		       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
+ */
+int
+woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	int ret = 0;
+
+	ENTER();
+
+	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_sd8997/mlinux/moal_eth_ioctl.h b/wlan_sd8997/mlinux/moal_eth_ioctl.h
new file mode 100644
index 0000000..9fc7b85
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_eth_ioctl.h
@@ -0,0 +1,493 @@
+
+/** @file moal_eth_ioctl.h
+ *
+ * @brief This file contains definition for private IOCTL call.
+ *
+ * Copyright (C) 2014-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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
+
+/** Marvell private command identifier string */
+#define CMD_MARVELL     "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
+#if defined(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_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_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"
+#define PRIV_CMD_SDCMD52RW      "sdcmd52rw"
+#define PRIV_CMD_ARPFILTER      "arpfilter"
+#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"
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+#define PRIV_CMD_RADIO_CTRL     "radioctrl"
+#endif
+#define PRIV_CMD_WMM_CFG        "wmmcfg"
+#if defined(STA_SUPPORT)
+#define PRIV_CMD_11D_CFG        "11dcfg"
+#define PRIV_CMD_11D_CLR_TBL    "11dclrtbl"
+#endif
+#define PRIV_CMD_WWS_CFG        "wwscfg"
+#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_ATIM_WINDOW    "atimwindow"
+#define PRIV_CMD_AMSDU_AGGR_CTRL    "amsduaggrctrl"
+#define PRIV_CMD_TX_BF_CAP          "httxbfcap"
+#define PRIV_CMD_SDIO_CLOCK         "sdioclock"
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+#define PRIV_CMD_MPA_CTRL           "mpactrl"
+#endif
+#define PRIV_CMD_SLEEP_PARAMS       "sleepparams"
+#define PRIV_CMD_NET_MON            "netmon"
+#if defined(DFS_TESTING_SUPPORT)
+#define PRIV_CMD_DFS_TESTING        "dfstesting"
+#endif
+#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_ADHOC_AES      "adhocaes"
+#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"
+#define PRIV_CMD_COALESCE_STATUS    "coalesce_status"
+#define PRIV_CMD_FW_WAKEUP_METHOD   "fwwakeupmethod"
+#define PRIV_CMD_SD_CMD53_RW        "sdcmd53rw"
+#ifdef RX_PACKET_COALESCE
+#define PRIV_CMD_RX_COAL_CFG "rxpktcoal_cfg"
+#endif
+#define PRIV_CMD_MULTI_CHAN_CFG "mc_cfg"
+#define PRIV_CMD_MULTI_CHAN_POLICY "mc_policy"
+#define PRIV_CMD_DRCS_CFG "mc_cfg_ext"
+#if defined(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_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"
+
+#define PRIV_CMD_GET_SENSOR_TEMP        "get_sensor_temp"
+
+#define PRIV_CMD_11K_CFG        "11k_enable"
+#define PRIV_CMD_11K_NEIGHBOR_REPORT        "neighbor_report"
+#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
+
+#if defined(SDIO_SUSPEND_RESUME)
+#define PRIV_CMD_AUTO_ARP	"auto_arp"
+#endif
+
+#define PRIV_CMD_PER_PKT_CFG    "per_pkt_cfg"
+
+#define PRIV_CMD_DEAUTH_CTRL    "ctrldeauth"
+
+/**Private command ID to set/get independent reset*/
+#define PRIV_CMD_IND_RST_CFG            "indrstcfg"
+
+/** 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_KEEP_CONNECT         "keep_connect"
+
+#define PRIV_CMD_BOOTSLEEP            "bootsleep"
+
+#define PRIV_CMD_GET_CORRELATED_TIME "GET_CORRELATED_TIME"
+
+int woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+
+/*
+ * 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 {
+  /** The value of the parameter itself */
+	t_s32 value;
+  /** Hardware should not use auto select */
+	t_u8 fixed;
+  /** Disable the feature */
+	t_u8 disabled;
+  /** Various specifc flags (if any) */
+	t_u16 flags;
+};
+
+/*
+ *  For all data larger than 16 octets, we need to use a
+ *  pointer to memory allocated in user space.
+ */
+struct mw_point {
+  /** Pointer to the data  (in user space) */
+	t_u8 *pointer;
+  /** number of fields or size in bytes */
+	t_u16 length;
+  /** Optional params */
+	t_u16 flags;
+};
+
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ */
+union mwreq_data {
+    /** Config - generic */
+	char name[IFNAMSIZ];
+
+    /** Extended network name */
+	struct mw_point essid;
+    /** Operation mode */
+	t_u32 mode;
+    /** PM duration/timeout */
+	struct mw_param power;
+    /** Access point address */
+	struct sockaddr ap_addr;
+    /** Other small parameters */
+	struct mw_param param;
+    /** Other large parameters */
+	struct mw_point data;
+};
+
+ /* The structure to exchange data for ioctl */
+struct mwreq {
+	union {
+	/** if name, e.g. "eth0" */
+		char ifrn_name[IFNAMSIZ];
+	} ifr_ifrn;
+
+    /** Data part */
+	union mwreq_data u;
+};
+
+/** woal HT capacity info structure */
+typedef struct woal_priv_ht_cap_info {
+    /** HT capacity info for bg */
+	t_u32 ht_cap_info_bg;
+    /** HT capacity info for a */
+	t_u32 ht_cap_info_a;
+} woal_ht_cap_info;
+
+/** woal private addba structure */
+typedef struct woal_priv_addba {
+    /** Time out */
+	t_u32 time_out;
+    /** Transmission window size */
+	t_u32 tx_win_size;
+    /** Receiver window size */
+	t_u32 rx_win_size;
+    /** Tx amsdu */
+	t_u32 tx_amsdu;
+    /** Rx amsdu */
+	t_u32 rx_amsdu;
+} woal_addba;
+
+/** 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;
+} woal_tx_rate_cfg;
+
+/** woal embedded supplicant structure */
+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);
+mlan_status woal_ioctl_aggr_prio_tbl(moal_private *priv, t_u32 action,
+				     mlan_ds_11n_aggr_prio_tbl *aggr_prio_tbl);
+
+int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req);
+
+#define PRIV_CMD_ACS_SCAN "acs"
+
+/** Type definition of mlan_acs_scan */
+typedef struct _acs_result {
+    /** Best Channel Number */
+	t_u8 best_ch;
+    /** Channel Statistics Number */
+	t_u8 ch_stats_num;
+    /** Channel Statistics */
+	ChStat_t ch_stats[0];
+} acs_result, *pacs_result;
+
+#define TLV_TYPE_PER_PKT_CFG 0x0001
+#define TX_PKT_CTRL  MBIT(0)
+#define RX_PKT_INFO  MBIT(1)
+
+/** Enum for different CW mode type */
+typedef enum _cw_modes_e {
+	CWMODE_DISABLE,
+	CWMODE_TXCONTPKT,
+	CWMODE_TXCONTWAVE,
+} cw_modes_e;
+#endif /** _WOAL_ETH_PRIV_H_ */
diff --git a/wlan_sd8997/mlinux/moal_ioctl.c b/wlan_sd8997/mlinux/moal_ioctl.c
new file mode 100644
index 0000000..c4cc7ad
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_ioctl.c
@@ -0,0 +1,6854 @@
+/** @file moal_ioctl.c
+  *
+  * @brief This file contains ioctl function to MLAN
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include    "moal_main.h"
+#include    "moal_eth_ioctl.h"
+#include    "moal_sdio.h"
+#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_cfgvendor.h"
+#endif
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+#define MRVL_TLV_HEADER_SIZE            4
+/* Marvell 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[] = {
+	{"US ", 0x10},		/* US FCC            */
+	{"CA ", 0x20},		/* IC Canada         */
+	{"SG ", 0x10},		/* Singapore         */
+	{"EU ", 0x30},		/* ETSI              */
+	{"AU ", 0x30},		/* Australia         */
+	{"KR ", 0x30},		/* Republic Of Korea */
+	{"CN ", 0x50},		/* China             */
+	{"JP ", 0xFF},		/* Japan special     */
+};
+
+/** EEPROM Region code mapping table */
+static region_code_mapping_t hw_region_code_mapping[] = {
+	{"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"
+};
+
+/********************************************************
+			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
+extern int cfg80211_wext;
+int disconnect_on_suspend;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+extern int dfs_offload;
+#endif
+#endif
+
+extern int roamoffload_in_hs;
+
+/** gtk rekey offload mode */
+extern int gtk_rekey_offload;
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief This function converts region string to region code
+ *
+ *  @param region_string    Region string
+ *
+ *  @return                 Region code
+ */
+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 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)
+{
+	int 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)
+		memcpy(&mlist->mac_list[mlist->num_multicast_addr], mac,
+		       ETH_ALEN);
+	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)
+			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_IOCTL_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 = *(t_u32 *)req->pbuf;
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (sub_command != MLAN_OID_GET_DEBUG_INFO) {
+		if (priv->phandle->surprise_removed == MTRUE ||
+		    priv->phandle->driver_state) {
+			PRINTM(MERROR,
+			       "IOCTL is not allowed while the device is not present or hang\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#if defined(SDIO_SUSPEND_RESUME)
+		if (priv->phandle->is_suspended == MTRUE) {
+			PRINTM(MERROR,
+			       "IOCTL is not allowed while suspended\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);
+#ifdef DFS_TESTING_SUPPORT
+		if (priv->phandle->cac_period_jiffies) {
+			cac_left_jiffies = priv->phandle->cac_period_jiffies -
+				(jiffies - priv->phandle->meas_start_jiffies);
+		}
+#endif
+		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 && 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;
+				memcpy(&priv->phandle->delay_ssid_bssid,
+				       &bss->param.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:
+		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
+ *
+ *  @return       MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ *                  -- success, otherwise fail
+ */
+mlan_status
+woal_request_set_mac_address(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_MAC_ADDR;
+	memcpy(&bss->param.mac_addr, priv->current_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, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
+		HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
+	} else {
+		PRINTM(MERROR,
+		       "set mac address failed! status=%d, error_code=0x%x\n",
+		       status, req->status_code);
+	}
+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;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_NO_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)
+		memcpy(&bss->param.deauth_param.mac_addr, mac,
+		       sizeof(mlan_802_11_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 Check current uap/go connection status
+ *         Need handle channel switch if current channel is DFS channel
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param new channel 		new channel
+ *  @return              N/A
+ */
+void
+woal_check_uap_dfs_status(moal_private *priv, t_u8 wait_option,
+			  t_u8 new_channel)
+{
+	chan_band_info channel;
+	mlan_bss_info bss_info;
+#if defined(UAP_SUPPORT)
+	IEEEtypes_ChanSwitchAnn_t *chan_switch = NULL;
+	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;
+	t_u8 bw = 0, oper_class = 0;
+#endif
+
+	/* Get BSS information */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, wait_option, &bss_info))
+		goto done;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_ap_channel(priv, MLAN_ACT_GET, wait_option, &channel))
+		goto done;
+	PRINTM(MCMND, "is_11h_active=%d dfs_check_channel=%d\n",
+	       bss_info.is_11h_active, bss_info.dfs_check_channel);
+	PRINTM(MCMND, "uap current channel=%d new_channel=%d\n",
+	       channel.channel, new_channel);
+#if defined(UAP_SUPPORT)
+	if (new_channel == channel.channel)
+		goto done;
+	if (bss_info.is_11h_active &&
+	    (bss_info.dfs_check_channel == channel.channel)) {
+		if (new_channel < MAX_BG_CHANNEL) {
+			bw = 20;
+		} else {
+			switch (channel.bandcfg.chanWidth) {
+			case CHAN_BW_20MHZ:
+				bw = 20;
+				break;
+			case CHAN_BW_40MHZ:
+				bw = 40;
+				break;
+			case CHAN_BW_80MHZ:
+				bw = 80;
+				break;
+			default:
+				break;
+			}
+		}
+		woal_priv_get_nonglobal_operclass_by_bw_channel(priv, bw,
+								new_channel,
+								&oper_class);
+		PRINTM(MCMND,
+		       "Switch the uap channel from %d to %d, oper_class=%d bw=%d\n",
+		       channel.channel, new_channel, oper_class, bw);
+		ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+		if (ioctl_req) {
+			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 */
+			if (!oper_class) {
+				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 =
+					sizeof(IEEEtypes_ChanSwitchAnn_t) -
+					sizeof(IEEEtypes_Header_t);
+				chan_switch->chan_switch_mode = 1;	/* STA should not transmit */
+				chan_switch->new_channel_num = new_channel;
+				chan_switch->chan_switch_count =
+					DEF_CHAN_SWITCH_COUNT;
+				DBG_HEXDUMP(MCMD_D, "CSA IE",
+					    (t_u8 *)pcust_chansw_ie->ie_buffer,
+					    pcust_chansw_ie->ie_length);
+			} else {
+				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;
+				ext_chan_switch->element_id =
+					EXTEND_CHANNEL_SWITCH_ANN;
+				ext_chan_switch->len =
+					sizeof(IEEEtypes_ExtChanSwitchAnn_t) -
+					sizeof(IEEEtypes_Header_t);
+				ext_chan_switch->chan_switch_mode = 1;	/* STA should not transmit */
+				ext_chan_switch->new_channel_num = new_channel;
+				ext_chan_switch->chan_switch_count =
+					DEF_CHAN_SWITCH_COUNT;
+				ext_chan_switch->new_oper_class = oper_class;
+				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,
+						    wait_option);
+			if (status != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Failed to set CSA IE\n");
+				goto done;
+			}
+			PRINTM(MCMND, "CSA/ECSA ie index=%d\n",
+			       pcust_chansw_ie->ie_index);
+			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 *
+							 (DEF_CHAN_SWITCH_COUNT
+							  + 2) * 110 / 1000);
+
+			pcust_chansw_ie->ie_index = 0xffff;
+			pcust_chansw_ie->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			status = woal_request_ioctl(priv, ioctl_req,
+						    MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Failed to clear CSA/ECSA IE\n");
+			}
+		}
+	}
+#endif
+done:
+#if defined(UAP_SUPPORT)
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+#endif
+	return;
+}
+
+/**
+ *  @brief Check current multi-channel connections
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param new channel 	new channel
+ *
+ *  @return              N/A
+ */
+void
+woal_check_mc_connection(moal_private *priv, t_u8 wait_option, t_u8 new_channel)
+{
+	moal_handle *handle = priv->phandle;
+#ifdef UAP_SUPPORT
+	int i;
+#endif
+	t_u16 enable = 0;
+
+	woal_mc_policy_cfg(priv, &enable, wait_option, MLAN_ACT_GET);
+	if (!enable)
+		return;
+#ifdef UAP_SUPPORT
+	for (i = 0; i < handle->priv_num; i++) {
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
+			if (handle->priv[i]->bss_started == MTRUE)
+				woal_check_uap_dfs_status(handle->priv[i],
+							  wait_option,
+							  new_channel);
+		}
+	}
+#endif
+	return;
+}
+
+/**
+ *  @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;
+	mlan_ssid_bssid temp_ssid_bssid;
+
+	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);
+	}
+	memcpy(&temp_ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_find_best_network(priv, wait_option, &temp_ssid_bssid))
+		woal_check_mc_connection(priv, wait_option,
+					 temp_ssid_bssid.channel);
+
+	/* 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)
+		memcpy(&bss->param.ssid_bssid, 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);
+#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)
+			memcpy(bss_info, &info->param.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)
+			memcpy(misc->param.gen_ie.ie_data, ie, *ie_len);
+	}
+
+	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)
+			memcpy(ie, misc->param.gen_ie.ie_data, *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(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 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(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(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)
+		memcpy(&pcfg->param.power_cfg, power_cfg,
+		       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)
+		memcpy(power_cfg, &pcfg->param.power_cfg,
+		       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(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 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();
+	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))
+		memcpy(&rate->param.rate_cfg, datarate,
+		       sizeof(mlan_rate_cfg_t));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret == MLAN_STATUS_SUCCESS && datarate && action == MLAN_ACT_GET)
+		memcpy(datarate, &rate->param.rate_cfg,
+		       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)
+		memcpy(assoc_rsp, &misc->param.assoc_resp,
+		       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_ecsa_enable = info->param.fw_info.ecsa_enable;
+		priv->phandle->fw_getlog_enable =
+			info->param.fw_info.getlog_enable;
+		priv->phandle->fw_roaming_support =
+			info->param.fw_info.fw_roaming_support;
+		if (priv->current_addr[0] == 0xff)
+			memcpy(priv->current_addr,
+			       &info->param.fw_info.mac_addr,
+			       sizeof(mlan_802_11_mac_addr));
+		memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
+		if (fw_info)
+			memcpy(fw_info, &info->param.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);
+	memcpy(buf, &cfg->param.ext_cap, sizeof(ExtCap_t));
+	ret = sizeof(ExtCap_t);
+out:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef PROC_DEBUG
+/**
+ *  @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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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) {
+			memcpy(debug_info, &info->param.debug_info,
+			       sizeof(mlan_debug_info));
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+#endif /* PROC_DEBUG */
+
+#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 > MLAN_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) > MLAN_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 *custom_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;
+	custom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), flag);
+	if (!custom_ie) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (copy_from_user
+	    (custom_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 ((custom_ie->len == 0)||(custom_ie->len ==
+				    sizeof(custom_ie->ie_data_list[0].
+					   ie_index)))
+		ioctl_req->action = MLAN_ACT_GET;
+	else
+		ioctl_req->action = MLAN_ACT_SET;
+
+	memcpy(&misc->param.cust_ie, 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(custom_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;
+	IEEEtypes_ActionCategory_e *action_cat;
+	t_u8 *action;
+	struct tx_status_info *tx_info = NULL;
+	struct sk_buff *skb = NULL;
+	unsigned long flags;
+	struct ieee80211_mgmt *mgmt_frame;
+	t_u8 *pdata;
+
+	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;
+	action_cat =
+		(IEEEtypes_ActionCategory_e *)&pmbuf->pbuf[pmbuf->data_offset +
+							   MLAN_ACTION_FRAME_CATEGORY_OFFSET];
+	action = &pmbuf->pbuf[pmbuf->data_offset +
+			      MLAN_ACTION_FRAME_ACTION_OFFSET];
+
+	if (*action_cat == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM &&
+	    *action == 0x1) {
+		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(pmbuf->data_len, GFP_ATOMIC);
+			if (skb) {
+				mgmt_frame = (struct ieee80211_mgmt *)skb->data;
+				//Copy DA,SA and BSSID feilds.
+				pdata = (t_u8 *)mgmt_frame->da;
+				memcpy(pdata,
+				       &pmbuf->pbuf[pmbuf->data_offset + 14],
+				       3 * MLAN_MAC_ADDR_LENGTH);
+				//Copy packet data starting from category field
+				pdata = (t_u8 *)&mgmt_frame->u.action.category;
+				memcpy(pdata, (t_u8 *)action_cat,
+				       packet_len - sizeof(t_u16) -
+				       sizeof(moal_wlan_802_11_header));
+				/* packet_len - size of frame length field send from app */
+				skb_put(skb, packet_len - sizeof(t_u16));
+				spin_lock_irqsave(&priv->tx_stat_lock, flags);
+				tx_info->tx_skb = skb;
+				tx_info->tx_seq_num = pmbuf->tx_seq_num;
+				tx_info->tx_cookie = 0;
+				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);
+		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;
+	memcpy(pcust_bcn_ie->ie_buffer, ie, ie_len);
+
+	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;
+
+	memcpy(&misc->param.tdls_config, tdls_data,
+	       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_IOCTL_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(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(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)
+#if defined(WIFI_DIRECT_SUPPORT)
+		    || (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
+#endif
+			) {
+			PRINTM(MWARN, "Invalid BSS role\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (bss_role == 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(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 */
+
+#if defined(SDIO_SUSPEND_RESUME)
+#endif
+
+/**
+ *  @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_IOCTL_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)
+		memcpy(&pmcfg->param.hs_cfg, hscfg, 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) {
+			memcpy(hscfg, &pmcfg->param.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);
+	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 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)
+{
+	moal_handle *handle = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_hs_cfg hscfg;
+	int i;
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	handle = priv->phandle;
+	/* 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 (roamoffload_in_hs) {
+		/*Disable firmware roaming */
+		woal_enable_fw_roaming(priv, 0);
+	}
+	if (handle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
+	    handle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
+	    handle->fw_roam_enable == AUTO_RECONNECT)
+		woal_config_fw_roaming(priv, ROAM_OFFLOAD_RESUME_CFG, NULL);
+	if (handle->fw_roam_enable == AUTO_RECONNECT)
+		woal_set_clear_pmk(priv, MLAN_ACT_CLEAR);
+
+#if defined(SDIO_SUSPEND_RESUME)
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	if (GTK_REKEY_OFFLOAD_SUSPEND == 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);
+			}
+		}
+	}
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**  @brief This function config fw roaming parameters
+ *
+ *  @param priv     A Pointer to the moal_private structure
+ *  @return         MTRUE or MFALSE
+ */
+int
+woal_set_fw_roaming_params(moal_private *priv)
+{
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	woal_roam_offload_cfg roam_offload_cfg;
+	t_u8 zero[MLAN_MAX_KEY_LENGTH] = { 0 };
+
+	/*Enable fw roaming */
+	woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, NULL);
+	/*Download fw roaming parameters */
+	woal_config_fw_roaming(priv, ROAM_OFFLOAD_PARAM_CFG,
+			       &priv->phandle->fw_roam_params);
+
+	/*Download userset passphrase key and current connection's PMK */
+	if (!priv->phandle->fw_roam_params.userset_passphrase) {
+		woal_set_clear_pmk(priv, MLAN_ACT_SET);
+		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;
+	sec->multi_passphrase = 1;
+	req->action = MLAN_ACT_SET;
+
+	/*Copy user set passphrase */
+	memcpy((char *)sec->param.roam_passphrase,
+	       (char *)priv->phandle->ssid_passphrase,
+	       MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
+	roam_offload_cfg.userset_passphrase =
+		priv->phandle->fw_roam_params.userset_passphrase;
+
+	if (memcmp(priv->pmk.pmk, zero, MLAN_MAX_KEY_LENGTH)) {
+		/*Download current connection PMK */
+		if (priv->pmk_saved) {
+			woal_set_clear_pmk(priv, MLAN_ACT_SET);
+			priv->pmk_saved = false;
+		}
+	}
+
+	/*Set userset to mlan adapter */
+	woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, &roam_offload_cfg);
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (ret)
+		goto done;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**  @brief This function enable/disable fw roaming
+ *
+ *  @param priv     A Pointer to the moal_private structure
+ *  @param enable   Enable/disable fw roaming
+ *  @return         MTRUE or MFALSE
+ */
+int
+woal_enable_fw_roaming(moal_private *priv, int data)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_roam_offload *roam = 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;
+	}
+
+	if (!data && !priv->phandle->fw_roam_enable) {
+		PRINTM(MIOCTL, "Fw roaming already disabled\n");
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_ROAM_OFFLOAD;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	roam = (mlan_ds_misc_roam_offload *) & misc->param.roam_offload;
+	roam->aplist.ap_num = 0;
+	/* SET operation */
+	ioctl_req->action = MLAN_ACT_SET;
+	roam->enable = data;
+	roam->config_mode = ROAM_OFFLOAD_ENABLE;
+
+	if (roamoffload_in_hs && data) {
+		priv->phandle->fw_roam_enable = data;
+		goto done;
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	priv->phandle->fw_roam_enable = data;
+	if (!data) {
+		memset((char *)&priv->phandle->fw_roam_params, 0,
+		       sizeof(woal_roam_offload_cfg));
+		memset((char *)&priv->phandle->ssid_passphrase, 0,
+		       MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
+	} else if (priv->media_connected && priv->pmk_saved) {
+		woal_set_clear_pmk(priv, MLAN_ACT_SET);
+		priv->pmk_saved = false;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO_SUSPEND_RESUME)
+/**  @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
+
+	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 (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_IOCTL_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
+
+	if (roamoffload_in_hs && handle->fw_roam_enable) {
+		woal_set_fw_roaming_params(priv);
+	}
+	if (handle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
+	    handle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
+	    handle->fw_roam_enable == AUTO_RECONNECT) {
+		woal_config_fw_roaming(priv, ROAM_OFFLOAD_SUSPEND_CFG, NULL);
+		if (priv->phandle->fw_roam_enable == AUTO_RECONNECT)
+			woal_set_clear_pmk(priv, MLAN_ACT_SET);
+	}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	if (GTK_REKEY_OFFLOAD_SUSPEND == 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);
+			}
+		}
+	}
+#endif
+
+	/* 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_interruptible_timeout(handle->hs_activate_wait_q,
+						   handle->
+						   hs_activate_wait_q_woken,
+						   HS_ACTIVE_TIMEOUT);
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	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 {
+		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 */
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	if (hs_actived != MTRUE) {
+		handle->hs_skip_count++;
+#ifdef SDIO_SUSPEND_RESUME
+		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;
+}
+#endif
+
+#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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	union {
+		t_u32 l;
+		t_u8 c[4];
+	} ver;
+	char fw_ver[32];
+
+	ENTER();
+
+	ver.l = handle->fw_release_number;
+	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 drvdbg       Driver debug level
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_set_drvdbg(moal_private *priv, t_u32 drvdbg)
+{
+	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 = drvdbg;
+
+	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_IOCTL_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)
+		memcpy(&misc->param.mgmt_subtype_mask,
+		       pmgmt_subtype_mask,
+		       sizeof(misc->param.mgmt_subtype_mask));
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+
+	if (req->action == MLAN_ACT_GET)
+		memcpy(pmgmt_subtype_mask, &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;
+	memcpy(&bf_cfg->param.tx_bf, 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)
+		memcpy(tx_bf_cfg, &bf_cfg->param.tx_bf,
+		       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)
+{
+	ENTER();
+
+	if (priv == NULL) {
+		LEAVE();
+		return;
+	}
+	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) {
+			memcpy(pm_info, &pmcfg->param.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 && 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;
+	chan_band_info chan;
+	chan_band_info uapchan;
+	ENTER();
+
+	if (priv->skip_cac) {
+		LEAVE();
+		return ret;
+	}
+
+	/* 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)) {
+		/* When any other interface is active
+		 * Get rid of CAC timer when drcs is disabled */
+		t_u16 enable = 0;
+		ret = woal_mc_policy_cfg(priv, &enable, wait_option,
+					 MLAN_ACT_GET);
+		if (!enable) {
+			LEAVE();
+			return ret;
+		} else {
+			woal_get_active_intf_channel(priv, &chan);
+			woal_set_get_ap_channel(priv, MLAN_ACT_GET,
+						MOAL_IOCTL_WAIT, &uapchan);
+			if (chan.channel != uapchan.channel) {
+				if (uapchan.is_dfs_chan) {
+					PRINTM(MERROR,
+					       "DFS channel is not allowed when another connection exists on different channel\n");
+					PRINTM(MERROR,
+					       "Another connection's channel=%d, dfs channel=%d\n",
+					       chan.channel, uapchan.channel);
+					return -EINVAL;
+				} else {
+					//check if we need move first uap0 from DFS channel to new non dfs channel
+					woal_check_mc_connection(priv,
+								 wait_option,
+								 uapchan.
+								 channel);
+				}
+			}
+		}
+	}
+
+	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 && 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();
+
+	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;
+	memcpy(&radio_cfg->param.remain_chan, pchan,
+	       sizeof(mlan_ds_remain_chan));
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		memcpy(pchan, &radio_cfg->param.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;
+}
+
+#if defined(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;
+	memcpy(&misc_cfg->param.p2p_config, p2p_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)
+			memcpy(p2p_config, &misc_cfg->param.p2p_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)
+{
+	int ret = 0;
+	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");
+		ret = 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)
+		memcpy(channel, &(bss->param.sta_channel), sizeof(*channel));
+
+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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+			memcpy(signal, &info->param.signal,
+			       sizeof(mlan_ds_get_signal));
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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;
+	memcpy((void *)&scan->param.scan_resp, (void *)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) {
+			memcpy(scan_resp, &scan->param.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;
+
+		memcpy(scan->param.scan_req.scan_ssid.ssid,
+		       req_ssid->ssid,
+		       MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len));
+		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));
+	memcpy(&bss->param.ssid_bssid.ssid, &bss_info.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;
+	t_u8 *mac = 0;
+
+	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;
+
+	memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		memcpy(ssid_bssid, &bss->param.ssid_bssid,
+		       sizeof(mlan_ssid_bssid));
+		mac = (t_u8 *)&ssid_bssid->bssid;
+		PRINTM(MINFO, "Find network: ssid=%s, " MACSTR ", idx=%d\n",
+		       ssid_bssid->ssid.ssid, MAC2STR(mac),
+		       (int)ssid_bssid->idx);
+	}
+
+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;
+	t_u8 *mac = 0;
+
+	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;
+
+	memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
+
+	mac = (t_u8 *)&ssid_bssid->bssid;
+	PRINTM(MINFO, "ssid=%s, " MACSTR ", idx=%d\n",
+	       ssid_bssid->ssid.ssid, MAC2STR(mac), (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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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;
+	memcpy(scan->param.user_scan.scan_cfg_buf, 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);
+
+	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)
+		memcpy(scan_cfg, &scan->param.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);
+	memcpy(&scan->param.scan_cfg, &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(cfg80211_wext) && handle->scan_request) {
+	    /** 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;
+	struct 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) {
+	/** skip check the scan age out */
+		ret = woal_find_best_network(priv, wait_option, ssid_bssid);
+		LEAVE();
+		return ret;
+	}
+#endif
+	do_gettimeofday(&t);
+/** scan result timeout value */
+#define SCAN_RESULT_AGEOUT      10
+	if (t.tv_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                    auto reconnection configure
+ *
+ * @param priv               Pointer to moal_private structure
+ * @param cfg_mode           configure mode
+ * @param roam_offload_cfg   Pointer to woal_roam_offload_cfg structure
+ *
+ *  @return                  Number of bytes written, negative for failure.
+ */
+mlan_status
+woal_config_fw_roaming(moal_private *priv, t_u8 cfg_mode,
+		       woal_roam_offload_cfg * roam_offload_cfg)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_roam_offload *roam = 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_ROAM_OFFLOAD;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	roam = (mlan_ds_misc_roam_offload *) & misc->param.roam_offload;
+	roam->aplist.ap_num = 0;
+	ioctl_req->action = MLAN_ACT_SET;
+	roam->enable = priv->phandle->fw_roam_enable;
+	roam->config_mode = cfg_mode;
+
+	if ((roam->config_mode == ROAM_OFFLOAD_ENABLE) && roam_offload_cfg) {
+		roam->userset_passphrase = roam_offload_cfg->userset_passphrase;
+		if (roam->userset_passphrase)
+			roam->enable = 0;
+	}
+	if (roam->config_mode == ROAM_OFFLOAD_PARAM_CFG) {
+		memcpy((t_u8 *)&roam->bssid_reconnect,
+		       (t_u8 *)&roam_offload_cfg->bssid, MLAN_MAC_ADDR_LENGTH);
+		if (roam_offload_cfg->ssid_list.ssid_num) {
+			memcpy((t_u8 *)&roam->ssid_list,
+			       (t_u8 *)&roam_offload_cfg->ssid_list,
+			       sizeof(mlan_ds_misc_ssid_list));
+		}
+		if (roam_offload_cfg->black_list.ap_num) {
+			memcpy((t_u8 *)&roam->black_list,
+			       (t_u8 *)&roam_offload_cfg->black_list,
+			       sizeof(mlan_ds_misc_roam_offload_aplist));
+		}
+		roam->trigger_condition = roam_offload_cfg->trigger_condition;
+		roam->retry_count = roam_offload_cfg->retry_count;
+		if (roam_offload_cfg->rssi_param_set_flag) {
+			roam->para_rssi.set_flag = 1;
+			roam->para_rssi.max_rssi = roam_offload_cfg->max_rssi;
+			roam->para_rssi.min_rssi = roam_offload_cfg->min_rssi;
+			roam->para_rssi.step_rssi = roam_offload_cfg->step_rssi;
+		}
+		if (roam_offload_cfg->band_rssi_flag) {
+			roam->band_rssi_flag = roam_offload_cfg->band_rssi_flag;
+			memcpy((t_u8 *)&roam->band_rssi,
+			       (t_u8 *)&roam_offload_cfg->band_rssi,
+			       sizeof(mlan_ds_misc_band_rssi));
+		}
+		if (roam_offload_cfg->bgscan_set_flag) {
+			roam->bgscan_set_flag =
+				roam_offload_cfg->bgscan_set_flag;
+			memcpy((t_u8 *)&roam->bgscan_cfg,
+			       (t_u8 *)&roam_offload_cfg->bgscan_cfg,
+			       sizeof(mlan_ds_misc_bgscan_cfg));
+		}
+		if (roam_offload_cfg->ees_param_set_flag) {
+			roam->ees_param_set_flag =
+				roam_offload_cfg->ees_param_set_flag;
+			memcpy((t_u8 *)&roam->ees_cfg,
+			       (t_u8 *)&roam_offload_cfg->ees_cfg,
+			       sizeof(mlan_ds_misc_ees_cfg));
+		}
+		roam->bcn_miss_threshold = roam_offload_cfg->bcn_miss_threshold;
+		roam->pre_bcn_miss_threshold =
+			roam_offload_cfg->pre_bcn_miss_threshold;
+		roam->repeat_count = roam_offload_cfg->repeat_count;
+	}
+	if (roam->config_mode == ROAM_OFFLOAD_SUSPEND_CFG) {
+		memcpy(roam->bssid_reconnect,
+		       priv->phandle->auto_reconnect_bssid,
+		       MLAN_MAC_ADDR_LENGTH);
+		roam->ssid_list.ssid_num = 1;
+		memcpy((t_u8 *)&roam->ssid_list.ssids[0].ssid,
+		       (t_u8 *)&priv->phandle->auto_reconnect_ssid.ssid,
+		       priv->phandle->auto_reconnect_ssid.ssid_len);
+
+		roam->retry_count = priv->phandle->auto_reconnect_retry_count;
+	}
+
+	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 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;
+	memcpy(scan->param.user_scan.scan_cfg_buf, scan_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;
+		memcpy(priv->scan_cfg.random_mac, priv->random_mac, ETH_ALEN);
+		ret = woal_request_bgscan(priv, MOAL_IOCTL_WAIT,
+					  &priv->scan_cfg);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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;
+}
+
+/**
+ *  @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)
+		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);
+	memcpy(&scan->param.scan_cfg, &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);
+	memcpy(&scan->param.scan_cfg, &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;
+
+	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 */
+
+/**
+ * @brief Set/Get configure multi-channel policy
+ *
+ * @param priv		A pointer to moal_private structure
+ * @param enable	A pointer to enable
+ * @param wait_option	wait_option of ioctl
+ * @param action	action of ioctl
+ *
+ * @return          MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_mc_policy_cfg(moal_private *priv, t_u16 *enable,
+		   t_u8 wait_option, t_u8 action)
+{
+	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) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_MULTI_CHAN_POLICY;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = action;
+	if (MLAN_ACT_SET == action)
+		cfg->param.multi_chan_policy = *enable;
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (MLAN_ACT_GET == action)
+		*enable = cfg->param.multi_chan_policy;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ * @brief               Set/Get network monitor configurations
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param wait_option  wait option
+ * @param enable	    Enable/Disable
+ * @param filter	    Filter flag - Management/Control/Data
+ * @param band_chan_cfg           Network monitor band channel config
+ *
+ * @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_net_monitor(moal_private *priv, t_u8 wait_option,
+		     t_u8 enable, t_u8 filter,
+		     netmon_band_chan_cfg * band_chan_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_net_monitor *net_mon = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	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;
+	net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
+	misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	net_mon->enable_net_mon = enable;
+	if (net_mon->enable_net_mon) {
+		net_mon->filter_flag = filter;
+		if (band_chan_cfg && band_chan_cfg->channel) {
+			/* fill TLV only if chan band is specified */
+			net_mon->band = band_chan_cfg->band;
+			net_mon->channel = band_chan_cfg->channel;
+			net_mon->chan_bandwidth = band_chan_cfg->chan_bandwidth;
+		}
+	}
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* update chan band values from response in band_chan_cfg */
+	if (net_mon->enable_net_mon) {
+		if (band_chan_cfg) {
+			band_chan_cfg->band = net_mon->band;
+			band_chan_cfg->channel = net_mon->channel;
+			band_chan_cfg->chan_bandwidth = net_mon->chan_bandwidth;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @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;
+	memcpy(del_ba->peer_mac_addr, zero_mac, ETH_ALEN);
+
+	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 config RTT to mlan layer
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param ch_info   A pointer to wifi_channel_info
+ *  @param bandcfg  A pointer to Band_Config_t
+ *
+ *  @return            void
+ */
+void
+woal_channel_info_to_bandcfg(moal_private *priv, wifi_channel_info * ch_info,
+			     Band_Config_t *bandcfg)
+{
+	t_u8 channel = 0;
+
+	if (!ch_info || !bandcfg)
+		return;
+
+	channel = ieee80211_frequency_to_channel(ch_info->center_freq);
+
+	switch (ch_info->width) {
+	case WIFI_CHAN_WIDTH_10:
+		bandcfg->chanWidth = CHAN_BW_10MHZ;
+		break;
+	case WIFI_CHAN_WIDTH_20:
+		bandcfg->chanWidth = CHAN_BW_20MHZ;
+		break;
+	case WIFI_CHAN_WIDTH_40:
+		bandcfg->chanWidth = CHAN_BW_40MHZ;
+		break;
+	case WIFI_CHAN_WIDTH_80:
+		bandcfg->chanWidth = CHAN_BW_80MHZ;
+		break;
+	default:
+		bandcfg->chanWidth = CHAN_BW_20MHZ;
+		break;
+	}
+	bandcfg->chan2Offset = SEC_CHAN_NONE;
+	if (bandcfg->chanWidth == CHAN_BW_40MHZ) {
+		if (ch_info->center_freq0 < ch_info->center_freq)
+			bandcfg->chan2Offset = SEC_CHAN_BELOW;
+		else
+			bandcfg->chan2Offset = SEC_CHAN_ABOVE;
+	} else if (bandcfg->chanWidth == CHAN_BW_80MHZ)
+		bandcfg->chan2Offset = woal_get_second_channel_offset(channel);
+	bandcfg->chanBand = (channel <= MAX_BG_CHANNEL) ? BAND_2GHZ : BAND_5GHZ;
+	bandcfg->scanMode = SCAN_MODE_MANUAL;
+
+	return;
+}
+
+/**
+ *  @brief config RTT to mlan layer
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param ch_info   A pointer to wifi_channel_info
+ *  @param bandcfg  A pointer to Band_Config_t
+ *
+ *  @return            void
+ */
+void
+woal_bandcfg_to_channel_info(moal_private *priv, Band_Config_t *bandcfg,
+			     t_u8 channel, wifi_channel_info * ch_info)
+{
+	if (!ch_info || !bandcfg)
+		return;
+
+	ch_info->center_freq =
+		ieee80211_channel_to_frequency(channel,
+					       (channel <=
+						MAX_BG_CHANNEL) ?
+					       NL80211_BAND_2GHZ :
+					       NL80211_BAND_5GHZ);
+
+	switch (bandcfg->chanWidth) {
+	case CHAN_BW_10MHZ:
+		ch_info->width = WIFI_CHAN_WIDTH_10;
+		break;
+	case CHAN_BW_20MHZ:
+		ch_info->width = WIFI_CHAN_WIDTH_20;
+		break;
+	case CHAN_BW_40MHZ:
+		ch_info->width = WIFI_CHAN_WIDTH_40;
+		break;
+	case CHAN_BW_80MHZ:
+		ch_info->width = WIFI_CHAN_WIDTH_80;
+		break;
+	default:
+		ch_info->width = WIFI_CHAN_WIDTH_20;
+		break;
+	}
+
+	return;
+}
+
+/**
+ *  @brief config RTT to mlan layer
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  wait option
+ *  @param hotspotcfg   A pointer to rtt_config_params_t
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+woal_config_rtt(moal_private *priv, t_u8 wait_option,
+		wifi_rtt_config_params_t * rtt_params_in)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_rtt_config_params *rtt_params = NULL;
+	t_u32 i = 0;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	req->action = MLAN_ACT_SET;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CONFIG_RTT;
+	rtt_params = &(misc->param.rtt_params);
+	rtt_params->rtt_config_num = rtt_params_in->rtt_config_num;
+	for (i = 0; i < MIN(rtt_params->rtt_config_num, MAX_RTT_CONFIG_NUM);
+	     i++) {
+		memcpy(rtt_params->rtt_config[i].addr,
+		       rtt_params_in->rtt_config[i].addr,
+		       sizeof(rtt_params->rtt_config[i].addr));
+		rtt_params->rtt_config[i].type =
+			rtt_params_in->rtt_config[i].type;
+		rtt_params->rtt_config[i].peer =
+			rtt_params_in->rtt_config[i].peer;
+		rtt_params->rtt_config[i].channel =
+			ieee80211_frequency_to_channel(rtt_params_in->
+						       rtt_config[i].channel.
+						       center_freq);
+		woal_channel_info_to_bandcfg(priv,
+					     &(rtt_params_in->rtt_config[i].
+					       channel),
+					     &(rtt_params->rtt_config[i].
+					       bandcfg));
+		rtt_params->rtt_config[i].burst_period =
+			rtt_params_in->rtt_config[i].burst_period;
+		rtt_params->rtt_config[i].num_burst =
+			rtt_params_in->rtt_config[i].num_burst;
+		rtt_params->rtt_config[i].num_frames_per_burst =
+			rtt_params_in->rtt_config[i].num_frames_per_burst;
+		rtt_params->rtt_config[i].num_retries_per_rtt_frame =
+			rtt_params_in->rtt_config[i].num_retries_per_rtt_frame;
+		rtt_params->rtt_config[i].num_retries_per_ftmr =
+			rtt_params_in->rtt_config[i].num_retries_per_ftmr;
+		rtt_params->rtt_config[i].LCI_request =
+			rtt_params_in->rtt_config[i].LCI_request;
+		rtt_params->rtt_config[i].LCR_request =
+			rtt_params_in->rtt_config[i].LCR_request;
+		rtt_params->rtt_config[i].burst_duration =
+			rtt_params_in->rtt_config[i].burst_duration;
+		rtt_params->rtt_config[i].preamble =
+			rtt_params_in->rtt_config[i].preamble;
+		rtt_params->rtt_config[i].bw = rtt_params_in->rtt_config[i].bw;
+	}
+
+	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 cancel RTT to mlan layer
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  wait option
+ *  @param hotspotcfg   A pointer to rtt_config_params_t
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+woal_cancel_rtt(moal_private *priv, t_u8 wait_option, t_u32 addr_num,
+		t_u8 addr[][MLAN_MAC_ADDR_LENGTH])
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_rtt_cancel_params *rtt_cancel = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	req->action = MLAN_ACT_SET;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CANCEL_RTT;
+	rtt_cancel = &(misc->param.rtt_cancel);
+	rtt_cancel->rtt_cancel_num = addr_num;
+	memcpy(rtt_cancel->rtt_cancel, addr,
+	       sizeof(rtt_cancel->rtt_cancel[0]) *
+	       MIN(rtt_cancel->rtt_cancel_num, MAX_RTT_CONFIG_NUM));
+
+	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 cancel RTT to mlan layer
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  wait option
+ *  @param hotspotcfg   A pointer to rtt_config_params_t
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+woal_rtt_responder_cfg(moal_private *priv, t_u8 wait_option,
+		       mlan_rtt_responder * rtt_rsp_cfg)
+{
+	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 == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	req->action = MLAN_ACT_SET;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_RTT_RESPONDER_CFG;
+	memcpy(&(misc->param.rtt_rsp_cfg), rtt_rsp_cfg,
+	       sizeof(misc->param.rtt_rsp_cfg));
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	memcpy(rtt_rsp_cfg, &(misc->param.rtt_rsp_cfg), sizeof(*rtt_rsp_cfg));
+
+done:
+	if (ret != 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)
+{
+	char event[1000];
+	mlan_ds_host_clock *host_clock = NULL;
+	ENTER();
+	switch (info->sub_command) {
+	case MLAN_OID_MISC_GET_CORRELATED_TIME:
+		host_clock = &info->param.host_clock;
+		memset(event, 0, sizeof(event));
+		sprintf(event, "%s %llu %llu", CUS_EVT_GET_CORRELATED_TIME,
+			host_clock->time, host_clock->fw_time);
+		woal_broadcast_event(priv, event, strlen(event));
+		PRINTM(MERROR, "CMD = %s\n", event);
+	default:
+		break;
+	}
+}
+
+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");
diff --git a/wlan_sd8997/mlinux/moal_main.c b/wlan_sd8997/mlinux/moal_main.c
new file mode 100644
index 0000000..68d419f
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_main.c
@@ -0,0 +1,9040 @@
+/** @file moal_main.c
+  *
+  * @brief This file contains the major functions in WLAN
+  * driver.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+#include    "moal_sdio.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include    "moal_cfg80211.h"
+#include    "moal_cfgvendor.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
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+#define KERN_VERSION    "3X"
+
+/** Driver version */
+char driver_version[] =
+	"SD8997-%s-C" KERN_VERSION "16" MLAN_RELEASE_VERSION
+	"-GPL" "-(" "FP" FPNUM ")"
+#ifdef	DEBUG_LEVEL2
+	"-dbg"
+#endif
+	" ";
+
+/** Firmware name */
+char *fw_name;
+int req_fw_nowait;
+int fw_reload;
+
+/** MAC address */
+char *mac_addr;
+
+#ifdef MFG_CMD_SUPPORT
+/** Mfg mode */
+int mfg_mode;
+#endif
+
+/** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+int intmode = INT_MODE_SDIO;
+/** GPIO interrupt pin number */
+int gpiopin;
+
+#ifdef CONFIG_OF
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+/** Region alpha2 string */
+extern char *reg_alpha2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int country_ie_ignore;
+extern int beacon_hints;
+#endif
+#endif
+extern int cfg80211_drcs;
+#endif
+
+int drcs_chantime_mode = 0;
+
+/** Auto deep sleep */
+int auto_ds;
+
+/** IEEE PS mode */
+int ps_mode;
+
+/** Max Tx buffer size */
+int max_tx_buf;
+
+#ifdef STA_SUPPORT
+/** Max STA interfaces */
+int max_sta_bss = DEF_STA_BSS;
+/** STA interface name */
+char *sta_name;
+#endif
+
+#ifdef UAP_SUPPORT
+/** Max uAP interfaces */
+int max_uap_bss = DEF_UAP_BSS;
+/** uAP interface name */
+char *uap_name;
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+/** Max WIFIDIRECT interfaces */
+int max_wfd_bss = DEF_WIFIDIRECT_BSS;
+/** WIFIDIRECT interface name */
+char *wfd_name;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+/** max VIRTUAL bss */
+int max_vir_bss = DEF_VIRTUAL_BSS;
+#endif
+#endif
+
+/** Max NAN interfaces */
+int max_nan_bss = DEF_NAN_BSS;
+/** NAN interface name */
+char *nan_name;
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+int pm_keep_power = 1;
+/** HS when shutdown */
+int shutdown_hs;
+#endif
+
+#if defined(STA_SUPPORT)
+/** 802.11d configuration */
+int cfg_11d;
+#endif
+
+/** fw serial download check */
+int fw_serial = 1;
+
+/** napi support*/
+int napi;
+
+/** DPD data config file */
+char *dpd_data_cfg;
+
+/** CAL data config file */
+char *cal_data_cfg;
+/** Init config file (MAC address, register etc.) */
+char *init_cfg;
+
+/** Set configuration data of Tx power limitation */
+char *txpwrlimit_cfg;
+/** Set configuration data of Tx power limitatio */
+char *country_txpwrlimit;
+/** Allow setting tx power table of country */
+int cntry_txpwr = 0;
+
+/** Init hostcmd file */
+char *init_hostcmd_cfg;
+
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+/** CFG80211 and WEXT mode */
+int cfg80211_wext = STA_WEXT_MASK | UAP_WEXT_MASK;
+#else
+/** CFG80211 mode */
+int cfg80211_wext = STA_CFG80211_MASK | UAP_CFG80211_MASK;
+#endif
+
+int fw_region = 1;
+
+/** Work queue priority */
+int wq_sched_prio;
+/** Work queue scheduling policy */
+int wq_sched_policy = SCHED_NORMAL;
+/** rx_work flag */
+int rx_work;
+
+int hw_test;
+
+#ifdef CONFIG_OF
+int dts_enable = 1;
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+int p2p_enh;
+#endif
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+int dfs_offload = 0;
+#endif
+
+int roamoffload_in_hs = 0;
+
+#ifdef ANDROID_KERNEL
+int wakelock_timeout = WAKE_LOCK_TIMEOUT;
+#endif
+
+/** woal_callbacks */
+static mlan_callbacks woal_callbacks = {
+	.moal_get_fw_data = moal_get_fw_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_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,
+
+	.moal_write_reg = moal_write_reg,
+	.moal_read_reg = moal_read_reg,
+	.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,
+	.moal_memset = moal_memset,
+	.moal_memcpy = moal_memcpy,
+	.moal_memmove = moal_memmove,
+	.moal_memcmp = moal_memcmp,
+	.moal_udelay = moal_udelay,
+	.moal_get_system_time = moal_get_system_time,
+	.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_get_host_time_ns = moal_get_host_time_ns,
+	.moal_do_div = moal_do_div,
+};
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#if defined(WIFI_DIRECT_SUPPORT)
+int drv_mode = (DRV_MODE_STA | DRV_MODE_UAP | DRV_MODE_WIFIDIRECT);
+#else
+int drv_mode = (DRV_MODE_STA | DRV_MODE_UAP);
+#endif
+#else
+#ifdef STA_SUPPORT
+int drv_mode = DRV_MODE_STA;
+#else
+int drv_mode = DRV_MODE_UAP;
+#endif /* STA_SUPPORT */
+#endif /* STA_SUPPORT & UAP_SUPPORT */
+
+int gtk_rekey_offload = GTK_REKEY_OFFLOAD_DISABLE;
+
+int pmic = 0;
+
+int antcfg = 0;
+
+t_u32 uap_oper_ctrl = 0;
+
+int hs_wake_interval = 400;
+int indication_gpio = 0xff;
+
+int indrstcfg = 0xffffffff;
+
+/** all the feature are enabled */
+#define DEFAULT_DEV_CAP_MASK 0xffffffff
+t_u32 dev_cap_mask = DEFAULT_DEV_CAP_MASK;
+int sdio_rx_aggr = MTRUE;
+/********************************************************
+		Global Variables
+********************************************************/
+
+/** 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];
+
+/** The global variable of scan beacon buffer **/
+int fixed_beacon_buffer = 0;
+/** the pointer of new fwdump fname for each dump**/
+char *fwdump_fname = NULL;
+
+#ifdef WIFI_DIRECT_SUPPORT
+int GoAgeoutTime = 0;
+#endif
+
+t_u16 multi_dtim = 0;
+
+t_u16 inact_tmo = 0;
+
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define	DEFAULT_DEBUG_MASK	(0xffffffff)
+#else
+#define DEFAULT_DEBUG_MASK	(MMSG | MFATAL | MERROR)
+#endif /* DEBUG_LEVEL2 */
+t_u32 drvdbg = DEFAULT_DEBUG_MASK;
+
+#endif /* DEBUG_LEVEL1 */
+
+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);
+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)
+u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb,
+		      void *accel_priv, select_queue_fallback_t fallback);
+#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
+
+void woal_sdio_reg_dbg(moal_handle *phandle);
+
+mlan_debug_info info;
+
+static moal_handle *reset_handle;
+/** Hang workqueue */
+static struct workqueue_struct *hang_workqueue;
+/** Hang work */
+static struct work_struct hang_work;
+
+/**
+ *  @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;
+	ENTER();
+	if (!reset_handle) {
+		LEAVE();
+		return;
+	}
+	for (i = 0; i < reset_handle->priv_num; i++) {
+		if (reset_handle->priv[i] && reset_handle->priv[i]->netdev) {
+			PRINTM(MMSG, "Close netdev %s\n",
+			       reset_handle->priv[i]->netdev->name);
+			rtnl_lock();
+			dev_close(reset_handle->priv[i]->netdev);
+			rtnl_unlock();
+			break;
+		}
+	}
+	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;
+		mlan_ioctl(handle->pmlan_adapter, NULL);
+		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++) {
+#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 set/clear pmk to FW
+ *
+ *  @param priv     A Pointer to the moal_private structure
+ *  @param action     set/clear action
+ *
+ *  @return      0: success  fail otherwise
+ */
+int
+woal_set_clear_pmk(moal_private *priv, t_u8 action)
+{
+	mlan_ioctl_req *req;
+	mlan_ds_sec_cfg *sec;
+	mlan_status status;
+	int ret = 0;
+	t_u8 zero[MLAN_MAX_KEY_LENGTH] = { 0 };
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+
+	if (req == NULL) {
+		ret = -ENOMEM;
+	} else {
+		sec = (mlan_ds_sec_cfg *)req->pbuf;
+		sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE;
+		req->req_id = MLAN_IOCTL_SEC_CFG;
+		req->action = action;
+
+		if (action == MLAN_ACT_SET) {
+			sec->param.passphrase.psk_type = MLAN_PSK_PMK;
+			if (memcmp(priv->pmk.pmk, zero, MLAN_MAX_KEY_LENGTH))
+				memcpy(&sec->param.passphrase.psk.pmk.pmk,
+				       priv->pmk.pmk, MLAN_MAX_KEY_LENGTH);
+			if (memcmp(priv->pmk.pmk_r0, zero, MLAN_MAX_KEY_LENGTH)
+			    && memcmp(priv->pmk.pmk_r0_name, zero,
+				      MLAN_MAX_PMKR0_NAME_LENGTH)) {
+				memcpy(&sec->param.passphrase.psk.pmk.pmk_r0,
+				       priv->pmk.pmk_r0, MLAN_MAX_KEY_LENGTH);
+				memcpy(&sec->param.passphrase.psk.pmk.
+				       pmk_r0_name, priv->pmk.pmk_r0_name,
+				       MLAN_MAX_PMKR0_NAME_LENGTH);
+			}
+		}
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (MLAN_STATUS_SUCCESS != status)
+			ret = -EFAULT;
+		if (status != MLAN_STATUS_PENDING)
+			kfree(req);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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
+
+#if defined(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)) {
+					memcpy(&ssid_bssid->ssid,
+					       &bss_info.ssid,
+					       sizeof(bss_info.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)) {
+				memcpy(&ssid_bssid->bssid, &bss_info.bssid,
+				       MLAN_MAC_ADDR_LENGTH);
+				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 Get mode
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option   Wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
+ *
+ *  @return              Wireless mode
+ */
+t_u32
+woal_get_mode(moal_private *priv, t_u8 wait_option)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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
+ */
+static void
+woal_update_firmware_name(moal_handle *handle)
+{
+	if (fw_name) {
+		handle->drv_mode.fw_name = fw_name;
+	} else {
+		if (!fw_serial || handle->fw_reload || fw_reload)
+			handle->drv_mode.fw_name = DEFAULT_WLAN_FW_NAME;
+		else
+#if defined(UAP_SUPPORT) && defined(STA_SUPPORT)
+			handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME;
+#else
+#ifdef UAP_SUPPORT
+			handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME;
+#else
+			handle->drv_mode.fw_name = DEFAULT_FW_NAME;
+#endif /* UAP_SUPPORT */
+#endif /* UAP_SUPPORT && STA_SUPPORT */
+	}
+}
+
+/**
+ *  @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;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	int last_wfd_index = 0;
+#endif
+#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;
+	}
+#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;
+	}
+#endif /* UAP_SUPPORT */
+
+#if defined(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;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+		intf_num += max_vir_bss;
+#endif
+	}
+#endif /* WIFI_DIRECT_SUPPORT  && V14_FEATURE */
+
+	if (drv_mode_local & DRV_MODE_NAN) {
+		if ((max_nan_bss < 1) || (max_nan_bss > MAX_NAN_BSS)) {
+			PRINTM(MWARN,
+			       "Unsupported max_nan_bss (%d), setting to default\n",
+			       max_nan_bss);
+			max_nan_bss = DEF_NAN_BSS;
+		}
+		intf_num += max_nan_bss;
+	}
+
+	/* 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 >= 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 >= 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 */
+
+#if defined(WIFI_DIRECT_SUPPORT)
+	if (drv_mode_local & DRV_MODE_WIFIDIRECT) {
+		for (j = 0; j < max_wfd_bss; j++) {
+			if (i >= 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 && V14_FEATURE */
+
+	if (drv_mode_local & DRV_MODE_NAN) {
+		for (j = 0; j < max_nan_bss; j++) {
+			if (i >= intf_num)
+				break;
+			bss_tbl[i].bss_type = MLAN_BSS_TYPE_NAN;
+			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(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 >= 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 = 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;
+}
+
+#ifdef CONFIG_OF
+/**
+ *  @brief This function read the initial parameter from device tress
+ *
+ *  @return         N/A
+ */
+static 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, "sd8xxx-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;
+			}
+		}
+#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);
+			}
+		}
+#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
+#if defined(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, "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
+#if defined(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;
+			}
+		} else if (!strncmp(prop->name, "p2p_enh", strlen("p2p_enh"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "p2p_enh=0x%x\n", data);
+				p2p_enh = data;
+			}
+		} else if (!strncmp
+			   (prop->name, "cfg80211_drcs",
+			    strlen("cfg80211_drcs"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "cfg80211_drcs=0x%x\n", data);
+				cfg80211_drcs = 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, "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);
+			}
+		}
+#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, "drcs_chantime_mode",
+			    strlen("drcs_chantime_mode"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				drcs_chantime_mode = data;
+				PRINTM(MIOCTL, "drcs_chantime_mode=%d\n",
+				       drcs_chantime_mode);
+			}
+		} 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, "roamoffload_in_hs",
+			  strlen("roamoffload_in_hs"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				roamoffload_in_hs = data;
+				PRINTM(MIOCTL, "roamoffload_in_hs=%d\n",
+				       roamoffload_in_hs);
+			}
+		} 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);
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function initializes software
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_init_sw(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	unsigned int i;
+	mlan_device device;
+	t_void *pmlan;
+
+	ENTER();
+
+	/* Initialize moal_handle structure */
+	handle->hardware_status = HardwareStatusInitializing;
+	handle->main_state = MOAL_STATE_IDLE;
+
+#ifdef STA_SUPPORT
+	if ((drv_mode & DRV_MODE_STA)
+#ifdef STA_WEXT
+	    && !IS_STA_WEXT(cfg80211_wext)
+#endif
+#ifdef STA_CFG80211
+	    && !IS_STA_CFG80211(cfg80211_wext)
+#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
+
+	memcpy(handle->driver_version, driver_version, strlen(driver_version));
+
+	if (woal_update_drv_tbl(handle, 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);
+
+#if defined(SDIO_SUSPEND_RESUME)
+	handle->is_suspended = MFALSE;
+	handle->hs_activated = MFALSE;
+	handle->hs_auto_arp = MTRUE;
+	handle->suspend_fail = MFALSE;
+#ifdef SDIO_SUSPEND_RESUME
+	handle->suspend_notify_req = MFALSE;
+#endif
+	handle->hs_skip_count = 0;
+	handle->hs_force_count = 0;
+	handle->cmd52_func = 0;
+	handle->cmd52_reg = 0;
+	handle->cmd52_val = 0;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	handle->scan_chan_gap = DEF_SCAN_CHAN_GAP;
+#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
+	init_waitqueue_head(&handle->hs_activate_wait_q);
+#endif
+
+	/* 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
+
+#ifdef DFS_TESTING_SUPPORT
+	handle->cac_period_jiffies = 0;
+#endif
+#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
+	handle->mon_if = NULL;
+
+#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 */
+
+#if defined(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
+
+	handle->rtt_capa.rtt_one_sided_supported = MTRUE;
+	handle->rtt_capa.rtt_ftm_supported = MTRUE;
+	handle->rtt_capa.lci_support = MTRUE;
+	handle->rtt_capa.lcr_support = MTRUE;
+	handle->rtt_capa.preamble_support =
+		PREAMBLE_LEGACY | PREAMBLE_HT | PREAMBLE_VHT;
+	handle->rtt_capa.bw_support =
+		BW_20_SUPPORT | BW_40_SUPPORT | BW_80_SUPPORT;
+	handle->rtt_capa.responder_supported = MTRUE;
+	handle->rtt_capa.mc_version = 60;
+
+	/* Register to MLAN */
+	memset(&device, 0, sizeof(mlan_device));
+	device.pmoal_handle = handle;
+
+	device.sdio_rx_aggr_enable = sdio_rx_aggr;
+
+#ifdef MFG_CMD_SUPPORT
+	device.mfg_mode = (t_u32)mfg_mode;
+#endif
+	device.int_mode = (t_u32)intmode;
+	device.gpio_pin = (t_u32)gpiopin;
+#ifdef DEBUG_LEVEL1
+	device.drvdbg = drvdbg;
+#endif
+	device.fixed_beacon_buffer = (t_u32)fixed_beacon_buffer;
+	device.auto_ds = (t_u32)auto_ds;
+	device.ps_mode = (t_u32)ps_mode;
+	device.max_tx_buf = (t_u32)max_tx_buf;
+#if defined(STA_SUPPORT)
+	device.cfg_11d = (t_u32)cfg_11d;
+#endif
+	device.indrstcfg = (t_u32)indrstcfg;
+	device.drcs_chantime_mode = (t_u32)drcs_chantime_mode;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+#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);
+#endif
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+#ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
+	device.mpa_tx_cfg = MLAN_INIT_PARA_ENABLED;
+#else
+	device.mpa_tx_cfg = MLAN_INIT_PARA_DISABLED;
+#endif
+#endif
+#ifdef SDIO_MULTI_PORT_RX_AGGR
+#ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
+	device.mpa_rx_cfg = MLAN_INIT_PARA_ENABLED;
+#else
+	device.mpa_rx_cfg = MLAN_INIT_PARA_DISABLED;
+#endif
+#endif
+
+	if (rx_work == MLAN_INIT_PARA_ENABLED)
+		device.rx_work = MTRUE;
+	else if (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 (napi)
+		device.rx_work = MTRUE;
+
+	device.dev_cap_mask = dev_cap_mask;
+
+	device.multi_dtim = multi_dtim;
+
+	device.inact_tmo = inact_tmo;
+	device.hs_wake_interval = hs_wake_interval;
+	device.indication_gpio = indication_gpio;
+
+	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;
+	}
+	memcpy(&device.callbacks, &woal_callbacks, sizeof(mlan_callbacks));
+	if (fw_region)
+		device.fw_region = MTRUE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	if (MLAN_STATUS_SUCCESS == mlan_register(&device, &pmlan))
+		handle->pmlan_adapter = pmlan;
+	else
+		ret = MLAN_STATUS_FAILURE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees the structure of moal_handle
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         N/A
+ */
+static void
+woal_free_moal_handle(moal_handle *handle)
+{
+	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);
+		wiphy_free(handle->wiphy);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		kfree(handle->regd);
+#endif
+		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);
+
+	/* 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));
+	}
+	/* Free allocated memory for fwdump filename */
+	kfree(handle->fwdump_fname);
+	if (fwdump_fname) {
+		kfree(fwdump_fname);
+		fwdump_fname = 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 >= 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 < 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;
+}
+
+#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;
+
+	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;
+	}
+
+	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 ((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);
+#if defined(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])) {
+							PRINTM(MERROR,
+							       "Set MAC address failed\n");
+							goto done;
+						}
+						memcpy(handle->priv[i]->netdev->
+						       dev_addr,
+						       handle->priv[i]->
+						       current_addr, 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 */
+			strncpy(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)));
+			memcpy(buf + strlen(CMD_STR), &cmd_len, sizeof(t_u32));
+
+			/* 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
+
+/**
+ * @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_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
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+woal_set_user_init_data(moal_handle *handle, int type, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 *cfg_data = NULL;
+	t_size len;
+
+	ENTER();
+
+	if (type == INIT_CFG_DATA) {
+		if (req_fw_nowait) {
+#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
+				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 (req_fw_nowait) {
+#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
+				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 {
+			int status =
+				request_firmware(&handle->user_data,
+						 country_txpwrlimit,
+						 handle->hotplug_device);
+			/* File does not exist, skip download */
+			if (status == -ENOENT) {
+				PRINTM(MIOCTL,
+				       "Country power table file does not exist\n");
+				LEAVE();
+				return MLAN_STATUS_SUCCESS;
+			} else if (status) {
+				PRINTM(MERROR,
+				       "country txpwrlimit config file request_firmware() failed\n");
+				goto done;
+			}
+		}
+	} else if (type == INIT_HOSTCMD_CFG_DATA) {
+		if (req_fw_nowait) {
+#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
+				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 (handle->user_data) {
+		cfg_data = (t_u8 *)(handle->user_data)->data;
+		len = (handle->user_data)->size;
+		if (type == INIT_HOSTCMD_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;
+}
+
+/**
+ * @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();
+
+#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);
+
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode == MLAN_INIT_PARA_ENABLED)
+		goto done;
+#endif
+
+	if (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 (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 (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 (uap_oper_ctrl)
+		woal_set_uap_operation_ctrl(handle);
+#endif
+
+#ifdef MFG_CMD_SUPPORT
+done:
+#endif
+err:
+	if (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");
+
+		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 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;
+	t_u8 retry = 0;
+
+	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 (fw_reload == FW_RELOAD_SDIO_INBAND_RESET)
+			fw.fw_reload = fw_reload;
+		else
+			fw.fw_reload = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+		ret = mlan_dnld_fw(handle->pmlan_adapter, &fw);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+		if (ret == MLAN_STATUS_FAILURE) {
+			PRINTM(MERROR,
+			       "WLAN: Fail download FW with nowwait: %d\n",
+			       req_fw_nowait);
+			woal_sdio_reg_dbg(handle);
+			goto done;
+		}
+		PRINTM(MMSG, "WLAN FW is active\n");
+	}
+
+    /** data request */
+	memset(&param, 0, sizeof(mlan_init_param));
+
+	if (dpd_data_cfg && strncmp(dpd_data_cfg, "none", strlen("none"))) {
+		if (req_fw_nowait) {
+#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
+				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 {
+			if ((request_firmware
+			     (&handle->dpd_data, dpd_data_cfg,
+			      handle->hotplug_device)) < 0) {
+				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;
+		}
+	}
+	if (txpwrlimit_cfg && strncmp(txpwrlimit_cfg, "none", strlen("none"))) {
+		if (req_fw_nowait) {
+#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
+				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;
+		}
+	}
+
+	if (cal_data_cfg && strncmp(cal_data_cfg, "none", strlen("none"))) {
+		if (req_fw_nowait) {
+#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
+				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) {
+		PRINTM(MERROR,
+		       "Please add cal_data_cfg for 8887/8977/8997/8987/9098\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;
+	}
+
+	handle->hardware_status = HardwareStatusFwReady;
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (handle->fw_reload)
+		goto done;
+	handle->init_wait_q_woken = MFALSE;
+
+	ret = mlan_set_init_param(handle->pmlan_adapter, &param);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	ret = mlan_init_fw(handle->pmlan_adapter);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	if (ret == MLAN_STATUS_FAILURE)
+		goto done;
+	else if (ret == MLAN_STATUS_SUCCESS) {
+		handle->hardware_status = HardwareStatusReady;
+		goto done;
+	}
+	/* Wait for mlan_init to complete */
+	while (wait_event_interruptible(handle->init_wait_q,
+					handle->init_wait_q_woken) ==
+	       -ERESTARTSYS && retry < MAX_RETRY_CNT) {
+		retry++;
+	}
+	if (handle->hardware_status != HardwareStatusReady) {
+		woal_moal_debug_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
+				     handle, MTRUE);
+#if defined(DEBUG_LEVEL1)
+		if (drvdbg & MFW_D) {
+			drvdbg &= ~MFW_D;
+			woal_dump_firmware_info_v3(handle);
+		}
+#endif
+		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;
+	struct timeval tstamp;
+
+	ENTER();
+
+	if (!firmware) {
+		do_gettimeofday(&tstamp);
+		if (tstamp.tv_sec >
+		    (handle->req_fw_time.tv_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)
+{
+	ENTER();
+	woal_request_fw_dpc((moal_handle *)context, firmware);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+	if (firmware)
+		release_firmware(firmware);
+#endif
+	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)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int err;
+
+	ENTER();
+
+	PRINTM(MMSG, "Request firmware: %s\n", handle->drv_mode.fw_name);
+	if (req_fw_nowait) {
+#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
+		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);
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes firmware
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_init_fw(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	do_gettimeofday(&handle->req_fw_time);
+
+	ret = woal_request_fw(handle);
+	if (ret < 0) {
+		PRINTM(MFATAL, "woal_request_fw failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+done:
+	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
+ */
+static void
+woal_fill_mlan_buffer(moal_private *priv,
+		      mlan_buffer *pmbuf, struct sk_buff *skb)
+{
+	struct timeval tstamp;
+	struct ethhdr *eth;
+	t_u8 tid;
+	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.
+	 */
+	do_gettimeofday(&tstamp);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+	skb->tstamp = timeval_to_ktime(tstamp);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+	skb_set_timestamp(skb, &tstamp);
+#else
+	memcpy(&skb->stamp, &tstamp, sizeof(skb->stamp));
+#endif
+
+	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 = 0;
+	pmbuf->in_ts_sec = (t_u32)tstamp.tv_sec;
+	pmbuf->in_ts_usec = (t_u32)tstamp.tv_usec;
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief This function opens the network device for monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_mon_open(struct net_device *ndev)
+{
+	ENTER();
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief This function closes the network device for monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_mon_close(struct net_device *ndev)
+{
+	ENTER();
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief This function sets the MAC address to firmware for monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ * @param addr            MAC address to set
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_mon_set_mac_address(struct net_device *ndev, void *addr)
+{
+	ENTER();
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief This function sets multicast address to firmware for monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+void
+woal_mon_set_multicast_list(struct net_device *ndev)
+{
+	ENTER();
+	LEAVE();
+}
+
+/**
+ * @brief This function handles packet transmission for monitor interface
+ *
+ * @param skb             A pointer to sk_buff structure
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	int len_rthdr;
+	int qos_len = 0;
+	int dot11_hdr_len = 24;
+	int snap_len = 6;
+	unsigned char *pdata;
+	unsigned short fc;
+	unsigned char src_mac_addr[6];
+	unsigned char dst_mac_addr[6];
+	struct ieee80211_hdr *dot11_hdr;
+	struct ieee80211_radiotap_header *prthdr =
+		(struct ieee80211_radiotap_header *)skb->data;
+	monitor_iface *mon_if = netdev_priv(ndev);
+
+	ENTER();
+
+	if (mon_if == NULL || mon_if->base_ndev == NULL) {
+		goto fail;
+	}
+
+	/* check for not even having the fixed radiotap header part */
+	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) {
+		PRINTM(MERROR, "Invalid radiotap hdr length,"
+		       "skb->len: %d\n", skb->len);
+		goto fail;	/* too short to be possibly valid */
+	}
+
+	/* is it a header version we can trust to find length from? */
+	if (unlikely(prthdr->it_version))
+		goto fail;	/* only version 0 is supported */
+
+	/* then there must be a radiotap header with a length we can use */
+	len_rthdr = ieee80211_get_radiotap_len(skb->data);
+
+	/* does the skb contain enough to deliver on the alleged length? */
+	if (unlikely(skb->len < len_rthdr)) {
+		PRINTM(MERROR, "Invalid data length,"
+		       "skb->len: %d\n", skb->len);
+		goto fail;	/* skb too short for claimed rt header extent */
+	}
+
+	/* Skip the ratiotap header */
+	skb_pull(skb, len_rthdr);
+
+	dot11_hdr = (struct ieee80211_hdr *)skb->data;
+	fc = le16_to_cpu(dot11_hdr->frame_control);
+	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
+		/* Check if this ia a Wireless Distribution System (WDS) frame
+		 * which has 4 MAC addresses
+		 */
+		if (dot11_hdr->frame_control & 0x0080)
+			qos_len = 2;
+		if ((dot11_hdr->frame_control & 0x0300) == 0x0300)
+			dot11_hdr_len += 6;
+
+		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
+		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
+
+		/* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for
+		 * for two MAC addresses
+		 */
+		skb_pull(skb,
+			 dot11_hdr_len + qos_len + snap_len -
+			 sizeof(src_mac_addr) * 2);
+		pdata = (unsigned char *)skb->data;
+		memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));
+		memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr,
+		       sizeof(src_mac_addr));
+
+		LEAVE();
+		return woal_hard_start_xmit(skb, mon_if->base_ndev);
+	}
+
+fail:
+	dev_kfree_skb(skb);
+	LEAVE();
+	return NETDEV_TX_OK;
+}
+
+/**
+ *  @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_mon_get_stats(struct net_device *dev)
+{
+	monitor_iface *mon_if = (monitor_iface *)netdev_priv(dev);
+	return &mon_if->stats;
+}
+
+static const struct net_device_ops woal_cfg80211_mon_if_ops = {
+	.ndo_open = woal_mon_open,
+	.ndo_start_xmit = woal_mon_hard_start_xmit,
+	.ndo_stop = woal_mon_close,
+	.ndo_get_stats = woal_mon_get_stats,
+	.ndo_set_mac_address = woal_mon_set_mac_address,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	.ndo_set_rx_mode = woal_mon_set_multicast_list,
+#else
+	.ndo_set_multicast_list = woal_mon_set_multicast_list,
+#endif
+};
+
+/**
+ * @brief This function setup monitor interface
+ *
+ * @param dev             A pointer to net_device structure
+ * @param addr            MAC address to set
+ *
+ * @return                0 -- success, otherwise fail
+ */
+
+void
+woal_mon_if_setup(struct net_device *dev)
+{
+	ENTER();
+	ether_setup(dev);
+	dev->netdev_ops = &woal_cfg80211_mon_if_ops;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 9)
+	dev->needs_free_netdev = true;
+#else
+	dev->destructor = free_netdev;
+#endif
+	LEAVE();
+}
+
+/**
+ * @brief Request the driver to add a monitor interface
+ *
+ * @param priv             A pointer to moal_private
+ * @param name              Virtual interface name
+ * @param name_assign_type  Interface name assignment type
+ *
+ * @return                  A pointer to monitor_iface
+ */
+monitor_iface *
+woal_prepare_mon_if(moal_private *priv,
+		    const char *name, unsigned char name_assign_type)
+{
+	int ret = 0;
+	struct net_device *ndev = NULL;
+	monitor_iface *mon_if = NULL;
+
+	ENTER();
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	ndev = alloc_netdev_mq(sizeof(*mon_if), name, name_assign_type,
+			       woal_mon_if_setup, 1);
+#else
+	ndev = alloc_netdev_mq(sizeof(*mon_if), name, NET_NAME_UNKNOWN,
+			       woal_mon_if_setup, 1);
+#endif
+#else
+	ndev = alloc_netdev_mq(sizeof(*mon_if), name, woal_mon_if_setup, 1);
+#endif
+#else
+	ndev = alloc_netdev_mq(sizeof(*mon_if), name, woal_mon_if_setup);
+#endif
+	if (!ndev) {
+		PRINTM(MFATAL, "Init virtual ethernet device failed\n");
+		ret = -EFAULT;
+		goto fail;
+	}
+
+	ret = dev_alloc_name(ndev, ndev->name);
+	if (ret < 0) {
+		PRINTM(MFATAL, "Net device alloc name fail.\n");
+		ret = -EFAULT;
+		goto fail;
+	}
+	//?memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
+
+	mon_if = netdev_priv(ndev);
+	memcpy(mon_if->ifname, ndev->name, IFNAMSIZ);
+
+	ndev->type = ARPHRD_IEEE80211_RADIOTAP;
+	ndev->netdev_ops = &woal_cfg80211_mon_if_ops;
+
+	mon_if->priv = priv;
+	mon_if->mon_ndev = ndev;
+	mon_if->base_ndev = priv->netdev;
+	mon_if->radiotap_enabled = 1;
+	mon_if->flag = 1;
+
+fail:
+	if (ret) {
+		if (ndev)
+			free_netdev(ndev);
+		LEAVE();
+		return NULL;
+	}
+
+	LEAVE();
+	return mon_if;
+}
+
+#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,
+	.ndo_do_ioctl = woal_do_ioctl,
+	.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(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(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,
+	.ndo_do_ioctl = woal_uap_do_ioctl,
+	.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(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 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 (sta_name)
+		snprintf(name, sizeof(name), "%s%%d", sta_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 (uap_name)
+		snprintf(name, sizeof(name), "%s%%d", 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
+#if defined(WIFI_DIRECT_SUPPORT)
+	memset(name, 0, sizeof(name));
+	if (wfd_name)
+		snprintf(name, sizeof(name), "%s%%d", 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
+	memset(name, 0, sizeof(name));
+	if (nan_name)
+		snprintf(name, sizeof(name), "%s%%d", nan_name);
+	else
+		snprintf(name, sizeof(name), "%s", default_nan_name);
+	if ((bss_type == MLAN_BSS_TYPE_NAN) && (dev_alloc_name(dev, name) < 0)) {
+		PRINTM(MERROR, "Could not allocate nan 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->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;
+#if defined(WIFI_DIRECT_SUPPORT)
+	else if (bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+		priv->bss_role = MLAN_BSS_ROLE_STA;
+#endif
+	else if (bss_type == MLAN_BSS_TYPE_NAN)
+		priv->bss_role = MLAN_BSS_ROLE_STA;
+
+	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
+#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
+#if defined(WIFI_DIRECT_SUPPORT)
+	    || bss_type == MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+	    || bss_type == MLAN_BSS_TYPE_NAN)
+		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
+	    && (mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		) {
+		if (init_cfg) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_user_init_data(handle, INIT_CFG_DATA,
+						    MOAL_IOCTL_WAIT)) {
+				PRINTM(MFATAL,
+				       "Set user init data and param failed\n");
+				goto error;
+			}
+		}
+		if (init_hostcmd_cfg) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_user_init_data(handle,
+						    INIT_HOSTCMD_CFG_DATA,
+						    MOAL_IOCTL_WAIT)) {
+				PRINTM(MFATAL,
+				       "Set user init hostcmd data and param failed\n");
+				goto error;
+			}
+		}
+	}
+
+	handle->priv_num++;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	if (!priv->phandle->wiphy && IS_STA_OR_UAP_CFG80211(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(cfg80211_wext)) {
+		if (bss_type == MLAN_BSS_TYPE_STA
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+		    || bss_type == MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+#endif
+		    || bss_type == MLAN_BSS_TYPE_NAN)
+			/* 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;
+			}
+	}
+#endif /* STA_SUPPORT */
+#endif /* STA_CFG80211 */
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+	if ((priv->bss_role == MLAN_BSS_ROLE_UAP) &&
+	    IS_UAP_CFG80211(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 */
+
+	/* 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: Marvell 802.11 Adapter\n", dev->name);
+	/* Set MAC address from the insmod command line */
+	if (handle->set_mac_addr) {
+		memset(priv->current_addr, 0, ETH_ALEN);
+		memcpy(priv->current_addr, handle->mac_addr, ETH_ALEN);
+#if defined(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)) {
+			PRINTM(MERROR, "Set MAC address failed\n");
+			goto error;
+		}
+		memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
+	}
+	/* Set MAC address for UAPx/MLANx/WFDx and let them different with each other */
+	if (priv->bss_index > 0
+#ifdef WIFI_DIRECT_SUPPORT
+	    && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+		) {
+		priv->current_addr[4] += priv->bss_index;
+		woal_request_set_mac_address(priv);
+		memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
+		PRINTM(MCMND, "Set %s interface addr: " MACSTR "\n", dev->name,
+		       MAC2STR(priv->current_addr));
+	}
+	if (bss_type == MLAN_BSS_TYPE_STA ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		mlan_fw_info fw_info;
+		woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+
+		for (i = 0; i < handle->histogram_table_num; i++) {
+			priv->hist_data[i] = kmalloc(sizeof(hgm_data) +
+						     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;
+			}
+		}
+		if (priv->hist_data)
+			woal_hist_data_reset(priv);
+	}
+#ifdef CONFIG_PROC_FS
+	woal_create_proc_entry(priv);
+#ifdef PROC_DEBUG
+	woal_debug_entry(priv);
+#endif /* PROC_DEBUG */
+#endif /* CONFIG_PROC_FS */
+
+	LEAVE();
+	return priv;
+error:
+	handle->priv_num = bss_index;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	/* Unregister wiphy device and free */
+	if (priv) {
+		if (priv->wdev && IS_STA_OR_UAP_CFG80211(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(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);
+
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_flush_tdls_list(priv);
+#ifdef STA_CFG80211
+#endif
+
+	if (priv->bss_type == MLAN_BSS_TYPE_STA ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		for (i = 0; i < handle->histogram_table_num; i++) {
+			kfree(priv->hist_data[i]);
+			priv->hist_data[i] = NULL;
+		}
+	}
+#ifdef CONFIG_PROC_FS
+#ifdef PROC_DEBUG
+	/* Remove proc debug */
+	woal_debug_remove(priv);
+#endif /* PROC_DEBUG */
+	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 defined(STA_CFG80211) || defined(UAP_CFG80211)
+	/* Unregister wiphy device and free */
+	if (priv->wdev && IS_STA_OR_UAP_CFG80211(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)
+		woal_deinit_wifi_hal(priv);
+#endif
+
+	/* Clear the priv in handle */
+	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;
+
+	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_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;
+
+	radio->param.ant_cfg.tx_antenna = (antcfg & 0x0030) >> 4;
+	radio->param.ant_cfg.rx_antenna = antcfg & 0x0003;
+	/* 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
+ */
+static 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 cancel all works in the queue
+ *  and destroy the main workqueue.
+ *
+ *  @param handle    A pointer to moal_handle
+ *
+ *  @return        N/A
+ */
+static 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;
+	}
+	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);
+	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(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. */
+	{
+		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 defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (!p2p_enh) {
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+		    IS_STA_CFG80211(cfg80211_wext)) {
+			priv->phandle->wiphy->interface_modes |=
+				MBIT(NL80211_IFTYPE_P2P_GO) |
+				MBIT(NL80211_IFTYPE_P2P_CLIENT);
+		}
+	}
+#endif
+#endif
+#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);
+
+	ENTER();
+	woal_flush_tx_stat_queue(priv);
+
+#ifdef STA_SUPPORT
+#ifdef STA_CFG80211
+	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)
+		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);
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (!p2p_enh) {
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+		    !priv->bss_virtual &&
+		    IS_STA_CFG80211(cfg80211_wext) &&
+		    IS_UAP_CFG80211(cfg80211_wext)) {
+			priv->phandle->wiphy->interface_modes &=
+				~(MBIT(NL80211_IFTYPE_P2P_GO) |
+				  MBIT(NL80211_IFTYPE_P2P_CLIENT));
+		}
+	}
+#endif
+#endif
+#endif
+	MODULE_PUT;
+
+	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;
+	}
+
+	memcpy(prev_addr, priv->current_addr, 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);
+	memcpy(priv->current_addr, phw_addr->sa_data, ETH_ALEN);
+#if defined(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)) {
+		PRINTM(MERROR, "Set MAC address failed\n");
+		/* For failure restore the MAC address */
+		memcpy(priv->current_addr, prev_addr, ETH_ALEN);
+		ret = -EFAULT;
+		goto done;
+	}
+	HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
+	memcpy(dev->dev_addr, priv->current_addr, 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;
+	struct timeval t;
+	int i = 0;
+	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
+	do_gettimeofday(&t);
+	if (info.pending_cmd &&
+	    (t.tv_sec > (info.dnld_cmd_in_secs + MOAL_CMD_TIMEOUT_MAX))) {
+		if (t.tv_sec > (info.dnld_cmd_in_secs + MOAL_CMD_TIMEOUT) &&
+		    !info.num_cmd_timeout) {
+			PRINTM(MERROR, "Ignore invalid time, wait=%d\n",
+			       (int)(t.tv_sec - info.dnld_cmd_in_secs));
+		} else {
+			PRINTM(MERROR, "Timeout cmd id = 0x%x wait=%d\n",
+			       info.pending_cmd,
+			       (int)(t.tv_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.tv_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.tv_sec - info.pm_wakeup_in_secs));
+			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_MULTI_PORT_TX_AGGR
+	int j;
+	t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+#endif
+	char str[512] = { 0 };
+	char *s;
+
+	ENTER();
+
+	if (!priv || 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, "num_cmd_timeout = %d\n", info.num_cmd_timeout);
+	PRINTM(MERROR, "dbg.num_cmd_timeout = %d\n", info.dbg_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);
+
+	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, "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, "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, "data_sent=%d cmd_sent=%d\n", info.data_sent,
+	       info.cmd_sent);
+
+	PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", info.ps_mode, info.ps_state);
+	PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d\n",
+	       info.pm_wakeup_card_req, info.pm_wakeup_fw_try);
+	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);
+
+	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_invalid_update=%d\n", info.mp_invalid_update);
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	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
+	for (i = 0; i < 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);
+	}
+
+	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
+ */
+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)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+
+	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) {
+		woal_mlan_debug_info(priv);
+		woal_moal_debug_info(priv, NULL, MFALSE);
+		woal_broadcast_event(priv, CUS_EVT_DRIVER_HANG,
+				     strlen(CUS_EVT_DRIVER_HANG));
+#if defined(STA_CFG80211) || defined(UAP_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
+		priv->phandle->driver_state = MTRUE;
+		woal_process_hang(priv->phandle);
+	}
+
+	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)
+		  , void *accel_priv
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 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();
+
+	/*
+	 * 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);
+}
+
+/**
+ *  @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();
+}
+
+/**
+ *  @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
+ */
+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();
+	memcpy(ra, skb->data, MLAN_MAC_ADDR_LENGTH);
+	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
+
+/**
+ *  @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
+ */
+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);
+				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
+ */
+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);
+			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
+ */
+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) {
+			/* 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, iph->saddr,
+						tcph->source, iph->daddr,
+						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 = iph->saddr;
+			tcp_session->dst_ip_addr = iph->daddr;
+			tcp_session->src_tcp_port = tcph->source;
+			tcp_session->dst_tcp_port = 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)) {
+			memcpy(skb->data, pmbuf->pbuf + pmbuf->data_offset,
+			       pmbuf->data_len);
+			tcp_session->ack_seq = ack_seq;
+			ret = DROP_TCP_ACK;
+			skb->cb[0]++;
+//We will drop 90% tcp ack
+#define TCP_ACK_MAX_HOLD    9
+			if (skb->cb[0] >= 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
+ */
+int
+woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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();
+	PRINTM(MDATA, "%lu : %s (bss=%d): Data <= kernel\n",
+	       jiffies, dev->name, priv->bss_index);
+
+	if (priv->phandle->surprise_removed == MTRUE) {
+		dev_kfree_skb_any(skb);
+		priv->stats.tx_dropped++;
+		goto done;
+	}
+	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;
+	}
+	if (skb->cloned || (skb_headroom(skb) < (MLAN_MIN_DATA_HEADER_LEN +
+						 sizeof(mlan_buffer) +
+						 priv->extra_tx_head_len))) {
+		PRINTM(MWARN,
+		       "Tx: skb cloned %d or Insufficient skb headroom %d\n",
+		       skb->cloned, skb_headroom(skb));
+		/* 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);
+		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;
+	}
+#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
+
+	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);
+			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 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;
+	}
+	memcpy(mac_buff, buf, strlen(buf));
+
+	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();
+	woal_request_set_multicast_list(priv, dev);
+	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;
+		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;
+#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
+#endif
+	}
+#endif
+
+	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;
+#endif
+
+#ifdef STA_SUPPORT
+	priv->pmk_saved = MFALSE;
+	memset(&priv->pmk, 0, sizeof(mlan_pmk_t));
+#endif
+
+	priv->enable_tcp_ack_enh = MTRUE;
+
+	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);
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+			if (priv->bss_virtual) {
+				if (priv->pa_netdev) {
+					memcpy(priv->current_addr,
+					       priv->pa_netdev->dev_addr,
+					       ETH_ALEN);
+					priv->current_addr[4] ^= 0x80;
+					woal_request_set_mac_address(priv);
+					memcpy(priv->netdev->dev_addr,
+					       priv->current_addr, ETH_ALEN);
+					PRINTM(MCMND,
+					       "Set WFD interface addr: " MACSTR
+					       "\n",
+					       MAC2STR(priv->current_addr));
+				}
+			} else {
+				priv->current_addr[0] |= 0x02;
+				woal_request_set_mac_address(priv);
+				memcpy(priv->netdev->dev_addr,
+				       priv->current_addr, ETH_ALEN);
+				PRINTM(MCMND,
+				       "Set WFD device addr: " MACSTR "\n",
+				       MAC2STR(priv->current_addr));
+			}
+		}
+#endif
+#endif
+#endif
+#ifdef UAP_SUPPORT
+#if defined(DFS_TESTING_SUPPORT)
+	priv->user_cac_period_msec = 0;
+#endif
+#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;
+
+	/* 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);
+
+#ifdef STA_SUPPORT
+	woal_cancel_scan(priv, wait_option);
+#endif
+
+	/* 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 defined(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;
+}
+
+#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
+		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);
+		memcpy(NLMSG_DATA(nlh), netdev->name, IFNAMSIZ);
+		memcpy(((t_u8 *)(NLMSG_DATA(nlh))) + IFNAMSIZ, payload, len);
+
+		/* 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);
+
+		/* 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;
+
+		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));
+			memcpy(&req_ssid,
+			       &priv->prev_ssid_bssid.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");
+					memcpy(&ssid_bssid.bssid,
+					       &priv->prev_ssid_bssid.bssid,
+					       MLAN_MAC_ADDR_LENGTH);
+				} else {
+					/* Search AP by ESSID for asynced essid setting */
+					PRINTM(MINFO,
+					       "Set asynced essid: Search AP by ESSID\n");
+				}
+
+				memcpy(&ssid_bssid.ssid,
+				       &priv->prev_ssid_bssid.ssid,
+				       sizeof(mlan_802_11_ssid));
+			} else {
+				/* Search AP by BSSID first */
+				PRINTM(MINFO,
+				       "Reassoc: Search AP by BSSID first\n");
+				memcpy(&ssid_bssid.bssid,
+				       &priv->prev_ssid_bssid.bssid,
+				       MLAN_MAC_ADDR_LENGTH);
+			}
+
+			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));
+				memcpy(&ssid_bssid.ssid,
+				       &priv->prev_ssid_bssid.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 {
+						memcpy(&priv->prev_ssid_bssid.
+						       ssid, &bss_info.ssid,
+						       sizeof
+						       (mlan_802_11_ssid));
+						memcpy(&priv->prev_ssid_bssid.
+						       bssid, &bss_info.bssid,
+						       MLAN_MAC_ADDR_LENGTH);
+					}
+					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 */
+
+#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;
+		}
+		memcpy(dscp_except,
+		       (t_u8 *)qos_mapping_ie + sizeof(IEEEtypes_Header_t),
+		       dscp_except_num * sizeof(DSCP_Exception_t));
+		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
+	mlan_ds_misc_gtk_rekey_data zero_gtk;
+	t_u16 reason_code = 0;
+
+	ENTER();
+	priv->media_connected = MFALSE;
+	if (!disconnect_reason)
+		reason_code = MLAN_REASON_DEAUTH_LEAVING;
+	else
+		reason_code = disconnect_reason;
+	woal_stop_queue(priv->netdev);
+	if (netif_carrier_ok(priv->netdev))
+		netif_carrier_off(priv->netdev);
+	woal_flush_tcp_sess_queue(priv);
+
+	priv->gtk_data_ready = MFALSE;
+	memset(&zero_gtk, 0x00, sizeof(zero_gtk));
+	if (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);
+	}
+	memset(&priv->gtk_rekey_data, 0, sizeof(mlan_ds_misc_gtk_rekey_data));
+
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_flush_tdls_list(priv);
+#ifdef STA_CFG80211
+#endif
+	if (priv->bss_type == MLAN_BSS_TYPE_STA && priv->hist_data)
+		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->iftype != NL80211_IFTYPE_ADHOC
+		    && ((priv->bss_type != MLAN_BSS_TYPE_STA) ||
+			(priv->bss_type == MLAN_BSS_TYPE_STA &&
+			 priv->sme_current.ssid))
+			) {
+			PRINTM(MMSG,
+			       "wlan: Disconnected from " MACSTR
+			       ": Reason code %d\n", MAC2STR(priv->cfg_bssid),
+			       reason_code);
+			spin_unlock_irqrestore(&priv->connect_lock, flags);
+			/* 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 */
+			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;
+		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);
+	strncpy(event_buf, CUS_EVT_AP_CONNECTED,
+		MIN((sizeof(event_buf) - 1), custom_len));
+	woal_broadcast_event(priv, event_buf, custom_len + ETH_ALEN);
+	LEAVE();
+}
+#endif /* STA_SUPPORT */
+
+#define OFFSET_SEQNUM 4
+/**
+ *  @brief  This function stores the FW dumps received from events in a file
+ *
+ *  @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)
+{
+	struct file *pfile_fwdump = NULL;
+	loff_t pos = 0;
+	t_u16 seqnum;
+	t_u8 path_name[64];
+
+	ENTER();
+	if (phandle->fwdump_fname)
+		pfile_fwdump =
+			filp_open(phandle->fwdump_fname,
+				  O_CREAT | O_WRONLY | O_APPEND, 0644);
+	else {
+		seqnum = woal_le16_to_cpu(*(t_u16 *)
+					  (pmevent->event_buf + OFFSET_SEQNUM));
+		if (seqnum == 1) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	    /** Create dump directort*/
+			woal_create_dump_dir(phandle, path_name,
+					     sizeof(path_name));
+#else
+			memset(path_name, 0, sizeof(path_name));
+			strcpy(path_name, "/data");
+#endif
+			PRINTM(MMSG, "Firmware Dump directory name is %s\n",
+			       path_name);
+			woal_dump_drv_info(phandle, path_name);
+			if (fwdump_fname) {
+				memset(fwdump_fname, 0, 64);
+			} else {
+				gfp_t flag;
+				flag = (in_atomic() ||
+					irqs_disabled())? GFP_ATOMIC :
+					GFP_KERNEL;
+				fwdump_fname = kzalloc(64, flag);
+			}
+			sprintf(fwdump_fname, "%s/file_fwdump", path_name);
+			pfile_fwdump =
+				filp_open(fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+			if (IS_ERR(pfile_fwdump)) {
+				memset(fwdump_fname, 0, 64);
+				sprintf(fwdump_fname, "%s/%s", "/var",
+					"file_fwdump");
+				pfile_fwdump =
+					filp_open(fwdump_fname,
+						  O_CREAT | O_WRONLY | O_APPEND,
+						  0644);
+			}
+		} else
+			pfile_fwdump =
+				filp_open(fwdump_fname,
+					  O_CREAT | O_WRONLY | O_APPEND, 0644);
+	}
+	if (IS_ERR(pfile_fwdump)) {
+		PRINTM(MERROR, "Cannot create firmware dump file\n");
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile_fwdump, pmevent->event_buf, pmevent->event_len, &pos);
+#else
+	kernel_write(pfile_fwdump, pmevent->event_buf, pmevent->event_len,
+		     &pos);
+#endif
+	filp_close(pfile_fwdump, NULL);
+	LEAVE();
+	return;
+}
+
+#define DRV_INFO_SIZE 0x40000
+#define ROW_SIZE_16      16
+#define ROW_SIZE_32      32
+/**
+ *  @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 < (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;
+}
+
+#define SDIO_SCRATCH_REG 0xE8
+/**
+ *  @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_dump_sdio_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 = SDIO_SCRATCH_REG;
+	unsigned int reg_table[] = { 0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62,
+		0x64, 0x65, 0x66, 0x68, 0x69, 0x6a
+	};
+	char buf[256], *ptr;
+
+	ENTER();
+
+	if (!phandle || !drv_buf) {
+		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
+		LEAVE();
+		return 0;
+	}
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+
+	drv_ptr += sprintf(drv_ptr, "--------sdio_reg_debug_info---------\n");
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+	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 = 0x10;
+			reg_end = 0x17;
+		} else if (loop == 2) {
+			/* Read specific registers of SDIO function1 */
+			index = 0;
+			func = 1;
+			reg_start = reg_table[index++];
+			reg_end =
+				reg_table[sizeof(reg_table) / sizeof(int) - 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)
+				data = sdio_f0_readb(((struct sdio_mmc_card *)
+						      phandle->card)->func, reg,
+						     &ret);
+			else
+				data = sdio_readb(((struct sdio_mmc_card *)
+						   phandle->card)->func, reg,
+						  &ret);
+			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);
+	}
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+
+	drv_ptr +=
+		sprintf(drv_ptr, "--------sdio_reg_debug_info End---------\n");
+
+	LEAVE();
+	return drv_ptr - (char *)drv_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;
+	char str_buf[MLAN_MAX_VER_STR_LEN];
+
+	ENTER();
+	if (!phandle || !buf) {
+		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
+		LEAVE();
+		return 0;
+	}
+	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);
+	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));
+#if defined(SDIO_SUSPEND_RESUME)
+	ptr += sprintf(ptr, "hs_skip_count = %u\n", phandle->hs_skip_count);
+	ptr += sprintf(ptr, "hs_force_count = %u\n", phandle->hs_force_count);
+#endif
+
+	ptr += woal_dump_priv_drv_info(phandle, ptr);
+	ptr += sprintf(ptr, "------------moal_debug_info End-------------\n");
+
+	ptr += woal_dump_sdio_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_MULTI_PORT_TX_AGGR
+	int j;
+	t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+#endif
+	char str[11 * DBG_CMD_NUM + 1] = { 0 };
+	char *s;
+
+	ENTER();
+	if (!priv || 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, "num_cmd_timeout = %d\n", info.num_cmd_timeout);
+	ptr += sprintf(ptr, "dbg.num_cmd_timeout = %d\n",
+		       info.dbg_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);
+	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, "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, "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, "data_sent=%d cmd_sent=%d\n", info.data_sent,
+		       info.cmd_sent);
+	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\n",
+		       info.pm_wakeup_card_req, info.pm_wakeup_fw_try);
+	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);
+
+	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_invalid_update=%d\n", info.mp_invalid_update);
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	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
+	ptr += sprintf(ptr, "------------mlan_debug_info End-------------\n");
+
+	LEAVE();
+	return ptr - (char *)buf;
+}
+
+/**
+ *  @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 < len; i += rowsize) {
+		linelen = min(remaining, rowsize);
+		remaining -= rowsize;
+
+		hex_dump_to_buffer(ptr + i, linelen, rowsize, 1, linebuf,
+				   sizeof(linebuf), ascii);
+
+		pos += sprintf(pos, "%p: %s\n", ptr + i, linebuf);
+	}
+
+	return pos - (char *)save_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++) {
+		ptr += sprintf(ptr, "<--moal_private(%d)-->\n", i);
+		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
+ *  @param pfile  A pointer to file structure
+ *
+ *  @return          The length of this log
+ */
+static int
+woal_dump_mlan_hex(moal_private *priv, t_u8 *buf, struct file *pfile)
+{
+	char *ptr = (char *)buf;
+	int i;
+	int len = 0;
+
+	ENTER();
+
+	if (!buf || !priv || !pfile ||
+	    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");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#else
+	kernel_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#endif
+	len += ptr - (char *)buf;
+#ifdef SDIO_MULTI_PORT_TX_AGGR
+	if (info.mpa_buf && info.mpa_buf_size) {
+		ptr = (char *)buf;
+		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");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+		vfs_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#else
+		kernel_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#endif
+		len += ptr - (char *)buf;
+	}
+#endif
+	for (i = 0; i < info.mlan_priv_num; i++) {
+		ptr = (char *)buf;
+		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);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+		vfs_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#else
+		kernel_write(pfile, buf, ptr - (char *)buf, &pfile->f_pos);
+#endif
+		len += ptr - (char *)buf;
+	}
+
+	LEAVE();
+	return len;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+/**
+ *  @brief This function create dump directory
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param dir_buf   A pointer to dir_buf buffer
+ *  @param buf_size  Size of dir_buf buffer
+ *
+ *  @return         N/A
+ */
+void
+woal_create_dump_dir(moal_handle *phandle, char *dir_buf, int buf_size)
+{
+	struct dentry *dentry;
+	struct path path;
+	t_u32 sec, usec;
+	int ret;
+
+	ENTER();
+
+	if (!phandle || !dir_buf) {
+		PRINTM(MERROR, "Can't create directory\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	moal_get_system_time(phandle, &sec, &usec);
+	memset(dir_buf, 0, buf_size);
+	sprintf(dir_buf, "%s%u", "/data/dump_", sec);
+
+	dentry = kern_path_create(AT_FDCWD, dir_buf, &path, 1);
+	if (IS_ERR(dentry)) {
+		PRINTM(MERROR,
+		       "Create directory %s error, try create dir in /var",
+		       dir_buf);
+		memset(dir_buf, 0, buf_size);
+		sprintf(dir_buf, "%s%u", "/var/dump_", sec);
+		dentry = kern_path_create(AT_FDCWD, dir_buf, &path, 1);
+	}
+	if (IS_ERR(dentry)) {
+		PRINTM(MERROR, "Create directory %s error, use default folder",
+		       dir_buf);
+		goto default_dir;
+	}
+	ret = vfs_mkdir(path.dentry->d_inode, dentry, 0777);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+	mutex_unlock(&path.dentry->d_inode->i_mutex);
+#else
+	inode_unlock(path.dentry->d_inode);
+#endif
+
+	if (ret < 0) {
+		PRINTM(MERROR,
+		       "Create directory failure, use default folder\n");
+		PRINTM(MERROR, "Create directory failure, ret = %d\n", ret);
+		goto default_dir;
+	} else {
+		PRINTM(MERROR, "Create directory %s successfully\n", dir_buf);
+		goto done;
+	}
+
+default_dir:
+	memset(dir_buf, 0, buf_size);
+	sprintf(dir_buf, "%s", "/data");
+done:
+	LEAVE();
+}
+#endif
+
+/**
+ *  @brief This function save dump buf to file
+ *
+ *  @param dir_name  A pointer to directory name
+ *  @param file_name A pointer to file name
+ *  @param buf       A pointer to dump data
+ *  @param buf_len   The length of dump buf
+ *
+ *  @return         SUCCESS OR FAILURE
+ */
+mlan_status
+woal_save_dump_info_to_file(char *dir_name, char *file_name, t_u8 *buf,
+			    t_u32 buf_len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	struct file *pfile = NULL;
+	t_u8 name[64];
+	loff_t pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	if (!dir_name || !file_name || !buf) {
+		PRINTM(MERROR, "Can't save dump info to file\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(name, 0, sizeof(name));
+	sprintf(name, "%s/%s", dir_name, file_name);
+	pfile = filp_open(name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR,
+		       "Create file %s error, try to save dump file in /var\n",
+		       name);
+		memset(name, 0, sizeof(name));
+		sprintf(name, "%s/%s", "/var", file_name);
+		pfile = filp_open(name, O_CREAT | O_RDWR, 0644);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR, "Create Dump file for %s error\n", name);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MERROR, "Dump data %s saved in %s\n", file_name, name);
+
+	pos = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	vfs_write(pfile, buf, buf_len, &pos);
+	set_fs(fs);
+#else
+	kernel_write(pfile, buf, buf_len, &pos);
+#endif
+	filp_close(pfile, NULL);
+
+	PRINTM(MERROR, "Dump data %s saved in %s successfully\n", file_name,
+	       name);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function dump drv info to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param dir_name   A pointer to directory name
+ *
+ *  @return         N/A
+ */
+void
+woal_dump_drv_info(moal_handle *phandle, t_u8 *dir_name)
+{
+	int ret = 0;
+	struct file *pfile = NULL;
+	t_u8 *drv_buf;
+	t_u8 file_name[64];
+	t_u32 len = 0;
+	t_u32 total_len = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	mm_segment_t fs;
+#endif
+
+	ENTER();
+
+	PRINTM(MERROR, "=== START DRIVER INFO DUMP===");
+	ret = moal_vmalloc(phandle, DRV_INFO_SIZE + 1, &drv_buf);
+	if ((ret != MLAN_STATUS_SUCCESS) || !drv_buf) {
+		PRINTM(MERROR, "Error: vmalloc drv buffer failed!\n");
+		goto done;
+	}
+	memset(file_name, 0, sizeof(file_name));
+	sprintf(file_name, "%s/%s", dir_name, "file_drv_info");
+	pfile = filp_open(file_name, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR,
+		       "Create file %s error, try create /var/file_drv_info",
+		       file_name);
+		pfile = filp_open("/var/file_drv_info", O_CREAT | O_RDWR, 0644);
+	} else {
+		PRINTM(MERROR, "DRV dump data in %s\n", file_name);
+	}
+	if (IS_ERR(pfile)) {
+		PRINTM(MERROR, "Create file_drv_info file failed\n");
+		goto done;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+#endif
+
+	len = woal_dump_moal_drv_info(phandle, drv_buf);
+	total_len += len;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile, drv_buf, len, &pfile->f_pos);
+#else
+	kernel_write(pfile, drv_buf, len, &pfile->f_pos);
+#endif
+
+	len = woal_dump_mlan_drv_info(woal_get_priv(phandle, MLAN_BSS_ROLE_ANY),
+				      drv_buf);
+	total_len += len;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile, drv_buf, len, &pfile->f_pos);
+#else
+	kernel_write(pfile, drv_buf, len, &pfile->f_pos);
+#endif
+
+	len = woal_dump_moal_hex(phandle, drv_buf);
+	total_len += len;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	vfs_write(pfile, drv_buf, len, &pfile->f_pos);
+#else
+	kernel_write(pfile, drv_buf, len, &pfile->f_pos);
+#endif
+
+	len = woal_dump_mlan_hex(woal_get_priv(phandle, MLAN_BSS_ROLE_ANY),
+				 drv_buf, pfile);
+	total_len += len;
+
+	PRINTM(MERROR, "Drv info total bytes = %ld (0x%lx)\n",
+	       (long int)total_len, (long unsigned int)total_len);
+
+	filp_close(pfile, NULL);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+	set_fs(fs);
+#endif
+	PRINTM(MERROR, "=== DRIVER INFO DUMP END===");
+done:
+	if (drv_buf)
+		moal_vfree(phandle, drv_buf);
+	LEAVE();
+}
+
+#define DEBUG_HOST_READY		0xCC
+#define DEBUG_FW_DONE			0xFF
+#define DEBUG_MEMDUMP_FINISH            0xFE
+#define MAX_POLL_TRIES			100
+
+#define DEBUG_DUMP_CTRL_REG               0xF9
+#define DEBUG_DUMP_START_REG              0xF1
+#define DEBUG_DUMP_END_REG                0xF8
+
+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
+#define MAX_FULL_NAME_LEN               32
+t_u8 *name_prefix = "/data/file_";
+
+typedef struct {
+	t_u8 mem_name[MAX_NAME_LEN];
+	t_u8 *mem_Ptr;
+	struct file *pfile_mem;
+	t_u8 done_flag;
+} memory_type_mapping;
+
+memory_type_mapping mem_type_mapping_tbl = { "DUMP", NULL, NULL, 0xDD };
+
+typedef enum {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+} rdwr_status;
+
+/**
+ *  @brief This function read/write firmware via cmd52
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param doneflag  A flag
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+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 = 0;
+	t_u8 debug_host_ready = 0;
+
+	dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG;
+	debug_host_ready = DEBUG_HOST_READY;
+	sdio_writeb(((struct sdio_mmc_card *)phandle->card)->func,
+		    debug_host_ready, dbg_dump_ctrl_reg, &ret);
+	if (ret) {
+		PRINTM(MERROR, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+		ctrl_data =
+			sdio_readb(((struct sdio_mmc_card *)phandle->card)->
+				   func, dbg_dump_ctrl_reg, &ret);
+		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");
+			sdio_writeb(((struct sdio_mmc_card *)phandle->card)->
+				    func, debug_host_ready, dbg_dump_ctrl_reg,
+				    &ret);
+			if (ret) {
+				PRINTM(MERROR, "SDIO Write ERR\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		udelay(100);
+	}
+	if (ctrl_data == debug_host_ready) {
+		PRINTM(MERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+
+	return RDWR_STATUS_SUCCESS;
+}
+
+/**
+ *  @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 path_name[64], file_name[32], firmware_dump_file[128];
+	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;
+	memory_type_mapping *pmem_type_mapping_tbl = &mem_type_mapping_tbl;
+
+	if (!phandle) {
+		PRINTM(MERROR, "Could not dump firmwware info\n");
+		return;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+    /** Create dump directort*/
+	woal_create_dump_dir(phandle, path_name, sizeof(path_name));
+#else
+	memset(path_name, 0, sizeof(path_name));
+	strcpy(path_name, "/data");
+#endif
+	PRINTM(MERROR, "Directory name is %s\n", path_name);
+
+	woal_dump_drv_info(phandle, path_name);
+
+	dbg_dump_start_reg = DEBUG_DUMP_START_REG;
+	dbg_dump_end_reg = DEBUG_DUMP_END_REG;
+	dbg_dump_ctrl_reg = DEBUG_DUMP_CTRL_REG;
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+	phandle->fw_dump = MTRUE;
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+	/* 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++) {
+			start_flag =
+				sdio_readb(((struct sdio_mmc_card *)phandle->
+					    card)->func, reg, &ret);
+			if (ret) {
+				PRINTM(MMSG, "SDIO READ ERR\n");
+				goto done;
+			}
+	     /** 0 means dump starting*/
+			if (start_flag == 0)
+				break;
+			if (tries == MAX_POLL_TRIES) {
+				PRINTM(MMSG, "FW not ready to dump\n");
+				goto done;
+			}
+			udelay(100);
+		}
+	}
+
+	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++) {
+			*dbg_ptr =
+				sdio_readb(((struct sdio_mmc_card *)phandle->
+					    card)->func, reg, &ret);
+			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(phandle, temp_Ptr,
+					    pmem_type_mapping_tbl->mem_Ptr,
+					    memory_size);
+				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) {
+			PRINTM(MMSG, "%s done:"
+#ifdef MLAN_64BIT
+			       "size = 0x%lx\n",
+#else
+			       "size = 0x%x\n",
+#endif
+			       pmem_type_mapping_tbl->mem_name,
+			       dbg_ptr - pmem_type_mapping_tbl->mem_Ptr);
+
+			memset(file_name, 0, sizeof(file_name));
+			sprintf(file_name, "%s%s", "file_sdio_",
+				pmem_type_mapping_tbl->mem_name);
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_save_dump_info_to_file(path_name, file_name,
+							pmem_type_mapping_tbl->
+							mem_Ptr,
+							dbg_ptr -
+							pmem_type_mapping_tbl->
+							mem_Ptr))
+				PRINTM(MERROR,
+				       "Can't save dump file %s in %s\n",
+				       file_name, path_name);
+			moal_vfree(phandle, 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 */
+	memset(firmware_dump_file, 0, sizeof(firmware_dump_file));
+	sprintf(firmware_dump_file, "%s/%s", path_name, file_name);
+	memcpy(phandle->firmware_dump_file, firmware_dump_file,
+	       sizeof(firmware_dump_file));
+done:
+	phandle->fw_dump = MFALSE;
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+	if (pmem_type_mapping_tbl->mem_Ptr) {
+		moal_vfree(phandle, pmem_type_mapping_tbl->mem_Ptr);
+		pmem_type_mapping_tbl->mem_Ptr = NULL;
+	}
+	PRINTM(MERROR, "==== 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
+ */
+void
+woal_sdio_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 = SDIO_SCRATCH_REG;
+	unsigned int reg_table[] = { 0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62,
+		0x64, 0x65, 0x66, 0x68, 0x69, 0x6a
+	};
+	char buf[256], *ptr;
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter);
+
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+	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 = 0x10;
+			reg_end = 0x17;
+		} else if (loop == 2) {
+			/* Read specific registers of SDIO function1 */
+			index = 0;
+			func = 1;
+			reg_start = reg_table[index++];
+			reg_end = reg_table[ARRAY_SIZE(reg_table) - 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)
+				data = sdio_f0_readb(((struct sdio_mmc_card *)
+						      phandle->card)->func, reg,
+						     &ret);
+			else
+				data = sdio_readb(((struct sdio_mmc_card *)
+						   phandle->card)->func, reg,
+						  &ret);
+			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);
+	}
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+}
+
+/**
+ *  @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;
+	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;
+	}
+
+	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));
+#if defined(SDIO_SUSPEND_RESUME)
+	PRINTM(MERROR, "hs_skip_count = %u\n", phandle->hs_skip_count);
+	PRINTM(MERROR, "hs_force_count = %u\n", phandle->hs_force_count);
+#endif
+
+	if (priv) {
+		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 < (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)
+			PRINTM(MERROR, "%s: num_tx_timeout = %d\n",
+			       priv->netdev->name, priv->num_tx_timeout);
+	}
+
+#if defined(SDIO_SUSPEND_RESUME)
+	if (phandle->is_suspended == MTRUE) {
+		LEAVE();
+		return;
+	}
+#endif
+
+	/* Display SDIO registers */
+	if (flag &&
+	    ((phandle->main_state == MOAL_END_MAIN_PROCESS) ||
+	     (phandle->main_state == MOAL_STATE_IDLE))) {
+		woal_sdio_reg_dbg(phandle);
+	} else {
+		phandle->sdio_reg_dbg = MTRUE;
+		queue_work(phandle->workqueue, &phandle->main_work);
+	}
+
+	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[] = "txpower_XX.bin";
+	char file_path[256];
+	char *last_slash = 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;
+
+	/* Replace XX with ISO 3166-1 alpha-2 country code */
+	strncpy(strstr(country_name, "XX"), country, strlen(country));
+
+	memset(file_path, 0, sizeof(file_path));
+	/* file_path should be Null terminated */
+	if (fw_name && (strlen(fw_name) < sizeof(file_path))) {
+		strncpy(file_path, fw_name,
+			MIN((sizeof(file_path) - 1), strlen(fw_name)));
+		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 {
+		strncpy(file_path, "mrvl/", sizeof(file_path));
+	}
+	strncpy(file_path + strlen(file_path), country_name,
+		strlen(country_name));
+	country_txpwrlimit = file_path;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_user_init_data(handle, COUNTRY_POWER_TABLE,
+				    MOAL_IOCTL_WAIT)) {
+		PRINTM(MFATAL, "Download power table to firmware failed\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	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
+ */
+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 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)
+	moal_private *priv;
+#endif
+#endif
+	ENTER();
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return;
+	}
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	if (handle->rx_bgscan_stop) {
+		handle->rx_bgscan_stop = MFALSE;
+		priv = handle->bg_scan_priv;
+		handle->bg_scan_priv = NULL;
+		if (priv && priv->sched_scanning) {
+			cfg80211_sched_scan_stopped(priv->wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+						    , priv->bg_scan_reqid
+#endif
+				);
+			PRINTM(MEVENT, "Report sched_Scan stopped\n");
+			priv->sched_scanning = MFALSE;
+		}
+	}
+#endif
+#endif
+	mlan_rx_process(handle->pmlan_adapter, NULL);
+	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);
+#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->sdio_reg_dbg == MTRUE) {
+		handle->sdio_reg_dbg = MFALSE;
+		woal_sdio_reg_dbg(handle);
+#if defined(DEBUG_LEVEL1)
+		if (drvdbg & MFW_D) {
+			drvdbg &= ~MFW_D;
+			woal_dump_firmware_info_v3(handle);
+		}
+#endif
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	/* Change the priority and scheduling policy of main work queue */
+	if ((wq_sched_prio != current->rt_priority) ||
+	    (wq_sched_policy != current->policy)) {
+		PRINTM(MMSG,
+		       "Set work queue priority %d and scheduling policy %d\n",
+		       wq_sched_prio, wq_sched_policy);
+		sched_setscheduler(current, wq_sched_policy, &sp);
+	}
+#endif
+
+	handle->main_state = MOAL_ENTER_WORK_QUEUE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#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;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+
+	LEAVE();
+}
+
+/**
+ * @brief Handles interrupt
+ *
+ */
+/**
+ * @param handle  A pointer to moal_handle struct
+ *
+ * @return        MLAN_STATUS_FAILURE-- when the interrupt is not for us.
+ */
+mlan_status
+woal_interrupt(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	handle->main_state = MOAL_RECV_INT;
+	PRINTM(MINTR, "*\n");
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* call mlan_interrupt to read int status */
+	mlan_interrupt(handle->pmlan_adapter);
+#ifdef SDIO_SUSPEND_RESUME
+	if (handle->is_suspended) {
+		PRINTM(MINTR, "Receive interrupt in hs_suspended\n");
+		LEAVE();
+		return ret;
+	}
+#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();
+	return ret;
+}
+
+/**
+ * @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
+ *
+ *  @return        A pointer to moal_handle structure
+ */
+moal_handle *
+woal_add_card(void *card)
+{
+	moal_handle *handle = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int netlink_num = NETLINK_MARVELL;
+	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;
+
+	/* 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 */
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
+		if (m_handle[index] == NULL)
+			break;
+	}
+	if (index < MAX_MLAN_ADAPTER) {
+		m_handle[index] = handle;
+		handle->handle_idx = index;
+	} else {
+		PRINTM(MERROR, "Exceeded maximum cards supported!\n");
+		goto err_kmalloc;
+	}
+
+	if (mac_addr
+#ifdef MFG_CMD_SUPPORT
+	    && mfg_mode != MLAN_INIT_PARA_ENABLED
+#endif
+		) {
+		t_u8 temp[20];
+		t_u8 len = strlen(mac_addr) + 1;
+		if (len < sizeof(temp)) {
+			memcpy(temp, mac_addr, len);
+			handle->set_mac_addr = 1;
+			/* note: the following function overwrites the temp buffer */
+			woal_mac2u8(handle->mac_addr, temp);
+		}
+	}
+
+	handle->histogram_table_num = 3;
+
+	((struct sdio_mmc_card *)card)->handle = handle;
+#ifdef SPI_SUPPORT
+	((struct woal_spi_card *)card)->handle = handle;
+#endif
+
+#ifdef STA_SUPPORT
+	handle->scan_pending_on_block = MFALSE;
+	MOAL_INIT_SEMAPHORE(&handle->async_sem);
+#endif
+
+	/* 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);
+
+	if (!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 (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);
+	}
+
+#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 (woal_register_dev(handle) != MLAN_STATUS_SUCCESS) {
+		PRINTM(MFATAL, "Failed to register wlan device!\n");
+		goto err_registerdev;
+	}
+#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;
+	}
+
+	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");
+	woal_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 (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;
+	((struct sdio_mmc_card *)card)->handle = 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;
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode == MLAN_INIT_PARA_ENABLED)
+		fw_name = NULL;
+#endif
+	/* 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;
+	handle->surprise_removed = MTRUE;
+
+	flush_workqueue(handle->workqueue);
+	if (handle->rx_workqueue)
+		flush_workqueue(handle->rx_workqueue);
+
+	if (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) {
+			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");
+	}
+	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));
+	}
+#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
+#if defined(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
+	/* 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 */
+#ifdef CONFIG_PROC_FS
+	woal_proc_exit(handle);
+#endif
+	/* Unregister device */
+	PRINTM(MINFO, "unregister device\n");
+	woal_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;
+	}
+
+	/* 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");
+	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));
+	}
+
+	/* Remove interface */
+	for (i = 0; i < MIN(MLAN_MAX_BSS_NUM, 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));
+		}
+		handle->pmlan_adapter = NULL;
+	}
+
+	handle->priv_num = 0;
+	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
+
+#define FW_POLL_TRIES 100
+#define FW_RESET_REG  0x0EE
+#define FW_RESET_VAL  0x99
+
+/**
+ *  @brief This function reload fw
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return        0--success, otherwise failure
+ */
+static int
+woal_reset_and_reload_fw(moal_handle *handle)
+{
+	int ret = 0, tries = 0;
+	t_u32 value = 1;
+	t_u32 reset_reg = FW_RESET_REG;
+	t_u8 reset_val = FW_RESET_VAL;
+
+	ENTER();
+	mlan_pm_wakeup_card(handle->pmlan_adapter);
+
+    /** wait SOC fully wake up */
+	for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+		ret = woal_write_reg(handle, reset_reg, 0xba);
+		if (ret == MLAN_STATUS_SUCCESS) {
+			woal_read_reg(handle, reset_reg, &value);
+			if (value == 0xba) {
+				PRINTM(MMSG, "FW wake up\n");
+				break;
+			}
+		}
+		udelay(1000);
+	}
+	/* Write register to notify FW */
+	if (woal_write_reg(handle, reset_reg, reset_val) != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to write register.\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	/* Poll register around 100 ms */
+	for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+		woal_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;
+	}
+	/* 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 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 reload fw
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param mode     FW reload mode
+ *
+ *  @return        0--success, otherwise failure
+ */
+void
+woal_request_fw_reload(moal_handle *handle, t_u8 mode)
+{
+	int intf_num;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+#if defined(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 && V14_FEATURE */
+
+	ENTER();
+
+    /** start block IOCTL */
+	handle->driver_state = MTRUE;
+	if (mode == FW_RELOAD_WITH_EMULATION) {
+		fw_reload = FW_RELOAD_WITH_EMULATION;
+		PRINTM(MMSG, "FW reload with re-emulation...\n");
+		LEAVE();
+		return;
+	}
+
+    /** detach network interface */
+	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);
+	}
+	handle->fw_reload = MTRUE;
+	woal_update_firmware_name(handle);
+	if (mode == FW_RELOAD_NO_EMULATION) {
+		ret = woal_reload_fw(handle);
+	} else if (mode == FW_RELOAD_SDIO_INBAND_RESET)
+		ret = woal_reset_and_reload_fw(handle);
+	else
+		ret = -EFAULT;
+	if (ret) {
+		PRINTM(MERROR, "FW reload fail\n");
+		goto done;
+	}
+    /** un-block IOCTL */
+	handle->fw_reload = MFALSE;
+	handle->driver_state = 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)) {
+			ret = -EFAULT;
+			kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+	handle->hardware_status = HardwareStatusReady;
+	/* Reset all interfaces */
+	ret = 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++) {
+		woal_init_priv(handle->priv[intf_num], MOAL_IOCTL_WAIT);
+#if defined(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 && V14_FEATURE */
+	}
+
+	/* 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;
+}
+
+/**
+ *  @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);
+
+#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);
+
+	/* Register with bus */
+	ret = woal_bus_register();
+	if (ret == MLAN_STATUS_SUCCESS)
+		PRINTM(MMSG, "wlan: Driver loaded successfully\n");
+	else
+		PRINTM(MMSG, "wlan: Driver loading failed\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 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 */
+
+		/* Unregister all connected radiotap net devices */
+		if (handle->mon_if) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			woal_set_net_monitor(handle->mon_if->priv,
+					     MOAL_IOCTL_WAIT, MFALSE, 0, NULL);
+			if (handle->ioctl_timeout) {
+				woal_ioctl_timeout(handle);
+				goto exit;
+			}
+#endif
+			netif_device_detach(handle->mon_if->mon_ndev);
+			if (handle->mon_if->mon_ndev->reg_state ==
+			    NETREG_REGISTERED)
+				unregister_netdev(handle->mon_if->mon_ndev);
+			handle->mon_if = NULL;
+		}
+
+		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
+				spin_lock_irqsave(&handle->scan_req_lock,
+						  flags);
+				if (IS_STA_CFG80211(cfg80211_wext) &&
+				    handle->scan_request) {
+					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(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 (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 (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 (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;
+	}
+
+	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(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(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(fw_region, int, 0);
+MODULE_PARM_DESC(fw_region, "1: create channel regulatory domain from 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);
+#if defined(WIFI_DIRECT_SUPPORT)
+MODULE_PARM_DESC(drv_mode,
+		 "Bit 0: STA; Bit 1: uAP; Bit 2: WIFIDIRECT; Bit 4: NAN");
+#else
+MODULE_PARM_DESC(drv_mode, "Bit 0: STA; Bit 1: uAP; Bit 4: NAN");
+#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */
+#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 */
+#if defined(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 && V14_FEATURE */
+module_param(nan_name, charp, 0);
+MODULE_PARM_DESC(nan_name, "NAN interface name");
+module_param(max_nan_bss, int, 0);
+MODULE_PARM_DESC(max_nan_bss, "Number of NAN interfaces (1)");
+#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(ps_mode, int, 0660);
+MODULE_PARM_DESC(ps_mode,
+		 "0: MLAN default; 1: Enable IEEE PS mode; 2: Disable IEEE PS mode");
+module_param(max_tx_buf, int, 0);
+MODULE_PARM_DESC(max_tx_buf, "Maximum Tx buffer size (2048/4096/8192)");
+
+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");
+
+#ifdef SDIO_SUSPEND_RESUME
+module_param(pm_keep_power, int, 0);
+MODULE_PARM_DESC(pm_keep_power, "1: PM keep power; 0: PM no power");
+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
+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,
+		 "Allow setting tx power table of country; 0: disable (default), 1: enable.");
+module_param(init_hostcmd_cfg, charp, 0);
+MODULE_PARM_DESC(init_hostcmd_cfg, "Init hostcmd file name");
+module_param(cfg80211_wext, int, 0660);
+MODULE_PARM_DESC(cfg80211_wext,
+#ifdef STA_WEXT
+		 "Bit 0: STA WEXT; "
+#endif
+#ifdef UAP_WEXT
+		 "Bit 1: UAP WEXT; "
+#endif
+#ifdef STA_CFG80211
+		 "Bit 2: STA CFG80211; "
+#endif
+#ifdef UAP_CFG80211
+		 "Bit 3: UAP CFG80211;"
+#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");
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+module_param(p2p_enh, int, 0);
+MODULE_PARM_DESC(p2p_enh, "1: Enable enhanced P2P; 0: Disable enhanced P2P");
+#endif
+#endif
+#endif
+
+#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(sdio_rx_aggr, int, 0);
+MODULE_PARM_DESC(sdio_rx_aggr,
+		 "1: Enable SDIO rx aggr; 0: Disable SDIO rx aggr");
+
+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]");
+
+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(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
+
+module_param(drcs_chantime_mode, int, 0);
+MODULE_PARM_DESC(drcs_chantime_mode,
+		 "0: use default value;Bit31~Bit24:Channel time for channel index0;Bit23~Bit16:mode for channel index0;Bit15~Bit8:Channel time for channel index1;Bit7~Bit0:mode for channel index1; mode:0--PM1,1--Null2Self.");
+
+module_param(roamoffload_in_hs, int, 0);
+MODULE_PARM_DESC(roamoffload_in_hs,
+		 "1: enable fw roaming only when host suspend; 0: always enable fw roaming.");
+
+MODULE_DESCRIPTION("M-WLAN Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_VERSION(MLAN_RELEASE_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/wlan_sd8997/mlinux/moal_main.h b/wlan_sd8997/mlinux/moal_main.h
new file mode 100644
index 0000000..7cc922c
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_main.h
@@ -0,0 +1,2856 @@
+/** @file moal_main.h
+  *
+  * @brief This file contains wlan driver specific defines etc.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+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
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include       <linux/config.h>
+#endif
+
+/* 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 <net/ieee80211_radiotap.h>
+
+#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
+
+#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"
+
+#ifdef OPENWRT
+#ifdef mwiphy_name
+#undef mwiphy_name
+#define mwiphy_name          "phy%d"
+#endif
+#ifdef default_mlan_name
+#undef default_mlan_name
+#define default_mlan_name "wlan%d"
+#endif
+#endif
+
+/**
+ * define write_can_lock() to fix compile issue on ACTIA platform
+ */
+#if !defined(write_can_lock) && defined(CONFIG_PREEMPT_RT_FULL)
+#define write_can_lock(X) 1
+#endif
+
+#define MLAN_ACTION_FRAME_CATEGORY_OFFSET (40)
+#define MLAN_ACTION_FRAME_ACTION_OFFSET (41)
+
+/** Define BOOLEAN */
+typedef t_u8 BOOLEAN;
+
+/** Driver version */
+extern char driver_version[];
+
+/** Private structure for MOAL */
+typedef struct _moal_private moal_private;
+/** Handle data structure for MOAL  */
+typedef struct _moal_handle moal_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 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;
+
+/** Moal WNM timing measurement structure */
+typedef struct {
+    /** dialog token */
+	t_u8 dialog_token;
+    /** follow up dialogue token */
+	t_u8 follow_up_dialog_token;
+    /** Time 1 */
+	t_u32 t1;
+    /** Time 4 */
+	t_u32 t4;
+    /** Time 1 error */
+	t_u8 t1_err;
+    /** time 4 error */
+	t_u8 t4_err;
+} __attribute__ ((packed)) moal_wnm_tm_msmt;
+
+/** wlan_802_11_header */
+typedef struct {
+    /** 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;
+} __attribute__ ((packed)) moal_wlan_802_11_header;
+
+/** moal timestamps structure */
+typedef struct {
+	/** t2 time */
+	t_u32 t2;
+	/** t2 error */
+	t_u8 t2_err;
+	/** t3 time */
+	t_u32 t3;
+	/** t3 error */
+	t_u8 t3_err;
+	/** ingress time */
+	t_u64 ingress_time;
+} __attribute__ ((packed)) moal_timestamps;
+
+/** moal P2P context structure */
+typedef struct {
+	t_u8 vendor_specific;
+	t_u8 length;
+	t_u8 data[0];
+} __attribute__ ((packed)) moal_ptp_context;
+
+/**
+ *  @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);
+}
+
+#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;
+	memcpy(dst, 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(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 */
+#define NUM_TX_TIMEOUT_THRESHOLD      5
+
+/** Custom event : DRIVER HANG */
+#define CUS_EVT_DRIVER_HANG	            "EVENT=DRIVER_HANG"
+
+/** 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_GET_CORRELATED_TIME     "EVENT=CORRELATED-TIME"
+#define CUS_EVT_TIMING_MSMT_CONFIRM     "EVENT=TIMING-MSMT-CONFIRM"
+#define CUS_EVT_TM_FRAME_INDICATION     "EVENT=TIMING-MSMT-FRAME"
+
+/** 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"
+
+#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
+
+/** 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
+
+/** 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_MARVELL     (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 HIGH_RX_PENDING         100
+/** low rx pending packets */
+#define LOW_RX_PENDING          80
+
+/** MAX Tx Pending count */
+#define MAX_TX_PENDING      100
+
+/** LOW Tx Pending count */
+#define LOW_TX_PENDING      80
+
+/** 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
+
+/** 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        2
+/** Default uAP BSS */
+#define DEF_UAP_BSS        1
+#endif
+#if defined(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 && V14_FEATURE */
+/** Driver mode NAN bit */
+#define DRV_MODE_NAN              MBIT(4)
+/** Maximum NAN BSS */
+#define MAX_NAN_BSS               1
+/** Default NAN BSS */
+#define DEF_NAN_BSS               1
+
+#define DRV_MODE_WLAN            (MBIT(0)|MBIT(1)|MBIT(2)|MBIT(3)|MBIT(4))
+
+/**
+ * the maximum number of adapter supported
+ **/
+#define MAX_MLAN_ADAPTER    2
+
+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;
+
+#ifdef PROC_DEBUG
+/** Debug data */
+struct debug_data {
+    /** Name */
+	char name[32];
+    /** Size */
+	t_u32 size;
+    /** Address */
+	t_ptr addr;
+};
+
+/** 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;
+};
+#endif
+
+/** Maximum IP address buffer length */
+#define IPADDR_MAX_BUF          20
+/** IP address operation: Remove */
+#define IPADDR_OP_REMOVE        0
+
+#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;
+};
+
+/** TX status info structure */
+struct tx_status_info {
+	struct list_head link;
+    /** cookie */
+	t_u64 tx_cookie;
+    /** seq_num */
+	t_u8 tx_seq_num;
+	/**          skb */
+	void *tx_skb;
+};
+
+/** timesync packet info structure */
+
+#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;
+/** dot11 tx control 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;
+
+/** dot11 rx control protocol */
+typedef struct {
+   /** Data rate of received packet*/
+	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;
+
+/** 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;
+};
+
+/** Number of samples in histogram (/proc/mwlan/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[0];
+} hgm_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;
+	/** 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;
+#ifdef UAP_SUPPORT
+	/** uAP started or not */
+	BOOLEAN bss_started;
+    /** host based uap flag */
+	BOOLEAN uap_host_based;
+	/** uAP skip CAC*/
+	BOOLEAN skip_cac;
+	/** tx block flag */
+	BOOLEAN uap_tx_blocked;
+#if defined(DFS_TESTING_SUPPORT)
+    /** user cac period */
+	t_u32 user_cac_period_msec;
+    /** channel under nop */
+	BOOLEAN chan_under_nop;
+#endif
+#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
+#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;
+    /** bgscan request id */
+	t_u64 bg_scan_reqid;
+#ifdef STA_CFG80211
+    /** roaming enabled flag */
+	t_u8 roaming_enabled;
+	/** 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];
+	/** key data */
+	t_u8 conn_wep_key[MAX_WEP_KEY_SIZE];
+    /** connection param */
+	struct cfg80211_connect_params sme_current;
+    /** roaming required flag */
+	t_u8 roaming_required;
+#endif
+#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
+	/** pmk saved flag */
+	t_u8 pmk_saved;
+	/** pmk */
+	mlan_pmk_t pmk;
+	/** 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;
+	/** Keep connect */
+	bool keep_connect;
+    /** 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;
+    /**mobility domain value*/
+	t_u16 ft_md;
+    /**ft capability*/
+	t_u8 ft_cap;
+    /**set true during ft connection*/
+	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 */
+#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];
+#ifdef PROC_DEBUG
+    /** MLAN debug info */
+	struct debug_data_priv items_priv;
+#endif
+
+    /** tcp session queue */
+	struct list_head tcp_sess_queue;
+    /** TCP Ack enhance flag */
+	t_u8 enable_tcp_ack_enh;
+    /** 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 LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	atomic_t wmm_tx_pending[4];
+#endif
+    /** 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 */
+	hgm_data *hist_data[3];
+	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;
+	void *rings[RING_ID_MAX];
+	t_u8 pkt_fate_monitor_enable;
+	void *packet_filter;
+	void *nan_cb;
+};
+
+/** channel_field.flags */
+#define CHANNEL_FLAGS_TURBO 0x0010
+#define CHANNEL_FLAGS_CCK   0x0020
+#define CHANNEL_FLAGS_OFDM  0x0040
+#define CHANNEL_FLAGS_2GHZ  0x0080
+#define CHANNEL_FLAGS_5GHZ  0x0100
+#define CHANNEL_FLAGS_ONLY_PASSIVSCAN_ALLOW  0x0200
+#define CHANNEL_FLAGS_DYNAMIC_CCK_OFDM  0x0400
+#define CHANNEL_FLAGS_GFSK  0x0800
+struct channel_field {
+	/** frequency */
+	t_u16 frequency;
+	/** flags */
+	t_u16 flags;
+} __packed;
+
+/** mcs_field.known */
+#define MCS_KNOWN_BANDWIDTH   0x01
+#define MCS_KNOWN_MCS_INDEX_KNOWN  0x02
+#define MCS_KNOWN_GUARD_INTERVAL   0x04
+#define MCS_KNOWN_HT_FORMAT   0x08
+#define MCS_KNOWN_FEC_TYPE    0x10
+#define MCS_KNOWN_STBC_KNOWN  0x20
+#define MCS_KNOWN_NESS_KNOWN  0x40
+#define MCS_KNOWN_NESS_DATA   0x80
+/** bandwidth */
+#define RX_BW_20   0
+#define RX_BW_40   1
+#define RX_BW_20L  2
+#define RX_BW_20U  3
+#define RX_BW_80   4
+/** mcs_field.flags
+The flags field is any combination of the following:
+0x03    bandwidth - 0: 20, 1: 40, 2: 20L, 3: 20U
+0x04    guard interval - 0: long GI, 1: short GI
+0x08    HT format - 0: mixed, 1: greenfield
+0x10    FEC type - 0: BCC, 1: LDPC
+0x60    Number of STBC streams
+0x80    Ness - bit 0 (LSB) of Number of extension spatial streams */
+struct mcs_field {
+	/** known */
+	t_u8 known;
+	/** flags */
+	t_u8 flags;
+	/** mcs */
+	t_u8 mcs;
+} __packed;
+
+/** vht_field.known */
+#define VHT_KNOWN_STBC                  0x0001
+#define VHT_KNOWN_TXOP_PS_NA     0x0002
+#define VHT_KNOWN_GI                       0x0004
+#define VHT_KNOWN_SGI_NSYM_DIS  0x0008
+#define VHT_KNOWN_LDPC_EXTRA_OFDM_SYM  0x0010
+#define VHT_KNOWN_BEAMFORMED    0x0020
+#define VHT_KNOWN_BANDWIDTH       0x0040
+#define VHT_KNOWN_GROUP_ID           0x0080
+#define VHT_KNOWN_PARTIAL_AID       0x0100
+
+/** vht_field.flags */
+#define VHT_FLAG_STBC                       0x01
+#define VHT_FLAG_TXOP_PS_NA          0x02
+#define VHT_FLAG_SGI                          0x04
+#define VHT_FLAG_SGI_NSYM_M10_9   0x08
+#define VHT_FLAG_LDPC_EXTRA_OFDM_SYM  0x10
+#define VHT_FLAG_BEAMFORMED         0x20
+
+/** vht_field.coding */
+#define VHT_CODING_LDPC_USER0   0x01
+#define VHT_CODING_LDPC_USER1   0x02
+#define VHT_CODING_LDPC_USER2   0x04
+#define VHT_CODING_LDPC_USER3   0x08
+
+/** vht_field */
+struct vht_field {
+	/** pad: for vht field require 2 bytes alignment */
+	t_u8 pad;
+	/** known */
+	t_u16 known;
+	/** flags */
+	t_u8 flags;
+	/** bandwidth */
+	t_u8 bandwidth;
+	/** mcs_nss for up to 4 users */
+	t_u8 mcs_nss[4];
+	/** coding for up to 4 users */
+	t_u8 coding;
+	/** group_id */
+	t_u8 group_id;
+	/** partial_aid */
+	t_u16 partial_aid;
+} __packed;
+
+/** radiotap_body.flags */
+#define RADIOTAP_FLAGS_DURING_CFG  0x01
+#define RADIOTAP_FLAGS_SHORT_PREAMBLE  0x02
+#define RADIOTAP_FLAGS_WEP_ENCRYPTION  0x04
+#define RADIOTAP_FLAGS_WITH_FRAGMENT   0x08
+#define RADIOTAP_FLAGS_INCLUDE_FCS  0x10
+#define RADIOTAP_FLAGS_PAD_BTW_HEADER_PAYLOAD  0x20
+#define RADIOTAP_FLAGS_FAILED_FCS_CHECK  0x40
+#define RADIOTAP_FLAGS_USE_SGI_HT  0x80
+struct radiotap_body {
+	/** timestamp */
+	t_u64 timestamp;
+	/** flags */
+	t_u8 flags;
+	/** rate for LG pkt, RATE flag will be present, it shows datarate in 500Kbps.
+	  * For HT/VHT pkt, RATE flag will not be present, it is not used. */
+	t_u8 rate;
+	/** channel */
+	struct channel_field channel;
+	/** antenna_signal */
+	t_s8 antenna_signal;
+	/** antenna_noise */
+	t_s8 antenna_noise;
+	/** antenna */
+	t_u8 antenna;
+	/** union for HT/VHT pkt */
+	union {
+		/** mcs field */
+		struct mcs_field mcs;
+		/** vht field */
+		struct vht_field vht;
+	} u;
+} __packed;
+
+struct radiotap_header {
+	struct ieee80211_radiotap_header hdr;
+	struct radiotap_body body;
+} __packed;
+
+/** Roam offload config parameters */
+typedef struct woal_priv_fw_roam_offload_cfg {
+	/* User set passphrase */
+	t_u8 userset_passphrase;
+	/* BSSID for fw roaming/auto_reconnect */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/* Retry_count for fw roaming/auto_reconnect */
+	t_u8 retry_count;
+	/* Condition to trigger roaming
+	 * Bit0 : RSSI low trigger
+	 * Bit1 : Pre-beacon lost trigger
+	 * Bit2 : Link Lost trigger
+	 * Bit3 : Deauth by ext-AP trigger
+	 * Bit4 ~ Bit15 : Reserved
+	 * value 0 : no trigger
+	 * value 0xff : invalid
+	 */
+	t_u16 trigger_condition;
+	/* SSID List(White list) */
+	mlan_ds_misc_ssid_list ssid_list;
+	/* Black list(BSSID list) */
+	mlan_ds_misc_roam_offload_aplist black_list;
+
+	/* RSSI paramters set flag */
+	t_u8 rssi_param_set_flag;
+	/* MAX_RSSI for fw roaming */
+	t_u8 max_rssi;
+	/*  MIN_RSSI for fw roaming */
+	t_u8 min_rssi;
+	/*  Step_RSSI for fw roaming */
+	t_u8 step_rssi;
+
+	/* BAND and RSSI_HYSTERESIS set flag */
+	t_u8 band_rssi_flag;
+	mlan_ds_misc_band_rssi band_rssi;
+
+	/* BGSCAN params set flag */
+	t_u8 bgscan_set_flag;
+	mlan_ds_misc_bgscan_cfg bgscan_cfg;
+
+	/* EES mode params set flag */
+	t_u8 ees_param_set_flag;
+	mlan_ds_misc_ees_cfg ees_cfg;
+
+	/* Beacon miss threshold */
+	t_u8 bcn_miss_threshold;
+
+	/* Beacon miss threshold */
+	t_u8 pre_bcn_miss_threshold;
+
+	/* scan repeat count */
+	t_u16 repeat_count;
+} woal_roam_offload_cfg;
+
+int woal_set_clear_pmk(moal_private *priv, t_u8 action);
+mlan_status woal_config_fw_roaming(moal_private *priv, t_u8 cfg_mode,
+				   woal_roam_offload_cfg * roam_offload_cfg);
+int woal_enable_fw_roaming(moal_private *priv, int data);
+
+#define GTK_REKEY_OFFLOAD_DISABLE                    0
+#define GTK_REKEY_OFFLOAD_ENABLE                     1
+#define GTK_REKEY_OFFLOAD_SUSPEND                    2
+
+/** Monitor Band Channel Config */
+typedef struct _netmon_band_chan_cfg {
+	t_u32 band;
+	t_u32 channel;
+	t_u32 chan_bandwidth;
+} netmon_band_chan_cfg;
+
+typedef struct _monitor_iface {
+	/* The priv data of interface on which the monitor iface is based */
+	moal_private *priv;
+	struct wireless_dev wdev;
+	int radiotap_enabled;
+	/* The net_device on which the monitor iface is based. */
+	struct net_device *base_ndev;
+	struct net_device *mon_ndev;
+	char ifname[IFNAMSIZ];
+	int flag;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	struct cfg80211_chan_def chandef;
+#endif
+	/** Netmon Band Channel Config */
+	netmon_band_chan_cfg band_chan_cfg;
+	/** Monitor device statistics structure */
+	struct net_device_stats stats;
+} monitor_iface;
+
+/** 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;
+
+	/** Monitor interface */
+	monitor_iface *mon_if;
+
+	/** 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_mwlan;
+#endif
+	/** Firmware */
+	const struct firmware *firmware;
+	/** Firmware request start time */
+	struct 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;
+	/** ECSA support */
+	t_u8 fw_ecsa_enable;
+	/** FW ROAMING support */
+	t_u8 fw_roam_enable;
+	/** FW ROAMING capability in fw */
+	t_u8 fw_roaming_support;
+	/** Retry count for auto reconnect based on FW ROAMING*/
+	t_u16 auto_reconnect_retry_count;
+	/** The SSID for auto reconnect FW ROAMING*/
+	mlan_802_11_ssid auto_reconnect_ssid;
+	/** The BSSID for auto reconnect FW ROAMING*/
+	mlan_802_11_mac_addr auto_reconnect_bssid;
+	/** The parameters for FW  ROAMING*/
+	woal_roam_offload_cfg fw_roam_params;
+	/** The keys for FW  ROAMING*/
+	mlan_ds_passphrase ssid_passphrase[MAX_SEC_SSID_NUM];
+
+	/** 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__;
+#if defined(SDIO_SUSPEND_RESUME)
+	/** Device suspend flag */
+	BOOLEAN is_suspended;
+#ifdef SDIO_SUSPEND_RESUME
+	/** suspend notify flag */
+	BOOLEAN suspend_notify_req;
+#endif
+	/** 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;
+#endif
+	/** 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;
+#if defined(SDIO_SUSPEND_RESUME)
+	/** hs skip count */
+	t_u32 hs_skip_count;
+	/** hs force count */
+	t_u32 hs_force_count;
+	/** suspend_fail flag */
+	BOOLEAN suspend_fail;
+#endif
+#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 */
+	/** RTT capability */
+	wifi_rtt_capabilities rtt_capa;
+	/** RTT config */
+	wifi_rtt_config_params_t rtt_params;
+	/** Driver workqueue */
+	struct workqueue_struct *workqueue;
+	/** main work */
+	struct work_struct main_work;
+    /** Driver workqueue */
+	struct workqueue_struct *rx_workqueue;
+	/** main work */
+	struct work_struct rx_work;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	struct wiphy *wiphy;
+	/** Country code for regulatory domain */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+    /** band */
+	enum ieee80211_band band;
+    /** first scan done flag */
+	t_u8 first_scan_done;
+    /** scan channel gap */
+	t_u16 scan_chan_gap;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+    /** recieve bgscan stop */
+	t_u8 rx_bgscan_stop;
+    /** bg scan Private pointer */
+	moal_private *bg_scan_priv;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+    /** remain on channel flag */
+	t_u8 remain_on_channel;
+	/** bss index for remain on channel */
+	t_u8 remain_bss_index;
+	/** 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
+	/** Read SDIO registers for debugging */
+	t_u32 sdio_reg_dbg;
+	/** 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;
+    /** 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
+#ifdef DFS_TESTING_SUPPORT
+    /** cac period length, valid only when dfs testing is enabled */
+	long cac_period_jiffies;
+#endif
+    /** handle index - for multiple card supports */
+	t_u8 handle_idx;
+#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;
+#ifdef STA_CFG80211
+	/** CFG80211 scan request description */
+	struct cfg80211_scan_request *scan_request;
+#endif
+#endif
+	/** main state */
+	t_u8 main_state;
+    /** driver state */
+	t_u8 driver_state;
+    /** ioctl timeout */
+	t_u8 ioctl_timeout;
+    /** FW dump state */
+	t_u8 fw_dump;
+    /** FW dump full name */
+	t_u8 firmware_dump_file[128];
+	/** cmd52 function */
+	t_u8 cmd52_func;
+	/** cmd52 register */
+	t_u8 cmd52_reg;
+	/** cmd52 value */
+	t_u8 cmd52_val;
+#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;
+	/** 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;
+	t_u8 histogram_table_num;
+	struct notifier_block woal_notifier;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	struct ieee80211_regdomain *regd;
+#endif
+#endif
+	struct net_device napi_dev;
+	struct napi_struct napi_rx;
+};
+/**
+ *  @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;
+}
+
+/* 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
+
+/** Host command DS gen structure */
+typedef struct _HostCmd_DS_GEN {
+    /** Command */
+	t_u16 command;
+    /** Size */
+	t_u16 size;
+    /** Sequence number */
+	t_u16 seq_num;
+    /** Result */
+	t_u16 result;
+} HostCmd_DS_GEN;
+
+/** Host command DS 802.11 cfg data structure */
+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
+
+/** 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);
+/**  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 interface module */
+/** Add card */
+moal_handle *woal_add_card(void *card);
+/** 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
+
+/** Interrupt handler */
+mlan_status woal_interrupt(moal_handle *handle);
+
+/** 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);
+/** Get/set net monitor mode configurations */
+int woal_net_monitor_ioctl(moal_private *priv, struct iwreq *wrq);
+/** 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 drvdbg);
+#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);
+/** 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);
+#ifdef CONFIG_PROC_FS
+mlan_status woal_request_soft_reset(moal_handle *handle);
+#endif
+void woal_request_fw_reload(moal_handle *handle, t_u8 mode);
+/** 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 PROC_DEBUG
+/** 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);
+#endif
+/** 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);
+#if defined(SDIO_SUSPEND_RESUME)
+/** Enable Host Sleep configuration */
+int woal_enable_hs(moal_private *priv);
+/** hs active timeout 2 second */
+#define HS_ACTIVE_TIMEOUT  (2 * HZ)
+#endif
+/** Get wakeup reason */
+mlan_status woal_get_wakeup_reason(moal_private *priv,
+				   mlan_ds_hs_wakeup_reason *wakeup_reason);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+void woal_create_dump_dir(moal_handle *phandle, char *dir_buf, int buf_size);
+#endif
+mlan_status woal_save_dump_info_to_file(char *dir_name, char *file_name,
+					t_u8 *buf, t_u32 buf_len);
+void woal_dump_drv_info(moal_handle *phandle, t_u8 *dir_name);
+
+void woal_dump_firmware_info_v3(moal_handle *phandle);
+/* Store the FW dumps received from events in a file */
+void woal_store_firmware_dump(moal_handle *phandle, mlan_event *pmevent);
+
+/** 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);
+/** 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);
+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,
+				moal_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);
+
+#if defined(STA_SUPPORT) || defined(UAP_SUPPORT)
+/** Get statistics information */
+mlan_status woal_get_stats_info(moal_private *priv, t_u8 wait_option,
+				mlan_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
+/** 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,
+					  mlan_ds_remain_chan *pchan);
+void woal_remain_timer_func(void *context);
+
+#if defined(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 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
+
+#ifdef PROC_DEBUG
+/** Create debug proc fs */
+void woal_debug_entry(moal_private *priv);
+/** Remove debug proc fs */
+void woal_debug_remove(moal_private *priv);
+#endif /* PROC_DEBUG */
+
+/** 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 REASSOCIATION
+int woal_reassociation_thread(void *data);
+void woal_reassoc_timer_func(void *context);
+#endif /* REASSOCIATION */
+
+t_void woal_main_work_queue(struct work_struct *work);
+t_void woal_rx_work_queue(struct work_struct *work);
+
+int 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);
+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_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_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);
+void woal_reconfig_bgscan(moal_handle *handle);
+#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
+mlan_status woal_request_bgscan(moal_private *priv, t_u8 wait_option,
+				wlan_bgscan_cfg *scan_cfg);
+#endif
+
+void woal_flush_tcp_sess_queue(moal_private *priv);
+void woal_flush_tdls_list(moal_private *priv);
+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);
+mlan_status woal_mc_policy_cfg(moal_private *priv, t_u16 *enable,
+			       t_u8 wait_option, t_u8 action);
+void woal_check_mc_connection(moal_private *priv, t_u8 wait_option,
+			      t_u8 new_channel);
+#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
+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_u8 rx_rate, t_s8 snr, t_s8 nflr,
+			t_u8 antenna);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+mlan_status woal_set_net_monitor(moal_private *priv, t_u8 wait_option,
+				 t_u8 enable, t_u8 filter,
+				 netmon_band_chan_cfg * band_chan_cfg);
+#endif
+mlan_status woal_delba_all(moal_private *priv, t_u8 wait_option);
+void woal_channel_info_to_bandcfg(moal_private *priv,
+				  wifi_channel_info * ch_info,
+				  Band_Config_t *bandcfg);
+void woal_bandcfg_to_channel_info(moal_private *priv, Band_Config_t *bandcfg,
+				  t_u8 channel, wifi_channel_info * ch_info);
+mlan_status woal_config_rtt(moal_private *priv, t_u8 wait_option,
+			    wifi_rtt_config_params_t * rtt_params);
+mlan_status woal_cancel_rtt(moal_private *priv, t_u8 wait_option,
+			    t_u32 addr_num, t_u8 addr[][MLAN_MAC_ADDR_LENGTH]);
+mlan_status woal_rtt_responder_cfg(moal_private *priv, t_u8 wait_option,
+				   mlan_rtt_responder * rtt_rsp_cfg);
+
+monitor_iface *woal_prepare_mon_if(moal_private *priv,
+				   const char *name,
+				   unsigned char name_assign_type);
+
+#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);
+#endif
+void woal_ioctl_get_misc_conf(moal_private *priv, mlan_ds_misc_cfg *info);
+#endif /* _MOAL_MAIN_H */
diff --git a/wlan_sd8997/mlinux/moal_priv.c b/wlan_sd8997/mlinux/moal_priv.c
new file mode 100644
index 0000000..d916a1d
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_priv.c
@@ -0,0 +1,7397 @@
+/** @file  moal_priv.c
+  *
+  * @brief This file contains standard ioctl functions
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+Change log:
+    10/30/2008: initial version
+************************************************************************/
+
+#include	"moal_main.h"
+#include	"moal_sdio.h"
+
+#include    "moal_eth_ioctl.h"
+
+/********************************************************
+			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_GN, BAND_B | BAND_G | BAND_GN, BAND_G | BAND_GN,
+	BAND_GN | BAND_GAC, BAND_B | BAND_G | BAND_GN | BAND_GAC,
+		BAND_G | BAND_GN | BAND_GAC,
+	BAND_A,
+	BAND_AN, BAND_A | BAND_AN,
+	BAND_AN | BAND_AAC, BAND_A | BAND_AN | BAND_AAC,
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+extern int cfg80211_wext;
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ * @brief Associated to a specific indexed entry in the ScanTable
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param wrq          A pointer to iwreq 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;
+	memcpy(ssid_bssid.ssid.ssid, buf + i, 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)) {
+		memcpy(&priv->prev_ssid_bssid.ssid,
+		       &bss_info.ssid, sizeof(mlan_802_11_ssid));
+		memcpy(&priv->prev_ssid_bssid.bssid,
+		       &bss_info.bssid, MLAN_MAC_ADDR_LENGTH);
+	}
+#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;
+	int intf_num;
+	moal_handle *handle = priv->phandle;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+#if defined(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 && V14_FEATURE */
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	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);
+#if defined(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 && V14_FEATURE */
+	}
+
+	/* 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;
+		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) {
+			ret = -EFAULT;
+			if (status != MLAN_STATUS_PENDING)
+				kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+
+	/* 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 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];
+	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 (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] != 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[4];
+	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;
+	t_u32 adhoc_chan_bandwidth = 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 (radio_cfg->param.band_cfg.adhoc_start_band & BAND_GN
+		    || radio_cfg->param.band_cfg.adhoc_start_band & BAND_AN
+		    || radio_cfg->param.band_cfg.adhoc_start_band & BAND_GAC
+		    || radio_cfg->param.band_cfg.adhoc_start_band & BAND_AAC) {
+			/* secondary bandwidth */
+			data[3] =
+				radio_cfg->param.band_cfg.adhoc_chan_bandwidth;
+			wrq->u.data.length = 4;
+		}
+
+		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;
+			}
+		}
+		if (user_data_len == 4) {
+			if (!(adhoc_band & (BAND_GN
+					    | BAND_GAC | BAND_AN | BAND_AAC))) {
+				PRINTM(MERROR,
+				       "11n is not enabled for adhoc, can not set HT/VHT channel bandwidth\n");
+				ret = -EINVAL;
+				goto error;
+			}
+			adhoc_chan_bandwidth = data[3];
+			if ((adhoc_chan_bandwidth != CHANNEL_BW_20MHZ) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_ABOVE) &&
+			    (adhoc_chan_bandwidth != CHANNEL_BW_40MHZ_BELOW)
+			    && (adhoc_chan_bandwidth != CHANNEL_BW_80MHZ)
+				) {
+				PRINTM(MERROR,
+				       "Invalid secondary channel bandwidth, only allowed 0, 1, 3 or 4\n");
+				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;
+		radio_cfg->param.band_cfg.adhoc_chan_bandwidth =
+			adhoc_chan_bandwidth;
+		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 Set/Get network monitor configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_net_monitor_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int user_data_len = wrq->u.data.length;
+	int data[5] = { 0 }, copy_len;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_net_monitor *net_mon = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = priv->phandle;
+	monitor_iface *mon_if = NULL;
+	struct net_device *ndev = NULL;
+
+	ENTER();
+
+	copy_len = MIN(sizeof(data), sizeof(int) * user_data_len);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
+	misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (!user_data_len) {
+		req->action = MLAN_ACT_GET;
+	} else if (user_data_len == 1 || user_data_len == 2 ||
+		   user_data_len == 4 || user_data_len == 5) {
+		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] != MTRUE && data[0] != MFALSE) {
+			PRINTM(MERROR,
+			       "NET_MON: Activity should be enable(=1)/disable(=0)\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		net_mon->enable_net_mon = data[0];
+		if (data[0] == MTRUE) {
+			int i;
+			if (user_data_len != 2 && user_data_len != 4
+			    && user_data_len != 5) {
+				PRINTM(MERROR,
+				       "NET_MON: Invalid number of args!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+
+			/* Supported filter flags */
+			if (!data[1] || data[1] &
+			    ~(MLAN_NETMON_DATA | MLAN_NETMON_MANAGEMENT |
+			      MLAN_NETMON_CONTROL | MLAN_NETMON_NOPROM |
+			      MLAN_NETMON_DECRYPTED)) {
+				PRINTM(MERROR,
+				       "NET_MON: Invalid filter flag\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (user_data_len > 2) {
+				/* Supported bands */
+				for (i = 0; i < sizeof(SupportedAdhocBand); i++)
+					if (data[2] == SupportedAdhocBand[i])
+						break;
+				if (i == sizeof(SupportedAdhocBand)) {
+					PRINTM(MERROR,
+					       "NET_MON: Invalid band\n");
+					ret = -EINVAL;
+					goto done;
+				}
+			}
+			/* Supported channel */
+			if (user_data_len > 3 &&
+			    (data[3] < 1 || data[3] > MLAN_MAX_CHANNEL)) {
+				PRINTM(MERROR,
+				       "NET_MON: Invalid channel number\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (user_data_len == 5) {
+				/* Secondary channel offset */
+				if (!(data[2] & (BAND_GN | BAND_AN))) {
+					PRINTM(MERROR,
+					       "No 11n in band, can not set "
+					       "secondary channel offset\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				if ((data[4] != CHANNEL_BW_20MHZ) &&
+				    (data[4] != CHANNEL_BW_40MHZ_ABOVE) &&
+				    (data[4] != CHANNEL_BW_40MHZ_BELOW)
+				    && (data[4] != CHANNEL_BW_80MHZ)
+					) {
+					PRINTM(MERROR,
+					       "Invalid secondary channel bandwidth, "
+					       "only allowed 0, 1, 3 or 4\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				net_mon->chan_bandwidth = data[4];
+			}
+			net_mon->filter_flag = data[1];
+			net_mon->band = data[2];
+			net_mon->channel = data[3];
+		}
+		req->action = MLAN_ACT_SET;
+	} else {
+		PRINTM(MERROR, "NET_MON: Invalid number of args!\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_SET) {
+		if (data[0]) {
+			/* Enable sniffer mode */
+			if (!handle->mon_if) {
+				mon_if = woal_prepare_mon_if(priv, "rtap", 0);
+				if (!mon_if) {
+					PRINTM(MFATAL,
+					       "Prepare mon_if fail.\n");
+					ret = -EFAULT;
+					goto done;
+				}
+				ndev = mon_if->mon_ndev;
+				ret = register_netdevice(ndev);
+				if (ret) {
+					PRINTM(MFATAL,
+					       "register net_device failed, ret=%d\n",
+					       ret);
+					free_netdev(ndev);
+					ret = -EFAULT;
+					goto done;
+				}
+				handle->mon_if = mon_if;
+			}
+			/* Save band channel config */
+			handle->mon_if->band_chan_cfg.band = net_mon->band;
+			handle->mon_if->band_chan_cfg.channel =
+				net_mon->channel;
+			handle->mon_if->band_chan_cfg.chan_bandwidth =
+				net_mon->chan_bandwidth;
+		} else {
+			/* Disable sniffer mode */
+			if (handle->mon_if) {
+				ndev = handle->mon_if->mon_ndev;
+				handle->mon_if = NULL;
+				unregister_netdevice(ndev);
+			}
+		}
+	}
+
+	data[0] = net_mon->enable_net_mon;
+	data[1] = net_mon->filter_flag;
+	data[2] = net_mon->band;
+	data[3] = net_mon->channel;
+	data[4] = net_mon->chan_bandwidth;
+	wrq->u.data.length = 5;
+	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:
+	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 = 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 < pcfg->param.power_ext.num_pwr_grp) &&
+		       (power_ext_len < 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;
+}
+
+/**
+ *  @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;
+}
+
+/**
+ *  @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 ATIM window
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_atim_window(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	int atim = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&atim, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((atim < 0) || (atim > MLAN_MAX_ATIM_WINDOW)) {
+			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_ATIM_WINDOW;
+	req->req_id = MLAN_IOCTL_BSS;
+	if (!wrq->u.data.length)
+		req->action = MLAN_ACT_GET;
+	else {
+		req->action = MLAN_ACT_SET;
+		bss->param.atim_window = atim;
+	}
+
+	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.atim_window,
+	     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 "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;
+}
+
+/**
+ * @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;
+}
+
+/**
+ * @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 Set/Get module configuration
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_fw_wakeup_method(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data[2];
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	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;
+
+	if (wrq->u.data.length > 2) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (!wrq->u.data.length) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		if (copy_from_user
+		    (data, wrq->u.data.pointer,
+		     sizeof(int) * wrq->u.data.length)) {
+			PRINTM(MINFO, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data[0] != FW_WAKEUP_METHOD_INTERFACE &&
+		    data[0] != FW_WAKEUP_METHOD_GPIO) {
+			PRINTM(MERROR, "Invalid FW wake up method:%d\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == FW_WAKEUP_METHOD_GPIO) {
+			if (wrq->u.data.length == 1) {
+				PRINTM(MERROR,
+				       "Please provide gpio pin number for FW_WAKEUP_METHOD gpio\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			pm_cfg->param.fw_wakeup_params.gpio_pin = data[1];
+		}
+
+		pm_cfg->param.fw_wakeup_params.method = data[0];
+	}
+
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_FW_WAKEUP_METHOD;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = ((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.method;
+	data[1] =
+		((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.gpio_pin;
+
+	if (data[0] == FW_WAKEUP_METHOD_INTERFACE)
+		wrq->u.data.length = 1;
+	else
+		wrq->u.data.length = 2;
+	if (copy_to_user
+	    (wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Configure 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_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[][35] = { {"sleep clock error in ppm"},
+	{"wakeup offset in usec"},
+	{"clock stabilization time in usec"},
+	{"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");
+			LEAVE();
+			return -EINVAL;
+		}
+#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 Control Coalescing status 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_coalescing_status_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_misc_cfg *pcoal = NULL;
+	mlan_ioctl_req *req = NULL;
+	char buf[8];
+	struct iwreq *wreq = (struct iwreq *)wrq;
+	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;
+	}
+	pcoal = (mlan_ds_misc_cfg *)req->pbuf;
+
+	memset(buf, 0, sizeof(buf));
+	if (!wrq->u.data.length) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		if (copy_from_user(buf, wrq->u.data.pointer,
+				   MIN(sizeof(buf) - 1, wreq->u.data.length))) {
+			PRINTM(MINFO, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (buf[0] == 1)
+			pcoal->param.coalescing_status =
+				MLAN_MISC_COALESCING_ENABLE;
+		else
+			pcoal->param.coalescing_status =
+				MLAN_MISC_COALESCING_DISABLE;
+	}
+
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	pcoal->sub_command = MLAN_OID_MISC_COALESCING_STATUS;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	buf[0] = ((mlan_ds_misc_cfg *)req->pbuf)->param.coalescing_status;
+
+	if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
+		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;
+}
+
+#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 the iwreq structure
+ *
+ *  @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 the iwreq structure
+ *
+ *  @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 the iwreq structure
+ *
+ *  @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 the iwreq structure
+ *
+ *  @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      Pointer to the iwreq structure
+ *
+ *  @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 (!data_length || data_length >= sizeof(buf)) {
+		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;
+	}
+
+	/* 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);
+			strncpy((char *)sec->param.passphrase.ssid.ssid, end,
+				MIN(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;
+			memcpy(sec->param.passphrase.psk.passphrase.passphrase,
+			       end,
+			       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:");
+			memcpy(buf + len, sec->param.passphrase.ssid.ssid,
+			       sec->param.passphrase.ssid.ssid_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();
+
+	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;
+}
+
+/** AES key length */
+#define AES_KEY_LEN 16
+/**
+ *  @brief Adhoc AES control
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to the iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_adhoc_aes_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	static char buf[256];
+	int ret = 0, action = -1;
+	unsigned int i;
+	t_u8 key_ascii[32];
+	t_u8 key_hex[16];
+	t_u8 *tmp = NULL;
+	mlan_bss_info bss_info;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	int data_length = wrq->u.data.length, copy_len;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	memset(key_ascii, 0x00, sizeof(key_ascii));
+	memset(key_hex, 0x00, sizeof(key_hex));
+	memset(buf, 0x00, sizeof(buf));
+
+	/* Get current BSS information */
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (bss_info.bss_mode != MLAN_BSS_MODE_IBSS ||
+	    bss_info.media_connected == MTRUE) {
+		PRINTM(MERROR, "STA is connected or not in IBSS mode.\n");
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	copy_len = data_length;
+
+	if (data_length > 0) {
+		if (data_length >= sizeof(buf)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (copy_from_user(buf, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		if (data_length == 1) {
+			/* Get Adhoc AES 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_CFG_ENCRYPT_KEY;
+			sec->param.encrypt_key.key_len = AES_KEY_LEN;
+			sec->param.encrypt_key.key_index =
+				MLAN_KEY_INDEX_UNICAST;
+			status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				ret = -EFAULT;
+				goto done;
+			}
+
+			memcpy(key_hex, sec->param.encrypt_key.key_material,
+			       sizeof(key_hex));
+			HEXDUMP("Adhoc AES Key (HEX)", key_hex,
+				sizeof(key_hex));
+
+			wrq->u.data.length = sizeof(key_ascii) + 1;
+
+			tmp = key_ascii;
+			for (i = 0; i < sizeof(key_hex); i++)
+				tmp += sprintf((char *)tmp, "%02x", key_hex[i]);
+		} else if (data_length >= 2) {
+			/* Parse the buf to get the cmd_action */
+			action = woal_atox(buf);
+			if (action < 1 || action > 2) {
+				PRINTM(MERROR, "Invalid action argument %d\n",
+				       action);
+				ret = -EINVAL;
+				goto done;
+			}
+
+			req->req_id = MLAN_IOCTL_SEC_CFG;
+			req->action = MLAN_ACT_SET;
+			sec = (mlan_ds_sec_cfg *)req->pbuf;
+			sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+
+			if (action == 1) {
+				/* Set Adhoc AES Key  */
+				memcpy(key_ascii, &buf[2], sizeof(key_ascii));
+				woal_ascii2hex(key_hex, (char *)key_ascii,
+					       sizeof(key_hex));
+				HEXDUMP("Adhoc AES Key (HEX)", key_hex,
+					sizeof(key_hex));
+
+				sec->param.encrypt_key.key_len = AES_KEY_LEN;
+				sec->param.encrypt_key.key_index =
+					MLAN_KEY_INDEX_UNICAST;
+				sec->param.encrypt_key.key_flags =
+					KEY_FLAG_SET_TX_KEY |
+					KEY_FLAG_GROUP_KEY;
+				memcpy(sec->param.encrypt_key.mac_addr,
+				       (u8 *)bcast_addr, ETH_ALEN);
+				memcpy(sec->param.encrypt_key.key_material,
+				       key_hex, sec->param.encrypt_key.key_len);
+
+				status = woal_request_ioctl(priv, req,
+							    MOAL_IOCTL_WAIT);
+				if (status != MLAN_STATUS_SUCCESS) {
+					ret = -EFAULT;
+					goto done;
+				}
+			} else {
+				/* Clear Adhoc AES Key */
+				sec->param.encrypt_key.key_len = AES_KEY_LEN;
+				sec->param.encrypt_key.key_index =
+					MLAN_KEY_INDEX_UNICAST;
+				sec->param.encrypt_key.key_flags =
+					KEY_FLAG_REMOVE_KEY;
+				memcpy(sec->param.encrypt_key.mac_addr,
+				       (u8 *)bcast_addr, ETH_ALEN);
+				memset(sec->param.encrypt_key.key_material, 0,
+				       sizeof(sec->param.encrypt_key.
+					      key_material));
+
+				status = woal_request_ioctl(priv, req,
+							    MOAL_IOCTL_WAIT);
+				if (status != MLAN_STATUS_SUCCESS) {
+					ret = -EFAULT;
+					goto done;
+				}
+			}
+		}
+
+		HEXDUMP("Adhoc AES Key (ASCII)", key_ascii, sizeof(key_ascii));
+		wrq->u.data.length = sizeof(key_ascii);
+		if (wrq->u.data.pointer) {
+			if (copy_to_user(wrq->u.data.pointer, &key_ascii,
+					 sizeof(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 MAX_TX_BF_GLOBAL_ARGS   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;
+	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 > 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 < 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 < 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 *)wrq->u.data.pointer;
+	pcurrent = (t_u8 *)prsp_info->scan_table_entry_buf;
+
+	pbuffer_end = 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 *)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)
+{
+	int ret = 0;
+	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) {
+		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 */
+	if (copy_from_user
+	    (&scan_start, wrq->u.data.pointer, sizeof(scan_start))) {
+		PRINTM(MERROR, "copy from user failed\n");
+		ret = -EFAULT;
+		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");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	/* 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);
+	}
+	handle->scan_pending_on_block = MFALSE;
+	handle->scan_priv = NULL;
+	MOAL_REL_SEMAPHORE(&handle->async_sem);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @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) {
+		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 {
+		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;
+		}
+	}
+
+	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, func, 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) */
+	func = buf[1];		/* func (0/1/2) */
+	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, func = %d, addr = %#x, mode = %d, block size = %d, block(byte) number = %d\n",
+	       func, 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 > total_len)
+			pattern_len = total_len;
+		memset(data, 0, WOAL_2K_BYTES);
+
+		/* Copy/duplicate the pattern to data buffer */
+		for (pos = 0; pos < 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;
+}
+
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/**
+ * @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];
+	case 5:
+		misc->param.mpa_ctrl.tx_max_ports = data[4];
+	case 4:
+		misc->param.mpa_ctrl.rx_buf_size = data[3];
+	case 3:
+		misc->param.mpa_ctrl.tx_buf_size = data[2];
+	case 2:
+		misc->param.mpa_ctrl.rx_enable = data[1];
+	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 /* SDIO_MULTI_PORT_TX_AGGR || SDIO_MULTI_PORT_RX_AGGR */
+
+/**
+ * @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 arg_len = 7;
+	int data[arg_len], 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;
+
+	ENTER();
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (data_length > arg_len) {
+		ret = -EINVAL;
+		goto done;
+	}
+	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;
+		memcpy(&scan->param.scan_cfg, data, sizeof(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 (!data_length) {
+		memcpy(data, &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 = ARRAY_SIZE(data);
+	}
+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 ad-hoc awake period parameter */
+	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] != SPECIAL_ADHOC_AWAKE_PD) &&
+		    ((data[i] < MIN_ADHOC_AWAKE_PD) ||
+		     (data[i] > MAX_ADHOC_AWAKE_PD))) {
+			PRINTM(MERROR,
+			       "Invalid argument for adhoc awake period\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		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;
+		memcpy(&pm_cfg->param.ps_cfg, data,
+		       MIN(sizeof(pm_cfg->param.ps_cfg), sizeof(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;
+	}
+	memcpy(data, &pm_cfg->param.ps_cfg,
+	       MIN((sizeof(int) * allowed), sizeof(pm_cfg->param.ps_cfg)));
+	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;
+		}
+
+		memcpy(cfg->param.addts.ie_data,
+		       addts_ioctl.ie_data, cfg->param.addts.ie_data_len);
+
+		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;
+
+		memcpy(addts_ioctl.ie_data,
+		       cfg->param.addts.ie_data, cfg->param.addts.ie_data_len);
+
+		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;
+		}
+
+		memcpy(cfg->param.delts.ie_data,
+		       delts_ioctl.ie_data, cfg->param.delts.ie_data_len);
+
+		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;
+		}
+
+		memcpy((void *)pqstats, (void *)&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));
+		memcpy((void *)&qstats_ioctl, (void *)pqstats,
+		       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));
+		memcpy((void *)&qstatus_ioctl, (void *)&pwmm->param.q_status,
+		       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));
+		memcpy((void *)&ts_status_ioctl, (void *)&pwmm->param.ts_status,
+		       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;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ *  @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] > 0xFFFF) {
+			PRINTM(MERROR, "The maximum user CAC is 65535 msec.\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 / 1000;
+		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;
+}
+#endif /* DFS_SUPPORT && DFS_TESTING_SUPPORT */
+
+/**
+ *  @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;
+		}
+
+		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];
+		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;
+		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;
+		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 wrq          A pointer to iwreq 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");
+			LEAVE();
+			return -EINVAL;
+		}
+
+		/* 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 || data[1] > 15)) {
+				PRINTM(MERROR,
+				       "Invalid gpio pin no (0-15 , 0xFF for default)!\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(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;
+		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;
+		case WOAL_SET_GET_WWS_CFG:
+			ret = woal_wws_cfg(priv, wrq);
+			break;
+		case WOAL_SLEEP_PD:
+			ret = woal_sleep_pd(priv, wrq);
+			break;
+		case WOAL_FW_WAKEUP_METHOD:
+			ret = woal_fw_wakeup_method(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;
+		case WOAL_COALESCING_STATUS:
+			ret = woal_coalescing_status_ioctl(priv, wrq);
+			break;
+#if defined(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;
+		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_ATIM_WINDOW:
+			ret = woal_atim_window(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;
+		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_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;
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+		case WOAL_SDIO_MPA_CTRL:
+			ret = woal_do_sdio_mpa_ctrl(priv, wrq);
+			break;
+#endif
+		case WOAL_SLEEP_PARAMS:
+			ret = woal_sleep_params_ioctl(priv, wrq);
+			break;
+		case WOAL_NET_MONITOR:
+			ret = woal_net_monitor_ioctl(priv, wrq);
+			break;
+#if defined(DFS_TESTING_SUPPORT)
+		case WOAL_DFS_TESTING:
+			ret = woal_dfs_testing(priv, wrq);
+			break;
+#endif
+		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_ADHOC_AES:
+			ret = woal_adhoc_aes_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) {
+		case WOAL_CMD_53RDWR:
+			ret = woal_cmd53rdwr_ioctl(priv, wrq);
+			break;
+		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(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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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) {
+			memcpy(chan_list, &bss->param.chanlist,
+			       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_sd8997/mlinux/moal_priv.h b/wlan_sd8997/mlinux/moal_priv.h
new file mode 100644
index 0000000..0554d1d
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_priv.h
@@ -0,0 +1,777 @@
+
+/** @file moal_priv.h
+ *
+ * @brief This file contains definition for extended private IOCTL call.
+ *
+ * Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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
+
+/** 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 set/get ATIM window */
+#define WOAL_ATIM_WINDOW            4
+/** 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
+/** 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
+/** 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
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+/** 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 network monitor */
+#define WOAL_NET_MONITOR            30
+/** Private command ID to set/get TX BF capabilities */
+#define WOAL_TX_BF_CAP              31
+#if defined(DFS_TESTING_SUPPORT)
+/** Private command ID to set/get dfs testing settings */
+#define WOAL_DFS_TESTING            33
+#endif
+/** 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 firmware wakeup method */
+#define WOAL_FW_WAKEUP_METHOD       15
+/** 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
+/** Private command ID for coalesced status */
+#define WOAL_COALESCING_STATUS      20
+#if defined(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 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
+/** Private command to get/set Ad-Hoc AES */
+#define WOAL_ADHOC_AES              2
+#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
+
+/** Get log buffer size */
+#define GETLOG_BUFSIZE              512
+
+/** 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)
+
+/** Private command ID to read/write Command 53 */
+#define WOAL_CMD_53RDWR             2
+
+/** 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
+
+/**
+ * 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"},
+	{
+	 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"},
+	{
+	 WOAL_SET_GET_WWS_CFG,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "wwscfg"},
+#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_FW_WAKEUP_METHOD,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "fwwakeupmethod"},
+	{
+	 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"},
+	{
+	 WOAL_COALESCING_STATUS,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "coalesce_status"},
+#if defined(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_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_ATIM_WINDOW,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "atimwindow"},
+	{
+	 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"},
+	{
+	 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"},
+	{
+	 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"},
+#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
+	{
+	 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_NET_MONITOR,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "netmon"},
+#if defined(DFS_TESTING_SUPPORT)
+	{
+	 WOAL_DFS_TESTING,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "dfstesting"},
+#endif
+	{
+	 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_ADHOC_AES,
+	 IW_PRIV_TYPE_CHAR | 256,
+	 IW_PRIV_TYPE_CHAR | 256,
+	 "adhocaes"},
+	{
+	 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,
+	 ""},
+	{
+	 WOAL_CMD_53RDWR,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 "sdcmd53rw"},
+	{
+	 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
+};
+
+/** 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;
+
+#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_sd8997/mlinux/moal_proc.c b/wlan_sd8997/mlinux/moal_proc.c
new file mode 100644
index 0000000..44bf966
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_proc.c
@@ -0,0 +1,778 @@
+/**  @file moal_proc.c
+  *
+  * @brief This file contains functions for proc file.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#include    "moal_sdio.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+#ifdef CONFIG_PROC_FS
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+#define PROC_DIR	NULL
+#define MWLAN_PROC_DIR  "mwlan/"
+#define MWLAN_PROC  "mwlan"
+/** Proc top level directory entry */
+struct proc_dir_entry *proc_mwlan;
+int proc_dir_entry_use_count;
+#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
+
+extern int drv_mode;
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief Proc read function for info
+ *
+ *  @param sfp      pointer to seq_file structure
+ *  @param data     void pointer to 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
+
+	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
+	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);
+#if defined(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 < 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 */
+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
+}
+
+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,
+};
+
+#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;
+
+	memcpy(string, buffer + strlen("sdcmd52rw="),
+	       MIN((CMD52_STR_LEN - 1), (len - strlen("sdcmd52rw="))));
+	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;
+}
+
+/**
+ *  @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;
+
+	int func = 0, reg = 0, val = 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)drv_mode)
+			if (woal_switch_drv_mode(handle, config_data) !=
+			    MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Could not switch drv mode\n");
+			}
+	}
+	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);
+	}
+	if (!strncmp(databuf, "debug_dump", strlen("debug_dump"))) {
+		priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+		if (priv) {
+			PRINTM(MERROR, "Recevie debug_dump command\n");
+#ifdef DEBUG_LEVEL1
+			drvdbg &= ~MFW_D;
+#endif
+			woal_mlan_debug_info(priv);
+			woal_moal_debug_info(priv, NULL, MFALSE);
+
+			woal_dump_firmware_info_v3(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)
+				memcpy(handle->fwdump_fname,
+				       databuf + strlen("fwdump_file="),
+				       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);
+		} else
+			config_data = FW_RELOAD_SDIO_INBAND_RESET;
+		PRINTM(MMSG, "Request fw_reload=%d\n", config_data);
+		woal_request_fw_reload(handle, config_data);
+	}
+	MODULE_PUT;
+	LEAVE();
+	return (int)count;
+}
+
+/**
+ *  @brief config proc read function
+ *
+ *  @param sfp      pointer to seq_file structure
+ *  @param data     Void pointer to data
+ *
+ *  @return         number of output data
+ */
+static int
+woal_config_read(struct seq_file *sfp, void *data)
+{
+	moal_handle *handle = (moal_handle *)sfp->private;
+
+	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)drv_mode);
+	seq_printf(sfp, "sdcmd52rw=%d 0x%0x 0x%02X\n", handle->cmd52_func,
+		   handle->cmd52_reg, handle->cmd52_val);
+
+	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
+}
+
+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,
+};
+
+/********************************************************
+		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; *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 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_DIR;
+#endif
+	char config_proc_dir[20];
+
+	ENTER();
+
+	PRINTM(MINFO, "Create Proc Interface\n");
+	if (!handle->proc_mwlan) {
+#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(MWLAN_PROC, pde->name)) {
+				/* Directory exists */
+				PRINTM(MWARN,
+				       "proc interface already exists!\n");
+				handle->proc_mwlan = pde;
+				break;
+			}
+		}
+		if (pde == NULL) {
+			handle->proc_mwlan = proc_mkdir(MWLAN_PROC, PROC_DIR);
+			if (!handle->proc_mwlan)
+				PRINTM(MERROR,
+				       "Cannot create proc interface!\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+			else
+				atomic_set(&handle->proc_mwlan->count, 1);
+#endif
+		}
+#else
+		if (!proc_mwlan) {
+			handle->proc_mwlan = proc_mkdir(MWLAN_PROC, PROC_DIR);
+			if (!handle->proc_mwlan) {
+				PRINTM(MERROR,
+				       "Cannot create proc interface!\n");
+			}
+		} else {
+			handle->proc_mwlan = proc_mwlan;
+		}
+#endif
+		if (handle->proc_mwlan) {
+			if (handle->handle_idx)
+				sprintf(config_proc_dir, "config%d",
+					handle->handle_idx);
+			else
+				strcpy(config_proc_dir, "config");
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			r = proc_create_data(config_proc_dir, 0644,
+					     handle->proc_mwlan,
+					     &config_proc_fops, handle);
+			if (r == NULL)
+#else
+			r = create_proc_entry(config_proc_dir, 0644,
+					      handle->proc_mwlan);
+			if (r) {
+				r->data = handle;
+				r->proc_fops = &config_proc_fops;
+			} else
+#endif
+				PRINTM(MMSG, "Fail to create proc config\n");
+			proc_dir_entry_use_count++;
+		}
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+		proc_mwlan = handle->proc_mwlan;
+#endif
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Remove the top level proc directory
+ *
+ *  @param handle   pointer moal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_proc_exit(moal_handle *handle)
+{
+	ENTER();
+
+	PRINTM(MINFO, "Remove Proc Interface\n");
+	if (handle->proc_mwlan) {
+		char config_proc_dir[20];
+		if (handle->handle_idx)
+			sprintf(config_proc_dir, "config%d",
+				handle->handle_idx);
+		else
+			strcpy(config_proc_dir, "config");
+		remove_proc_entry(config_proc_dir, handle->proc_mwlan);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		/* Remove only if we are the only instance using this */
+		if (atomic_read(&(handle->proc_mwlan->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_mwlan->count));
+#endif
+			if (!--proc_dir_entry_use_count) {
+				remove_proc_entry(MWLAN_PROC, PROC_DIR);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+				proc_mwlan = NULL;
+#endif
+			}
+
+			handle->proc_mwlan = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		}
+#endif
+	}
+
+	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));
+		strcpy(proc_dir_name, MWLAN_PROC_DIR);
+
+		if (strlen(dev->name) >
+		    ((sizeof(proc_dir_name) - 1) - strlen(MWLAN_PROC_DIR))) {
+			PRINTM(MERROR,
+			       "Failed to create proc entry, device name is too long\n");
+			LEAVE();
+			return;
+		}
+		strcat(proc_dir_name, dev->name);
+		/* Try to create mwlan/mlanX first */
+		priv->proc_entry = proc_mkdir(proc_dir_name, PROC_DIR);
+		if (priv->proc_entry) {
+			/* Success. Continue normally */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+			if (!priv->phandle->proc_mwlan) {
+				priv->phandle->proc_mwlan =
+					priv->proc_entry->parent;
+			}
+			atomic_inc(&(priv->phandle->proc_mwlan->count));
+#endif
+		} else {
+			/* Failure. mwlan may not exist. Try to create that first */
+			priv->phandle->proc_mwlan =
+				proc_mkdir(MWLAN_PROC, PROC_DIR);
+			if (!priv->phandle->proc_mwlan) {
+				/* Failure. Something broken */
+				LEAVE();
+				return;
+			} else {
+				/* Success. Now retry creating mlanX */
+				priv->proc_entry =
+					proc_mkdir(proc_dir_name, PROC_DIR);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+				atomic_inc(&(priv->phandle->proc_mwlan->count));
+#endif
+			}
+		}
+#else
+	if (priv->phandle->proc_mwlan && !priv->proc_entry) {
+		priv->proc_entry =
+			proc_mkdir(dev->name, priv->phandle->proc_mwlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		atomic_inc(&(priv->phandle->proc_mwlan->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);
+			if (r == NULL)
+#else
+			r = create_proc_entry("info", 0, priv->proc_entry);
+			if (r) {
+				r->data = dev;
+				r->proc_fops = &info_proc_fops;
+			} else
+#endif
+				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_mwlan && priv->proc_entry) {
+		remove_proc_entry("info", priv->proc_entry);
+		remove_proc_entry(priv->proc_entry_name,
+				  priv->phandle->proc_mwlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		atomic_dec(&(priv->phandle->proc_mwlan->count));
+#endif
+		priv->proc_entry = NULL;
+	}
+	LEAVE();
+}
+#endif
diff --git a/wlan_sd8997/mlinux/moal_sdio.h b/wlan_sd8997/mlinux/moal_sdio.h
new file mode 100644
index 0000000..0de69e2
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_sdio.h
@@ -0,0 +1,132 @@
+/** @file moal_sdio.h
+  *
+  * @brief This file contains definitions for SDIO interface.
+  * driver.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/****************************************************
+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
+
+#ifdef STA_SUPPORT
+/** Default firmware name */
+
+#define DEFAULT_FW_NAME	"mrvl/sdsd8997_combo_v4.bin"
+
+#ifndef DEFAULT_FW_NAME
+#define DEFAULT_FW_NAME ""
+#endif
+#endif /* STA_SUPPORT */
+
+#ifdef UAP_SUPPORT
+/** Default firmware name */
+
+#define DEFAULT_AP_FW_NAME "mrvl/sdsd8997_combo_v4.bin"
+
+#ifndef DEFAULT_AP_FW_NAME
+#define DEFAULT_AP_FW_NAME ""
+#endif
+#endif /* UAP_SUPPORT */
+
+/** Default firmaware name */
+
+#define DEFAULT_AP_STA_FW_NAME "mrvl/sdsd8997_combo_v4.bin"
+#define DEFAULT_WLAN_FW_NAME "mrvl/sd8997_wlan_v4.bin"
+
+#ifndef DEFAULT_AP_STA_FW_NAME
+#define DEFAULT_AP_STA_FW_NAME ""
+#endif
+
+/********************************************************
+		Global Functions
+********************************************************/
+
+/** Function to write register */
+mlan_status woal_write_reg(moal_handle *handle, t_u32 reg, t_u32 data);
+/** Function to read register */
+mlan_status woal_read_reg(moal_handle *handle, t_u32 reg, t_u32 *data);
+/** Function to write data to IO memory */
+mlan_status woal_write_data_sync(moal_handle *handle, mlan_buffer *pmbuf,
+				 t_u32 port, t_u32 timeout);
+/** Function to read data from IO memory */
+mlan_status woal_read_data_sync(moal_handle *handle, mlan_buffer *pmbuf,
+				t_u32 port, t_u32 timeout);
+
+/** Register to bus driver function */
+mlan_status woal_bus_register(void);
+/** Unregister from bus driver function */
+void woal_bus_unregister(void);
+
+/** Register device function */
+mlan_status woal_register_dev(moal_handle *handle);
+/** Unregister device function */
+void woal_unregister_dev(moal_handle *handle);
+
+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 */
+
+/** 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;
+};
+
+/** 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_sd8997/mlinux/moal_sdio_mmc.c b/wlan_sd8997/mlinux/moal_sdio_mmc.c
new file mode 100644
index 0000000..2fa13f5
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_sdio_mmc.c
@@ -0,0 +1,1011 @@
+/** @file moal_sdio_mmc.c
+ *
+ *  @brief This file contains SDIO MMC IF (interface) module
+ *  related functions.
+ *
+ * Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+/****************************************************
+Change log:
+	02/25/09: Initial creation -
+		  This file supports SDIO MMC only
+****************************************************/
+
+#include <linux/firmware.h>
+
+#include "moal_sdio.h"
+
+/** define marvell vendor id */
+#define MARVELL_VENDOR_ID 0x02df
+
+/* The macros below are hardware platform dependent.
+   The definition should match the actual platform */
+/** Initialize GPIO port */
+#define GPIO_PORT_INIT()
+/** Set GPIO port to high */
+#define GPIO_PORT_TO_HIGH()
+/** Set GPIO port to low */
+#define GPIO_PORT_TO_LOW()
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+#ifdef SDIO_SUSPEND_RESUME
+/** PM keep power */
+extern int pm_keep_power;
+extern int shutdown_hs;
+#endif
+
+extern int disconnect_on_suspend;
+
+/** Device ID for SD8997 */
+#define SD_DEVICE_ID_8997   (0x9141)
+
+/** WLAN IDs */
+static const struct sdio_device_id wlan_ids[] = {
+	{SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8997)},
+	{},
+};
+
+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_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
+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
+};
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**  @brief This function dump the sdio register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @return         N/A
+ */
+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;
+	int fun1_reg[] = { 0x03, 0x04, 0x05, 0x60, 0x61 };
+
+	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);
+	}
+
+	array_size = ARRAY_SIZE(fun1_reg);
+	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;
+}
+
+/********************************************************
+		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;
+
+	PRINTM(MINFO, "*** IN SDIO IRQ ***\n");
+	woal_interrupt(handle);
+
+	LEAVE();
+}
+
+/**  @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;
+
+	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_disable_func(func);
+		sdio_release_host(func);
+		kfree(card);
+		PRINTM(MFATAL, "sdio_enable_func() failed: ret=%d\n", ret);
+		LEAVE();
+		return -EIO;
+	}
+	sdio_release_host(func);
+	if (NULL == woal_add_card(card)) {
+		PRINTM(MERROR, "woal_add_card failed\n");
+		kfree(card);
+		sdio_claim_host(func);
+		sdio_disable_func(func);
+		sdio_release_host(func);
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	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) {
+			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
+
+#define SHUTDOWN_HOST_SLEEP_DEF_GAP      100
+#define SHUTDOWN_HOST_SLEEP_DEF_GPIO     0x3
+#define SHUTDOWN_HOST_SLEEP_DEF_COND     0x0
+
+/**  @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 timeout = 0;
+	int i, retry_num = 8;
+	moal_private *priv = NULL;
+
+	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 (shutdown_hs) {
+		priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+		if (priv)
+			priv->keep_connect = 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,
+					       "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));
+
+		timeout =
+			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);
+	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(MERROR,
+		       "%s: cannot remain alive while host is suspended\n",
+		       sdio_func_id(func));
+		LEAVE();
+		return -ENOSYS;
+	}
+	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 == 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 (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) {
+#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;
+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);
+	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
+ */
+mlan_status
+woal_write_reg(moal_handle *handle, t_u32 reg, t_u32 data)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	sdio_writeb(((struct sdio_mmc_card *)handle->card)->func, (t_u8)data,
+		    reg, (int *)&ret);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+ */
+mlan_status
+woal_read_reg(moal_handle *handle, t_u32 reg, t_u32 *data)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 val;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	val = sdio_readb(((struct sdio_mmc_card *)handle->card)->func, reg,
+			 (int *)&ret);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	*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
+ */
+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];
+	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) {
+		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;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+		return MLAN_STATUS_FAILURE;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+ */
+mlan_status
+woal_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
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+#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
+ */
+mlan_status
+woal_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
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+	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
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#endif
+#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_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;
+	}
+
+	/* init GPIO PORT for wakeup purpose */
+	GPIO_PORT_INIT();
+	/* set default value */
+	GPIO_PORT_TO_HIGH();
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function de-registers the IF module in bus driver
+ *
+ *  @return         N/A
+ */
+void
+woal_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
+ */
+void
+woal_unregister_dev(moal_handle *handle)
+{
+	ENTER();
+	if (handle->card) {
+		/* Release the SDIO IRQ */
+		sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+		sdio_release_irq(((struct sdio_mmc_card *)handle->card)->func);
+		sdio_disable_func(((struct sdio_mmc_card *)handle->card)->func);
+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+
+		sdio_set_drvdata(((struct sdio_mmc_card *)handle->card)->func,
+				 NULL);
+
+		GPIO_PORT_TO_LOW();
+		PRINTM(MWARN, "Making the sdio dev card as NULL\n");
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function registers the device
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_register_dev(moal_handle *handle)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = handle->card;
+	struct sdio_func *func;
+
+	ENTER();
+
+	GPIO_PORT_INIT();
+	GPIO_PORT_TO_HIGH();
+
+	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);
+
+	handle->hotplug_device = &func->dev;
+
+	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;
+}
diff --git a/wlan_sd8997/mlinux/moal_shim.c b/wlan_sd8997/mlinux/moal_shim.c
new file mode 100644
index 0000000..31036b8
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_shim.c
@@ -0,0 +1,3134 @@
+/** @file moal_shim.c
+  *
+  * @brief This file contains the callback functions registered to MLAN
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include	"moal_main.h"
+#include	"moal_sdio.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include "moal_cfg80211.h"
+#include "moal_cfgvendor.h"
+#endif
+extern int drv_mode;
+#include <asm/div64.h>
+
+/********************************************************
+		Local Variables
+********************************************************/
+/** moal_lock */
+typedef struct _moal_lock {
+	/** Lock */
+	spinlock_t lock;
+	/** Flags */
+	unsigned long flags;
+} moal_lock;
+
+/********************************************************
+		Global Variables
+********************************************************/
+extern int cfg80211_wext;
+
+extern int hw_test;
+
+#ifdef ANDROID_KERNEL
+extern int wakelock_timeout;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+extern int dfs_offload;
+#endif
+#endif
+
+/** napi support*/
+extern int napi;
+
+typedef MLAN_PACK_START struct {
+	t_u32 t4;
+	t_u8 t4_error;
+	t_u32 t1;
+	t_u8 t1_error;
+	t_u64 egress_time;
+} MLAN_PACK_END confirm_timestamps;
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Alloc a buffer
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+	    IN t_u32 size, IN t_u32 flag, OUT t_u8 **ppbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	t_u32 mem_flag = (in_interrupt() || irqs_disabled())?
+		GFP_ATOMIC : GFP_KERNEL;
+
+	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_handle 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(IN t_void *pmoal_handle, IN t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	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_handle 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(IN t_void *pmoal_handle, IN t_u32 size, OUT t_u8 **ppbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	*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_handle 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(IN t_void *pmoal_handle, IN t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	if (!pbuf)
+		return MLAN_STATUS_FAILURE;
+	vfree(pbuf);
+	atomic_dec(&handle->vmalloc_count);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Fill memory with constant byte
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+	    IN t_void *pmem, IN t_u8 byte, IN 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_handle 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(IN t_void *pmoal_handle,
+	    IN t_void *pdest, IN const t_void *psrc, IN t_u32 num)
+{
+	t_void *p = pdest;
+
+	if (pdest && psrc && num)
+		p = memcpy(pdest, psrc, num);
+
+	return p;
+}
+
+/**
+ *  @brief Move memory from one area to another
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+	     IN t_void *pdest, IN const t_void *psrc, IN 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_handle 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(IN t_void *pmoal_handle,
+	    IN const t_void *pmem1, IN const t_void *pmem2, IN t_u32 num)
+{
+	t_s32 result;
+
+	result = memcmp(pmem1, pmem2, num);
+
+	return result;
+}
+
+/**
+ *  @brief Delay function
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param delay  delay in micro-second
+ *
+ *  @return       N/A
+ */
+t_void
+moal_udelay(IN t_void *pmoal_handle, IN t_u32 delay)
+{
+	if (delay >= 1000)
+		mdelay(delay / 1000);
+	if (delay % 1000)
+		udelay(delay % 1000);
+}
+
+/**
+ *  @brief Retrieves the current system time
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, OUT t_u32 *psec, OUT t_u32 *pusec)
+{
+	struct timeval t;
+
+	do_gettimeofday(&t);
+	*psec = (t_u32)t.tv_sec;
+	*pusec = (t_u32)t.tv_usec;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Initializes the timer
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		OUT t_void **pptimer,
+		IN t_void (*callback) (t_void *pcontext), IN t_void *pcontext)
+{
+	moal_drv_timer *timer = NULL;
+	t_u32 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_handle Pointer to the MOAL context
+ *  @param ptimer   Pointer to the timer
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_free_timer(IN t_void *pmoal_handle, IN 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_handle 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(IN t_void *pmoal_handle,
+		 IN t_void *ptimer, IN t_u8 periodic, IN 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_handle Pointer to the MOAL context
+ *  @param ptimer   Pointer to the timer
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_stop_timer(IN t_void *pmoal_handle, IN 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_handle Pointer to the MOAL context
+ *  @param pplock   Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_init_lock(IN t_void *pmoal_handle, OUT t_void **pplock)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle Pointer to the MOAL context
+ *  @param plock    Lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_free_lock(IN t_void *pmoal_handle, IN t_void *plock)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	moal_lock *mlock = plock;
+
+	kfree(mlock);
+	if (mlock)
+		atomic_dec(&handle->lock_count);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Request a spin lock
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param plock    Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_spin_lock(IN t_void *pmoal_handle, IN t_void *plock)
+{
+	moal_lock *mlock = plock;
+	unsigned long flags = 0;
+
+	if (mlock) {
+		spin_lock_irqsave(&mlock->lock, flags);
+		mlock->flags = flags;
+		return MLAN_STATUS_SUCCESS;
+	} else {
+		return MLAN_STATUS_FAILURE;
+	}
+}
+
+/**
+ *  @brief Request a spin_unlock
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param plock    Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_spin_unlock(IN t_void *pmoal_handle, IN t_void *plock)
+{
+	moal_lock *mlock = (moal_lock *)plock;
+
+	if (mlock) {
+		spin_unlock_irqrestore(&mlock->lock, mlock->flags);
+
+		return MLAN_STATUS_SUCCESS;
+	} else {
+		return MLAN_STATUS_FAILURE;
+	}
+}
+
+/**
+ *  @brief This function reads one block of firmware data from MOAL
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		 IN t_u32 offset, IN t_u32 len, OUT t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+
+	if (!pbuf || !len)
+		return MLAN_STATUS_FAILURE;
+
+	if (offset + len > handle->firmware->size)
+		return MLAN_STATUS_FAILURE;
+
+	memcpy(pbuf, handle->firmware->data + offset, len);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN completes the initialization firmware.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN mlan_status status,
+			  IN mlan_hw_info * phw, IN pmlan_bss_tbl ptbl)
+{
+	ENTER();
+	if (status == MLAN_STATUS_SUCCESS) {
+		PRINTM(MCMND, "Get Hw Spec done, fw_cap=0x%x\n", phw->fw_cap);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN completes the initialization firmware.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	ENTER();
+	if (status == MLAN_STATUS_SUCCESS)
+		handle->hardware_status = HardwareStatusReady;
+	handle->init_wait_q_woken = MTRUE;
+	wake_up_interruptible(&handle->init_wait_q);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN shutdown firmware is completed.
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param status   The status code for mlan_shutdown request
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_shutdown_fw_complete(IN t_void *pmoal_handle, IN mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle 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(IN t_void *pmoal_handle,
+		    IN pmlan_ioctl_req pioctl_req, IN mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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_handle 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(IN t_void *pmoal_handle,
+		       IN t_u32 size, OUT pmlan_buffer *pmbuf)
+{
+	*pmbuf = woal_alloc_mlan_buffer((moal_handle *)pmoal_handle, size);
+	if (NULL == *pmbuf)
+		return MLAN_STATUS_FAILURE;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function frees mlan_buffer.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf)
+{
+	if (!pmbuf)
+		return MLAN_STATUS_FAILURE;
+	woal_free_mlan_buffer((moal_handle *)pmoal_handle, pmbuf);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN complete send data packet.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+			  IN pmlan_buffer pmbuf, IN mlan_status status)
+{
+	moal_private *priv = NULL;
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	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);
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	if (pmbuf) {
+		priv = woal_bss_index_to_priv(pmoal_handle, 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);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function write a command/data packet to card.
+ *         This function blocks the call until it finishes
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		     IN pmlan_buffer pmbuf, IN t_u32 port, IN t_u32 timeout)
+{
+	return woal_write_data_sync((moal_handle *)pmoal_handle, pmbuf, port,
+				    timeout);
+}
+
+/**
+ *  @brief This function read data packet/event/command from card.
+ *         This function blocks the call until it finish
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle,
+		    IN OUT pmlan_buffer pmbuf, IN t_u32 port, IN t_u32 timeout)
+{
+	return woal_read_data_sync((moal_handle *)pmoal_handle, pmbuf, port,
+				   timeout);
+}
+
+/**
+ *  @brief This function writes data into card register.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN t_u32 reg, IN t_u32 data)
+{
+	return woal_write_reg((moal_handle *)pmoal_handle, reg, data);
+}
+
+/**
+ *  @brief This function reads data from card register.
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN t_u32 reg, OUT t_u32 *data)
+{
+	return woal_read_reg((moal_handle *)pmoal_handle, reg, data);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ *  @brief This function uploads the packet to the network stack monitor interface
+ *
+ *  @param handle Pointer to the MOAL context
+ *  @param pmbuf    Pointer to mlan_buffer
+ *
+ *  @return  MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING/MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_recv_packet_to_mon_if(IN moal_handle *handle, IN pmlan_buffer pmbuf)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	struct radiotap_header *rth = NULL;
+	radiotap_info rt_info;
+	t_u8 format = 0;
+	t_u8 bw = 0;
+	t_u8 gi = 0;
+	t_u8 ldpc = 0;
+	t_u8 chan_num;
+	t_u8 band = 0;
+	struct ieee80211_hdr *dot11_hdr = NULL;
+	t_u8 *payload = NULL;
+	t_u32 vht_sig1 = 0;
+	t_u32 vht_sig2 = 0;
+	ENTER();
+	if (!pmbuf->pdesc) {
+		LEAVE();
+		return status;
+	}
+
+	skb = (struct sk_buff *)pmbuf->pdesc;
+
+	if ((handle->mon_if) && netif_running(handle->mon_if->mon_ndev)) {
+		if (handle->mon_if->radiotap_enabled) {
+			if (skb_headroom(skb) < sizeof(*rth)) {
+				PRINTM(MERROR,
+				       "%s No space to add Radio TAP header\n",
+				       __func__);
+				status = MLAN_STATUS_FAILURE;
+				handle->mon_if->stats.rx_dropped++;
+				goto done;
+			}
+			dot11_hdr =
+				(struct ieee80211_hdr *)(pmbuf->pbuf +
+							 pmbuf->data_offset);
+			memcpy(&rt_info,
+			       pmbuf->pbuf + pmbuf->data_offset -
+			       sizeof(rt_info), sizeof(rt_info));
+			ldpc = (rt_info.rate_info.rate_info & 0x20) >> 5;
+			format = (rt_info.rate_info.rate_info & 0x18) >> 3;
+			bw = (rt_info.rate_info.rate_info & 0x06) >> 1;
+			gi = rt_info.rate_info.rate_info & 0x01;
+			skb_push(skb, sizeof(*rth));
+			rth = (struct radiotap_header *)skb->data;
+			memset(skb->data, 0, sizeof(*rth));
+			rth->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+			rth->hdr.it_pad = 0;
+			rth->hdr.it_len = cpu_to_le16(sizeof(*rth));
+			rth->hdr.it_present =
+				cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
+					    (1 << IEEE80211_RADIOTAP_FLAGS) |
+					    (1 << IEEE80211_RADIOTAP_CHANNEL) |
+					    (1 <<
+					     IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+					    (1 <<
+					     IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+					    (1 << IEEE80211_RADIOTAP_ANTENNA));
+	    /** Timstamp */
+			rth->body.timestamp = cpu_to_le64(jiffies);
+	    /** Flags */
+			rth->body.flags = (rt_info.extra_info.flags &
+					   ~(RADIOTAP_FLAGS_USE_SGI_HT |
+					     RADIOTAP_FLAGS_WITH_FRAGMENT |
+					     RADIOTAP_FLAGS_WEP_ENCRYPTION |
+					     RADIOTAP_FLAGS_FAILED_FCS_CHECK));
+	    /** reverse fail fcs, 1 means pass FCS in FW, but means fail FCS in radiotap */
+			rth->body.flags |=
+				(~rt_info.extra_info.
+				 flags) & RADIOTAP_FLAGS_FAILED_FCS_CHECK;
+			if ((format == MLAN_RATE_FORMAT_HT) && (gi == 1))
+				rth->body.flags |= RADIOTAP_FLAGS_USE_SGI_HT;
+			if (ieee80211_is_mgmt(dot11_hdr->frame_control) ||
+			    ieee80211_is_data(dot11_hdr->frame_control)) {
+				if ((ieee80211_has_morefrags
+				     (dot11_hdr->frame_control)) ||
+				    (!ieee80211_is_first_frag
+				     (dot11_hdr->seq_ctrl))) {
+					rth->body.flags |=
+						RADIOTAP_FLAGS_WITH_FRAGMENT;
+				}
+			}
+			if (ieee80211_is_data(dot11_hdr->frame_control) &&
+			    ieee80211_has_protected(dot11_hdr->frame_control)) {
+				payload =
+					(t_u8 *)dot11_hdr +
+					ieee80211_hdrlen(dot11_hdr->
+							 frame_control);
+				if (!(*(payload + 3) & 0x20))
+						 /** ExtIV bit shall be 0 for WEP frame */
+					rth->body.flags |=
+						RADIOTAP_FLAGS_WEP_ENCRYPTION;
+			}
+	    /** Rate, t_u8 only apply for LG mode */
+			if (format == MLAN_RATE_FORMAT_LG) {
+				rth->hdr.it_present |=
+					cpu_to_le32(1 <<
+						    IEEE80211_RADIOTAP_RATE);
+				rth->body.rate = rt_info.rate_info.bitrate;
+			}
+	    /** Channel */
+			rth->body.channel.flags = 0;
+			if (rt_info.chan_num)
+				chan_num = rt_info.chan_num;
+			else
+				chan_num =
+					handle->mon_if->band_chan_cfg.channel;
+			band = (chan_num <=
+				14) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+			rth->body.channel.frequency =
+				cpu_to_le16(ieee80211_channel_to_frequency
+					    (chan_num, band));
+			rth->body.channel.flags |=
+				cpu_to_le16((band ==
+					     IEEE80211_BAND_2GHZ) ?
+					    CHANNEL_FLAGS_2GHZ :
+					    CHANNEL_FLAGS_5GHZ);
+			if (rth->body.channel.
+			    flags & cpu_to_le16(CHANNEL_FLAGS_2GHZ))
+				rth->body.channel.flags |=
+					cpu_to_le16
+					(CHANNEL_FLAGS_DYNAMIC_CCK_OFDM);
+			else
+				rth->body.channel.flags |=
+					cpu_to_le16(CHANNEL_FLAGS_OFDM);
+			if (handle->mon_if->chandef.chan &&
+			    (handle->mon_if->chandef.chan->
+			     flags & (IEEE80211_CHAN_PASSIVE_SCAN |
+				      IEEE80211_CHAN_RADAR)))
+				rth->body.channel.flags |=
+					cpu_to_le16
+					(CHANNEL_FLAGS_ONLY_PASSIVSCAN_ALLOW);
+	    /** Antenna */
+			rth->body.antenna_signal = -(rt_info.nf - rt_info.snr);
+			rth->body.antenna_noise = -rt_info.nf;
+			rth->body.antenna = rt_info.antenna;
+	    /** MCS */
+			if (format == MLAN_RATE_FORMAT_HT) {
+				rth->hdr.it_present |=
+					cpu_to_le32(1 <<
+						    IEEE80211_RADIOTAP_MCS);
+				rth->body.u.mcs.known =
+					rt_info.extra_info.mcs_known;
+				rth->body.u.mcs.flags =
+					rt_info.extra_info.mcs_flags;
+		/** MCS mcs */
+				rth->body.u.mcs.known |=
+					MCS_KNOWN_MCS_INDEX_KNOWN;
+				rth->body.u.mcs.mcs =
+					rt_info.rate_info.mcs_index;
+		/** MCS bw */
+				rth->body.u.mcs.known |= MCS_KNOWN_BANDWIDTH;
+				rth->body.u.mcs.flags &= ~(0x03);
+						 /** Clear, 20MHz as default */
+				if (bw == 1)
+					rth->body.u.mcs.flags |= RX_BW_40;
+		/** MCS gi */
+				rth->body.u.mcs.known |=
+					MCS_KNOWN_GUARD_INTERVAL;
+				rth->body.u.mcs.flags &= ~(1 << 2);
+				if (gi)
+					rth->body.u.mcs.flags |= gi << 2;
+		/** MCS FEC */
+				rth->body.u.mcs.known |= MCS_KNOWN_FEC_TYPE;
+				rth->body.u.mcs.flags &= ~(1 << 4);
+				if (ldpc)
+					rth->body.u.mcs.flags |= ldpc << 4;
+			}
+	    /** VHT */
+			if (format == MLAN_RATE_FORMAT_VHT) {
+				vht_sig1 = rt_info.extra_info.vht_sig1;
+				vht_sig2 = rt_info.extra_info.vht_sig2;
+		/** Present Flag */
+				rth->hdr.it_present |=
+					cpu_to_le32(1 <<
+						    IEEE80211_RADIOTAP_VHT);
+		/** STBC */
+				rth->body.u.vht.known |=
+					cpu_to_le16(VHT_KNOWN_STBC);
+				if (vht_sig1 & MBIT(3))
+					rth->body.u.vht.flags |= VHT_FLAG_STBC;
+		/** TXOP_PS_NA */
+		/** TODO: Not support now */
+		/** GI */
+				rth->body.u.vht.known |=
+					cpu_to_le16(VHT_KNOWN_GI);
+				if (vht_sig2 & MBIT(0))
+					rth->body.u.vht.flags |= VHT_FLAG_SGI;
+		/** SGI NSYM DIS */
+				rth->body.u.vht.known |=
+					cpu_to_le16(VHT_KNOWN_SGI_NSYM_DIS);
+				if (vht_sig2 & MBIT(1))
+					rth->body.u.vht.flags |=
+						VHT_FLAG_SGI_NSYM_M10_9;
+		/** LDPC_EXTRA_OFDM_SYM */
+		/** TODO: Not support now */
+		/** BEAMFORMED */
+				rth->body.u.vht.known |=
+					cpu_to_le16(VHT_KNOWN_BEAMFORMED);
+				if (vht_sig2 & MBIT(8))
+					rth->body.u.vht.flags |=
+						VHT_FLAG_BEAMFORMED;
+		/** BANDWIDTH */
+				rth->body.u.vht.known |=
+					cpu_to_le16(VHT_KNOWN_BANDWIDTH);
+				if (bw == 1)
+					rth->body.u.vht.bandwidth = RX_BW_40;
+				else if (bw == 2)
+					rth->body.u.vht.bandwidth = RX_BW_80;
+		/** GROUP_ID */
+				rth->body.u.vht.known |=
+					cpu_to_le16(VHT_KNOWN_GROUP_ID);
+				rth->body.u.vht.group_id =
+					(vht_sig1 & (0x3F0)) >> 4;
+		/** PARTIAL_AID */
+		/** TODO: Not support now */
+		/** mcs_nss */
+				rth->body.u.vht.mcs_nss[0] =
+					(vht_sig2 & (0xF0)) >> 4;
+				rth->body.u.vht.mcs_nss[0] |=
+					(vht_sig1 & (0x1C00)) >> (10 - 4);
+		/** coding */
+				if (vht_sig2 & MBIT(2))
+					rth->body.u.vht.coding |=
+						VHT_CODING_LDPC_USER0;
+			}
+		}
+		skb_set_mac_header(skb, 0);
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		skb->pkt_type = PACKET_OTHERHOST;
+		skb->protocol = htons(ETH_P_802_2);
+		memset(skb->cb, 0, sizeof(skb->cb));
+		skb->dev = handle->mon_if->mon_ndev;
+
+		handle->mon_if->stats.rx_bytes += skb->len;
+		handle->mon_if->stats.rx_packets++;
+
+		if (in_interrupt())
+			netif_rx(skb);
+		else
+			netif_rx_ni(skb);
+
+		status = MLAN_STATUS_PENDING;
+	}
+
+done:
+
+	LEAVE();
+	return status;
+}
+#endif
+
+/**
+ *  @brief This function uploads the packet to the network stack
+ *
+ *  @param pmoal_handle 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(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+	struct sk_buff *skb = NULL;
+	moal_handle *handle = (moal_handle *)pmoal_handle;
+	dot11_rxcontrol rxcontrol;
+	t_u8 rx_info_flag = MFALSE;
+	int j;
+	ENTER();
+	if (pmbuf) {
+
+		priv = woal_bss_index_to_priv(pmoal_handle, pmbuf->bss_index);
+		skb = (struct sk_buff *)pmbuf->pdesc;
+		if (priv) {
+			if (skb) {
+				skb_reserve(skb, pmbuf->data_offset);
+				skb_put(skb, pmbuf->data_len);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+				if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
+					status = moal_recv_packet_to_mon_if
+						(pmoal_handle, pmbuf);
+					if (status == MLAN_STATUS_PENDING)
+						atomic_dec(&handle->
+							   mbufalloc_count);
+					goto done;
+				}
+#endif
+				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__);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		/** drop the packet without skb in monitor mode */
+				if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
+					PRINTM(MINFO,
+					       "%s Drop packet without skb\n",
+					       __func__);
+					status = MLAN_STATUS_FAILURE;
+					priv->stats.rx_dropped++;
+					goto done;
+				}
+#endif
+				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);
+				memcpy(skb->data,
+				       (t_u8 *)(pmbuf->pbuf +
+						pmbuf->data_offset),
+				       pmbuf->data_len);
+				skb_put(skb, pmbuf->data_len);
+
+			}
+			skb->dev = priv->netdev;
+			skb->protocol = eth_type_trans(skb, priv->netdev);
+			skb->ip_summed = CHECKSUM_NONE;
+
+#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 (wakelock_timeout) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+				__pm_wakeup_event(&handle->ws,
+						  wakelock_timeout);
+#else
+				wake_lock_timeout(&handle->wake_lock,
+						  msecs_to_jiffies
+						  (wakelock_timeout));
+#endif
+			}
+#endif
+			if (priv->rx_protocols.protocol_num) {
+				for (j = 0; j < priv->rx_protocols.protocol_num;
+				     j++) {
+					if (htons(skb->protocol) ==
+					    priv->rx_protocols.protocols[j])
+						rx_info_flag = MTRUE;
+				}
+			}
+			if (rx_info_flag &&
+			    (skb_tailroom(skb) > sizeof(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));
+				memcpy(skb->data, &rxcontrol,
+				       sizeof(dot11_rxcontrol));
+			}
+			if (in_interrupt())
+				netif_rx(skb);
+			else {
+				if (atomic_read(&handle->rx_pending) >
+				    MAX_RX_PENDING_THRHLD)
+					netif_rx(skb);
+				else
+					netif_rx_ni(skb);
+			}
+		}
+	}
+done:
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function handles event receive
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param pmevent  Pointer to the mlan event structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_recv_event(IN t_void *pmoal_handle, IN 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
+#if defined(SDIO_SUSPEND_RESUME)
+	mlan_ds_ps_info pm_info;
+#endif
+	char event[512] = { 0 };
+	t_u8 category = 0;
+	t_u8 action_code = 0;
+	char *buf;
+	t_u8 peer_addr[ETH_ALEN];
+	moal_wnm_tm_msmt *tm_ind;
+	moal_wlan_802_11_header *header;
+	moal_timestamps *tsstamp;
+	t_u8 payload_len, i;
+	moal_ptp_context *ptp_context;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	t_u8 enable = 1;
+#endif
+#endif
+	t_u8 *req_ie = NULL;
+	t_u16 ie_len = 0;
+	apinfo *pinfo = NULL, *req_tlv = NULL;
+	MrvlIEtypesHeader_t *tlv = NULL;
+	t_u16 tlv_type = 0, tlv_len = 0, tlv_buf_left = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+	struct cfg80211_roam_info roam_info;
+#endif
+
+	ENTER();
+
+	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 (pmevent->event_id == MLAN_EVENT_ID_FW_DUMP_INFO) {
+		woal_store_firmware_dump(pmoal_handle, pmevent);
+		goto done;
+	}
+	priv = woal_bss_index_to_priv(pmoal_handle, 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;
+	}
+	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);
+			memcpy(wrqu.ap_addr.sa_data, pmevent->event_buf,
+			       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)) {
+			memcpy(priv->cfg_bssid, pmevent->event_buf, 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);
+		memcpy(pmevent->event_buf, CUS_EVT_AP_CONNECTED, 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);
+
+		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) {
+						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 (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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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_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 */
+		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
+			woal_set_rssi_threshold(priv,
+						MLAN_EVENT_ID_FW_BCN_RSSI_LOW,
+						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_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_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
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+		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 (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 (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_state = MTRUE;
+		woal_moal_debug_info(priv, NULL, MFALSE);
+		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
+		woal_process_hang(priv->phandle);
+		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;
+				woal_get_scan_table(priv, MOAL_NO_WAIT,
+						    &scan_resp);
+				PRINTM(MIOCTL,
+				       "Trigger mlan get bgscan result\n");
+			}
+#endif
+#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) {
+				priv->phandle->rx_bgscan_stop = MTRUE;
+				priv->phandle->bg_scan_priv = priv;
+				queue_work(priv->phandle->rx_workqueue,
+					   &priv->phandle->rx_work);
+				PRINTM(MEVENT, "Sched_Scan stopped\n");
+			}
+		}
+#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);
+				cfg80211_sched_scan_results(priv->wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+							    ,
+							    priv->bg_scan_reqid
+#endif
+					);
+				priv->last_event = 0;
+				PRINTM(MEVENT,
+				       "Reporting Sched_Scan results\n");
+			}
+		}
+#endif
+#endif
+		break;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	case MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY:
+		if (priv->phandle->is_cac_timer_set) {
+			t_u8 radar_detected = pmevent->event_buf[0];
+			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;
+		}
+		break;
+	case MLAN_EVENT_ID_FW_RADAR_DETECTED:
+		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 {
+			PRINTM(MEVENT, "radar detected during BSS active \n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			if (dfs_offload)
+				woal_cfg80211_dfs_vendor_event(priv,
+							       event_dfs_radar_detected,
+							       &priv->chan);
+			else
+#endif
+				cfg80211_radar_event(priv->wdev->wiphy,
+						     &priv->chan, GFP_KERNEL);
+		}
+		break;
+#endif
+#endif
+	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;
+#endif /* STA_SUPPORT */
+	case MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE:
+#ifdef UAP_SUPPORT
+		if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
+#ifdef UAP_CFG80211
+			chan_band_info *pchan_info =
+				(chan_band_info *) pmevent->event_buf;
+			if (IS_UAP_CFG80211(cfg80211_wext)) {
+				PRINTM(MMSG,
+				       "CSA/ECSA: Switch to new channel %d complete!\n",
+				       pchan_info->channel);
+				priv->channel = pchan_info->channel;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,12,0)
+				if (priv->csa_chan.chan &&
+				    (pchan_info->channel ==
+				     priv->csa_chan.chan->hw_value)) {
+					memcpy(&priv->chan, &priv->csa_chan,
+					       sizeof(struct
+						      cfg80211_chan_def));
+				}
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,8,0)
+				if (priv->uap_host_based) {
+					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);
+					woal_cfg80211_notify_uap_channel(priv,
+									 pchan_info);
+				}
+#endif
+			}
+#endif
+		}
+		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_handle,
+				       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_handle,
+				       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_handle,
+				       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_handle,
+				       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
+#if defined(SDIO_SUSPEND_RESUME)
+		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_interruptible(&priv->phandle->
+					      hs_activate_wait_q);
+		}
+#endif
+		break;
+	case MLAN_EVENT_ID_DRV_HS_DEACTIVATED:
+#ifdef STA_SUPPORT
+		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
+				       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_handle,
+				       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
+#if defined(SDIO_SUSPEND_RESUME)
+		priv->phandle->hs_activated = MFALSE;
+#endif
+		break;
+#ifdef UAP_SUPPORT
+	case MLAN_EVENT_ID_UAP_FW_BSS_START:
+		if (priv->hist_data)
+			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);
+		memcpy(priv->current_addr, pmevent->event_buf + 6, ETH_ALEN);
+		memcpy(priv->netdev->dev_addr, priv->current_addr, 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_handle,
+				       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 defined(DFS_TESTING_SUPPORT)
+#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
+#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)) {
+			chan_band_info *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_cfg80211_notify_uap_channel(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);
+		break;
+	case MLAN_EVENT_ID_UAP_FW_BSS_IDLE:
+		priv->media_connected = MFALSE;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+		break;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	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);
+			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
+	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;
+			t_u8 addr[ETH_ALEN];
+
+			sinfo.filled = 0;
+			sinfo.generation = 0;
+			/* copy the station mac address */
+			memset(addr, 0xFF, ETH_ALEN);
+			memcpy(addr, pmevent->event_buf, 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
+				/* 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);
+		}
+#endif /* UAP_CFG80211 */
+		memmove((pmevent->event_buf + strlen(CUS_EVT_STA_CONNECTED) +
+			 1), pmevent->event_buf, pmevent->event_len);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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)
+			/* skip 2 bytes extra header will get the mac address */
+			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);
+		memcpy(pmevent->event_buf, (t_u8 *)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 = 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:
+		buf = (t_u8 *)(pmevent->event_buf + sizeof(pmevent->event_id));
+		payload_len =
+			pmevent->event_len - sizeof(pmevent->event_id) -
+			sizeof(moal_timestamps);
+		category = *(buf + sizeof(moal_wlan_802_11_header));
+		action_code = *(buf + sizeof(moal_wlan_802_11_header) + 1);
+		header = (moal_wlan_802_11_header *) (buf);
+		tm_ind = (moal_wnm_tm_msmt *) (buf +
+					       sizeof(moal_wlan_802_11_header) +
+					       2);
+		tsstamp = (moal_timestamps *) ((t_u8 *)buf + payload_len);
+		memcpy(peer_addr, (t_u8 *)&header->addr2, ETH_ALEN);
+		if ((category == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM) &&
+		    (action_code == 0x1)) {
+			sprintf(event,
+				"%s " FULL_MACSTR
+				" %u %u %u %u %u %u %u %u %u %u %lu %llu",
+				CUS_EVT_TM_FRAME_INDICATION,
+				FULL_MAC2STR(peer_addr), tm_ind->dialog_token,
+				tsstamp->t2, tsstamp->t2_err, tsstamp->t3,
+				tsstamp->t3_err, tm_ind->follow_up_dialog_token,
+				tm_ind->t1, tm_ind->t1_err, tm_ind->t4,
+				tm_ind->t4_err,
+				(unsigned long)tsstamp->t2 * 10L,
+				tsstamp->ingress_time);
+
+			if (payload_len >
+			    (sizeof(moal_wnm_tm_msmt) +
+			     sizeof(moal_wlan_802_11_header) + 2)) {
+				ptp_context =
+					(moal_ptp_context *) (buf +
+							      sizeof
+							      (moal_wlan_802_11_header)
+							      + 2 +
+							      sizeof
+							      (moal_wnm_tm_msmt));
+				sprintf(event + strlen(event), " %02x %02x",
+					ptp_context->vendor_specific,
+					ptp_context->length);
+				for (i = 0; i < ptp_context->length; i++)
+					sprintf(event + strlen(event), " %02x",
+						ptp_context->data[i]);
+			}
+			woal_broadcast_event(priv, event, strlen(event));
+		}
+#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, 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;
+				memcpy(&bss->param.ssid_bssid,
+				       &priv->phandle->delay_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 && 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:
+		{
+			unsigned long flag;
+			tx_status_event *tx_status =
+				(tx_status_event *)(pmevent->event_buf + 4);
+			struct tx_status_info *tx_info = NULL;
+			t_u8 catagory = 0, action = 0, dialog_token = 0;
+			t_u8 peer_addr[6];
+			confirm_timestamps tsbuff = { 0 };
+
+			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;
+				{
+					catagory =
+						((struct ieee80211_mgmt *)skb->
+						 data)->u.action.category;
+					action = *(&
+						   ((struct ieee80211_mgmt *)
+						    skb->data)->u.action.
+						   category + 1);
+					dialog_token = *(&((struct ieee80211_mgmt *)skb->data)->u.action.category + 2);	//dt is 2 bytes after category
+					memcpy(peer_addr,
+					       (t_u8
+						*)((struct ieee80211_mgmt *)
+						   skb->data)->da, 6);
+					PRINTM(MEVENT,
+					       "Wlan: Tx status=%d, cat = %d, act = %d, dt = %d\n",
+					       ack, catagory, action,
+					       dialog_token);
+					/* this is a tx done for timining measurement action frame
+					 * so we need to send the tx timestamp of txed frame back to supplicant
+					 * for this send the timestamps along with the tx_status event buffer */
+					if (catagory ==
+					    IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM
+					    && action == 0x1) {
+						/* create a timestamp buffer to send to host supplicant */
+
+						PRINTM(MEVENT,
+						       "Wlan: Tx t1=%lld, t4 = %lld, t1_error = %lld, t4_error=%lld\n",
+						       tx_status->t1_tstamp,
+						       tx_status->t4_tstamp,
+						       tx_status->t1_error,
+						       tx_status->t4_error);
+
+						/* for timestamps only use lower 32-bits as spec defines 11v timestamps as 32-bits */
+						tsbuff.t4 =
+							(u32)
+							woal_le32_to_cpu
+							(tx_status->t4_tstamp);
+						tsbuff.t1 =
+							(u32)
+							woal_le32_to_cpu
+							(tx_status->t1_tstamp);
+						tsbuff.t4_error =
+							(u8)tx_status->t4_error;
+						tsbuff.t1_error =
+							(u8)tx_status->t4_error;
+						tsbuff.egress_time =
+							(u64)
+							woal_le64_to_cpu
+							(tx_status->
+							 egress_time);
+
+						if (skb_tailroom(skb) <
+						    sizeof(confirm_timestamps))
+						{
+							struct sk_buff *new_skb
+								= NULL;
+							PRINTM(MWARN,
+							       "Tx Status: Insufficient skb tailroom %d\n",
+							       skb_tailroom
+							       (skb));
+							/* Insufficient skb tailroom - allocate a new skb */
+							new_skb =
+								skb_copy_expand
+								(skb, 0,
+								 sizeof
+								 (confirm_timestamps),
+								 GFP_ATOMIC);
+							if (unlikely(!new_skb)) {
+								PRINTM(MERROR,
+								       "Tx Status: Cannot allocate skb\n");
+								dev_kfree_skb_any
+									(skb);
+								goto done;
+							}
+							skb = new_skb;
+							PRINTM(MINFO,
+							       "new skb tailroom %d\n",
+							       skb_tailroom
+							       (skb));
+						}
+						if (tx_info->tx_cookie) {
+							memcpy(skb_put
+							       (skb,
+								sizeof
+								(confirm_timestamps)),
+							       &tsbuff,
+							       sizeof
+							       (confirm_timestamps));
+						} else {
+							sprintf(event,
+								"%s "
+								FULL_MACSTR
+								" %u %u %u %u %u %u %llu",
+								CUS_EVT_TIMING_MSMT_CONFIRM,
+								FULL_MAC2STR
+								(peer_addr),
+								dialog_token,
+								tsbuff.t1,
+								tsbuff.t1_error,
+								tsbuff.t4,
+								tsbuff.t4_error,
+								tsbuff.t1 * 10,
+								tsbuff.
+								egress_time);
+							woal_broadcast_event
+								(priv, event,
+								 sizeof(event));
+						}
+					}
+				}
+#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);
+		}
+		break;
+
+	case MLAN_EVENT_ID_DRV_FT_RESPONSE:
+		if (priv->phandle->fw_roam_enable)
+			break;
+#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);
+			memcpy(priv->target_ap_bssid, pmevent->event_buf,
+			       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;
+	case MLAN_EVENT_ID_FW_ROAM_OFFLOAD_RESULT:
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		woal_cfg80211_vendor_event(priv, event_set_key_mgmt_offload,
+					   &enable, sizeof(enable));
+#endif
+#endif
+		memcpy(priv->cfg_bssid, pmevent->event_buf, ETH_ALEN);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)pmevent->event_buf +
+					      MLAN_MAC_ADDR_LENGTH);
+		tlv_buf_left = pmevent->event_len - MLAN_MAC_ADDR_LENGTH;
+		while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+			tlv_type = woal_le16_to_cpu(tlv->type);
+			tlv_len = woal_le16_to_cpu(tlv->len);
+
+			if (tlv_buf_left <
+			    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+				PRINTM(MERROR,
+				       "Error processing firmware roam success TLVs, bytes left < TLV length\n");
+				break;
+			}
+
+			switch (tlv_type) {
+			case TLV_TYPE_APINFO:
+				pinfo = (apinfo *) tlv;
+				break;
+			case TLV_TYPE_ASSOC_REQ_IE:
+				req_tlv = (apinfo *) tlv;
+				break;
+			default:
+				break;
+			}
+			tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+			tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+						      sizeof
+						      (MrvlIEtypesHeader_t));
+		}
+		if (!pinfo) {
+			PRINTM(MERROR,
+			       "ERROR:AP info in roaming event buffer is NULL\n");
+			goto done;
+		}
+		if (req_tlv) {
+			req_ie = req_tlv->rsp_ie;
+			ie_len = req_tlv->header.len;
+		}
+
+		woal_inform_bss_from_scan_result(priv, NULL, MOAL_NO_WAIT);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+		memset(&roam_info, 0, sizeof(struct cfg80211_roam_info));
+		roam_info.bssid = priv->cfg_bssid;
+		roam_info.req_ie = req_ie;
+		roam_info.req_ie_len = ie_len;
+		roam_info.resp_ie = pinfo->rsp_ie;
+		roam_info.resp_ie_len = pinfo->header.len;
+		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, req_ie,
+				ie_len, pinfo->rsp_ie, pinfo->header.len,
+				GFP_KERNEL);
+#else
+		cfg80211_roamed(priv->netdev, priv->cfg_bssid, req_ie, ie_len,
+				pinfo->rsp_ie, pinfo->header.len, GFP_KERNEL);
+#endif
+#endif
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		woal_roam_ap_info(priv, pmevent->event_buf, pmevent->event_len);
+#endif
+#endif
+		PRINTM(MMSG, "FW Roamed to bssid " MACSTR " successfully\n",
+		       MAC2STR(priv->cfg_bssid));
+		break;
+	case MLAN_EVENT_ID_DRV_RTT_RESULT:
+		DBG_HEXDUMP(MEVT_D, "RTT result", pmevent->event_buf,
+			    pmevent->event_len);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext))
+			woal_cfg80211_event_rtt_result(priv, pmevent->event_buf,
+						       pmevent->event_len);
+#endif
+#endif
+		break;
+	default:
+		break;
+	}
+done:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prints the debug message in mlan
+ *
+ *  @param pmoal_handle Pointer to the MOAL context
+ *  @param level    debug level
+ *  @param pformat  point to string format buf
+ *
+ *  @return         N/A
+ */
+t_void
+moal_print(IN t_void *pmoal_handle, IN t_u32 level, IN 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_handle Pointer to the MOAL context
+ *  @param bss_index    BSS index
+ *  @param level        debug level
+ *
+ *  @return            N/A
+ */
+t_void
+moal_print_netintf(IN t_void *pmoal_handle, IN t_u32 bss_index, IN t_u32 level)
+{
+#ifdef DEBUG_LEVEL1
+	moal_handle *phandle = (moal_handle *)pmoal_handle;
+
+	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_handle     A pointer to moal_private structure
+ *  @param cond             Condition to check
+ *
+ *  @return                 N/A
+ */
+t_void
+moal_assert(IN t_void *pmoal_handle, IN t_u32 cond)
+{
+	if (!cond) {
+		panic("Assert failed: Panic!");
+	}
+}
+
+/**
+ *  @brief This function save the histogram data
+ *
+ *  @param pmoal_handle     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(IN t_void *pmoal_handle, IN t_u32 bss_index, IN t_u8 rx_rate,
+		   IN t_s8 snr, IN t_s8 nflr, IN t_u8 antenna)
+{
+	moal_private *priv = NULL;
+	priv = woal_bss_index_to_priv(pmoal_handle, bss_index);
+	if (priv && antenna >= priv->phandle->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_handle     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(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			IN t_u8 *peer_addr, IN t_s8 snr, IN t_s8 nflr)
+{
+	moal_private *priv = NULL;
+	struct tdls_peer *peer = NULL;
+	unsigned long flags;
+	priv = woal_bss_index_to_priv(pmoal_handle, 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 This function records host time in nano seconds
+*
+*  @return                 64 bit value of host time in nano seconds
+*/
+s64
+get_host_time_ns(void)
+{
+	struct timespec ts;
+	getnstimeofday(&ts);
+	return timespec_to_ns(&ts);
+}
+
+/**
+ *  @brief Retrieves the current system time
+ *
+ *  @param time     Pointer for the seconds of system time
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_get_host_time_ns(OUT t_u64 *time)
+{
+	struct timespec ts;
+	t_u64 hclk_val;
+
+	getnstimeofday(&ts);
+	hclk_val = (ts.tv_sec * 1000000000L) + ts.tv_nsec;
+	*time = hclk_val;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @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(IN t_u64 num, IN t_u32 base)
+{
+	t_u64 val = num;
+	do_div(val, base);
+	return val;
+}
diff --git a/wlan_sd8997/mlinux/moal_shim.h b/wlan_sd8997/mlinux/moal_shim.h
new file mode 100644
index 0000000..e090714
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_shim.h
@@ -0,0 +1,111 @@
+/** @file moal_shim.h
+  *
+  * @brief This file contains declaration referring to
+  * functions defined in moal module
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change Log:
+    10/21/2008: initial version
+************************************************************/
+
+#ifndef _MOAL_H
+#define _MOAL_H
+
+mlan_status moal_get_fw_data(IN t_void *pmoal_handle,
+			     IN t_u32 offset, IN t_u32 len, OUT t_u8 *pbuf);
+mlan_status moal_get_hw_spec_complete(IN t_void *pmoal_handle,
+				      IN mlan_status status,
+				      IN mlan_hw_info * phw,
+				      IN pmlan_bss_tbl ptbl);
+mlan_status moal_init_fw_complete(IN t_void *pmoal_handle,
+				  IN mlan_status status);
+mlan_status moal_shutdown_fw_complete(IN t_void *pmoal_handle,
+				      IN mlan_status status);
+mlan_status moal_ioctl_complete(IN t_void *pmoal_handle,
+				IN pmlan_ioctl_req pioctl_req,
+				IN mlan_status status);
+mlan_status moal_alloc_mlan_buffer(IN t_void *pmoal_handle, IN t_u32 size,
+				   OUT pmlan_buffer *pmbuf);
+mlan_status moal_free_mlan_buffer(IN t_void *pmoal_handle,
+				  IN pmlan_buffer pmbuf);
+mlan_status moal_send_packet_complete(IN t_void *pmoal_handle,
+				      IN pmlan_buffer pmbuf,
+				      IN mlan_status status);
+
+/** moal_write_reg */
+mlan_status moal_write_reg(IN t_void *pmoal_handle,
+			   IN t_u32 reg, IN t_u32 data);
+/** moal_read_reg */
+mlan_status moal_read_reg(IN t_void *pmoal_handle,
+			  IN t_u32 reg, OUT t_u32 *data);
+mlan_status moal_write_data_sync(IN t_void *pmoal_handle,
+				 IN pmlan_buffer pmbuf,
+				 IN t_u32 port, IN t_u32 timeout);
+mlan_status moal_read_data_sync(IN t_void *pmoal_handle,
+				IN OUT pmlan_buffer pmbuf,
+				IN t_u32 port, IN t_u32 timeout);
+mlan_status moal_recv_packet(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf);
+mlan_status moal_recv_event(IN t_void *pmoal_handle, IN pmlan_event pmevent);
+mlan_status moal_malloc(IN t_void *pmoal_handle,
+			IN t_u32 size, IN t_u32 flag, OUT t_u8 **ppbuf);
+mlan_status moal_mfree(IN t_void *pmoal_handle, IN t_u8 *pbuf);
+mlan_status moal_vmalloc(IN t_void *pmoal_handle,
+			 IN t_u32 size, OUT t_u8 **ppbuf);
+mlan_status moal_vfree(IN t_void *pmoal_handle, IN t_u8 *pbuf);
+t_void *moal_memset(IN t_void *pmoal_handle,
+		    IN t_void *pmem, IN t_u8 byte, IN t_u32 num);
+t_void *moal_memcpy(IN t_void *pmoal_handle,
+		    IN t_void *pdest, IN const t_void *psrc, IN t_u32 num);
+t_void *moal_memmove(IN t_void *pmoal_handle,
+		     IN t_void *pdest, IN const t_void *psrc, IN t_u32 num);
+t_s32 moal_memcmp(IN t_void *pmoal_handle,
+		  IN const t_void *pmem1, IN const t_void *pmem2, IN t_u32 num);
+/** moal_udelay */
+t_void moal_udelay(IN t_void *pmoal_handle, IN t_u32 udelay);
+mlan_status moal_get_system_time(IN t_void *pmoal_handle, OUT t_u32 *psec,
+				 OUT t_u32 *pusec);
+mlan_status moal_init_lock(IN t_void *pmoal_handle, OUT t_void **pplock);
+mlan_status moal_free_lock(IN t_void *pmoal_handle, IN t_void *plock);
+mlan_status moal_spin_lock(IN t_void *pmoal_handle, IN t_void *plock);
+mlan_status moal_spin_unlock(IN t_void *pmoal_handle, IN t_void *plock);
+t_void moal_print(IN t_void *pmoal_handle, IN t_u32 level, IN char *pformat,
+		  IN ...);
+t_void moal_print_netintf(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			  IN t_u32 level);
+t_void moal_assert(IN t_void *pmoal_handle, IN t_u32 cond);
+t_void moal_hist_data_add(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			  IN t_u8 rx_rate, IN t_s8 snr, IN t_s8 nflr,
+			  IN t_u8 antenna);
+
+t_void moal_updata_peer_signal(IN t_void *pmoal_handle, IN t_u32 bss_index,
+			       IN t_u8 *peer_addr, IN t_s8 snr, IN t_s8 nflr);
+mlan_status moal_get_host_time_ns(OUT t_u64 *time);
+t_u64 moal_do_div(IN t_u64 num, IN t_u32 base);
+
+mlan_status moal_init_timer(IN t_void *pmoal_handle,
+			    OUT t_void **pptimer,
+			    IN t_void (*callback) (t_void *pcontext),
+			    IN t_void *pcontext);
+mlan_status moal_free_timer(IN t_void *pmoal_handle, IN t_void *ptimer);
+mlan_status moal_start_timer(IN t_void *pmoal_handle,
+			     IN t_void *ptimer,
+			     IN t_u8 periodic, IN t_u32 msec);
+mlan_status moal_stop_timer(IN t_void *pmoal_handle, IN t_void *ptimer);
+
+#endif /*_MOAL_H */
diff --git a/wlan_sd8997/mlinux/moal_sta_cfg80211.c b/wlan_sd8997/mlinux/moal_sta_cfg80211.c
new file mode 100644
index 0000000..186ebf9
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_sta_cfg80211.c
@@ -0,0 +1,6808 @@
+/** @file moal_sta_cfg80211.c
+  *
+  * @brief This file contains the functions for STA CFG80211.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include "moal_cfg80211.h"
+#include "moal_cfgvendor.h"
+#include "moal_sta_cfg80211.h"
+#include "moal_eth_ioctl.h"
+#ifdef UAP_SUPPORT
+#include    "moal_uap.h"
+#endif
+
+extern int cfg80211_wext;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int fw_region;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+
+extern int cntry_txpwr;
+
+/* Supported crypto cipher suits to be advertised to cfg80211 */
+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(3, 8, 0)
+static int woal_cfg80211_set_monitor_channel(struct wiphy *wiphy,
+					     struct cfg80211_chan_def *chandef);
+#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 t_u8 *mac,
+#else
+				     t_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
+
+static int woal_cfg80211_join_ibss(struct wiphy *wiphy,
+				   struct net_device *dev,
+				   struct cfg80211_ibss_params *params);
+
+static int woal_cfg80211_leave_ibss(struct wiphy *wiphy,
+				    struct net_device *dev);
+
+#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 */
+
+#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);
+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);
+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);
+#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,10,0)
+int woal_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev,
+				struct cfg80211_update_ft_ies_params *ftie);
+#endif
+/** 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,
+	.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
+	.join_ibss = woal_cfg80211_join_ibss,
+	.leave_ibss = woal_cfg80211_leave_ibss,
+	.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(3, 1, 0)
+	.set_rekey_data = woal_cfg80211_set_rekey_data,
+#endif
+	.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,
+	.add_station = woal_cfg80211_add_station,
+	.change_station = woal_cfg80211_change_station,
+#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,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
+		.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
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+		.mgmt_frame_register =
+		woal_cfg80211_mgmt_frame_register,.mgmt_tx =
+		woal_cfg80211_mgmt_tx,
+#endif
+#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
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		.set_monitor_channel = woal_cfg80211_set_monitor_channel,
+#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),}
+};
+
+/********************************************************
+				Local Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static const struct ieee80211_txrx_stypes
+ ieee80211_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+	[NL80211_IFTYPE_ADHOC] = {
+				  .tx = BIT(IEEE80211_STYPE_ACTION >> 4),
+				  .rx = BIT(IEEE80211_STYPE_ACTION >> 4),
+				  },
+	[NL80211_IFTYPE_STATION] = {
+				    .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				    BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				    .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				    BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+				    },
+	[NL80211_IFTYPE_AP] = {
+			       .tx = 0xffff,
+			       .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+			       BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+			       BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+			       BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+			       BIT(IEEE80211_STYPE_AUTH >> 4) |
+			       BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+			       BIT(IEEE80211_STYPE_ACTION >> 4),
+			       },
+	[NL80211_IFTYPE_AP_VLAN] = {
+				    .tx = 0x0000,
+				    .rx = 0x0000,
+				    },
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	[NL80211_IFTYPE_P2P_CLIENT] = {
+				       .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				       BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				       .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				       BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+				       },
+	[NL80211_IFTYPE_P2P_GO] = {
+				   .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+				   BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				   .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+				   BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+				   BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+				   BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+				   BIT(IEEE80211_STYPE_AUTH >> 4) |
+				   BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+				   BIT(IEEE80211_STYPE_ACTION >> 4),
+				   },
+#endif
+#endif
+	[NL80211_IFTYPE_MESH_POINT] = {
+				       .tx = 0x0000,
+				       .rx = 0x0000,
+				       },
+
+};
+#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) | MBIT(NL80211_IFTYPE_MONITOR) |
+#endif
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	 MBIT(NL80211_IFTYPE_P2P_GO) | MBIT(NL80211_IFTYPE_P2P_CLIENT) |
+#endif
+#endif
+	 MBIT(NL80211_IFTYPE_ADHOC)
+	 }
+};
+
+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 moal_handle *m_handle[];
+extern int hw_test;
+extern int ps_mode;
+/** Region alpha2 string */
+char *reg_alpha2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+int country_ie_ignore = 0;
+int beacon_hints = 0;
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+extern int p2p_enh;
+#endif
+#endif
+
+int cfg80211_drcs = 0;
+
+#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
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int
+woal_cfg80211_set_monitor_channel(struct wiphy *wiphy,
+				  struct cfg80211_chan_def *chandef)
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv =
+		(moal_private *)woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+	netmon_band_chan_cfg band_chan_cfg;
+	t_u32 bandwidth = 0;
+	int ret = -EFAULT;
+
+	ENTER();
+
+	if (handle->mon_if) {
+		if (cfg80211_chandef_identical
+		    (&handle->mon_if->chandef, chandef)) {
+			ret = 0;
+			goto done;
+		}
+		if (woal_is_any_interface_active(handle)) {
+			PRINTM(MERROR,
+			       "Cannot change monitor channel for an active"
+			       " interface\n");
+			goto done;
+		}
+		memset(&band_chan_cfg, 0x00, sizeof(band_chan_cfg));
+		/* Set channel */
+		band_chan_cfg.channel =
+			ieee80211_frequency_to_channel(chandef->chan->
+						       center_freq);
+		/* Set band */
+		if (chandef->chan->band == IEEE80211_BAND_2GHZ)
+			band_chan_cfg.band |= (BAND_B | BAND_G);
+		if (chandef->chan->band == IEEE80211_BAND_5GHZ)
+			band_chan_cfg.band |= BAND_A;
+		if (chandef->chan->band == IEEE80211_BAND_2GHZ)
+			band_chan_cfg.band |= BAND_GN;
+		if (chandef->chan->band == IEEE80211_BAND_5GHZ)
+			band_chan_cfg.band |= BAND_AN;
+		if (chandef->chan->band == IEEE80211_BAND_2GHZ)
+			band_chan_cfg.band |= BAND_GAC;
+		if (chandef->chan->band == IEEE80211_BAND_5GHZ)
+			band_chan_cfg.band |= BAND_AAC;
+		/* Set bandwidth */
+		if (chandef->width == NL80211_CHAN_WIDTH_20)
+			bandwidth = CHANNEL_BW_20MHZ;
+		else if (chandef->width == NL80211_CHAN_WIDTH_40)
+			bandwidth =
+				chandef->center_freq1 >
+				chandef->chan->
+				center_freq ? CHANNEL_BW_40MHZ_ABOVE :
+				CHANNEL_BW_40MHZ_BELOW;
+		else if (chandef->width == NL80211_CHAN_WIDTH_80)
+			bandwidth = CHANNEL_BW_80MHZ;
+		band_chan_cfg.chan_bandwidth = bandwidth;
+
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_net_monitor(priv, MOAL_IOCTL_WAIT, MTRUE, 0x7,
+					 &band_chan_cfg)) {
+			PRINTM(MERROR, "%s: woal_set_net_monitor fail\n",
+			       __func__);
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memcpy(&handle->mon_if->band_chan_cfg, &band_chan_cfg,
+		       sizeof(handle->mon_if->band_chan_cfg));
+		handle->mon_if->chandef = *chandef;
+
+		if (handle->mon_if->chandef.chan)
+			PRINTM(MINFO,
+			       "set_monitor_channel+++ chan[band=%d center_freq=%d hw_value=%d] width=%d center_freq1=%d center_freq2=%d\n",
+			       handle->mon_if->chandef.chan->band,
+			       handle->mon_if->chandef.chan->center_freq,
+			       handle->mon_if->chandef.chan->hw_value,
+			       handle->mon_if->chandef.width,
+			       handle->mon_if->chandef.center_freq1,
+			       handle->mon_if->chandef.center_freq2);
+		PRINTM(MINFO,
+		       "set_monitor_channel+++ band=%x channel=%d bandwidth=%d\n",
+		       handle->mon_if->band_chan_cfg.band,
+		       handle->mon_if->band_chan_cfg.channel,
+		       handle->mon_if->band_chan_cfg.chan_bandwidth);
+		ret = 0;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function check cfg80211 special region code.
+ *
+ *  @param region_string         Region string
+ *
+ *  @return     MTRUE/MFALSE
+ */
+t_u8
+is_cfg80211_special_region_code(char *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;
+	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 NL802.11 channel type into driver channel type
+ *
+ * The mapping is as follows -
+ *      NL80211_CHAN_NO_HT     -> CHANNEL_BW_20MHZ
+ *      NL80211_CHAN_HT20      -> CHANNEL_BW_20MHZ
+ *      NL80211_CHAN_HT40PLUS  -> CHANNEL_BW_40MHZ_ABOVE
+ *      NL80211_CHAN_HT40MINUS -> CHANNEL_BW_40MHZ_BELOW
+ *      Others                 -> CHANNEL_BW_20MHZ
+ *
+ *  @param channel_type     Channel type
+ *
+ *  @return                 Driver channel type
+ */
+static int
+woal_cfg80211_channel_type_to_channel(enum nl80211_channel_type channel_type)
+{
+	int channel;
+
+	ENTER();
+
+	switch (channel_type) {
+	case NL80211_CHAN_NO_HT:
+	case NL80211_CHAN_HT20:
+		channel = CHANNEL_BW_20MHZ;
+		break;
+	case NL80211_CHAN_HT40PLUS:
+		channel = CHANNEL_BW_40MHZ_ABOVE;
+		break;
+	case NL80211_CHAN_HT40MINUS:
+		channel = CHANNEL_BW_40MHZ_BELOW;
+		break;
+	default:
+		channel = CHANNEL_BW_20MHZ;
+	}
+	LEAVE();
+	return channel;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ *  @brief get nl80211_channel_type from cfg80211_chan_def
+ *
+ *  @param chan_def     struct cfg80211_chan_def
+ *
+ *  @return                 nl80211_channel_type type
+ */
+static enum nl80211_channel_type
+woal_channel_to_nl80211_channel_type(struct cfg80211_chan_def *chan_def)
+{
+	enum nl80211_channel_type channel_type = 0;
+
+	ENTER();
+
+	switch (chan_def->width) {
+	case NL80211_CHAN_WIDTH_20:
+		/** Channel width 20MHz**/
+		channel_type = NL80211_CHAN_HT20;
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		/** Channel width 40MHz**/
+		if (chan_def->center_freq1 < chan_def->chan->center_freq)
+			channel_type = NL80211_CHAN_HT40MINUS;
+		else if (chan_def->center_freq1 > chan_def->chan->center_freq)
+			channel_type = NL80211_CHAN_HT40PLUS;
+		break;
+	default:
+		channel_type = NL80211_CHAN_HT20;
+		break;
+	}
+	LEAVE();
+	return channel_type;
+}
+#endif
+
+/**
+ *  @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_ADHOC:
+		return MLAN_BSS_MODE_IBSS;
+	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 };
+
+	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 (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;
+		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;
+}
+
+/**
+ * @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;
+	}
+
+	if (MTRUE ==
+	    is_cfg80211_special_region_code(priv->phandle->country_code)) {
+		PRINTM(MIOCTL,
+		       "skip region code config, cfg80211 special region code: %s\n",
+		       priv->phandle->country_code);
+		goto done;
+	}
+	PRINTM(MIOCTL, "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;
+
+	/* 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;
+
+	/* 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;
+	int chan_width = 0;
+
+	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;
+	chan_width = woal_cfg80211_channel_type_to_channel(channel_type);
+	/* 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);
+	}
+	/* Set channel offset */
+	radio_cfg->param.band_cfg.adhoc_chan_bandwidth = chan_width;
+
+	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, channel bandwidth %d and mode = %d channel=%d\n",
+	       config_bands, radio_cfg->param.band_cfg.adhoc_chan_bandwidth,
+	       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
+ */
+mlan_status
+woal_set_ewpa_mode(moal_private *priv, t_u8 wait_option,
+		   mlan_ssid_bssid *ssid_bssid)
+{
+	int ret = 0;
+	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) {
+		ret = -ENOMEM;
+		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));
+	memcpy(&sec->param.passphrase.ssid, &ssid_bssid->ssid,
+	       sizeof(sec->param.passphrase.ssid));
+	memcpy(&sec->param.passphrase.bssid, &ssid_bssid->bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+	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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	struct timespec tstamp;
+#endif
+	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 < 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 CFG80211_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. */
+			get_monotonic_boottime(&tstamp);
+			ts = (t_u64)tstamp.tv_sec * 1000000 +
+				tstamp.tv_nsec / 1000;
+#else
+			memcpy(&ts, scan_table[i].time_stamp, sizeof(ts));
+#endif
+			memcpy(&cap_info, &scan_table[i].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;
+
+	memcpy(&ie_buf[sizeof(IEEEtypes_Header_t)],
+	       &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
+	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();
+	country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
+	if (!country_ie) {
+		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) {
+		PRINTM(MIOCTL, "Wrong Country IE length!\n");
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		LEAVE();
+		return 0;
+	}
+	PRINTM(MIOCTL, "Find bss country IE: %c%c band=%d\n", country_ie[2],
+	       country_ie[3], priv->phandle->band);
+	priv->phandle->country_code[0] = country_ie[2];
+	priv->phandle->country_code[1] = country_ie[3];
+	priv->phandle->country_code[2] = ' ';
+	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) {
+		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)));
+	memcpy((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));
+
+	/* 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
+ */
+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));
+	memcpy(scan_req.ssid_list[0].ssid, conn_param->ssid,
+	       conn_param->ssid_len);
+	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 |
+			     IEEE80211_CHAN_RADAR))
+			scan_req.chan_list[0].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE;
+		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 |
+					     IEEE80211_CHAN_RADAR))
+					scan_req.chan_list[chan_idx].scan_type =
+						MLAN_SCAN_TYPE_PASSIVE;
+				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++;
+			}
+		}
+	}
+	memcpy(scan_req.random_mac, priv->random_mac, ETH_ALEN);
+	ret = woal_request_userscan(priv, wait_option, &scan_req);
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+	LEAVE();
+	return ret;
+
+}
+
+/**
+ * @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
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_assoc(moal_private *priv, void *sme, t_u8 wait_option)
+{
+	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;
+	enum nl80211_channel_type chan_type = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	struct cfg80211_chan_def *chan_def = NULL;
+#endif
+	struct ieee80211_channel *channel = NULL;
+	t_u16 beacon_interval = 0;
+	bool privacy;
+	struct cfg80211_bss *bss = 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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+		chan_type = ibss_param->channel_type;
+#else
+		chan_type = 0;
+#endif
+#else
+		chan_def = &ibss_param->chandef;
+		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;
+		bss = cfg80211_get_bss(priv->wdev->wiphy, channel, bssid, ssid,
+				       ssid_len, WLAN_CAPABILITY_ESS,
+				       WLAN_CAPABILITY_ESS);
+		if (bss) {
+			if (!reg_alpha2 ||
+			    strncmp(reg_alpha2, "99", strlen("99")))
+				woal_process_country_ie(priv, bss);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+			cfg80211_put_bss(priv->wdev->wiphy, bss);
+#else
+			cfg80211_put_bss(bss);
+#endif
+		} else
+			woal_send_domain_info_cmd_fw(priv, wait_option);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(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;
+	}
+
+	memcpy(req_ssid.ssid, ssid, ssid_len);
+	if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
+		PRINTM(MERROR, "Invalid SSID - aborting\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if ((mode == MLAN_BSS_MODE_IBSS) && channel) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		chan_type = woal_channel_to_nl80211_channel_type(chan_def);
+#endif
+		if (MLAN_STATUS_SUCCESS != woal_set_rf_channel(priv,
+							       channel,
+							       chan_type,
+							       wait_option)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	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;
+	}
+
+	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;
+		}
+	}
+	memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(mlan_802_11_ssid));
+	if (bssid)
+		memcpy(&ssid_bssid.bssid, bssid, ETH_ALEN);
+	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;
+		PRINTM(MCMND, "channel flags=0x%x\n", channel->flags);
+	}
+	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;
+		}
+	}
+
+done:
+	if (ret) {
+		/* clear the encryption mode */
+		woal_cfg80211_set_auth(priv, MLAN_ENCRYPTION_MODE_NONE, MFALSE,
+				       wait_option);
+		/* 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 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;
+	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
+	};
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	mlan_bss_info bss_info;
+	t_u8 dtim_period = 0;
+#endif
+
+	ENTER();
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	sinfo->filled =
+		BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES)
+		| BIT(NL80211_STA_INFO_RX_PACKETS) |
+		BIT(NL80211_STA_INFO_TX_PACKETS) | BIT(NL80211_STA_INFO_SIGNAL)
+		| BIT(NL80211_STA_INFO_TX_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 |= BIT(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;
+	}
+
+	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 (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;
+	}
+	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 |= BIT(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
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	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)
+{
+	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 (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", dfs_offload);
+}
+#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];
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+	int ret = 0;
+#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(MIOCTL, "cfg80211 regulatory domain callback "
+	       "%c%c\n", request->alpha2[0], request->alpha2[1]);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (dfs_offload)
+		woal_update_radar_chans_dfs_state(wiphy);
+#endif
+	memset(region, 0, sizeof(region));
+	memcpy(region, request->alpha2, sizeof(request->alpha2));
+	region[2] = ' ';
+	if (MTRUE == is_cfg80211_special_region_code(region)) {
+		PRINTM(MIOCTL, "Skip configure special region code\n");
+		LEAVE();
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+		return ret;
+#else
+		return;
+#endif
+	}
+	if ((handle->country_code[0] != request->alpha2[0]) ||
+	    (handle->country_code[1] != request->alpha2[1])) {
+		t_u8 country_code[COUNTRY_CODE_LEN];
+		memset(country_code, 0, sizeof(country_code));
+		country_code[0] = request->alpha2[0];
+		country_code[1] = request->alpha2[1];
+		if (cntry_txpwr) {
+			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
+			}
+		}
+	}
+	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(MIOCTL, "Regulatory domain BY_DRIVER\n");
+		break;
+	case NL80211_REGDOM_SET_BY_CORE:
+		PRINTM(MIOCTL, "Regulatory domain BY_CORE\n");
+		break;
+	case NL80211_REGDOM_SET_BY_USER:
+		PRINTM(MIOCTL, "Regulatory domain BY_USER\n");
+		break;
+		/* TODO: apply driver specific changes in channel flags based
+		   on the request initiator if necessory. * */
+	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+		PRINTM(MIOCTL, "Regulatory domain BY_COUNTRY_IE\n");
+		break;
+	}
+	if (priv->wdev && priv->wdev->wiphy &&
+	    (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE))
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+
+	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_IOCTL_WAIT or MOAL_NO_WAIT)
+ * @param bss_role      bss role
+ *
+ * @return         0 --success, otherwise fail
+ */
+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 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_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;
+
+	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);
+#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);
+	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;
+}
+
+/**
+ *  @brief check if the scan result expired
+ *
+ *  @param priv         A pointer to moal_private
+ *
+ *
+ *  @return             MTRUE/MFALSE;
+ */
+t_u8
+woal_is_scan_result_expired(moal_private *priv)
+{
+	mlan_scan_resp scan_resp;
+	struct timeval t;
+	ENTER();
+	if (!woal_is_any_interface_active(priv->phandle)) {
+		LEAVE();
+		return MTRUE;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
+		LEAVE();
+		return MTRUE;
+	}
+	do_gettimeofday(&t);
+/** scan result expired value */
+#define SCAN_RESULT_EXPIRTED      1
+	if (t.tv_sec > (scan_resp.age_in_secs + SCAN_RESULT_EXPIRTED)) {
+		LEAVE();
+		return MTRUE;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+#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;
+	mlan_bss_info bss_info;
+	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 (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
+	if (priv->fake_scan_complete || !woal_is_scan_result_expired(priv)) {
+		PRINTM(MEVENT, "Reporting fake scan results\n");
+		woal_inform_bss_from_scan_result(priv, NULL, MOAL_IOCTL_WAIT);
+		woal_cfg80211_scan_done(request, MFALSE);
+		return ret;
+	}
+	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");
+			woal_inform_bss_from_scan_result(priv, NULL,
+							 MOAL_IOCTL_WAIT);
+			woal_cfg80211_scan_done(request, MFALSE);
+			return ret;
+		}
+	}
+	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);
+	memset(&scan_req, 0x00, sizeof(scan_req));
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+	if (!is_broadcast_ether_addr(request->bssid)) {
+		memcpy(scan_req.specific_bssid, request->bssid, ETH_ALEN);
+		PRINTM(MIOCTL, "scan: bssid=" MACSTR "\n",
+		       MAC2STR(scan_req.specific_bssid));
+	}
+#endif
+
+	if (priv->phandle->scan_request->n_channels <= 38)
+		scan_req.ext_scan_type = EXT_SCAN_ENHANCE;
+
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->phandle->miracast_mode ||
+	    woal_is_any_interface_active(priv->phandle))
+		scan_req.scan_chan_gap = priv->phandle->scan_chan_gap;
+	else
+		scan_req.scan_chan_gap = 0;
+#endif
+	for (i = 0; i < priv->phandle->scan_request->n_ssids; i++) {
+		memcpy(scan_req.ssid_list[i].ssid,
+		       priv->phandle->scan_request->ssids[i].ssid,
+		       priv->phandle->scan_request->ssids[i].ssid_len);
+		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 < 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 |
+			      IEEE80211_CHAN_RADAR))
+		    || !priv->phandle->scan_request->n_ssids)
+			scan_req.chan_list[i].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE;
+		else
+			scan_req.chan_list[i].scan_type = MLAN_SCAN_TYPE_ACTIVE;
+#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))
+			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)
+			scan_req.chan_list[i].scan_time =
+				MIN_SPECIFIC_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) {
+			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];
+		}
+		memcpy(scan_req.random_mac, buf, ETH_ALEN);
+	} else
+#endif
+		memcpy(scan_req.random_mac, priv->random_mac, ETH_ALEN);
+
+	PRINTM(MCMND, "wlan:random_mac " MACSTR "\n",
+	       MAC2STR(scan_req.random_mac));
+	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);
+	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 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;
+	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);
+#ifdef UAP_CFG80211
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		LEAVE();
+		return 0;
+	}
+#endif
+	if (priv->wdev->iftype != NL80211_IFTYPE_STATION
+#if defined(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 && V14_FEATURE */
+		) {
+		PRINTM(MERROR,
+		       "Received infra assoc request when station not in infra mode\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	memset(&ssid_bssid, 0, sizeof(ssid_bssid));
+	memcpy(&ssid_bssid.ssid.ssid, sme->ssid, sme->ssid_len);
+	ssid_bssid.ssid.ssid_len = sme->ssid_len;
+	if (sme->bssid)
+		memcpy(&ssid_bssid.bssid, sme->bssid, ETH_ALEN);
+	/* 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);
+
+#if defined(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
+	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;
+	ret = woal_cfg80211_assoc(priv, (void *)sme, MOAL_IOCTL_WAIT);
+
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
+	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;
+		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: 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);
+		priv->ft_ie_len = 0;
+		priv->ft_pre_connect = MFALSE;
+		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);
+
+	}
+	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);
+	long start_time;
+
+	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
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_disconnect in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (priv->cfg_disconnect) {
+		PRINTM(MERROR, "Disassociation already in progress\n");
+		LEAVE();
+		return -EBUSY;
+	}
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MMSG, " Already disconnected\n");
+		LEAVE();
+		return 0;
+	}
+
+	if (priv->keep_connect) {
+		LEAVE();
+		return 0;
+	}
+
+	priv->cfg_disconnect = MTRUE;
+	start_time = jiffies;
+	if (woal_disconnect
+	    (priv, MOAL_IOCTL_WAIT_TIMEOUT, priv->cfg_bssid,
+	     reason_code) != MLAN_STATUS_SUCCESS) {
+		priv->cfg_disconnect = MFALSE;
+		LEAVE();
+		return -EFAULT;
+	}
+       /**Add delay to avoid auth failure after wps success */
+	if ((jiffies - start_time) < 1 * HZ)
+		woal_sched_timeout(1500);
+
+	priv->cfg_disconnect = MFALSE;
+
+#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);
+	priv->channel = 0;
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @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 t_u8 *mac,
+#else
+			  t_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;
+	}
+
+	memcpy(mac, priv->cfg_bssid, 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 bandcfg  Driver band configuration
+ *
+ *  @return         IEEE band type
+ */
+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 > scan_resp.num_in_chan_stats || idx < 0) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (idx == 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)
+/**
+ * @brief Function gets channel info from cfg80211
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param wdev            A pointer to wireless_dev structure
+ * @param chandef         A pointer to cfg80211_chan_def
+ *
+ * @return                0 -- success, otherwise fail
+ */
+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;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+
+	memset(&channel, 0x00, sizeof(channel));
+
+	if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
+		if ((handle->mon_if) &&
+		    (handle->mon_if->mon_ndev == wdev->netdev)) {
+			*chandef = handle->mon_if->chandef;
+			return 0;
+		}
+		return -EFAULT;
+	}
+#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(MERROR, "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(MINFO,
+			       "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 Join the specified
+ * IBSS (or create if necessary)
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params          A pointer to cfg80211_ibss_params structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+			struct cfg80211_ibss_params *params)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+
+	ENTER();
+
+	if (priv->wdev->iftype != NL80211_IFTYPE_ADHOC) {
+		PRINTM(MERROR,
+		       "Request IBSS join received when station not in ibss mode\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	ret = woal_cfg80211_assoc(priv, (void *)params, MOAL_IOCTL_WAIT);
+
+	if (!ret) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
+				     params->chandef.chan, GFP_KERNEL);
+#else
+		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
+#endif
+		PRINTM(MINFO, "Joined/created adhoc network with bssid"
+		       MACSTR " successfully\n", MAC2STR(priv->cfg_bssid));
+	} else {
+		PRINTM(MINFO, "Failed creating/joining adhoc network\n");
+		memset(priv->cfg_bssid, 0, ETH_ALEN);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to leave the IBSS
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+	if (priv->cfg_disconnect) {
+		PRINTM(MERROR, "IBSS leave already in progress\n");
+		LEAVE();
+		return -EBUSY;
+	}
+
+	if (priv->media_connected == MFALSE) {
+		LEAVE();
+		return -EINVAL;
+	}
+
+	priv->cfg_disconnect = 1;
+
+	PRINTM(MINFO, "Leaving from IBSS " MACSTR "\n",
+	       MAC2STR(priv->cfg_bssid));
+	if (woal_disconnect
+	    (priv, MOAL_IOCTL_WAIT, priv->cfg_bssid,
+	     DEF_DEAUTH_REASON_CODE) != MLAN_STATUS_SUCCESS) {
+		priv->cfg_disconnect = 0;
+		LEAVE();
+		return -EFAULT;
+	}
+	priv->cfg_disconnect = 0;
+	memset(priv->cfg_bssid, 0, ETH_ALEN);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @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 (hw_test || (ps_mode == MLAN_INIT_PARA_DISABLED)) {
+		PRINTM(MIOCTL, "block set power hw_test=%d ps_mode=%d\n",
+		       hw_test, ps_mode);
+		LEAVE();
+		return -EFAULT;
+	}
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_set_power_mgmt in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+#if defined(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 nl80211_channel_type channel_type,
+				    t_u32 duration)
+{
+	mlan_ds_remain_chan chan_cfg;
+	int ret = 0;
+
+	ENTER();
+
+	if (!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 NL80211_CHAN_HT40MINUS:
+			chan_cfg.bandcfg.chan2Offset = SEC_CHAN_BELOW;
+			break;
+		case NL80211_CHAN_HT40PLUS:
+			chan_cfg.bandcfg.chan2Offset = SEC_CHAN_ABOVE;
+			break;
+
+		case NL80211_CHAN_NO_HT:
+		case NL80211_CHAN_HT20:
+		default:
+			break;
+		}
+		chan_cfg.channel =
+			ieee80211_frequency_to_channel(chan->center_freq);
+		chan_cfg.remain_period = duration;
+	}
+	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 CFG80211_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
+	memcpy(&priv->phandle->chan, chan, sizeof(struct ieee80211_channel));
+
+	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 < 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)
+	/* only support 1 scan plan now */
+	if (request->scan_plans[0].interval > MIN_BGSCAN_INTERVAL)
+		priv->scan_cfg.scan_interval = request->scan_plans[0].interval;
+#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];
+		}
+		memcpy(priv->scan_cfg.random_mac, buf, ETH_ALEN);
+	} else
+#endif
+		memcpy(priv->scan_cfg.random_mac, priv->random_mac, ETH_ALEN);
+
+	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)) {
+		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(MIOCTL, "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_STA);
+#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");
+	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);
+					cfg80211_sched_scan_results(handle->
+								    priv[i]->
+								    wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+								    , 0
+#endif
+						);
+					handle->priv[i]->last_event = 0;
+					PRINTM(MIOCTL,
+					       "Report sched scan result in cfg80211 resume\n");
+				}
+			}
+		}
+	}
+
+	woal_get_wakeup_reason(priv, &wakeup_reason);
+
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (IS_STA_CFG80211(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->disconnect)
+			wakeup_report.disconnect = true;
+		break;
+	case MAGIC_PATTERN_MATCHED:
+		if (wiphy->wowlan_config->magic_pkt)
+			wakeup_report.magic_pkt = true;
+		if (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->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
+
+	handle->cfg80211_suspend = MFALSE;
+	PRINTM(MCMND, "<--- Leave woal_cfg80211_resume --->\n");
+	return 0;
+}
+
+/**
+ * @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;
+
+	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;
+
+	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;
+	memcpy(misc->param.tdls_oper.peer_mac, peer, ETH_ALEN);
+	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;
+	memcpy(misc->param.tdls_ies.peer_mac, peer, ETH_ALEN);
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (tdls_ies)
+		memcpy(tdls_ies, &misc->param.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(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));
+		memcpy(pos, tdls_ies->ext_cap, 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)
+		memcpy(pos, basic_rates, rate_num);
+	else
+		memcpy(pos, basic_rates_5G, 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;
+	memcpy(pos, ext_rates, 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 = 24;
+	t_u8 wmmInfoIe_len = 7;
+	t_u8 len = 0;
+	t_u8 *pos;
+
+	if (skb_tailroom(skb) < wmmParamIe_len + 2)
+		return;
+
+	qosInfo = (pQosInfo == NULL) ? 0xf : (*pQosInfo);
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		pos = skb_put(skb, wmmParamIe_len + 2);
+		len = wmmParamIe_len;
+	} else {
+		pos = skb_put(skb, wmmInfoIe_len + 2);
+		len = wmmInfoIe_len;
+	}
+
+	*pos++ = wmm_id;
+	*pos++ = len;
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		memcpy(pos, wmmParamElement, sizeof(wmmParamElement));
+		pos += sizeof(wmmParamElement);
+	} else {
+		memcpy(pos, wmmInfoElement, sizeof(wmmInfoElement));
+		pos += sizeof(wmmInfoElement);
+	}
+	*pos++ = qosInfo;
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		*pos++ = reserved;
+		memcpy(pos, ac_be, sizeof(ac_be));
+		pos += sizeof(ac_be);
+		memcpy(pos, ac_bk, sizeof(ac_bk));
+		pos += sizeof(ac_bk);
+		memcpy(pos, ac_vi, sizeof(ac_vi));
+		pos += sizeof(ac_vi);
+		memcpy(pos, 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
+*/
+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
+*/
+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) {
+				memcpy(tdls_peer->peer_addr, peer, ETH_ALEN);
+				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 *tf;
+	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;
+
+	tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+	memcpy(tf->da, peer, ETH_ALEN);
+	memcpy(tf->sa, priv->current_addr, ETH_ALEN);
+	tf->ether_type = cpu_to_be16(MLAN_ETHER_PKT_TYPE_TDLS_ACTION);
+	tf->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);
+
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_REQUEST;
+		skb_put(skb, sizeof(tf->u.setup_req));
+		tf->u.setup_req.dialog_token = dialog_token;
+		tf->u.setup_req.capability = cpu_to_le16(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);
+
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
+
+		skb_put(skb, sizeof(tf->u.setup_resp));
+		tf->u.setup_resp.status_code = cpu_to_le16(status_code);
+		tf->u.setup_resp.dialog_token = dialog_token;
+		tf->u.setup_resp.capability = cpu_to_le16(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);
+
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
+
+		skb_put(skb, sizeof(tf->u.setup_cfm));
+		tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
+		tf->u.setup_cfm.dialog_token = dialog_token;
+
+		break;
+	case WLAN_TDLS_TEARDOWN:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_TEARDOWN;
+
+		skb_put(skb, sizeof(tf->u.teardown));
+		tf->u.teardown.reason_code = cpu_to_le16(status_code);
+		break;
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
+
+		skb_put(skb, sizeof(tf->u.discover_req));
+		tf->u.discover_req.dialog_token = dialog_token;
+		break;
+	default:
+		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]);
+			memcpy(pSupp_chan, tdls_ies->supp_chan,
+			       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]);
+			memcpy(pRegulatory_class, tdls_ies->regulatory_class,
+			       sizeof(IEEEtypes_Header_t) +
+			       tdls_ies->regulatory_class[1]);
+		}
+		woal_tdls_add_ext_capab(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));
+			memcpy(HTcap, tdls_ies->ht_cap,
+			       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));
+			memcpy(VHTcap, tdls_ies->vht_cap,
+			       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));
+			memcpy(AidInfo, tdls_ies->aid_info,
+			       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));
+			memcpy(HTInfo, tdls_ies->ht_info,
+			       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));
+			memcpy(vht_oprat, tdls_ies->vht_oprat,
+			       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);
+	memcpy(mgmt->da, peer, ETH_ALEN);
+	memcpy(mgmt->sa, priv->current_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
+
+	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_ACTION);
+	/* add address 4 */
+	pos = skb_put(skb, ETH_ALEN);
+
+	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.category,
+			1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
+		/** init address 4 */
+		memcpy(pos, addr, ETH_ALEN);
+
+		woal_add_supported_rates_ie(priv, skb, band);
+		woal_add_ext_supported_rates_ie(priv, skb, band);
+		woal_tdls_add_ext_capab(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]);
+			memcpy(pSupp_chan, tdls_ies->supp_chan,
+			       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]);
+			memcpy(pRegulatory_class, tdls_ies->regulatory_class,
+			       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(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;
+
+	memcpy(lnkid->bssid, bssid, ETH_ALEN);
+	memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
+	memcpy(lnkid->resp_sta, peer, ETH_ALEN);
+}
+
+/**
+ * @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));
+	memcpy(pos, &pkt_type, sizeof(pkt_type));
+	memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
+
+	woal_construct_tdls_action_frame(priv, peer, action_code,
+					 dialog_token, status_code, skb);
+
+	if (extra_ies_len)
+		memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
+
+	/* the TDLS link IE is always added last */
+	/* we are the responder */
+	woal_tdls_add_link_ie(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);
+	memcpy(pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE, &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)
+		memcpy(skb_put(skb, extra_ies_len), extra_ies, 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(skb, priv->current_addr, peer,
+				      priv->cfg_bssid);
+		break;
+	case WLAN_TDLS_SETUP_RESPONSE:
+		/* we are the responder */
+		woal_tdls_add_link_ie(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);
+		memcpy(event_buf, CUS_EVT_TDLS_CONNECTED, custom_len);
+		memcpy(event_buf + custom_len, peer, ETH_ALEN);
+		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);
+		memcpy(event_buf, CUS_EVT_TDLS_TEARDOWN, custom_len);
+		memcpy(event_buf + custom_len, peer, ETH_ALEN);
+		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;
+}
+
+/**
+ * @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 (!(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:
+	return ret;
+}
+
+/**
+ * @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;
+}
+
+#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;
+	memcpy(tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr, addr, ETH_ALEN);
+	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;
+	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_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;
+	memcpy(tdls_data->tdls_data, addr, ETH_ALEN);
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		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,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;
+	memset(priv->ft_ie, 0, MAX_IE_SIZE);
+	memcpy(priv->ft_ie, ftie->ie, MIN(ftie->ie_len, MAX_IE_SIZE));
+	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;
+	memcpy((void *)priv->sme_current.bssid, &priv->target_ap_bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+	ret = woal_cfg80211_assoc(priv, (void *)&priv->sme_current,
+				  MOAL_IOCTL_WAIT);
+
+	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);
+			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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			memset(&roam_info, 0,
+			       sizeof(struct cfg80211_roam_info));
+			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));
+			priv->ft_ie_len = 0;
+		}
+		priv->ft_roaming_triggered_by_driver = MFALSE;
+
+	} else {
+		PRINTM(MMSG, "Fast BSS Transition use ft-over-air\n");
+		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->cfg_bssid));
+			cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
+						NULL, 0, NULL, 0,
+						woal_get_assoc_status(priv),
+						GFP_KERNEL);
+			memset(priv->cfg_bssid, 0, ETH_ALEN);
+			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);
+	memcpy(&priv->sme_current, sme, sizeof(struct cfg80211_connect_params));
+	if (sme->channel) {
+		priv->sme_current.channel = &priv->conn_chan;
+		memcpy(priv->sme_current.channel, sme->channel,
+		       sizeof(struct ieee80211_channel));
+	}
+	if (sme->bssid) {
+		priv->sme_current.bssid = priv->conn_bssid;
+		memcpy((void *)priv->sme_current.bssid, sme->bssid,
+		       MLAN_MAC_ADDR_LENGTH);
+	}
+	if (sme->ssid && sme->ssid_len) {
+		priv->sme_current.ssid = priv->conn_ssid;
+		memset(priv->conn_ssid, 0, MLAN_MAX_SSID_LENGTH);
+		memcpy((void *)priv->sme_current.ssid, sme->ssid,
+		       sme->ssid_len);
+	}
+	if (sme->ie && sme->ie_len) {
+		priv->sme_current.ie = kzalloc(sme->ie_len, GFP_KERNEL);
+		memcpy((void *)priv->sme_current.ie, sme->ie, sme->ie_len);
+	}
+	if (sme->key && sme->key_len && (sme->key_len <= MAX_WEP_KEY_SIZE)) {
+		priv->sme_current.key = priv->conn_wep_key;
+		memcpy((t_u8 *)priv->sme_current.key, sme->key, sme->key_len);
+	}
+}
+
+/**
+ * @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;
+	LEAVE();
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+/**
+ *  @brief This function update channel region config
+ *
+ *  @param buf              Buffer containing channel region config
+ *  @param num_chan         Length of buffer
+ *  @param regd             ieee80211_regdomain to be updated
+ *
+ *  @return                 N/A
+ */
+static struct ieee80211_regdomain *
+create_custom_regdomain(t_u8 *buf, t_u16 num_chan)
+{
+	struct ieee80211_reg_rule *rule;
+	bool new_rule;
+	int idx, freq, prev_freq = 0;
+	t_u32 bw, prev_bw = 0;
+	t_u8 chflags, prev_chflags = 0, valid_rules = 0;
+	struct ieee80211_regdomain *regd = NULL;
+	int regd_size;
+
+	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++) {
+		t_u8 chan;
+		enum ieee80211_band band;
+
+		chan = *buf++;
+		if (!chan) {
+			return NULL;
+		}
+		chflags = *buf++;
+		band = (chan <= 14) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+		freq = ieee80211_channel_to_frequency(chan, band);
+		new_rule = false;
+
+		if (chflags & MARVELL_CHANNEL_DISABLED)
+			continue;
+
+		if (band == IEEE80211_BAND_5GHZ) {
+			if (!(chflags & MARVELL_CHANNEL_NOHT80))
+				bw = MHZ_TO_KHZ(80);
+			else if (!(chflags & MARVELL_CHANNEL_NOHT40))
+				bw = MHZ_TO_KHZ(40);
+			else
+				bw = MHZ_TO_KHZ(20);
+		} else {
+			if (!(chflags & MARVELL_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);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		if (chflags & MARVELL_CHANNEL_PASSIVE)
+			rule->flags = NL80211_RRF_NO_IR;
+#endif
+		if (chflags & MARVELL_CHANNEL_DFS)
+			rule->flags = NL80211_RRF_DFS;
+
+		rule->freq_range.max_bandwidth_khz = bw;
+	}
+
+	regd->n_reg_rules = valid_rules;
+
+	/* set alpha2 from FW. */
+	regd->alpha2[0] = '9';
+	regd->alpha2[1] = '9';
+
+	return regd;
+}
+
+/**
+ *  @brief create custom channel regulatory config
+ *
+ *  @param priv         A pointer to moal_private structure
+ *
+ *  @return		        if success pointer to ieee80211_regdomain, else NULL
+ */
+static struct ieee80211_regdomain *
+woal_create_custom_regdomain(moal_private *priv)
+{
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	struct ieee80211_regdomain *regd = NULL;
+	t_u16 num_chan;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg) +
+					REGULATORY_CFG_LEN);
+	if (req == NULL) {
+		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));
+	/* Passing maximum buffer length to mlan */
+	misc->param.custom_reg_domain.cfg_len = REGULATORY_CFG_LEN;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		goto done;
+	}
+
+	if (misc->param.custom_reg_domain.cfg_len) {
+		num_chan = misc->param.custom_reg_domain.cfg_len / 2;
+		if (num_chan > NL80211_MAX_SUPP_REG_RULES) {
+			goto done;
+		}
+
+		regd = create_custom_regdomain(misc->param.custom_reg_domain.
+					       cfg_buf, num_chan);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return regd;
+}
+#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;
+
+	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;
+	}
+#if defined(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
+	if (bss_type == MLAN_BSS_TYPE_NAN)
+		wdev->iftype = NL80211_IFTYPE_STATION;
+	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;
+	}
+	woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Initialize the wiphy
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param wait_option     Wait option
+ *
+ * @return                MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_cfg80211_init_wiphy(moal_private *priv, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int retry_count, rts_thr, frag_thr;
+	struct wiphy *wiphy = NULL;
+	mlan_ioctl_req *req = NULL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	mlan_ds_radio_cfg *radio = NULL;
+#endif
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	t_u32 hw_dev_cap;
+#ifdef UAP_SUPPORT
+	mlan_uap_bss_param *sys_cfg = NULL;
+#endif
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 0, 0)
+	t_u16 enable = 0;
+#endif
+
+	ENTER();
+
+	wiphy = priv->phandle->wiphy;
+	/* 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])
+		woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_2GHZ]->
+					   ht_cap, hw_dev_cap,
+					   cfg_11n->param.supported_mcs_set);
+	/* For 2.4G band only card, this shouldn't be set */
+	if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
+		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
+	}
+	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 */
+	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;
+			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;
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 0, 0)
+	/* Enable multi-channel by default if multi-channel is supported */
+	if (cfg80211_iface_comb_ap_sta.num_different_channels > 1)
+		enable = 1;
+	ret = woal_mc_policy_cfg(priv, &enable, wait_option, MLAN_ACT_SET);
+#endif
+
+done:
+	LEAVE();
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	return ret;
+}
+
+/*
+ * 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;
+	int index = 0;
+
+	ENTER();
+
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+
+	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;
+	}
+#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_ADHOC) |
+		MBIT(NL80211_IFTYPE_AP);
+	wiphy->interface_modes |= MBIT(NL80211_IFTYPE_MONITOR);
+
+#if defined(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) {
+		wiphy->bands[IEEE80211_BAND_5GHZ] = &cfg80211_band_5ghz;
+		priv->phandle->band = IEEE80211_BAND_5GHZ;
+	}
+	/* Supported bands */
+	if (fw_info.fw_bands & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
+		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)
+	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;
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	if (cfg80211_drcs) {
+		cfg80211_iface_comb_ap_sta.num_different_channels = 2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		cfg80211_iface_comb_ap_sta.radar_detect_widths = 0;
+#endif
+	}
+	/* Initialize interface combinations */
+	wiphy->iface_combinations = &cfg80211_iface_comb_ap_sta;
+	wiphy->n_iface_combinations = 1;
+#endif
+
+	memcpy(wiphy->perm_addr, priv->current_addr, ETH_ALEN);
+	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;
+#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_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+	wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+#endif
+#ifdef ANDROID_KERNEL
+	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#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 = 1;
+#endif
+#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(3,4,0)
+	wiphy->features |= NL80211_FEATURE_HT_IBSS;
+#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, 8, 0)
+	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+#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 (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 (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
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (fw_region) {
+		priv->phandle->regd = woal_create_custom_regdomain(priv);
+		if (priv->phandle->regd) {
+			wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+				REGULATORY_DISABLE_BEACON_HINTS |
+				REGULATORY_COUNTRY_IE_IGNORE;
+			wiphy_apply_custom_regulatory(wiphy,
+						      priv->phandle->regd);
+		} else {
+			PRINTM(MERROR,
+			       "creating custom regulatory domain failed\n");
+		}
+	}
+#endif
+	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
+	if (wiphy_register(wiphy) < 0) {
+		PRINTM(MERROR, "Wiphy device registration failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err_wiphy;
+	}
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (!p2p_enh)
+		wiphy->interface_modes &= ~(MBIT(NL80211_IFTYPE_P2P_GO) |
+					    MBIT(NL80211_IFTYPE_P2P_CLIENT));
+#endif
+#endif
+
+	if ((!reg_alpha2 || strncmp(reg_alpha2, "99", strlen("99")))
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	    && !priv->phandle->regd
+#endif
+		) {
+	/** 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]);
+			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]);
+					regulatory_hint(wiphy, country);
+				}
+			} else
+				PRINTM(MERROR,
+				       "hw region code=%d not supported\n",
+				       fw_info.region_code);
+		}
+	}
+	priv->phandle->wiphy = wiphy;
+	woal_cfg80211_init_wiphy(priv, MOAL_IOCTL_WAIT);
+	return ret;
+err_wiphy:
+	if (wiphy)
+		wiphy_free(wiphy);
+	LEAVE();
+	return ret;
+}
+
+module_param(cfg80211_drcs, int, 0);
+MODULE_PARM_DESC(cfg80211_drcs,
+		 "1: Enable DRCS support; 0: Disable DRCS support");
+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
diff --git a/wlan_sd8997/mlinux/moal_sta_cfg80211.h b/wlan_sd8997/mlinux/moal_sta_cfg80211.h
new file mode 100644
index 0000000..31a3ee5
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_sta_cfg80211.h
@@ -0,0 +1,42 @@
+/** @file moal_sta_cfg80211.h
+  *
+  * @brief This file contains the STA CFG80211 specific defines.
+  *
+  * Copyright (C) 2014-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _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);
+
+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);
+
+#endif /* _MOAL_STA_CFG80211_H_ */
diff --git a/wlan_sd8997/mlinux/moal_uap.c b/wlan_sd8997/mlinux/moal_uap.c
new file mode 100644
index 0000000..6b413b3
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_uap.c
@@ -0,0 +1,3970 @@
+/** @file moal_uap.c
+  *
+  * @brief This file contains the major functions in UAP
+  * driver.
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include    "moal_main.h"
+#include    "moal_uap.h"
+#include    "moal_sdio.h"
+#include    "moal_eth_ioctl.h"
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#include    "moal_cfg80211.h"
+#endif
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+/********************************************************
+		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;
+	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;
+	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);
+	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 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;
+}
+
+/**
+ *  @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);
+		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;
+		}
+		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);
+		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;
+		}
+	}
+	/* 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;
+}
+
+/**
+ *  @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) > 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;
+		memcpy(cfg11d->param.domain_tlv, tlv,
+		       MIN(MAX_IE_SIZE, (TLV_HEADER_LEN + tlv_data_len)));
+	}
+	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;
+}
+
+#if defined(DFS_TESTING_SUPPORT)
+/**
+ *  @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;
+		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;
+		priv->phandle->cac_period_jiffies =
+			param.usr_cac_period * HZ / 1000;
+		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;
+		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;
+	}
+	/* 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;
+	memcpy(&ds_11hcfg->param.ch_nop_info, ch_info,
+	       sizeof(mlan_ds_11h_chan_nop_info));
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_FAILURE) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memcpy(ch_info, &ds_11hcfg->param.ch_nop_info,
+	       sizeof(mlan_ds_11h_chan_nop_info));
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+#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;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
+	} else {
+		/* Set HT Tx configurations */
+		cfg_11n->param.tx_cfg.httxcap = httx_cfg.httxcap;
+		PRINTM(MINFO, "SET: httxcap:0x%x\n", httx_cfg.httxcap);
+		cfg_11n->param.tx_cfg.misc_cfg = httx_cfg.misc_cfg;
+		PRINTM(MINFO, "SET: httxcap band:0x%x\n", httx_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;
+	}
+	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);
+		cfg_11n->param.tx_cfg.httxcap = 0;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
+		status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		httx_cfg.misc_cfg = cfg_11n->param.tx_cfg.httxcap;
+		PRINTM(MINFO, "GET: httxcap for 5GHz:0x%x\n",
+		       httx_cfg.misc_cfg);
+	}
+	/* 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);
+	memcpy(vhtcfg, &cfg_11ac->param.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++;
+		memcpy(vhtcfg, &cfg_11ac->param.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
+ *  @invoke_hostcmd Argument
+ *
+ *  @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 dev          A pointer to net_device structure
+ *  @param req          A pointer to ifreq 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 > 3)) {
+			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_VHT)
+				) {
+				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))
+					) {
+					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.user_data_cnt == 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;
+			}
+		}
+	}
+
+	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)
+				tx_rate_config.nss = rate->param.rate_cfg.nss;
+		}
+		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;
+	}
+
+	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;
+	case UAP_SDCMD52_RW:
+		ret = woal_uap_sdcmd52_rw(dev, req);
+		break;
+	case UAP_SNMP_MIB:
+		ret = woal_uap_snmp_mib(dev, req);
+		break;
+#ifdef DFS_TESTING_SUPPORT
+	case UAP_DFS_TESTING:
+		ret = woal_uap_dfs_testing(dev, req);
+		break;
+#endif
+	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;
+	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;
+
+	memcpy(&bss->param.deauth_param, &deauth_param,
+	       sizeof(mlan_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 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)
+		memcpy(&pm_cfg->param.ps_mgmt, ps_mgmt,
+		       sizeof(mlan_ds_ps_mgmt));
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (action == MLAN_ACT_GET)
+			memcpy(ps_mgmt, &pm_cfg->param.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;
+	}
+
+	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;
+		memcpy(&pm_cfg->param.ps_mgmt, &ps_mgmt,
+		       sizeof(mlan_ds_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,
+		     sizeof(mlan_ds_sta_list))) {
+			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;
+	memcpy(sec->param.encrypt_key.mac_addr, key_msg->mac_addr, ETH_ALEN);
+	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;
+	memcpy(sec->param.encrypt_key.key_material, key_msg->key,
+	       sec->param.encrypt_key.key_len);
+
+	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) {
+		memcpy(misc->param.gen_ie.ie_data, wapi_psk_ie,
+		       misc->param.gen_ie.len);
+	} else if (msg->msg[0] & WAPI_MODE_CERT) {
+		memcpy(misc->param.gen_ie.ie_data, wapi_cert_ie,
+		       misc->param.gen_ie.len);
+	} 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)
+		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
+ */
+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;
+	}
+	memcpy(sys_cfg, &info->param.bss_config, 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_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 = 0x20;
+		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 = 0x6f;
+		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();
+	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;
+		sys_cfg->supported_mcs_set[4] = 0x01;
+		if (fw_info.usr_dev_mcs_support == HT_STREAM_MODE_2X2) {
+			sys_cfg->supported_mcs_set[1] = 0xFF;
+			sys_cfg->supported_mcs_set[12] |= MBIT(2);
+		} else {
+			sys_cfg->supported_mcs_set[1] = 0;
+			sys_cfg->supported_mcs_set[12] &= ~(MBIT(2) | MBIT(3));
+		}
+	}
+
+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();
+
+	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;
+	}
+	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 Parse AP configuration from ASCII string
+ *
+ *  @param ap_cfg   A pointer to mlan_uap_bss_param structure
+ *  @param buf      A pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_uap_ap_cfg_parse_data(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);
+				memcpy(ap_cfg->wep_cfg.key0.key, value,
+				       MIN(sizeof(ap_cfg->wep_cfg.key0.key),
+					   strlen(value)));
+				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);
+			memcpy(ap_cfg->wpa_cfg.passphrase, value,
+			       MIN(sizeof(ap_cfg->wpa_cfg.passphrase),
+				   strlen(value)));
+			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);
+	memcpy(buf, data, MIN(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(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
+ */
+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;
+
+	memcpy(&bss->param.ap_scan_channels, scan_channels,
+	       sizeof(mlan_uap_scan_channels));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		memcpy(scan_channels, &bss->param.ap_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;
+
+	memcpy(&bss->param.ap_channel, uap_channel, sizeof(chan_band_info));
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		memcpy(uap_channel, &bss->param.ap_channel,
+		       sizeof(chan_band_info));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	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)
+			   || dfs_offload
+#endif
+			) {
+			/* 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");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		bss->sub_command = MLAN_OID_BSS_START;
+		bss->param.host_based = priv->uap_host_based;
+		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);
+		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
+ */
+int
+woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	int ret = 0;
+	ENTER();
+	PRINTM(MIOCTL, "uap_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 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 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)
+			memcpy(ustats, &info->param.ustats,
+			       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)
+		memcpy(&bss->param.ap_wmm_para, ap_wmm_para,
+		       sizeof(wmm_parameter_t));
+
+	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)
+		memcpy(ap_wmm_para, &bss->param.ap_wmm_para,
+		       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)
+		memcpy(&bss->param.bss_config, sys_cfg,
+		       sizeof(mlan_uap_bss_param));
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (action == MLAN_ACT_GET)
+		memcpy(sys_cfg, &bss->param.bss_config,
+		       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_sd8997/mlinux/moal_uap.h b/wlan_sd8997/mlinux/moal_uap.h
new file mode 100644
index 0000000..ef2f8f1
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_uap.h
@@ -0,0 +1,520 @@
+/** @file moal_uap.h
+  *
+  * @brief This file contains uap driver specific defines etc.
+  *
+  * Copyright (C) 2009-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/********************************************************
+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
+/** sdcmd52 read write subcommand */
+#define UAP_SDCMD52_RW      6
+/** 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
+#ifdef DFS_TESTING_SUPPORT
+/** dfs testing subcommand */
+#define UAP_DFS_TESTING     10
+#endif
+/** 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
+
+/** 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
+
+/** TX rate cfg structure */
+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];
+} 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;
+
+/** CAC timer status structure */
+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)
+
+/** uap get station list */
+#define UAP_GET_STA_LIST            (SIOCDEVPRIVATE + 11)
+#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 _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;
+} addba_param;
+
+/** aggr_prio_tbl */
+typedef struct _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];
+} 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 _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;
+} fw_info;
+
+/** HT TX cfg header parameter structure */
+typedef struct _ht_tx_cfg_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} ht_tx_cfg_para_hdr;
+
+/** TX beamformer parameter header structure */
+typedef struct _tx_bf_cfg_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} tx_bf_cfg_para_hdr;
+
+/** VHT cfg parameter header structure */
+typedef struct _vht_cfg_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} vht_cfg_para_hdr;
+
+/** UAP operation parameter header structure */
+typedef struct _uap_oper_para_hdr {
+    /** Sub command */
+	t_u32 subcmd;
+    /** Action: Set/Get */
+	t_u32 action;
+} uap_oper_para_hdr;
+
+/** 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;
+
+/** 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;
+
+/** 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;
+
+/** SNMP mib parameter structure */
+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[0];
+} 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
+
+#ifdef DFS_TESTING_SUPPORT
+/** 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;
+} dfs_testing_para;
+#endif
+
+/** 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[0];
+} 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);
+int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+int woal_uap_bss_ctrl(moal_private *priv, t_u8 wait_option, int data);
+#ifdef UAP_CFG80211
+#if defined(DFS_TESTING_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+int woal_uap_get_channel_nop_info(moal_private *priv, t_u8 wait_option,
+				  mlan_ds_11h_chan_nop_info * ch_info);
+#endif
+#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,
+			       mlan_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(mlan_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_set_uap_ht_tx_cfg(moal_private *priv, Band_Config_t bandcfg, 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, mlan_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_sd8997/mlinux/moal_uap_cfg80211.c b/wlan_sd8997/mlinux/moal_uap_cfg80211.c
new file mode 100644
index 0000000..acf489c
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_uap_cfg80211.c
@@ -0,0 +1,3348 @@
+/** @file moal_uap_cfg80211.c
+  *
+  * @brief This file contains the functions for uAP CFG80211.
+  *
+  * Copyright (C) 2011-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#include "moal_cfg80211.h"
+#include "moal_uap_cfg80211.h"
+/** deauth reason code */
+#define  REASON_CODE_DEAUTH_LEAVING 3
+/********************************************************
+				Local Variables
+********************************************************/
+
+/********************************************************
+				Global Variables
+********************************************************/
+#ifdef WIFI_DIRECT_SUPPORT
+extern int GoAgeoutTime;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int dfs_offload;
+#endif
+/********************************************************
+				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;
+
+	memcpy(bss->param.deauth_param.mac_addr, mac_addr,
+	       MLAN_MAC_ADDR_LENGTH);
+	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 all station
+ *
+ * @param priv            A pointer to moal_private structure
+ *
+ * @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 IEEEtypes_Rsn_t structure
+ * @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 < 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 = 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 < 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 = le16_to_cpu(key_mgmt->count);
+	if (left <
+	    (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;
+		}
+	}
+	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 < 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 = 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 < 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 = le16_to_cpu(key_mgmt->count);
+	if (left <
+	    (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 ie              Pointer IE buffer
+ * @param sys_config      Pointer to mlan_uap_bss_param structure
+ *
+ * @return                N/A
+ */
+static t_void
+woal_set_wmm_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;
+	IEEEtypes_VendorSpecific_t *pvendor_ie;
+	IEEEtypes_ElementId_e element_id;
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	t_u8 *poui;
+
+	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;
+			poui = pvendor_ie->vend_hdr.oui;
+			if (!memcmp(poui, wmm_oui, sizeof(wmm_oui))) {
+				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.
+					 */
+					memcpy(&sys_config->wmm_para,
+					       pcurrent_ptr +
+					       sizeof(IEEEtypes_Header_t),
+					       element_len);
+				}
+			}
+
+			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 params          A pointer to cfg80211_ap_settings structure
+ * @return                0 -- success, otherwise fail
+ */
+t_u8
+woal_check_11ac_capability(moal_private *priv,
+			   struct cfg80211_ap_settings *params)
+#else
+/**
+ * @brief initialize AP or GO bss config
+ * @param priv            A pointer to moal private structure
+ * @return                0 -- success, otherwise fail
+ */
+t_u8
+woal_check_11ac_capability(moal_private *priv)
+#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();
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (!(fw_info.fw_bands & BAND_AAC)) {
+		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;
+}
+
+/**
+ * @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;
+}
+
+#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 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(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(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(&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 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(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));
+		memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
+		rate_len = rate_ie->len;
+	}
+	ext_rate_ie =
+		(void *)woal_parse_ie_tlv(tail_ie, tail_len,
+					  WLAN_EID_EXT_SUPP_RATES);
+	if (ext_rate_ie) {
+		memcpy(&bss_cfg->rates[rate_len], ext_rate_ie + 1,
+		       ext_rate_ie->len);
+		rate_len += ext_rate_ie->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;
+	t_u8 *wapi_ie = NULL;
+	int wapi_ie_len = 0;
+#if defined(DFS_TESTING_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	mlan_ds_11h_chan_nop_info chan_nop_info;
+	Band_Config_t bandcfg;
+#endif
+#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;
+		woal_set_get_gen_ie(priv, MLAN_ACT_SET, wapi_ie, &wapi_ie_len,
+				    MOAL_IOCTL_WAIT);
+	}
+	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;
+	}
+
+	/* Setting the default values */
+	sys_config->channel = 6;
+	sys_config->preamble_type = 0;
+	sys_config->mgmt_ie_passthru_mask = priv->mgmt_subtype_mask;
+	memcpy(sys_config->mac_addr, priv->current_addr, ETH_ALEN);
+
+#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 == MLAN_FRAG_RTS_DISABLED) {
+		sys_config->frag_threshold = MLAN_FRAG_MAX_VALUE;
+	}
+	if (sys_config->rts_threshold == 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 */
+	memcpy(&priv->chan, &params->chandef, sizeof(struct cfg80211_chan_def));
+#endif
+
+#if defined(DFS_TESTING_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	PRINTM(MCMND, "Checking if AP's channel %d is under NOP\n",
+	       priv->channel);
+	woal_convert_chan_to_bandconfig(&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
+#endif
+
+	if (priv->channel) {
+		woal_check_mc_connection(priv, MOAL_IOCTL_WAIT, 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->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)
+				memcpy(sys_config->rates, rates_wfd,
+				       sizeof(rates_wfd));
+			else
+#endif
+				memcpy(sys_config->rates, rates_bg,
+				       sizeof(rates_bg));
+		} else {
+			sys_config->bandcfg.chanBand = BAND_5GHZ;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+			chan2Offset =
+				woal_get_second_channel_offset(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->
+								       channel);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			enable_11ac = woal_check_11ac_capability(priv, 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);
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+				memcpy(sys_config->rates, rates_wfd,
+				       sizeof(rates_wfd));
+			else
+#endif
+				memcpy(sys_config->rates, rates_a,
+				       sizeof(rates_a));
+		}
+
+		/* Replaced with rate from userspace, if exist */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+		woal_set_uap_rates(sys_config, params->beacon.head,
+				   params->beacon.head_len, params->beacon.tail,
+				   params->beacon.tail_len);
+#else
+		woal_set_uap_rates(sys_config, params->head, params->head_len,
+				   params->tail, params->tail_len);
+#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;
+		}
+		if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			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;
+	}
+	memcpy(sys_config->ssid.ssid, params->ssid,
+	       MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len));
+	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;
+			memcpy(&sys_config->wep_cfg.key0, &priv->uap_wep_key[0],
+			       sizeof(wep_key));
+			memcpy(&sys_config->wep_cfg.key1, &priv->uap_wep_key[1],
+			       sizeof(wep_key));
+			memcpy(&sys_config->wep_cfg.key2, &priv->uap_wep_key[2],
+			       sizeof(wep_key));
+			memcpy(&sys_config->wep_cfg.key3, &priv->uap_wep_key[3],
+			       sizeof(wep_key));
+		}
+		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;
+	}
+	memcpy(sys_config->ssid.ssid, ssid_ie + 2, *(ssid_ie + 1));
+	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;
+		memcpy(&sys_config->wep_cfg.key0, &priv->uap_wep_key[0],
+		       sizeof(wep_key));
+		memcpy(&sys_config->wep_cfg.key1, &priv->uap_wep_key[1],
+		       sizeof(wep_key));
+		memcpy(&sys_config->wep_cfg.key2, &priv->uap_wep_key[2],
+		       sizeof(wep_key));
+		memcpy(&sys_config->wep_cfg.key3, &priv->uap_wep_key[3],
+		       sizeof(wep_key));
+	} 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 (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		/*find and set wmm ie */
+		woal_set_wmm_ies(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, MFALSE);
+		woal_uap_set_11n_status(priv, sys_config, MLAN_ACT_DISABLE);
+	} else {
+		woal_set_uap_ht_tx_cfg(priv, sys_config->bandcfg, 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 (sys_config->bandcfg.chanBand == BAND_5GHZ) {
+		if (enable_11ac && enable_11n) {
+			vhtcap_ie = woal_get_vhtcap_info(ie, ie_len);
+			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 (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv,
+							   MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_config)) {
+		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;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+/**
+ * @brief Request the driver to add a monitor interface
+ *
+ * @param wiphy             A pointer to wiphy structure
+ * @param name              Virtual interface name
+ * @param name_assign_type  Interface name assignment type
+ * @param flags             Flags for the virtual interface
+ * @param params            A pointer to vif_params structure
+ * @param new_dev           Netdevice to be passed out
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_add_mon_if(struct wiphy *wiphy,
+			 const char *name,
+			 unsigned char name_assign_type,
+			 u32 *flags, struct vif_params *params,
+			 struct net_device **new_dev)
+#else
+/**
+ * @brief Request the driver to add a monitor interface
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param name            Virtual interface name
+ * @param flags           Flags for the virtual interface
+ * @param params          A pointer to vif_params structure
+ * @param new_dev         Netdevice to be passed out
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_add_mon_if(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+			 const
+#endif
+			 char *name, u32 *flags, struct vif_params *params,
+			 struct net_device **new_dev)
+#endif
+{
+	int ret = 0;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv =
+		(moal_private *)woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+	monitor_iface *mon_if = NULL;
+	struct net_device *ndev = NULL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	chan_band_info chan_info;
+#endif
+	unsigned char name_assign_type_tmp = 0;
+
+	ENTER();
+
+	ASSERT_RTNL();
+
+	if (handle->mon_if) {
+		PRINTM(MERROR, "%s: monitor interface exist: %s basedev %s\n",
+		       __func__, handle->mon_if->mon_ndev->name,
+		       handle->mon_if->base_ndev->name);
+		ret = -EFAULT;
+		goto fail;
+	}
+
+	if (!priv) {
+		PRINTM(MERROR, "add_mon_if: priv is NULL\n");
+		ret = -EFAULT;
+		goto fail;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	name_assign_type_tmp = name_assign_type;
+#endif
+	mon_if = woal_prepare_mon_if(priv, name, name_assign_type_tmp);
+	if (!mon_if) {
+		PRINTM(MFATAL, "Prepare mon_if fail.\n");
+		goto fail;
+	}
+
+	ndev = mon_if->mon_ndev;
+	dev_net_set(ndev, wiphy_net(wiphy));
+	memcpy(ndev->perm_addr, wiphy->perm_addr, ETH_ALEN);
+	memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
+	SET_NETDEV_DEV(ndev, wiphy_dev(wiphy));
+	ndev->ieee80211_ptr = &mon_if->wdev;
+	mon_if->wdev.iftype = NL80211_IFTYPE_MONITOR;
+	mon_if->wdev.wiphy = wiphy;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	/* if any interface is active, the sniffer will always operate
+	 * on the same channel as that of active connection, else will
+	 * operate on the specified channel and band
+	 */
+	memset(&chan_info, 0x00, sizeof(chan_info));
+	mon_if->band_chan_cfg.channel = 0;
+	if (!woal_is_any_interface_active(handle)) {
+		/* Set default band channel config */
+		mon_if->band_chan_cfg.band = BAND_B | BAND_G;
+		mon_if->band_chan_cfg.band |= BAND_GN;
+		mon_if->band_chan_cfg.channel = 1;
+		mon_if->band_chan_cfg.chan_bandwidth = CHANNEL_BW_20MHZ;
+		chan_info.channel = 1;
+		chan_info.is_11n_enabled = MTRUE;
+	}
+	if (MLAN_STATUS_SUCCESS != woal_set_net_monitor(priv, MOAL_IOCTL_WAIT,
+							MTRUE, 0x7,
+							&mon_if->
+							band_chan_cfg)) {
+		PRINTM(MERROR, "%s: woal_set_net_monitor fail\n", __func__);
+		ret = -EFAULT;
+		goto fail;
+	}
+	if (woal_is_any_interface_active(handle)) {
+		/* set current band channel config */
+		chan_info.bandcfg.chanBand = mon_if->band_chan_cfg.band;
+		if (mon_if->band_chan_cfg.band & (BAND_B | BAND_G
+						  | BAND_GN | BAND_GAC))
+			chan_info.bandcfg.chanBand = BAND_2GHZ;
+		else
+			/* TODO: Add support for BAND_4GHZ */
+			chan_info.bandcfg.chanBand = BAND_5GHZ;
+		chan_info.bandcfg.chanWidth =
+			mon_if->band_chan_cfg.chan_bandwidth;
+		chan_info.channel = mon_if->band_chan_cfg.channel;
+		chan_info.is_11n_enabled = MTRUE;
+	}
+	if (MLAN_STATUS_FAILURE == woal_chandef_create(priv, &mon_if->chandef,
+						       &chan_info)) {
+		/* stop monitor mode on error */
+		woal_set_net_monitor(priv, MOAL_IOCTL_WAIT, MFALSE, 0, NULL);
+		ret = -EFAULT;
+		goto fail;
+	}
+#endif
+
+	ret = register_netdevice(ndev);
+	if (ret) {
+		PRINTM(MFATAL, "register net_device failed, ret=%d\n", ret);
+		free_netdev(ndev);
+		goto fail;
+	}
+
+	handle->mon_if = mon_if;
+
+	if (new_dev)
+		*new_dev = ndev;
+
+fail:
+	LEAVE();
+	return ret;
+}
+
+#if defined(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
+ */
+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
+ */
+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 = (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;
+
+	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);
+	ret = register_netdevice(ndev);
+	if (ret) {
+		handle->priv[new_priv->bss_index] = NULL;
+		handle->priv_num--;
+		if (ndev->reg_state == NETREG_REGISTERED) {
+			unregister_netdevice(ndev);
+			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);
+#ifdef PROC_DEBUG
+	woal_debug_entry(new_priv);
+#endif /* PROC_DEBUG */
+#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
+ */
+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);
+
+	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;
+			}
+		}
+	}
+
+	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
+		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
+#ifdef PROC_DEBUG
+		/* Remove proc debug */
+		woal_debug_remove(vir_priv);
+#endif /* PROC_DEBUG */
+		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)
+			unregister_netdevice(dev);
+	}
+	return ret;
+}
+#endif
+#endif
+
+/**
+ *  @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
+#ifdef PROC_DEBUG
+				/* Remove proc debug */
+				woal_debug_remove(priv);
+#endif /* PROC_DEBUG */
+				woal_proc_remove(priv);
+#endif /* CONFIG_PROC_FS */
+				netif_device_detach(priv->netdev);
+				if (priv->netdev->reg_state ==
+				    NETREG_REGISTERED)
+					unregister_netdevice(priv->netdev);
+				handle->priv[i] = NULL;
+				vir_intf++;
+			}
+		}
+	}
+#endif
+	if (handle->mon_if) {
+		netif_device_detach(handle->mon_if->mon_ndev);
+		if (handle->mon_if->mon_ndev->reg_state == NETREG_REGISTERED)
+			unregister_netdevice(handle->mon_if->mon_ndev);
+		handle->mon_if = NULL;
+	}
+	rtnl_unlock();
+#ifdef WIFI_DIRECT_SUPPORT
+	handle->priv_num -= vir_intf;
+#endif
+	LEAVE();
+}
+
+/**
+ *  @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 CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+	u32 *flags = &params->flags;
+#endif
+
+	ENTER();
+	PRINTM(MIOCTL, "add virtual intf: %d name: %s\n", type, name);
+	switch (type) {
+	case NL80211_IFTYPE_MONITOR:
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+		ret = woal_cfg80211_add_mon_if(wiphy, name, name_assign_type,
+					       flags, params, &ndev);
+#else
+		ret = woal_cfg80211_add_mon_if(wiphy, name, flags, params,
+					       &ndev);
+#endif
+		break;
+#if defined(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_MONITOR) {
+		if ((handle->mon_if) && (handle->mon_if->mon_ndev == dev)) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_net_monitor(handle->mon_if->priv,
+						 MOAL_IOCTL_WAIT, MFALSE, 0,
+						 NULL)) {
+				PRINTM(MERROR,
+				       "%s: woal_set_net_monitor fail\n",
+				       __func__);
+				ret = -EFAULT;
+			}
+#endif
+			handle->mon_if = NULL;
+		}
+		unregister_netdevice(dev);
+		LEAVE();
+		return ret;
+	}
+	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;
+	}
+#if defined(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;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	t_u8 wait_option = MOAL_IOCTL_WAIT;
+#endif
+	ENTER();
+
+	PRINTM(MMSG, "wlan: Starting AP\n");
+#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 (dfs_offload)
+			wait_option = MOAL_NO_WAIT;
+#endif
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, 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();
+
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	if (priv->phandle->driver_state) {
+		PRINTM(MERROR,
+		       "Block  woal_cfg80211_del_beacon in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	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 (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 (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_RESET)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		/* Set WLAN MAC addresses */
+		if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(priv)) {
+			PRINTM(MERROR, "Set MAC address failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_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 (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, 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 (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 ||
+		    priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
+#endif
+			woal_deauth_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;
+
+	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_SIGNAL);
+#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;
+		}
+	}
+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;
+
+	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;
+	memcpy(mac, info->param.sta_list.info[idx].mac_address, 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
+	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;
+	memcpy(sys_config->filter.mac_list, params->mac_addrs,
+	       sys_config->filter.mac_count * sizeof(mlan_802_11_mac_addr));
+	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, 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
+ */
+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:
+		break;
+	case NL80211_CHAN_WIDTH_20:
+		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;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+	case NL80211_CHAN_WIDTH_80P80:
+	case NL80211_CHAN_WIDTH_160:
+		chan2Offset =
+			woal_get_second_channel_offset(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, wait_option, 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;
+	memcpy(&priv->chan, &priv->csa_chan, sizeof(struct cfg80211_chan_def));
+	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();
+}
+
+#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;
+	chan_band_info channel;
+	t_u16 enable = 0;
+
+	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;
+	}
+	ret = woal_mc_policy_cfg(priv, &enable, MOAL_IOCTL_WAIT, MLAN_ACT_GET);
+	if (enable) {
+		if (MLAN_STATUS_SUCCESS ==
+		    woal_get_active_intf_channel(priv, &channel)) {
+			if (channel.channel != chandef->chan->hw_value) {
+				PRINTM(MERROR,
+				       "DFS channel is not allowed when another connection exists on different channel\n");
+				PRINTM(MERROR,
+				       "Another connection's channel=%d, dfs channel=%d\n",
+				       channel.channel,
+				       chandef->chan->hw_value);
+				ret = -EINVAL;
+				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(&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 defined(DFS_TESTING_SUPPORT)
+	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);
+	}
+#endif
+
+	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 {
+		memcpy(&handle->dfs_channel, chandef,
+		       sizeof(struct cfg80211_chan_def));
+		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;
+	}
+
+	memcpy(&priv->csa_chan, &params->chandef,
+	       sizeof(struct cfg80211_chan_def));
+	memcpy(&priv->beacon_after, &params->beacon_after,
+	       sizeof(struct cfg80211_beacon_data));
+
+	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
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+/**
+ * @brief Notify cfg80211 uap 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_uap_channel(moal_private *priv,
+				 chan_band_info * pchan_info)
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	struct cfg80211_chan_def chandef;
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+	enum nl80211_channel_type type;
+	enum ieee80211_band band;
+	int freq = 0;
+#endif
+#endif
+	ENTER();
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_chandef_create(priv, &chandef, pchan_info)) {
+		cfg80211_ch_switch_notify(priv->netdev, &chandef);
+		priv->channel = pchan_info->channel;
+		memcpy(&priv->chan, &chandef, sizeof(struct cfg80211_chan_def));
+	}
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+	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
+
+/**
+ * @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_sd8997/mlinux/moal_uap_cfg80211.h b/wlan_sd8997/mlinux/moal_uap_cfg80211.h
new file mode 100644
index 0000000..f28cdb7
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_uap_cfg80211.h
@@ -0,0 +1,29 @@
+/** @file moal_uap_cfg80211.h
+  *
+  * @brief This file contains the uAP CFG80211 specific defines.
+  *
+  * Copyright (C) 2014-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef _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_sd8997/mlinux/moal_uap_priv.c b/wlan_sd8997/mlinux/moal_uap_priv.c
new file mode 100644
index 0000000..9f975bd
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_uap_priv.c
@@ -0,0 +1,190 @@
+/** @file  moal_uap_priv.c
+  *
+  * @brief This file contains standard ioctl functions
+  *
+  * Copyright (C) 2010-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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_SIXTEEN_INT:
+		switch (wrq->u.data.flags) {
+		case WOAL_UAP_NET_MONITOR:
+			ret = woal_net_monitor_ioctl(priv, wrq);
+			break;
+		default:
+			ret = -EINVAL;
+			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, wrq->u.data.pointer,
+						  wrq->u.data.length);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	case WOAL_UAP_SETONEINT_GETONEINT:
+		switch (wrq->u.data.flags) {
+		case WOAL_UAP_SET_GET_BSS_ROLE:
+			ret = woal_set_get_bss_role(priv, wrq);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+#endif
+#endif
+	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, 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_sd8997/mlinux/moal_uap_priv.h b/wlan_sd8997/mlinux/moal_uap_priv.h
new file mode 100644
index 0000000..6fbfcb7
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_uap_priv.h
@@ -0,0 +1,209 @@
+/** @file  moal_uap_priv.h
+  *
+  * @brief This file contains definition for extended private IOCTL call.
+  *
+  * Copyright (C) 2010-2018, Marvell International Lt.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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/get sixteen int */
+#define WOAL_UAP_SET_GET_SIXTEEN_INT            (WOAL_UAP_IOCTL + 4)
+/** Private command ID to set/get net monitor mode */
+#define WOAL_UAP_NET_MONITOR        1
+
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/** Private command ID to set one int/get one int */
+#define WOAL_UAP_SETONEINT_GETONEINT            (WOAL_UAP_IOCTL + 5)
+/** 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)
+
+/**
+ * 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_SET_GET_SIXTEEN_INT,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 ""},
+	{
+	 WOAL_UAP_NET_MONITOR,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "netmon"},
+#if defined(WIFI_DIRECT_SUPPORT)
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	{
+	 WOAL_UAP_SETONEINT_GETONEINT,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 ""},
+	{
+	 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"},
+};
+
+#endif /* _MOAL_UAP_PRIV_H_ */
diff --git a/wlan_sd8997/mlinux/moal_uap_wext.c b/wlan_sd8997/mlinux/moal_uap_wext.c
new file mode 100644
index 0000000..70c5cba
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_uap_wext.c
@@ -0,0 +1,1879 @@
+/** @file  moal_uap_wext.c
+  *
+  * @brief This file contains wireless extension standard ioctl functions
+  *
+  * Copyright (C) 2010-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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;
+
+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},
+};
+
+/** 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 < 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, char *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,
+	      char *cwrq, char *extra)
+{
+	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,
+	     struct sockaddr *awrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+
+	ENTER();
+
+	if (priv->bss_started)
+		memcpy(awrq->sa_data, priv->current_addr, MLAN_MAC_ADDR_LENGTH);
+	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,
+	     struct sockaddr *awrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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 < ap_cfg->num_of_chan; i++)
+		if (ap_cfg->chan_list[i].chan_number == chan)
+			break;
+	if (i == 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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+		  t_u32 *uwrq, char *extra)
+{
+	int ret = 0;
+	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,
+		  t_u32 *uwrq, char *extra)
+{
+	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)
+			memcpy(pkey->key, extra, dwrq->length);
+		/* 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)
+					memcpy(pkey, &ap_cfg->wep_cfg.key0,
+					       sizeof(wep_key));
+				if (key_index == 1)
+					memcpy(pkey, &ap_cfg->wep_cfg.key1,
+					       sizeof(wep_key));
+				if (key_index == 2)
+					memcpy(pkey, &ap_cfg->wep_cfg.key2,
+					       sizeof(wep_key));
+				if (key_index == 3)
+					memcpy(pkey, &ap_cfg->wep_cfg.key3,
+					       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,
+		struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+			memcpy(extra, pkey->key, pkey->length);
+			dwrq->flags &= ~IW_ENCODE_DISABLED;
+		} else {
+			ret = -EFAULT;
+		}
+		break;
+	case PROTOCOL_WPA:
+	case PROTOCOL_WPA2:
+	case PROTOCOL_WPA2_MIXED:
+		memcpy(extra, ap_cfg->wpa_cfg.passphrase,
+		       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,
+		struct iw_point *dwrq, 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,
+		struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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");
+			}
+			memcpy(priv->bcn_ie_buf + priv->bcn_ie_len,
+			       ((t_u8 *)tlv),
+			       sizeof(IEEEtypes_Header_t) + tlv->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);
+			}
+			memcpy(priv->bcn_ie_buf + priv->bcn_ie_len,
+			       ((t_u8 *)tlv),
+			       sizeof(IEEEtypes_Header_t) + tlv->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,
+		    struct iw_point *dwrq, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+			memcpy(pwep_key->key, pkey_material, ext->key_len);
+		}
+	} 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;
+		memcpy(sec->param.encrypt_key.key_material, pkey_material,
+		       ext->key_len);
+		memcpy(sec->param.encrypt_key.mac_addr, ext->addr.sa_data,
+		       ETH_ALEN);
+		sec->param.encrypt_key.key_flags = ext->ext_flags;
+		if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->rx_seq,
+			       SEQ_MAX_SIZE);
+			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) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->tx_seq,
+			       SEQ_MAX_SIZE);
+			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,
+		    struct iw_point *dwrq, 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, struct iw_point *dwrq, 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)) {
+		memcpy(sta_addr, (t_u8 *)mlme->addr.sa_data, ETH_ALEN);
+		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;
+			}
+			memcpy(sta_list, &pinfo->param.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 (!memcmp(bc_addr, sta_addr, ETH_ALEN)) {
+			for (i = 0; i < sta_list->sta_count; i++) {
+				memcpy(bss->param.deauth_param.mac_addr,
+				       sta_list->info[i].mac_address, ETH_ALEN);
+				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 {
+			memcpy(bss->param.deauth_param.mac_addr, sta_addr,
+			       ETH_ALEN);
+			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,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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");
+		ret = -EFAULT;
+		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,
+	      struct iw_param *vwrq, 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");
+		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,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_point *dwrq, 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,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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
+
+	memcpy(sys_cfg->ssid.ssid, extra,
+	       MIN(sys_cfg->ssid.ssid_len, MLAN_MAX_SSID_LENGTH));
+	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);
+		memcpy(extra, ap_cfg->ssid.ssid, 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
+********************************************************/
+
+/** 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
+};
+
+/**
+ *  @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_sd8997/mlinux/moal_wext.c b/wlan_sd8997/mlinux/moal_wext.c
new file mode 100644
index 0000000..b1ad6be
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_wext.c
@@ -0,0 +1,3157 @@
+/** @file  moal_wext.c
+  *
+  * @brief This file contains wireless extension standard ioctl functions
+  *
+  * Copyright (C) 2008-2018, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+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 */
+/** Macro for minimum size of scan buffer */
+#define MIN_ACCEPTED_GET_SCAN_BUF 8000
+
+/********************************************************
+			Global Variables
+********************************************************/
+extern int hw_test;
+/********************************************************
+			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));
+	memcpy(priv->nick_name, extra, dwrq->length);
+	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, char *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,
+	      char *cwrq, char *extra)
+{
+	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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_freq *fwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+		  t_u32 *uwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	     struct sockaddr *awrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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)
+		memcpy(awrq->sa_data, &bss_info.bssid, MLAN_MAC_ADDR_LENGTH);
+	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 sockaddr 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,
+	     struct sockaddr *awrq, 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);
+	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;
+		}
+		memcpy(&ssid_bssid.bssid, awrq->sa_data, ETH_ALEN);
+	}
+
+	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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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,
+		  t_u32 *uwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_param *vwrq, 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,
+	      struct iw_param *vwrq, 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 (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;
+	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;
+		memcpy(sec->param.encrypt_key.key_material, extra,
+		       dwrq->length);
+		/* 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,
+		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;
+	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) {
+		memcpy(extra, sec->param.encrypt_key.key_material,
+		       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,
+		struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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);
+	memcpy(extra, ie, 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,
+		struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+		    struct iw_point *dwrq, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+	memcpy(sec->param.encrypt_key.mac_addr, (u8 *)ext->addr.sa_data,
+	       ETH_ALEN);
+	/* 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;
+		memcpy(sec->param.encrypt_key.key_material, pkey_material,
+		       ext->key_len);
+		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) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->rx_seq,
+			       SEQ_MAX_SIZE);
+			DBG_HEXDUMP(MCMD_D, "Rx PN", sec->param.encrypt_key.pn,
+				    SEQ_MAX_SIZE);
+		}
+		if (ext->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID) {
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->tx_seq,
+			       SEQ_MAX_SIZE);
+			DBG_HEXDUMP(MCMD_D, "Tx PN", sec->param.encrypt_key.pn,
+				    SEQ_MAX_SIZE);
+		}
+		memcpy(sec->param.encrypt_key.key_material, pkey_material,
+		       ext->key_len);
+		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;
+			memcpy(sec->param.encrypt_key.pn, (t_u8 *)ext->tx_seq,
+			       SEQ_MAX_SIZE);
+			memcpy(&sec->param.encrypt_key.pn[SEQ_MAX_SIZE],
+			       (t_u8 *)ext->rx_seq, 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,
+		    struct iw_point *dwrq, 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, struct iw_point *dwrq, 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,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	       struct iw_point *dwrq, char *extra)
+{
+	int i;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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,
+	      struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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;
+	}
+	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 (!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;
+		}
+		memcpy(country_code, buf + strlen("COUNTRY") + 1,
+		       COUNTRY_CODE_LEN - 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(dwrq->pointer, buf, dwrq->length))
+		ret = -EFAULT;
+done:
+	kfree(buf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @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;
+			memcpy(req_ssid.ssid,
+			       (t_u8 *)req->essid, req->essid_len);
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_request_scan(priv, MOAL_NO_WAIT, &req_ssid)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	} else {
+#endif
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_request_scan(priv, MOAL_NO_WAIT, NULL)) {
+			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,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	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 */
+		memcpy(req_ssid.ssid, extra,
+		       MIN(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);
+		memcpy(&ssid_bssid.ssid, &req_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 (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) {
+		memcpy(&priv->prev_ssid_bssid.ssid, &req_ssid,
+		       sizeof(mlan_802_11_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;
+	}
+	memcpy(&priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+	       sizeof(mlan_802_11_ssid));
+	memcpy(&priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+	       MLAN_MAC_ADDR_LENGTH);
+#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);
+		memcpy(extra, bss_info.ssid.ssid, 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;
+		memcpy(iwe.u.ap_addr.sa_data, &scan_table[i].mac_address,
+		       ETH_ALEN);
+
+		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;
+					memcpy(buf, praw_data,
+					       element_len +
+					       sizeof(IEEEtypes_Header_t));
+					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 = 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 = &mic;
+	iwrq.data.length = sizeof(mic);
+
+	wireless_send_event(priv->netdev, IWEVMICHAELMICFAILURE, &iwrq,
+			    (char *)&mic);
+
+	LEAVE();
+	return;
+}
+#endif
+
+#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
+};
+
+/**
+ *  @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;
+	woal_get_stats_info(priv, wait_option, NULL);
+
+	LEAVE();
+	return &priv->w_stats;
+}
+#endif /* STA_SUPPORT */
diff --git a/wlan_sd8997/mlinux/moal_wext.h b/wlan_sd8997/mlinux/moal_wext.h
new file mode 100644
index 0000000..00c6be6
--- /dev/null
+++ b/wlan_sd8997/mlinux/moal_wext.h
@@ -0,0 +1,51 @@
+/** @file moal_wext.h
+ *
+ * @brief This file contains definition for wireless extension IOCTL call.
+ *
+ * Copyright (C) 2008-2018, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+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_ */
diff --git a/wlan_sd8997/script/wifidirect/start_auto_go.sh b/wlan_sd8997/script/wifidirect/start_auto_go.sh
new file mode 100755
index 0000000..78aa8a8
--- /dev/null
+++ b/wlan_sd8997/script/wifidirect/start_auto_go.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# iwpriv mlan0 drvdbg 0x20037
+# change the mac address
+./wifidirect/update_mac.sh
+echo "wfd0 Mac address updated in config/wifidirect.conf"
+
+
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 1
+#else
+# iwpriv wfd0 bssrole 1
+#endif
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 0
+#else
+# iwpriv wfd0 bssrole 0
+#endif
+# iwpriv wfd0 bssrole 1
+# change the group owner parameters
+# either in uaputl_wifidirect.conf or using CLI below
+#./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+#./uaputl.exe -i wfd0 sys_cfg_eapol_gwk_hsk 2000 3
+#./uaputl.exe -i wfd0 sys_cfg_eapol_pwk_hsk 2000 3
+# iwpriv wfd0 bssrole 0
+./wifidirectutl wfd0 wifidirect_mode 1
+iwpriv wfd0 bssrole 1
+./wifidirectutl wfd0 wifidirect_mode 2
+./uaputl.exe -i wfd0 bss_start
diff --git a/wlan_sd8997/script/wifidirect/start_find_phase.sh b/wlan_sd8997/script/wifidirect/start_find_phase.sh
new file mode 100755
index 0000000..26ddd60
--- /dev/null
+++ b/wlan_sd8997/script/wifidirect/start_find_phase.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# iwpriv wfd0 drvdbg 0x20037
+#change the mac address
+./wifidirect/update_mac.sh
+echo "wfd0 Mac address updated in config/wifidirect.conf"
+
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 1
+#else
+# iwpriv wfd0 bssrole 1
+#endif
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 0
+#else
+# iwpriv wfd0 bssrole 0
+#endif
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+# change the passphrase
+# either in uaputl_wifidirect.conf or using CLI below
+#./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+./wifidirectutl wfd0 wifidirect_mode 1
+./wifidirectutl wfd0 wifidirect_params_config config/wifidirect.conf
+./mlanutl wfd0 hostcmd config/bg_scan_wifidirect.conf bgscfg
+./wifidirectutl wfd0 wifidirect_mode 4
diff --git a/wlan_sd8997/script/wifidirect/start_listen_state.sh b/wlan_sd8997/script/wifidirect/start_listen_state.sh
new file mode 100755
index 0000000..91c1e4d
--- /dev/null
+++ b/wlan_sd8997/script/wifidirect/start_listen_state.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+iwpriv wfd0 drvdbg 0x20037
+# change the mac address
+ifconfig mlan0 hw ether 00:50:43:21:0e:08
+ifconfig wfd0 hw ether 00:50:43:21:0e:08
+ifconfig uap0 hw ether 00:50:43:21:0e:08
+
+iwpriv wfd0 deepsleep 0
+iwconfig wfd0 power off
+
+iwpriv wfd0 bssrole 1
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+iwpriv wfd0 bssrole 0
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+./uaputl.exe -i wfd0 sys_cfg_protocol 32
+./uaputl.exe -i wfd0 sys_cfg_cipher 8 8
+./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+./wifidirectutl wfd0 wifidirect_mode 1
diff --git a/wlan_sd8997/script/wifidirect/stop_auto_go.sh b/wlan_sd8997/script/wifidirect/stop_auto_go.sh
new file mode 100755
index 0000000..eda03ef
--- /dev/null
+++ b/wlan_sd8997/script/wifidirect/stop_auto_go.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+./uaputl.exe -i wfd0 bss_stop
+sleep 1
+iwpriv wfd0 bssrole 0
+./wifidirectutl wfd0 wifidirect_mode 0
+# IE clear assume index 0, 1
+./uaputl.exe -i wfd0 sys_cfg_custom_ie 0 0
+./uaputl.exe -i wfd0 sys_cfg_custom_ie 1 0
diff --git a/wlan_sd8997/script/wifidirect/stop_wifidirect_client.sh b/wlan_sd8997/script/wifidirect/stop_wifidirect_client.sh
new file mode 100755
index 0000000..5ae1ad5
--- /dev/null
+++ b/wlan_sd8997/script/wifidirect/stop_wifidirect_client.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# deauth the GO first
+./wifidirectutl wfd0 wifidirect_mode 0
+# IE clear assume index 0, 1
+./uaputl.exe -i wfd0 sys_cfg_custom_ie 0 0
+./uaputl.exe -i wfd0 sys_cfg_custom_ie 1 0
diff --git a/wlan_sd8997/script/wifidirect/update_mac.sh b/wlan_sd8997/script/wifidirect/update_mac.sh
new file mode 100755
index 0000000..d744db9
--- /dev/null
+++ b/wlan_sd8997/script/wifidirect/update_mac.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+MAC=`ifconfig wfd0 | grep wfd0 | tr -s ' ' | cut -d ' ' -f5`
+MAC26=`echo $MAC | cut -d ':' -f2-6`
+LAA=`echo $MAC | cut -d ':' -f1`
+LAA=$((0x$LAA+2))
+if [ $LAA -lt 16 ] ; then
+LAA=`printf "%X\n" $LAA`
+MACLAA=0$LAA:$MAC26
+else
+LAA=`printf "%X\n" $LAA`
+MACLAA=$LAA:$MAC26
+fi
+sed "s/00:50:43:00:00:00/$MAC/" config/wifidirect.conf > tmp$$
+mv tmp$$ config/wifidirect.conf
+sed "s/02:50:43:00:00:00/$MACLAA/" config/wifidirect.conf > tmp$$
+mv tmp$$ config/wifidirect.conf
diff --git a/wlan_sd8997/script/wifidisplay/start_auto_go.sh b/wlan_sd8997/script/wifidisplay/start_auto_go.sh
new file mode 100755
index 0000000..cc8b49a
--- /dev/null
+++ b/wlan_sd8997/script/wifidisplay/start_auto_go.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# iwpriv mlan0 drvdbg 0x20037
+# change the mac address
+./wifidirect/update_mac.sh
+echo "wfd0 Mac address updated in config/wifidirect.conf"
+
+
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 1
+#else
+# iwpriv wfd0 bssrole 1
+#endif
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 0
+#else
+# iwpriv wfd0 bssrole 0
+#endif
+# iwpriv wfd0 bssrole 1
+# change the group owner parameters
+# either in uaputl_wifidirect.conf or using CLI below
+#./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+#./uaputl.exe -i wfd0 sys_cfg_eapol_gwk_hsk 2000 3
+#./uaputl.exe -i wfd0 sys_cfg_eapol_pwk_hsk 2000 3
+# iwpriv wfd0 bssrole 0
+./wifidirectutl wfd0 wifidirect_mode 1
+./wifidirectutl wfd0 wifidirect_mode 5
+
+#enable wifi-display
+./wifidirectutl wfd0 wifidisplay_mode 1
+./wifidirectutl wfd0 wifidisplay_config config/wifidisplay.conf
+
+iwpriv wfd0 bssrole 1
+./wifidirectutl wfd0 wifidirect_mode 2
+./uaputl.exe -i wfd0 bss_start
diff --git a/wlan_sd8997/script/wifidisplay/start_find_phase.sh b/wlan_sd8997/script/wifidisplay/start_find_phase.sh
new file mode 100755
index 0000000..8fef6d0
--- /dev/null
+++ b/wlan_sd8997/script/wifidisplay/start_find_phase.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# iwpriv wfd0 drvdbg 0x20037
+#change the mac address
+./wifidirect/update_mac.sh
+echo "wfd0 Mac address updated in config/wifidirect.conf"
+
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 1
+#else
+# iwpriv wfd0 bssrole 1
+#endif
+./uaputl.exe -i wfd0 sys_config config/uaputl_wifidirect.conf
+#ifdef STREAM_2X2
+iwpriv wfd0 bssrole 0
+#else
+# iwpriv wfd0 bssrole 0
+#endif
+./wifidirectutl wfd0 wifidirect_config config/wifidirect.conf
+# change the passphrase
+# either in uaputl_wifidirect.conf or using CLI below
+#./uaputl.exe -i wfd0 sys_cfg_wpa_passphrase 1234567890
+./wifidirectutl wfd0 wifidirect_mode 1
+./wifidirectutl wfd0 wifidirect_params_config config/wifidirect.conf
+./mlanconfig wfd0 hostcmd config/bg_scan_wifidirect.conf bgscfg
+./wifidirectutl wfd0 wifidirect_mode 4
+
+#enable wifi-display
+./wifidirectutl wfd0 wifidisplay_mode 1
+./wifidirectutl wfd0 wifidisplay_config config/wifidisplay.conf
+
diff --git a/wlan_sd8997/script/wifidisplay/update_mac.sh b/wlan_sd8997/script/wifidisplay/update_mac.sh
new file mode 100755
index 0000000..d744db9
--- /dev/null
+++ b/wlan_sd8997/script/wifidisplay/update_mac.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+MAC=`ifconfig wfd0 | grep wfd0 | tr -s ' ' | cut -d ' ' -f5`
+MAC26=`echo $MAC | cut -d ':' -f2-6`
+LAA=`echo $MAC | cut -d ':' -f1`
+LAA=$((0x$LAA+2))
+if [ $LAA -lt 16 ] ; then
+LAA=`printf "%X\n" $LAA`
+MACLAA=0$LAA:$MAC26
+else
+LAA=`printf "%X\n" $LAA`
+MACLAA=$LAA:$MAC26
+fi
+sed "s/00:50:43:00:00:00/$MAC/" config/wifidirect.conf > tmp$$
+mv tmp$$ config/wifidirect.conf
+sed "s/02:50:43:00:00:00/$MACLAA/" config/wifidirect.conf > tmp$$
+mv tmp$$ config/wifidirect.conf